[BACK]Return to nilfs_vnops.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / fs / nilfs

Annotation of src/sys/fs/nilfs/nilfs_vnops.c, Revision 1.18

1.18    ! rmind       1: /* $NetBSD: nilfs_vnops.c,v 1.17 2012/03/13 18:40:38 elad Exp $ */
1.1       reinoud     2:
                      3: /*
                      4:  * Copyright (c) 2008, 2009 Reinoud Zandijk
                      5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  *
                     16:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     17:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     18:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     19:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     20:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     21:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     22:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     23:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     24:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     25:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     26:  *
                     27:  */
                     28:
                     29: #include <sys/cdefs.h>
                     30: #ifndef lint
1.18    ! rmind      31: __KERNEL_RCSID(0, "$NetBSD: nilfs_vnops.c,v 1.17 2012/03/13 18:40:38 elad Exp $");
1.1       reinoud    32: #endif /* not lint */
                     33:
                     34:
                     35: #include <sys/param.h>
                     36: #include <sys/systm.h>
                     37: #include <sys/namei.h>
                     38: #include <sys/resourcevar.h>   /* defines plimit structure in proc struct */
                     39: #include <sys/kernel.h>
                     40: #include <sys/file.h>          /* define FWRITE ... */
                     41: #include <sys/stat.h>
                     42: #include <sys/buf.h>
                     43: #include <sys/proc.h>
                     44: #include <sys/mount.h>
                     45: #include <sys/vnode.h>
                     46: #include <sys/signalvar.h>
                     47: #include <sys/malloc.h>
                     48: #include <sys/dirent.h>
                     49: #include <sys/lockf.h>
                     50: #include <sys/kauth.h>
                     51:
                     52: #include <miscfs/genfs/genfs.h>
                     53: #include <uvm/uvm_extern.h>
                     54:
                     55: #include <fs/nilfs/nilfs_mount.h>
                     56: #include "nilfs.h"
                     57: #include "nilfs_subr.h"
                     58: #include "nilfs_bswap.h"
                     59:
                     60:
                     61: #define VTOI(vnode) ((struct nilfs_node *) (vnode)->v_data)
                     62:
                     63:
                     64: /* externs */
                     65: extern int prtactive;
                     66:
                     67: /* implementations of vnode functions; table follows at end */
                     68: /* --------------------------------------------------------------------- */
                     69:
                     70: int
                     71: nilfs_inactive(void *v)
                     72: {
                     73:        struct vop_inactive_args /* {
                     74:                struct vnode *a_vp;
                     75:                bool         *a_recycle;
                     76:        } */ *ap = v;
                     77:        struct vnode *vp = ap->a_vp;
                     78:        struct nilfs_node *nilfs_node = VTOI(vp);
                     79:
                     80:        DPRINTF(NODE, ("nilfs_inactive called for nilfs_node %p\n", VTOI(vp)));
                     81:
                     82:        if (nilfs_node == NULL) {
                     83:                DPRINTF(NODE, ("nilfs_inactive: inactive NULL NILFS node\n"));
1.7       hannken    84:                VOP_UNLOCK(vp);
1.1       reinoud    85:                return 0;
                     86:        }
                     87:
                     88:        /*
                     89:         * Optionally flush metadata to disc. If the file has not been
                     90:         * referenced anymore in a directory we ought to free up the resources
                     91:         * on disc if applicable.
                     92:         */
1.7       hannken    93:        VOP_UNLOCK(vp);
1.1       reinoud    94:
                     95:        return 0;
                     96: }
                     97:
                     98: /* --------------------------------------------------------------------- */
                     99:
                    100: int
                    101: nilfs_reclaim(void *v)
                    102: {
                    103:        struct vop_reclaim_args /* {
                    104:                struct vnode *a_vp;
                    105:        } */ *ap = v;
                    106:        struct vnode *vp = ap->a_vp;
                    107:        struct nilfs_node *nilfs_node = VTOI(vp);
                    108:
                    109:        DPRINTF(NODE, ("nilfs_reclaim called for node %p\n", nilfs_node));
                    110:        if (prtactive && vp->v_usecount > 1)
                    111:                vprint("nilfs_reclaim(): pushing active", vp);
                    112:
                    113:        if (nilfs_node == NULL) {
                    114:                DPRINTF(NODE, ("nilfs_reclaim(): null nilfsnode\n"));
                    115:                return 0;
                    116:        }
                    117:
                    118:        /* update note for closure */
                    119:        nilfs_update(vp, NULL, NULL, NULL, UPDATE_CLOSE);
                    120:
                    121:        /* dispose all node knowledge */
                    122:        nilfs_dispose_node(&nilfs_node);
                    123:
                    124:        return 0;
                    125: }
                    126:
                    127: /* --------------------------------------------------------------------- */
                    128:
                    129: int
                    130: nilfs_read(void *v)
                    131: {
                    132:        struct vop_read_args /* {
                    133:                struct vnode *a_vp;
                    134:                struct uio *a_uio;
                    135:                int a_ioflag;
                    136:                kauth_cred_t a_cred;
                    137:        } */ *ap = v;
                    138:        struct vnode *vp     = ap->a_vp;
                    139:        struct uio   *uio    = ap->a_uio;
                    140:        int           ioflag = ap->a_ioflag;
                    141:        int           advice = IO_ADV_DECODE(ap->a_ioflag);
                    142:        struct uvm_object    *uobj;
                    143:        struct nilfs_node      *nilfs_node = VTOI(vp);
                    144:        uint64_t file_size;
                    145:        vsize_t len;
                    146:        int error;
                    147:
                    148:        DPRINTF(READ, ("nilfs_read called\n"));
                    149:
                    150:        /* can this happen? some filingsystems have this check */
                    151:        if (uio->uio_offset < 0)
                    152:                return EINVAL;
                    153:        if (uio->uio_resid == 0)
                    154:                return 0;
                    155:
                    156:        /* protect against rogue programs reading raw directories and links */
                    157:        if ((ioflag & IO_ALTSEMANTICS) == 0) {
                    158:                if (vp->v_type == VDIR)
                    159:                        return EISDIR;
                    160:                /* all but regular files just give EINVAL */
                    161:                if (vp->v_type != VREG)
                    162:                        return EINVAL;
                    163:        }
                    164:
                    165:        assert(nilfs_node);
                    166:        file_size = nilfs_rw64(nilfs_node->inode.i_size);
                    167:
                    168:        /* read contents using buffercache */
                    169:        uobj = &vp->v_uobj;
                    170:        error = 0;
                    171:        while (uio->uio_resid > 0) {
                    172:                /* reached end? */
                    173:                if (file_size <= uio->uio_offset)
                    174:                        break;
                    175:
                    176:                /* maximise length to file extremity */
                    177:                len = MIN(file_size - uio->uio_offset, uio->uio_resid);
                    178:                if (len == 0)
                    179:                        break;
                    180:
                    181:                /* ubc, here we come, prepare to trap */
                    182:                error = ubc_uiomove(uobj, uio, len, advice,
                    183:                    UBC_READ | UBC_PARTIALOK | UBC_UNMAP_FLAG(vp));
                    184:                if (error)
                    185:                        break;
                    186:        }
                    187:
                    188:        /* note access time unless not requested */
                    189:        if (!(vp->v_mount->mnt_flag & MNT_NOATIME)) {
                    190:                nilfs_node->i_flags |= IN_ACCESS;
                    191:                if ((ioflag & IO_SYNC) == IO_SYNC)
                    192:                        error = nilfs_update(vp, NULL, NULL, NULL, UPDATE_WAIT);
                    193:        }
                    194:
                    195:        return error;
                    196: }
                    197:
                    198: /* --------------------------------------------------------------------- */
                    199:
                    200: int
                    201: nilfs_write(void *v)
                    202: {
                    203:        struct vop_write_args /* {
                    204:                struct vnode *a_vp;
                    205:                struct uio *a_uio;
                    206:                int a_ioflag;
                    207:                kauth_cred_t a_cred;
                    208:        } */ *ap = v;
                    209:        struct vnode *vp     = ap->a_vp;
                    210:        struct uio   *uio    = ap->a_uio;
                    211:        int           ioflag = ap->a_ioflag;
                    212:        int           advice = IO_ADV_DECODE(ap->a_ioflag);
                    213:        struct uvm_object    *uobj;
                    214:        struct nilfs_node      *nilfs_node = VTOI(vp);
                    215:        uint64_t file_size, old_size;
                    216:        vsize_t len;
1.13      rmind     217:        int error, resid, extended;
1.1       reinoud   218:
                    219:        DPRINTF(WRITE, ("nilfs_write called\n"));
                    220:
                    221:        /* can this happen? some filingsystems have this check */
                    222:        if (uio->uio_offset < 0)
                    223:                return EINVAL;
                    224:        if (uio->uio_resid == 0)
                    225:                return 0;
                    226:
                    227:        /* protect against rogue programs writing raw directories or links */
                    228:        if ((ioflag & IO_ALTSEMANTICS) == 0) {
                    229:                if (vp->v_type == VDIR)
                    230:                        return EISDIR;
                    231:                /* all but regular files just give EINVAL for now */
                    232:                if (vp->v_type != VREG)
                    233:                        return EINVAL;
                    234:        }
                    235:
                    236:        assert(nilfs_node);
                    237:        panic("nilfs_write() called\n");
                    238: return EIO;
                    239:
                    240:        /* remember old file size */
                    241:        assert(nilfs_node);
                    242:        file_size = nilfs_rw64(nilfs_node->inode.i_size);
                    243:        old_size = file_size;
                    244:
                    245:        /* if explicitly asked to append, uio_offset can be wrong? */
                    246:        if (ioflag & IO_APPEND)
                    247:                uio->uio_offset = file_size;
                    248:
                    249: #if 0
                    250:        extended = (uio->uio_offset + uio->uio_resid > file_size);
                    251:        if (extended) {
                    252:                DPRINTF(WRITE, ("extending file from %"PRIu64" to %"PRIu64"\n",
                    253:                        file_size, uio->uio_offset + uio->uio_resid));
                    254:                error = nilfs_grow_node(nilfs_node, uio->uio_offset + uio->uio_resid);
                    255:                if (error)
                    256:                        return error;
                    257:                file_size = uio->uio_offset + uio->uio_resid;
                    258:        }
                    259: #endif
                    260:
                    261:        /* write contents using buffercache */
                    262:        uobj = &vp->v_uobj;
                    263:        resid = uio->uio_resid;
                    264:        error = 0;
                    265:
                    266:        uvm_vnp_setwritesize(vp, file_size);
                    267:        while (uio->uio_resid > 0) {
                    268:                /* maximise length to file extremity */
                    269:                len = MIN(file_size - uio->uio_offset, uio->uio_resid);
                    270:                if (len == 0)
                    271:                        break;
                    272:
                    273:                /* ubc, here we come, prepare to trap */
                    274:                error = ubc_uiomove(uobj, uio, len, advice,
                    275:                    UBC_WRITE | UBC_UNMAP_FLAG(vp));
                    276:                if (error)
                    277:                        break;
                    278:        }
                    279:        uvm_vnp_setsize(vp, file_size);
                    280:
                    281:        /* mark node changed and request update */
                    282:        nilfs_node->i_flags |= IN_CHANGE | IN_UPDATE;
1.16      christos  283:        if (vp->v_mount->mnt_flag & MNT_RELATIME)
                    284:                nilfs_node->i_flags |= IN_ACCESS;
1.1       reinoud   285:
                    286:        /*
                    287:         * XXX TODO FFS has code here to reset setuid & setgid when we're not
                    288:         * the superuser as a precaution against tampering.
                    289:         */
                    290:
                    291:        /* if we wrote a thing, note write action on vnode */
                    292:        if (resid > uio->uio_resid)
                    293:                VN_KNOTE(vp, NOTE_WRITE | (extended ? NOTE_EXTEND : 0));
                    294:
                    295:        if (error) {
                    296:                /* bring back file size to its former size */
                    297:                /* take notice of its errors? */
                    298: //             (void) nilfs_chsize(vp, (u_quad_t) old_size, NOCRED);
                    299:
                    300:                /* roll back uio */
                    301:                uio->uio_offset -= resid - uio->uio_resid;
                    302:                uio->uio_resid = resid;
                    303:        } else {
                    304:                /* if we write and we're synchronous, update node */
                    305:                if ((resid > uio->uio_resid) && ((ioflag & IO_SYNC) == IO_SYNC))
                    306:                        error = nilfs_update(vp, NULL, NULL, NULL, UPDATE_WAIT);
                    307:        }
                    308:
                    309:        return error;
                    310: }
                    311:
                    312:
                    313: /* --------------------------------------------------------------------- */
                    314:
                    315: /*
1.6       reinoud   316:  * bmap functionality that translates logical block numbers to the virtual
                    317:  * block numbers to be stored on the vnode itself.
1.1       reinoud   318:  */
                    319:
                    320: int
                    321: nilfs_trivial_bmap(void *v)
                    322: {
                    323:        struct vop_bmap_args /* {
                    324:                struct vnode *a_vp;
                    325:                daddr_t a_bn;
                    326:                struct vnode **a_vpp;
                    327:                daddr_t *a_bnp;
                    328:                int *a_runp;
                    329:        } */ *ap = v;
                    330:        struct vnode  *vp  = ap->a_vp;  /* our node     */
                    331:        struct vnode **vpp = ap->a_vpp; /* return node  */
                    332:        daddr_t *bnp  = ap->a_bnp;      /* translated   */
                    333:        daddr_t  bn   = ap->a_bn;       /* origional    */
                    334:        int     *runp = ap->a_runp;
                    335:        struct nilfs_node *node = VTOI(vp);
1.6       reinoud   336:        uint64_t *l2vmap;
1.1       reinoud   337:        uint32_t blocksize;
1.6       reinoud   338:        int blks, run, error;
1.1       reinoud   339:
                    340:        DPRINTF(TRANSLATE, ("nilfs_bmap() called\n"));
                    341:        /* XXX could return `-1' to indicate holes/zero's */
                    342:
                    343:        blocksize = node->nilfsdev->blocksize;
1.6       reinoud   344:        blks = MAXPHYS / blocksize;
1.1       reinoud   345:
1.6       reinoud   346:        /* get mapping memory */
                    347:        l2vmap = malloc(sizeof(uint64_t) * blks, M_TEMP, M_WAITOK);
                    348:
                    349:        /* get virtual block numbers for the vnode's buffer span */
                    350:        error = nilfs_btree_nlookup(node, bn, blks, l2vmap);
                    351:        if (error) {
                    352:                free(l2vmap, M_TEMP);
                    353:                return error;
                    354:        }
                    355:
                    356:        /* store virtual blocks on our own vp */
1.1       reinoud   357:        if (vpp)
                    358:                *vpp = vp;
                    359:
1.6       reinoud   360:        /* start at virt[0] */
                    361:        *bnp = l2vmap[0];
                    362:
                    363:        /* get runlength */
                    364:        run = 1;
                    365:        while ((run < blks) && (l2vmap[run] == *bnp + run))
                    366:                run++;
                    367:
                    368:        /* set runlength */
1.1       reinoud   369:        if (runp)
1.6       reinoud   370:                *runp = run;
                    371:
                    372:        DPRINTF(TRANSLATE, ("\tstart %"PRIu64" -> %"PRIu64" run %d\n",
                    373:                bn, *bnp, run));
                    374:
                    375:        /* mark not translated on virtual block number 0 */
                    376:        if (*bnp == 0)
                    377:                *bnp = -1;
1.1       reinoud   378:
                    379:        /* return success */
1.6       reinoud   380:        free(l2vmap, M_TEMP);
1.1       reinoud   381:        return 0;
                    382: }
                    383:
                    384: /* --------------------------------------------------------------------- */
                    385:
                    386: static void
                    387: nilfs_read_filebuf(struct nilfs_node *node, struct buf *bp)
                    388: {
                    389:        struct nilfs_device *nilfsdev = node->nilfsdev;
                    390:        struct buf *nbp;
                    391:        uint64_t *l2vmap, *v2pmap;
                    392:        uint64_t from, blks;
                    393:        uint32_t blocksize, buf_offset;
                    394:        uint8_t  *buf_pos;
                    395:        int blk2dev = nilfsdev->blocksize / DEV_BSIZE;
                    396:        int i, error;
                    397:
                    398:        /*
                    399:         * Translate all the block sectors into a series of buffers to read
                    400:         * asynchronously from the nilfs device. Note that this lookup may
                    401:         * induce readin's too.
                    402:         */
                    403:
                    404:        blocksize = nilfsdev->blocksize;
                    405:
                    406:        from = bp->b_blkno;
                    407:        blks = bp->b_bcount / blocksize;
                    408:
                    409:        DPRINTF(READ, ("\tread in from inode %"PRIu64" blkno %"PRIu64" "
                    410:                        "+ %"PRIu64" blocks\n", node->ino, from, blks));
                    411:
                    412:        DPRINTF(READ, ("\t\tblkno %"PRIu64" "
                    413:                        "+ %d bytes\n", bp->b_blkno, bp->b_bcount));
                    414:
                    415:        /* get mapping memory */
                    416:        l2vmap = malloc(sizeof(uint64_t) * blks, M_TEMP, M_WAITOK);
                    417:        v2pmap = malloc(sizeof(uint64_t) * blks, M_TEMP, M_WAITOK);
                    418:
                    419:        /* get virtual block numbers for the vnode's buffer span */
1.6       reinoud   420:        for (i = 0; i < blks; i++)
                    421:                l2vmap[i] = from + i;
1.1       reinoud   422:
                    423:        /* translate virtual block numbers to physical block numbers */
                    424:        error = nilfs_nvtop(node, blks, l2vmap, v2pmap);
                    425:        if (error)
                    426:                goto out;
                    427:
                    428:        /* issue translated blocks */
                    429:        bp->b_resid = bp->b_bcount;
                    430:        for (i = 0; i < blks; i++) {
                    431:                DPRINTF(READ, ("read_filebuf : ino %"PRIu64" blk %d -> "
                    432:                        "%"PRIu64" -> %"PRIu64"\n",
                    433:                        node->ino, i, l2vmap[i], v2pmap[i]));
                    434:
                    435:                buf_offset = i * blocksize;
                    436:                buf_pos    = (uint8_t *) bp->b_data + buf_offset;
                    437:
                    438:                /* note virtual block 0 marks not mapped */
                    439:                if (l2vmap[i] == 0) {
                    440:                        memset(buf_pos, 0, blocksize);
                    441:                        nestiobuf_done(bp, blocksize, 0);
                    442:                        continue;
                    443:                }
                    444:
                    445:                /* nest iobuf */
                    446:                nbp = getiobuf(NULL, true);
                    447:                nestiobuf_setup(bp, nbp, buf_offset, blocksize);
                    448:                KASSERT(nbp->b_vp == node->vnode);
                    449:                /* nbp is B_ASYNC */
                    450:
                    451:                nbp->b_lblkno   = i;
                    452:                nbp->b_blkno    = v2pmap[i] * blk2dev;  /* in DEV_BSIZE */
                    453:                nbp->b_rawblkno = nbp->b_blkno;
                    454:
                    455:                VOP_STRATEGY(nilfsdev->devvp, nbp);
                    456:        }
                    457:
                    458:        if ((bp->b_flags & B_ASYNC) == 0)
                    459:                biowait(bp);
                    460:
                    461: out:
                    462:        free(l2vmap, M_TEMP);
                    463:        free(v2pmap, M_TEMP);
                    464:        if (error) {
                    465:                bp->b_error = EIO;
                    466:                biodone(bp);
                    467:        }
                    468: }
                    469:
                    470:
                    471: static void
                    472: nilfs_write_filebuf(struct nilfs_node *node, struct buf *bp)
                    473: {
                    474:        /* TODO pass on to segment collector */
                    475:        panic("nilfs_strategy writing called\n");
                    476: }
                    477:
                    478:
                    479: int
                    480: nilfs_vfsstrategy(void *v)
                    481: {
                    482:        struct vop_strategy_args /* {
                    483:                struct vnode *a_vp;
                    484:                struct buf *a_bp;
                    485:        } */ *ap = v;
                    486:        struct vnode *vp = ap->a_vp;
                    487:        struct buf   *bp = ap->a_bp;
                    488:        struct nilfs_node *node = VTOI(vp);
                    489:
                    490:        DPRINTF(STRATEGY, ("nilfs_strategy called\n"));
                    491:
                    492:        /* check if we ought to be here */
                    493:        if (vp->v_type == VBLK || vp->v_type == VCHR)
                    494:                panic("nilfs_strategy: spec");
                    495:
                    496:        /* translate if needed and pass on */
                    497:        if (bp->b_flags & B_READ) {
                    498:                nilfs_read_filebuf(node, bp);
                    499:                return bp->b_error;
                    500:        }
                    501:
                    502:        /* send to segment collector */
                    503:        nilfs_write_filebuf(node, bp);
                    504:        return bp->b_error;
                    505: }
                    506:
                    507: /* --------------------------------------------------------------------- */
                    508:
                    509: int
                    510: nilfs_readdir(void *v)
                    511: {
                    512:        struct vop_readdir_args /* {
                    513:                struct vnode *a_vp;
                    514:                struct uio *a_uio;
                    515:                kauth_cred_t a_cred;
                    516:                int *a_eofflag;
                    517:                off_t **a_cookies;
                    518:                int *a_ncookies;
                    519:        } */ *ap = v;
                    520:        struct uio *uio = ap->a_uio;
                    521:        struct vnode *vp = ap->a_vp;
                    522:        struct nilfs_node *node = VTOI(vp);
                    523:        struct nilfs_dir_entry *ndirent;
                    524:        struct dirent dirent;
                    525:        struct buf *bp;
                    526:        uint64_t file_size, diroffset, transoffset, blkoff;
                    527:        uint64_t blocknr;
                    528:        uint32_t blocksize = node->nilfsdev->blocksize;
                    529:        uint8_t *pos, name_len;
                    530:        int error;
                    531:
                    532:        DPRINTF(READDIR, ("nilfs_readdir called\n"));
                    533:
                    534:        if (vp->v_type != VDIR)
                    535:                return ENOTDIR;
                    536:
                    537:        file_size = nilfs_rw64(node->inode.i_size);
                    538:
                    539:        /* we are called just as long as we keep on pushing data in */
                    540:        error = 0;
                    541:        if ((uio->uio_offset < file_size) &&
                    542:            (uio->uio_resid >= sizeof(struct dirent))) {
                    543:                diroffset   = uio->uio_offset;
                    544:                transoffset = diroffset;
                    545:
                    546:                blocknr = diroffset / blocksize;
                    547:                blkoff  = diroffset % blocksize;
                    548:                error = nilfs_bread(node, blocknr, NOCRED, 0, &bp);
                    549:                if (error)
                    550:                        return EIO;
                    551:                while (diroffset < file_size) {
                    552:                        DPRINTF(READDIR, ("readdir : offset = %"PRIu64"\n",
                    553:                                diroffset));
                    554:                        if (blkoff >= blocksize) {
                    555:                                blkoff = 0; blocknr++;
                    556:                                brelse(bp, BC_AGE);
                    557:                                error = nilfs_bread(node, blocknr, NOCRED, 0,
                    558:                                                &bp);
                    559:                                if (error)
                    560:                                        return EIO;
                    561:                        }
                    562:
                    563:                        /* read in one dirent */
                    564:                        pos = (uint8_t *) bp->b_data + blkoff;
                    565:                        ndirent = (struct nilfs_dir_entry *) pos;
                    566:
                    567:                        name_len = ndirent->name_len;
                    568:                        memset(&dirent, 0, sizeof(struct dirent));
                    569:                        dirent.d_fileno = nilfs_rw64(ndirent->inode);
                    570:                        dirent.d_type   = ndirent->file_type;   /* 1:1 ? */
                    571:                        dirent.d_namlen = name_len;
                    572:                        strncpy(dirent.d_name, ndirent->name, name_len);
                    573:                        dirent.d_reclen = _DIRENT_SIZE(&dirent);
                    574:                        DPRINTF(READDIR, ("copying `%*.*s`\n", name_len,
                    575:                                name_len, dirent.d_name));
                    576:
                    577:                        /*
                    578:                         * If there isn't enough space in the uio to return a
                    579:                         * whole dirent, break off read
                    580:                         */
                    581:                        if (uio->uio_resid < _DIRENT_SIZE(&dirent))
                    582:                                break;
                    583:
                    584:                        /* transfer */
                    585:                        if (name_len)
                    586:                                uiomove(&dirent, _DIRENT_SIZE(&dirent), uio);
                    587:
                    588:                        /* advance */
                    589:                        diroffset += nilfs_rw16(ndirent->rec_len);
                    590:                        blkoff    += nilfs_rw16(ndirent->rec_len);
                    591:
                    592:                        /* remember the last entry we transfered */
                    593:                        transoffset = diroffset;
                    594:                }
                    595:                brelse(bp, BC_AGE);
                    596:
                    597:                /* pass on last transfered offset */
                    598:                uio->uio_offset = transoffset;
                    599:        }
                    600:
                    601:        if (ap->a_eofflag)
                    602:                *ap->a_eofflag = (uio->uio_offset >= file_size);
                    603:
                    604:        return error;
                    605: }
                    606:
                    607: /* --------------------------------------------------------------------- */
                    608:
                    609: int
                    610: nilfs_lookup(void *v)
                    611: {
                    612:        struct vop_lookup_args /* {
                    613:                struct vnode *a_dvp;
                    614:                struct vnode **a_vpp;
                    615:                struct componentname *a_cnp;
                    616:        } */ *ap = v;
                    617:        struct vnode *dvp = ap->a_dvp;
                    618:        struct vnode **vpp = ap->a_vpp;
                    619:        struct componentname *cnp = ap->a_cnp;
                    620:        struct nilfs_node  *dir_node, *res_node;
                    621:        struct nilfs_mount *ump;
                    622:        uint64_t ino;
                    623:        const char *name;
                    624:        int namelen, nameiop, islastcn, mounted_ro;
                    625:        int vnodetp;
                    626:        int error, found;
                    627:
                    628:        dir_node = VTOI(dvp);
                    629:        ump = dir_node->ump;
                    630:        *vpp = NULL;
                    631:
                    632:        DPRINTF(LOOKUP, ("nilfs_lookup called\n"));
                    633:
                    634:        /* simplify/clarification flags */
                    635:        nameiop     = cnp->cn_nameiop;
                    636:        islastcn    = cnp->cn_flags & ISLASTCN;
                    637:        mounted_ro  = dvp->v_mount->mnt_flag & MNT_RDONLY;
                    638:
                    639:        /* check exec/dirread permissions first */
                    640:        error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred);
                    641:        if (error)
                    642:                return error;
                    643:
                    644:        DPRINTF(LOOKUP, ("\taccess ok\n"));
                    645:
                    646:        /*
                    647:         * If requesting a modify on the last path element on a read-only
                    648:         * filingsystem, reject lookup; XXX why is this repeated in every FS ?
                    649:         */
                    650:        if (islastcn && mounted_ro && (nameiop == DELETE || nameiop == RENAME))
                    651:                return EROFS;
                    652:
                    653:        DPRINTF(LOOKUP, ("\tlooking up cnp->cn_nameptr '%s'\n",
                    654:            cnp->cn_nameptr));
                    655:        /* look in the nami cache; returns 0 on success!! */
                    656:        error = cache_lookup(dvp, vpp, cnp);
                    657:        if (error >= 0)
                    658:                return error;
                    659:
                    660:        DPRINTF(LOOKUP, ("\tNOT found in cache\n"));
                    661:
                    662:        /*
                    663:         * Obviously, the file is not (anymore) in the namecache, we have to
                    664:         * search for it. There are three basic cases: '.', '..' and others.
                    665:         *
                    666:         * Following the guidelines of VOP_LOOKUP manpage and tmpfs.
                    667:         */
                    668:        error = 0;
                    669:        if ((cnp->cn_namelen == 1) && (cnp->cn_nameptr[0] == '.')) {
                    670:                DPRINTF(LOOKUP, ("\tlookup '.'\n"));
                    671:                /* special case 1 '.' */
1.4       pooka     672:                vref(dvp);
1.1       reinoud   673:                *vpp = dvp;
                    674:                /* done */
                    675:        } else if (cnp->cn_flags & ISDOTDOT) {
                    676:                /* special case 2 '..' */
                    677:                DPRINTF(LOOKUP, ("\tlookup '..'\n"));
                    678:
                    679:                /* get our node */
                    680:                name    = "..";
                    681:                namelen = 2;
                    682:                error = nilfs_lookup_name_in_dir(dvp, name, namelen,
                    683:                                &ino, &found);
                    684:                if (error)
                    685:                        goto out;
                    686:                if (!found)
                    687:                        error = ENOENT;
                    688:
                    689:                /* first unlock parent */
1.7       hannken   690:                VOP_UNLOCK(dvp);
1.1       reinoud   691:
                    692:                if (error == 0) {
                    693:                        DPRINTF(LOOKUP, ("\tfound '..'\n"));
                    694:                        /* try to create/reuse the node */
                    695:                        error = nilfs_get_node(ump, ino, &res_node);
                    696:
                    697:                        if (!error) {
                    698:                                DPRINTF(LOOKUP,
                    699:                                        ("\tnode retrieved/created OK\n"));
                    700:                                *vpp = res_node->vnode;
                    701:                        }
                    702:                }
                    703:
                    704:                /* try to relock parent */
                    705:                vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
                    706:        } else {
                    707:                DPRINTF(LOOKUP, ("\tlookup file\n"));
                    708:                /* all other files */
                    709:                /* lookup filename in the directory returning its inode */
                    710:                name    = cnp->cn_nameptr;
                    711:                namelen = cnp->cn_namelen;
                    712:                error = nilfs_lookup_name_in_dir(dvp, name, namelen,
                    713:                                &ino, &found);
                    714:                if (error)
                    715:                        goto out;
                    716:                if (!found) {
                    717:                        DPRINTF(LOOKUP, ("\tNOT found\n"));
                    718:                        /*
                    719:                         * UGH, didn't find name. If we're creating or
                    720:                         * renaming on the last name this is OK and we ought
                    721:                         * to return EJUSTRETURN if its allowed to be created.
                    722:                         */
                    723:                        error = ENOENT;
                    724:                        if (islastcn &&
                    725:                                (nameiop == CREATE || nameiop == RENAME))
                    726:                                        error = 0;
                    727:                        if (!error) {
                    728:                                error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred);
                    729:                                if (!error) {
                    730:                                        error = EJUSTRETURN;
                    731:                                }
                    732:                        }
                    733:                        /* done */
                    734:                } else {
                    735:                        /* try to create/reuse the node */
                    736:                        error = nilfs_get_node(ump, ino, &res_node);
                    737:                        if (!error) {
                    738:                                /*
                    739:                                 * If we are not at the last path component
                    740:                                 * and found a non-directory or non-link entry
                    741:                                 * (which may itself be pointing to a
                    742:                                 * directory), raise an error.
                    743:                                 */
                    744:                                vnodetp = res_node->vnode->v_type;
                    745:                                if ((vnodetp != VDIR) && (vnodetp != VLNK)) {
                    746:                                        if (!islastcn)
                    747:                                                error = ENOTDIR;
                    748:                                }
                    749:
                    750:                        }
                    751:                        if (!error) {
                    752:                                *vpp = res_node->vnode;
                    753:                        }
                    754:                }
                    755:        }
                    756:
                    757: out:
                    758:        /*
                    759:         * Store result in the cache if requested. If we are creating a file,
                    760:         * the file might not be found and thus putting it into the namecache
                    761:         * might be seen as negative caching.
                    762:         */
1.18    ! rmind     763:        if (nameiop != CREATE)
1.1       reinoud   764:                cache_enter(dvp, *vpp, cnp);
                    765:
                    766:        DPRINTFIF(LOOKUP, error, ("nilfs_lookup returing error %d\n", error));
                    767:
                    768:        return error;
                    769: }
                    770:
                    771: /* --------------------------------------------------------------------- */
                    772:
                    773: static void
                    774: nilfs_ctime_to_timespec(struct timespec *ts, uint64_t ctime)
                    775: {
                    776:        ts->tv_sec  = ctime;
                    777:        ts->tv_nsec = 0;
                    778: }
                    779:
                    780:
                    781: int
                    782: nilfs_getattr(void *v)
                    783: {
                    784:        struct vop_getattr_args /* {
                    785:                struct vnode *a_vp;
                    786:                struct vattr *a_vap;
                    787:                kauth_cred_t a_cred;
                    788:                struct lwp   *a_l;
                    789:        } */ *ap = v;
                    790:        struct vnode       *vp  = ap->a_vp;
                    791:        struct vattr       *vap = ap->a_vap;
                    792:        struct nilfs_node  *node = VTOI(vp);
                    793:        struct nilfs_inode *inode = &node->inode;
                    794:
                    795:        DPRINTF(VFSCALL, ("nilfs_getattr called\n"));
                    796:
                    797:        /* basic info */
1.4       pooka     798:        vattr_null(vap);
1.1       reinoud   799:        vap->va_type      = vp->v_type;
                    800:        vap->va_mode      = nilfs_rw16(inode->i_mode);  /* XXX same? */
                    801:        vap->va_nlink     = nilfs_rw16(inode->i_links_count);
                    802:        vap->va_uid       = nilfs_rw32(inode->i_uid);
                    803:        vap->va_gid       = nilfs_rw32(inode->i_gid);
                    804:        vap->va_fsid      = vp->v_mount->mnt_stat.f_fsidx.__fsid_val[0];
                    805:        vap->va_fileid    = node->ino;
                    806:        vap->va_size      = nilfs_rw64(inode->i_size);
                    807:        vap->va_blocksize = node->nilfsdev->blocksize;
                    808:
                    809:        /* times */
                    810:        nilfs_ctime_to_timespec(&vap->va_atime, nilfs_rw64(inode->i_mtime));
                    811:        nilfs_ctime_to_timespec(&vap->va_mtime, nilfs_rw64(inode->i_mtime));
                    812:        nilfs_ctime_to_timespec(&vap->va_ctime, nilfs_rw64(inode->i_ctime));
                    813:        nilfs_ctime_to_timespec(&vap->va_birthtime, nilfs_rw64(inode->i_ctime));
                    814:
                    815:        vap->va_gen       = nilfs_rw32(inode->i_generation);
                    816:        vap->va_flags     = 0;  /* vattr flags */
                    817:        vap->va_bytes     = nilfs_rw64(inode->i_blocks) * vap->va_blocksize;
                    818:        vap->va_filerev   = vap->va_gen;  /* XXX file revision? same as gen? */
                    819:        vap->va_vaflags   = 0;  /* XXX chflags flags */
                    820:
                    821:        return 0;
                    822: }
                    823:
                    824: /* --------------------------------------------------------------------- */
                    825:
                    826: #if 0
                    827: static int
                    828: nilfs_chown(struct vnode *vp, uid_t new_uid, gid_t new_gid,
                    829:          kauth_cred_t cred)
                    830: {
                    831:        return EINVAL;
                    832: }
                    833:
                    834:
                    835: static int
                    836: nilfs_chmod(struct vnode *vp, mode_t mode, kauth_cred_t cred)
                    837: {
                    838:
                    839:        return EINVAL;
                    840: }
                    841:
                    842:
                    843: /* exported */
                    844: int
                    845: nilfs_chsize(struct vnode *vp, u_quad_t newsize, kauth_cred_t cred)
                    846: {
                    847:        return EINVAL;
                    848: }
                    849:
                    850:
                    851: static int
                    852: nilfs_chflags(struct vnode *vp, mode_t mode, kauth_cred_t cred)
                    853: {
                    854:        return EINVAL;
                    855: }
                    856:
                    857:
                    858: static int
                    859: nilfs_chtimes(struct vnode *vp,
                    860:        struct timespec *atime, struct timespec *mtime,
                    861:        struct timespec *birthtime, int setattrflags,
                    862:        kauth_cred_t cred)
                    863: {
                    864:        return EINVAL;
                    865: }
                    866: #endif
                    867:
                    868:
                    869: int
                    870: nilfs_setattr(void *v)
                    871: {
                    872:        struct vop_setattr_args /* {
                    873:                struct vnode *a_vp;
                    874:                struct vattr *a_vap;
                    875:                kauth_cred_t a_cred;
                    876:                struct lwp   *a_l;
                    877:        } */ *ap = v;
                    878:        struct vnode *vp = ap->a_vp;
                    879:
                    880:        vp = vp;
                    881:        DPRINTF(VFSCALL, ("nilfs_setattr called\n"));
                    882:        return EINVAL;
                    883: }
                    884:
                    885: /* --------------------------------------------------------------------- */
                    886:
                    887: /*
                    888:  * Return POSIX pathconf information for NILFS file systems.
                    889:  */
                    890: int
                    891: nilfs_pathconf(void *v)
                    892: {
                    893:        struct vop_pathconf_args /* {
                    894:                struct vnode *a_vp;
                    895:                int a_name;
                    896:                register_t *a_retval;
                    897:        } */ *ap = v;
                    898:        uint32_t bits;
                    899:
                    900:        DPRINTF(VFSCALL, ("nilfs_pathconf called\n"));
                    901:
                    902:        switch (ap->a_name) {
                    903:        case _PC_LINK_MAX:
                    904:                *ap->a_retval = (1<<16)-1;      /* 16 bits */
                    905:                return 0;
                    906:        case _PC_NAME_MAX:
1.14      christos  907:                *ap->a_retval = NILFS_MAXNAMLEN;
1.1       reinoud   908:                return 0;
                    909:        case _PC_PATH_MAX:
                    910:                *ap->a_retval = PATH_MAX;
                    911:                return 0;
                    912:        case _PC_PIPE_BUF:
                    913:                *ap->a_retval = PIPE_BUF;
                    914:                return 0;
                    915:        case _PC_CHOWN_RESTRICTED:
                    916:                *ap->a_retval = 1;
                    917:                return 0;
                    918:        case _PC_NO_TRUNC:
                    919:                *ap->a_retval = 1;
                    920:                return 0;
                    921:        case _PC_SYNC_IO:
                    922:                *ap->a_retval = 0;     /* synchronised is off for performance */
                    923:                return 0;
                    924:        case _PC_FILESIZEBITS:
                    925:                /* 64 bit file offsets -> 2+floor(2log(2^64-1)) = 2 + 63 = 65 */
                    926:                bits = 64; /* XXX ought to deliver 65 */
                    927: #if 0
                    928:                if (nilfs_node)
                    929:                        bits = 64 * vp->v_mount->mnt_dev_bshift;
                    930: #endif
                    931:                *ap->a_retval = bits;
                    932:                return 0;
                    933:        }
                    934:
                    935:        return EINVAL;
                    936: }
                    937:
                    938:
                    939: /* --------------------------------------------------------------------- */
                    940:
                    941: int
                    942: nilfs_open(void *v)
                    943: {
                    944:        struct vop_open_args /* {
                    945:                struct vnode *a_vp;
                    946:                int a_mode;
                    947:                kauth_cred_t a_cred;
                    948:                struct proc *a_p;
                    949:        } */ *ap = v;
                    950:        int flags;
                    951:
                    952:        DPRINTF(VFSCALL, ("nilfs_open called\n"));
                    953:
                    954:        /*
                    955:         * Files marked append-only must be opened for appending.
                    956:         */
                    957:        flags = 0;
                    958:        if ((flags & APPEND) && (ap->a_mode & (FWRITE | O_APPEND)) == FWRITE)
                    959:                return (EPERM);
                    960:
                    961:        return 0;
                    962: }
                    963:
                    964:
                    965: /* --------------------------------------------------------------------- */
                    966:
                    967: int
                    968: nilfs_close(void *v)
                    969: {
                    970:        struct vop_close_args /* {
                    971:                struct vnode *a_vp;
                    972:                int a_fflag;
                    973:                kauth_cred_t a_cred;
                    974:                struct proc *a_p;
                    975:        } */ *ap = v;
                    976:        struct vnode *vp = ap->a_vp;
                    977:        struct nilfs_node *nilfs_node = VTOI(vp);
                    978:
                    979:        DPRINTF(VFSCALL, ("nilfs_close called\n"));
                    980:        nilfs_node = nilfs_node;        /* shut up gcc */
                    981:
1.12      rmind     982:        mutex_enter(vp->v_interlock);
1.1       reinoud   983:                if (vp->v_usecount > 1)
                    984:                        nilfs_itimes(nilfs_node, NULL, NULL, NULL);
1.12      rmind     985:        mutex_exit(vp->v_interlock);
1.1       reinoud   986:
                    987:        return 0;
                    988: }
                    989:
                    990:
                    991: /* --------------------------------------------------------------------- */
                    992:
1.2       elad      993: static int
                    994: nilfs_check_possible(struct vnode *vp, struct vattr *vap, mode_t mode)
1.1       reinoud   995: {
                    996:        int flags;
                    997:
                    998:        /* check if we are allowed to write */
1.2       elad      999:        switch (vap->va_type) {
1.1       reinoud  1000:        case VDIR:
                   1001:        case VLNK:
                   1002:        case VREG:
                   1003:                /*
                   1004:                 * normal nodes: check if we're on a read-only mounted
                   1005:                 * filingsystem and bomb out if we're trying to write.
                   1006:                 */
                   1007:                if ((mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY))
                   1008:                        return EROFS;
                   1009:                break;
                   1010:        case VBLK:
                   1011:        case VCHR:
                   1012:        case VSOCK:
                   1013:        case VFIFO:
                   1014:                /*
                   1015:                 * special nodes: even on read-only mounted filingsystems
                   1016:                 * these are allowed to be written to if permissions allow.
                   1017:                 */
                   1018:                break;
                   1019:        default:
                   1020:                /* no idea what this is */
                   1021:                return EINVAL;
                   1022:        }
                   1023:
                   1024:        /* noone may write immutable files */
                   1025:        /* TODO: get chflags(2) flags */
                   1026:        flags = 0;
                   1027:        if ((mode & VWRITE) && (flags & IMMUTABLE))
                   1028:                return EPERM;
                   1029:
1.2       elad     1030:        return 0;
                   1031: }
                   1032:
                   1033: static int
                   1034: nilfs_check_permitted(struct vnode *vp, struct vattr *vap, mode_t mode,
                   1035:     kauth_cred_t cred)
                   1036: {
                   1037:
1.1       reinoud  1038:        /* ask the generic genfs_can_access to advice on security */
1.17      elad     1039:        return kauth_authorize_vnode(cred, kauth_access_action(mode,
                   1040:            vp->v_type, vap->va_mode), vp, NULL, genfs_can_access(vp->v_type,
                   1041:            vap->va_mode, vap->va_uid, vap->va_gid, mode, cred));
1.1       reinoud  1042: }
                   1043:
1.2       elad     1044: int
                   1045: nilfs_access(void *v)
                   1046: {
                   1047:        struct vop_access_args /* {
                   1048:                struct vnode *a_vp;
                   1049:                int a_mode;
                   1050:                kauth_cred_t a_cred;
                   1051:                struct proc *a_p;
                   1052:        } */ *ap = v;
                   1053:        struct vnode    *vp   = ap->a_vp;
                   1054:        mode_t           mode = ap->a_mode;
                   1055:        kauth_cred_t     cred = ap->a_cred;
                   1056:        /* struct nilfs_node *nilfs_node = VTOI(vp); */
                   1057:        struct vattr vap;
                   1058:        int error;
                   1059:
                   1060:        DPRINTF(VFSCALL, ("nilfs_access called\n"));
                   1061:
                   1062:        error = VOP_GETATTR(vp, &vap, NULL);
                   1063:        if (error)
                   1064:                return error;
                   1065:
                   1066:        error = nilfs_check_possible(vp, &vap, mode);
                   1067:        if (error)
                   1068:                return error;
                   1069:
                   1070:        error = nilfs_check_permitted(vp, &vap, mode, cred);
                   1071:
                   1072:        return error;
                   1073: }
                   1074:
1.1       reinoud  1075: /* --------------------------------------------------------------------- */
                   1076:
                   1077: int
                   1078: nilfs_create(void *v)
                   1079: {
                   1080:        struct vop_create_args /* {
                   1081:                struct vnode *a_dvp;
                   1082:                struct vnode **a_vpp;
                   1083:                struct componentname *a_cnp;
                   1084:                struct vattr *a_vap;
                   1085:        } */ *ap = v;
                   1086:        struct vnode  *dvp = ap->a_dvp;
                   1087:        struct vnode **vpp = ap->a_vpp;
                   1088:        struct vattr  *vap  = ap->a_vap;
                   1089:        struct componentname *cnp = ap->a_cnp;
                   1090:        int error;
                   1091:
                   1092:        DPRINTF(VFSCALL, ("nilfs_create called\n"));
                   1093:        error = nilfs_create_node(dvp, vpp, vap, cnp);
                   1094:
                   1095:        vput(dvp);
                   1096:        return error;
                   1097: }
                   1098:
                   1099: /* --------------------------------------------------------------------- */
                   1100:
                   1101: int
                   1102: nilfs_mknod(void *v)
                   1103: {
                   1104:        struct vop_mknod_args /* {
                   1105:                struct vnode *a_dvp;
                   1106:                struct vnode **a_vpp;
                   1107:                struct componentname *a_cnp;
                   1108:                struct vattr *a_vap;
                   1109:        } */ *ap = v;
                   1110:        struct vnode  *dvp = ap->a_dvp;
                   1111:        struct vnode **vpp = ap->a_vpp;
                   1112:        struct vattr  *vap  = ap->a_vap;
                   1113:        struct componentname *cnp = ap->a_cnp;
                   1114:        int error;
                   1115:
                   1116:        DPRINTF(VFSCALL, ("nilfs_mknod called\n"));
                   1117:        error = nilfs_create_node(dvp, vpp, vap, cnp);
                   1118:
                   1119:        vput(dvp);
                   1120:        return error;
                   1121: }
                   1122:
                   1123: /* --------------------------------------------------------------------- */
                   1124:
                   1125: int
                   1126: nilfs_mkdir(void *v)
                   1127: {
                   1128:        struct vop_mkdir_args /* {
                   1129:                struct vnode *a_dvp;
                   1130:                struct vnode **a_vpp;
                   1131:                struct componentname *a_cnp;
                   1132:                struct vattr *a_vap;
                   1133:        } */ *ap = v;
                   1134:        struct vnode  *dvp = ap->a_dvp;
                   1135:        struct vnode **vpp = ap->a_vpp;
                   1136:        struct vattr  *vap  = ap->a_vap;
                   1137:        struct componentname *cnp = ap->a_cnp;
                   1138:        int error;
                   1139:
                   1140:        DPRINTF(VFSCALL, ("nilfs_mkdir called\n"));
                   1141:        error = nilfs_create_node(dvp, vpp, vap, cnp);
                   1142:
                   1143:        vput(dvp);
                   1144:        return error;
                   1145: }
                   1146:
                   1147: /* --------------------------------------------------------------------- */
                   1148:
                   1149: static int
                   1150: nilfs_do_link(struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
                   1151: {
                   1152:        struct nilfs_node *nilfs_node, *dir_node;
                   1153:        struct vattr vap;
                   1154:        int error;
                   1155:
                   1156:        DPRINTF(VFSCALL, ("nilfs_link called\n"));
1.10      rmind    1157:        KASSERT(dvp != vp);
                   1158:        KASSERT(vp->v_type != VDIR);
                   1159:        KASSERT(dvp->v_mount == vp->v_mount);
1.1       reinoud  1160:
                   1161:        /* lock node */
                   1162:        error = vn_lock(vp, LK_EXCLUSIVE);
                   1163:        if (error)
                   1164:                return error;
                   1165:
                   1166:        /* get attributes */
                   1167:        dir_node = VTOI(dvp);
                   1168:        nilfs_node = VTOI(vp);
                   1169:
                   1170:        error = VOP_GETATTR(vp, &vap, FSCRED);
1.5       hannken  1171:        if (error) {
1.7       hannken  1172:                VOP_UNLOCK(vp);
1.1       reinoud  1173:                return error;
1.5       hannken  1174:        }
1.1       reinoud  1175:
                   1176:        /* check link count overflow */
1.5       hannken  1177:        if (vap.va_nlink >= (1<<16)-1) {        /* uint16_t */
1.7       hannken  1178:                VOP_UNLOCK(vp);
1.1       reinoud  1179:                return EMLINK;
1.5       hannken  1180:        }
1.1       reinoud  1181:
1.5       hannken  1182:        error = nilfs_dir_attach(dir_node->ump, dir_node, nilfs_node,
                   1183:            &vap, cnp);
                   1184:        if (error)
1.7       hannken  1185:                VOP_UNLOCK(vp);
1.5       hannken  1186:        return error;
1.1       reinoud  1187: }
                   1188:
                   1189: int
                   1190: nilfs_link(void *v)
                   1191: {
                   1192:        struct vop_link_args /* {
                   1193:                struct vnode *a_dvp;
                   1194:                struct vnode *a_vp;
                   1195:                struct componentname *a_cnp;
                   1196:        } */ *ap = v;
                   1197:        struct vnode *dvp = ap->a_dvp;
                   1198:        struct vnode *vp  = ap->a_vp;
                   1199:        struct componentname *cnp = ap->a_cnp;
                   1200:        int error;
                   1201:
                   1202:        error = nilfs_do_link(dvp, vp, cnp);
                   1203:        if (error)
                   1204:                VOP_ABORTOP(dvp, cnp);
                   1205:
                   1206:        VN_KNOTE(vp, NOTE_LINK);
                   1207:        VN_KNOTE(dvp, NOTE_WRITE);
                   1208:        vput(dvp);
                   1209:
                   1210:        return error;
                   1211: }
                   1212:
                   1213: /* --------------------------------------------------------------------- */
                   1214:
                   1215: static int
                   1216: nilfs_do_symlink(struct nilfs_node *nilfs_node, char *target)
                   1217: {
                   1218:        return EROFS;
                   1219: }
                   1220:
                   1221:
                   1222: int
                   1223: nilfs_symlink(void *v)
                   1224: {
                   1225:        struct vop_symlink_args /* {
                   1226:                struct vnode *a_dvp;
                   1227:                struct vnode **a_vpp;
                   1228:                struct componentname *a_cnp;
                   1229:                struct vattr *a_vap;
                   1230:                char *a_target;
                   1231:        } */ *ap = v;
                   1232:        struct vnode  *dvp = ap->a_dvp;
                   1233:        struct vnode **vpp = ap->a_vpp;
                   1234:        struct vattr  *vap  = ap->a_vap;
                   1235:        struct componentname *cnp = ap->a_cnp;
                   1236:        struct nilfs_node *dir_node;
                   1237:        struct nilfs_node *nilfs_node;
                   1238:        int error;
                   1239:
                   1240:        DPRINTF(VFSCALL, ("nilfs_symlink called\n"));
                   1241:        DPRINTF(VFSCALL, ("\tlinking to `%s`\n",  ap->a_target));
                   1242:        error = nilfs_create_node(dvp, vpp, vap, cnp);
                   1243:        KASSERT(((error == 0) && (*vpp != NULL)) || ((error && (*vpp == NULL))));
                   1244:        if (!error) {
                   1245:                dir_node = VTOI(dvp);
                   1246:                nilfs_node = VTOI(*vpp);
                   1247:                KASSERT(nilfs_node);
                   1248:                error = nilfs_do_symlink(nilfs_node, ap->a_target);
                   1249:                if (error) {
                   1250:                        /* remove node */
                   1251:                        nilfs_shrink_node(nilfs_node, 0);
                   1252:                        nilfs_dir_detach(nilfs_node->ump, dir_node, nilfs_node, cnp);
                   1253:                }
                   1254:        }
                   1255:        vput(dvp);
                   1256:        return error;
                   1257: }
                   1258:
                   1259: /* --------------------------------------------------------------------- */
                   1260:
                   1261: int
                   1262: nilfs_readlink(void *v)
                   1263: {
                   1264:        struct vop_readlink_args /* {
                   1265:                struct vnode *a_vp;
                   1266:                struct uio *a_uio;
                   1267:                kauth_cred_t a_cred;
                   1268:        } */ *ap = v;
                   1269: #if 0
                   1270:        struct vnode *vp = ap->a_vp;
                   1271:        struct uio *uio = ap->a_uio;
                   1272:        kauth_cred_t cred = ap->a_cred;
                   1273:        struct nilfs_node *nilfs_node;
                   1274:        struct pathcomp pathcomp;
                   1275:        struct vattr vattr;
                   1276:        uint8_t *pathbuf, *targetbuf, *tmpname;
                   1277:        uint8_t *pathpos, *targetpos;
                   1278:        char *mntonname;
                   1279:        int pathlen, targetlen, namelen, mntonnamelen, len, l_ci;
                   1280:        int first, error;
                   1281: #endif
                   1282:        ap = ap;
                   1283:
                   1284:        DPRINTF(VFSCALL, ("nilfs_readlink called\n"));
                   1285:
                   1286:        return EROFS;
                   1287: }
                   1288:
                   1289: /* --------------------------------------------------------------------- */
                   1290:
                   1291: /* note: i tried to follow the logics of the tmpfs rename code */
                   1292: int
                   1293: nilfs_rename(void *v)
                   1294: {
                   1295:        struct vop_rename_args /* {
                   1296:                struct vnode *a_fdvp;
                   1297:                struct vnode *a_fvp;
                   1298:                struct componentname *a_fcnp;
                   1299:                struct vnode *a_tdvp;
                   1300:                struct vnode *a_tvp;
                   1301:                struct componentname *a_tcnp;
                   1302:        } */ *ap = v;
                   1303:        struct vnode *tvp = ap->a_tvp;
                   1304:        struct vnode *tdvp = ap->a_tdvp;
                   1305:        struct vnode *fvp = ap->a_fvp;
                   1306:        struct vnode *fdvp = ap->a_fdvp;
                   1307:        struct componentname *tcnp = ap->a_tcnp;
                   1308:        struct componentname *fcnp = ap->a_fcnp;
                   1309:        struct nilfs_node *fnode, *fdnode, *tnode, *tdnode;
                   1310:        struct vattr fvap, tvap;
                   1311:        int error;
                   1312:
                   1313:        DPRINTF(VFSCALL, ("nilfs_rename called\n"));
                   1314:
                   1315:        /* disallow cross-device renames */
                   1316:        if (fvp->v_mount != tdvp->v_mount ||
                   1317:            (tvp != NULL && fvp->v_mount != tvp->v_mount)) {
                   1318:                error = EXDEV;
                   1319:                goto out_unlocked;
                   1320:        }
                   1321:
                   1322:        fnode  = VTOI(fvp);
                   1323:        fdnode = VTOI(fdvp);
                   1324:        tnode  = (tvp == NULL) ? NULL : VTOI(tvp);
                   1325:        tdnode = VTOI(tdvp);
                   1326:
                   1327:        /* lock our source dir */
                   1328:        if (fdnode != tdnode) {
                   1329:                error = vn_lock(fdvp, LK_EXCLUSIVE | LK_RETRY);
                   1330:                if (error != 0)
                   1331:                        goto out_unlocked;
                   1332:        }
                   1333:
                   1334:        /* get info about the node to be moved */
1.15      hannken  1335:        vn_lock(fvp, LK_SHARED | LK_RETRY);
1.1       reinoud  1336:        error = VOP_GETATTR(fvp, &fvap, FSCRED);
1.15      hannken  1337:        VOP_UNLOCK(fvp);
1.1       reinoud  1338:        KASSERT(error == 0);
                   1339:
                   1340:        /* check when to delete the old already existing entry */
                   1341:        if (tvp) {
                   1342:                /* get info about the node to be moved to */
1.15      hannken  1343:                error = VOP_GETATTR(tvp, &tvap, FSCRED);
1.1       reinoud  1344:                KASSERT(error == 0);
                   1345:
                   1346:                /* if both dirs, make sure the destination is empty */
                   1347:                if (fvp->v_type == VDIR && tvp->v_type == VDIR) {
                   1348:                        if (tvap.va_nlink > 2) {
                   1349:                                error = ENOTEMPTY;
                   1350:                                goto out;
                   1351:                        }
                   1352:                }
                   1353:                /* if moving dir, make sure destination is dir too */
                   1354:                if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
                   1355:                        error = ENOTDIR;
                   1356:                        goto out;
                   1357:                }
                   1358:                /* if we're moving a non-directory, make sure dest is no dir */
                   1359:                if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
                   1360:                        error = EISDIR;
                   1361:                        goto out;
                   1362:                }
                   1363:        }
                   1364:
                   1365:        /* dont allow renaming directories acros directory for now */
                   1366:        if (fdnode != tdnode) {
                   1367:                if (fvp->v_type == VDIR) {
                   1368:                        error = EINVAL;
                   1369:                        goto out;
                   1370:                }
                   1371:        }
                   1372:
                   1373:        /* remove existing entry if present */
                   1374:        if (tvp)
                   1375:                nilfs_dir_detach(tdnode->ump, tdnode, tnode, tcnp);
                   1376:
                   1377:        /* create new directory entry for the node */
                   1378:        error = nilfs_dir_attach(tdnode->ump, tdnode, fnode, &fvap, tcnp);
                   1379:        if (error)
                   1380:                goto out;
                   1381:
                   1382:        /* unlink old directory entry for the node, if failing, unattach new */
                   1383:        error = nilfs_dir_detach(tdnode->ump, fdnode, fnode, fcnp);
                   1384:        if (error)
                   1385:                nilfs_dir_detach(tdnode->ump, tdnode, fnode, tcnp);
                   1386:
                   1387: out:
                   1388:         if (fdnode != tdnode)
1.7       hannken  1389:                 VOP_UNLOCK(fdvp);
1.1       reinoud  1390:
                   1391: out_unlocked:
                   1392:        VOP_ABORTOP(tdvp, tcnp);
                   1393:        if (tdvp == tvp)
                   1394:                vrele(tdvp);
                   1395:        else
                   1396:                vput(tdvp);
                   1397:        if (tvp)
                   1398:                vput(tvp);
                   1399:        VOP_ABORTOP(fdvp, fcnp);
                   1400:
                   1401:        /* release source nodes. */
                   1402:        vrele(fdvp);
                   1403:        vrele(fvp);
                   1404:
                   1405:        return error;
                   1406: }
                   1407:
                   1408: /* --------------------------------------------------------------------- */
                   1409:
                   1410: int
                   1411: nilfs_remove(void *v)
                   1412: {
                   1413:        struct vop_remove_args /* {
                   1414:                struct vnode *a_dvp;
                   1415:                struct vnode *a_vp;
                   1416:                struct componentname *a_cnp;
                   1417:        } */ *ap = v;
                   1418:        struct vnode *dvp = ap->a_dvp;
                   1419:        struct vnode *vp  = ap->a_vp;
                   1420:        struct componentname *cnp = ap->a_cnp;
1.3       mbalmer  1421:        struct nilfs_node *dir_node = VTOI(dvp);
1.1       reinoud  1422:        struct nilfs_node *nilfs_node = VTOI(vp);
                   1423:        struct nilfs_mount *ump = dir_node->ump;
                   1424:        int error;
                   1425:
                   1426:        DPRINTF(VFSCALL, ("nilfs_remove called\n"));
                   1427:        if (vp->v_type != VDIR) {
                   1428:                error = nilfs_dir_detach(ump, dir_node, nilfs_node, cnp);
                   1429:                DPRINTFIF(NODE, error, ("\tgot error removing file\n"));
                   1430:        } else {
                   1431:                DPRINTF(NODE, ("\tis a directory: perm. denied\n"));
                   1432:                error = EPERM;
                   1433:        }
                   1434:
                   1435:        if (error == 0) {
                   1436:                VN_KNOTE(vp, NOTE_DELETE);
                   1437:                VN_KNOTE(dvp, NOTE_WRITE);
                   1438:        }
                   1439:
                   1440:        if (dvp == vp)
                   1441:                vrele(vp);
                   1442:        else
                   1443:                vput(vp);
                   1444:        vput(dvp);
                   1445:
                   1446:        return error;
                   1447: }
                   1448:
                   1449: /* --------------------------------------------------------------------- */
                   1450:
                   1451: int
                   1452: nilfs_rmdir(void *v)
                   1453: {
                   1454:        struct vop_rmdir_args /* {
                   1455:                struct vnode *a_dvp;
                   1456:                struct vnode *a_vp;
                   1457:                struct componentname *a_cnp;
                   1458:        } */ *ap = v;
                   1459:        struct vnode *vp = ap->a_vp;
                   1460:        struct vnode *dvp = ap->a_dvp;
                   1461:        struct componentname *cnp = ap->a_cnp;
1.3       mbalmer  1462:        struct nilfs_node *dir_node = VTOI(dvp);
1.1       reinoud  1463:        struct nilfs_node *nilfs_node = VTOI(vp);
                   1464:        struct nilfs_mount *ump = dir_node->ump;
                   1465:        int refcnt, error;
                   1466:
                   1467:        DPRINTF(NOTIMPL, ("nilfs_rmdir called\n"));
                   1468:
                   1469:        /* don't allow '.' to be deleted */
                   1470:        if (dir_node == nilfs_node) {
                   1471:                vrele(dvp);
                   1472:                vput(vp);
                   1473:                return EINVAL;
                   1474:        }
                   1475:
                   1476:        /* check to see if the directory is empty */
                   1477:        error = 0;
                   1478:        refcnt = 2; /* XXX */
                   1479:        if (refcnt > 1) {
                   1480:                /* NOT empty */
                   1481:                vput(dvp);
                   1482:                vput(vp);
                   1483:                return ENOTEMPTY;
                   1484:        }
                   1485:
                   1486:        /* detach the node from the directory */
                   1487:        error = nilfs_dir_detach(ump, dir_node, nilfs_node, cnp);
                   1488:        if (error == 0) {
                   1489:                cache_purge(vp);
                   1490: //             cache_purge(dvp);       /* XXX from msdosfs, why? */
                   1491:                VN_KNOTE(vp, NOTE_DELETE);
                   1492:        }
                   1493:        DPRINTFIF(NODE, error, ("\tgot error removing file\n"));
                   1494:
                   1495:        /* unput the nodes and exit */
                   1496:        vput(dvp);
                   1497:        vput(vp);
                   1498:
                   1499:        return error;
                   1500: }
                   1501:
                   1502: /* --------------------------------------------------------------------- */
                   1503:
                   1504: int
                   1505: nilfs_fsync(void *v)
                   1506: {
                   1507:        struct vop_fsync_args /* {
                   1508:                struct vnode *a_vp;
                   1509:                kauth_cred_t a_cred;
                   1510:                int a_flags;
                   1511:                off_t offlo;
                   1512:                off_t offhi;
                   1513:                struct proc *a_p;
                   1514:        } */ *ap = v;
                   1515:        struct vnode *vp = ap->a_vp;
                   1516: //     struct nilfs_node *nilfs_node = VTOI(vp);
                   1517: //     int error, flags, wait;
                   1518:
                   1519:        DPRINTF(STRATEGY, ("nilfs_fsync called : %s, %s\n",
                   1520:                (ap->a_flags & FSYNC_WAIT)     ? "wait":"no wait",
                   1521:                (ap->a_flags & FSYNC_DATAONLY) ? "data_only":"complete"));
                   1522:
                   1523:        vp = vp;
                   1524:        return 0;
                   1525: }
                   1526:
                   1527: /* --------------------------------------------------------------------- */
                   1528:
                   1529: int
                   1530: nilfs_advlock(void *v)
                   1531: {
                   1532:        struct vop_advlock_args /* {
                   1533:                struct vnode *a_vp;
                   1534:                void *a_id;
                   1535:                int a_op;
                   1536:                struct flock *a_fl;
                   1537:                int a_flags;
                   1538:        } */ *ap = v;
                   1539:        struct vnode *vp = ap->a_vp;
                   1540:        struct nilfs_node *nilfs_node = VTOI(vp);
                   1541:        uint64_t file_size;
                   1542:
                   1543:        DPRINTF(LOCKING, ("nilfs_advlock called\n"));
                   1544:
                   1545:        assert(nilfs_node);
                   1546:        file_size = nilfs_rw64(nilfs_node->inode.i_size);
                   1547:
                   1548:        return lf_advlock(ap, &nilfs_node->lockf, file_size);
                   1549: }
                   1550:
                   1551: /* --------------------------------------------------------------------- */
                   1552:
                   1553:
                   1554: /* Global vfs vnode data structures for nilfss */
                   1555: int (**nilfs_vnodeop_p) __P((void *));
                   1556:
                   1557: const struct vnodeopv_entry_desc nilfs_vnodeop_entries[] = {
                   1558:        { &vop_default_desc, vn_default_error },
                   1559:        { &vop_lookup_desc, nilfs_lookup },     /* lookup */
                   1560:        { &vop_create_desc, nilfs_create },     /* create */
                   1561:        { &vop_mknod_desc, nilfs_mknod },       /* mknod */     /* TODO */
                   1562:        { &vop_open_desc, nilfs_open },         /* open */
                   1563:        { &vop_close_desc, nilfs_close },       /* close */
                   1564:        { &vop_access_desc, nilfs_access },     /* access */
                   1565:        { &vop_getattr_desc, nilfs_getattr },   /* getattr */
                   1566:        { &vop_setattr_desc, nilfs_setattr },   /* setattr */   /* TODO chflags */
                   1567:        { &vop_read_desc, nilfs_read },         /* read */
                   1568:        { &vop_write_desc, nilfs_write },       /* write */     /* WRITE */
                   1569:        { &vop_fcntl_desc, genfs_fcntl },       /* fcntl */     /* TODO? */
                   1570:        { &vop_ioctl_desc, genfs_enoioctl },    /* ioctl */     /* TODO? */
                   1571:        { &vop_poll_desc, genfs_poll },         /* poll */      /* TODO/OK? */
                   1572:        { &vop_kqfilter_desc, genfs_kqfilter }, /* kqfilter */  /* ? */
                   1573:        { &vop_revoke_desc, genfs_revoke },     /* revoke */    /* TODO? */
                   1574:        { &vop_mmap_desc, genfs_mmap },         /* mmap */      /* OK? */
                   1575:        { &vop_fsync_desc, nilfs_fsync },       /* fsync */
                   1576:        { &vop_seek_desc, genfs_seek },         /* seek */
                   1577:        { &vop_remove_desc, nilfs_remove },     /* remove */
                   1578:        { &vop_link_desc, nilfs_link },         /* link */      /* TODO */
                   1579:        { &vop_rename_desc, nilfs_rename },     /* rename */    /* TODO */
                   1580:        { &vop_mkdir_desc, nilfs_mkdir },       /* mkdir */
                   1581:        { &vop_rmdir_desc, nilfs_rmdir },       /* rmdir */
                   1582:        { &vop_symlink_desc, nilfs_symlink },   /* symlink */   /* TODO */
                   1583:        { &vop_readdir_desc, nilfs_readdir },   /* readdir */
                   1584:        { &vop_readlink_desc, nilfs_readlink }, /* readlink */  /* TEST ME */
                   1585:        { &vop_abortop_desc, genfs_abortop },   /* abortop */   /* TODO/OK? */
                   1586:        { &vop_inactive_desc, nilfs_inactive }, /* inactive */
                   1587:        { &vop_reclaim_desc, nilfs_reclaim },   /* reclaim */
                   1588:        { &vop_lock_desc, genfs_lock },         /* lock */
                   1589:        { &vop_unlock_desc, genfs_unlock },     /* unlock */
                   1590:        { &vop_bmap_desc, nilfs_trivial_bmap }, /* bmap */      /* 1:1 bmap */
                   1591:        { &vop_strategy_desc, nilfs_vfsstrategy },/* strategy */
                   1592: /*     { &vop_print_desc, nilfs_print },       */      /* print */
                   1593:        { &vop_islocked_desc, genfs_islocked }, /* islocked */
                   1594:        { &vop_pathconf_desc, nilfs_pathconf }, /* pathconf */
                   1595:        { &vop_advlock_desc, nilfs_advlock },   /* advlock */   /* TEST ME */
                   1596:        { &vop_bwrite_desc, vn_bwrite },        /* bwrite */    /* ->strategy */
                   1597:        { &vop_getpages_desc, genfs_getpages }, /* getpages */
                   1598:        { &vop_putpages_desc, genfs_putpages }, /* putpages */
                   1599:        { NULL, NULL }
                   1600: };
                   1601:
                   1602:
                   1603: const struct vnodeopv_desc nilfs_vnodeop_opv_desc = {
                   1604:        &nilfs_vnodeop_p, nilfs_vnodeop_entries
                   1605: };
                   1606:

CVSweb <webmaster@jp.NetBSD.org>