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