[BACK]Return to chfs_vnode.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / ufs / chfs

Annotation of src/sys/ufs/chfs/chfs_vnode.c, Revision 1.17.2.1

1.17.2.1! ad          1: /*     $NetBSD: chfs_vnode.c,v 1.18 2020/01/17 20:08:10 ad Exp $       */
1.1       ahoka       2:
                      3: /*-
                      4:  * Copyright (c) 2010 Department of Software Engineering,
                      5:  *                   University of Szeged, Hungary
                      6:  * Copyright (C) 2010 Tamas Toth <ttoth@inf.u-szeged.hu>
                      7:  * Copyright (C) 2010 Adam Hoka <ahoka@NetBSD.org>
                      8:  * All rights reserved.
                      9:  *
                     10:  * This code is derived from software contributed to The NetBSD Foundation
                     11:  * by the Department of Software Engineering, University of Szeged, Hungary
                     12:  *
                     13:  * Redistribution and use in source and binary forms, with or without
                     14:  * modification, are permitted provided that the following conditions
                     15:  * are met:
                     16:  * 1. Redistributions of source code must retain the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer.
                     18:  * 2. Redistributions in binary form must reproduce the above copyright
                     19:  *    notice, this list of conditions and the following disclaimer in the
                     20:  *    documentation and/or other materials provided with the distribution.
                     21:  *
                     22:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     23:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     24:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     25:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     26:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
                     27:  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
                     28:  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
                     29:  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
                     30:  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     31:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     32:  * SUCH DAMAGE.
                     33:  */
                     34:
                     35: #include "chfs.h"
                     36: #include "chfs_inode.h"
                     37: #include <sys/kauth.h>
                     38: #include <sys/namei.h>
                     39: #include <sys/uio.h>
                     40: #include <sys/buf.h>
                     41:
1.3       elad       42: #include <miscfs/genfs/genfs.h>
                     43:
1.8       ttoth      44: /* chfs_vnode_lookup - lookup for a vnode */
1.13      hannken    45: static bool
                     46: chfs_vnode_lookup_selector(void *ctx, struct vnode *vp)
                     47: {
                     48:        ino_t *ino = ctx;
                     49:
1.15      riastrad   50:        KASSERT(mutex_owned(vp->v_interlock));
                     51:
1.13      hannken    52:        return (VTOI(vp) != NULL && VTOI(vp)->ino == *ino);
                     53: }
1.1       ahoka      54: struct vnode *
                     55: chfs_vnode_lookup(struct chfs_mount *chmp, ino_t vno)
                     56: {
1.13      hannken    57:        struct vnode_iterator *marker;
1.1       ahoka      58:        struct vnode *vp;
                     59:
1.13      hannken    60:        vfs_vnode_iterator_init(chmp->chm_fsmp, &marker);
                     61:        vp = vfs_vnode_iterator_next(marker, chfs_vnode_lookup_selector, &vno);
                     62:        vfs_vnode_iterator_destroy(marker);
                     63:
                     64:        return vp;
1.1       ahoka      65: }
                     66:
1.8       ttoth      67: /* chfs_readvnode - reads a vnode from the flash and setups its inode */
1.1       ahoka      68: int
1.8       ttoth      69: chfs_readvnode(struct mount *mp, ino_t ino, struct vnode **vpp)
1.1       ahoka      70: {
                     71:        struct ufsmount* ump = VFSTOUFS(mp);
                     72:        struct chfs_mount *chmp = ump->um_chfs;
                     73:        struct chfs_vnode_cache *chvc;
                     74:        struct chfs_flash_vnode *chfvn;
                     75:        struct chfs_inode *ip;
                     76:        int err;
                     77:        char* buf;
                     78:        size_t retlen, len;
                     79:        struct vnode* vp = NULL;
1.2       agc        80:        dbg("readvnode | ino: %llu\n", (unsigned long long)ino);
1.1       ahoka      81:
                     82:        len = sizeof(struct chfs_flash_vnode);
                     83:
                     84:        KASSERT(vpp != NULL);
                     85:
                     86:        if (vpp != NULL) {
                     87:                vp = *vpp;
                     88:        }
                     89:
                     90:        ip = VTOI(vp);
                     91:        chvc = ip->chvc;
                     92:
1.8       ttoth      93:        /* root node is in-memory only */
1.1       ahoka      94:        if (chvc && ino != CHFS_ROOTINO) {
1.7       ttoth      95:                dbg("offset: %" PRIu32 ", lnr: %d\n",
1.1       ahoka      96:                    CHFS_GET_OFS(chvc->v->nref_offset), chvc->v->nref_lnr);
                     97:
                     98:                KASSERT((void *)chvc != (void *)chvc->v);
                     99:
1.8       ttoth     100:                /* reading */
1.1       ahoka     101:                buf = kmem_alloc(len, KM_SLEEP);
                    102:                err = chfs_read_leb(chmp, chvc->v->nref_lnr, buf,
                    103:                    CHFS_GET_OFS(chvc->v->nref_offset), len, &retlen);
1.11      he        104:                if (err) {
                    105:                        kmem_free(buf, len);
1.1       ahoka     106:                        return err;
1.11      he        107:                }
1.1       ahoka     108:                if (retlen != len) {
                    109:                        chfs_err("Error reading vnode: read: %zu insted of: %zu\n",
                    110:                            len, retlen);
1.11      he        111:                        kmem_free(buf, len);
1.1       ahoka     112:                        return EIO;
                    113:                }
                    114:                chfvn = (struct chfs_flash_vnode*)buf;
1.8       ttoth     115:
                    116:                /* setup inode fields */
1.1       ahoka     117:                chfs_set_vnode_size(vp, chfvn->dn_size);
                    118:                ip->mode = chfvn->mode;
1.4       ttoth     119:                ip->ch_type = IFTOCHT(ip->mode);
                    120:                vp->v_type = CHTTOVT(ip->ch_type);
1.1       ahoka     121:                ip->version = chfvn->version;
                    122:                ip->uid = chfvn->uid;
                    123:                ip->gid = chfvn->gid;
                    124:                ip->atime = chfvn->atime;
                    125:                ip->mtime = chfvn->mtime;
                    126:                ip->ctime = chfvn->ctime;
1.8       ttoth     127:
1.1       ahoka     128:                kmem_free(buf, len);
                    129:        }
                    130:
                    131:
                    132:        *vpp = vp;
                    133:        return 0;
                    134: }
                    135:
1.8       ttoth     136: /*
                    137:  * chfs_readddirent -
                    138:  * reads a directory entry from flash and adds it to its inode
                    139:  */
1.1       ahoka     140: int
                    141: chfs_readdirent(struct mount *mp, struct chfs_node_ref *chnr, struct chfs_inode *pdir)
                    142: {
                    143:        struct ufsmount *ump = VFSTOUFS(mp);
                    144:        struct chfs_mount *chmp = ump->um_chfs;
                    145:        struct chfs_flash_dirent_node chfdn;
1.8       ttoth     146:        struct chfs_dirent *fd;
1.1       ahoka     147:        size_t len = sizeof(struct chfs_flash_dirent_node);
                    148:        size_t retlen;
                    149:        int err = 0;
                    150:
1.8       ttoth     151:        /* read flash_dirent_node */
1.1       ahoka     152:        err = chfs_read_leb(chmp, chnr->nref_lnr, (char *)&chfdn,
                    153:            CHFS_GET_OFS(chnr->nref_offset), len, &retlen);
                    154:        if (err) {
                    155:                return err;
                    156:        }
                    157:        if (retlen != len) {
                    158:                chfs_err("Error reading vnode: read: %zu insted of: %zu\n",
                    159:                    retlen, len);
                    160:                return EIO;
                    161:        }
                    162:
1.8       ttoth     163:        /* set fields of dirent */
1.1       ahoka     164:        fd = chfs_alloc_dirent(chfdn.nsize + 1);
                    165:        fd->version = chfdn.version;
                    166:        fd->vno = chfdn.vno;
                    167:        fd->type = chfdn.dtype;
                    168:        fd->nsize = chfdn.nsize;
                    169:
1.8       ttoth     170:        /* read the name of the dirent */
1.1       ahoka     171:        err = chfs_read_leb(chmp, chnr->nref_lnr, fd->name,
                    172:            CHFS_GET_OFS(chnr->nref_offset) + len, chfdn.nsize, &retlen);
                    173:        if (err) {
                    174:                return err;
                    175:        }
                    176:
                    177:        if (retlen != chfdn.nsize) {
                    178:                chfs_err("Error reading vnode: read: %zu insted of: %zu\n",
                    179:                    len, retlen);
                    180:                return EIO;
                    181:        }
                    182:
                    183:        fd->name[fd->nsize] = 0;
                    184:        fd->nref = chnr;
                    185:
1.8       ttoth     186:        /* add to inode */
1.1       ahoka     187:        chfs_add_fd_to_inode(chmp, pdir, fd);
                    188:        return 0;
                    189: }
                    190:
1.8       ttoth     191: /* chfs_makeinode - makes a new file and initializes its structures */
1.1       ahoka     192: int
                    193: chfs_makeinode(int mode, struct vnode *dvp, struct vnode **vpp,
1.4       ttoth     194:     struct componentname *cnp, enum vtype type)
1.1       ahoka     195: {
                    196:        struct chfs_inode *ip, *pdir;
                    197:        struct vnode *vp;
                    198:        struct ufsmount* ump = VFSTOUFS(dvp->v_mount);
                    199:        struct chfs_mount* chmp = ump->um_chfs;
                    200:        struct chfs_vnode_cache* chvc;
1.3       elad      201:        int error;
1.1       ahoka     202:        ino_t vno;
1.8       ttoth     203:        struct chfs_dirent *nfd;
1.1       ahoka     204:
                    205:        dbg("makeinode\n");
                    206:        pdir = VTOI(dvp);
                    207:
                    208:        *vpp = NULL;
                    209:
1.8       ttoth     210:        /* number of vnode will be the new maximum */
1.1       ahoka     211:        vno = ++(chmp->chm_max_vno);
                    212:
1.17.2.1! ad        213:        error = VFS_VGET(dvp->v_mount, vno, LK_EXCLUSIVE, &vp);
1.1       ahoka     214:        if (error)
                    215:                return (error);
                    216:
1.8       ttoth     217:        /* setup vnode cache */
1.1       ahoka     218:        mutex_enter(&chmp->chm_lock_vnocache);
                    219:        chvc = chfs_vnode_cache_get(chmp, vno);
                    220:
                    221:        chvc->pvno = pdir->ino;
                    222:        chvc->vno_version = kmem_alloc(sizeof(uint64_t), KM_SLEEP);
                    223:        *(chvc->vno_version) = 1;
                    224:        if (type != VDIR)
                    225:                chvc->nlink = 1;
                    226:        else
                    227:                chvc->nlink = 2;
                    228:        chvc->state = VNO_STATE_CHECKEDABSENT;
1.6       ttoth     229:        mutex_exit(&chmp->chm_lock_vnocache);
1.1       ahoka     230:
1.8       ttoth     231:        /* setup inode */
1.1       ahoka     232:        ip = VTOI(vp);
                    233:        ip->ino = vno;
                    234:
                    235:        if (type == VDIR)
                    236:                chfs_set_vnode_size(vp, 512);
                    237:        else
                    238:                chfs_set_vnode_size(vp, 0);
                    239:
                    240:        ip->uid = kauth_cred_geteuid(cnp->cn_cred);
                    241:        ip->gid = kauth_cred_getegid(cnp->cn_cred);
                    242:        ip->version = 1;
                    243:        ip->iflag |= (IN_ACCESS | IN_CHANGE | IN_UPDATE);
                    244:
                    245:        ip->chvc = chvc;
                    246:        ip->target = NULL;
                    247:
                    248:        ip->mode = mode;
1.14      hannken   249:        vp->v_type = type;              /* Rest init'd in chfs_loadvnode(). */
1.4       ttoth     250:        ip->ch_type = VTTOCHT(vp->v_type);
1.3       elad      251:
1.8       ttoth     252:        /* authorize setting SGID if needed */
1.3       elad      253:        if (ip->mode & ISGID) {
                    254:                error = kauth_authorize_vnode(cnp->cn_cred, KAUTH_VNODE_WRITE_SECURITY,
                    255:                    vp, NULL, genfs_can_chmod(vp->v_type, cnp->cn_cred, ip->uid,
                    256:                    ip->gid, mode));
                    257:                if (error)
                    258:                        ip->mode &= ~ISGID;
                    259:        }
1.1       ahoka     260:
1.8       ttoth     261:        /* write vnode information to the flash */
1.1       ahoka     262:        chfs_update(vp, NULL, NULL, UPDATE_WAIT);
                    263:
                    264:        mutex_enter(&chmp->chm_lock_mountfields);
                    265:
                    266:        error = chfs_write_flash_vnode(chmp, ip, ALLOC_NORMAL);
                    267:        if (error) {
                    268:                mutex_exit(&chmp->chm_lock_mountfields);
                    269:                vput(vp);
                    270:                return error;
                    271:        }
1.8       ttoth     272:
                    273:        /* update parent's vnode information and write it to the flash */
1.1       ahoka     274:        pdir->iflag |= (IN_ACCESS | IN_CHANGE | IN_MODIFY | IN_UPDATE);
                    275:        chfs_update(dvp, NULL, NULL, UPDATE_WAIT);
                    276:
                    277:        error = chfs_write_flash_vnode(chmp, pdir, ALLOC_NORMAL);
                    278:        if (error) {
                    279:                mutex_exit(&chmp->chm_lock_mountfields);
                    280:                vput(vp);
                    281:                return error;
                    282:        }
                    283:
1.8       ttoth     284:        /* setup directory entry */
1.1       ahoka     285:        nfd = chfs_alloc_dirent(cnp->cn_namelen + 1);
                    286:        nfd->vno = ip->ino;
                    287:        nfd->version = (++pdir->chvc->highest_version);
1.4       ttoth     288:        nfd->type = ip->ch_type;
1.1       ahoka     289:        nfd->nsize = cnp->cn_namelen;
                    290:        memcpy(&(nfd->name), cnp->cn_nameptr, cnp->cn_namelen);
                    291:        nfd->name[nfd->nsize] = 0;
                    292:        nfd->nhash = hash32_buf(nfd->name, cnp->cn_namelen, HASH32_BUF_INIT);
                    293:
1.8       ttoth     294:        /* write out */
1.1       ahoka     295:        error = chfs_write_flash_dirent(chmp, pdir, ip, nfd, ip->ino, ALLOC_NORMAL);
                    296:        if (error) {
                    297:         mutex_exit(&chmp->chm_lock_mountfields);
                    298:                vput(vp);
                    299:                return error;
                    300:        }
                    301:
                    302:        //TODO set parent's dir times
                    303:
1.8       ttoth     304:        /* add dirent to parent */
1.1       ahoka     305:        chfs_add_fd_to_inode(chmp, pdir, nfd);
1.8       ttoth     306:
1.1       ahoka     307:        pdir->chvc->nlink++;
                    308:
                    309:        mutex_exit(&chmp->chm_lock_mountfields);
                    310:
1.10      hannken   311:        VOP_UNLOCK(vp);
1.1       ahoka     312:        *vpp = vp;
1.17      christos  313:        cache_enter(dvp, *vpp, cnp->cn_nameptr, cnp->cn_namelen, cnp->cn_flags);
1.1       ahoka     314:        return (0);
                    315: }
                    316:
1.8       ttoth     317: /* chfs_set_vnode_size - updates size of vnode and also inode */
1.1       ahoka     318: void
                    319: chfs_set_vnode_size(struct vnode *vp, size_t size)
                    320: {
                    321:        struct chfs_inode *ip;
                    322:
                    323:        KASSERT(vp != NULL);
                    324:
                    325:        ip = VTOI(vp);
                    326:        KASSERT(ip != NULL);
                    327:
                    328:        ip->size = size;
                    329:        vp->v_size = vp->v_writesize = size;
                    330:        return;
                    331: }
                    332:
1.8       ttoth     333: /*
                    334:  * chfs_change_size_free - updates free size
                    335:  * "change" parameter is positive if we have to increase the size
                    336:  * and negative if we have to decrease it
                    337:  */
1.1       ahoka     338: void
                    339: chfs_change_size_free(struct chfs_mount *chmp,
                    340:        struct chfs_eraseblock *cheb, int change)
                    341: {
                    342:        KASSERT(mutex_owned(&chmp->chm_lock_sizes));
                    343:        KASSERT((int)(chmp->chm_free_size + change) >= 0);
                    344:        KASSERT((int)(cheb->free_size + change) >= 0);
                    345:        KASSERT((int)(cheb->free_size + change) <= chmp->chm_ebh->eb_size);
                    346:        chmp->chm_free_size += change;
                    347:        cheb->free_size += change;
                    348:        return;
                    349: }
                    350:
1.8       ttoth     351: /*
                    352:  * chfs_change_size_dirty - updates dirty size
                    353:  * "change" parameter is positive if we have to increase the size
                    354:  * and negative if we have to decrease it
                    355:  */
1.1       ahoka     356: void
                    357: chfs_change_size_dirty(struct chfs_mount *chmp,
                    358:        struct chfs_eraseblock *cheb, int change)
                    359: {
                    360:        KASSERT(mutex_owned(&chmp->chm_lock_sizes));
                    361:        KASSERT((int)(chmp->chm_dirty_size + change) >= 0);
                    362:        KASSERT((int)(cheb->dirty_size + change) >= 0);
                    363:        KASSERT((int)(cheb->dirty_size + change) <= chmp->chm_ebh->eb_size);
                    364:        chmp->chm_dirty_size += change;
                    365:        cheb->dirty_size += change;
                    366:        return;
                    367: }
                    368:
1.8       ttoth     369: /*
                    370:  * chfs_change_size_unchecked - updates unchecked size
                    371:  * "change" parameter is positive if we have to increase the size
                    372:  * and negative if we have to decrease it
                    373:  */
1.1       ahoka     374: void
                    375: chfs_change_size_unchecked(struct chfs_mount *chmp,
                    376:        struct chfs_eraseblock *cheb, int change)
                    377: {
                    378:        KASSERT(mutex_owned(&chmp->chm_lock_sizes));
                    379:        KASSERT((int)(chmp->chm_unchecked_size + change) >= 0);
                    380:        KASSERT((int)(cheb->unchecked_size + change) >= 0);
                    381:        KASSERT((int)(cheb->unchecked_size + change) <= chmp->chm_ebh->eb_size);
                    382:        chmp->chm_unchecked_size += change;
                    383:        cheb->unchecked_size += change;
                    384:        return;
                    385: }
                    386:
1.8       ttoth     387: /*
                    388:  * chfs_change_size_used - updates used size
                    389:  * "change" parameter is positive if we have to increase the size
                    390:  * and negative if we have to decrease it
                    391:  */
1.1       ahoka     392: void
                    393: chfs_change_size_used(struct chfs_mount *chmp,
                    394:        struct chfs_eraseblock *cheb, int change)
                    395: {
                    396:        KASSERT(mutex_owned(&chmp->chm_lock_sizes));
                    397:        KASSERT((int)(chmp->chm_used_size + change) >= 0);
                    398:        KASSERT((int)(cheb->used_size + change) >= 0);
                    399:        KASSERT((int)(cheb->used_size + change) <= chmp->chm_ebh->eb_size);
                    400:        chmp->chm_used_size += change;
                    401:        cheb->used_size += change;
                    402:        return;
                    403: }
                    404:
1.8       ttoth     405: /*
                    406:  * chfs_change_size_wasted - updates wasted size
                    407:  * "change" parameter is positive if we have to increase the size
                    408:  * and negative if we have to decrease it
                    409:  */
1.1       ahoka     410: void
                    411: chfs_change_size_wasted(struct chfs_mount *chmp,
                    412:        struct chfs_eraseblock *cheb, int change)
                    413: {
                    414:        KASSERT(mutex_owned(&chmp->chm_lock_sizes));
                    415:        KASSERT((int)(chmp->chm_wasted_size + change) >= 0);
                    416:        KASSERT((int)(cheb->wasted_size + change) >= 0);
                    417:        KASSERT((int)(cheb->wasted_size + change) <= chmp->chm_ebh->eb_size);
                    418:        chmp->chm_wasted_size += change;
                    419:        cheb->wasted_size += change;
                    420:        return;
                    421: }
                    422:

CVSweb <webmaster@jp.NetBSD.org>