Mon Apr 11 01:36:59 2011 UTC ()
ZZmsg


(dholland)
diff -r1.136 -r1.137 src/sys/kern/vfs_lookup.c

cvs diff -r1.136 -r1.137 src/sys/kern/vfs_lookup.c (expand / switch to unified diff)

--- src/sys/kern/vfs_lookup.c 2011/04/11 01:36:28 1.136
+++ src/sys/kern/vfs_lookup.c 2011/04/11 01:36:59 1.137
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: vfs_lookup.c,v 1.136 2011/04/11 01:36:28 dholland Exp $ */ 1/* $NetBSD: vfs_lookup.c,v 1.137 2011/04/11 01:36:59 dholland Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1982, 1986, 1989, 1993 4 * Copyright (c) 1982, 1986, 1989, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * (c) UNIX System Laboratories, Inc. 6 * (c) UNIX System Laboratories, Inc.
7 * All or some portions of this file are derived from material licensed 7 * All or some portions of this file are derived from material licensed
8 * to the University of California by American Telephone and Telegraph 8 * to the University of California by American Telephone and Telegraph
9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
10 * the permission of UNIX System Laboratories, Inc. 10 * the permission of UNIX System Laboratories, Inc.
11 * 11 *
12 * Redistribution and use in source and binary forms, with or without 12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions 13 * modification, are permitted provided that the following conditions
14 * are met: 14 * are met:
@@ -27,27 +27,27 @@ @@ -27,27 +27,27 @@
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE. 34 * SUCH DAMAGE.
35 * 35 *
36 * @(#)vfs_lookup.c 8.10 (Berkeley) 5/27/95 36 * @(#)vfs_lookup.c 8.10 (Berkeley) 5/27/95
37 */ 37 */
38 38
39#include <sys/cdefs.h> 39#include <sys/cdefs.h>
40__KERNEL_RCSID(0, "$NetBSD: vfs_lookup.c,v 1.136 2011/04/11 01:36:28 dholland Exp $"); 40__KERNEL_RCSID(0, "$NetBSD: vfs_lookup.c,v 1.137 2011/04/11 01:36:59 dholland Exp $");
41 41
42#include "opt_magiclinks.h" 42#include "opt_magiclinks.h"
43 43
44#include <sys/param.h> 44#include <sys/param.h>
45#include <sys/systm.h> 45#include <sys/systm.h>
46#include <sys/kernel.h> 46#include <sys/kernel.h>
47#include <sys/syslimits.h> 47#include <sys/syslimits.h>
48#include <sys/time.h> 48#include <sys/time.h>
49#include <sys/namei.h> 49#include <sys/namei.h>
50#include <sys/vnode.h> 50#include <sys/vnode.h>
51#include <sys/mount.h> 51#include <sys/mount.h>
52#include <sys/errno.h> 52#include <sys/errno.h>
53#include <sys/filedesc.h> 53#include <sys/filedesc.h>
@@ -403,26 +403,28 @@ struct namei_state { @@ -403,26 +403,28 @@ struct namei_state {
403 struct nameidata *ndp; 403 struct nameidata *ndp;
404 struct componentname *cnp; 404 struct componentname *cnp;
405 405
406 /* used by the pieces of namei */ 406 /* used by the pieces of namei */
407 struct vnode *namei_startdir; /* The directory namei() starts from. */ 407 struct vnode *namei_startdir; /* The directory namei() starts from. */
408 408
409 /* used by the pieces of lookup */ 409 /* used by the pieces of lookup */
410 int lookup_alldone; 410 int lookup_alldone;
411 411
412 int docache; /* == 0 do not cache last component */ 412 int docache; /* == 0 do not cache last component */
413 int rdonly; /* lookup read-only flag bit */ 413 int rdonly; /* lookup read-only flag bit */
414 struct vnode *dp; /* the directory we are searching */ 414 struct vnode *dp; /* the directory we are searching */
415 int slashes; 415 int slashes;
 416
 417 unsigned attempt_retry:1; /* true if error allows emul retry */
416}; 418};
417 419
418 420
419/* 421/*
420 * Initialize the namei working state. 422 * Initialize the namei working state.
421 */ 423 */
422static void 424static void
423namei_init(struct namei_state *state, struct nameidata *ndp) 425namei_init(struct namei_state *state, struct nameidata *ndp)
424{ 426{
425 state->ndp = ndp; 427 state->ndp = ndp;
426 state->cnp = &ndp->ni_cnd; 428 state->cnp = &ndp->ni_cnd;
427 KASSERT((state->cnp->cn_flags & INRELOOKUP) == 0); 429 KASSERT((state->cnp->cn_flags & INRELOOKUP) == 0);
428 430
@@ -1223,151 +1225,171 @@ terminal: @@ -1223,151 +1225,171 @@ terminal:
1223 if ((cnp->cn_flags & LOCKLEAF) == 0) { 1225 if ((cnp->cn_flags & LOCKLEAF) == 0) {
1224 VOP_UNLOCK(state->dp); 1226 VOP_UNLOCK(state->dp);
1225 } 1227 }
1226 return (0); 1228 return (0);
1227 1229
1228bad: 1230bad:
1229 ndp->ni_vp = NULL; 1231 ndp->ni_vp = NULL;
1230 return (error); 1232 return (error);
1231} 1233}
1232 1234
1233////////////////////////////// 1235//////////////////////////////
1234 1236
1235static int 1237static int
1236do_namei(struct namei_state *state, struct vnode *forcecwd, 1238namei_oneroot(struct namei_state *state, struct vnode *forcecwd,
1237 int neverfollow, int inhibitmagic) 1239 int neverfollow, int inhibitmagic)
1238{ 1240{
1239 int error; 
1240 
1241 struct nameidata *ndp = state->ndp; 1241 struct nameidata *ndp = state->ndp;
1242 struct componentname *cnp = state->cnp; 1242 struct componentname *cnp = state->cnp;
1243 const char *savepath = NULL; 1243 int error;
1244 
1245 KASSERT(cnp == &ndp->ni_cnd); 
1246 
1247 if (cnp->cn_flags & TRYEMULROOT) { 
1248 savepath = pathbuf_stringcopy_get(ndp->ni_pathbuf); 
1249 } 
1250 
1251 emul_retry: 
1252 
1253 if (savepath != NULL) { 
1254 /* kinda gross */ 
1255 strcpy(ndp->ni_pathbuf->pb_path, savepath); 
1256 pathbuf_stringcopy_put(ndp->ni_pathbuf, savepath); 
1257 savepath = NULL; 
1258 } 
1259 1244
1260 error = namei_start(state, forcecwd); 1245 error = namei_start(state, forcecwd);
1261 if (error) { 1246 if (error) {
1262 if (savepath != NULL) { 
1263 pathbuf_stringcopy_put(ndp->ni_pathbuf, savepath); 
1264 } 
1265 return error; 1247 return error;
1266 } 1248 }
1267 1249
1268 /* 1250 /*
1269 * Keep going until we run out of path components. 1251 * Keep going until we run out of path components.
1270 */ 1252 */
1271 for (;;) { 1253 for (;;) {
1272 1254
1273 /* 1255 /*
1274 * If the directory we're on is unmounted, bail out. 1256 * If the directory we're on is unmounted, bail out.
1275 * XXX: should this also check if it's unlinked? 1257 * XXX: should this also check if it's unlinked?
1276 */ 1258 */
1277 if (state->namei_startdir->v_mount == NULL) { 1259 if (state->namei_startdir->v_mount == NULL) {
1278 if (savepath != NULL) { 
1279 pathbuf_stringcopy_put(ndp->ni_pathbuf, savepath); 
1280 } 
1281 namei_end(state); 1260 namei_end(state);
1282 return (ENOENT); 1261 return (ENOENT);
1283 } 1262 }
1284 1263
1285 /* 1264 /*
1286 * Look up the next path component. 1265 * Look up the next path component.
1287 * (currently, this may consume more than one) 1266 * (currently, this may consume more than one)
1288 */ 1267 */
1289 error = do_lookup(state, state->namei_startdir); 1268 error = do_lookup(state, state->namei_startdir);
1290 if (error != 0) { 1269 if (error != 0) {
1291 /* XXX this should use namei_end() */ 1270 /* XXX this should use namei_end() */
1292 if (ndp->ni_dvp) { 1271 if (ndp->ni_dvp) {
1293 vput(ndp->ni_dvp); 1272 vput(ndp->ni_dvp);
1294 } 1273 }
1295 if (ndp->ni_erootdir != NULL) { 1274 /*
1296 /* Retry the whole thing from the normal root */ 1275 * Note that if we're doing TRYEMULROOT we can
1297 cnp->cn_flags &= ~TRYEMULROOT; 1276 * retry with the normal root. Setting this
1298 goto emul_retry; 1277 * here matches previous practice, but the
1299 } 1278 * previous practice didn't make much sense
1300 KASSERT(savepath == NULL); 1279 * and somebody should sit down and figure out
 1280 * which cases should cause retry and which
 1281 * shouldn't. XXX.
 1282 */
 1283 state->attempt_retry = 1;
1301 return (error); 1284 return (error);
1302 } 1285 }
1303 1286
1304 /* 1287 /*
1305 * If we've reached a symbolic link, follow it, unless we 1288 * If we've reached a symbolic link, follow it, unless we
1306 * aren't supposed to. 1289 * aren't supposed to.
1307 */ 1290 */
1308 if (namei_atsymlink(state)) { 1291 if (namei_atsymlink(state)) {
1309 if (neverfollow) { 1292 if (neverfollow) {
1310 error = EINVAL; 1293 error = EINVAL;
1311 } else { 1294 } else {
1312 error = namei_follow(state, inhibitmagic); 1295 error = namei_follow(state, inhibitmagic);
1313 } 1296 }
1314 if (error) { 1297 if (error) {
1315 KASSERT(ndp->ni_dvp != ndp->ni_vp); 1298 KASSERT(ndp->ni_dvp != ndp->ni_vp);
1316 vput(ndp->ni_dvp); 1299 vput(ndp->ni_dvp);
1317 vput(ndp->ni_vp); 1300 vput(ndp->ni_vp);
1318 ndp->ni_vp = NULL; 1301 ndp->ni_vp = NULL;
1319 if (savepath != NULL) { 
1320 pathbuf_stringcopy_put(ndp->ni_pathbuf, savepath); 
1321 } 
1322 return error; 1302 return error;
1323 } 1303 }
1324 } 1304 }
1325 else { 1305 else {
1326 break; 1306 break;
1327 } 1307 }
1328 } 1308 }
1329 1309
1330 /* 1310 /*
1331 * Done. 1311 * Done.
1332 */ 1312 */
1333 1313
1334 /* 1314 /*
1335 * If LOCKPARENT is not set, the parent directory isn't returned. 1315 * If LOCKPARENT is not set, the parent directory isn't returned.
1336 */ 1316 */
1337 if ((cnp->cn_flags & LOCKPARENT) == 0 && ndp->ni_dvp != NULL) { 1317 if ((cnp->cn_flags & LOCKPARENT) == 0 && ndp->ni_dvp != NULL) {
1338 if (ndp->ni_dvp == ndp->ni_vp) { 1318 if (ndp->ni_dvp == ndp->ni_vp) {
1339 vrele(ndp->ni_dvp); 1319 vrele(ndp->ni_dvp);
1340 } else { 1320 } else {
1341 vput(ndp->ni_dvp); 1321 vput(ndp->ni_dvp);
1342 } 1322 }
1343 ndp->ni_dvp = NULL; 1323 ndp->ni_dvp = NULL;
1344 } 1324 }
1345 1325
 1326 return 0;
 1327}
 1328
 1329static int
 1330namei_tryemulroot(struct namei_state *state, struct vnode *forcecwd,
 1331 int neverfollow, int inhibitmagic)
 1332{
 1333 int error;
 1334
 1335 struct nameidata *ndp = state->ndp;
 1336 struct componentname *cnp = state->cnp;
 1337 const char *savepath = NULL;
 1338
 1339 KASSERT(cnp == &ndp->ni_cnd);
 1340
 1341 if (cnp->cn_flags & TRYEMULROOT) {
 1342 savepath = pathbuf_stringcopy_get(ndp->ni_pathbuf);
 1343 }
 1344
 1345 emul_retry:
 1346 state->attempt_retry = 0;
 1347
 1348 error = namei_oneroot(state, forcecwd, neverfollow, inhibitmagic);
 1349 if (error) {
 1350 /*
 1351 * Once namei has started up, the existence of ni_erootdir
 1352 * tells us whether we're working from an emulation root.
 1353 * The TRYEMULROOT flag isn't necessarily authoritative.
 1354 */
 1355 if (ndp->ni_erootdir != NULL && state->attempt_retry) {
 1356 /* Retry the whole thing using the normal root */
 1357 cnp->cn_flags &= ~TRYEMULROOT;
 1358 state->attempt_retry = 0;
 1359
 1360 /* kinda gross */
 1361 strcpy(ndp->ni_pathbuf->pb_path, savepath);
 1362 pathbuf_stringcopy_put(ndp->ni_pathbuf, savepath);
 1363 savepath = NULL;
 1364
 1365 goto emul_retry;
 1366 }
 1367 }
1346 if (savepath != NULL) { 1368 if (savepath != NULL) {
1347 pathbuf_stringcopy_put(ndp->ni_pathbuf, savepath); 1369 pathbuf_stringcopy_put(ndp->ni_pathbuf, savepath);
1348 } 1370 }
1349 1371 return error;
1350 return 0; 
1351} 1372}
1352 1373
1353int 1374int
1354namei(struct nameidata *ndp) 1375namei(struct nameidata *ndp)
1355{ 1376{
1356 struct namei_state state; 1377 struct namei_state state;
1357 int error; 1378 int error;
1358 1379
1359 namei_init(&state, ndp); 1380 namei_init(&state, ndp);
1360 error = do_namei(&state, NULL, 0/*!neverfollow*/, 0/*!inhibitmagic*/); 1381 error = namei_tryemulroot(&state, NULL,
 1382 0/*!neverfollow*/, 0/*!inhibitmagic*/);
1361 namei_cleanup(&state); 1383 namei_cleanup(&state);
1362 1384
1363 return error; 1385 return error;
1364} 1386}
1365 1387
1366//////////////////////////////////////////////////////////// 1388////////////////////////////////////////////////////////////
1367 1389
1368/* 1390/*
1369 * Externally visible interfaces used by nfsd (bletch, yuk, XXX) 1391 * Externally visible interfaces used by nfsd (bletch, yuk, XXX)
1370 * 1392 *
1371 * The "index" version differs from the "main" version in that it's 1393 * The "index" version differs from the "main" version in that it's
1372 * called from a different place in a different context. For now I 1394 * called from a different place in a different context. For now I
1373 * want to be able to shuffle code in from one call site without 1395 * want to be able to shuffle code in from one call site without
@@ -1376,27 +1398,28 @@ namei(struct nameidata *ndp) @@ -1376,27 +1398,28 @@ namei(struct nameidata *ndp)
1376 * It turns out that the "main" version was a cut and pasted copy of 1398 * It turns out that the "main" version was a cut and pasted copy of
1377 * namei with a few changes; the "index" version on the other hand 1399 * namei with a few changes; the "index" version on the other hand
1378 * always takes a single component and is an elaborate form of calling 1400 * always takes a single component and is an elaborate form of calling
1379 * VOP_LOOKUP once. 1401 * VOP_LOOKUP once.
1380 */ 1402 */
1381 1403
1382int 1404int
1383lookup_for_nfsd(struct nameidata *ndp, struct vnode *forcecwd, int neverfollow) 1405lookup_for_nfsd(struct nameidata *ndp, struct vnode *forcecwd, int neverfollow)
1384{ 1406{
1385 struct namei_state state; 1407 struct namei_state state;
1386 int error; 1408 int error;
1387 1409
1388 namei_init(&state, ndp); 1410 namei_init(&state, ndp);
1389 error = do_namei(&state, forcecwd, neverfollow, 1/*inhibitmagic*/); 1411 error = namei_tryemulroot(&state, forcecwd,
 1412 neverfollow, 1/*inhibitmagic*/);
1390 namei_cleanup(&state); 1413 namei_cleanup(&state);
1391 1414
1392 return error; 1415 return error;
1393} 1416}
1394 1417
1395static int 1418static int
1396do_lookup_for_nfsd_index(struct namei_state *state, struct vnode *startdir) 1419do_lookup_for_nfsd_index(struct namei_state *state, struct vnode *startdir)
1397{ 1420{
1398 int error = 0; 1421 int error = 0;
1399 1422
1400 struct componentname *cnp = state->cnp; 1423 struct componentname *cnp = state->cnp;
1401 struct nameidata *ndp = state->ndp; 1424 struct nameidata *ndp = state->ndp;
1402 const char *cp; /* pointer into pathname argument */ 1425 const char *cp; /* pointer into pathname argument */