Date: Mon, 13 Jun 2011 15:33:42 GMT From: Ilya Putsikau <ilya@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 194682 for review Message-ID: <201106131533.p5DFXgkM074432@skunkworks.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@194682?ac=10 Change 194682 by ilya@ilya_triton2011 on 2011/06/13 15:33:26 Restore vfs_hash and original node creations on FreeBSD Affected files ... .. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_node.c#2 edit .. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_node.h#4 edit Differences ... ==== //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_node.c#2 (text+ko) ==== @@ -3,173 +3,165 @@ * Amit Singh <singh@> */ +#include "config.h" + +#include <sys/types.h> +#include <sys/module.h> +#include <sys/systm.h> +#include <sys/errno.h> +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/conf.h> +#include <sys/uio.h> +#include <sys/malloc.h> +#include <sys/queue.h> +#include <sys/lock.h> +#include <sys/sx.h> +#include <sys/mutex.h> +#include <sys/proc.h> +#include <sys/vnode.h> +#include <sys/namei.h> +#include <sys/mount.h> +#include <sys/sysctl.h> +#include <sys/fcntl.h> +#include <sys/fnv_hash.h> + #include "fuse.h" +#include "fuse_node.h" +#include "fuse_internal.h" #include "fuse_ipc.h" -#include "fuse_locking.h" -#include "fuse_node.h" + +#include <sys/priv.h> +#include <security/mac/mac_framework.h> + +static void +fuse_vnode_init(struct vnode *vp, struct fuse_vnode_data *fvdat, + uint64_t nodeid, enum vtype vtyp) +{ + fvdat->nid = nodeid; + if (nodeid == FUSE_ROOT_ID) { + vp->v_vflag |= VV_ROOT; + } + vp->v_type = vtyp; + vp->v_data = fvdat; + mtx_init(&fvdat->createlock, "fuse node create mutex", NULL, MTX_DEF); + sx_init(&fvdat->nodelock, "fuse node sx lock"); + sx_init(&fvdat->truncatelock, "fuse node truncate sx lock"); +} void -FSNodeScrub(struct fuse_vnode_data *fvdat) +fuse_vnode_destroy(struct vnode *vp) { - lck_mtx_destroy(fvdat->createlock, fuse_lock_group); - lck_rw_destroy(fvdat->nodelock, fuse_lock_group); - lck_rw_destroy(fvdat->truncatelock, fuse_lock_group); - fvdat->fMagic = kFSNodeBadMagic; -} + struct fuse_vnode_data *fvdat = vp->v_data; + + vp->v_data = NULL; + mtx_destroy(&fvdat->createlock); + sx_destroy(&fvdat->nodelock); + sx_destroy(&fvdat->truncatelock); + free(fvdat, M_FUSEVN); +} -errno_t -FSNodeGetOrCreateFileVNodeByID(mount_t mp, - uint64_t nodeid, - vnode_t dvp, - enum vtype vtyp, - uint64_t insize, - vnode_t *vnPtr, - int flags) +static int +fuse_vnode_cmp(struct vnode *vp, void *nidp) { - int err; - int junk; - vnode_t vn; - HNodeRef hn; - vnode_t dirVN; - dev_t dummy_device; - struct fuse_vnode_data *fvdat = NULL; - struct fuse_data *mntdata; - int markroot = FALSE; - uint64_t size = 0; + return (VTOI(vp) != *((uint64_t *)nidp)); +} - if (insize == 0xffffffff) { - markroot = TRUE; - } else { - size = insize; - } +static uint32_t __inline +fuse_vnode_hash(uint64_t id) +{ + return (fnv_32_buf(&id, sizeof(id), FNV1_32_INIT)); +} - hn = NULL; - vn = NULL; - dirVN = NULL; +static int +fuse_vnode_alloc(struct mount *mp, + struct thread *td, + uint64_t nodeid, + enum vtype vtyp, + int lkflags, + struct vnode **vpp) +{ + struct fuse_vnode_data *fvdat; + struct vnode *vp2; + int err = 0; - mntdata = vfs_fsprivate(mp); - dummy_device = (dev_t)mntdata->fdev; + DEBUG("been asked for vno #%ju\n", (uintmax_t)nodeid); - err = HNodeLookupCreatingIfNecessary(dummy_device, - (ino_t)nodeid, // XXXXXXXX - 0 /* fork index */, - &hn, - &vn); - if ((err == 0) && (vn == NULL)) { + if (vtyp == VNON) { + return EINVAL; + } - struct vnode_fsparam params; - fvdat = (struct fuse_vnode_data *)FSNodeGenericFromHNode(hn); - if (!fvdat->fInitialised) { - int k; - fvdat->fMagic = kFSNodeMagic; - fvdat->fInitialised = TRUE; - fvdat->nid = nodeid; - fvdat->vtype = vtyp; - fvdat->parent = NULL; - fvdat->filesize = size; - fvdat->newfilesize = 0; - fvdat->nlookup = 0; - if (dvp) { - fvdat->parent_nid = VTOFUD(dvp)->nid; - } else { - fvdat->parent_nid = 0; - } - for (k = 0; k < FUFH_MAXTYPE; k++) { - fvdat->fufh[k].fufh_flags = 0; - } - fvdat->createlock = lck_mtx_alloc_init(fuse_lock_group, fuse_lock_attr); - fvdat->nodelock = lck_rw_alloc_init(fuse_lock_group, fuse_lock_attr); - fvdat->truncatelock = lck_rw_alloc_init(fuse_lock_group, fuse_lock_attr); - fvdat->creator = current_thread(); - fvdat->flag = flags; - //LIST_INIT(&fvdat->fh_head); - } + *vpp = NULL; + err = vfs_hash_get(mp, fuse_vnode_hash(nodeid), lkflags, td, vpp, + fuse_vnode_cmp, &nodeid); + if (err) + return (err); - if (err == 0) { - params.vnfs_mp = mp; - params.vnfs_vtype = vtyp; - params.vnfs_str = NULL; - params.vnfs_dvp = NULL; // dvp; XXXXXXXXXXXXXXXXXXXXXXXXXX - params.vnfs_fsnode = hn; - params.vnfs_vops = fuse_vnode_operations; - params.vnfs_marksystem = FALSE; - params.vnfs_rdev = 0; - params.vnfs_cnp = NULL; - params.vnfs_flags = VNFS_NOCACHE | VNFS_CANTCACHE; - params.vnfs_filesize = size; - params.vnfs_markroot = markroot; + if (*vpp) { + MPASS((*vpp)->v_type == vtyp && (*vpp)->v_data != NULL); + DEBUG("vnode taken from hash\n"); + return (0); + } - err = vnode_create(VNCREATE_FLAVOR, sizeof(params), ¶ms, &vn); - } + lkflags = LK_EXCLUSIVE | LK_RETRY; /* XXXIP don't loose other flags */ - if (err == 0) { - HNodeAttachVNodeSucceeded(hn, 0 /* forkIndex */, vn); - if (markroot == TRUE) { - fvdat->parent = vn; - } - } else { - if (HNodeAttachVNodeFailed(hn, 0 /* forkIndex */)) { - FSNodeScrub(fvdat); - HNodeScrubDone(hn); - } - } + fvdat = malloc(sizeof(*fvdat), M_FUSEVN, M_WAITOK | M_ZERO); + err = getnewvnode("fuse", mp, &fuse_vnops, vpp); + if (err) { + free(fvdat, M_FUSEVN); + return (err); } - if (err == 0) { - *vnPtr = vn; - vnode_settag(vn, VT_KERNFS); + vn_lock(*vpp, lkflags); + err = insmntque(*vpp, mp); + if (err) { + free(fvdat, M_FUSEVN); + return (err); } - if (dirVN != NULL) { - junk = vnode_put(dirVN); - /* assert(junk == 0); */ + fuse_vnode_init(*vpp, fvdat, nodeid, vtyp); + err = vfs_hash_insert(*vpp, fuse_vnode_hash(nodeid), lkflags, + td, &vp2, fuse_vnode_cmp, &nodeid); + + if (err) { + fuse_vnode_destroy(*vpp); + *vpp = NULL; + return (err); } - /* assert((err == 0) == (*vnPtr != NULL); */ + /* + * XXXIP: Prevent silent vnode reuse. It may happen because several fuse + * filesystems ignore inode numbers + */ + KASSERT(vp2 == NULL, + ("vfs hash collision for node #%ju\n", (uintmax_t)nodeid)); - return err; + return (0); } int -fuse_vget_i(mount_t mp, - uint64_t nodeid, - vfs_context_t context, - vnode_t dvp, - vnode_t *vpp, - struct componentname *cnp, - enum vtype vtyp, - uint64_t size, - enum vget_mode mode, - uint64_t parentid) +fuse_vnode_get(struct mount *mp, + uint64_t nodeid, + struct vnode *dvp, + struct vnode **vpp, + struct componentname *cnp, + enum vtype vtyp, + uint64_t size) { + struct thread *td = (cnp != NULL ? cnp->cn_thread : curthread); int err = 0; debug_printf("dvp=%p\n", dvp); - if (vtyp == VNON) { - return EINVAL; - } - -#if 0 //XROOT - if (nodeid == FUSE_ROOT_ID) { - *vpp = fusefs_get_data(mp)->rvp; //XROOT - err = vnode_get(*vpp); - if (err) { - *vpp = NULLVP; - return err; - } - goto found; - } -#endif - - err = FSNodeGetOrCreateFileVNodeByID(mp, nodeid, dvp, vtyp, size, vpp, 0); + err = fuse_vnode_alloc(mp, td, nodeid, vtyp, LK_EXCLUSIVE | LK_RETRY, vpp); if (err) { return err; } - cache_enter(dvp, *vpp, cnp); + if (cnp != NULL) { + cache_enter(dvp, *vpp, cnp); + } -found: VTOFUD(*vpp)->nlookup++; return 0; ==== //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_node.h#4 (text+ko) ==== @@ -10,22 +10,14 @@ #include <sys/mutex.h> #include "fuse_file.h" -#include "fuse_nodehash.h" -enum { - kFSNodeMagic = 1, - kFSNodeBadMagic = 2, - kHNodeMagic = 3, -}; - #define FN_CREATING 0x00000001 struct fuse_vnode_data { - uint32_t fMagic; - boolean_t fInitialised; uint64_t nid; uint64_t nlookup; enum vtype vtype; + /* XXXIP very likely to be stale, it's not updated in rename() */ uint64_t parent_nid; struct mtx createlock; @@ -40,16 +32,17 @@ * modified. Typically, we would take this lock at the beginning of a * vnop and drop it at the end of the vnop. */ - struct sx *nodelock; + struct sx nodelock; void *nodelockowner; /* * The truncatelock guards against the EOF changing on us (that is, a * file resize) unexpectedly. */ - struct sx *truncatelock; + struct sx truncatelock; struct vnode *c_vp; + /* XXXIP reference is very likely to be stale, it's not updated in rename() */ struct vnode *parent; off_t filesize; off_t newfilesize; @@ -59,13 +52,11 @@ struct vattr cached_attrs; struct timespec cached_attrs_valid; }; -typedef struct fuse_vnode_data * fusenode_t; -#define VTOFUD(vp) \ - ((struct fuse_vnode_data *)FSNodeGenericFromHNode((vp)->v_data)) +#define VTOFUD(vp) ((struct fuse_vnode_data *)((vp)->v_data)) #define VTOI(vp) (VTOFUD(vp)->nid) #define VTOVA(vp) (&(VTOFUD(vp)->cached_attrs)) -#define VTOILLU(vp) ((unsigned long long)(VTOFUD(vp) ? VTOI(vp) : 0)) +#define VTOILLU(vp) ((uint64_t)(VTOFUD(vp) ? VTOI(vp) : 0)) #define FUSE_NULL_ID 0 @@ -79,17 +70,6 @@ MALLOC_DECLARE(M_FUSEVN); -vfs_hash_cmp_t fuse_vnode_cmp; -vfs_hash_cmp_t fuse_vnode_setparent_cmp; - -void fuse_vnode_init(struct vnode *vp, struct fuse_vnode_data *fvdat, - uint64_t nodeid, enum vtype vtyp, uint64_t parentid); -void fuse_vnode_ditch(struct vnode *vp, struct thread *td); -void fuse_vnode_teardown(struct vnode *vp, struct thread *td, - struct ucred *cred, enum vtype vtyp); - -enum vget_mode { VG_NORMAL, VG_WANTNEW, VG_FORCENEW }; - struct get_filehandle_param { enum fuse_opcode opcode; uint8_t do_gc:1; @@ -116,37 +96,17 @@ #define C_CREATING 0x04000 #define C_ACCESS_NOOP 0x08000 -int -FSNodeGetOrCreateFileVNodeByID(struct mount *mp, - uint64_t nodeid, - struct vnode *dvp, - enum vtype vtyp, - uint64_t insize, - struct vnode **vnPtr, - int flags); +extern struct vop_vector fuse_vnops; -void FSNodeScrub(struct fuse_vnode_data *fvdat); +void fuse_vnode_destroy(struct vnode *vp); int -fuse_vget_i(struct mount *mp, - struct thread *td, - uint64_t nodeid, - enum vtype vtyp, - struct vnode **vpp, - enum vget_mode vmod, - uint64_t parentid); -#ifdef XXXIP -int -fuse_vget_i(struct mount *mp, - uint64_t nodeid, - vfs_context_t context, - struct vnode *dvp, - struct vnode *vpp, - struct componentname *cnp, - enum vtype vtyp, - uint64_t size, - enum vget_mode mode, - uint64_t parentid); -#endif +fuse_vnode_get(struct mount *mp, + uint64_t nodeid, + struct vnode *dvp, + struct vnode **vpp, + struct componentname *cnp, + enum vtype vtyp, + uint64_t size); #endif /* _FUSE_NODE_H_ */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201106131533.p5DFXgkM074432>