Module Name: src Committed By: hannken Date: Wed Oct 15 09:03:53 UTC 2014
Modified Files: src/sys/fs/nilfs: nilfs_subr.c nilfs_subr.h nilfs_vfsops.c nilfs_vnops.c Log Message: Prepare nilfs for vcache: - Calling getnewvnode() with "mp == NULL" is wrong. Stop attaching a vnode to system file nodes and change nilfs_bread() to translate the block address and then uyse the device for the read. - Move the vnode initialisation to nilfs_get_node() and use nilfs_get_node_raw() to initialise the nilfs node only. - Same for nilfs_reclaim() versus nilfs_dispose_node(). - Change nilfs_get_node() to return an unlocked vnode instead of a nilfs node with locked vnode. Adapt nilfs_lookup() and nilfs_root(). - Don't treat unsupported node types (blk, chr ...) as regular, return ENXIO instead. - Fix nilfs_getattr() to mask the mode with ALLPERMS. - Destroy sync_cv before free. To generate a diff of this commit: cvs rdiff -u -r1.10 -r1.11 src/sys/fs/nilfs/nilfs_subr.c cvs rdiff -u -r1.1 -r1.2 src/sys/fs/nilfs/nilfs_subr.h cvs rdiff -u -r1.16 -r1.17 src/sys/fs/nilfs/nilfs_vfsops.c cvs rdiff -u -r1.28 -r1.29 src/sys/fs/nilfs/nilfs_vnops.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/fs/nilfs/nilfs_subr.c diff -u src/sys/fs/nilfs/nilfs_subr.c:1.10 src/sys/fs/nilfs/nilfs_subr.c:1.11 --- src/sys/fs/nilfs/nilfs_subr.c:1.10 Fri Oct 18 19:57:28 2013 +++ src/sys/fs/nilfs/nilfs_subr.c Wed Oct 15 09:03:53 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: nilfs_subr.c,v 1.10 2013/10/18 19:57:28 christos Exp $ */ +/* $NetBSD: nilfs_subr.c,v 1.11 2014/10/15 09:03:53 hannken Exp $ */ /* * Copyright (c) 2008, 2009 Reinoud Zandijk @@ -28,7 +28,7 @@ #include <sys/cdefs.h> #ifndef lint -__KERNEL_RCSID(0, "$NetBSD: nilfs_subr.c,v 1.10 2013/10/18 19:57:28 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: nilfs_subr.c,v 1.11 2014/10/15 09:03:53 hannken Exp $"); #endif /* not lint */ #include <sys/param.h> @@ -149,12 +149,22 @@ int nilfs_bread(struct nilfs_node *node, uint64_t blocknr, struct kauth_cred *cred, int flags, struct buf **bpp) { - uint64_t vblocknr; + struct nilfs_device *nilfsdev = node->nilfsdev; + uint64_t vblocknr, pblockno; int error; error = nilfs_btree_lookup(node, blocknr, &vblocknr); if (error) return error; + + /* Read special files through devvp as they have no vnode attached. */ + if (node->ino < NILFS_USER_INO && node->ino != NILFS_ROOT_INO) { + error = nilfs_nvtop(node, 1, &vblocknr, &pblockno); + if (error) + return error; + return nilfs_dev_bread(nilfsdev, pblockno, cred, flags, bpp); + } + return bread(node->vnode, vblocknr, node->nilfsdev->blocksize, cred, flags, bpp); } @@ -746,7 +756,7 @@ nilfs_register_node(struct nilfs_node *n } -static void +void nilfs_deregister_node(struct nilfs_node *node) { struct nilfs_mount *ump; @@ -799,67 +809,25 @@ nilfs_get_node_raw(struct nilfs_device * uint64_t ino, struct nilfs_inode *inode, struct nilfs_node **nodep) { struct nilfs_node *node; - struct vnode *nvp; - struct mount *mp; - int (**vnodeops)(void *); - int error; *nodep = NULL; - vnodeops = nilfs_vnodeop_p; - - /* associate with mountpoint if present*/ - mp = ump? ump->vfs_mountp : NULL; - error = getnewvnode(VT_NILFS, mp, vnodeops, NULL, &nvp); - if (error) - return error; - - /* lock node */ - error = vn_lock(nvp, LK_EXCLUSIVE | LK_RETRY); - if (error) { - nvp->v_data = NULL; - ungetnewvnode(nvp); - return error; - } node = pool_get(&nilfs_node_pool, PR_WAITOK); memset(node, 0, sizeof(struct nilfs_node)); /* crosslink */ - node->vnode = nvp; node->ump = ump; node->nilfsdev = nilfsdev; - nvp->v_data = node; /* initiase nilfs node */ node->ino = ino; node->inode = *inode; node->lockf = NULL; - /* needed? */ + /* initialise locks */ mutex_init(&node->node_mutex, MUTEX_DEFAULT, IPL_NONE); cv_init(&node->node_lock, "nilfsnlk"); - /* initialise genfs */ - genfs_node_init(nvp, &nilfs_genfsops); - - /* check if we're fetching the root */ - if (ino == NILFS_ROOT_INO) - nvp->v_vflag |= VV_ROOT; - - /* update vnode's file type XXX is there a function for this? */ - nvp->v_type = VREG; - if (S_ISDIR(inode->i_mode)) - nvp->v_type = VDIR; - if (S_ISLNK(inode->i_mode)) - nvp->v_type = VLNK; -#if 0 - if (S_ISCHR(inode->i_mode)) - nvp->v_type = VCHR; - if (S_ISBLK(inode->i_mode)) - nvp->v_type = VBLK; -#endif - /* XXX what else? */ - /* fixup inode size for system nodes */ if ((ino < NILFS_USER_INO) && (ino != NILFS_ROOT_INO)) { DPRINTF(VOLUMES, ("NEED TO GET my size for inode %"PRIu64"\n", @@ -868,39 +836,41 @@ nilfs_get_node_raw(struct nilfs_device * inode->i_size = nilfs_rw64(((uint64_t) -2)); } - uvm_vnp_setsize(nvp, nilfs_rw64(inode->i_size)); - - if (ump) - nilfs_register_node(node); - /* return node */ *nodep = node; return 0; } - int -nilfs_get_node(struct nilfs_mount *ump, uint64_t ino, struct nilfs_node **nodep) +nilfs_get_node(struct mount *mp, uint64_t ino, struct vnode **vpp) { struct nilfs_device *nilfsdev; struct nilfs_inode inode, *entry; + struct nilfs_node *node; + struct nilfs_mount *ump = VFSTONILFS(mp); + struct vnode *nvp; struct buf *bp; uint64_t ivblocknr; uint32_t entry_in_block; int error; /* lookup node in hash table */ - *nodep = nilfs_hash_lookup(ump, ino); - if (*nodep) + node = nilfs_hash_lookup(ump, ino); + if (node) { + *vpp = node->vnode; + VOP_UNLOCK(*vpp); return 0; + } /* lock to disallow simultanious creation of same udf_node */ mutex_enter(&ump->get_node_lock); /* relookup since it could be created while waiting for the mutex */ - *nodep = nilfs_hash_lookup(ump, ino); - if (*nodep) { + node = nilfs_hash_lookup(ump, ino); + if (node) { + *vpp = node->vnode; mutex_exit(&ump->get_node_lock); + VOP_UNLOCK(*vpp); return 0; } @@ -931,17 +901,70 @@ nilfs_get_node(struct nilfs_mount *ump, brelse(bp, BC_AGE); /* get node */ - error = nilfs_get_node_raw(ump->nilfsdev, ump, ino, &inode, nodep); + error = nilfs_get_node_raw(ump->nilfsdev, ump, ino, &inode, &node); + if (error) { + mutex_exit(&ump->get_node_lock); + return error; + } + + error = getnewvnode(VT_NILFS, mp, nilfs_vnodeop_p, NULL, &nvp); + if (error) { + nilfs_dispose_node(&node); + mutex_exit(&ump->get_node_lock); + return error; + } + + /* lock node */ + error = vn_lock(nvp, LK_EXCLUSIVE | LK_RETRY); + if (error) { + ungetnewvnode(nvp); + nilfs_dispose_node(&node); + mutex_exit(&ump->get_node_lock); + return error; + } + + nvp->v_type = IFTOVT(inode.i_mode); + switch (nvp->v_type) { + case VREG: + case VDIR: + case VLNK: + break; + /* other types not yet supported. */ + default: + nvp->v_type = VNON; + VOP_UNLOCK(nvp); + ungetnewvnode(nvp); + nilfs_dispose_node(&node); + mutex_exit(&ump->get_node_lock); + return ENXIO; + } + + node->vnode = nvp; + nvp->v_data = node; + + /* initialise genfs */ + genfs_node_init(nvp, &nilfs_genfsops); + + /* check if we're fetching the root */ + if (ino == NILFS_ROOT_INO) + nvp->v_vflag |= VV_ROOT; + + uvm_vnp_setsize(nvp, nilfs_rw64(inode.i_size)); + + nilfs_register_node(node); + mutex_exit(&ump->get_node_lock); - return error; + *vpp = nvp; + VOP_UNLOCK(*vpp); + + return 0; } void nilfs_dispose_node(struct nilfs_node **nodep) { - struct vnode *vp; struct nilfs_node *node; /* protect against rogue values */ @@ -949,23 +972,14 @@ nilfs_dispose_node(struct nilfs_node **n return; node = *nodep; - vp = node->vnode; /* remove dirhash if present */ dirhash_purge(&node->dir_hash); - /* remove from our hash lookup table */ - if (node->ump) - nilfs_deregister_node(node); - /* destroy our locks */ mutex_destroy(&node->node_mutex); cv_destroy(&node->node_lock); - /* dissociate from our vnode */ - genfs_node_destroy(node->vnode); - vp->v_data = NULL; - /* free our associated memory */ pool_put(&nilfs_node_pool, node); Index: src/sys/fs/nilfs/nilfs_subr.h diff -u src/sys/fs/nilfs/nilfs_subr.h:1.1 src/sys/fs/nilfs/nilfs_subr.h:1.2 --- src/sys/fs/nilfs/nilfs_subr.h:1.1 Sat Jul 18 16:31:42 2009 +++ src/sys/fs/nilfs/nilfs_subr.h Wed Oct 15 09:03:53 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: nilfs_subr.h,v 1.1 2009/07/18 16:31:42 reinoud Exp $ */ +/* $NetBSD: nilfs_subr.h,v 1.2 2014/10/15 09:03:53 hannken Exp $ */ /* * Copyright (c) 2008, 2009 Reinoud Zandijk @@ -56,7 +56,8 @@ int nilfs_btree_nlookup(struct nilfs_nod int nilfs_nvtop(struct nilfs_node *node, uint64_t blks, uint64_t *l2vmap, uint64_t *v2pmap); /* node action implementators */ -int nilfs_get_node(struct nilfs_mount *ump, uint64_t ino, struct nilfs_node **nodep); +void nilfs_deregister_node(struct nilfs_node *); +int nilfs_get_node(struct mount *mp, uint64_t ino, struct vnode **vpp); int nilfs_get_node_raw(struct nilfs_device *nilfsdev, struct nilfs_mount *ump, uint64_t ino, struct nilfs_inode *inode, struct nilfs_node **nodep); void nilfs_dispose_node(struct nilfs_node **node); Index: src/sys/fs/nilfs/nilfs_vfsops.c diff -u src/sys/fs/nilfs/nilfs_vfsops.c:1.16 src/sys/fs/nilfs/nilfs_vfsops.c:1.17 --- src/sys/fs/nilfs/nilfs_vfsops.c:1.16 Wed Apr 16 18:55:18 2014 +++ src/sys/fs/nilfs/nilfs_vfsops.c Wed Oct 15 09:03:53 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: nilfs_vfsops.c,v 1.16 2014/04/16 18:55:18 maxv Exp $ */ +/* $NetBSD: nilfs_vfsops.c,v 1.17 2014/10/15 09:03:53 hannken Exp $ */ /* * Copyright (c) 2008, 2009 Reinoud Zandijk @@ -28,7 +28,7 @@ #include <sys/cdefs.h> #ifndef lint -__KERNEL_RCSID(0, "$NetBSD: nilfs_vfsops.c,v 1.16 2014/04/16 18:55:18 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: nilfs_vfsops.c,v 1.17 2014/10/15 09:03:53 hannken Exp $"); #endif /* not lint */ @@ -70,18 +70,6 @@ MODULE(MODULE_CLASS_VFS, nilfs, NULL); #define VTOI(vnode) ((struct nilfs_node *) vnode->v_data) -#define NILFS_SET_SYSTEMFILE(vp) { \ - /* XXXAD Is the vnode locked? */ \ - (vp)->v_vflag |= VV_SYSTEM; \ - vref(vp); \ - vput(vp); } - -#define NILFS_UNSET_SYSTEMFILE(vp) { \ - /* XXXAD Is the vnode locked? */ \ - (vp)->v_vflag &= ~VV_SYSTEM; \ - vrele(vp); } - - /* verbose levels of the nilfs filingsystem */ int nilfs_verbose = NILFS_DEBUGGING; @@ -257,10 +245,6 @@ nilfs_create_system_nodes(struct nilfs_d if (error) goto errorout; - NILFS_SET_SYSTEMFILE(nilfsdev->dat_node->vnode); - NILFS_SET_SYSTEMFILE(nilfsdev->cp_node->vnode); - NILFS_SET_SYSTEMFILE(nilfsdev->su_node->vnode); - return 0; errorout: nilfs_dispose_node(&nilfsdev->dat_node); @@ -279,13 +263,6 @@ nilfs_release_system_nodes(struct nilfs_ if (nilfsdev->refcnt > 0) return; - if (nilfsdev->dat_node) - NILFS_UNSET_SYSTEMFILE(nilfsdev->dat_node->vnode); - if (nilfsdev->cp_node) - NILFS_UNSET_SYSTEMFILE(nilfsdev->cp_node->vnode); - if (nilfsdev->su_node) - NILFS_UNSET_SYSTEMFILE(nilfsdev->su_node->vnode); - nilfs_dispose_node(&nilfsdev->dat_node); nilfs_dispose_node(&nilfsdev->cp_node); nilfs_dispose_node(&nilfsdev->su_node); @@ -513,6 +490,7 @@ nilfs_unmount_device(struct nilfs_device vput(nilfsdev->devvp); /* free our device info */ + cv_destroy(&nilfsdev->sync_cv); free(nilfsdev, M_NILFSMNT); } @@ -745,7 +723,6 @@ nilfs_mount_checkpoint(struct nilfs_moun printf("mount_nilfs: can't read ifile node\n"); return EINVAL; } - NILFS_SET_SYSTEMFILE(ump->ifile_node->vnode); /* get root node? */ @@ -951,13 +928,10 @@ nilfs_unmount(struct mount *mp, int mntf nilfsdev = ump->nilfsdev; /* - * Flush all nodes associated to this mountpoint. By specifying - * SKIPSYSTEM we can skip vnodes marked with VV_SYSTEM. This hardly - * documented feature allows us to exempt certain files from being - * flushed. + * Flush all nodes associated to this mountpoint. */ flags = (mntflags & MNT_FORCE) ? FORCECLOSE : 0; - if ((error = vflush(mp, NULLVP, flags | SKIPSYSTEM)) != 0) + if ((error = vflush(mp, NULLVP, flags)) != 0) return error; /* if we're the write mount, we ought to close the writing session */ @@ -965,8 +939,6 @@ nilfs_unmount(struct mount *mp, int mntf if (error) return error; - if (ump->ifile_node) - NILFS_UNSET_SYSTEMFILE(ump->ifile_node->vnode); nilfs_dispose_node(&ump->ifile_node); /* remove our mount point */ @@ -998,17 +970,20 @@ nilfs_start(struct mount *mp, int flags) int nilfs_root(struct mount *mp, struct vnode **vpp) { - struct nilfs_mount *ump = VFSTONILFS(mp); - struct nilfs_node *node; int error; DPRINTF(NODE, ("nilfs_root called\n")); - error = nilfs_get_node(ump, NILFS_ROOT_INO, &node); - if (node) { - *vpp = node->vnode; - KASSERT(node->vnode->v_vflag & VV_ROOT); + error = nilfs_get_node(mp, NILFS_ROOT_INO, vpp); + if (error == 0) { + error = vn_lock(*vpp, LK_EXCLUSIVE); + if (error) { + vrele(*vpp); + *vpp = NULL; + return error; + } } + KASSERT(error != 0 || ((*vpp)->v_vflag & VV_ROOT)); DPRINTF(NODE, ("nilfs_root finished\n")); return error; Index: src/sys/fs/nilfs/nilfs_vnops.c diff -u src/sys/fs/nilfs/nilfs_vnops.c:1.28 src/sys/fs/nilfs/nilfs_vnops.c:1.29 --- src/sys/fs/nilfs/nilfs_vnops.c:1.28 Fri Jul 25 08:20:51 2014 +++ src/sys/fs/nilfs/nilfs_vnops.c Wed Oct 15 09:03:53 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: nilfs_vnops.c,v 1.28 2014/07/25 08:20:51 dholland Exp $ */ +/* $NetBSD: nilfs_vnops.c,v 1.29 2014/10/15 09:03:53 hannken Exp $ */ /* * Copyright (c) 2008, 2009 Reinoud Zandijk @@ -28,7 +28,7 @@ #include <sys/cdefs.h> #ifndef lint -__KERNEL_RCSID(0, "$NetBSD: nilfs_vnops.c,v 1.28 2014/07/25 08:20:51 dholland Exp $"); +__KERNEL_RCSID(0, "$NetBSD: nilfs_vnops.c,v 1.29 2014/10/15 09:03:53 hannken Exp $"); #endif /* not lint */ @@ -118,9 +118,15 @@ nilfs_reclaim(void *v) /* update note for closure */ nilfs_update(vp, NULL, NULL, NULL, UPDATE_CLOSE); + /* remove from our hash lookup table */ + nilfs_deregister_node(nilfs_node); + /* dispose all node knowledge */ + genfs_node_destroy(vp); nilfs_dispose_node(&nilfs_node); + vp->v_data = NULL; + return 0; } @@ -621,16 +627,13 @@ nilfs_lookup(void *v) struct vnode *dvp = ap->a_dvp; struct vnode **vpp = ap->a_vpp; struct componentname *cnp = ap->a_cnp; - struct nilfs_node *dir_node, *res_node; - struct nilfs_mount *ump; + struct mount *mp = dvp->v_mount; uint64_t ino; const char *name; int namelen, nameiop, islastcn, mounted_ro; int vnodetp; int error, found; - dir_node = VTOI(dvp); - ump = dir_node->ump; *vpp = NULL; DPRINTF(LOOKUP, ("nilfs_lookup called\n")); @@ -638,7 +641,7 @@ nilfs_lookup(void *v) /* simplify/clarification flags */ nameiop = cnp->cn_nameiop; islastcn = cnp->cn_flags & ISLASTCN; - mounted_ro = dvp->v_mount->mnt_flag & MNT_RDONLY; + mounted_ro = mp->mnt_flag & MNT_RDONLY; /* check exec/dirread permissions first */ error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred); @@ -691,23 +694,16 @@ nilfs_lookup(void *v) if (!found) error = ENOENT; - /* first unlock parent */ - VOP_UNLOCK(dvp); - if (error == 0) { DPRINTF(LOOKUP, ("\tfound '..'\n")); /* try to create/reuse the node */ - error = nilfs_get_node(ump, ino, &res_node); + error = nilfs_get_node(mp, ino, vpp); if (!error) { DPRINTF(LOOKUP, ("\tnode retrieved/created OK\n")); - *vpp = res_node->vnode; } } - - /* try to relock parent */ - vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY); } else { DPRINTF(LOOKUP, ("\tlookup file\n")); /* all other files */ @@ -738,7 +734,7 @@ nilfs_lookup(void *v) /* done */ } else { /* try to create/reuse the node */ - error = nilfs_get_node(ump, ino, &res_node); + error = nilfs_get_node(mp, ino, vpp); if (!error) { /* * If we are not at the last path component @@ -746,16 +742,16 @@ nilfs_lookup(void *v) * (which may itself be pointing to a * directory), raise an error. */ - vnodetp = res_node->vnode->v_type; + vnodetp = (*vpp)->v_type; if ((vnodetp != VDIR) && (vnodetp != VLNK)) { - if (!islastcn) + if (!islastcn) { + vrele(*vpp); + *vpp = NULL; error = ENOTDIR; + } } } - if (!error) { - *vpp = res_node->vnode; - } } } @@ -765,7 +761,7 @@ out: * the file might not be found and thus putting it into the namecache * might be seen as negative caching. */ - if (nameiop != CREATE) + if (error == 0 && nameiop != CREATE) cache_enter(dvp, *vpp, cnp->cn_nameptr, cnp->cn_namelen, cnp->cn_flags); @@ -773,8 +769,6 @@ out: if (error) return error; - if (*vpp != dvp) - VOP_UNLOCK(*vpp); return 0; } @@ -807,7 +801,7 @@ nilfs_getattr(void *v) /* basic info */ vattr_null(vap); vap->va_type = vp->v_type; - vap->va_mode = nilfs_rw16(inode->i_mode); /* XXX same? */ + vap->va_mode = nilfs_rw16(inode->i_mode) & ALLPERMS; vap->va_nlink = nilfs_rw16(inode->i_links_count); vap->va_uid = nilfs_rw32(inode->i_uid); vap->va_gid = nilfs_rw32(inode->i_gid);