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