PERFORCE change 194684 for review

Ilya Putsikau ilya at FreeBSD.org
Mon Jun 13 15:35:55 UTC 2011


http://p4web.freebsd.org/@@194684?ac=10

Change 194684 by ilya at ilya_triton2011 on 2011/06/13 15:35:37

	Fix internal functions definfions, rename fdisp_simple_vfs_getattr -> fdisp_simple_vfs_statfs

Affected files ...

.. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_file.c#2 edit
.. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_internal.c#6 edit
.. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_internal.h#8 edit
.. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_ipc.h#6 edit
.. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_vnops.c#11 edit

Differences ...

==== //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_file.c#2 (text+ko) ====

@@ -3,14 +3,34 @@
  * 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/mount.h>
+#include <sys/vnode.h>
+#include <sys/sysctl.h>
+
 #include "fuse.h"
 #include "fuse_file.h"
+#include "fuse_internal.h"
 #include "fuse_ipc.h"
 #include "fuse_node.h"
-#include "fuse_sysctl.h"
 
 int
-fuse_filehandle_get(vnode_t vp, vfs_context_t context, fufh_type_t fufh_type)
+fuse_filehandle_get(struct vnode *vp, struct thread *td, struct ucred *cred, fufh_type_t fufh_type)
 {
     struct fuse_vnode_data *fvdat = VTOFUD(vp);
     struct fuse_dispatcher  fdi;
@@ -42,7 +62,7 @@
     }
 
     fdisp_init(&fdi, sizeof(*foi));
-    fdisp_make_vp(&fdi, op, vp, context);
+    fdisp_make_vp(&fdi, op, vp, td, cred);
 
     foi = fdi.indata;
     foi->flags = oflags;
@@ -68,7 +88,7 @@
 }
 
 int
-fuse_filehandle_put(vnode_t vp, vfs_context_t context, fufh_type_t fufh_type,
+fuse_filehandle_put(struct vnode *vp, struct thread *td, struct ucred *cred, fufh_type_t fufh_type,
                     int foregrounded)
 {
     struct fuse_dispatcher  fdi;
@@ -103,7 +123,7 @@
     }
 
     fdisp_init(&fdi, sizeof(*fri));
-    fdisp_make_vp(&fdi, op, vp, context);
+    fdisp_make_vp(&fdi, op, vp, td, cred);
     fri = fdi.indata;
     fri->fh = fufh->fh_id;
     fri->flags = fufh->open_flags;

==== //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_internal.c#6 (text+ko) ====

@@ -280,8 +280,6 @@
 int
 fuse_internal_readdir(struct vnode           *vp,
                       struct uio             *uio,
-                      struct thread          *td,
-                      struct ucred           *cred,
                       struct fuse_filehandle *fufh,
                       struct fuse_iov        *cookediov)
 {
@@ -300,7 +298,7 @@
     while (uio_resid(uio) > 0) {
 
         fdi.iosize = sizeof(*fri);
-        fdisp_make_vp(&fdi, FUSE_READDIR, vp, td, cred);
+        fdisp_make_vp(&fdi, FUSE_READDIR, vp, NULL, NULL);
 
         fri = fdi.indata;
         fri->fh = fufh->fh_id;
@@ -544,6 +542,7 @@
 int
 fuse_internal_newentry_core(struct vnode *dvp,
                             struct vnode **vpp,
+                            struct componentname   *cnp,
                             enum vtype vtyp,
                             struct fuse_dispatcher *fdip)
 {
@@ -563,8 +562,8 @@
         goto out;
     }
 
-    err = fuse_vget_i(mp, curthread, feo->nodeid, vtyp, vpp,
-                      VG_FORCENEW, VTOI(dvp));
+    err = fuse_vnode_get(mp, feo->nodeid, dvp, vpp, cnp,
+	vtyp, 0);
     if (err) {
         fuse_internal_forget_send(mp, curthread, NULL, feo->nodeid, 1, fdip);
         return err;
@@ -593,7 +592,7 @@
     fdisp_init(&fdi, 0);
     fuse_internal_newentry_makerequest(vnode_mount(dvp), VTOI(dvp), cnp,
 	                               op, buf, bufsize, &fdi);
-    err = fuse_internal_newentry_core(dvp, vpp, vtyp, &fdi);
+    err = fuse_internal_newentry_core(dvp, vpp, cnp, vtyp, &fdi);
     fuse_invalidate_attr(dvp);
 
     return (err);

==== //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_internal.h#8 (text+ko) ====

@@ -14,12 +14,24 @@
 #include "fuse_ipc.h"
 #include "fuse_node.h"
 
+static __inline int
+vfs_isrdonly(struct mount *mp)
+{
+    return ((mp->mnt_flag & MNT_RDONLY) != 0 ? 1 : 0);
+}
+
 static __inline struct mount *
 vnode_mount(struct vnode *vp)
 {
 	return (vp->v_mount);
 }
 
+static __inline int
+vnode_mountedhere(struct vnode *vp)
+{
+	return (vp->v_mountedhere != NULL ? 1 : 0);
+}
+
 static __inline enum vtype
 vnode_vtype(struct vnode *vp)
 {
@@ -32,6 +44,18 @@
     return ((vp->v_vflag & VV_ROOT) != 0 ? 1 : 0);
 }
 
+static __inline int
+vnode_isreg(struct vnode *vp)
+{
+    return (vp->v_type == VREG ? 1 : 0);
+}
+
+static __inline int
+vnode_isdir(struct vnode *vp)
+{
+    return (vp->v_type == VDIR ? 1 : 0);
+}
+
 static __inline ssize_t
 uio_resid(struct uio *uio)
 {
@@ -50,6 +74,12 @@
     uio->uio_offset = offset;
 }
 
+static __inline void
+uio_setresid(struct uio *uio, ssize_t resid)
+{
+    uio->uio_resid = resid;
+}
+
 /* XXX */
 void cluster_push(struct vnode *vp, int a);
 
@@ -166,8 +196,6 @@
 int
 fuse_internal_readdir(struct vnode           *vp,
                       struct uio             *uio,
-                      struct thread          *td,
-                      struct ucred           *cred,
                       struct fuse_filehandle *fufh,
                       struct fuse_iov        *cookediov);
 
@@ -246,6 +274,7 @@
 int
 fuse_internal_newentry_core(struct vnode *dvp,
                             struct vnode **vpp,
+                            struct componentname   *cnp,
                             enum vtype vtyp,
                             struct fuse_dispatcher *fdip);
 

==== //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_ipc.h#6 (text+ko) ====

@@ -302,14 +302,12 @@
     return (fdisp_wait_answ(fdip));
 }
 
-static __inline__ int
-fdisp_simple_vfs_getattr(struct fuse_dispatcher *fdip,
-                         struct mount           *mp,
-			 struct thread		*td,
-			 struct ucred		*cred)
+static __inline int
+fdisp_simple_vfs_statfs(struct fuse_dispatcher *fdip,
+                         struct mount           *mp)
 {
    fdisp_init(fdip, 0);
-   fdisp_make(fdip, mp, FUSE_STATFS, FUSE_ROOT_ID, td, cred);
+   fdisp_make(fdip, mp, FUSE_STATFS, FUSE_ROOT_ID, NULL, NULL);
    return (fdisp_wait_answ(fdip));
 }
 

==== //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_vnops.c#11 (text+ko) ====

@@ -46,60 +46,6 @@
 
 #include <sys/priv.h>
 
-#if 0
-/* function prototype for iterators over filehandles (of a vp) */
-typedef int fuse_metrics_t(struct fuse_filehandle *fufh, struct thread *td,
-                           struct ucred *cred, void *param);
-
-
-/* parameter struct for fuse_standard_metrics() */
-struct standard_metrics_param {
-	int mode;
-	enum fuse_opcode op;
-	struct fuse_filehandle *fufh;
-};
-
-struct fuse_release_param {
-	int err;
-	uint8_t fg:1;
-	uint8_t flush:1;
-};
-
-static __inline void    fuse_vnode_init_data(struct vnode *vp, struct fuse_vnode_data *fvdat,
-                                             uint64_t nodeid);
-static __inline void    fuse_vnode_init_misc(struct vnode *vp, enum vtype vtyp,
-                                             uint64_t parentid);
-static int              fuse_recyc_backend(struct vnode *vp, struct thread *td);
-static void             fuse_filehandle_gc(struct vnode *vp, struct thread *td,
-                                           struct ucred *cred,
-                                           struct fuse_release_param *frp);
-static int              iterate_filehandles(struct vnode *vp, struct thread *td,
-                                            struct ucred *cred,
-                                            fuse_metrics_t fmetr, void *param);
-#if FUSE_HAS_CREATE
-static __inline int     create_filehandle(struct vnode *vp, struct thread *td,
-                                          struct ucred *cred, int mode,
-                                          struct fuse_dispatcher *fdip);
-#endif
-static void             fuse_send_release(struct fuse_filehandle *fufh,
-                                          struct thread *td, struct ucred *cred,
-                                          int flags,
-                                          struct fuse_release_param *frp);
-extern int              fuse_read_directbackend(struct fuse_io_data *fioda);
-
-static fuse_metrics_t fuse_file_ditch;
-static fuse_metrics_t fuse_standard_metrics;
-static fuse_metrics_t fuse_fsync_filehandle;
-static fuse_metrics_t release_filehandle;
-
-#if FUSE_HAS_CREATE
-static vfs_hash_cmp_t fuse_vnode_fgdrop_cmp;
-#endif
-static vfs_hash_cmp_t fuse_vnode_findparent_cmp;
-
-/* file ops */
-static fo_close_t fuse_close_f;
-
 /* vnode ops */
 static vop_access_t   fuse_vnop_access;
 static vop_close_t    fuse_vnop_close;
@@ -159,162 +105,11 @@
 	.vop_unlock        = fuse_vnop_unlock,
 };
 
-struct fileops fuse_fileops = {
-	.fo_read     = fuse_io_file,
-	.fo_write    = fuse_io_file,
-	/*
-         * following fields are filled from vnops, but "vnops.foo" is not
-         * legitimate in a definition, so we set them at module load time
-	 */
-	.fo_ioctl    = NULL,
-	.fo_poll     = NULL,
-	.fo_kqfilter = NULL,
-	.fo_stat     = NULL,
-	.fo_close    = fuse_close_f,
-	.fo_flags    = DFLAG_PASSABLE | DFLAG_SEEKABLE
-};
-
-#if FUSE_HAS_CREATE
-struct vop_vector fuse_germ_vnops;
-#endif
-
 MALLOC_DEFINE(M_FUSEVN, "fuse_vnode", "fuse vnode private data");
 MALLOC_DEFINE(M_FUSEFH, "fuse_filehandles", "buffer for fuse filehandles");
 
 int fuse_pbuf_freecnt = -1;
 
-/******************
- *
- * >>> VFS hash comparators
- *
- ******************/
-
-#if FUSE_HAS_CREATE
-/*
- * Vnode comparison function with which the given vnode always
- * gets inserted, but got marked invalid upon a clash. Caller
- * is free (and expected to) deal with clashes.
- */
-
-int
-fuse_vnode_fgdrop_cmp(struct vnode *vp, void *param)
-{
-	struct fuse_vnode_data *fvdat = param;
-
-	if (VTOI(vp) == fvdat->nid)
-		fvdat->nid = FUSE_NULL_ID;
-
-	return (1);
-}
-#endif
-
-/*
- * A skewed use of the vfs hash subsystem for finding out parent
- * nodeid. This comparator never matches, just collects data during
- * scanning through the nodes (without vnode locking).
- */
-
-static int
-fuse_vnode_findparent_cmp(struct vnode *vp, void *param)
-{
-	struct parentmanager_param *pmp = param;
-
-	/*
-	 * In general, we'd need a (nodeid, vtyp) pair to match
-	 * but we may assume that the type is directory, because
-	 * that's what users of this function will want.
-	 */
-
-	if (VTOI(vp) == pmp->nodeid && vp->v_type == VDIR) {
-		KASSERT(! pmp->valid,
-		        ("more than one vnode seems to match #%llu",
-			 (unsigned long long)pmp->nodeid));
-		pmp->parent_nid = VTOFUD(vp)->parent_nid;
-		pmp->valid = 1;
-	}
-
-	return (1);
-}
-
-/******************
- *
- * >>> Vnode related aux routines
- *
- ******************/
-
-static __inline void
-fuse_vnode_init_data(struct vnode *vp, struct fuse_vnode_data *fvdat,
-                     uint64_t nodeid)
-{
-	fvdat->nid = nodeid;
-	vp->v_data = fvdat;
-}
-
-static __inline void
-fuse_vnode_init_misc(struct vnode *vp, enum vtype vtyp, uint64_t parentid)
-{
-	struct fuse_vnode_data *fvdat = VTOFUD(vp);
-
-	VNASSERT(fvdat, vp, (("init_misc on virgin vnode"))); 
-
-	fvdat->parent_nid = parentid;
-	vp->v_type = vtyp;
-
-	LIST_INIT(&fvdat->fh_head);
-
-	vp->v_bufobj.bo_private = vp;
-}	
-
-void
-fuse_vnode_init(struct vnode *vp, struct fuse_vnode_data *fvdat,
-                uint64_t nodeid, enum vtype vtyp, uint64_t parentid)
-{
-	fuse_vnode_init_data(vp, fvdat, nodeid);
-	fuse_vnode_init_misc(vp, vtyp, parentid);
-}	
-
-void
-fuse_vnode_ditch(struct vnode *vp, struct thread *td)
-{
-	if (! td)
-		td = curthread;
-
-	if (vp->v_vflag & VV_ROOT) {
-		fdata_kick_set(fusefs_get_data(vp->v_mount));
-		return;
-	}
-	DEBUG2G("vp %p, #%llu\n", vp, VTOILLU(vp));
-	vnode_destroy_vobject(vp);
-	/*
-	 * this implies we won't get feedback on recycling
-	 * (other than panicking, or the lack of that)
-	 * but creating a customized set of bad vnode ops
-	 * would be too much hassle...
-	 */
-	vp->v_op = &dead_vnodeops;
-	fuse_recyc_backend(vp, td);
-}
-
-void
-fuse_vnode_teardown(struct vnode *vp, struct thread *td, struct ucred *cred,
-                 enum vtype vtyp)
-{
-	struct fuse_dispatcher fdi;
-	struct fuse_vnode_data *fvdat = VTOFUD(vp);
-
-	if (vp->v_type == vtyp) {
-		bzero(&fdi, sizeof(fdi));
-		vfs_hash_remove(vp);
-		fuse_internal_forget_send(vp->v_mount, td, cred, fvdat->nid,
-		                 fvdat->nlookup, &fdi);
-		fvdat->nid = FUSE_NULL_ID;
-	} else
-		fuse_vnode_ditch(vp, td);
-
-	vput(vp);
-}
-#endif
-
 /*
     struct vnop_access_args {
         struct vnode *a_vp;
@@ -2135,7 +1930,7 @@
 	((char *)fdi.indata)[cnp->cn_namelen] = '\0';
 	memcpy((char *)fdi.indata + cnp->cn_namelen + 1, target, len);
 
-	err = fuse_internal_newentry_core(dvp, vpp, VLNK, &fdi);
+	err = fuse_internal_newentry_core(dvp, vpp, cnp, VLNK, &fdi);
 	fuse_invalidate_attr(dvp);
 	return (err);
 }
@@ -2476,503 +2271,3 @@
 
 	return vop_stdunlock(ap);
 }
-
-static int
-release_filehandle(struct fuse_filehandle *fufh, struct thread *td,
-                   struct ucred *cred, void *param)
-{
-	KASSERT(fufh->useco >= 0,
-	        ("negative use count for fuse filehandle #%llu@#%llu",
-	         (long long unsigned)fufh->fh_id, VTOILLU(fufh->fh_vp)));
-	KASSERT(! fufh->fp || fufh->useco > 0,
-	        ("filehandle bound with 0 use counter"));
-	DEBUG2G("vnode #%llu, fufh %p #%llu, owner file %p, useco %d\n",
-	        VTOILLU(fufh->fh_vp), fufh, (long long unsigned) fufh->fh_id,
-	        fufh->fp, fufh->useco);
-	if (! fufh->fp && fufh->useco == 0) {
-		LIST_REMOVE(fufh, fh_link);
-		fuse_send_release(fufh, td, cred, fufh->mode, param);
-	}
-
-	return (0);		
-}
-
-static void
-fuse_filehandle_gc(struct vnode *vp, struct thread *td, struct ucred *cred,
-                   struct fuse_release_param *frp)
-{
-	ASSERT_VOP_ELOCKED__FH(vp);
-	iterate_filehandles(vp, td, cred, release_filehandle, frp);
-}
-
-static int
-iterate_filehandles(struct vnode *vp, struct thread *td, struct ucred *cred,
-		    fuse_metrics_t fmetr, void *param)
-{
-	struct fuse_filehandle *fufh, *fufhxxx;
-	struct fuse_vnode_data *fvdat = VTOFUD(vp);
-	int rv = 0;
-
-	RECTIFY_TDCR(td, cred);
-
-	LIST_FOREACH_SAFE(fufh, &fvdat->fh_head, fh_link, fufhxxx) {
-		KASSERT(fufh->fh_vp == vp,
-		        ("vnode mismatch for fuse_filehandle %p\n", fufh));
-		if ((rv = fmetr(fufh, td, cred, param)))
-			return (rv); 
-	}
-
-	return (0);
-}
-
-static int
-fuse_standard_metrics(struct fuse_filehandle *fufh, struct thread *td,
-                      struct ucred *cred, void *param)
-{
-	struct standard_metrics_param *stmp = param;
-
-	DEBUG2G("fufh->mode %#x, mode %#x\n", fufh->mode, stmp->mode);
-	if (fufh->cred->cr_uid == cred->cr_uid &&
-	    fufh->cred->cr_rgid == cred->cr_rgid &&
-	    fufh->pid == td->td_proc->p_pid &&
-	    ((fufh->mode ^ stmp->mode) & ~(O_CREAT | O_EXCL | O_TRUNC)) == 0 &&
-	    fufh->op == stmp->op) {
-		stmp->fufh = fufh;
-		fufh->useco++;
-		return (-1);
-	}
-
-	return (0);
-}
-
-#if FUSE_HAS_CREATE
-static __inline int
-create_filehandle(struct vnode *vp, struct thread *td, struct ucred *cred,
-                  int mode, struct fuse_dispatcher *fdip)
-{
-	struct fuse_vnode_data *fvdat = VTOFUD(vp);
-	uint64_t parentid = fvdat->parent_nid;
-	struct componentname *cnp = fvdat->germcnp;
-	struct fuse_open_in *foi;
-	struct fuse_entry_out *feo;
-	struct fuse_mknod_in fmni;
-	int err;
-	int gone_good_old = 0;
-	struct vnode *clashvp;
-
-	vp->v_data = NULL;
-	mode &= ~O_NOCTTY;
-
-	fdisp_init(fdip, sizeof(*foi) + cnp->cn_namelen + 1);
-
-	if (fusefs_get_data(vp->v_mount)->dataflag & FSESS_NOCREATE)
-		goto good_old;
-	fdisp_make(fdip, vp->v_mount, FUSE_CREATE, parentid, td, cred);
-
-	/*
-	 * Looks stupid, but this is how we could smuggle in these
-	 * values from fuse_create...
-	 */
-	foi = fdip->indata;
-	foi->flags = OFLAGS(mode);
-	foi->mode = fvdat->flags;
-
-	memcpy((char *)fdip->indata + sizeof(*foi), cnp->cn_nameptr,
-	       cnp->cn_namelen);
-	((char *)fdip->indata)[sizeof(*foi) + cnp->cn_namelen] = '\0';
-
-	err = fdisp_wait_answ(fdip);
-
-	if (err == ENOSYS) {
-		fusefs_get_data(vp->v_mount)->dataflag |= FSESS_NOCREATE;
-		fdip->tick = NULL;
-		goto good_old;
-	} else if (err)
-		goto undo;
-
-	goto bringup;
-
-good_old:
-	gone_good_old = 1;
-	fmni.mode = fvdat->flags;
-	fmni.rdev = 0;
-	fuse_internal_newentry_makerequest(vp->v_mount, parentid, cnp, FUSE_MKNOD,
-	                    &fmni, sizeof(fmni), fdip);
-	err = fdisp_wait_answ(fdip);
-	if (err)
-		goto undo;
-
-bringup:
-	feo = fdip->answ;
-	
-	if ((err = fuse_internal_checkentry(feo, VREG))) {
-		fuse_ticket_drop(fdip->tick);
-		goto undo;
-	}
-
-	bzero(fvdat, sizeof(*fvdat));
-	fuse_vnode_init(vp, fvdat, feo->nodeid, VREG, parentid);
-	fvdat->nlookup++;
-	vp->v_op = &fuse_vnops;
-	cache_attrs(vp, feo);
-
-try_insert:
-	VOP_UNLOCK(vp, 0);
-	/*
-	 * We can't let the vnode being vput() here, the caller wants
-	 * that do by herself.
-	 * That means hash collisions must be relaxed. With a funky
-	 * comparison function insertion will succeed, but we get a clear
-	 * sign of the collision and we can handle it by ourselves.
-	 */
-	err = vfs_hash_get(vp->v_mount, feo->nodeid, LK_EXCLUSIVE, td,
-	                   &clashvp, fuse_vnode_cmp, &feo->nodeid);
-	if (! err && clashvp)
-		fuse_vnode_teardown(clashvp, td, cred, VREG);
-
-	if (! err) {
-		err = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
-		if (err)
-			printf("fuse4bsd: leaking vnode %p\n", vp);
-		else {
-			struct mount *mp = vp->v_mount;
-
-			vp->v_mount = NULL;
-			err = insmntque(vp, mp);
-		}
-	}
-
-	if (! err)
-		err = vfs_hash_insert(vp, feo->nodeid, LK_EXCLUSIVE, td,
-		                      &clashvp, fuse_vnode_fgdrop_cmp, fvdat);
-	if (! err && fvdat->nid == FUSE_NULL_ID) {
-		vfs_hash_remove(vp);
-		fvdat->nid = feo->nodeid;
-		goto try_insert;
-	}
-
-	if (err) {
-		if (gone_good_old)
-			fuse_internal_forget_send(vp->v_mount, td, cred, feo->nodeid, 1,
-			                 fdip);
-		else {
-			struct fuse_release_in *fri;
-			uint64_t nodeid = feo->nodeid;
-			uint64_t fh_id = ((struct fuse_open_out *)(feo + 1))->fh;
-			struct fuse_pidcred *pidcred;
-
-			fdisp_init(fdip, sizeof(*fri));
-			fdisp_make(fdip, vp->v_mount, FUSE_RELEASE, nodeid, td,
-			           cred);
-			fri = fdip->indata;
-			fri->fh = fh_id;
-			fri->flags = OFLAGS(mode);
-			/*
-			 * The node must be forgotten after the release.
-			 * Release is sent in the background as usual (that's not
-			 * necessary, but anyway...), so we do the forgetting
-			 * by a dedicated callback handler.
-			 *
-			 * Current pid/cred is attached to the ticket as a parameter
-			 * as the FORGET must be sent with current pid/cred but
-			 * it will be sent from another context.
-			 */
-			fiov_adjust(&fdip->tick->tk_aw_handler_parm,
-			            sizeof(*pidcred));
-			pidcred = fdip->tick->tk_aw_handler_parm.base;
-			pidcred->pid = td->td_proc->p_pid;
-			memcpy(&pidcred->cred, cred, sizeof(*cred));
-			fuse_insert_callback(fdip->tick, fuse_internal_forget_callback);
-			fuse_insert_message(fdip->tick);
-		}
-
-		return (err);
-	}
-
-	fdip->answ = gone_good_old ? NULL : feo + 1;
-
-	return (0);
-
-undo:
-	free(fvdat, M_FUSEVN);
-	vp->v_data = NULL;
-	return (err);
-}
-#endif
-
-int
-fuse_get_filehandle(struct vnode *vp, struct thread *td, struct ucred *cred,
-               int mode, struct fuse_filehandle **fufhp,
-               struct get_filehandle_param *gefhp)
-{
-	struct fuse_vnode_data *fvdat = VTOFUD(vp);
-	struct fuse_dispatcher fdi;
-	struct fuse_open_in *foi;
-	struct fuse_open_out *foo;
-	int err = 0;
-	struct fuse_filehandle *fufh = NULL;
-	enum fuse_opcode op;
-	int gone_create = 0;
-
-	RECTIFY_TDCR(td, cred);
-
-	/*
-	 * "create" messaging is almost transparent for get_filehandle. There are
-	 * some gotos and status variables though.
-	 * And it's totally transparent for fuse_open.
-	 * (By transparent I mean that they don't see the special "germic" state of
-	 * the vnode... if the vnode is a germ, it will be tried to be initialized
-	 * via a dedicated method, but from that on we go on as usual.)
-	 */
-#if FUSE_HAS_CREATE
-	if (vp->v_op == &fuse_germ_vnops) {
-		KASSERT(gefhp, ("create_filehandle called without get_filehandle_param"));
-		gone_create = 1;
-		if (gefhp)
-			gefhp->do_gc = 0;
-		op = FUSE_OPEN;
-		fdi.answ = NULL;
-		if ((err = create_filehandle(vp, td, cred, mode, &fdi)))
-			goto out;
-		else if (fdi.answ)
-			goto setup_filehandle;
-	}
-#endif
-
-	if (gefhp && gefhp->opcode)
-		op = gefhp->opcode;
-	else
-        	op = FUSE_OPEN;
-
-	if (op == FUSE_OPENDIR)
-		mode = FREAD;
-	else
-		mode &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
-
-	if (! (gefhp && gefhp->do_new)) {
-		struct standard_metrics_param stmp;
-		stmp.mode = mode;
-		stmp.op = op;
-
-		ASSERT_VOP_LOCKED__FH(vp);
-		err = iterate_filehandles(vp, td, cred, fuse_standard_metrics,
-		                          &stmp);
-
-		if (err) {
-			if (err == -1) {
-				DEBUG2G("suitable fh of vnode #%llu found\n",
-				        VTOILLU(vp));
-				fufh = stmp.fufh;
-				err = 0;
-			}
-			goto out;
-		}
-	}
-
-	DEBUG2G("we need to fetch a new filehandle for vnode #%llu\n", VTOILLU(vp));
-
-	fdisp_init(&fdi, sizeof(*foi));
-	fdisp_make_vp(&fdi, op, vp, td, cred);
-
-	foi = fdi.indata;
-	foi->flags = OFLAGS(mode);
-
-	if ((err = fdisp_wait_answ(&fdi)))
-		goto out;
-
-#if FUSE_HAS_CREATE
-setup_filehandle:
-#endif
-	foo = fdi.answ;
-
-	fufh = malloc(sizeof(*fufh), M_FUSEFH, M_WAITOK | M_ZERO);
-
-	/*
-	 * We need to reference the vnode from fuse private file data
-	 * as files' f_vnode field might point to another vnode (eg.,
-	 * if we are accessed through a nullfs overlay).
-	 */
-	fufh->fh_vp = vp;
-	fufh->fh_id = foo->fh;
-	fufh->flags = foo->open_flags;
-
-	fuse_ticket_drop(fdi.tick);
-
-	fufh->mode = mode;
-	fufh->cred = crhold(cred);
-	fufh->pid = td->td_proc->p_pid;
-	fufh->useco = 1;
-	fufh->op = op;
-
-	ASSERT_VOP_ELOCKED__FH(vp);
-	LIST_INSERT_HEAD(&fvdat->fh_head, fufh, fh_link);
-	if (gefhp && gefhp->do_gc) {
-		/*
-		 * The neat idea is that a cache cleanup is the best time for
-		 * a gc -- gc'ing unbound filehandles at inactive/reclaim time
-		 * is not enough, they can just accumulate while something
-		 * happens with the file, given the cache is flushed frequently
-		 * (otherwise there is no reason for the system to spawn them,
-		 * as the data can be read from core).
-		 * So then, let's just tie their gc to cache flush...
-		 * Luckily, this won't break the POSIX semantics that an
-		 * unlinked file is get kept until there is reference to it,
-		 * because that's done via the lookup/forget mechanism, and not
-		 * via filehandles.
-		 */
-		/*
-		 * Now we use unbound filehandles pretty rarely (as read/write
-		 * of regular files doesn't rely on them anymore), only during
-		 * exec and reading directories. It's pretty much unlikely that
-		 * one can be reused in any way, so we drop them
-		 * unconditionally.
-		 */
-		struct fuse_release_param frp;
-
-		DEBUG2G("gc'ing...\n");
-		frp.fg = 0;
-		frp.flush = 0;
-		iterate_filehandles(vp, td, cred, release_filehandle, &frp);
-	}
-	fvdat->fh_counter++;
-
-#if _DEBUG2G
-	if (gefhp && gefhp->do_gc) {
-		DEBUG2G("after gc...\n");
-		vn_printf(vp, " ");
-	}
-#endif
-
-out:
-	if (gone_create && ! err)
-		fufh->flags |= FOPEN_KEEP_CACHE;
-
-	*fufhp = fufh;
-
-	return (err);
-}
-
-static void
-fuse_send_release(struct fuse_filehandle *fufh, struct thread *td,
-                  struct ucred *cred, int flags, struct fuse_release_param *frp)
-{
-	struct vnode *vp = fufh->fh_vp;
-	struct fuse_dispatcher fdi;
-	struct fuse_release_in *fri;
-	int err = 0;
-
-	KASSERT(! fufh->fp && fufh->useco == 0, ("active-looking fuse filehandle was attempted to release"));
-
-	VTOFUD(vp)->fh_counter--;
-	DEBUG2G("filehandle of vnode #%llu being released, fh counter now is %d\n",
-	         VTOILLU(vp), VTOFUD(vp)->fh_counter);
-
-	if (vp->v_type == VBAD)
-		goto out;
-
-	fdisp_init(&fdi, sizeof(*fri));
-	fdisp_make_vp(&fdi,
-	              fufh->op == FUSE_OPENDIR ? FUSE_RELEASEDIR : FUSE_RELEASE,
-	              vp, td, cred);
-	fri = fdi.indata;
-	fri->fh = fufh->fh_id;
-	fri->flags = OFLAGS(flags);
-#if FUSE_HAS_FLUSH_RELEASE
-	if (frp->flush)
-		fri->release_flags = FUSE_RELEASE_FLUSH;
-#endif
-
-	if (frp->fg) {
-		err = fdisp_wait_answ(&fdi);
-		if (err)
-			goto out;
-		else
-			fuse_ticket_drop(fdi.tick);
-	} else {
-		fuse_insert_callback(fdi.tick, NULL);
-		fuse_insert_message(fdi.tick);
-	}
-
-out:
-	crfree(fufh->cred);
-	free(fufh, M_FUSEFH);
-	if (err && frp->err == 0)
-		frp->err = err;
-}
-
-static int
-fuse_close_f(struct file *fp, struct thread *td)
-{
-	struct fuse_filehandle *fufh;
-	struct vnode *vp = NULL, *ovl_vp = fp->f_vnode;
-	struct fuse_release_param frp;
-
-	if (! _file_is_fat(fp))
-		panic("non-fat file passed to close routine");
-
-	vn_lock(ovl_vp, LK_EXCLUSIVE | LK_RETRY);
-
-	if (_file_is_bad(fp)) {
-		DEBUG2G("fp %p, (overlay) vnode %p: went bad, giving up\n",
-		        fp, ovl_vp);
-		goto out;
-	}
-	fufh = FTOFH(fp);
-	vp = fufh->fh_vp;
-	KASSERT(fufh->fp == fp, ("file's filehandle is stolen"));
-	DEBUG2G("vnode #%llu, fufh owner %p, useco %d\n",
-	        VTOILLU(vp), fp, fufh->useco);
-
-	fufh->useco--;
-	ASSERT_VOP_ELOCKED__FH(vp);
-	fufh->fp = NULL;
-	if (fufh->useco == 0)
-		LIST_REMOVE(fufh, fh_link);
-	fp->f_data = NULL;
-
-	if (fufh->useco == 0) {
-		frp.err = 0;
-#if FUSE_HAS_FLUSH_RELEASE
-		frp.fg = 1;
-		frp.flush = 1;
-#else
-		frp.fg = 0;
-		frp.flush = 0;
-#endif
-		fuse_send_release(fufh, td, NULL, fp->f_flag & ~O_EXCL, &frp);
-	}
-
-out:
-	if (fp->f_flag & FWRITE && vp)
-                vp->v_writecount--;
-	vput(ovl_vp);
-	return (frp.err);
-}
-
-static int 
-fuse_fsync_filehandle(struct fuse_filehandle *fufh, struct thread *td,
-                      struct ucred *cred, void *param)
-{
-	struct fuse_fsync_in *ffsi;
-	struct fuse_dispatcher *fdip = param;
-
-	fdip->iosize = sizeof(*ffsi);
-	fdip->tick = NULL;
-	fdisp_make_vp(fdip,
-	              (fufh->op == FUSE_OPENDIR) ? FUSE_FSYNCDIR : FUSE_FSYNC,
-	              fufh->fh_vp, td, cred);
-
-	ffsi = fdip->indata;
-	ffsi->fh = fufh->fh_id;
-	/*
-	 * this sets that we wanna sync file data,
-	 * not just metadata; a 0 value would have no
-	 * counterpart in BSD semantics
-	 */
-	ffsi->fsync_flags = 1;
-  
-	fuse_insert_callback(fdip->tick, fuse_internal_fsync_callback);
-	fuse_insert_message(fdip->tick);
-
-	return (0);
-}


More information about the p4-projects mailing list