[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.37.10.2

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

CVSweb <webmaster@jp.NetBSD.org>