Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/lib Fix regression that has been introduced when the lookup/...
details: https://anonhg.NetBSD.org/src/rev/2e0d2ed8bdae
branches: trunk
changeset: 781045:2e0d2ed8bdae
user: manu <manu%NetBSD.org@localhost>
date: Thu Aug 16 09:25:43 2012 +0000
description:
Fix regression that has been introduced when the lookup/reclaim race
condition was addressed in libpuffs by counting lookups.
The fix assumes that cookies map to struct puffs_cookie, which has not
been documented as a requirement for filesystems using libpuffs. As an
example, we got burnt by this assumption in libp2k (kern/46734), and
we fixed bit by actually mapping libp2k cookies to struct puffs_node.
It is unlikely, but there may be third party filesystems that use cookies
unmapped to struct puffs_node, and they were left broken for now.
- we introduce a puffs_init() flag PUFFS_FLAG_PNCOOKIE that let filesystems
inform libpuffs that they map cookies to struct puffs_node. Is that flag
is used, the lookup/reclaim race condition fix is enabled. We enable the
flag for libp2k.
- filesystems that use puffs_pn_new() obviouslty use struct puffs_node
and gain PUFFS_FLAG_PNCOOKIE automatically even if they did not specify
it in puffs_init(). This include all our PUFFS filesystem in-tree except
libp2k.
- for filesystems not willing to use struct puffs_node, we introduce a
reclaim2 vnop, which is reclaim with an additionnal lookup count argument.
This vnop let the filesystem implement the lookup/reclaim race fix on
its own.
diffstat:
lib/libp2k/p2k.c | 9 ++++++++-
lib/libpuffs/dispatcher.c | 37 ++++++++++++++++++++++++-------------
lib/libpuffs/pnode.c | 6 ++++--
lib/libpuffs/puffs.3 | 8 +++++++-
lib/libpuffs/puffs.h | 13 +++++++++----
lib/libpuffs/puffs_ops.3 | 26 +++++++++++++++++++++++++-
6 files changed, 77 insertions(+), 22 deletions(-)
diffs (289 lines):
diff -r b64fb3d636ba -r 2e0d2ed8bdae lib/libp2k/p2k.c
--- a/lib/libp2k/p2k.c Thu Aug 16 08:39:43 2012 +0000
+++ b/lib/libp2k/p2k.c Thu Aug 16 09:25:43 2012 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: p2k.c,v 1.56 2012/08/12 02:51:18 manu Exp $ */
+/* $NetBSD: p2k.c,v 1.57 2012/08/16 09:25:44 manu Exp $ */
/*
* Copyright (c) 2007, 2008, 2009 Antti Kantee. All Rights Reserved.
@@ -358,6 +358,13 @@
}
}
+ /*
+ * Explicitely tell that our cookies can be treated as
+ * puffs_node, since we never let libpuffs know by
+ * calling call puffs_pn_new()
+ */
+ puffs_flags |= PUFFS_FLAG_PNCOOKIE;
+
p2m = allocp2m();
if (p2m == NULL)
return NULL;
diff -r b64fb3d636ba -r 2e0d2ed8bdae lib/libpuffs/dispatcher.c
--- a/lib/libpuffs/dispatcher.c Thu Aug 16 08:39:43 2012 +0000
+++ b/lib/libpuffs/dispatcher.c Thu Aug 16 09:25:43 2012 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: dispatcher.c,v 1.43 2012/08/10 08:42:10 manu Exp $ */
+/* $NetBSD: dispatcher.c,v 1.44 2012/08/16 09:25:43 manu Exp $ */
/*
* Copyright (c) 2006, 2007, 2008 Antti Kantee. All Rights Reserved.
@@ -31,7 +31,7 @@
#include <sys/cdefs.h>
#if !defined(lint)
-__RCSID("$NetBSD: dispatcher.c,v 1.43 2012/08/10 08:42:10 manu Exp $");
+__RCSID("$NetBSD: dispatcher.c,v 1.44 2012/08/16 09:25:43 manu Exp $");
#endif /* !lint */
#include <sys/types.h>
@@ -125,7 +125,7 @@
struct puffs_req *preq = puffs__framebuf_getdataptr(pcc->pcc_pb);
void *auxbuf; /* help with typecasting */
puffs_cookie_t opcookie;
- int error = 0, buildpath;
+ int error = 0, buildpath, pncookie;
/* XXX: smaller hammer, please */
if ((PUFFSOP_OPCLASS(preq->preq_opclass == PUFFSOP_VFS &&
@@ -145,6 +145,9 @@
assert((pcc->pcc_flags & PCC_DONE) == 0);
buildpath = pu->pu_flags & PUFFS_FLAG_BUILDPATH;
+ pncookie = pu->pu_flags & PUFFS_FLAG_PNCOOKIE;
+ assert(!buildpath || pncookie);
+
preq->preq_setbacks = 0;
if (pu->pu_flags & PUFFS_FLAG_OPDUMP)
@@ -302,7 +305,7 @@
}
}
- if (!error) {
+ if (pncookie && !error) {
if (pn == NULL)
pn = PU_CMAP(pu, auxt->pvnr_newnode);
pn->pn_nlookup++;
@@ -349,7 +352,7 @@
}
}
- if (!error) {
+ if (pncookie && !error) {
if (pn == NULL)
pn = PU_CMAP(pu, auxt->pvnr_newnode);
pn->pn_nlookup++;
@@ -396,7 +399,7 @@
}
}
- if (!error) {
+ if (pncookie && !error) {
if (pn == NULL)
pn = PU_CMAP(pu, auxt->pvnr_newnode);
pn->pn_nlookup++;
@@ -701,7 +704,7 @@
}
}
- if (!error) {
+ if (pncookie && !error) {
if (pn == NULL)
pn = PU_CMAP(pu, auxt->pvnr_newnode);
pn->pn_nlookup++;
@@ -766,7 +769,7 @@
}
}
- if (!error) {
+ if (pncookie && !error) {
if (pn == NULL)
pn = PU_CMAP(pu, auxt->pvnr_newnode);
pn->pn_nlookup++;
@@ -835,6 +838,12 @@
struct puffs_vnmsg_reclaim *auxt = auxbuf;
struct puffs_node *pn;
+ if (pops->puffs_node_reclaim2 != NULL) {
+ error = pops->puffs_node_reclaim2(pu, opcookie,
+ auxt->pvnr_nlookup);
+ break;
+ }
+
if (pops->puffs_node_reclaim == NULL) {
error = 0;
break;
@@ -847,11 +856,13 @@
* but before the reply, leaving the kernel
* with a invalid vnode/cookie reference.
*/
- pn = PU_CMAP(pu, opcookie);
- pn->pn_nlookup -= auxt->pvnr_nlookup;
- if (pn->pn_nlookup >= 1) {
- error = 0;
- break;
+ if (pncookie) {
+ pn = PU_CMAP(pu, opcookie);
+ pn->pn_nlookup -= auxt->pvnr_nlookup;
+ if (pn->pn_nlookup >= 1) {
+ error = 0;
+ break;
+ }
}
error = pops->puffs_node_reclaim(pu, opcookie);
diff -r b64fb3d636ba -r 2e0d2ed8bdae lib/libpuffs/pnode.c
--- a/lib/libpuffs/pnode.c Thu Aug 16 08:39:43 2012 +0000
+++ b/lib/libpuffs/pnode.c Thu Aug 16 09:25:43 2012 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: pnode.c,v 1.12 2012/04/18 00:57:22 manu Exp $ */
+/* $NetBSD: pnode.c,v 1.13 2012/08/16 09:25:43 manu Exp $ */
/*
* Copyright (c) 2006 Antti Kantee. All Rights Reserved.
@@ -27,7 +27,7 @@
#include <sys/cdefs.h>
#if !defined(lint)
-__RCSID("$NetBSD: pnode.c,v 1.12 2012/04/18 00:57:22 manu Exp $");
+__RCSID("$NetBSD: pnode.c,v 1.13 2012/08/16 09:25:43 manu Exp $");
#endif /* !lint */
#include <sys/types.h>
@@ -60,6 +60,8 @@
LIST_INSERT_HEAD(&pu->pu_pnodelst, pn, pn_entries);
+ pu->pu_flags |= PUFFS_FLAG_PNCOOKIE;
+
return pn;
}
diff -r b64fb3d636ba -r 2e0d2ed8bdae lib/libpuffs/puffs.3
--- a/lib/libpuffs/puffs.3 Thu Aug 16 08:39:43 2012 +0000
+++ b/lib/libpuffs/puffs.3 Thu Aug 16 09:25:43 2012 +0000
@@ -1,4 +1,4 @@
-.\" $NetBSD: puffs.3,v 1.55 2012/08/10 21:00:45 wiz Exp $
+.\" $NetBSD: puffs.3,v 1.56 2012/08/16 09:25:43 manu Exp $
.\"
.\" Copyright (c) 2006, 2007, 2008 Antti Kantee. All rights reserved.
.\"
@@ -235,6 +235,12 @@
the one searched for.
Especially if the file system uses the abovementioned function, it
is a good idea to define this flag.
+.It Dv PUFFS_FLAG_PNCOOKIE
+Tell puffs that cookies map to
+.Vt struct pnode .
+This is automagically set if
+.Fn puffs_pn_new
+is called.
.It Dv PUFFS_KFLAG_CACHE_FS_TTL
Enforce name and attribute caches based on file system-supplied TTL.
In lookup, create, mknod, mkdir, and symlink, the file system must
diff -r b64fb3d636ba -r 2e0d2ed8bdae lib/libpuffs/puffs.h
--- a/lib/libpuffs/puffs.h Thu Aug 16 08:39:43 2012 +0000
+++ b/lib/libpuffs/puffs.h Thu Aug 16 09:25:43 2012 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: puffs.h,v 1.123 2012/07/21 05:17:10 manu Exp $ */
+/* $NetBSD: puffs.h,v 1.124 2012/08/16 09:25:44 manu Exp $ */
/*
* Copyright (c) 2005, 2006, 2007 Antti Kantee. All Rights Reserved.
@@ -248,8 +248,10 @@
struct timespec *, int);
int (*puffs_node_write2)(struct puffs_usermount *, puffs_cookie_t,
uint8_t *, off_t, size_t *, const struct puffs_cred *, int, int);
+ int (*puffs_node_reclaim2)(struct puffs_usermount *,
+ puffs_cookie_t, int);
- void *puffs_ops_spare[29];
+ void *puffs_ops_spare[28];
};
typedef int (*pu_pathbuild_fn)(struct puffs_usermount *,
@@ -283,7 +285,8 @@
#define PUFFS_FLAG_BUILDPATH 0x80000000 /* node paths in pnode */
#define PUFFS_FLAG_OPDUMP 0x40000000 /* dump all operations */
#define PUFFS_FLAG_HASHPATH 0x20000000 /* speedup: hash paths */
-#define PUFFS_FLAG_MASK 0xe0000000
+#define PUFFS_FLAG_PNCOOKIE 0x10000000 /* cookies are pnodes */
+#define PUFFS_FLAG_MASK 0xf0000000
#define PUFFS_FLAG_KERN(a) ((a) & PUFFS_KFLAG_MASK)
#define PUFFS_FLAG_LIB(a) ((a) & PUFFS_FLAG_MASK)
@@ -405,7 +408,9 @@
struct timespec *, int); \
int fsname##_node_write2(struct puffs_usermount *, \
puffs_cookie_t, uint8_t *, off_t, size_t *, \
- const struct puffs_cred *, int, int);
+ const struct puffs_cred *, int, int); \
+ int fsname##_node_reclaim2(struct puffs_usermount *, \
+ puffs_cookie_t, int);
#define PUFFSOP_INIT(ops) \
diff -r b64fb3d636ba -r 2e0d2ed8bdae lib/libpuffs/puffs_ops.3
--- a/lib/libpuffs/puffs_ops.3 Thu Aug 16 08:39:43 2012 +0000
+++ b/lib/libpuffs/puffs_ops.3 Thu Aug 16 09:25:43 2012 +0000
@@ -1,4 +1,4 @@
-.\" $NetBSD: puffs_ops.3,v 1.34 2012/07/28 09:56:09 njoly Exp $
+.\" $NetBSD: puffs_ops.3,v 1.35 2012/08/16 09:25:44 manu Exp $
.\"
.\" Copyright (c) 2007 Antti Kantee. All rights reserved.
.\"
@@ -228,6 +228,10 @@
.Fa "struct puffs_usermount *pu" "puffs_cookie_t opc"
.Fc
.Ft int
+.Fo puffs_node_reclaim2
+.Fa "struct puffs_usermount *pu" "puffs_cookie_t opc" "int nlookup"
+.Fc
+.Ft int
.Fo puffs_node_inactive
.Fa "struct puffs_usermount *pu" "puffs_cookie_t opc"
.Fc
@@ -617,6 +621,8 @@
open file semantics.
The data may be removed only when
.Fn puffs_node_reclaim
+or
+.Fn puffs_node_reclaim2
is called for the node, as this assures there are no further users.
.It Fn puffs_node_link "pu" "opc" "targ" "pcn"
Create a hard link for the node
@@ -791,6 +797,22 @@
In case the file
.Fa opc
has a link count of zero, it may be safely removed now.
+.It Fn puffs_node_reclaim2 "pu" "opc" "nlookup"
+Same as
+.Fn puffs_node_reclaim
+with an addditional argument for the number of lookups that have been done
+on the node (Node creation is counted as a lookup). This can be used by the
+filesystem to avoid a race condition, where the kernel sends a reclaim
+while it does not have received the reply for a lookup. If the filesystem
+tracks lookup count, and compares to
+.Fa nlookup
+it can detect this situation and ignore the reclaim.
+.Pp
+If the filesystem maps cookies to
+.Vt struct puffs_node
+then the framework will do that work, and
+.Fn puffs_node_reclaim
+can be reliabily used without the race condition.
.It Fn puffs_node_abortop "pu" "opc" "pcn"
In case the operation following lookup (e.g., mkdir or remove) is not
executed for some reason, abortop will be issued.
@@ -802,6 +824,8 @@
has lost its last reference in the kernel.
However, the cookie must still remain valid until
.Fn puffs_node_reclaim
+or
+.Fn puffs_node_reclaim2
is called.
.It Fn puffs_setback "pcc" "op"
Issue a "setback" operation which will be handled when the request response
Home |
Main Index |
Thread Index |
Old Index