Module Name: src
Committed By: rmind
Date: Fri Jul 2 03:16:01 UTC 2010
Modified Files:
src/sys/miscfs/genfs: layer_extern.h layer_subr.c layer_vfsops.c
layer_vnops.c
src/sys/miscfs/nullfs: null.h null_vfsops.c null_vnops.c
Log Message:
Slightly clean-up layerfs and nullfs: update the big description more to
the reality (remove duplicate one in nullfs, merge some differences from
it), KNF, improve and update some comments, add few KASSERT()s, remove
unused declarations, avoid double inclusion of headers, misc.
No functional changes.
To generate a diff of this commit:
cvs rdiff -u -r1.24 -r1.25 src/sys/miscfs/genfs/layer_extern.h
cvs rdiff -u -r1.29 -r1.30 src/sys/miscfs/genfs/layer_subr.c
cvs rdiff -u -r1.32 -r1.33 src/sys/miscfs/genfs/layer_vfsops.c
cvs rdiff -u -r1.41 -r1.42 src/sys/miscfs/genfs/layer_vnops.c
cvs rdiff -u -r1.18 -r1.19 src/sys/miscfs/nullfs/null.h
cvs rdiff -u -r1.81 -r1.82 src/sys/miscfs/nullfs/null_vfsops.c
cvs rdiff -u -r1.34 -r1.35 src/sys/miscfs/nullfs/null_vnops.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/miscfs/genfs/layer_extern.h
diff -u src/sys/miscfs/genfs/layer_extern.h:1.24 src/sys/miscfs/genfs/layer_extern.h:1.25
--- src/sys/miscfs/genfs/layer_extern.h:1.24 Mon Jan 28 14:31:18 2008
+++ src/sys/miscfs/genfs/layer_extern.h Fri Jul 2 03:16:00 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: layer_extern.h,v 1.24 2008/01/28 14:31:18 dholland Exp $ */
+/* $NetBSD: layer_extern.h,v 1.25 2010/07/02 03:16:00 rmind Exp $ */
/*
* Copyright (c) 1999 National Aeronautics & Space Administration
@@ -32,6 +32,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
+
/*
* Copyright (c) 1992, 1993, 1995
* The Regents of the University of California. All rights reserved.
@@ -65,23 +66,26 @@
*
*/
+#ifndef _MISCFS_GENFS_LAYER_EXTERN_H_
+#define _MISCFS_GENFS_LAYER_EXTERN_H_
+
/*
* Routines defined by layerfs
*/
-/* misc routines in layer_subr.c */
+/* Routines to manage nodes. */
void layerfs_init(void);
void layerfs_done(void);
int layer_node_alloc(struct mount *, struct vnode *, struct vnode **);
int layer_node_create(struct mount *, struct vnode *, struct vnode **);
-struct vnode *
- layer_node_find(struct mount *, struct vnode *);
+struct vnode *layer_node_find(struct mount *, struct vnode *);
+
#define LOG2_SIZEVNODE 7 /* log2(sizeof struct vnode) */
#define LAYER_NHASH(lmp, vp) \
(&((lmp)->layerm_node_hashtbl[(((u_long)vp)>>LOG2_SIZEVNODE) & \
(lmp)->layerm_node_hash]))
-/* vfs routines */
+/* VFS routines */
int layerfs_start(struct mount *, int);
int layerfs_root(struct mount *, struct vnode **);
int layerfs_quotactl(struct mount *, int, uid_t, void *);
@@ -90,8 +94,7 @@
int layerfs_vget(struct mount *, ino_t, struct vnode **);
int layerfs_fhtovp(struct mount *, struct fid *, struct vnode **);
int layerfs_vptofh(struct vnode *, struct fid *, size_t *);
-int layerfs_snapshot(struct mount *, struct vnode *,
- struct timespec *);
+int layerfs_snapshot(struct mount *, struct vnode *, struct timespec *);
int layerfs_renamelock_enter(struct mount *);
void layerfs_renamelock_exit(struct mount *);
@@ -116,3 +119,5 @@
int layer_rmdir(void *);
int layer_getpages(void *);
int layer_putpages(void *);
+
+#endif /* _MISCFS_GENFS_LAYER_EXTERN_H_ */
Index: src/sys/miscfs/genfs/layer_subr.c
diff -u src/sys/miscfs/genfs/layer_subr.c:1.29 src/sys/miscfs/genfs/layer_subr.c:1.30
--- src/sys/miscfs/genfs/layer_subr.c:1.29 Sun Jun 6 08:01:31 2010
+++ src/sys/miscfs/genfs/layer_subr.c Fri Jul 2 03:16:00 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: layer_subr.c,v 1.29 2010/06/06 08:01:31 hannken Exp $ */
+/* $NetBSD: layer_subr.c,v 1.30 2010/07/02 03:16:00 rmind Exp $ */
/*
* Copyright (c) 1999 National Aeronautics & Space Administration
@@ -32,6 +32,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
+
/*
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
@@ -68,7 +69,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: layer_subr.c,v 1.29 2010/06/06 08:01:31 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: layer_subr.c,v 1.30 2010/07/02 03:16:00 rmind Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -84,8 +85,6 @@
#include <miscfs/genfs/layer.h>
#include <miscfs/genfs/layer_extern.h>
-#define NLAYERNODECACHE 16
-
#ifdef LAYERFS_DIAGNOSTIC
int layerfs_debug = 1;
#endif
@@ -98,34 +97,23 @@
* alias is removed the lower vnode is vrele'd.
*/
-/*
- * Initialise cache headers
- */
void
layerfs_init(void)
{
-#ifdef LAYERFS_DIAGNOSTIC
- if (layerfs_debug)
- printf("layerfs_init\n"); /* printed during system boot */
-#endif
+ /* Nothing. */
}
-/*
- * Free global resources of layerfs.
- */
void
layerfs_done(void)
{
-#ifdef LAYERFS_DIAGNOSTIC
- if (layerfs_debug)
- printf("layerfs_done\n"); /* printed on layerfs detach */
-#endif
+ /* Nothing. */
}
/*
- * Return a locked, VREF'ed alias for lower vnode if already exists, else NULL.
- * The layermp's hashlock must be held on entry.
- * It will be held upon return iff we return NULL.
+ * layer_node_find: find and return alias for lower vnode or NULL.
+ *
+ * => Return alias vnode locked and referenced. if already exists.
+ * => The layermp's hashlock must be held on entry, we will unlock on success.
*/
struct vnode *
layer_node_find(struct mount *mp, struct vnode *lowervp)
@@ -137,58 +125,59 @@
int error;
/*
- * Find hash base, and then search the (two-way) linked
- * list looking for a layer_node structure which is referencing
- * the lower vnode. If found, the increment the layer_node
- * reference count (but NOT the lower vnode's VREF counter)
- * and return the vnode locked.
+ * Find hash bucket and search the (two-way) linked list looking
+ * for a layerfs node structure which is referencing the lower vnode.
+ * If found, the increment the layer_node reference count, but NOT
+ * the lower vnode's reference counter. Return vnode locked.
*/
+ KASSERT(mutex_owned(&lmp->layerm_hashlock));
hd = LAYER_NHASH(lmp, lowervp);
loop:
LIST_FOREACH(a, hd, layer_hash) {
- if (a->layer_lowervp == lowervp && LAYERTOV(a)->v_mount == mp) {
- vp = LAYERTOV(a);
- mutex_enter(&vp->v_interlock);
- /*
- * If we find a node being cleaned out, then
- * ignore it and continue. A thread trying to
- * clean out the extant layer vnode needs to
- * acquire the shared lock (i.e. the lower
- * vnode's lock), which our caller already holds.
- * To allow the cleaning to succeed the current
- * thread must make progress. So, for a brief
- * time more than one vnode in a layered file
- * system may refer to a single vnode in the
- * lower file system.
- */
- if ((vp->v_iflag & VI_XLOCK) != 0) {
- mutex_exit(&vp->v_interlock);
- continue;
- }
- mutex_exit(&lmp->layerm_hashlock);
- /*
- * We must not let vget() try to lock the layer
- * vp, since the lower vp is already locked and
- * locking the layer vp will involve locking
- * the lower vp.
- */
- error = vget(vp, LK_INTERLOCK | LK_NOWAIT);
- if (error) {
- kpause("layerfs", false, 1, NULL);
- mutex_enter(&lmp->layerm_hashlock);
- goto loop;
- }
- return (vp);
+ if (a->layer_lowervp != lowervp) {
+ continue;
+ }
+ vp = LAYERTOV(a);
+ if (vp->v_mount != mp) {
+ continue;
+ }
+ mutex_enter(&vp->v_interlock);
+ /*
+ * If we find a node being cleaned out, then ignore it and
+ * continue. A thread trying to clean out the extant layer
+ * vnode needs to acquire the shared lock (i.e. the lower
+ * vnode's lock), which our caller already holds. To allow
+ * the cleaning to succeed the current thread must make
+ * progress. So, for a brief time more than one vnode in a
+ * layered file system may refer to a single vnode in the
+ * lower file system.
+ */
+ if ((vp->v_iflag & VI_XLOCK) != 0) {
+ mutex_exit(&vp->v_interlock);
+ continue;
+ }
+ mutex_exit(&lmp->layerm_hashlock);
+ /*
+ * We must not let vget() try to lock the layer vp, since
+ * the lower vp is already locked and locking the layer vp
+ * will involve locking the lower vp.
+ */
+ error = vget(vp, LK_INTERLOCK | LK_NOWAIT);
+ if (error) {
+ kpause("layerfs", false, 1, NULL);
+ mutex_enter(&lmp->layerm_hashlock);
+ goto loop;
}
+ return vp;
}
return NULL;
}
-
/*
- * Make a new layer_node node.
- * Vp is the alias vnode, lowervp is the lower vnode.
- * Maintain a reference to lowervp.
+ * layer_node_alloc: make a new layerfs vnode.
+ *
+ * => vp is the alias vnode, lowervp is the lower vnode.
+ * => We will hold a reference to lowervp.
*/
int
layer_node_alloc(struct mount *mp, struct vnode *lowervp, struct vnode **vpp)
@@ -201,8 +190,9 @@
extern int (**dead_vnodeop_p)(void *);
error = getnewvnode(lmp->layerm_tag, mp, lmp->layerm_vnodeop_p, &vp);
- if (error != 0)
- return (error);
+ if (error) {
+ return error;
+ }
vp->v_type = lowervp->v_type;
mutex_enter(&vp->v_interlock);
vp->v_iflag |= VI_LAYER;
@@ -225,61 +215,57 @@
xp->layer_flags = 0;
/*
- * Before we insert our new node onto the hash chains,
- * check to see if someone else has beaten us to it.
- * (We could have slept in MALLOC.)
+ * Before inserting the node into the hash, check if other thread
+ * did not race with us. If so - return that node, destroy ours.
*/
mutex_enter(&lmp->layerm_hashlock);
if ((nvp = layer_node_find(mp, lowervp)) != NULL) {
- *vpp = nvp;
-
- /* free the substructures we've allocated. */
- kmem_free(xp, lmp->layerm_size);
+ /* Free the structures we have created. */
if (vp->v_type == VBLK || vp->v_type == VCHR)
spec_node_destroy(vp);
vp->v_type = VBAD; /* node is discarded */
vp->v_op = dead_vnodeop_p; /* so ops will still work */
vrele(vp); /* get rid of it. */
- return (0);
+ kmem_free(xp, lmp->layerm_size);
+ *vpp = nvp;
+ return 0;
}
/*
* Insert the new node into the hash.
* Add a reference to the lower node.
*/
-
- *vpp = vp;
vref(lowervp);
hd = LAYER_NHASH(lmp, lowervp);
LIST_INSERT_HEAD(hd, xp, layer_hash);
uvm_vnp_setsize(vp, 0);
mutex_exit(&lmp->layerm_hashlock);
- return (0);
-}
+ *vpp = vp;
+ return 0;
+}
/*
- * Try to find an existing layer_node vnode refering
- * to it, otherwise make a new layer_node vnode which
- * contains a reference to the lower vnode.
+ * layer_node_create: try to find an existing layerfs vnode refering to it,
+ * otherwise make a new vnode which contains a reference to the lower vnode.
*
- * >>> we assume that the lower node is already locked upon entry, so we
- * propagate the lock state to upper node <<
+ * => Caller should lock the lower node.
*/
int
-layer_node_create(struct mount *mp, struct vnode *lowervp, struct vnode **newvpp)
+layer_node_create(struct mount *mp, struct vnode *lowervp, struct vnode **nvpp)
{
struct vnode *aliasvp;
struct layer_mount *lmp = MOUNTTOLAYERMOUNT(mp);
+ KASSERT(VOP_ISLOCKED(lowervp));
+
mutex_enter(&lmp->layerm_hashlock);
aliasvp = layer_node_find(mp, lowervp);
if (aliasvp != NULL) {
/*
- * layer_node_find has taken another reference
- * to the alias vnode and moved the lock holding to
- * aliasvp
+ * Note: layer_node_find() has taken another reference to
+ * the alias vnode and moved the lock holding to aliasvp.
*/
#ifdef LAYERFS_DIAGNOSTIC
if (layerfs_debug)
@@ -289,48 +275,33 @@
int error;
mutex_exit(&lmp->layerm_hashlock);
-
/*
- * Get new vnode.
+ * Get a new vnode. Make it to reference the layer_node.
+ * Note: aliasvp will be return with the reference held.
*/
+ error = (lmp->layerm_alloc)(mp, lowervp, &aliasvp);
+ if (error)
+ return error;
#ifdef LAYERFS_DIAGNOSTIC
if (layerfs_debug)
printf("layer_node_create: create new alias vnode\n");
#endif
-
- /*
- * Make new vnode reference the layer_node.
- */
- if ((error = (lmp->layerm_alloc)(mp, lowervp, &aliasvp)) != 0)
- return error;
-
- /*
- * aliasvp is already VREF'd by getnewvnode()
- */
}
/*
- * Now that we have VREF'd the upper vnode, release the reference
- * to the lower node. The existence of the layer_node retains one
+ * Now that we acquired a reference on the upper vnode, release one
+ * on the lower node. The existence of the layer_node retains one
* reference to the lower node.
*/
vrele(lowervp);
-
-#ifdef DIAGNOSTIC
- if (lowervp->v_usecount < 1) {
- /* Should never happen... */
- vprint("layer_node_create: alias", aliasvp);
- vprint("layer_node_create: lower", lowervp);
- panic("layer_node_create: lower has 0 usecount.");
- }
-#endif
+ KASSERT(lowervp->v_usecount > 0);
#ifdef LAYERFS_DIAGNOSTIC
if (layerfs_debug)
vprint("layer_node_create: alias", aliasvp);
#endif
- *newvpp = aliasvp;
- return (0);
+ *nvpp = aliasvp;
+ return 0;
}
#ifdef LAYERFS_DIAGNOSTIC
Index: src/sys/miscfs/genfs/layer_vfsops.c
diff -u src/sys/miscfs/genfs/layer_vfsops.c:1.32 src/sys/miscfs/genfs/layer_vfsops.c:1.33
--- src/sys/miscfs/genfs/layer_vfsops.c:1.32 Fri Jan 8 11:35:10 2010
+++ src/sys/miscfs/genfs/layer_vfsops.c Fri Jul 2 03:16:01 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: layer_vfsops.c,v 1.32 2010/01/08 11:35:10 pooka Exp $ */
+/* $NetBSD: layer_vfsops.c,v 1.33 2010/07/02 03:16:01 rmind Exp $ */
/*
* Copyright (c) 1999 National Aeronautics & Space Administration
@@ -32,6 +32,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
+
/*
* Copyright (c) 1992, 1993, 1995
* The Regents of the University of California. All rights reserved.
@@ -69,17 +70,15 @@
*/
/*
- * generic layer vfs ops.
+ * Generic layer VFS operations.
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: layer_vfsops.c,v 1.32 2010/01/08 11:35:10 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: layer_vfsops.c,v 1.33 2010/07/02 03:16:01 rmind Exp $");
#include <sys/param.h>
#include <sys/sysctl.h>
#include <sys/systm.h>
-#include <sys/time.h>
-#include <sys/proc.h>
#include <sys/vnode.h>
#include <sys/mount.h>
#include <sys/namei.h>
@@ -104,14 +103,12 @@
default:
return ENOTTY;
}
-
return 0;
}
/*
- * VFS start. Nothing needed here - the start routine
- * on the underlying filesystem will have been called
- * when that filesystem was mounted.
+ * VFS start. Nothing needed here - the start routine on the underlying
+ * filesystem will have been called when that filesystem was mounted.
*/
int
layerfs_start(struct mount *mp, int flags)
@@ -129,21 +126,14 @@
{
struct vnode *vp;
-#ifdef LAYERFS_DIAGNOSTIC
- if (layerfs_debug)
- printf("layerfs_root(mp = %p, vp = %p->%p)\n", mp,
- MOUNTTOLAYERMOUNT(mp)->layerm_rootvp,
- LAYERVPTOLOWERVP(MOUNTTOLAYERMOUNT(mp)->layerm_rootvp));
-#endif
-
- /*
- * Return locked reference to root.
- */
vp = MOUNTTOLAYERMOUNT(mp)->layerm_rootvp;
if (vp == NULL) {
*vpp = NULL;
- return (EINVAL);
+ return EINVAL;
}
+ /*
+ * Return root vnode with locked and with a reference held.
+ */
vref(vp);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
*vpp = vp;
@@ -160,27 +150,18 @@
int
layerfs_statvfs(struct mount *mp, struct statvfs *sbp)
{
- int error;
struct statvfs *sbuf;
+ int error;
- sbuf = kmem_alloc(sizeof(*sbuf), KM_SLEEP);
- if (sbuf == NULL)
+ sbuf = kmem_zalloc(sizeof(*sbuf), KM_SLEEP);
+ if (sbuf == NULL) {
return ENOMEM;
-
-#ifdef LAYERFS_DIAGNOSTIC
- if (layerfs_debug)
- printf("layerfs_statvfs(mp = %p, vp = %p->%p)\n", mp,
- MOUNTTOLAYERMOUNT(mp)->layerm_rootvp,
- LAYERVPTOLOWERVP(MOUNTTOLAYERMOUNT(mp)->layerm_rootvp));
-#endif
-
- (void)memset(sbuf, 0, sizeof(*sbuf));
-
+ }
error = VFS_STATVFS(MOUNTTOLAYERMOUNT(mp)->layerm_vfs, sbuf);
- if (error)
+ if (error) {
goto done;
-
- /* now copy across the "interesting" information and fake the rest */
+ }
+ /* Copy across the relevant data and fake the rest. */
sbp->f_flag = sbuf->f_flag;
sbp->f_bsize = sbuf->f_bsize;
sbp->f_frsize = sbuf->f_frsize;
@@ -208,53 +189,53 @@
/*
* XXX - Assumes no data cached at layer.
*/
- return (0);
+ return 0;
}
int
layerfs_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
{
- int error;
struct vnode *vp;
+ int error;
- if ((error = VFS_VGET(MOUNTTOLAYERMOUNT(mp)->layerm_vfs,
- ino, &vp))) {
+ error = VFS_VGET(MOUNTTOLAYERMOUNT(mp)->layerm_vfs, ino, &vp);
+ if (error) {
*vpp = NULL;
- return (error);
+ return error;
}
- if ((error = layer_node_create(mp, vp, vpp))) {
+ error = layer_node_create(mp, vp, vpp);
+ if (error) {
vput(vp);
*vpp = NULL;
- return (error);
+ return error;
}
-
- return (0);
+ return 0;
}
int
layerfs_fhtovp(struct mount *mp, struct fid *fidp, struct vnode **vpp)
{
- int error;
struct vnode *vp;
+ int error;
- if ((error = VFS_FHTOVP(MOUNTTOLAYERMOUNT(mp)->layerm_vfs,
- fidp, &vp)))
- return (error);
-
- if ((error = layer_node_create(mp, vp, vpp))) {
+ error = VFS_FHTOVP(MOUNTTOLAYERMOUNT(mp)->layerm_vfs, fidp, &vp);
+ if (error) {
+ return error;
+ }
+ error = layer_node_create(mp, vp, vpp);
+ if (error) {
vput(vp);
*vpp = NULL;
return (error);
}
-
- return (0);
+ return 0;
}
int
layerfs_vptofh(struct vnode *vp, struct fid *fhp, size_t *fh_size)
{
- return (VFS_VPTOFH(LAYERVPTOLOWERVP(vp), fhp, fh_size));
+ return VFS_VPTOFH(LAYERVPTOLOWERVP(vp), fhp, fh_size);
}
/*
@@ -274,7 +255,8 @@
layerfs_snapshot(struct mount *mp, struct vnode *vp,
struct timespec *ts)
{
- return (EOPNOTSUPP);
+
+ return EOPNOTSUPP;
}
SYSCTL_SETUP(sysctl_vfs_layerfs_setup, "sysctl vfs.layerfs subtree setup")
@@ -313,11 +295,13 @@
int
layerfs_renamelock_enter(struct mount *mp)
{
+
return VFS_RENAMELOCK_ENTER(MOUNTTOLAYERMOUNT(mp)->layerm_vfs);
}
void
layerfs_renamelock_exit(struct mount *mp)
{
+
VFS_RENAMELOCK_EXIT(MOUNTTOLAYERMOUNT(mp)->layerm_vfs);
}
Index: src/sys/miscfs/genfs/layer_vnops.c
diff -u src/sys/miscfs/genfs/layer_vnops.c:1.41 src/sys/miscfs/genfs/layer_vnops.c:1.42
--- src/sys/miscfs/genfs/layer_vnops.c:1.41 Thu Jun 24 13:03:16 2010
+++ src/sys/miscfs/genfs/layer_vnops.c Fri Jul 2 03:16:01 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: layer_vnops.c,v 1.41 2010/06/24 13:03:16 hannken Exp $ */
+/* $NetBSD: layer_vnops.c,v 1.42 2010/07/02 03:16:01 rmind Exp $ */
/*
* Copyright (c) 1999 National Aeronautics & Space Administration
@@ -32,6 +32,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
+
/*
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
@@ -73,64 +74,30 @@
*/
/*
- * Null Layer vnode routines.
- *
- * (See mount_null(8) for more information.)
+ * Generic layer vnode operations.
*
* The layer.h, layer_extern.h, layer_vfs.c, and layer_vnops.c files provide
- * the core implementation of the null file system and most other stacked
- * fs's. The description below refers to the null file system, but the
- * services provided by the layer* files are useful for all layered fs's.
- *
- * The null layer duplicates a portion of the file system
- * name space under a new name. In this respect, it is
- * similar to the loopback file system. It differs from
- * the loopback fs in two respects: it is implemented using
- * a stackable layers techniques, and it's "null-node"s stack above
- * all lower-layer vnodes, not just over directory vnodes.
- *
- * The null layer has two purposes. First, it serves as a demonstration
- * of layering by proving a layer which does nothing. (It actually
- * does everything the loopback file system does, which is slightly
- * more than nothing.) Second, the null layer can serve as a prototype
- * layer. Since it provides all necessary layer framework,
- * new file system layers can be created very easily be starting
- * with a null layer.
- *
- * The remainder of the man page examines the null layer as a basis
- * for constructing new layers.
- *
- *
- * INSTANTIATING NEW NULL LAYERS
- *
- * New null layers are created with mount_null(8).
- * Mount_null(8) takes two arguments, the pathname
- * of the lower vfs (target-pn) and the pathname where the null
- * layer will appear in the namespace (alias-pn). After
- * the null layer is put into place, the contents
- * of target-pn subtree will be aliased under alias-pn.
- *
- * It is conceivable that other overlay filesystems will take different
- * parameters. For instance, data migration or access controll layers might
- * only take one pathname which will serve both as the target-pn and
- * alias-pn described above.
- *
- *
- * OPERATION OF A NULL LAYER
- *
- * The null layer is the minimum file system layer,
- * simply bypassing all possible operations to the lower layer
- * for processing there. The majority of its activity centers
- * on the bypass routine, through which nearly all vnode operations
- * pass.
- *
- * The bypass routine accepts arbitrary vnode operations for
- * handling by the lower layer. It begins by examing vnode
- * operation arguments and replacing any layered nodes by their
- * lower-layer equivalents. It then invokes the operation
- * on the lower layer. Finally, it replaces the layered nodes
- * in the arguments and, if a vnode is return by the operation,
- * stacks a layered node on top of the returned vnode.
+ * the core implementation of stacked file-systems.
+ *
+ * The layerfs duplicates a portion of the file system name space under
+ * a new name. In this respect, it is similar to the loopback file system.
+ * It differs from the loopback fs in two respects: it is implemented using
+ * a stackable layers technique, and it is "layerfs-nodes" stack above all
+ * lower-layer vnodes, not just over directory vnodes.
+ *
+ * OPERATION OF LAYERFS
+ *
+ * The layerfs is the minimum file system layer, bypassing all possible
+ * operations to the lower layer for processing there. The majority of its
+ * activity centers on the bypass routine, through which nearly all vnode
+ * operations pass.
+ *
+ * The bypass routine accepts arbitrary vnode operations for handling by
+ * the lower layer. It begins by examining vnode operation arguments and
+ * replacing any layered nodes by their lower-layer equivalents. It then
+ * invokes an operation on the lower layer. Finally, it replaces the
+ * layered nodes in the arguments and, if a vnode is returned by the
+ * operation, stacks a layered node on top of the returned vnode.
*
* The bypass routine in this file, layer_bypass(), is suitable for use
* by many different layered filesystems. It can be used by multiple
@@ -143,96 +110,67 @@
* default vnode operation in its vnodeopv_entry_desc table. Additionally
* the filesystem must store the bypass entry point in the layerm_bypass
* field of struct layer_mount. All other layer routines in this file will
- * use the layerm_bypass routine.
+ * use the layerm_bypass() routine.
*
* Although the bypass routine handles most operations outright, a number
- * of operations are special cased, and handled by the layered fs. One
- * group, layer_setattr, layer_getattr, layer_access, layer_open, and
- * layer_fsync, perform layer-specific manipulation in addition to calling
- * the bypass routine. The other group
-
- * Although bypass handles most operations, vop_getattr, vop_lock,
- * vop_unlock, vop_inactive, vop_reclaim, and vop_print are not
- * bypassed. Vop_getattr must change the fsid being returned.
- * Vop_lock and vop_unlock must handle any locking for the
- * current vnode as well as pass the lock request down.
- * Vop_inactive and vop_reclaim are not bypassed so that
- * they can handle freeing null-layer specific data. Vop_print
- * is not bypassed to avoid excessive debugging information.
- * Also, certain vnode operations change the locking state within
- * the operation (create, mknod, remove, link, rename, mkdir, rmdir,
- * and symlink). Ideally these operations should not change the
- * lock state, but should be changed to let the caller of the
- * function unlock them. Otherwise all intermediate vnode layers
- * (such as union, umapfs, etc) must catch these functions to do
+ * of operations are special cased and handled by the layerfs. For instance,
+ * layer_getattr() must change the fsid being returned. While layer_lock()
+ * and layer_unlock() must handle any locking for the current vnode as well
+ * as pass the lock request down. layer_inactive() and layer_reclaim() are
+ * not bypassed so that they can handle freeing layerfs-specific data. Also,
+ * certain vnode operations (create, mknod, remove, link, rename, mkdir,
+ * rmdir, and symlink) change the locking state within the operation. Ideally
+ * these operations should not change the lock state, but should be changed
+ * to let the caller of the function unlock them. Otherwise, all intermediate
+ * vnode layers (such as union, umapfs, etc) must catch these functions to do
* the necessary locking at their layer.
*
- *
* INSTANTIATING VNODE STACKS
*
- * Mounting associates the null layer with a lower layer,
- * effect stacking two VFSes. Vnode stacks are instead
- * created on demand as files are accessed.
- *
- * The initial mount creates a single vnode stack for the
- * root of the new null layer. All other vnode stacks
- * are created as a result of vnode operations on
- * this or other null vnode stacks.
- *
- * New vnode stacks come into existence as a result of
- * an operation which returns a vnode.
- * The bypass routine stacks a null-node above the new
+ * Mounting associates "layerfs-nodes" stack and lower layer, in effect
+ * stacking two VFSes. The initial mount creates a single vnode stack for
+ * the root of the new layerfs. All other vnode stacks are created as a
+ * result of vnode operations on this or other layerfs vnode stacks.
+ *
+ * New vnode stacks come into existence as a result of an operation which
+ * returns a vnode. The bypass routine stacks a layerfs-node above the new
* vnode before returning it to the caller.
*
- * For example, imagine mounting a null layer with
- * "mount_null /usr/include /dev/layer/null".
- * Changing directory to /dev/layer/null will assign
- * the root null-node (which was created when the null layer was mounted).
- * Now consider opening "sys". A vop_lookup would be
- * done on the root null-node. This operation would bypass through
- * to the lower layer which would return a vnode representing
- * the UFS "sys". layer_bypass then builds a null-node
- * aliasing the UFS "sys" and returns this to the caller.
- * Later operations on the null-node "sys" will repeat this
- * process when constructing other vnode stacks.
- *
- *
- * CREATING OTHER FILE SYSTEM LAYERS
- *
- * One of the easiest ways to construct new file system layers is to make
- * a copy of the null layer, rename all files and variables, and
- * then begin modifing the copy. Sed can be used to easily rename
- * all variables.
+ * For example, imagine mounting a null layer with:
*
- * The umap layer is an example of a layer descended from the
- * null layer.
+ * "mount_null /usr/include /dev/layer/null"
*
+ * Changing directory to /dev/layer/null will assign the root layerfs-node,
+ * which was created when the null layer was mounted). Now consider opening
+ * "sys". A layer_lookup() would be performed on the root layerfs-node.
+ * This operation would bypass through to the lower layer which would return
+ * a vnode representing the UFS "sys". Then, layer_bypass() builds a
+ * layerfs-node aliasing the UFS "sys" and returns this to the caller.
+ * Later operations on the layerfs-node "sys" will repeat this process when
+ * constructing other vnode stacks.
*
* INVOKING OPERATIONS ON LOWER LAYERS
*
- * There are two techniques to invoke operations on a lower layer
- * when the operation cannot be completely bypassed. Each method
- * is appropriate in different situations. In both cases,
- * it is the responsibility of the aliasing layer to make
- * the operation arguments "correct" for the lower layer
- * by mapping an vnode arguments to the lower layer.
- *
- * The first approach is to call the aliasing layer's bypass routine.
- * This method is most suitable when you wish to invoke the operation
- * currently being handled on the lower layer. It has the advantage
- * that the bypass routine already must do argument mapping.
- * An example of this is null_getattrs in the null layer.
- *
- * A second approach is to directly invoke vnode operations on
- * the lower layer with the VOP_OPERATIONNAME interface.
- * The advantage of this method is that it is easy to invoke
- * arbitrary operations on the lower layer. The disadvantage
- * is that vnodes' arguments must be manually mapped.
- *
+ * There are two techniques to invoke operations on a lower layer when the
+ * operation cannot be completely bypassed. Each method is appropriate in
+ * different situations. In both cases, it is the responsibility of the
+ * aliasing layer to make the operation arguments "correct" for the lower
+ * layer by mapping any vnode arguments to the lower layer.
+ *
+ * The first approach is to call the aliasing layer's bypass routine. This
+ * method is most suitable when you wish to invoke the operation currently
+ * being handled on the lower layer. It has the advantage that the bypass
+ * routine already must do argument mapping. An example of this is
+ * layer_getattr().
+ *
+ * A second approach is to directly invoke vnode operations on the lower
+ * layer with the VOP_OPERATIONNAME interface. The advantage of this method
+ * is that it is easy to invoke arbitrary operations on the lower layer.
+ * The disadvantage is that vnode's arguments must be manually mapped.
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: layer_vnops.c,v 1.41 2010/06/24 13:03:16 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: layer_vnops.c,v 1.42 2010/07/02 03:16:01 rmind Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -249,7 +187,6 @@
#include <miscfs/genfs/layer_extern.h>
#include <miscfs/genfs/genfs.h>
-
/*
* This is the 08-June-99 bypass routine, based on the 10-Apr-92 bypass
* routine by John Heidemann.
@@ -345,7 +282,6 @@
if (reles & VDESC_VP0_WILLRELE)
vref(*this_vp_p);
}
-
}
/*
@@ -402,9 +338,8 @@
**vppp = NULL;
}
}
-
- out:
- return (error);
+out:
+ return error;
}
/*
@@ -422,15 +357,14 @@
struct componentname * a_cnp;
} */ *ap = v;
struct componentname *cnp = ap->a_cnp;
- int flags = cnp->cn_flags;
struct vnode *dvp, *lvp, *ldvp;
- int error;
+ int error, flags = cnp->cn_flags;
dvp = ap->a_dvp;
if ((flags & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
(cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
- return (EROFS);
+ return EROFS;
ldvp = LAYERVPTOLOWERVP(dvp);
ap->a_dvp = ldvp;
@@ -448,7 +382,6 @@
* is done in the layers below us.
*/
if (ldvp == lvp) {
-
/*
* Got the same object back, because we looked up ".",
* or ".." in the root node of a mount point.
@@ -458,13 +391,13 @@
*ap->a_vpp = dvp;
vrele(lvp);
} else if (lvp != NULL) {
- /* dvp, ldvp and vp are all locked */
+ /* Note: dvp, ldvp and lvp are all locked. */
error = layer_node_create(dvp->v_mount, lvp, ap->a_vpp);
if (error) {
vput(lvp);
}
}
- return (error);
+ return error;
}
/*
@@ -487,16 +420,16 @@
vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL ||
vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) &&
(vp->v_mount->mnt_flag & MNT_RDONLY))
- return (EROFS);
+ return EROFS;
if (vap->va_size != VNOVAL) {
switch (vp->v_type) {
case VDIR:
- return (EISDIR);
+ return EISDIR;
case VCHR:
case VBLK:
case VSOCK:
case VFIFO:
- return (0);
+ return 0;
case VREG:
case VLNK:
default:
@@ -505,10 +438,10 @@
* mounted read-only.
*/
if (vp->v_mount->mnt_flag & MNT_RDONLY)
- return (EROFS);
+ return EROFS;
}
}
- return (LAYERFS_DO_BYPASS(vp, ap));
+ return LAYERFS_DO_BYPASS(vp, ap);
}
/*
@@ -526,11 +459,13 @@
struct vnode *vp = ap->a_vp;
int error;
- if ((error = LAYERFS_DO_BYPASS(vp, ap)) != 0)
- return (error);
+ error = LAYERFS_DO_BYPASS(vp, ap);
+ if (error) {
+ return error;
+ }
/* Requires that arguments be restored. */
ap->a_vap->va_fsid = vp->v_mount->mnt_stat.f_fsidx.__fsid_val[0];
- return (0);
+ return 0;
}
int
@@ -556,13 +491,13 @@
case VLNK:
case VREG:
if (vp->v_mount->mnt_flag & MNT_RDONLY)
- return (EROFS);
+ return EROFS;
break;
default:
break;
}
}
- return (LAYERFS_DO_BYPASS(vp, ap));
+ return LAYERFS_DO_BYPASS(vp, ap);
}
/*
@@ -571,7 +506,12 @@
int
layer_open(void *v)
{
- struct vop_open_args *ap = v;
+ struct vop_open_args /* {
+ const struct vnodeop_desc *a_desc;
+ struct vnode *a_vp;
+ int a_mode;
+ kauth_cred_t a_cred;
+ } */ *ap = v;
struct vnode *vp = ap->a_vp;
enum vtype lower_type = LAYERVPTOLOWERVP(vp)->v_type;
@@ -600,7 +540,6 @@
mutex_exit(&vp->v_interlock);
ap->a_flags &= ~LK_INTERLOCK;
}
-
return LAYERFS_DO_BYPASS(vp, ap);
}
@@ -631,12 +570,10 @@
/*
* If vinvalbuf is calling us, it's a "shallow fsync" -- don't bother
* syncing the underlying vnodes, since they'll be fsync'ed when
- * reclaimed; otherwise,
- * pass it through to the underlying layer.
+ * reclaimed; otherwise, pass it through to the underlying layer.
*
* XXX Do we still need to worry about shallow fsync?
*/
-
int
layer_fsync(void *v)
{
@@ -652,11 +589,9 @@
if (ap->a_flags & FSYNC_RECLAIM) {
return 0;
}
-
- return (LAYERFS_DO_BYPASS(ap->a_vp, ap));
+ return LAYERFS_DO_BYPASS(ap->a_vp, ap);
}
-
int
layer_inactive(void *v)
{
@@ -686,8 +621,7 @@
* That's too much work for now.
*/
VOP_UNLOCK(vp);
-
- return (0);
+ return 0;
}
int
@@ -698,17 +632,17 @@
struct vnode *a_vp;
struct componentname *a_cnp;
} */ *ap = v;
-
- int error;
- struct vnode *vp = ap->a_vp;
+ struct vnode *vp = ap->a_vp;
+ int error;
vref(vp);
- if ((error = LAYERFS_DO_BYPASS(vp, ap)) == 0)
+ error = LAYERFS_DO_BYPASS(vp, ap);
+ if (error == 0) {
VTOLAYER(vp)->layer_flags |= LAYERFS_REMOVED;
-
+ }
vrele(vp);
- return (error);
+ return error;
}
int
@@ -722,10 +656,8 @@
struct vnode *a_tvp;
struct componentname *a_tcnp;
} */ *ap = v;
-
+ struct vnode *fdvp = ap->a_fdvp, *tvp;
int error;
- struct vnode *fdvp = ap->a_fdvp;
- struct vnode *tvp;
tvp = ap->a_tvp;
if (tvp) {
@@ -740,8 +672,7 @@
VTOLAYER(tvp)->layer_flags |= LAYERFS_REMOVED;
vrele(tvp);
}
-
- return (error);
+ return error;
}
int
@@ -756,12 +687,13 @@
struct vnode *vp = ap->a_vp;
vref(vp);
- if ((error = LAYERFS_DO_BYPASS(vp, ap)) == 0)
+ error = LAYERFS_DO_BYPASS(vp, ap);
+ if (error == 0) {
VTOLAYER(vp)->layer_flags |= LAYERFS_REMOVED;
-
+ }
vrele(vp);
- return (error);
+ return error;
}
int
@@ -781,8 +713,7 @@
* decomissioned, so we have to be careful about calling
* VOP's on ourself. We must be careful as VXLOCK is set.
*/
- /* After this assignment, this node will not be re-used. */
- if ((vp == lmp->layerm_rootvp)) {
+ if (vp == lmp->layerm_rootvp) {
/*
* Oops! We no longer have a root node. Most likely reason is
* that someone forcably unmunted the underlying fs.
@@ -791,6 +722,7 @@
*/
lmp->layerm_rootvp = NULL;
}
+ /* After this assignment, this node will not be re-used. */
xp->layer_lowervp = NULL;
mutex_enter(&lmp->layerm_hashlock);
LIST_REMOVE(xp, layer_hash);
@@ -799,7 +731,7 @@
vp->v_data = NULL;
vrele(lowervp);
- return (0);
+ return 0;
}
/*
@@ -819,9 +751,10 @@
} */ *ap = v;
struct vnode *vp;
- ap->a_vp = vp = LAYERVPTOLOWERVP(ap->a_vp);
+ vp = LAYERVPTOLOWERVP(ap->a_vp);
+ ap->a_vp = vp;
- return (VCALL(vp, ap->a_desc->vdesc_offset, ap));
+ return VCALL(vp, ap->a_desc->vdesc_offset, ap);
}
int
@@ -832,7 +765,7 @@
} */ *ap = v;
struct vnode *vp = ap->a_vp;
printf ("\ttag VT_LAYERFS, vp=%p, lowervp=%p\n", vp, LAYERVPTOLOWERVP(vp));
- return (0);
+ return 0;
}
/*
@@ -847,17 +780,15 @@
struct buf *a_bp;
} */ *ap = v;
struct buf *bp = ap->a_bp;
- int error;
struct vnode *savedvp;
+ int error;
savedvp = bp->b_vp;
bp->b_vp = LAYERVPTOLOWERVP(bp->b_vp);
-
error = VOP_BWRITE(bp);
-
bp->b_vp = savedvp;
- return (error);
+ return error;
}
int
Index: src/sys/miscfs/nullfs/null.h
diff -u src/sys/miscfs/nullfs/null.h:1.18 src/sys/miscfs/nullfs/null.h:1.19
--- src/sys/miscfs/nullfs/null.h:1.18 Sat Jun 28 01:34:06 2008
+++ src/sys/miscfs/nullfs/null.h Fri Jul 2 03:16:01 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: null.h,v 1.18 2008/06/28 01:34:06 rumble Exp $ */
+/* $NetBSD: null.h,v 1.19 2010/07/02 03:16:01 rmind Exp $ */
/*
* Copyright (c) 1999 National Aeronautics & Space Administration
@@ -68,6 +68,9 @@
* @(#)null.h 8.2 (Berkeley) 1/21/94
*/
+#ifndef _MISCFS_NULLFS_H_
+#define _MISCFS_NULLFS_H_
+
#include <miscfs/genfs/layer.h>
struct null_args {
@@ -104,18 +107,7 @@
#define null_vnode ln.layer_vnode
#define null_flags ln.layer_flags
-int null_node_create(struct mount *, struct vnode *,
- struct vnode **);
-
#define MOUNTTONULLMOUNT(mp) ((struct null_mount *)((mp)->mnt_data))
-#define VTONULL(vp) ((struct null_node *)(vp)->v_data)
-#define NULLTOV(xp) ((xp)->null_vnode)
-#ifdef NULLFS_DIAGNOSTIC
-struct vnode *layer_checkvp(struct vnode *, char *, int);
-#define NULLVPTOLOWERVP(vp) layer_checkvp((vp), __FILE__, __LINE__)
-#else
-#define NULLVPTOLOWERVP(vp) (VTONULL(vp)->null_lowervp)
-#endif
extern int (**null_vnodeop_p)(void *);
extern struct vfsops nullfs_vfsops;
@@ -123,3 +115,4 @@
void nullfs_init(void);
#endif /* _KERNEL */
+#endif /* _MISCFS_NULLFS_H_ */
Index: src/sys/miscfs/nullfs/null_vfsops.c
diff -u src/sys/miscfs/nullfs/null_vfsops.c:1.81 src/sys/miscfs/nullfs/null_vfsops.c:1.82
--- src/sys/miscfs/nullfs/null_vfsops.c:1.81 Thu Jun 24 13:03:16 2010
+++ src/sys/miscfs/nullfs/null_vfsops.c Fri Jul 2 03:16:01 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: null_vfsops.c,v 1.81 2010/06/24 13:03:16 hannken Exp $ */
+/* $NetBSD: null_vfsops.c,v 1.82 2010/07/02 03:16:01 rmind Exp $ */
/*
* Copyright (c) 1999 National Aeronautics & Space Administration
@@ -32,6 +32,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
+
/*
* Copyright (c) 1992, 1993, 1995
* The Regents of the University of California. All rights reserved.
@@ -69,18 +70,17 @@
*/
/*
- * Null Layer
- * (See null_vnops.c for a description of what this does.)
+ * Null file-system: VFS operations.
+ *
+ * See null_vnops.c for a description.
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: null_vfsops.c,v 1.81 2010/06/24 13:03:16 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: null_vfsops.c,v 1.82 2010/07/02 03:16:01 rmind Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/sysctl.h>
-#include <sys/time.h>
-#include <sys/proc.h>
#include <sys/vnode.h>
#include <sys/mount.h>
#include <sys/namei.h>
@@ -96,25 +96,17 @@
static struct sysctllog *nullfs_sysctl_log;
-/*
- * Mount null layer
- */
int
nullfs_mount(struct mount *mp, const char *path, void *data, size_t *data_len)
{
- struct lwp *l = curlwp;
- struct nameidata nd;
- struct null_args *args = data;
struct vnode *lowerrootvp, *vp;
+ struct null_args *args = data;
struct null_mount *nmp;
struct layer_mount *lmp;
- int error = 0;
-
-#ifdef NULLFS_DIAGNOSTIC
- printf("nullfs_mount(mp = %p)\n", mp);
-#endif
+ struct nameidata nd;
+ int error;
- if (*data_len < sizeof *args)
+ if (*data_len < sizeof(*args))
return EINVAL;
if (mp->mnt_flag & MNT_GETARGS) {
@@ -122,35 +114,23 @@
if (lmp == NULL)
return EIO;
args->la.target = NULL;
- *data_len = sizeof *args;
+ *data_len = sizeof(*args);
return 0;
}
- /*
- * Update is not supported
- */
+ /* Update is not supported. */
if (mp->mnt_flag & MNT_UPDATE)
return EOPNOTSUPP;
- /*
- * Find lower node
- */
+ /* Find the lower vnode and lock it. */
NDINIT(&nd, LOOKUP, FOLLOW|LOCKLEAF, UIO_USERSPACE, args->la.target);
- if ((error = namei(&nd)) != 0)
- return (error);
-
- /*
- * Sanity check on lower vnode
- */
+ if ((error = namei(&nd)) != 0) {
+ return error;
+ }
lowerrootvp = nd.ni_vp;
- /*
- * First cut at fixing up upper mount point
- */
- nmp = (struct null_mount *) malloc(sizeof(struct null_mount),
- M_UFSMNT, M_WAITOK); /* XXX */
- memset(nmp, 0, sizeof(struct null_mount));
-
+ /* Create the mount point. */
+ nmp = malloc(sizeof(struct null_mount), M_UFSMNT, M_WAITOK | M_ZERO);
mp->mnt_data = nmp;
nmp->nullm_vfs = lowerrootvp->v_mount;
if (nmp->nullm_vfs->mnt_flag & MNT_LOCAL)
@@ -171,83 +151,54 @@
nmp->nullm_node_hashtbl = hashinit(desiredvnodes, HASH_LIST, true,
&nmp->nullm_node_hash);
- /*
- * Fix up null node for root vnode
- */
+ /* Setup a null node for root vnode. */
error = layer_node_create(mp, lowerrootvp, &vp);
- /*
- * Make sure the fixup worked
- */
if (error) {
vput(lowerrootvp);
hashdone(nmp->nullm_node_hashtbl, HASH_LIST,
nmp->nullm_node_hash);
- free(nmp, M_UFSMNT); /* XXX */
- return (error);
+ free(nmp, M_UFSMNT);
+ return error;
}
/*
- * Keep a held reference to the root vnode.
- * It is vrele'd in nullfs_unmount.
+ * Keep a held reference to the root vnode. It will be released on
+ * umount. Note: nullfs is MP-safe.
*/
vp->v_vflag |= VV_ROOT;
nmp->nullm_rootvp = vp;
-
- /* We don't need kernel_lock. */
mp->mnt_iflag |= IMNT_MPSAFE;
-
- /*
- * Unlock the node
- */
VOP_UNLOCK(vp);
error = set_statvfs_info(path, UIO_USERSPACE, args->la.target,
- UIO_USERSPACE, mp->mnt_op->vfs_name, mp, l);
-#ifdef NULLFS_DIAGNOSTIC
- printf("nullfs_mount: lower %s, alias at %s\n",
- mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname);
-#endif
+ UIO_USERSPACE, mp->mnt_op->vfs_name, mp, curlwp);
return error;
}
-/*
- * Free reference to null layer
- */
int
nullfs_unmount(struct mount *mp, int mntflags)
{
struct null_mount *nmp = MOUNTTONULLMOUNT(mp);
struct vnode *null_rootvp = nmp->nullm_rootvp;
- int error;
- int flags = 0;
-
-#ifdef NULLFS_DIAGNOSTIC
- printf("nullfs_unmount(mp = %p)\n", mp);
-#endif
+ int error, flags = 0;
if (mntflags & MNT_FORCE)
flags |= FORCECLOSE;
if (null_rootvp->v_usecount > 1 && (mntflags & MNT_FORCE) == 0)
- return (EBUSY);
+ return EBUSY;
+
if ((error = vflush(mp, null_rootvp, flags)) != 0)
- return (error);
+ return error;
-#ifdef NULLFS_DIAGNOSTIC
- vprint("alias root of lower", null_rootvp);
-#endif
- /*
- * Blow it away for future re-use
- */
+ /* Eliminate all activity and release the vnode. */
vgone(null_rootvp);
- /*
- * Finally, throw away the null_mount structure
- */
+ /* Finally, destroy the mount point structures. */
hashdone(nmp->nullm_node_hashtbl, HASH_LIST, nmp->nullm_node_hash);
mutex_destroy(&nmp->nullm_hashlock);
- free(mp->mnt_data, M_UFSMNT); /* XXX */
+ free(mp->mnt_data, M_UFSMNT);
mp->mnt_data = NULL;
- return (0);
+ return 0;
}
extern const struct vnodeopv_desc null_vnodeop_opv_desc;
@@ -322,6 +273,5 @@
error = ENOTTY;
break;
}
-
return error;
}
Index: src/sys/miscfs/nullfs/null_vnops.c
diff -u src/sys/miscfs/nullfs/null_vnops.c:1.34 src/sys/miscfs/nullfs/null_vnops.c:1.35
--- src/sys/miscfs/nullfs/null_vnops.c:1.34 Sun Dec 11 12:24:51 2005
+++ src/sys/miscfs/nullfs/null_vnops.c Fri Jul 2 03:16:01 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: null_vnops.c,v 1.34 2005/12/11 12:24:51 christos Exp $ */
+/* $NetBSD: null_vnops.c,v 1.35 2010/07/02 03:16:01 rmind Exp $ */
/*
* Copyright (c) 1999 National Aeronautics & Space Administration
@@ -32,6 +32,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
+
/*
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
@@ -73,181 +74,56 @@
*/
/*
- * Null Layer
- *
- * (See mount_null(8) for more information.)
- *
- * The null layer duplicates a portion of the file system
- * name space under a new name. In this respect, it is
- * similar to the loopback file system. It differs from
- * the loopback fs in two respects: it is implemented using
- * a stackable layers technique, and its "null-nodes" stack above
- * all lower-layer vnodes, not just over directory vnodes.
- *
- * The null layer has two purposes. First, it serves as a demonstration
- * of layering by providing a layer which does nothing (it actually
- * does everything the loopback file system does, which is slightly
- * more than nothing). Second, the null layer can serve as a prototype
- * layer. Since it provides all necessary layer framework,
- * new file system layers can be created very easily by starting
- * with a null layer.
- *
- * The remainder of this comment examines the null layer as a basis
- * for constructing new layers.
- *
- *
- * INSTANTIATING NEW NULL LAYERS
- *
- * New null layers are created with mount_null(8).
- * mount_null(8) takes two arguments, the pathname
- * of the lower vfs (target-pn) and the pathname where the null
- * layer will appear in the namespace (alias-pn). After
- * the null layer is put into place, the contents
- * of target-pn subtree will be aliased under alias-pn.
- *
- *
- * OPERATION OF A NULL LAYER
- *
- * The null layer is the minimum file system layer,
- * simply bypassing all possible operations to the lower layer
- * for processing there. The majority of its activity centers
- * on the bypass routine, through which nearly all vnode operations
- * pass.
- *
- * The bypass routine accepts arbitrary vnode operations for
- * handling by the lower layer. It begins by examining vnode
- * operation arguments and replacing any null-nodes by their
- * lower-layer equivalents. It then invokes the operation
- * on the lower layer. Finally, it replaces the null-nodes
- * in the arguments and, if a vnode is returned by the operation,
- * stacks a null-node on top of the returned vnode.
- *
- * Although bypass handles most operations, vop_getattr, vop_lock,
- * vop_unlock, vop_inactive, vop_reclaim, and vop_print are not
- * bypassed. vop_getattr must change the fsid being returned.
- * vop_lock and vop_unlock must handle any locking for the
- * current vnode as well as pass the lock request down.
- * vop_inactive and vop_reclaim are not bypassed so that
- * they can handle freeing null-layer specific data. vop_print
- * is not bypassed to avoid excessive debugging information.
- * Also, certain vnode operations change the locking state within
- * the operation (create, mknod, remove, link, rename, mkdir, rmdir,
- * and symlink). Ideally these operations should not change the
- * lock state, but should be changed to let the caller of the
- * function unlock them. Otherwise all intermediate vnode layers
- * (such as union, umapfs, etc) must catch these functions to do
- * the necessary locking at their layer.
- *
- *
- * INSTANTIATING VNODE STACKS
- *
- * Mounting associates the null layer with a lower layer,
- * in effect stacking two VFSes. Vnode stacks are instead
- * created on demand as files are accessed.
- *
- * The initial mount creates a single vnode stack for the
- * root of the new null layer. All other vnode stacks
- * are created as a result of vnode operations on
- * this or other null vnode stacks.
- *
- * New vnode stacks come into existence as a result of
- * an operation which returns a vnode.
- * The bypass routine stacks a null-node above the new
- * vnode before returning it to the caller.
- *
- * For example, imagine mounting a null layer with
- * "mount_null /usr/include /dev/layer/null".
- * Changing directory to /dev/layer/null will assign
- * the root null-node (which was created when the null layer was mounted).
- * Now consider opening "sys". A vop_lookup would be
- * done on the root null-node. This operation would bypass through
- * to the lower layer which would return a vnode representing
- * the UFS "sys". null_bypass then builds a null-node
- * aliasing the UFS "sys" and returns this to the caller.
- * Later operations on the null-node "sys" will repeat this
- * process when constructing other vnode stacks.
- *
- *
- * CREATING OTHER FILE SYSTEM LAYERS
- *
- * One of the easiest ways to construct new file system layers is to make
- * a copy of the null layer, rename all files and variables, and
- * then begin modifying the copy. sed(1) can be used to easily rename
- * all variables.
- *
- * The umap layer is an example of a layer descended from the
- * null layer.
- *
- *
- * INVOKING OPERATIONS ON LOWER LAYERS
- *
- * There are two techniques to invoke operations on a lower layer
- * when the operation cannot be completely bypassed. Each method
- * is appropriate in different situations. In both cases,
- * it is the responsibility of the aliasing layer to make
- * the operation arguments "correct" for the lower layer
- * by mapping any vnode arguments to the lower layer.
- *
- * The first approach is to call the aliasing layer's bypass routine.
- * This method is most suitable when you wish to invoke the operation
- * currently being handled on the lower layer. It has the advantage
- * that the bypass routine already must do argument mapping.
- * An example of this is null_getattrs in the null layer.
- *
- * A second approach is to directly invoke vnode operations on
- * the lower layer with the VOP_OPERATIONNAME interface.
- * The advantage of this method is that it is easy to invoke
- * arbitrary operations on the lower layer. The disadvantage
- * is that vnode arguments must be manually mapped.
+ * Null file-system.
*
+ * Implemented using layerfs, see layer_vnops.c for a description.
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: null_vnops.c,v 1.34 2005/12/11 12:24:51 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: null_vnops.c,v 1.35 2010/07/02 03:16:01 rmind Exp $");
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/proc.h>
-#include <sys/time.h>
#include <sys/vnode.h>
-#include <sys/mount.h>
-#include <sys/namei.h>
-#include <sys/malloc.h>
-#include <sys/buf.h>
+
#include <miscfs/genfs/genfs.h>
-#include <miscfs/nullfs/null.h>
#include <miscfs/genfs/layer_extern.h>
+#include <miscfs/nullfs/null.h>
/*
- * Global vfs data structures
+ * Global VFS data structures.
*/
+
int (**null_vnodeop_p)(void *);
+
const struct vnodeopv_entry_desc null_vnodeop_entries[] = {
- { &vop_default_desc, layer_bypass },
+ { &vop_default_desc, layer_bypass },
- { &vop_lookup_desc, layer_lookup },
- { &vop_setattr_desc, layer_setattr },
- { &vop_getattr_desc, layer_getattr },
- { &vop_access_desc, layer_access },
- { &vop_lock_desc, layer_lock },
- { &vop_unlock_desc, layer_unlock },
- { &vop_islocked_desc, layer_islocked },
- { &vop_fsync_desc, layer_fsync },
- { &vop_inactive_desc, layer_inactive },
- { &vop_reclaim_desc, layer_reclaim },
- { &vop_print_desc, layer_print },
- { &vop_remove_desc, layer_remove },
- { &vop_rename_desc, layer_rename },
- { &vop_rmdir_desc, layer_rmdir },
-
- { &vop_open_desc, layer_open }, /* mount option handling */
-
- { &vop_bwrite_desc, layer_bwrite },
- { &vop_bmap_desc, layer_bmap },
- { &vop_getpages_desc, layer_getpages },
- { &vop_putpages_desc, layer_putpages },
+ { &vop_lookup_desc, layer_lookup },
+ { &vop_setattr_desc, layer_setattr },
+ { &vop_getattr_desc, layer_getattr },
+ { &vop_access_desc, layer_access },
+ { &vop_lock_desc, layer_lock },
+ { &vop_unlock_desc, layer_unlock },
+ { &vop_islocked_desc, layer_islocked },
+ { &vop_fsync_desc, layer_fsync },
+ { &vop_inactive_desc, layer_inactive },
+ { &vop_reclaim_desc, layer_reclaim },
+ { &vop_print_desc, layer_print },
+ { &vop_remove_desc, layer_remove },
+ { &vop_rename_desc, layer_rename },
+ { &vop_rmdir_desc, layer_rmdir },
+
+ { &vop_open_desc, layer_open }, /* mount option handling */
+
+ { &vop_bwrite_desc, layer_bwrite },
+ { &vop_bmap_desc, layer_bmap },
+ { &vop_getpages_desc, layer_getpages },
+ { &vop_putpages_desc, layer_putpages },
{ NULL, NULL }
};
-const struct vnodeopv_desc null_vnodeop_opv_desc =
- { &null_vnodeop_p, null_vnodeop_entries };
+
+const struct vnodeopv_desc null_vnodeop_opv_desc = {
+ &null_vnodeop_p, null_vnodeop_entries
+};