Module Name: src
Committed By: dholland
Date: Mon Apr 11 01:33:05 UTC 2011
Modified Files:
src/sys/kern: vfs_lookup.c
src/sys/nfs: nfs_serv.c nfs_srvsubs.c
Log Message:
kern/ZZmsg
To generate a diff of this commit:
cvs rdiff -u -r1.132 -r1.133 src/sys/kern/vfs_lookup.c
cvs rdiff -u -r1.157 -r1.158 src/sys/nfs/nfs_serv.c
cvs rdiff -u -r1.9 -r1.10 src/sys/nfs/nfs_srvsubs.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/kern/vfs_lookup.c
diff -u src/sys/kern/vfs_lookup.c:1.132 src/sys/kern/vfs_lookup.c:1.133
--- src/sys/kern/vfs_lookup.c:1.132 Tue Mar 22 15:16:23 2011
+++ src/sys/kern/vfs_lookup.c Mon Apr 11 01:33:04 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: vfs_lookup.c,v 1.132 2011/03/22 15:16:23 pooka Exp $ */
+/* $NetBSD: vfs_lookup.c,v 1.133 2011/04/11 01:33:04 dholland Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1993
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_lookup.c,v 1.132 2011/03/22 15:16:23 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_lookup.c,v 1.133 2011/04/11 01:33:04 dholland Exp $");
#include "opt_magiclinks.h"
@@ -415,9 +415,6 @@
int slashes;
};
-/* XXX reorder things to make this decl unnecessary */
-static int do_lookup(struct namei_state *state, struct vnode *startdir);
-
/*
* Initialize the namei working state.
@@ -437,6 +434,21 @@
state->rdonly = 0;
state->dp = NULL;
state->slashes = 0;
+
+#ifdef DIAGNOSTIC
+ if (!state->cnp->cn_cred)
+ panic("namei: bad cred/proc");
+ if (state->cnp->cn_nameiop & (~OPMASK))
+ panic("namei: nameiop contaminated with flags");
+ if (state->cnp->cn_flags & OPMASK)
+ panic("namei: flags contaminated with nameiops");
+#endif
+
+ /*
+ * The buffer for name translation shall be the one inside the
+ * pathbuf.
+ */
+ state->ndp->ni_pnbuf = state->ndp->ni_pathbuf->pb_path;
}
/*
@@ -457,100 +469,101 @@
//////////////////////////////
/*
- * Start up namei. Early portion.
- *
- * This is divided from namei_start2 by the emul_retry: point.
- */
-static void
-namei_start1(struct namei_state *state)
-{
-
-#ifdef DIAGNOSTIC
- if (!state->cnp->cn_cred)
- panic("namei: bad cred/proc");
- if (state->cnp->cn_nameiop & (~OPMASK))
- panic("namei: nameiop contaminated with flags");
- if (state->cnp->cn_flags & OPMASK)
- panic("namei: flags contaminated with nameiops");
-#endif
-
- /*
- * The buffer for name translation shall be the one inside the
- * pathbuf.
- */
- state->ndp->ni_pnbuf = state->ndp->ni_pathbuf->pb_path;
-}
-
-/*
- * Start up namei. Copy the path, find the root dir and cwd, establish
- * the starting directory for lookup, and lock it.
+ * Get the directory context.
+ * Initializes the rootdir and erootdir state and returns a reference
+ * to the starting dir.
*/
-static int
-namei_start2(struct namei_state *state)
+static struct vnode *
+namei_getstartdir(struct namei_state *state)
{
struct nameidata *ndp = state->ndp;
struct componentname *cnp = state->cnp;
-
struct cwdinfo *cwdi; /* pointer to cwd state */
struct lwp *self = curlwp; /* thread doing namei() */
+ struct vnode *rootdir, *erootdir, *curdir, *startdir;
- /* length includes null terminator (was originally from copyinstr) */
- ndp->ni_pathlen = strlen(ndp->ni_pnbuf) + 1;
+ cwdi = self->l_proc->p_cwdi;
+ rw_enter(&cwdi->cwdi_lock, RW_READER);
- /*
- * POSIX.1 requirement: "" is not a valid file name.
- */
- if (ndp->ni_pathlen == 1) {
- ndp->ni_vp = NULL;
- return ENOENT;
+ /* root dir */
+ if (cwdi->cwdi_rdir == NULL || (cnp->cn_flags & NOCHROOT)) {
+ rootdir = rootvnode;
+ } else {
+ rootdir = cwdi->cwdi_rdir;
}
- ndp->ni_loopcnt = 0;
+ /* emulation root dir, if any */
+ if ((cnp->cn_flags & TRYEMULROOT) == 0) {
+ /* if we don't want it, don't fetch it */
+ erootdir = NULL;
+ } else if (cnp->cn_flags & EMULROOTSET) {
+ /* explicitly set emulroot; "/../" doesn't override this */
+ erootdir = ndp->ni_erootdir;
+ } else if (!strncmp(ndp->ni_pnbuf, "/../", 4)) {
+ /* explicit reference to real rootdir */
+ erootdir = NULL;
+ } else {
+ /* may be null */
+ erootdir = cwdi->cwdi_edir;
+ }
- /*
- * Get root directory for the translation.
- */
- cwdi = self->l_proc->p_cwdi;
- rw_enter(&cwdi->cwdi_lock, RW_READER);
- state->namei_startdir = cwdi->cwdi_rdir;
- if (state->namei_startdir == NULL)
- state->namei_startdir = rootvnode;
- ndp->ni_rootdir = state->namei_startdir;
+ /* current dir */
+ curdir = cwdi->cwdi_cdir;
- /*
- * Check if starting from root directory or current directory.
- */
- if (ndp->ni_pnbuf[0] == '/') {
- if (cnp->cn_flags & TRYEMULROOT) {
- if (cnp->cn_flags & EMULROOTSET) {
- /* Called from (eg) emul_find_interp() */
- state->namei_startdir = ndp->ni_erootdir;
- } else {
- if (cwdi->cwdi_edir == NULL
- || (ndp->ni_pnbuf[1] == '.'
- && ndp->ni_pnbuf[2] == '.'
- && ndp->ni_pnbuf[3] == '/')) {
- ndp->ni_erootdir = NULL;
- } else {
- state->namei_startdir = cwdi->cwdi_edir;
- ndp->ni_erootdir = state->namei_startdir;
- }
- }
- } else {
- ndp->ni_erootdir = NULL;
- if (cnp->cn_flags & NOCHROOT)
- state->namei_startdir = ndp->ni_rootdir = rootvnode;
- }
+ if (ndp->ni_pnbuf[0] != '/') {
+ startdir = curdir;
+ erootdir = NULL;
+ } else if (cnp->cn_flags & TRYEMULROOT && erootdir != NULL) {
+ startdir = erootdir;
} else {
- state->namei_startdir = cwdi->cwdi_cdir;
- ndp->ni_erootdir = NULL;
+ startdir = rootdir;
+ erootdir = NULL;
}
- vref(state->namei_startdir);
- rw_exit(&cwdi->cwdi_lock);
+
+ state->ndp->ni_rootdir = rootdir;
+ state->ndp->ni_erootdir = erootdir;
/*
- * Ktrace it.
+ * Get a reference to the start dir so we can safely unlock cwdi.
+ *
+ * XXX: should we hold references to rootdir and erootdir while
+ * we're running? What happens if a multithreaded process chroots
+ * during namei?
*/
+ vref(startdir);
+
+ rw_exit(&cwdi->cwdi_lock);
+ return startdir;
+}
+
+/*
+ * Get the directory context for the nfsd case, in parallel to
+ * getstartdir. Initializes the rootdir and erootdir state and
+ * returns a reference to the passed-instarting dir.
+ */
+static struct vnode *
+namei_getstartdir_for_nfsd(struct namei_state *state, struct vnode *startdir)
+{
+ /* always use the real root, and never set an emulation root */
+ state->ndp->ni_rootdir = rootvnode;
+ state->ndp->ni_erootdir = NULL;
+
+ vref(startdir);
+ return startdir;
+}
+
+
+/*
+ * Ktrace the namei operation.
+ */
+static void
+namei_ktrace(struct namei_state *state)
+{
+ struct nameidata *ndp = state->ndp;
+ struct componentname *cnp = state->cnp;
+ struct lwp *self = curlwp; /* thread doing namei() */
+ const char *emul_path;
+
if (ktrpoint(KTR_NAMEI)) {
if (ndp->ni_erootdir != NULL) {
/*
@@ -561,7 +574,6 @@
* in the exec_package - so we get it passed in ni_next
* (this is a hack).
*/
- const char *emul_path;
if (cnp->cn_flags & EMULROOTSET)
emul_path = ndp->ni_next;
else
@@ -571,6 +583,40 @@
} else
ktrnamei(ndp->ni_pnbuf, ndp->ni_pathlen);
}
+}
+
+/*
+ * Start up namei. Copy the path, find the root dir and cwd, establish
+ * the starting directory for lookup, and lock it. Also calls ktrace when
+ * appropriate.
+ */
+static int
+namei_start(struct namei_state *state, int isnfsd, struct vnode *forcecwd)
+{
+ struct nameidata *ndp = state->ndp;
+
+ /* length includes null terminator (was originally from copyinstr) */
+ ndp->ni_pathlen = strlen(ndp->ni_pnbuf) + 1;
+
+ /*
+ * POSIX.1 requirement: "" is not a valid file name.
+ */
+ if (ndp->ni_pathlen == 1) {
+ ndp->ni_vp = NULL;
+ return ENOENT;
+ }
+
+ ndp->ni_loopcnt = 0;
+
+ /* Get starting directory, set up root, and ktrace. */
+ if (isnfsd) {
+ state->namei_startdir = namei_getstartdir_for_nfsd(state,
+ forcecwd);
+ /* no ktrace */
+ } else {
+ state->namei_startdir = namei_getstartdir(state);
+ namei_ktrace(state);
+ }
vn_lock(state->namei_startdir, LK_EXCLUSIVE | LK_RETRY);
@@ -578,8 +624,7 @@
}
/*
- * Undo namei_start: unlock and release the current lookup directory,
- * and discard the path buffer.
+ * Undo namei_start: unlock and release the current lookup directory.
*/
static void
namei_end(struct namei_state *state)
@@ -1053,6 +1098,8 @@
KASSERT(cnp == &ndp->ni_cnd);
+ cnp->cn_nameptr = ndp->ni_pnbuf;
+
error = lookup_start(state, startdir);
if (error) {
goto bad;
@@ -1193,8 +1240,6 @@
KASSERT(cnp == &ndp->ni_cnd);
- namei_start1(state);
-
if (cnp->cn_flags & TRYEMULROOT) {
savepath = pathbuf_stringcopy_get(ndp->ni_pathbuf);
}
@@ -1208,7 +1253,7 @@
savepath = NULL;
}
- error = namei_start2(state);
+ error = namei_start(state, 0/*not nfsd*/, NULL);
if (error) {
if (savepath != NULL) {
pathbuf_stringcopy_put(ndp->ni_pathbuf, savepath);
@@ -1216,17 +1261,27 @@
return error;
}
- /* Loop through symbolic links */
+ /*
+ * Keep going until we run out of path components.
+ */
for (;;) {
+
+ /*
+ * If the directory we're on is unmounted, bail out.
+ * XXX: should this also check if it's unlinked?
+ */
if (state->namei_startdir->v_mount == NULL) {
- /* Give up if the directory is no longer mounted */
if (savepath != NULL) {
pathbuf_stringcopy_put(ndp->ni_pathbuf, savepath);
}
namei_end(state);
return (ENOENT);
}
- cnp->cn_nameptr = ndp->ni_pnbuf;
+
+ /*
+ * Look up the next path component.
+ * (currently, this may consume more than one)
+ */
error = do_lookup(state, state->namei_startdir);
if (error != 0) {
/* XXX this should use namei_end() */
@@ -1243,7 +1298,8 @@
}
/*
- * Check for symbolic link
+ * If we've reached a symbolic link, follow it, unless we
+ * aren't supposed to.
*/
if (namei_atsymlink(state)) {
error = namei_follow(state);
@@ -1264,15 +1320,19 @@
}
/*
- * Done
+ * Done.
*/
- if ((cnp->cn_flags & LOCKPARENT) == 0 && ndp->ni_dvp) {
+ /*
+ * If LOCKPARENT is not set, the parent directory isn't returned.
+ */
+ if ((cnp->cn_flags & LOCKPARENT) == 0 && ndp->ni_dvp != NULL) {
if (ndp->ni_dvp == ndp->ni_vp) {
vrele(ndp->ni_dvp);
} else {
vput(ndp->ni_dvp);
}
+ ndp->ni_dvp = NULL;
}
if (savepath != NULL) {
@@ -1317,25 +1377,14 @@
int linklen;
char *cp;
- ndp->ni_pnbuf = ndp->ni_pathbuf->pb_path;
namei_init(&state, ndp);
- /*
- * BEGIN wodge of code from nfsd
- */
-
- vref(dp);
- vn_lock(dp, LK_EXCLUSIVE | LK_RETRY);
+ namei_start(&state, 1/*nfsd*/, dp);
for (;;) {
- state.cnp->cn_nameptr = state.ndp->ni_pnbuf;
-
- /*
- * END wodge of code from nfsd
- */
-
error = do_lookup(&state, dp);
+
if (error) {
/* BEGIN from nfsd */
if (ndp->ni_dvp) {
@@ -1444,10 +1493,16 @@
struct namei_state state;
int error;
- vref(startdir);
+ /*
+ * Note: the name sent in here is not/should not be allowed to
+ * contain a slash.
+ */
- ndp->ni_pnbuf = ndp->ni_pathbuf->pb_path;
- ndp->ni_cnd.cn_nameptr = ndp->ni_pnbuf;
+ ndp->ni_pathlen = strlen(ndp->ni_pathbuf->pb_path) + 1;
+ ndp->ni_pnbuf = NULL;
+ ndp->ni_cnd.cn_nameptr = NULL;
+
+ vref(startdir);
namei_init(&state, ndp);
error = do_lookup(&state, startdir);
Index: src/sys/nfs/nfs_serv.c
diff -u src/sys/nfs/nfs_serv.c:1.157 src/sys/nfs/nfs_serv.c:1.158
--- src/sys/nfs/nfs_serv.c:1.157 Sat Mar 19 01:34:24 2011
+++ src/sys/nfs/nfs_serv.c Mon Apr 11 01:33:05 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: nfs_serv.c,v 1.157 2011/03/19 01:34:24 dholland Exp $ */
+/* $NetBSD: nfs_serv.c,v 1.158 2011/04/11 01:33:05 dholland Exp $ */
/*
* Copyright (c) 1989, 1993
@@ -55,7 +55,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nfs_serv.c,v 1.157 2011/03/19 01:34:24 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nfs_serv.c,v 1.158 2011/04/11 01:33:05 dholland Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -427,9 +427,6 @@
ind = nd;
VOP_UNLOCK(nd.ni_vp);
ind.ni_pathbuf = ipb;
- ind.ni_pathlen = strlen(nfs_pub.np_index);
- ind.ni_pnbuf = NULL;
- ind.ni_cnd.cn_nameptr = NULL;
error = lookup_for_nfsd_index(&ind, nd.ni_vp);
if (!error) {
Index: src/sys/nfs/nfs_srvsubs.c
diff -u src/sys/nfs/nfs_srvsubs.c:1.9 src/sys/nfs/nfs_srvsubs.c:1.10
--- src/sys/nfs/nfs_srvsubs.c:1.9 Sat Mar 19 01:34:24 2011
+++ src/sys/nfs/nfs_srvsubs.c Mon Apr 11 01:33:05 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: nfs_srvsubs.c,v 1.9 2011/03/19 01:34:24 dholland Exp $ */
+/* $NetBSD: nfs_srvsubs.c,v 1.10 2011/04/11 01:33:05 dholland Exp $ */
/*
* Copyright (c) 1989, 1993
@@ -70,7 +70,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nfs_srvsubs.c,v 1.9 2011/03/19 01:34:24 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nfs_srvsubs.c,v 1.10 2011/04/11 01:33:05 dholland Exp $");
#include <sys/param.h>
#include <sys/proc.h>
@@ -246,13 +246,8 @@
error = ENOMEM;
goto out;
}
- ndp->ni_pathlen = (tocp - path) + 1;
- /*ndp->ni_segflg = UIO_SYSSPACE; - obsolete */
- ndp->ni_rootdir = rootvnode;
- ndp->ni_erootdir = NULL;
if (pubflag) {
- ndp->ni_loopcnt = 0;
if (path[0] == '/')
dp = rootvnode;
} else {