Source-Changes-HG archive

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

[src/trunk]: src - open the file before doing fsync: glusterfs wants that.



details:   https://anonhg.NetBSD.org/src/rev/cccd3df57e64
branches:  trunk
changeset: 757352:cccd3df57e64
user:      manu <manu%NetBSD.org@localhost>
date:      Thu Aug 26 13:29:01 2010 +0000

description:
- open the file before doing fsync: glusterfs wants that.

- Automatically call fsync on close for files. If we just close, fsync
will come later and we will have to reopen

- Add a PND_DIRTY flag to keep track of files that really need a sync.
perfuse_node_fsync only calls the FUSE fsync method if there are data
to push.

- Add a PND_OPEN flag to keep track of open files. Checking non NULL
fh is not enough, as some filesystems will always set fh to 0.

- Add a sync diagnostic flag, to watch fsync and dirty flag activity.
Make the fh diagnostic flag more verbose

- Send the fh in setattr (it was hardcoded to 0)

I am now able to build libperfuse in a glusterfs mounted filesystem. Yeah!

diffstat:

 lib/libperfuse/ops.c          |  230 +++++++++++++++++++++++++++++++++++------
 lib/libperfuse/perfuse_if.h   |   10 +-
 lib/libperfuse/perfuse_priv.h |    4 +-
 lib/libperfuse/subr.c         |    9 +-
 usr.sbin/perfused/debug.c     |    3 +-
 usr.sbin/perfused/perfused.8  |    4 +-
 usr.sbin/perfused/perfused.c  |    4 +-
 7 files changed, 218 insertions(+), 46 deletions(-)

diffs (truncated from 568 to 300 lines):

diff -r ee3957c7a2c0 -r cccd3df57e64 lib/libperfuse/ops.c
--- a/lib/libperfuse/ops.c      Thu Aug 26 13:21:50 2010 +0000
+++ b/lib/libperfuse/ops.c      Thu Aug 26 13:29:01 2010 +0000
@@ -1,4 +1,4 @@
-/*  $NetBSD: ops.c,v 1.1 2010/08/25 07:16:00 manu Exp $ */
+/*  $NetBSD: ops.c,v 1.2 2010/08/26 13:29:01 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved.
@@ -824,7 +824,6 @@
                if (error != 0) 
                        return error;
 
-
                return 0;
        }
 
@@ -960,9 +959,14 @@
         * so that we can reuse it later
         */
        perfuse_new_fh((puffs_cookie_t)pn, foo->fh);
+
 #ifdef PERFUSE_DEBUG
        if (perfuse_diagflags & PDF_FH)
-               DPRINTF("%s: fh = %lld\n", __func__, foo->fh);
+               DPRINTF("%s: opc = %p, file = \"%s\", "
+                       "ino = %lld, fh = 0x%llx\n",
+                       __func__, (void *)opc, 
+                       (char *)PNPATH((struct puffs_node *)opc),
+                       PERFUSE_NODE_DATA(opc)->pnd_ino, foo->fh);
 #endif
 out:
        ps->ps_destroy_msg(pm);
@@ -982,16 +986,46 @@
        perfuse_msg_t *pm;
        int op;
        uint64_t fh;
+       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);
 
-       pn = (struct puffs_node *)opc;
+       if (puffs_pn_getvap(pn)->va_type == VDIR)
+               op = FUSE_RELEASEDIR;
+       else
+               op = FUSE_RELEASE;
+
+       if (!(pnd->pnd_flags & PND_OPEN))
+               return EBADF;
+
+       fh = perfuse_get_fh(opc);
 
-       if ((fh = perfuse_get_fh((puffs_cookie_t)pn)) == FUSE_UNKNOWN_FH)
-               return EBADF;
+       /*
+        * Sync before close for files
+        * XXX no pcr argument to pass
+        */
+       if ((op == FUSE_RELEASE) && (pnd->pnd_flags & PND_DIRTY)) {
+#ifdef PERFUSE_DEBUG
+               if (perfuse_diagflags & PDF_SYNC)
+                       DPRINTF("%s: SYNC opc = %p, file = \"%s\"\n", 
+                               __func__, (void*)opc, (char *)PNPATH(pn));
+#endif
+               if ((error = perfuse_node_fsync(pu, opc, NULL, 0, 0, 0)) != 0)
+                       return error;
+
+               pnd->pnd_flags &= ~PND_DIRTY;
+
+#ifdef PERFUSE_DEBUG
+               if (perfuse_diagflags & PDF_SYNC)
+                       DPRINTF("%s: CLEAR opc = %p, file = \"%s\"\n", 
+                               __func__, (void*)opc, (char *)PNPATH((pn)));
+#endif
+       }
 
        /*
         * Destroy the filehandle before sending the 
@@ -1004,14 +1038,10 @@
 
 #ifdef PERFUSE_DEBUG
        if (perfuse_diagflags & PDF_FH)
-               DPRINTF("%s: fh = %lld\n", __func__, fh);
+               DPRINTF("%s: opc = %p, ino = %lld, fh = 0x%llx\n",
+                       __func__, (void *)opc, pnd->pnd_ino, fh);
 #endif
 
-       if (puffs_pn_getvap(pn)->va_type == VDIR)
-               op = FUSE_RELEASEDIR;
-       else
-               op = FUSE_RELEASE;
-
        /*
         * release_flags may be set to FUSE_RELEASE_FLUSH
         * to flush locks. lock_owner must be set in that case
@@ -1024,12 +1054,18 @@
        fri->lock_owner = PERFUSE_NODE_DATA(pn)->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 = %lld, fh = 0x%llx\n",
+                        __func__, (void *)opc, pnd->pnd_ino, fri->fh);
+#endif
+
        if ((error = XCHG_MSG(ps, pu, pm, NO_PAYLOAD_REPLY_LEN)) != 0)
                goto out;
 
 out:
        if (error != 0)
-               DWARNX("%s: freed fh = %lld but filesystem returned error = %d",
+               DWARNX("%s: freed fh = 0x%llx but filesystem returned error = %d",
                       __func__, fh, error);
 
        ps->ps_destroy_msg(pm);
@@ -1077,8 +1113,14 @@
                fgi = GET_INPAYLOAD(ps, pm, fuse_getattr_in);
                fgi->getattr_flags = 0; 
                fgi->dummy = 0;
-               fgi->fh = 0;
+               fgi->fh = perfuse_get_fh(opc);
 
+#ifdef PERFUSE_DEBUG
+               if (perfuse_diagflags & PDF_FH)
+                       DPRINTF("%s: opc = %p, ino = %lld, fh = 0x%llx\n",
+                               __func__, (void *)opc,
+                               PERFUSE_NODE_DATA(opc)->pnd_ino, fgi->fh);
+#endif
                if ((error = XCHG_MSG(ps, pu, pm, sizeof(*fao))) != 0) {
                        ps->ps_destroy_msg(pm);
                        goto out;
@@ -1161,7 +1203,8 @@
        fsi = GET_INPAYLOAD(ps, pm, fuse_setattr_in);
        fsi->valid = 0;
 
-       if ((fh = perfuse_get_fh(opc)) != FUSE_UNKNOWN_FH) {
+       if (PERFUSE_NODE_DATA(opc)->pnd_flags & PND_OPEN) {
+               fh = perfuse_get_fh(opc);
                fsi->fh = fh;
                fsi->valid |= FUSE_FATTR_FH;
        }
@@ -1235,6 +1278,12 @@
        fpi->kh = 0;
        fpi->flags = 0;
 
+#ifdef PERFUSE_DEBUG
+       if (perfuse_diagflags & PDF_FH)
+               DPRINTF("%s: opc = %p, ino = %lld, fh = 0x%llx\n",
+                       __func__, (void *)opc,  
+                       PERFUSE_NODE_DATA(opc)->pnd_ino, fpi->fh);
+#endif
        if ((error = XCHG_MSG(ps, pu, pm, sizeof(*fpo))) != 0)
                goto out;
 
@@ -1272,9 +1321,15 @@
 {
        perfuse_msg_t *pm;
        struct perfuse_state *ps;
+       struct perfuse_node_data *pnd;
        struct fuse_fsync_in *ffi;
+       uint64_t fh;
+       int open_self;
        int error;
        
+       pm = NULL;
+       open_self = 0;  
+
        /* 
         * If we previously detected it as unimplemented,
         * skip the call to the filesystem.
@@ -1284,24 +1339,73 @@
                return ENOSYS;
 
        /*
+        * Do not sync if there are no change to sync
+        * XXX remove that testif we implement mmap
+        */
+       pnd = PERFUSE_NODE_DATA(opc);
+#ifdef PERFUSE_DEBUG
+       if (perfuse_diagflags & PDF_SYNC)
+               DPRINTF("%s: TEST opc = %p, file = \"%s\" is %sdirty\n", 
+                       __func__, (void*)opc,
+                       (char *)PNPATH((struct puffs_node *)opc),
+                       pnd->pnd_flags & PND_DIRTY ? "" : "not ");
+#endif
+       if (!(pnd->pnd_flags & PND_DIRTY))
+               return 0;
+
+       /*
+        * It seems NetBSD can call fsync without open first
+        * glusterfs complain in such a situation:
+        * "FSYNC() ERR => -1 (Invalid argument)"
+        */
+       if (!(pnd->pnd_flags & PND_OPEN)) {
+               if ((error = perfuse_node_open(pu, opc, FREAD, pcr)) != 0)
+                       goto out;
+               open_self = 1;
+       }
+
+       fh = perfuse_get_fh(opc);
+       
+       /*
         * If fsync_flags  is set, meta data should not be flushed.
         */
        pm = ps->ps_new_msg(pu, opc, FUSE_FSYNC, sizeof(*ffi), NULL);
        ffi = GET_INPAYLOAD(ps, pm, fuse_fsync_in);
-       ffi->fh = perfuse_get_fh(opc);
+       ffi->fh = fh;
        ffi->fsync_flags = (flags & FFILESYNC) ? 0 : 1;
 
+#ifdef PERFUSE_DEBUG
+       if (perfuse_diagflags & PDF_FH)
+               DPRINTF("%s: opc = %p, ino = %lld, fh = 0x%llx\n",
+                       __func__, (void *)opc,
+                       PERFUSE_NODE_DATA(opc)->pnd_ino, ffi->fh);
+#endif
+
        if ((error = XCHG_MSG(ps, pu, pm, NO_PAYLOAD_REPLY_LEN)) != 0)
                goto out;       
 
        /*
-        * No reply beyond fuse_out_header: nothing to do on success.
+        * No reply beyond fuse_out_header: nothing to do on success
+        * just clear the dirty flag
         */
+       pnd->pnd_flags &= ~PND_DIRTY;
+
+#ifdef PERFUSE_DEBUG
+       if (perfuse_diagflags & PDF_SYNC)
+               DPRINTF("%s: CLEAR opc = %p, file = \"%s\"\n", 
+                       __func__, (void*)opc,
+                       (char *)PNPATH((struct puffs_node *)opc));
+#endif
+
 out:
        if (error == ENOSYS)
                ps->ps_flags |= PS_NO_FSYNC;
 
-       ps->ps_destroy_msg(pm);
+       if (pm != NULL)
+               ps->ps_destroy_msg(pm);
+
+       if (open_self)
+               (void)perfuse_node_close(pu, opc, 0, pcr);
 
        return error;
 }
@@ -1522,6 +1626,7 @@
                DERR(EX_OSERR, "puffs_inval_namecache_node failed");
 
        puffs_setback(puffs_cc_getcc(pu), PUFFS_SETBACK_NOREF_N2);
+
 out:
        ps->ps_destroy_msg(pm);
 
@@ -1619,15 +1724,21 @@
         * It seems NetBSD can call readdir without open first
         * libfuse will crash if it is done that way, hence open first.
         */
-       if ((fh = perfuse_get_fh(opc)) == FUSE_UNKNOWN_FH) {
+       if (!(PERFUSE_NODE_DATA(opc)->pnd_flags & PND_OPEN)) {
                if ((error = perfuse_node_open(pu, opc, FREAD, pcr)) != 0)
                        goto out;
                open_self = 1;
-               
-               if ((fh = perfuse_get_fh(opc)) == FUSE_UNKNOWN_FH)
-                       DERRX(EX_SOFTWARE, "open directory without fh");
        }
 
+       fh = perfuse_get_fh(opc);
+
+#ifdef PERFUSE_DEBUG
+       if (perfuse_diagflags & PDF_FH)
+               DPRINTF("%s: opc = %p, ino = %lld, fh = 0x%llx\n",
+                       __func__, (void *)opc,
+                       PERFUSE_NODE_DATA(opc)->pnd_ino, fh);
+#endif
+
        pnd->pnd_all_fd = NULL;
        pnd->pnd_all_fd_len = 0;
        fd_offset = 0;
@@ -1783,31 +1894,32 @@
 {
        struct perfuse_state *ps;
        perfuse_msg_t *pm;
+       struct perfuse_node_data *pnd;
        struct fuse_forget_in *ffi;
        struct puffs_node *pn;
        struct puffs_node *pn_root;
        
        ps = puffs_getspecific(pu);
+       pnd = PERFUSE_NODE_DATA(opc);
 
        /*
         * Make sure open files are properly closed when reclaimed.



Home | Main Index | Thread Index | Old Index