Source-Changes-HG archive

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

[src/trunk]: src == file close operations ==



details:   https://anonhg.NetBSD.org/src/rev/f58833c0071a
branches:  trunk
changeset: 757794:f58833c0071a
user:      manu <manu%NetBSD.org@localhost>
date:      Thu Sep 23 16:02:34 2010 +0000

description:
== file close operations ==
- use PUFFS_KFLAG_WTCACHE to puffs_init so that all writes are
immediatly send to the filesystem, and we do not have anymore write
after inactive. As a consequence, we can close files at inactive
stage, and there is not any concern left with files opened at
create time. We also do not have anymore to open ourselves in readdir and
fsync.

- Fsync on close (inactive stage). That makes sure we will not need to
do these operations once the file is closed (FUSE want an open file).
short sircuit the request that come after the close, bu not fsinc'ing
closed files,

- Use PUFFS_KFLAG_IAONDEMAND to get less inactive calls

== Removed nodes ==
- more ENOENT retunred for operations on removed node (but there
are probably some still missing): getattr, ooen, setattr, fsync

- set PND_REMOVE before sending the UNLINK/RMDIR operations so that we avoid
races during UNLINK completion. Also set PND_REMOVED on node we overwirte
in rename

== Filehandle fixes ==
- queue open operation to avoid getting two fh for one file

- set FH in getattr, if the file is open

- Just requires a read FH for fsyncdir, as we always opendir in read
mode. Ok, this is misleading :-)

== Misc ==
- do not set FUSE_FATTR_ATIME_NOW in setattr, as we provide the time

- short circuit nilpotent operations in setattr

- add a filename diagnostic flag to dump file names

diffstat:

 lib/libperfuse/debug.c        |   10 +-
 lib/libperfuse/ops.c          |  386 +++++++++++++++++++++++++----------------
 lib/libperfuse/perfuse.c      |    5 +-
 lib/libperfuse/perfuse_if.h   |    3 +-
 lib/libperfuse/perfuse_priv.h |   29 +-
 lib/libperfuse/subr.c         |   35 +---
 usr.sbin/perfused/perfused.c  |    6 +-
 7 files changed, 272 insertions(+), 202 deletions(-)

diffs (truncated from 967 to 300 lines):

diff -r fb85306b4482 -r f58833c0071a lib/libperfuse/debug.c
--- a/lib/libperfuse/debug.c    Thu Sep 23 13:03:35 2010 +0000
+++ b/lib/libperfuse/debug.c    Thu Sep 23 16:02:34 2010 +0000
@@ -1,4 +1,4 @@
-/*  $NetBSD: debug.c,v 1.2 2010/09/15 01:51:43 manu Exp $ */
+/*  $NetBSD: debug.c,v 1.3 2010/09/23 16:02:34 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved.
@@ -79,7 +79,13 @@
        { 0, "UNKNOWN" },
 };
 
-const char *perfuse_qtypestr[] = { "READDIR", "READ", "WRITE", "AFTERWRITE" };
+const char *perfuse_qtypestr[] = { 
+       "READDIR",
+       "READ",
+       "WRITE",
+       "AFTERWRITE",
+       "OPEN"
+};
 
 const char *
 perfuse_opname(opcode)
diff -r fb85306b4482 -r f58833c0071a lib/libperfuse/ops.c
--- a/lib/libperfuse/ops.c      Thu Sep 23 13:03:35 2010 +0000
+++ b/lib/libperfuse/ops.c      Thu Sep 23 16:02:34 2010 +0000
@@ -1,4 +1,4 @@
-/*  $NetBSD: ops.c,v 1.16 2010/09/20 07:00:21 manu Exp $ */
+/*  $NetBSD: ops.c,v 1.17 2010/09/23 16:02:34 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved.
@@ -180,9 +180,10 @@
        ps = puffs_getspecific(pu);
 
 #ifdef PERFUSE_DEBUG
-       if ((perfuse_diagflags & PDF_FUSE) && (opc != 0))
-               DPRINTF("file = \"%s\"\n", 
-                       (char *)PNPATH((struct puffs_node *)opc));
+       if ((perfuse_diagflags & PDF_FILENAME) && (opc != 0))
+               DPRINTF("file = \"%s\" flags = 0x%x\n", 
+                       (char *)PNPATH((struct puffs_node *)opc), 
+                       PERFUSE_NODE_DATA(opc)->pnd_flags);
 #endif
        error = ps->ps_xchg_msg(pu, pm, len, wait);
 
@@ -324,6 +325,11 @@
        if (pnp != NULL)
                *pnp = pn;
 
+#ifdef PERFUSE_DEBUG
+       if (perfuse_diagflags & PDF_FILENAME)
+               DPRINTF("%s: opc = %p, looked up opc = %p, file = \"%s\"\n",
+                       __func__, (void *)opc, pn, (char *)PNPATH(pn));
+#endif
 out: 
        ps->ps_destroy_msg(pm);
 
@@ -989,13 +995,6 @@
                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;
        }
 
@@ -1030,17 +1029,9 @@
         * so that we can reuse it later
         */
        pn = perfuse_new_pn(pu, opc);
-       perfuse_new_fh(pu, (puffs_cookie_t)pn, foo->fh, FWRITE);
+       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);
 
@@ -1049,12 +1040,13 @@
         */
        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;
+#ifdef PERFUSE_DEBUG
+       if (perfuse_diagflags & (PDF_FH|PDF_FILENAME))
+               DPRINTF("%s: opc = %p, file = \"%s\", flags = 0x%x "
+                       "ino = %"PRId64", wfh = 0x%"PRIx64"\n",
+                       __func__, (void *)pn, (char *)PCNPATH(pcn),
+                       PERFUSE_NODE_DATA(pn)->pnd_flags, feo->nodeid, foo->fh);
+#endif
 
 out: 
        ps->ps_destroy_msg(pm);
@@ -1145,17 +1137,30 @@
        int error;
        
        ps = puffs_getspecific(pu);
+       pn = (struct puffs_node *)opc;
        pnd = PERFUSE_NODE_DATA(opc);
-
-       pn = (struct puffs_node *)opc;
+       pm = NULL;
+       error = 0;
+
+       /*
+        * Queue open on a node so that we do not open
+        * twice. This would be better with read and
+        * write distinguished.
+        */
+       while (pnd->pnd_flags & PND_INOPEN)
+               requeue_request(pu, opc, PCQ_OPEN);
+       pnd->pnd_flags |= PND_INOPEN;
+
        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;
+               if (pnd->pnd_flags & PND_REMOVED) {
+                       error = ENOENT;
+                       goto out;
+               }
 
                op = FUSE_OPENDIR;
                pmode = PUFFS_VREAD|PUFFS_VEXEC;
@@ -1172,11 +1177,11 @@
         * 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)pnd->pnd_parent, pcr, PUFFS_VEXEC))
-               return EACCES;
-
-       if (no_access(opc, pcr, pmode))
-               return EACCES;
+       if ((no_access((puffs_cookie_t)pnd->pnd_parent, pcr, PUFFS_VEXEC)) ||
+           (no_access(opc, pcr, pmode))) {
+               error = EACCES;
+               goto out;
+       }
 
        /*
         * libfuse docs say O_CREAT should not be set.
@@ -1185,22 +1190,27 @@
 
        /*
         * Do not open twice, and do not reopen for reading
-        * if we already have write handle.
+        * if we already have write handle. Just ask for
+        * inactive, in case the node was open by a create
+        * operation (we are not allowed to call puffs_setback
+        * at create time, puffs interface forbids it)
         */
        if (((mode & FREAD) && (pnd->pnd_flags & PND_RFH)) ||
+           ((mode & FREAD) && (pnd->pnd_flags & PND_WFH)) ||
            ((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;
+               puffs_setback(puffs_cc_getcc(pu), PUFFS_SETBACK_INACT_N1);
+               error = 0;
+               goto out;
        }
        
+       /* 
+        * Fail any attempt to reopen a removed file if
+        * we do not have any file handle left.
+        */
+       if (pnd->pnd_flags & PND_REMOVED) {
+               error = ENOENT;
+               goto out;
+       }
 
        /*
         * Convert PUFFS mode to FUSE mode: convert FREAD/FWRITE
@@ -1223,10 +1233,15 @@
         * Save the file handle in node private data 
         * so that we can reuse it later
         */
-       perfuse_new_fh(pu, (puffs_cookie_t)pn, foo->fh, mode);
+       perfuse_new_fh(opc, foo->fh, mode);
+        
+       /*
+        * Request inactive to be send on this node.
+        */
+       puffs_setback(puffs_cc_getcc(pu), PUFFS_SETBACK_INACT_N1);
 
 #ifdef PERFUSE_DEBUG
-       if (perfuse_diagflags & PDF_FH)
+       if (perfuse_diagflags & (PDF_FH|PDF_FILENAME))
                DPRINTF("%s: opc = %p, file = \"%s\", "
                        "ino = %"PRId64", %s%sfh = 0x%"PRIx64"\n",
                        __func__, (void *)opc, 
@@ -1236,7 +1251,11 @@
 #endif
 
 out:
-       ps->ps_destroy_msg(pm);
+       if (pm != NULL)
+               ps->ps_destroy_msg(pm);
+
+       pnd->pnd_flags &= ~PND_INOPEN;
+       (void)dequeue_requests(ps, opc, PCQ_OPEN, DEQUEUE_ALL);
 
        return error;
 }
@@ -1249,24 +1268,16 @@
        int flags;
        const struct puffs_cred *pcr;
 {
-       struct puffs_node *pn;
        struct perfuse_node_data *pnd;
 
-       pn = (struct puffs_node *)opc;
        pnd = PERFUSE_NODE_DATA(opc);
 
        if (!(pnd->pnd_flags & PND_OPEN))
                return EBADF;
 
        /* 
-        * The NetBSD kernel will send sync and setattr(mtime, ctime)
-        * afer a close on a regular file. Some FUSE filesystem will 
-        * assume theses operations are performed on open files. We 
-        * therefore postpone the close operation at reclaim time.
+        * Actual close is postponed at inactive time.
         */
-       if (puffs_pn_getvap(pn)->va_type != VREG)
-               return perfuse_node_close_common(pu, opc, flags);
-
        return 0;
 }
 
@@ -1352,7 +1363,11 @@
        struct fuse_attr_out *fao;
        int error;
        
-       if (PERFUSE_NODE_DATA(opc)->pnd_flags & PND_REMOVED)
+       /*
+        * If removed and not open, it fails
+        */
+       if ((PERFUSE_NODE_DATA(opc)->pnd_flags & PND_REMOVED) &&
+           !(PERFUSE_NODE_DATA(opc)->pnd_flags & PND_OPEN))
                return ENOENT;
 
        /*
@@ -1366,13 +1381,16 @@
 
        /*
         * FUSE_GETATTR_FH must be set in fgi->flags 
-        * if we use for fgi->fh, but we do not. 
+        * if we use for fgi->fh
         */
        pm = ps->ps_new_msg(pu, opc, FUSE_GETATTR, sizeof(*fgi), pcr);
        fgi = GET_INPAYLOAD(ps, pm, fuse_getattr_in);
        fgi->getattr_flags = 0; 
        fgi->dummy = 0;
-       fgi->fh = 0;
+       fgi->fh = perfuse_get_fh(opc, FREAD);
+
+       if (PERFUSE_NODE_DATA(opc)->pnd_flags & PND_OPEN)
+               fgi->getattr_flags |= FUSE_GETATTR_FH;
 
        if ((error = xchg_msg(pu, opc, pm, sizeof(*fao), wait_reply)) != 0)
                goto out;
@@ -1407,22 +1425,25 @@
        struct perfuse_state *ps;
        struct perfuse_node_data *pnd;
        struct fuse_setattr_in *fsi;
+       struct vattr *old_va;
        int error;
-       struct vattr *old_va;
 



Home | Main Index | Thread Index | Old Index