PERFORCE change 194687 for review
Ilya Putsikau
ilya at FreeBSD.org
Mon Jun 13 15:40:20 UTC 2011
http://p4web.freebsd.org/@@194687?ac=10
Change 194687 by ilya at ilya_triton2011 on 2011/06/13 15:39:55
Vnode operations merge.
Affected files ...
.. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_vnops.c#12 edit
Differences ...
==== //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_vnops.c#12 (text+ko) ====
@@ -74,7 +74,7 @@
static vop_print_t fuse_vnop_print;
static vop_unlock_t fuse_vnop_unlock;
-static struct vop_vector fuse_vnops = {
+struct vop_vector fuse_vnops = {
.vop_default = &default_vnodeops,
.vop_access = fuse_vnop_access,
.vop_close = fuse_vnop_close,
@@ -289,12 +289,11 @@
goto undo;
}
- err = FSNodeGetOrCreateFileVNodeByID(mp,
- feo->nodeid,
- dvp,
- VREG, /*size*/0,
- vpp,
- (gone_good_old) ? 0 : FN_CREATING);
+ err = fuse_vnode_get(mp, feo->nodeid, dvp, vpp, cnp, VREG,
+ /*size*/0);
+ if (!err && !gone_good_old) {
+ VTOFUD(*vpp)->flag |= FN_CREATING;
+ }
if (err) {
if (gone_good_old) {
fuse_internal_forget_send(mp, td, cred, feo->nodeid, 1, fdip);
@@ -416,7 +415,11 @@
return 0;
}
-#ifdef XXXVP
+#define fusetimespeccmp(tvp, uvp, cmp) \
+ (((tvp)->tv_sec == (uvp)->tv_sec) ? \
+ ((tvp)->tv_nsec cmp (uvp)->tv_nsec) : \
+ ((tvp)->tv_sec cmp (uvp)->tv_sec))
+
/*
struct vnop_getattr_args {
struct vnode *a_vp;
@@ -428,68 +431,72 @@
static int
fuse_vnop_getattr(struct vop_getattr_args *ap)
{
- struct vnode *vp = ap->a_vp;
- struct vattr *vap = ap->a_vap;
- struct ucred *cred = ap->a_cred;
- struct thread *td = curthread;
- struct fuse_dispatcher fdi;
- struct timespec uptsp;
- int err = 0;
+ int err = 0;
+ int dataflag;
+ struct vnode *vp = ap->a_vp;
+ struct vattr *vap = ap->a_vap;
+ struct ucred *cred = ap->a_cred;
+ struct thread *td = curthread;
+ struct fuse_dispatcher fdi;
+ struct timespec uptsp;
- /* look for cached attributes */
- nanouptime(&uptsp);
- if (timespeccmp(&uptsp, &VTOFUD(vp)->cached_attrs_valid, <=)) {
- DEBUG("found valid cached attrs for vp #%llu\n", VTOILLU(vp));
+ fuse_trace_printf_vnop();
- if (vap != VTOVA(vp))
- memcpy(vap, VTOVA(vp), sizeof(*vap));
+ dataflag = fusefs_get_data(vnode_mount(vp))->dataflag;
- return (0);
- }
+ /* Note that we are not bailing out on a dead file system just yet. */
- if (! (fusefs_get_data(vp->v_mount)->dataflag & FSESS_INITED)) {
- if (! (vp->v_vflag & VV_ROOT)) {
- fdata_kick_set(fusefs_get_data(vp->v_mount));
- err = ENOTCONN;
+ /* look for cached attributes */
+ nanouptime(&uptsp);
+ if (fusetimespeccmp(&uptsp, &VTOFUD(vp)->cached_attrs_valid, <=)) {
+ if (vap != VTOVA(vp)) {
+ memcpy(vap, VTOVA(vp), sizeof(*vap));
+ }
+ debug_printf("fuse_getattr a: returning 0\n");
+ return (0);
+ }
- return (err);
- } else
- goto fake;
- }
+ if (!(dataflag & FSESS_INITED)) {
+ if (!vnode_isvroot(vp)) {
+ fdata_kick_set(fusefs_get_data(vnode_mount(vp)));
+ err = ENOTCONN;
+ debug_printf("fuse_getattr b: returning ENOTCONN\n");
+ return (err);
+ } else {
+ goto fake;
+ }
+ }
- if ((err = fdisp_simple_putget(&fdi, FUSE_GETATTR, vp, td, cred))) {
- if (err == ENOTCONN && vp->v_vflag & VV_ROOT)
- /* see comment at similar place in fuse_statfs() */
- goto fake;
+ if ((err = fdisp_simple_putget_vp(&fdi, FUSE_GETATTR, vp, td, cred))) {
+ if (err == ENOTCONN && vnode_isvroot(vp)) {
+ /* see comment at similar place in fuse_statfs() */
+ goto fake;
+ }
+ debug_printf("fuse_getattr c: returning ENOTCONN\n");
+ return (err);
+ }
- return (err);
- }
+ cache_attrs(vp, (struct fuse_attr_out *)fdi.answ);
+ if (vap != VTOVA(vp)) {
+ memcpy(vap, VTOVA(vp), sizeof(*vap));
+ }
- cache_attrs(vp, (struct fuse_attr_out *)fdi.answ);
- if (vap != VTOVA(vp))
- memcpy(vap, VTOVA(vp), sizeof(*vap));
+ fuse_ticket_drop(fdi.tick);
- fuse_ticket_drop(fdi.tick);
+ if (vnode_vtype(vp) != vap->va_type) {
+ if (vnode_vtype(vp) == VNON && vap->va_type != VNON) {
+ // vp->v_type = vap->va_type;
+ } else {
+ /* stale vnode */
+ // XXX: vnode should be ditched.
+ debug_printf("fuse_getattr d: returning ENOTCONN\n");
+ return (ENOTCONN);
+ }
+ }
- if (vp->v_type != vap->va_type) {
- if (vp->v_type == VNON && vap->va_type != VNON) {
- DEBUG2G("vnode #%llu with no type\n", VTOILLU(vp));
- vp->v_type = vap->va_type;
- } else {
- /* stale vnode */
- DEBUG2G("node #%lu got stale (old type %#x, new type %#x), kicking...\n",
- vap->va_fileid, vp->v_type, vap->va_type);
- fuse_vnode_ditch(vp, td);
- return (ENOTCONN);
- }
- }
+ debug_printf("fuse_getattr e: returning 0\n");
- DEBUG("node #%llu, type %d\n", VTOILLU(vp), vap->va_type);
-#if _DEBUG
- DEBUG2G("\n");
- vn_printf(vp, " * ");
-#endif
- return (0);
+ return (0);
fake:
bzero(vap, sizeof(*vap));
@@ -497,7 +504,6 @@
return (0);
}
-#endif
/*
struct vnop_inactive_args {
@@ -584,47 +590,44 @@
struct componentname *a_cnp;
};
*/
-#ifdef XXXIP
int
fuse_vnop_lookup(struct vop_lookup_args *ap)
{
struct componentname *cnp = ap->a_cnp;
int nameiop = cnp->cn_nameiop;
int flags = cnp->cn_flags;
- int wantparent = flags & WANTPARENT;
+ int wantparent = flags & (LOCKPARENT|WANTPARENT);
int islastcn = flags & ISLASTCN;
struct vnode *dvp = ap->a_dvp;
struct vnode **vpp = ap->a_vpp;
struct thread *td = cnp->cn_thread;
struct ucred *cred = cnp->cn_cred;
+ struct mount *mp = vnode_mount(dvp);
fuse_trace_printf_vnop();
int err = 0;
int lookup_err = 0;
struct vnode *vp = NULL;
+ struct vnode *pdp = NULL;
struct fuse_attr *fattr = NULL;
struct fuse_dispatcher fdi;
enum fuse_opcode op;
- uint64_t nid, parentid;
+ uint64_t nid, parent_nid;
struct fuse_access_param facp;
-#ifdef INVARIANTS
- int cache_attrs_hit = 0;
-#endif
+ uint64_t size = 0;
- /* general stuff, based on vfs_cache_lookup */
+ if (fuse_isdeadfs(dvp)) {
+ *vpp = NULL;
+ return ENXIO;
+ }
-#if _DEBUG
- DEBUG2G("root node:\n");
- vn_printf(fusefs_get_data(dvp->v_mount)->rvp, " * ");
-#endif
-
- if (dvp->v_type != VDIR) {
+ if (vnode_vtype(dvp) != VDIR) {
return ENOTDIR;
}
- if (islastcn && (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
- (nameiop == DELETE || nameiop == RENAME)) {
+ if (islastcn && vfs_isrdonly(mp) &&
+ ((nameiop == DELETE) || (nameiop == RENAME) || (nameiop == CREATE))) {
return (EROFS);
}
@@ -636,122 +639,121 @@
*/
bzero(&facp, sizeof(facp));
- if (
-#ifdef NO_EARLY_PERM_CHECK_HACK
- 1
-#else
- dvp->v_vflag & VV_ROOT
-#endif
- ) {
- if ((err = fuse_internal_access(dvp, VEXEC, cred, td, &facp)))
- return err;
+ if (vnode_isvroot(dvp)) { /* early permission check hack */
+ if ((err = fuse_internal_access(dvp, VEXEC, cred, td, &facp))) {
+ return err;
+ }
}
- DEBUG2G("lookup in #%llu, nameiop %lu, with flags %#x\n",
- VTOILLU(dvp), cnp->cn_nameiop, flags);
-
- /* fetching data from "storage" */
-
if (flags & ISDOTDOT) {
- DEBUG2G("dotdot lookup!\n");
- nid = VTOFUD(dvp)->parent_nid;
- parentid = FUSE_NULL_ID;
+ pdp = VTOFUD(dvp)->parent;
+ nid = VTOI(pdp);
+ parent_nid = VTOFUD(dvp)->parent_nid;
fdisp_init(&fdi, 0);
op = FUSE_GETATTR;
+ goto calldaemon;
} else if (cnp->cn_namelen == 1 && *(cnp->cn_nameptr) == '.') {
- DEBUG2G("dot lookup!\n");
nid = VTOI(dvp);
- parentid = VTOFUD(dvp)->parent_nid; /* irrelevant */
+ parent_nid = VTOFUD(dvp)->parent_nid;
fdisp_init(&fdi, 0);
op = FUSE_GETATTR;
+ goto calldaemon;
} else {
- nid = VTOI(dvp);
- parentid = VTOI(dvp);
- fdisp_init(&fdi, cnp->cn_namelen + 1);
- op = FUSE_LOOKUP;
+ err = cache_lookup(dvp, vpp, cnp);
+ switch (err) {
+
+ case -1: /* positive match */
+#ifdef XXXIP
+ fuse_lookup_cache_hits++;
+#endif
+ return 0;
+
+ case 0: /* no match in cache */
+#ifdef XXXIP
+ fuse_lookup_cache_misses++;
+#endif
+ break;
+
+ case ENOENT: /* negative match */
+ /* fall through */
+ default:
+ return err;
+ }
}
- fdisp_make(&fdi, dvp->v_mount, op, nid, td, cred);
+ nid = VTOI(dvp);
+ parent_nid = VTOI(dvp);
+ fdisp_init(&fdi, cnp->cn_namelen + 1);
+ op = FUSE_LOOKUP;
+
+calldaemon:
+ fdisp_make(&fdi, vnode_mount(dvp), op, nid, td, cred);
if (op == FUSE_LOOKUP) {
memcpy(fdi.indata, cnp->cn_nameptr, cnp->cn_namelen);
((char *)fdi.indata)[cnp->cn_namelen] = '\0';
- DEBUG2G("standard lookup, looking up %s\n", (char *)fdi.indata);
}
lookup_err = fdisp_wait_answ(&fdi);
if (op == FUSE_LOOKUP && !lookup_err) {
nid = ((struct fuse_entry_out *)fdi.answ)->nodeid;
+ size = ((struct fuse_entry_out *)fdi.answ)->attr.size;
if (!nid) {
/*
* zero nodeid is the same as "not found",
* but it's also cacheable (which we keep
* keep on doing not as of writing this)
*/
- DEBUG2G("zero nid, ie ENOENT\n");
lookup_err = ENOENT;
} else if (nid == FUSE_ROOT_ID) {
- DEBUG2G("root inode found on lookup?!!\n");
lookup_err = EINVAL;
}
}
- if (lookup_err && (
- (!fdi.answ_stat) || /* this means messaging error */
- lookup_err != ENOENT || /* daemon reported other error than "legal" ENOENT */
- op != FUSE_LOOKUP /* we tolerate ENOENT only when we sent a LOOKUP */
- )) {
+ if (lookup_err &&
+ ((!fdi.answ_stat) || lookup_err != ENOENT || op != FUSE_LOOKUP)) {
/*
* There is error but not lookup related actually
* (messaging error)
*/
- DEBUG("lookup failed b/c messaging crap\n");
return (lookup_err);
}
- /* analyzing answer */
-
/*
* Now we got the answer and filtered out the crap, too, so we know that
* "found" iff lookup_err == 0
*/
if (lookup_err) {
- DEBUG("looked up thingy not found\n");
- if ((nameiop == CREATE || nameiop == RENAME)
- && islastcn
- /* && directory dvp has not been removed */) {
+ if ((nameiop == CREATE || nameiop == RENAME) &&
+ islastcn /* && directory dvp has not been removed */) {
- if (dvp->v_mount->mnt_flag & MNT_RDONLY) {
- err = EROFS;
- goto out;
- }
+ if (vfs_isrdonly(mp)) {
+ err = EROFS;
+ goto out;
+ }
- DEBUG("create/rename -- we have to make it\n");
- /*
- * Check for write access on directory.
- */
-
- if ((err = fuse_internal_access(dvp, VWRITE, cred, td, &facp)))
- goto out;
+#if 0 // THINK_ABOUT_THIS
+ if ((err = fuse_internal_access(dvp, VWRITE, cred, td, &facp))) {
+ goto out;
+ }
+#endif
- /*
- * Possibly record the position of a slot in the
- * directory large enough for the new component name.
- * This can be recorded in the vnode private data for
- * dvp. Set the SAVENAME flag to hold onto the
- * pathname for use later in VOP_CREATE or VOP_RENAME.
- */
- cnp->cn_flags |= SAVENAME;
-
- err = EJUSTRETURN;
- goto out;
+ /*
+ * Possibly record the position of a slot in the
+ * directory large enough for the new component name.
+ * This can be recorded in the vnode private data for
+ * dvp. Set the SAVENAME flag to hold onto the
+ * pathname for use later in VOP_CREATE or VOP_RENAME.
+ */
+ cnp->cn_flags |= SAVENAME;
+
+ err = EJUSTRETURN;
+ goto out;
}
- /*
- * Consider inserting name into cache.
- */
+ /* Consider inserting name into cache. */
/*
* No we can't use negative caching, as the fs
@@ -772,13 +774,13 @@
goto out;
} else {
+
if (op == FUSE_GETATTR) {
fattr = &((struct fuse_attr_out *)fdi.answ)->attr;
} else {
fattr = &((struct fuse_entry_out *)fdi.answ)->attr;
}
- DEBUG("we found something...\n");
/*
* If deleting, and at end of pathname, return parameters
* which can be used to remove file. If the wantparent flag
@@ -786,11 +788,9 @@
* and lock the inode, being careful with ".".
*/
if (nameiop == DELETE && islastcn) {
- DEBUG("something to delete\n");
/*
* Check for write access on directory.
*/
-
facp.xuid = fattr->uid;
facp.facc_flags |= FACCESS_STICKY;
err = fuse_internal_access(dvp, VWRITE, cred, td, &facp);
@@ -801,95 +801,112 @@
}
if (nid == VTOI(dvp)) {
- VREF(dvp);
+ vref(dvp);
*vpp = dvp;
goto out;
}
- if ((err = fuse_vget_i(dvp->v_mount, td,
- nid,
- IFTOVT(fattr->mode),
- &vp,
- VG_NORMAL,
- parentid))) {
- goto out;
+ /*
+ * XXX We discard generation, also brought to us by
+ * LOOKUP. It's purpose is unclear... it seems to be
+ * simply just yet another 32/64 bit extension for the
+ * inode number, but I'm not sure (hmm, it seems to
+ * have something to do with NFS exportability, too).
+ *
+ * (Linux has such a 32 bit value in its inode struct,
+ * and it really might just be a backward compatible
+ * extension for the inode space [but might as well
+ * be more into it, dunno]. The FUSE protocol uses
+ * a 64 bit generation value; FUSE/Linux uses it for
+ * filling the inode's i_generation field.)
+ */
+ err = fuse_vnode_get(dvp->v_mount,
+ nid,
+ dvp,
+ &vp,
+ cnp,
+ IFTOVT(fattr->mode),
+ size);
+ if (err) {
+ goto out;
}
*vpp = vp;
goto out;
+ }
+
+ /*
+ * If rewriting (RENAME), return the inode and the
+ * information required to rewrite the present directory
+ * Must get inode of directory entry to verify it's a
+ * regular file, or empty directory.
+ */
+ if (nameiop == RENAME && wantparent && islastcn) {
+
+#if 0 // THINK_ABOUT_THIS
+ if ((err = fuse_internal_access(dvp, VWRITE, cred, td, &facp))) {
+ goto out;
}
+#endif
/*
- * If rewriting (RENAME), return the inode and the
- * information required to rewrite the present directory
- * Must get inode of directory entry to verify it's a
- * regular file, or empty directory.
+ * Check for "."
*/
- if (nameiop == RENAME && wantparent && islastcn) {
- DEBUG("something to rename...\n");
+ if (nid == VTOI(dvp)) {
+ err = EISDIR;
+ goto out;
+ }
- facp.xuid = fattr->uid;
- facp.facc_flags |= FACCESS_STICKY;
- err = fuse_internal_access(dvp, VWRITE, cred, td, &facp);
- facp.facc_flags &= ~FACCESS_XQUERIES;
+ err = fuse_vnode_get(vnode_mount(dvp),
+ nid,
+ dvp,
+ &vp,
+ cnp,
+ IFTOVT(fattr->mode),
+ size);
+ if (err) {
+ goto out;
+ }
- if (err)
- goto out;
+ *vpp = vp;
+ /*
+ * Save the name for use in VOP_RENAME later.
+ */
+ cnp->cn_flags |= SAVENAME;
- /*
- * Check for "."
- */
- if (nid == VTOI(dvp)) {
- err = EISDIR;
- goto out;
- }
+ goto out;
+ }
- err = fuse_vget_i(dvp->v_mount, td, nid,
- IFTOVT(fattr->mode), &vp, VG_NORMAL,
- parentid);
- if (err)
- goto out;
- *vpp = vp;
- /*
- * Save the name for use in VOP_RENAME later.
- */
- cnp->cn_flags |= SAVENAME;
-
- goto out;
+ if (flags & ISDOTDOT) {
+ vref(pdp);
+ *vpp = pdp;
+ } else if (nid == VTOI(dvp)) {
+ vref(dvp);
+ *vpp = dvp;
+ } else {
+ err = fuse_vnode_get(vnode_mount(dvp),
+ nid,
+ dvp,
+ &vp,
+ cnp,
+ IFTOVT(fattr->mode),
+ size);
+ if (err) {
+ goto out;
}
-
- DEBUG("we peacefully found that file\n");
-
- if (nid == VTOI(dvp)) {
- VREF(dvp); /* We want ourself, ie "." */
- *vpp = dvp;
- } else {
- if (flags & ISDOTDOT)
- /*
- * If doing dotdot, we unlock dvp for vget time
- * to conform lock order regulations.
- */
- VOP_UNLOCK(dvp, 0);
- err = fuse_vget_i(dvp->v_mount, td, nid,
- IFTOVT(fattr->mode), &vp, VG_NORMAL,
- parentid);
- if (flags & ISDOTDOT)
- vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
- if (err)
- goto out;
- *vpp = vp;
+ if (vnode_vtype(vp) == VDIR) {
+ VTOFUD(vp)->parent = dvp;
+ //SETPARENT(vp, dvp);
}
+ *vpp = vp;
+ }
if (op == FUSE_GETATTR)
cache_attrs(*vpp, (struct fuse_attr_out *)fdi.answ);
else
cache_attrs(*vpp, (struct fuse_entry_out *)fdi.answ);
-#ifdef INVARIANTS
- cache_attrs_hit = 1;
-#endif
-
/* Insert name into cache if appropriate. */
/*
@@ -915,27 +932,19 @@
*/
#if 0
if (cnp->cn_flags & MAKEENTRY) {
- DEBUG("...caching\n");
cache_enter(dvp, *vpp, cnp);
}
#endif
}
out:
if (!lookup_err) {
- DEBUG("as the looked up thing was simply found, the cleanup is left for us\n");
-
+ // as the looked up thing was simply found, the cleanup is left for us
if (err) {
- DEBUG("though inode found, err exit with no vnode\n");
+ // though inode found, err exit with no vnode
if (op == FUSE_LOOKUP)
- fuse_internal_forget_send(dvp->v_mount, td, cred, nid, 1, &fdi);
+ fuse_internal_forget_send(vnode_mount(dvp), td, cred, nid, 1, &fdi);
return (err);
} else {
- if (op == FUSE_LOOKUP)
- VTOFUD(*vpp)->nlookup++;
-
- if (islastcn && flags & ISOPEN)
- VTOFUD(*vpp)->flags |= FVP_ACCESS_NOOP;
-
#ifndef NO_EARLY_PERM_CHECK_HACK
if (!islastcn) {
/* We have the attributes of the next item
@@ -966,18 +975,21 @@
* dir in question. But that can be known only
* by having the vnode...
*/
+ int tmpvtype = vnode_vtype(*vpp);
+
bzero(&facp, sizeof(facp));
- DEBUG("the early perm check hack\n");
+ // the early perm check hack
facp.facc_flags |= FACCESS_VA_VALID;
- KASSERT(cache_attrs_hit,
- (("invalid reference to cached attrs")));
- if ((*vpp)->v_type != VDIR && (*vpp)->v_type != VLNK)
+ if (tmpvtype != VDIR && tmpvtype != VLNK)
err = ENOTDIR;
- if (!err && !(*vpp)->v_mountedhere)
+
+ if (!err && !vnode_mountedhere(*vpp)) {
err = fuse_internal_access(*vpp, VEXEC, cred, td, &facp);
+ }
+
if (err) {
- if ((*vpp)->v_type == VLNK)
+ if (tmpvtype == VLNK)
DEBUG("weird, permission error with a symlink?\n");
vput(*vpp);
*vpp = NULL;
@@ -991,9 +1003,7 @@
return (err);
}
-#endif
-
/*
struct vnop_mkdir_args {
struct vnode *a_dvp;
@@ -1199,17 +1209,68 @@
static int
fuse_vnop_read(struct vop_read_args *ap)
{
+ int err;
struct vnode *vp = ap->a_vp;
- struct ucred *cred = ap->a_cred;
struct uio *uio = ap->a_uio;
+#ifdef XXXIP
int ioflag = ap->a_ioflag;
+ struct ucred *cred = ap->a_cred;
+#endif
+ off_t orig_resid;
+ off_t orig_offset;
- DEBUG2G("vnode #%llu\n", VTOILLU(vp));
- return fuse_io_vnode(vp, cred, uio, ioflag);
+ struct fuse_vnode_data *fvdat;
+
+ fuse_trace_printf_vnop();
+
+ if (fuse_isdeadfs_nop(vp)) {
+ if (vnode_vtype(vp) != VCHR) {
+ return EIO;
+ } else {
+ return 0;
+ }
+ }
+
+ if (uio_offset(uio) < 0) {
+ return EINVAL;
+ }
+
+ /*
+ * if (uio_offset(uio) > SOME_MAXIMUM_SIZE) {
+ * return 0;
+ * }
+ */
+
+ orig_resid = uio_resid(uio);
+ if (orig_resid == 0) {
+ return 0;
+ }
+
+ orig_offset = uio_offset(uio);
+ if (orig_offset < 0) {
+ return EINVAL;
+ }
+
+ fvdat = VTOFUD(vp);
+ if (!fvdat) {
+ return EINVAL;
+ }
+
+ /* Protect against size change here. */
+
+ if (vnode_isreg(vp)) {
+#ifdef XXXIP
+ err = cluster_read(vp, uio, fvdat->filesize, 0);
+#endif
+ } else if (vnode_isdir(vp)) {
+ err = EISDIR;
+ } else {
+ err = EPERM;
+ }
+
+ return err;
}
-#define DIRCOOKEDSIZE FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + MAXNAMLEN + 1)
-
/*
struct vnop_readdir_args {
struct vnode *a_vp;
@@ -1226,48 +1287,47 @@
struct vnode *vp = ap->a_vp;
struct ucred *cred = ap->a_cred;
struct uio *uio = ap->a_uio;
-
- struct thread *td = curthread;
+ int freefufh = 0;
int err = 0;
struct fuse_iov cookediov;
struct fuse_filehandle *fufh;
- struct fuse_io_data fioda;
- struct get_filehandle_param gefhp;
+ struct fuse_vnode_data *fvdat;
+
+ fuse_trace_printf_vnop();
+
+ if (fuse_isdeadfs_nop(vp)) {
+ return EBADF;
+ }
+
+#ifdef XXXIP
+ /* Sanity check the uio data. */
+ if ((uio_iovcnt(uio) > 1) ||
+ (uio_resid(uio) < (int)sizeof(struct dirent))) {
+ return (EINVAL);
+ }
+#endif
+
+ fvdat = VTOFUD(vp);
- bzero(&gefhp, sizeof(gefhp));
- gefhp.opcode = FUSE_OPENDIR;
- if ((err = fuse_get_filehandle(vp, td, cred, FREAD, &fufh, &gefhp))) {
- DEBUG2G("fetching filehandle failed\n");
- return (err);
+ fufh = &(fvdat->fufh[FUFH_RDONLY]);
+ if (!(fufh->fufh_flags & FUFH_VALID)) {
+ err = fuse_filehandle_get(vp, NULL, cred, FUFH_RDONLY);
+ if (err) {
+ return err;
+ }
+ freefufh = 1;
}
- /*
- * In "most cases" this will do and won't have to resize the buffer
- * (that is, if the daemon has a "tight" view of the dir entries,
- * which is the case if userspace uses the old API or the new one
- * in the analogous way; by our terminology, this means
- * freclen == bytesavail)
- * (See fuse_internal_readdir_processdata).
- */
+#define DIRCOOKEDSIZE FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + MAXNAMLEN + 1)
fiov_init(&cookediov, DIRCOOKEDSIZE);
- bzero(&fioda, sizeof(fioda));
- fioda.vp = vp;
- fioda.fufh = fufh;
- fioda.uio = uio;
- fioda.cred = cred;
- fioda.opcode = FUSE_READDIR;
- fioda.buffeater = fuse_internal_readdir_processdata;
- fioda.param = &cookediov;
- /*
- * We tried hard to use bio, but offsety readdir can't be handled
- * properly that way -- the offset field of fuse_dirents can't be
- * mapped to an offset of a bio buffer
- */
- err = fuse_read_directbackend(&fioda);
+ err = fuse_internal_readdir(vp, uio, fufh, &cookediov);
fiov_teardown(&cookediov);
- fufh->useco--;
+ if (freefufh) {
+ fufh->open_count--;
+ (void)fuse_filehandle_put(vp, NULL, NULL, FUFH_RDONLY, 0);
+ }
fuse_invalidate_attr(vp);
return err;
@@ -1286,19 +1346,27 @@
int err;
struct vnode *vp = ap->a_vp;
struct uio *uio = ap->a_uio;
+ struct ucred *cred = ap->a_cred;
struct fuse_dispatcher fdi;
fuse_trace_printf_vnop();
- if ((err = fdisp_simple_putget(&fdi, FUSE_READLINK, vp, curthread,
- ap->a_cred)))
- return (err);
+ if (fuse_isdeadfs_nop(vp)) {
+ return EBADF;
+ }
+
+ if (vnode_vtype(vp) != VLNK) {
+ return EINVAL;
+ }
+
+ if ((err = fdisp_simple_putget_vp(&fdi, FUSE_READLINK, vp, curthread, cred))) {
+ return err;
+ }
if (((char *)fdi.answ)[0] == '/' &&
- fusefs_get_data(vp->v_mount)->dataflag & FSESS_PUSH_SYMLINKS_IN) {
- char *mpth = vp->v_mount->mnt_stat.f_mntonname;
-
- err = uiomove(mpth, strlen(mpth), uio);
+ fusefs_get_data(vnode_mount(vp))->dataflag & FSESS_PUSH_SYMLINKS_IN) {
+ char *mpth = vnode_mount(vp)->mnt_stat.f_mntonname;
+ err = uiomove(mpth, strlen(mpth), uio);
}
if (!err) {
@@ -1320,18 +1388,46 @@
static int
fuse_vnop_reclaim(struct vop_reclaim_args *ap)
{
+ int type;
struct vnode *vp = ap->a_vp;
struct thread *td = ap->a_td;
+ struct fuse_vnode_data *fvdat = VTOFUD(vp);
+ struct fuse_filehandle *fufh = NULL;
+
+ fuse_trace_printf_vnop();
+
+ if (!fvdat) {
+ panic("FUSE: no vnode data during recycling");
+ }
+
+ for (type = 0; type < FUFH_MAXTYPE; type++) {
+ fufh = &(fvdat->fufh[type]);
+ if (fufh->fufh_flags & FUFH_VALID) {
+ if (fufh->fufh_flags & FUFH_STRATEGY) {
+ fufh->fufh_flags &= ~FUFH_MAPPED;
+ fufh->open_count = 0;
+ (void)fuse_filehandle_put(vp, td, NULL, type, 0);
+ } else {
+ panic("vnode being reclaimed but fufh (type=%d) is valid",
+ type);
+ }
+ }
+ }
- DEBUG("pfft...\n");
-#if _DEBUG
- DEBUG2G("=============>\n");
- kdb_backtrace();
- vn_printf(vp, " ");
- DEBUG2G("<=============\n");
-#endif
+ if ((!fuse_isdeadfs(vp)) && (fvdat->nlookup)) {
+ struct fuse_dispatcher fdi;
+ fdi.tick = NULL;
+ fuse_internal_forget_send(vnode_mount(vp), td, NULL, VTOI(vp),
+ fvdat->nlookup, &fdi);
+ }
+
+ cache_purge(vp);
+ /* XXXIP TODO */
+ vfs_hash_remove(vp);
vnode_destroy_vobject(vp);
- return (fuse_recyc_backend(vp, td));
+ fuse_vnode_destroy(vp);
+
+ return 0;
}
/*
@@ -1348,6 +1444,18 @@
struct vnode *vp = ap->a_vp;
struct componentname *cnp = ap->a_cnp;
+ fuse_trace_printf_vnop();
+
+ if (fuse_isdeadfs_nop(vp)) {
+ panic("fuse_vnop_remove(): called on a dead file system");
+ }
+
+ if (vnode_isdir(vp)) {
+ return EPERM;
+ }
+
+ cache_purge(vp);
+
return (fuse_internal_remove(dvp, vp, cnp, FUSE_UNLINK));
}
@@ -1364,252 +1472,34 @@
static int
fuse_vnop_rename(struct vop_rename_args *ap)
{
- struct vnode *tvp = ap->a_tvp;
- struct vnode *tdvp = ap->a_tdvp;
- struct vnode *fvp = ap->a_fvp;
- struct vnode *fdvp = ap->a_fdvp;
- struct componentname *tcnp = ap->a_tcnp;
- struct componentname *fcnp = ap->a_fcnp;
+ int err = 0;
+ struct vnode *fdvp = ap->a_fdvp;
+ struct vnode *fvp = ap->a_fvp;
+ struct componentname *tcnp = ap->a_tcnp;
+ struct vnode *tdvp = ap->a_tdvp;
+ struct vnode *tvp = ap->a_tvp;
+ struct componentname *fcnp = ap->a_fcnp;
- int doingdirectory = 0;
- int err = 0;
- struct thread *td;
- struct fuse_access_param facp;
- uint64_t fnid, tdnid;
- struct fuse_data *data = NULL;
- struct parentmanager_param pmp;
- struct vnode *xvp;
+ fuse_trace_printf_vnop();
- td = curthread;
- bzero(&facp, sizeof(facp));
+ if (fuse_isdeadfs_nop(fdvp)) {
+ panic("fuse_vnop_rename(): called on a dead file system");
+ }
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list