Source-Changes-HG archive

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

[src/trunk]: src/lib/libperfuse - performance improvement for read, readdir a...



details:   https://anonhg.NetBSD.org/src/rev/b3ea66bbed98
branches:  trunk
changeset: 757735:b3ea66bbed98
user:      manu <manu%NetBSD.org@localhost>
date:      Mon Sep 20 07:00:21 2010 +0000

description:
- performance improvement for read, readdir and write. Now we use
SOCK_DGRAM, we can send many pages at once without hitting any bug

- when creating a file, it is open for FUSE, but not for the kernel.
If the kernel does not do a subsequent open, we have a leak. We fight
against this by trying to close such file that the kernel left unopen
for some time.

- some code refactoring to make message exchange debug easier (more to come)

diffstat:

 lib/libperfuse/ops.c          |  250 +++++++++++++++++++++++++----------------
 lib/libperfuse/perfuse.c      |   23 ++-
 lib/libperfuse/perfuse_priv.h |   48 +++++---
 lib/libperfuse/subr.c         |   49 +++++++-
 4 files changed, 241 insertions(+), 129 deletions(-)

diffs (truncated from 943 to 300 lines):

diff -r 3bcd98e17ef5 -r b3ea66bbed98 lib/libperfuse/ops.c
--- a/lib/libperfuse/ops.c      Mon Sep 20 06:54:06 2010 +0000
+++ b/lib/libperfuse/ops.c      Mon Sep 20 07:00:21 2010 +0000
@@ -1,4 +1,4 @@
-/*  $NetBSD: ops.c,v 1.15 2010/09/15 01:51:43 manu Exp $ */
+/*  $NetBSD: ops.c,v 1.16 2010/09/20 07:00:21 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved.
@@ -43,7 +43,8 @@
 
 extern int perfuse_diagflags;
 
-static int node_close_common(struct puffs_usermount *, puffs_cookie_t, int);
+static int xchg_msg(struct puffs_usermount *, puffs_cookie_t, 
+    perfuse_msg_t *, size_t, enum perfuse_xchg_pb_reply); 
 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 *);
@@ -94,8 +95,8 @@
 #define IFTOVT(mode) (iftovt_tab[((mode) & S_IFMT) >> 12])
 #define VTTOIF(indx) (vttoif_tab[(int)(indx)])
 
-static int
-node_close_common(pu, opc, mode)
+int
+perfuse_node_close_common(pu, opc, mode)
        struct puffs_usermount *pu;
        puffs_cookie_t opc;
        int mode;
@@ -148,7 +149,8 @@
                         __func__, (void *)opc, pnd->pnd_ino, fri->fh);
 #endif
 
-       if ((error = XCHG_MSG(ps, pu, pm, NO_PAYLOAD_REPLY_LEN)) != 0)
+       if ((error = xchg_msg(pu, opc, pm,
+                             NO_PAYLOAD_REPLY_LEN, wait_reply)) != 0)
                goto out;
 
        ps->ps_destroy_msg(pm);
@@ -163,6 +165,30 @@
        return error;
 }
 
+/* ARGSUSED1 */
+static int
+xchg_msg(pu, opc, pm, len, wait)
+       struct puffs_usermount *pu;
+       puffs_cookie_t opc;
+       perfuse_msg_t *pm;
+       size_t len;
+       enum perfuse_xchg_pb_reply wait;
+{
+       struct perfuse_state *ps;
+       int error;
+
+       ps = puffs_getspecific(pu);
+
+#ifdef PERFUSE_DEBUG
+       if ((perfuse_diagflags & PDF_FUSE) && (opc != 0))
+               DPRINTF("file = \"%s\"\n", 
+                       (char *)PNPATH((struct puffs_node *)opc));
+#endif
+       error = ps->ps_xchg_msg(pu, pm, len, wait);
+
+       return error;
+}
+
 static int
 no_access(opc, pcr, mode)
        puffs_cookie_t opc;
@@ -285,7 +311,7 @@
        pm = ps->ps_new_msg(pu, opc, FUSE_LOOKUP, len, NULL);
        (void)strlcpy(_GET_INPAYLOAD(ps, pm, char *), path, len);
 
-       if ((error = XCHG_MSG(ps, pu, pm, sizeof(*feo))) != 0)
+       if ((error = xchg_msg(pu, opc, pm, sizeof(*feo), wait_reply)) != 0)
                goto out;
 
        feo = GET_OUTPAYLOAD(ps, pm, fuse_entry_out);
@@ -327,7 +353,7 @@
 
        ps =  puffs_getspecific(pu);
 
-       if ((error = XCHG_MSG(ps, pu, pm, sizeof(*feo))) != 0)
+       if ((error = xchg_msg(pu, opc, pm, sizeof(*feo), wait_reply)) != 0)
                goto out;
 
        feo = GET_OUTPAYLOAD(ps, pm, fuse_entry_out);
@@ -357,7 +383,8 @@
        /*
         * A fuse_attr_out is returned, but we ignore it.
         */
-       error = XCHG_MSG(ps, pu, pm, sizeof(struct fuse_attr_out));
+       error = xchg_msg(pu, (puffs_cookie_t)pn, 
+                        pm, sizeof(struct fuse_attr_out), wait_reply);
 
        /*
         * The parent directory needs a sync
@@ -604,9 +631,6 @@
        ps = perfuse_getspecific(pu);
 #endif
 
-       /*
-        * XXX Add a lock he day we go multithreaded
-        */
        pnd = PERFUSE_NODE_DATA(opc);
        pcq.pcq_type = type;
        pcq.pcq_cc = puffs_cc_getcc(pu);
@@ -644,9 +668,6 @@
        struct perfuse_node_data *pnd;
        int dequeued;
 
-       /*
-        * XXX Add a lock he day we go multithreaded
-        */
        pnd = PERFUSE_NODE_DATA(opc);
        dequeued = 0;
        TAILQ_FOREACH(pcq, &pnd->pnd_pcq, pcq_next) {
@@ -684,7 +705,7 @@
        int error;
 
        ps = puffs_getspecific(pu);
-
+       
         if (puffs_mount(pu, ps->ps_target, ps->ps_mountflags, ps->ps_root) != 0)
                 DERR(EX_OSERR, "puffs_mount failed");
 
@@ -702,7 +723,7 @@
        fii->max_readahead = 32 * PAGE_SIZE; 
        fii->flags = (FUSE_ASYNC_READ|FUSE_POSIX_LOCKS|FUSE_ATOMIC_O_TRUNC);
 
-       if ((error = XCHG_MSG(ps, pu, pm, sizeof(*fio))) != 0)
+       if ((error = xchg_msg(pu, 0, pm, sizeof(*fio), wait_reply)) != 0)
                DERRX(EX_SOFTWARE, "init message exchange failed (%d)", error);
 
        fio = GET_OUTPAYLOAD(ps, pm, fuse_init_out);
@@ -729,7 +750,7 @@
        opc = (puffs_cookie_t)puffs_getroot(pu);
        pm = ps->ps_new_msg(pu, opc, FUSE_DESTROY, 0, NULL);
 
-       if ((error = XCHG_MSG(ps, pu, pm, UNSPEC_REPLY_LEN)) != 0) {
+       if ((error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply)) != 0){
                DWARN("unmount %s", ps->ps_target);
                if (!(flags & MNT_FORCE))
                        goto out;
@@ -759,7 +780,7 @@
        opc = (puffs_cookie_t)puffs_getroot(pu);
        pm = ps->ps_new_msg(pu, opc, FUSE_STATFS, 0, NULL);
 
-       if ((error = XCHG_MSG(ps, pu, pm, sizeof(*fso))) != 0)
+       if ((error = xchg_msg(pu, opc, pm, sizeof(*fso), wait_reply)) != 0)
                goto out;
 
        fso = GET_OUTPAYLOAD(ps, pm, fuse_statfs_out);
@@ -964,10 +985,17 @@
 
                opc = (puffs_cookie_t)pn;
 
-               error = perfuse_node_open(pu, opc, FREAD|FWRITE, pcn->pcn_cred);
+               error = perfuse_node_open(pu, opc, FWRITE, pcn->pcn_cred);
                if (error != 0) 
                        return error;
 
+               /*
+                * This node has been open in the filesystem,
+                * but not by the kernel. We will have to close
+                * it on our own to avoid a leak
+                */
+               PERFUSE_NODE_DATA(opc)->pnd_flags |= PND_OPENFS;
+
                return 0;
        }
 
@@ -989,7 +1017,7 @@
        (void)strlcpy((char*)(void *)(fci + 1), name, namelen);
 
        len = sizeof(*feo) + sizeof(*foo);
-       if ((error = XCHG_MSG(ps, pu, pm, len)) != 0)
+       if ((error = xchg_msg(pu, opc, pm, len, wait_reply)) != 0)
                goto out;
 
        feo = GET_OUTPAYLOAD(ps, pm, fuse_entry_out);
@@ -1002,7 +1030,7 @@
         * so that we can reuse it later
         */
        pn = perfuse_new_pn(pu, opc);
-       perfuse_new_fh((puffs_cookie_t)pn, foo->fh, FWRITE);
+       perfuse_new_fh(pu, (puffs_cookie_t)pn, foo->fh, FWRITE);
        PERFUSE_NODE_DATA(pn)->pnd_ino = feo->nodeid;
 
 #ifdef PERFUSE_DEBUG
@@ -1020,6 +1048,14 @@
         * The parent directory needs a sync
         */
        PERFUSE_NODE_DATA(opc)->pnd_flags |= PND_DIRTY;
+
+       /*
+        * This node has been open in the filesystem,
+        * but not by the kernel. We will have to close
+        * it on our own to avoid a leak
+        */
+       PERFUSE_NODE_DATA(pn)->pnd_flags |= PND_OPENFS;
+
 out: 
        ps->ps_destroy_msg(pm);
 
@@ -1113,6 +1149,14 @@
 
        pn = (struct puffs_node *)opc;
        if (puffs_pn_getvap(pn)->va_type == VDIR) {
+               /*
+                * We may open removed files, but it seems much more 
+                * troublesome to open removed directories. glusterfs says 
+                * "OPENDIR (null) (fuse_loc_fill() failed)"
+                */
+               if (pnd->pnd_flags & PND_REMOVED)
+                       return ENOENT;
+
                op = FUSE_OPENDIR;
                pmode = PUFFS_VREAD|PUFFS_VEXEC;
        } else {
@@ -1143,10 +1187,20 @@
         * Do not open twice, and do not reopen for reading
         * if we already have write handle.
         */
-       if ((mode & FREAD) && (pnd->pnd_flags & PND_RFH))
+       if (((mode & FREAD) && (pnd->pnd_flags & PND_RFH)) ||
+           ((mode & FWRITE) && (pnd->pnd_flags & PND_WFH))) {
+               /*
+                * If the file was created, it was open for
+                * the filesystem but not for the kernel. This
+                * is not the case anymore, therefore we cleanup
+                * the flag to avoid an unwanted cleanup close
+                * after PERFUSE_OPENFS_TIMEOUT.
+                */
+               pnd->pnd_flags &= ~PND_OPENFS;
+
                return 0;
-       if ((mode & FWRITE) && (pnd->pnd_flags & PND_WFH))
-               return 0;
+       }
+       
 
        /*
         * Convert PUFFS mode to FUSE mode: convert FREAD/FWRITE
@@ -1160,16 +1214,16 @@
        foi->flags = fmode;
        foi->unused = 0;
 
-       if ((error = XCHG_MSG(ps, pu, pm, sizeof(*foo))) != 0)
+       if ((error = xchg_msg(pu, opc, pm, sizeof(*foo), wait_reply)) != 0)
                goto out;
 
        foo = GET_OUTPAYLOAD(ps, pm, fuse_open_out);
-       
+
        /*
         * Save the file handle in node private data 
         * so that we can reuse it later
         */
-       perfuse_new_fh((puffs_cookie_t)pn, foo->fh, mode);
+       perfuse_new_fh(pu, (puffs_cookie_t)pn, foo->fh, mode);
 
 #ifdef PERFUSE_DEBUG
        if (perfuse_diagflags & PDF_FH)
@@ -1180,6 +1234,7 @@
                        pnd->pnd_ino, mode & FREAD ? "r" : "",
                        mode & FWRITE ? "w" : "", foo->fh);
 #endif
+
 out:
        ps->ps_destroy_msg(pm);
 
@@ -1210,7 +1265,7 @@
         * therefore postpone the close operation at reclaim time.
         */
        if (puffs_pn_getvap(pn)->va_type != VREG)
-               return node_close_common(pu, opc, flags);
+               return perfuse_node_close_common(pu, opc, flags);
 
        return 0;
 }
@@ -1243,7 +1298,7 @@
                fai = GET_INPAYLOAD(ps, pm, fuse_access_in);
                fai->mask = mode;
 
-               error = XCHG_MSG(ps, pu, pm, NO_PAYLOAD_REPLY_LEN);
+               error = xchg_msg(pu, opc, pm, NO_PAYLOAD_REPLY_LEN, wait_reply);
                ps->ps_destroy_msg(pm);
        }
 
@@ -1266,7 +1321,8 @@
                                "fh = 0x%"PRIx64"\n", __func__, (void *)opc,
                                PERFUSE_NODE_DATA(opc)->pnd_ino, fgi->fh);
 #endif
-               if ((error = XCHG_MSG(ps, pu, pm, sizeof(*fao))) != 0) {
+               if ((error = xchg_msg(pu, opc, pm, 
+                                     sizeof(*fao), wait_reply)) != 0) {
                        ps->ps_destroy_msg(pm);



Home | Main Index | Thread Index | Old Index