Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/lib/libperfuse - Postpone file close at reclaim time, since ...



details:   https://anonhg.NetBSD.org/src/rev/0a392d0e019d
branches:  trunk
changeset: 757538:0a392d0e019d
user:      manu <manu%NetBSD.org@localhost>
date:      Fri Sep 03 07:15:18 2010 +0000

description:
- Postpone file close at reclaim time, since NetBSD sends fsync and
setattr(mtime, ctime) after close, while FUSE expects the file
to be open for these operations

- remove unused argument to node_mk_common()

- remove requeued requests when they are executed, not when they
are tagged for schedule

- try to make filehandle management simplier, by keeping track of only
one read and one write filehandle (the latter being really read/write).

- when CREATE is not available, we use the MKNOD/OPEN path. Fix a
bug here where we opened the parent directory instead of the node:
add the missing lookup of the mknod'ed node.

- lookup file we just created: glusterfs does not really see them
otherwise.

- open file when doing setattr(mtime, ctime) on non open files, as
some filesystems seems to require it.

- Do not flush pagecache for removed nodes

- Keep track of read/write operations in progress, and at reclaim
time, make sure they are over before closing and forgeting the file.

diffstat:

 lib/libperfuse/ops.c          |  442 ++++++++++++++++++++++++++---------------
 lib/libperfuse/perfuse_priv.h |   31 +-
 lib/libperfuse/subr.c         |   85 ++++---
 3 files changed, 347 insertions(+), 211 deletions(-)

diffs (truncated from 1064 to 300 lines):

diff -r 22d89e05acf4 -r 0a392d0e019d lib/libperfuse/ops.c
--- a/lib/libperfuse/ops.c      Fri Sep 03 07:12:51 2010 +0000
+++ b/lib/libperfuse/ops.c      Fri Sep 03 07:15:18 2010 +0000
@@ -1,4 +1,4 @@
-/*  $NetBSD: ops.c,v 1.6 2010/09/02 08:58:06 manu Exp $ */
+/*  $NetBSD: ops.c,v 1.7 2010/09/03 07:15:18 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved.
@@ -41,6 +41,7 @@
 #include "perfuse_priv.h"
 #include "fuse.h"
 
+static int node_close_common(struct puffs_usermount *, puffs_cookie_t, int);
 static int no_access(puffs_cookie_t, const struct puffs_cred *, mode_t);
 static void fuse_attr_to_vap(struct perfuse_state *,
     struct vattr *, struct fuse_attr *);
@@ -74,6 +75,7 @@
  */
 #define F_WAIT         0x010
 #define F_FLOCK                0x020
+#define OFLAGS(fflags)  ((fflags) - 1)
 
 /* 
  * Borrowed from src/sys/kern/vfs_subr.c and src/sys/sys/vnode.h 
@@ -90,6 +92,74 @@
 #define IFTOVT(mode) (iftovt_tab[((mode) & S_IFMT) >> 12])
 #define VTTOIF(indx) (vttoif_tab[(int)(indx)])
 
+static int
+node_close_common(pu, opc, mode)
+       struct puffs_usermount *pu;
+       puffs_cookie_t opc;
+       int mode;
+{
+       struct perfuse_state *ps;
+       perfuse_msg_t *pm;
+       int op;
+       uint64_t fh;
+       struct fuse_release_in *fri;
+       struct perfuse_node_data *pnd;
+       struct puffs_node *pn;
+       int error;
+
+       ps = puffs_getspecific(pu);
+       pn = (struct puffs_node *)opc;
+       pnd = PERFUSE_NODE_DATA(pn);
+
+       if (puffs_pn_getvap(pn)->va_type == VDIR) {
+               op = FUSE_RELEASEDIR;
+               mode = FREAD;
+       } else {
+               op = FUSE_RELEASE;
+       }
+
+       /*
+        * Destroy the filehandle before sending the 
+        * request to the FUSE filesystem, otherwise 
+        * we may get a second close() while we wait
+        * for the reply, and we would end up closing
+        * the same fh twice instead of closng both.
+        */
+       fh = perfuse_get_fh(opc, mode);
+       perfuse_destroy_fh(pn, fh);
+
+       /*
+        * release_flags may be set to FUSE_RELEASE_FLUSH
+        * to flush locks. lock_owner must be set in that case
+        */
+       pm = ps->ps_new_msg(pu, opc, op, sizeof(*fri), NULL);
+       fri = GET_INPAYLOAD(ps, pm, fuse_release_in);
+       fri->fh = fh;
+       fri->flags = 0;
+       fri->release_flags = 0;
+       fri->lock_owner = pnd->pnd_lock_owner;
+       fri->flags = (fri->lock_owner != 0) ? FUSE_RELEASE_FLUSH : 0;
+
+#ifdef PERFUSE_DEBUG
+       if (perfuse_diagflags & PDF_FH)
+               DPRINTF("%s: opc = %p, ino = %"PRId64", fh = 0x%"PRIx64"\n",
+                        __func__, (void *)opc, pnd->pnd_ino, fri->fh);
+#endif
+
+       if ((error = XCHG_MSG(ps, pu, pm, NO_PAYLOAD_REPLY_LEN)) != 0)
+               goto out;
+
+       ps->ps_destroy_msg(pm);
+
+       error = 0;
+
+out:
+       if (error != 0)
+               DERRX(EX_SOFTWARE, "%s: freed fh = 0x%"PRIx64" but filesystem "
+                     "returned error = %d", __func__, fh, error);
+
+       return error;
+}
 
 static int
 no_access(opc, pcr, mode)
@@ -802,6 +872,19 @@
        int error;
        
        /*
+        * Special case for ..
+        */
+       if (PCNISDOTDOT(pcn)) {
+               pn = PERFUSE_NODE_DATA(opc)->pnd_parent;
+               PERFUSE_NODE_DATA(pn)->pnd_flags &= ~PND_RECLAIMED;
+               
+               puffs_newinfo_setcookie(pni, pn);
+               puffs_newinfo_setvtype(pni, VDIR);
+
+               return 0;
+       }
+
+       /*
         * XXX This is borrowed from librefuse, 
         * and __UNCONST is said to be fixed.
         */
@@ -866,6 +949,12 @@
                if (error != 0)
                        return error;
 
+               error = node_lookup_common(pu, opc, (char*)PCNPATH(pcn), &pn);
+               if (error != 0) 
+                       return error;
+
+               opc = (puffs_cookie_t)pn;
+
                error = perfuse_node_open(pu, opc, FREAD|FWRITE, pcn->pcn_cred);
                if (error != 0) 
                        return error;
@@ -898,12 +987,26 @@
         * so that we can reuse it later
         */
        pn = perfuse_new_pn(pu, opc);
-       perfuse_new_fh((puffs_cookie_t)pn, foo->fh);
+       perfuse_new_fh((puffs_cookie_t)pn, foo->fh, FWRITE);
        PERFUSE_NODE_DATA(pn)->pnd_ino = feo->nodeid;
 
+#ifdef PERFUSE_DEBUG
+       if (perfuse_diagflags & PDF_FH)
+               DPRINTF("%s: opc = %p, file = \"%s\", "
+                       "ino = %"PRId64", rfh = 0x%"PRIx64"\n",
+                       __func__, (void *)pn, (char *)PCNPATH(pcn),
+                       feo->nodeid, foo->fh);
+#endif
+
        fuse_attr_to_vap(ps, &pn->pn_va, &feo->attr);
        puffs_newinfo_setcookie(pni, pn);
 
+       /*
+        * It seems we need to do this so that glusterfs gets fully
+        * aware that the file was created. If we do not do it, we 
+        * get "SETATTR (null) (fuse_loc_fill() failed)"
+        */
+       (void)node_lookup_common(pu, opc, (char*)PCNPATH(pcn), NULL);
 out: 
        ps->ps_destroy_msg(pm);
 
@@ -979,8 +1082,10 @@
        const struct puffs_cred *pcr;
 {
        struct perfuse_state *ps;
+       struct perfuse_node_data *pnd;
        perfuse_msg_t *pm;
        mode_t pmode;
+       mode_t fmode;
        int op;
        struct fuse_open_in *foi;
        struct fuse_open_out *foo;
@@ -988,6 +1093,7 @@
        int error;
        
        ps = puffs_getspecific(pu);
+       pnd = PERFUSE_NODE_DATA(opc);
 
        pn = (struct puffs_node *)opc;
        if (puffs_pn_getvap(pn)->va_type == VDIR) {
@@ -995,8 +1101,8 @@
                pmode = PUFFS_VREAD|PUFFS_VEXEC;
        } else {
                op = FUSE_OPEN;
-               if (mode & (O_RDWR|O_WRONLY))
-                       pmode = PUFFS_VWRITE;
+               if (mode & FWRITE)
+                       pmode = PUFFS_VWRITE|PUFFS_VREAD;
                else
                        pmode = PUFFS_VREAD;
        }
@@ -1006,8 +1112,7 @@
         * Opening a file requires R-- for reading, -W- for writing
         * In both cases, --X is required on the parent.
         */
-       if (no_access((puffs_cookie_t)PERFUSE_NODE_DATA(opc)->pnd_parent,
-           pcr, PUFFS_VEXEC))
+       if (no_access((puffs_cookie_t)pnd->pnd_parent, pcr, PUFFS_VEXEC))
                return EACCES;
 
        if (no_access(opc, pcr, pmode))
@@ -1017,23 +1122,30 @@
         * libfuse docs say O_CREAT should not be set.
         */
        mode &= ~O_CREAT;
-               
+
+       /*
+        * Do not open twice, and do not reopen for reading
+        * if we already have write handle.
+        * Directories are always open with read access only, 
+        * whatever flags we get.
+        */
+       if (op == FUSE_OPENDIR)
+               mode = (mode & ~(FREAD|FWRITE)) | FREAD;
+       if ((mode & FREAD) && (pnd->pnd_flags & PND_RFH))
+               return 0;
+       if ((mode & FWRITE) && (pnd->pnd_flags & PND_WFH))
+               return 0;
+
+       /*
+        * Convert PUFFS mode to FUSE mode: convert FREAD/FWRITE
+        * to O_RDONLY/O_WRONLY while perserving the other options.
+        */
+       fmode = mode & ~(FREAD|FWRITE);
+       fmode |= (mode & FWRITE) ? O_RDWR : O_RDONLY;
+
        pm = ps->ps_new_msg(pu, opc, op, sizeof(*foi), pcr);
        foi = GET_INPAYLOAD(ps, pm, fuse_open_in);
-       foi->flags = mode & ~O_ACCMODE; 
-       switch (mode & (FREAD|FWRITE)) {
-       case FREAD|FWRITE:
-               foi->flags |= O_RDWR;
-               break;
-       case FREAD:
-               foi->flags |= O_RDONLY;
-               break;
-       case FWRITE:
-               foi->flags |= O_WRONLY;
-               break;
-       default:
-               break;
-       }
+       foi->flags = fmode;
        foi->unused = 0;
 
        if ((error = XCHG_MSG(ps, pu, pm, sizeof(*foo))) != 0)
@@ -1045,15 +1157,16 @@
         * Save the file handle in node private data 
         * so that we can reuse it later
         */
-       perfuse_new_fh((puffs_cookie_t)pn, foo->fh);
+       perfuse_new_fh((puffs_cookie_t)pn, foo->fh, mode);
 
 #ifdef PERFUSE_DEBUG
        if (perfuse_diagflags & PDF_FH)
                DPRINTF("%s: opc = %p, file = \"%s\", "
-                       "ino = %"PRId64", fh = 0x%"PRIx64"\n",
+                       "ino = %"PRId64", %s%sfh = 0x%"PRIx64"\n",
                        __func__, (void *)opc, 
                        (char *)PNPATH((struct puffs_node *)opc),
-                       PERFUSE_NODE_DATA(opc)->pnd_ino, foo->fh);
+                       pnd->pnd_ino, mode & FREAD ? "r" : "",
+                       mode & FWRITE ? "w" : "", foo->fh);
 #endif
 out:
        ps->ps_destroy_msg(pm);
@@ -1061,7 +1174,7 @@
        return error;
 }
 
-/* ARGSUSED2 */
+/* ARGSUSED0 */
 int
 perfuse_node_close(pu, opc, flags, pcr)
        struct puffs_usermount *pu;
@@ -1069,95 +1182,34 @@
        int flags;
        const struct puffs_cred *pcr;
 {
-       struct perfuse_state *ps;
-       perfuse_msg_t *pm;
-       int op;
-       uint64_t fh;
+       struct puffs_node *pn;
        struct perfuse_node_data *pnd;
-       struct fuse_release_in *fri;
-       struct puffs_node *pn;
-       int error;
-       
-       ps = puffs_getspecific(pu);
+
        pn = (struct puffs_node *)opc;
-       pnd = PERFUSE_NODE_DATA(pn);
-
-       if (puffs_pn_getvap(pn)->va_type == VDIR)
-               op = FUSE_RELEASEDIR;
-       else
-               op = FUSE_RELEASE;
+       pnd = PERFUSE_NODE_DATA(opc);



Home | Main Index | Thread Index | Old Index