PERFORCE change 194384 for review
Ilya Putsikau
ilya at FreeBSD.org
Tue Jun 7 10:57:22 UTC 2011
http://p4web.freebsd.org/@@194384?ac=10
Change 194384 by ilya at ilya_triton2011 on 2011/06/07 10:56:33
fuse_vnops.c reduce diffs
Affected files ...
.. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_vnops.c#9 edit
Differences ...
==== //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_vnops.c#9 (text+ko) ====
@@ -348,18 +348,22 @@
static int
fuse_vnop_access(struct vop_access_args *ap)
{
- struct vnode *vp = ap->a_vp;
- struct fuse_access_param facp;
- struct fuse_vnode_data *fvdat = VTOFUD(vp);
+ struct vnode *vp = ap->a_vp;
+ struct fuse_access_param facp;
+ struct fuse_vnode_data *fvdat = VTOFUD(vp);
+
+ fuse_trace_printf_vnop();
+
+ bzero(&facp, sizeof(facp));
- bzero(&facp, sizeof(facp));
- if (fvdat->flags & FVP_ACCESS_NOOP)
- fvdat->flags &= ~FVP_ACCESS_NOOP;
- else
- facp.facc_flags |= FACCESS_DO_ACCESS;
+ if (fvdat->flags & FVP_ACCESS_NOOP) {
+ fvdat->flags &= ~FVP_ACCESS_NOOP;
+ } else {
+ facp.facc_flags |= FACCESS_DO_ACCESS;
+ }
- return fuse_internal_access(vp, ap->a_accmode,
- ap->a_cred, ap->a_td, &facp);
+ return fuse_internal_access(vp, ap->a_accmode,
+ ap->a_cred, ap->a_td, &facp);
}
/*
@@ -373,20 +377,20 @@
static int
fuse_vnop_close(struct vop_close_args *ap)
{
- struct fuse_release_param frp;
+ struct fuse_release_param frp;
- DEBUG2G("vnode #%llu\n", VTOILLU(ap->a_vp));
- frp.err = 0;
+ DEBUG2G("vnode #%llu\n", VTOILLU(ap->a_vp));
+ frp.err = 0;
#if FUSE_HAS_FLUSH_RELEASE
- frp.fg = 1;
- frp.flush = 1;
+ frp.fg = 1;
+ frp.flush = 1;
#else
- frp.fg = 0;
- frp.flush = 0;
+ frp.fg = 0;
+ frp.flush = 0;
#endif
- fuse_filehandle_gc(ap->a_vp, ap->a_td, ap->a_cred, &frp);
+ fuse_filehandle_gc(ap->a_vp, ap->a_td, ap->a_cred, &frp);
- return (frp.err);
+ return (frp.err);
}
/*
@@ -400,57 +404,57 @@
static int
fuse_vnop_create(struct vop_create_args *ap)
{
- struct vnode *dvp = ap->a_dvp;
- struct vnode **vpp = ap->a_vpp;
- struct vattr *vap = ap->a_vap;
+ struct vnode *dvp = ap->a_dvp;
+ struct vnode **vpp = ap->a_vpp;
+ struct vattr *vap = ap->a_vap;
#if FUSE_HAS_CREATE
- struct fuse_vnode_data *fvdat;
- int err;
+ struct fuse_vnode_data *fvdat;
+ int err;
- if (vap->va_type != VREG ||
- fusefs_get_data(dvp->v_mount)->dataflag & FSESS_NOCREATE)
- goto good_old;
+ if (vap->va_type != VREG ||
+ fusefs_get_data(dvp->v_mount)->dataflag & FSESS_NOCREATE)
+ goto good_old;
- /*
- * We cobble together here a new vnode as the caller expects that,
- * but we don't yet fully initialize it (that will happen when it
- * will be opened). We keep it in a "germic" state.
- */
- if ((err = getnewvnode("fuse", dvp->v_mount, &fuse_vnops, vpp)))
- return (err);
+ /*
+ * We cobble together here a new vnode as the caller expects that,
+ * but we don't yet fully initialize it (that will happen when it
+ * will be opened). We keep it in a "germic" state.
+ */
+ if ((err = getnewvnode("fuse", dvp->v_mount, &fuse_vnops, vpp)))
+ return (err);
- if ((err = vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY))) {
- printf("fuse4bsd: leaking vnode %p\n", *vpp);
- return (err);
- }
+ if ((err = vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY))) {
+ printf("fuse4bsd: leaking vnode %p\n", *vpp);
+ return (err);
+ }
- fvdat = malloc(sizeof(*fvdat), M_FUSEVN, M_WAITOK | M_ZERO);
+ fvdat = malloc(sizeof(*fvdat), M_FUSEVN, M_WAITOK | M_ZERO);
- fvdat->parent_nid = VTOI(dvp);
- /*
- * We overload some fields of the vnode data to carry the information
- * which will be needed to make the proper CREATE query in open.
- * germcnp is a dedicated field for this purpose though.
- */
- fvdat->flags = MAKEIMODE(vap->va_type, vap->va_mode);
- fvdat->germcnp = ap->a_cnp;
+ fvdat->parent_nid = VTOI(dvp);
+ /*
+ * We overload some fields of the vnode data to carry the information
+ * which will be needed to make the proper CREATE query in open.
+ * germcnp is a dedicated field for this purpose though.
+ */
+ fvdat->flags = MAKEIMODE(vap->va_type, vap->va_mode);
+ fvdat->germcnp = ap->a_cnp;
- /*
- * Stub vnops, almost the same as "dead", with the exception of the
- * critical ones which will let the vnode get fully emerged.
- */
- (*vpp)->v_op = &fuse_germ_vnops;
- (*vpp)->v_data = fvdat;
- (*vpp)->v_mount = dvp->v_mount;
+ /*
+ * Stub vnops, almost the same as "dead", with the exception of the
+ * critical ones which will let the vnode get fully emerged.
+ */
+ (*vpp)->v_op = &fuse_germ_vnops;
+ (*vpp)->v_data = fvdat;
+ (*vpp)->v_mount = dvp->v_mount;
- fuse_invalidate_attr(dvp);
+ fuse_invalidate_attr(dvp);
- return (0);
+ return (0);
good_old:
#endif
- vap->va_rdev = 0;
- return (VOP_MKNOD(dvp, vpp, ap->a_cnp, vap));
+ vap->va_rdev = 0;
+ return (VOP_MKNOD(dvp, vpp, ap->a_cnp, vap));
}
/*
@@ -477,84 +481,85 @@
static int
fuse_vnop_fsync(struct vop_fsync_args *ap)
{
- struct vnode *vp = ap->a_vp;
- struct thread *td = ap->a_td;
+ struct vnode *vp = ap->a_vp;
+ struct thread *td = ap->a_td;
+ struct fuse_dispatcher fdi;
- int err = 0;
- struct fuse_dispatcher fdi;
+ int err = 0;
- DEBUG("got flag %d\n", ap->a_waitfor);
+ DEBUG("got flag %d\n", ap->a_waitfor);
- /*
- * Usually, the call to vop_stdfsync is expected to do nothing, as we
- * tend to leave no dirty buffers behind. However, they might show up,
- * eg., after an interrupted write.
- * To be able to release the kernel's cleanup-dirty-buffers machinery
- * this is advised to be inserted here.
- */
+ /*
+ * Usually, the call to vop_stdfsync is expected to do nothing, as we
+ * tend to leave no dirty buffers behind. However, they might show up,
+ * eg., after an interrupted write.
+ * To be able to release the kernel's cleanup-dirty-buffers machinery
+ * this is advised to be inserted here.
+ */
- if ((err = vop_stdfsync(ap)))
- return (err);
+ if ((err = vop_stdfsync(ap)))
+ return (err);
- /*
- * In Linux, the fsync syscall handler is file based.
- * Hence in fuse too -- and this approach does make sense,
- * for exapmle, when it comes to implementing things like
- * sshfs: the sshfs userspace fsync handler flushes data
- * associated with the given filehandle, ie. sftp
- * messaging thread.
- *
- * On the other hand, BSD fsync is inherently not file
- * but vnode based: even fsync(2), to which one passes
- * a file descriptor, the corresponding file is used for
- * nothing but looking up the vnode behind (see fsync()
- * in kern/vfs_syscalls.c).
- *
- * We have thus two choices here: either grab the first
- * open file and use that for the fsync message or run
- * through all files (at least, the ones we have acces to,
- * ie., those belonging to the current process). The first
- * is bad: as we mentioned concerning sshfs, dirty data can belong
- * to each ssh messaging thread, being associated to file
- * handles independently.
- *
- * So we wanna sync all our open files. "Nowait" sync is easy,
- * just walk over all the files, and send FUSE_FSYNC(DIR) with
- * a null callback, and leave. "Wait" sync is harder: syncing
- * the files linearly, one after the other would be very easy
- * indeed but would be far more than a lethal dose of the KISS
- * principle. So sending of the messages and waiting for them
- * should be done synchronously. The messaging backend is flexible
- * enough for making the implementation of this not too hard,
- * but now I don't wanna go mucking with the proper handling of
- * interrupts, and other issues; and I don't wanna break the nice
- * hi-level messaging API which serves us well otherwise. So
- * currently I just say no here...
- *
- * Just to note: even the "nowait" type fsync could be optimized
- * if we went beyond the api, and lock/unlock all mutexes (tickets',
- * messages', callbacks') only once, and take out/put in stuff for all
- * files together, with one big breath. But doing not so is not as much
- * overhead as it would be worth for the trouble.
- */
+ /*
+ * In Linux, the fsync syscall handler is file based.
+ * Hence in fuse too -- and this approach does make sense,
+ * for exapmle, when it comes to implementing things like
+ * sshfs: the sshfs userspace fsync handler flushes data
+ * associated with the given filehandle, ie. sftp
+ * messaging thread.
+ *
+ * On the other hand, BSD fsync is inherently not file
+ * but vnode based: even fsync(2), to which one passes
+ * a file descriptor, the corresponding file is used for
+ * nothing but looking up the vnode behind (see fsync()
+ * in kern/vfs_syscalls.c).
+ *
+ * We have thus two choices here: either grab the first
+ * open file and use that for the fsync message or run
+ * through all files (at least, the ones we have acces to,
+ * ie., those belonging to the current process). The first
+ * is bad: as we mentioned concerning sshfs, dirty data can belong
+ * to each ssh messaging thread, being associated to file
+ * handles independently.
+ *
+ * So we wanna sync all our open files. "Nowait" sync is easy,
+ * just walk over all the files, and send FUSE_FSYNC(DIR) with
+ * a null callback, and leave. "Wait" sync is harder: syncing
+ * the files linearly, one after the other would be very easy
+ * indeed but would be far more than a lethal dose of the KISS
+ * principle. So sending of the messages and waiting for them
+ * should be done synchronously. The messaging backend is flexible
+ * enough for making the implementation of this not too hard,
+ * but now I don't wanna go mucking with the proper handling of
+ * interrupts, and other issues; and I don't wanna break the nice
+ * hi-level messaging API which serves us well otherwise. So
+ * currently I just say no here...
+ *
+ * Just to note: even the "nowait" type fsync could be optimized
+ * if we went beyond the api, and lock/unlock all mutexes (tickets',
+ * messages', callbacks') only once, and take out/put in stuff for all
+ * files together, with one big breath. But doing not so is not as much
+ * overhead as it would be worth for the trouble.
+ */
- /*
- * It seemed to be a good idea to lock the filehandle lock only before
- * doing iterate_filehandle but that configuration is suspected to cause
- * LOR alerts, so now we get the filehandle lock before the fuse_data
- * lock.
- */
- ASSERT_VOP_LOCKED__FH(vp);
+ /*
+ * It seemed to be a good idea to lock the filehandle lock only before
+ * doing iterate_filehandle but that configuration is suspected to cause
+ * LOR alerts, so now we get the filehandle lock before the fuse_data
+ * lock.
+ */
+ ASSERT_VOP_LOCKED__FH(vp);
- if (fusefs_get_data(vp->v_mount)->dataflag &
- (vp->v_type == VDIR ? FSESS_NOFSYNCDIR : FSESS_NOFSYNC))
- goto out;
+ if (fusefs_get_data(vp->v_mount)->dataflag &
+ (vp->v_type == VDIR ? FSESS_NOFSYNCDIR : FSESS_NOFSYNC)) {
+ goto out;
+ }
- fdisp_init(&fdi, 0);
- iterate_filehandles(vp, td, NULL, fuse_fsync_filehandle, &fdi);
+ fdisp_init(&fdi, 0);
+ iterate_filehandles(vp, td, NULL, fuse_fsync_filehandle, &fdi);
out:
- return (err);
+ return (err);
}
/*
@@ -717,58 +722,62 @@
static int
fuse_vnop_link(struct vop_link_args *ap)
{
- struct vnode *dvp = ap->a_tdvp;
- struct vnode *vp = ap->a_vp;
- struct componentname *cnp = ap->a_cnp;
+ struct vnode *vp = ap->a_vp;
+ struct vnode *tdvp = ap->a_tdvp;
+ struct componentname *cnp = ap->a_cnp;
+
+ int err = 0;
+ struct fuse_dispatcher fdi;
+ struct fuse_entry_out *feo;
+ struct fuse_link_in fli;
+
+ fuse_trace_printf_vnop();
- struct fuse_dispatcher fdi;
- struct fuse_link_in fli;
- struct fuse_entry_out *feo;
- int err = 0;
+ if (tdvp->v_mount != vp->v_mount) {
+ return (EXDEV);
+ }
- if (dvp->v_mount != vp->v_mount)
- return (EXDEV);
+ fli.oldnodeid = VTOI(vp);
- fli.oldnodeid = VTOI(vp);
+ /*
+ * Unlike Linux, we proceed here lazily: here we do nothing on
+ * the kernel side for registering the new, hardlinked entry.
+ * (That will just happen when the hardlinked entry is looked up
+ * first time). We just send the request to the daemon.
+ * This suits better for the BSD VFS.
+ */
- /*
- * Unlike Linux, we proceed here lazily: here we do nothing on
- * the kernel side for registering the new, hardlinked entry.
- * (That will just happen when the hardlinked entry is looked up
- * first time). We just send the request to the daemon.
- * This suits better for the BSD VFS.
- */
+ fdisp_init(&fdi, 0);
+ fuse_internal_newentry_makerequest(tdvp->v_mount, VTOI(tdvp), cnp,
+ FUSE_LINK, &fli, sizeof(fli), &fdi);
+ if ((err = fdisp_wait_answ(&fdi))) {
+ return (err);
+ }
- fdisp_init(&fdi, 0);
- fuse_internal_newentry_makerequest(dvp->v_mount, VTOI(dvp), cnp, FUSE_LINK, &fli,
- sizeof(fli), &fdi);
- if ((err = fdisp_wait_answ(&fdi)))
- return (err);
-
- feo = fdi.answ;
+ feo = fdi.answ;
- err = fuse_internal_checkentry(feo, vp->v_type);
+ err = fuse_internal_checkentry(feo, vp->v_type);
- fuse_ticket_drop(fdi.tick);
- fuse_invalidate_attr(dvp);
- /*
- * It depends on userspace if the hardlinked entry is really the
- * same vnode or not. Sort of unconventionally, the latter happens
- * if linking is managed by the hi-level FUSE library (in which case
- * syncing between the two nodes is up to the actual fs code).
- * Therefore we can't just cache the attrs we got for the hardlink node,
- * -- that regards to the hardlinked node and not the original.
- * What we do instead is invalidating cached attrs of the original so
- * the fs gets a chance to pass on updated attributes also for the
- * original node.
- *
- * See also remark at the similar place in the Linux kernel code.
- */
- fuse_invalidate_attr(vp);
+ fuse_ticket_drop(fdi.tick);
+ fuse_invalidate_attr(tdvp);
+ /*
+ * It depends on userspace if the hardlinked entry is really the
+ * same vnode or not. Sort of unconventionally, the latter happens
+ * if linking is managed by the hi-level FUSE library (in which case
+ * syncing between the two nodes is up to the actual fs code).
+ * Therefore we can't just cache the attrs we got for the hardlink node,
+ * -- that regards to the hardlinked node and not the original.
+ * What we do instead is invalidating cached attrs of the original so
+ * the fs gets a chance to pass on updated attributes also for the
+ * original node.
+ *
+ * See also remark at the similar place in the Linux kernel code.
+ */
+ fuse_invalidate_attr(vp);
- VTOFUD(vp)->nlookup++;
+ VTOFUD(vp)->nlookup++;
- return (err);
+ return (err);
}
/*
@@ -782,412 +791,419 @@
int
fuse_vnop_lookup(struct vop_lookup_args *ap)
{
- struct vnode *dvp = ap->a_dvp;
- struct vnode **vpp = ap->a_vpp;
- struct componentname *cnp = ap->a_cnp;
- int nameiop = cnp->cn_nameiop;
- struct thread *td = cnp->cn_thread;
- struct ucred *cred = cnp->cn_cred;
- int flags = cnp->cn_flags;
- int wantparent = flags & WANTPARENT;
- int islastcn = flags & ISLASTCN;
+ struct componentname *cnp = ap->a_cnp;
+ int nameiop = cnp->cn_nameiop;
+ int flags = cnp->cn_flags;
+ int wantparent = flags & 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;
+
+ fuse_trace_printf_vnop();
- int err = 0;
- int lookup_err = 0;
- struct vnode *vp = NULL;
- struct fuse_dispatcher fdi;
- struct fuse_attr *fattr = NULL;
- enum fuse_opcode op;
- uint64_t nid;
- uint64_t parentid;
- struct fuse_access_param facp;
+ int err = 0;
+ int lookup_err = 0;
+ struct vnode *vp = NULL;
+ struct fuse_attr *fattr = NULL;
+ struct fuse_dispatcher fdi;
+ enum fuse_opcode op;
+ uint64_t nid, parentid;
+ struct fuse_access_param facp;
#ifdef INVARIANTS
- int cache_attrs_hit = 0;
+ int cache_attrs_hit = 0;
#endif
- /* general stuff, based on vfs_cache_lookup */
+ /* general stuff, based on vfs_cache_lookup */
#if _DEBUG
- DEBUG2G("root node:\n");
- vn_printf(fusefs_get_data(dvp->v_mount)->rvp, " * ");
+ DEBUG2G("root node:\n");
+ vn_printf(fusefs_get_data(dvp->v_mount)->rvp, " * ");
#endif
- if (dvp->v_type != VDIR) {
- DEBUG("vnode #%llu of vtype %d is not a dir\n", VTOILLU(dvp),
- dvp->v_type);
- return (ENOTDIR);
- }
+ if (dvp->v_type != VDIR) {
+ return ENOTDIR;
+ }
- if (islastcn && (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
- (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
- return (EROFS);
+ if (islastcn && (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
+ (nameiop == DELETE || nameiop == RENAME)) {
+ return (EROFS);
+ }
- /*
- * We do access check prior to doing anything else only in the case
- * when we are at fs root (we'd like to say, "we are at the first
- * component", but that's not exactly the same... nevermind).
- * See further comments at further access checks.
- */
+ /*
+ * We do access check prior to doing anything else only in the case
+ * when we are at fs root (we'd like to say, "we are at the first
+ * component", but that's not exactly the same... nevermind).
+ * See further comments at further access checks.
+ */
- bzero(&facp, sizeof(facp));
- if (
+ bzero(&facp, sizeof(facp));
+ if (
#ifdef NO_EARLY_PERM_CHECK_HACK
- 1
+ 1
#else
- dvp->v_vflag & VV_ROOT
+ dvp->v_vflag & VV_ROOT
#endif
- ) {
- if ((err = fuse_internal_access(dvp, VEXEC, cred, td, &facp)))
- return (err);
- }
+ ) {
+ 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);
+ DEBUG2G("lookup in #%llu, nameiop %lu, with flags %#x\n",
+ VTOILLU(dvp), cnp->cn_nameiop, flags);
- /* fetching data from "storage" */
+ /* fetching data from "storage" */
- if (flags & ISDOTDOT) {
- DEBUG2G("dotdot lookup!\n");
- nid = VTOFUD(dvp)->parent_nid;
- parentid = FUSE_NULL_ID;
- fdisp_init(&fdi, 0);
- op = FUSE_GETATTR;
- } else if (cnp->cn_namelen == 1 && *(cnp->cn_nameptr) == '.') {
- DEBUG2G("dot lookup!\n");
- nid = VTOI(dvp);
- parentid = VTOFUD(dvp)->parent_nid; /* irrelevant */
- fdisp_init(&fdi, 0);
- op = FUSE_GETATTR;
- } else {
- nid = VTOI(dvp);
- parentid = VTOI(dvp);
- fdisp_init(&fdi, cnp->cn_namelen + 1);
- op = FUSE_LOOKUP;
- }
+ if (flags & ISDOTDOT) {
+ DEBUG2G("dotdot lookup!\n");
+ nid = VTOFUD(dvp)->parent_nid;
+ parentid = FUSE_NULL_ID;
+ fdisp_init(&fdi, 0);
+ op = FUSE_GETATTR;
+ } else if (cnp->cn_namelen == 1 && *(cnp->cn_nameptr) == '.') {
+ DEBUG2G("dot lookup!\n");
+ nid = VTOI(dvp);
+ parentid = VTOFUD(dvp)->parent_nid; /* irrelevant */
+ fdisp_init(&fdi, 0);
+ op = FUSE_GETATTR;
+ } else {
+ nid = VTOI(dvp);
+ parentid = VTOI(dvp);
+ fdisp_init(&fdi, cnp->cn_namelen + 1);
+ op = FUSE_LOOKUP;
+ }
- fdisp_make(&fdi, dvp->v_mount, op, nid, td, cred);
+ fdisp_make(&fdi, dvp->v_mount, 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);
- }
+ 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);
+ lookup_err = fdisp_wait_answ(&fdi);
- if (op == FUSE_LOOKUP && ! lookup_err) {
- nid = ((struct fuse_entry_out *)fdi.answ)->nodeid;
- 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 (op == FUSE_LOOKUP && !lookup_err) {
+ nid = ((struct fuse_entry_out *)fdi.answ)->nodeid;
+ 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 */
- )) {
- /*
- * There is error but not lookup related actually
- * (messaging error)
- */
- DEBUG("lookup failed b/c messaging crap\n");
- return (lookup_err);
- }
+ 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 */
+ )) {
+ /*
+ * There is error but not lookup related actually
+ * (messaging error)
+ */
+ DEBUG("lookup failed b/c messaging crap\n");
+ return (lookup_err);
+ }
- /* analyzing answer */
+ /* analyzing answer */
- /*
- * Now we got the answer and filtered out the crap, too, so we know that
- * "found" iff lookup_err == 0
- */
+ /*
+ * 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 (lookup_err) {
+ DEBUG("looked up thingy not found\n");
+ 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 (dvp->v_mount->mnt_flag & MNT_RDONLY) {
+ 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;
+ 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;
- /*
- * 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
- * changes are out of our control.
- * False positives' falseness turns out just as things
- * go by, but false negatives' falseness doesn't.
- * (and aiding the caching mechanism with extra control
- * mechanisms comes quite close to beating the whole purpose
- * caching...)
- */
+ /*
+ * No we can't use negative caching, as the fs
+ * changes are out of our control.
+ * False positives' falseness turns out just as things
+ * go by, but false negatives' falseness doesn't.
+ * (and aiding the caching mechanism with extra control
+ * mechanisms comes quite close to beating the whole purpose
+ * caching...)
+ */
#if 0
- if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE) {
- DEBUG("inserting NULL into cache\n");
- cache_enter(dvp, NULL, cnp);
- }
+ if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE) {
+ DEBUG("inserting NULL into cache\n");
+ cache_enter(dvp, NULL, cnp);
+ }
#endif
- err = ENOENT;
- goto out;
- } else {
- if (op == FUSE_GETATTR)
- fattr = &((struct fuse_attr_out *)fdi.answ)->attr;
- else
- fattr = &((struct fuse_entry_out *)fdi.answ)->attr;
+ err = ENOENT;
+ 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
- * isn't set, we return only the directory, otherwise we go on
- * and lock the inode, being careful with ".".
- */
- if (nameiop == DELETE && islastcn) {
- DEBUG("something to delete\n");
- /*
- * Check for write access on directory.
- */
+ 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
+ * isn't set, we return only the directory, otherwise we go on
+ * 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);
- facp.facc_flags &= ~FACCESS_XQUERIES;
+ facp.xuid = fattr->uid;
+ facp.facc_flags |= FACCESS_STICKY;
+ err = fuse_internal_access(dvp, VWRITE, cred, td, &facp);
+ facp.facc_flags &= ~FACCESS_XQUERIES;
- if (err)
- goto out;
+ if (err) {
+ goto out;
+ }
- if (nid == VTOI(dvp)) {
- VREF(dvp);
- *vpp = dvp;
- goto out;
- }
+ if (nid == VTOI(dvp)) {
+ VREF(dvp);
+ *vpp = dvp;
+ goto out;
+ }
- err = fuse_vget_i(dvp->v_mount, td, nid,
- IFTOVT(fattr->mode), &vp, VG_NORMAL,
- parentid);
- if (err)
- goto out;
- *vpp = vp;
+ if ((err = fuse_vget_i(dvp->v_mount, td,
+ nid,
+ IFTOVT(fattr->mode),
+ &vp,
+ VG_NORMAL,
+ parentid))) {
+ goto out;
+ }
- 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) {
- DEBUG("something to rename...\n");
+ /*
+ * 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) {
+ DEBUG("something to rename...\n");
- facp.xuid = fattr->uid;
- facp.facc_flags |= FACCESS_STICKY;
- err = fuse_internal_access(dvp, VWRITE, cred, td, &facp);
- facp.facc_flags &= ~FACCESS_XQUERIES;
+ facp.xuid = fattr->uid;
+ facp.facc_flags |= FACCESS_STICKY;
+ err = fuse_internal_access(dvp, VWRITE, cred, td, &facp);
+ facp.facc_flags &= ~FACCESS_XQUERIES;
- if (err)
- goto out;
+ if (err)
+ goto out;
- /*
- * Check for "."
- */
- if (nid == VTOI(dvp)) {
- err = EISDIR;
- goto out;
- }
+ /*
+ * Check for "."
+ */
+ if (nid == VTOI(dvp)) {
+ err = EISDIR;
+ 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;
+ 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;
- }
+ goto out;
+ }
- DEBUG("we peacefully found that file\n");
+ 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 (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 (op == FUSE_GETATTR)
- cache_attrs(*vpp, (struct fuse_attr_out *)fdi.answ);
- else
- cache_attrs(*vpp, (struct fuse_entry_out *)fdi.answ);
+ 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;
+ cache_attrs_hit = 1;
#endif
- /* Insert name into cache if appropriate. */
+ /* Insert name into cache if appropriate. */
- /*
- * Nooo, caching is evil. With caching, we can't avoid stale
- * information taking over the playground (cached info is not
- * just positive/negative, it does have qualitative aspects,
- * too). And a (VOP/FUSE)_GETATTR is always thrown anyway, when
- * walking down along cached path components, and that's not
- * any cheaper than FUSE_LOOKUP. This might change with
- * implementing kernel side attr caching, but... In Linux,
- * lookup results are not cached, and the daemon is bombarded
- * with FUSE_LOOKUPS on and on. This shows that by design, the
- * daemon is expected to handle frequent lookup queries
- * efficiently, do its caching in userspace, and so on.
- *
- * So just leave the name cache alone.
- */
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list