Mon Apr 11 02:21:17 2011 UTC ()
description:
Update comments.


(dholland)
diff -r1.172 -r1.173 src/sys/kern/vfs_lookup.c

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

--- src/sys/kern/vfs_lookup.c 2011/04/11 02:21:01 1.172
+++ src/sys/kern/vfs_lookup.c 2011/04/11 02:21:17 1.173
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: vfs_lookup.c,v 1.172 2011/04/11 02:21:01 dholland Exp $ */ 1/* $NetBSD: vfs_lookup.c,v 1.173 2011/04/11 02:21:17 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.172 2011/04/11 02:21:01 dholland Exp $"); 40__KERNEL_RCSID(0, "$NetBSD: vfs_lookup.c,v 1.173 2011/04/11 02:21:17 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>
@@ -307,27 +307,30 @@ pathbuf_copyin(const char *userpath, str @@ -307,27 +307,30 @@ pathbuf_copyin(const char *userpath, str
307 if (pb == NULL) { 307 if (pb == NULL) {
308 return ENOMEM; 308 return ENOMEM;
309 } 309 }
310 error = copyinstr(userpath, pb->pb_path, PATH_MAX, NULL); 310 error = copyinstr(userpath, pb->pb_path, PATH_MAX, NULL);
311 if (error) { 311 if (error) {
312 pathbuf_destroy(pb); 312 pathbuf_destroy(pb);
313 return error; 313 return error;
314 } 314 }
315 *ret = pb; 315 *ret = pb;
316 return 0; 316 return 0;
317} 317}
318 318
319/* 319/*
320 * XXX should not exist 320 * XXX should not exist:
 321 * 1. whether a pointer is kernel or user should be statically checkable
 322 * 2. copyin should be handled by the upper part of the syscall layer,
 323 * not in here.
321 */ 324 */
322int 325int
323pathbuf_maybe_copyin(const char *path, enum uio_seg seg, struct pathbuf **ret) 326pathbuf_maybe_copyin(const char *path, enum uio_seg seg, struct pathbuf **ret)
324{ 327{
325 if (seg == UIO_USERSPACE) { 328 if (seg == UIO_USERSPACE) {
326 return pathbuf_copyin(path, ret); 329 return pathbuf_copyin(path, ret);
327 } else { 330 } else {
328 *ret = pathbuf_create(path); 331 *ret = pathbuf_create(path);
329 if (*ret == NULL) { 332 if (*ret == NULL) {
330 return ENOMEM; 333 return ENOMEM;
331 } 334 }
332 return 0; 335 return 0;
333 } 336 }
@@ -366,48 +369,91 @@ pathbuf_stringcopy_put(struct pathbuf *p @@ -366,48 +369,91 @@ pathbuf_stringcopy_put(struct pathbuf *p
366 KASSERT(str == pb->pb_pathcopy); 369 KASSERT(str == pb->pb_pathcopy);
367 KASSERT(pb->pb_pathcopyuses > 0); 370 KASSERT(pb->pb_pathcopyuses > 0);
368 pb->pb_pathcopyuses--; 371 pb->pb_pathcopyuses--;
369 if (pb->pb_pathcopyuses == 0) { 372 if (pb->pb_pathcopyuses == 0) {
370 PNBUF_PUT(pb->pb_pathcopy); 373 PNBUF_PUT(pb->pb_pathcopy);
371 pb->pb_pathcopy = NULL; 374 pb->pb_pathcopy = NULL;
372 } 375 }
373} 376}
374 377
375 378
376//////////////////////////////////////////////////////////// 379////////////////////////////////////////////////////////////
377 380
378/* 381/*
379 * Convert a pathname into a pointer to a locked vnode. 382 * namei: convert a pathname into a pointer to a (maybe-locked) vnode,
 383 * and maybe also its parent directory vnode, and assorted other guff.
 384 * See namei(9) for the interface documentation.
 385 *
380 * 386 *
381 * The FOLLOW flag is set when symbolic links are to be followed 387 * The FOLLOW flag is set when symbolic links are to be followed
382 * when they occur at the end of the name translation process. 388 * when they occur at the end of the name translation process.
383 * Symbolic links are always followed for all other pathname 389 * Symbolic links are always followed for all other pathname
384 * components other than the last. 390 * components other than the last.
385 * 391 *
386 * The segflg defines whether the name is to be copied from user 392 * The segflg defines whether the name is to be copied from user
387 * space or kernel space. 393 * space or kernel space.
388 * 394 *
389 * Overall outline of namei: 395 * Overall outline of namei:
390 * 396 *
391 * copy in name 397 * copy in name
392 * get starting directory 398 * get starting directory
393 * while (!done && !error) { 399 * while (!done && !error) {
394 * call lookup to search path. 400 * call lookup to search path.
395 * if symbolic link, massage name in buffer and continue 401 * if symbolic link, massage name in buffer and continue
396 * } 402 * }
397 */ 403 */
398 404
399/* 405/*
 406 * Search a pathname.
 407 * This is a very central and rather complicated routine.
 408 *
 409 * The pathname is pointed to by ni_ptr and is of length ni_pathlen.
 410 * The starting directory is passed in. The pathname is descended
 411 * until done, or a symbolic link is encountered. The variable ni_more
 412 * is clear if the path is completed; it is set to one if a symbolic
 413 * link needing interpretation is encountered.
 414 *
 415 * The flag argument is LOOKUP, CREATE, RENAME, or DELETE depending on
 416 * whether the name is to be looked up, created, renamed, or deleted.
 417 * When CREATE, RENAME, or DELETE is specified, information usable in
 418 * creating, renaming, or deleting a directory entry may be calculated.
 419 * If flag has LOCKPARENT or'ed into it, the parent directory is returned
 420 * locked. Otherwise the parent directory is not returned. If the target
 421 * of the pathname exists and LOCKLEAF is or'ed into the flag the target
 422 * is returned locked, otherwise it is returned unlocked. When creating
 423 * or renaming and LOCKPARENT is specified, the target may not be ".".
 424 * When deleting and LOCKPARENT is specified, the target may be ".".
 425 *
 426 * Overall outline of lookup:
 427 *
 428 * dirloop:
 429 * identify next component of name at ndp->ni_ptr
 430 * handle degenerate case where name is null string
 431 * if .. and crossing mount points and on mounted filesys, find parent
 432 * call VOP_LOOKUP routine for next component name
 433 * directory vnode returned in ni_dvp, locked.
 434 * component vnode returned in ni_vp (if it exists), locked.
 435 * if result vnode is mounted on and crossing mount points,
 436 * find mounted on vnode
 437 * if more components of name, do next level at dirloop
 438 * return the answer in ni_vp, locked if LOCKLEAF set
 439 * if LOCKPARENT set, return locked parent in ni_dvp
 440 */
 441
 442
 443/*
400 * Internal state for a namei operation. 444 * Internal state for a namei operation.
 445 *
 446 * cnp is always equal to &ndp->ni_cnp.
401 */ 447 */
402struct namei_state { 448struct namei_state {
403 struct nameidata *ndp; 449 struct nameidata *ndp;
404 struct componentname *cnp; 450 struct componentname *cnp;
405 451
406 int docache; /* == 0 do not cache last component */ 452 int docache; /* == 0 do not cache last component */
407 int rdonly; /* lookup read-only flag bit */ 453 int rdonly; /* lookup read-only flag bit */
408 int slashes; 454 int slashes;
409 455
410 unsigned attempt_retry:1; /* true if error allows emul retry */ 456 unsigned attempt_retry:1; /* true if error allows emul retry */
411}; 457};
412 458
413 459
@@ -517,27 +563,27 @@ namei_getstartdir(struct namei_state *st @@ -517,27 +563,27 @@ namei_getstartdir(struct namei_state *st
517 * XXX: should we hold references to rootdir and erootdir while 563 * XXX: should we hold references to rootdir and erootdir while
518 * we're running? What happens if a multithreaded process chroots 564 * we're running? What happens if a multithreaded process chroots
519 * during namei? 565 * during namei?
520 */ 566 */
521 vref(startdir); 567 vref(startdir);
522 568
523 rw_exit(&cwdi->cwdi_lock); 569 rw_exit(&cwdi->cwdi_lock);
524 return startdir; 570 return startdir;
525} 571}
526 572
527/* 573/*
528 * Get the directory context for the nfsd case, in parallel to 574 * Get the directory context for the nfsd case, in parallel to
529 * getstartdir. Initializes the rootdir and erootdir state and 575 * getstartdir. Initializes the rootdir and erootdir state and
530 * returns a reference to the passed-instarting dir. 576 * returns a reference to the passed-in starting dir.
531 */ 577 */
532static struct vnode * 578static struct vnode *
533namei_getstartdir_for_nfsd(struct namei_state *state, struct vnode *startdir) 579namei_getstartdir_for_nfsd(struct namei_state *state, struct vnode *startdir)
534{ 580{
535 /* always use the real root, and never set an emulation root */ 581 /* always use the real root, and never set an emulation root */
536 state->ndp->ni_rootdir = rootvnode; 582 state->ndp->ni_rootdir = rootvnode;
537 state->ndp->ni_erootdir = NULL; 583 state->ndp->ni_erootdir = NULL;
538 584
539 vref(startdir); 585 vref(startdir);
540 return startdir; 586 return startdir;
541} 587}
542 588
543 589
@@ -603,37 +649,40 @@ namei_start(struct namei_state *state, s @@ -603,37 +649,40 @@ namei_start(struct namei_state *state, s
603 /* no ktrace */ 649 /* no ktrace */
604 } else { 650 } else {
605 startdir = namei_getstartdir(state); 651 startdir = namei_getstartdir(state);
606 namei_ktrace(state); 652 namei_ktrace(state);
607 } 653 }
608 654
609 vn_lock(startdir, LK_EXCLUSIVE | LK_RETRY); 655 vn_lock(startdir, LK_EXCLUSIVE | LK_RETRY);
610 656
611 *startdir_ret = startdir; 657 *startdir_ret = startdir;
612 return 0; 658 return 0;
613} 659}
614 660
615/* 661/*
616 * Check for being at a symlink. 662 * Check for being at a symlink that we're going to follow.
617 */ 663 */
618static inline int 664static inline int
619namei_atsymlink(struct namei_state *state, struct vnode *foundobj) 665namei_atsymlink(struct namei_state *state, struct vnode *foundobj)
620{ 666{
621 return (foundobj->v_type == VLNK) && 667 return (foundobj->v_type == VLNK) &&
622 (state->cnp->cn_flags & (FOLLOW|REQUIREDIR)); 668 (state->cnp->cn_flags & (FOLLOW|REQUIREDIR));
623} 669}
624 670
625/* 671/*
626 * Follow a symlink. 672 * Follow a symlink.
 673 *
 674 * Updates searchdir. inhibitmagic causes magic symlinks to not be
 675 * interpreted; this is used by nfsd.
627 */ 676 */
628static inline int 677static inline int
629namei_follow(struct namei_state *state, int inhibitmagic, 678namei_follow(struct namei_state *state, int inhibitmagic,
630 struct vnode *searchdir, struct vnode *foundobj, 679 struct vnode *searchdir, struct vnode *foundobj,
631 struct vnode **newsearchdir_ret) 680 struct vnode **newsearchdir_ret)
632{ 681{
633 struct nameidata *ndp = state->ndp; 682 struct nameidata *ndp = state->ndp;
634 struct componentname *cnp = state->cnp; 683 struct componentname *cnp = state->cnp;
635 684
636 struct lwp *self = curlwp; /* thread doing namei() */ 685 struct lwp *self = curlwp; /* thread doing namei() */
637 struct iovec aiov; /* uio for reading symbolic links */ 686 struct iovec aiov; /* uio for reading symbolic links */
638 struct uio auio; 687 struct uio auio;
639 char *cp; /* pointer into pathname argument */ 688 char *cp; /* pointer into pathname argument */
@@ -711,62 +760,28 @@ namei_follow(struct namei_state *state,  @@ -711,62 +760,28 @@ namei_follow(struct namei_state *state,
711 searchdir = ndp->ni_rootdir; 760 searchdir = ndp->ni_rootdir;
712 } 761 }
713 vref(searchdir); 762 vref(searchdir);
714 vn_lock(searchdir, LK_EXCLUSIVE | LK_RETRY); 763 vn_lock(searchdir, LK_EXCLUSIVE | LK_RETRY);
715 } 764 }
716 765
717 *newsearchdir_ret = searchdir; 766 *newsearchdir_ret = searchdir;
718 return 0; 767 return 0;
719} 768}
720 769
721////////////////////////////// 770//////////////////////////////
722 771
723/* 772/*
724 * Search a pathname. 773 * Inspect the leading path component and update the state accordingly.
725 * This is a very central and rather complicated routine. 
726 * 
727 * The pathname is pointed to by ni_ptr and is of length ni_pathlen. 
728 * The starting directory is passed in. The pathname is descended 
729 * until done, or a symbolic link is encountered. The variable ni_more 
730 * is clear if the path is completed; it is set to one if a symbolic 
731 * link needing interpretation is encountered. 
732 * 
733 * The flag argument is LOOKUP, CREATE, RENAME, or DELETE depending on 
734 * whether the name is to be looked up, created, renamed, or deleted. 
735 * When CREATE, RENAME, or DELETE is specified, information usable in 
736 * creating, renaming, or deleting a directory entry may be calculated. 
737 * If flag has LOCKPARENT or'ed into it, the parent directory is returned 
738 * locked. Otherwise the parent directory is not returned. If the target 
739 * of the pathname exists and LOCKLEAF is or'ed into the flag the target 
740 * is returned locked, otherwise it is returned unlocked. When creating 
741 * or renaming and LOCKPARENT is specified, the target may not be ".". 
742 * When deleting and LOCKPARENT is specified, the target may be ".". 
743 * 
744 * Overall outline of lookup: 
745 * 
746 * dirloop: 
747 * identify next component of name at ndp->ni_ptr 
748 * handle degenerate case where name is null string 
749 * if .. and crossing mount points and on mounted filesys, find parent 
750 * call VOP_LOOKUP routine for next component name 
751 * directory vnode returned in ni_dvp, locked. 
752 * component vnode returned in ni_vp (if it exists), locked. 
753 * if result vnode is mounted on and crossing mount points, 
754 * find mounted on vnode 
755 * if more components of name, do next level at dirloop 
756 * return the answer in ni_vp, locked if LOCKLEAF set 
757 * if LOCKPARENT set, return locked parent in ni_dvp 
758 */ 774 */
759 
760static int 775static int
761lookup_parsepath(struct namei_state *state) 776lookup_parsepath(struct namei_state *state)
762{ 777{
763 const char *cp; /* pointer into pathname argument */ 778 const char *cp; /* pointer into pathname argument */
764 779
765 struct componentname *cnp = state->cnp; 780 struct componentname *cnp = state->cnp;
766 struct nameidata *ndp = state->ndp; 781 struct nameidata *ndp = state->ndp;
767 782
768 KASSERT(cnp == &ndp->ni_cnd); 783 KASSERT(cnp == &ndp->ni_cnd);
769 784
770 /* 785 /*
771 * Search a new directory. 786 * Search a new directory.
772 * 787 *
@@ -824,26 +839,31 @@ lookup_parsepath(struct namei_state *sta @@ -824,26 +839,31 @@ lookup_parsepath(struct namei_state *sta
824 } else { 839 } else {
825 cnp->cn_flags |= MAKEENTRY; 840 cnp->cn_flags |= MAKEENTRY;
826 cnp->cn_flags &= ~ISLASTCN; 841 cnp->cn_flags &= ~ISLASTCN;
827 } 842 }
828 if (cnp->cn_namelen == 2 && 843 if (cnp->cn_namelen == 2 &&
829 cnp->cn_nameptr[1] == '.' && cnp->cn_nameptr[0] == '.') 844 cnp->cn_nameptr[1] == '.' && cnp->cn_nameptr[0] == '.')
830 cnp->cn_flags |= ISDOTDOT; 845 cnp->cn_flags |= ISDOTDOT;
831 else 846 else
832 cnp->cn_flags &= ~ISDOTDOT; 847 cnp->cn_flags &= ~ISDOTDOT;
833 848
834 return 0; 849 return 0;
835} 850}
836 851
 852/*
 853 * Call VOP_LOOKUP for a single lookup; return a new search directory
 854 * (used when crossing mountpoints up or searching union mounts down) and
 855 * the found object, which for create operations may be NULL on success.
 856 */
837static int 857static int
838lookup_once(struct namei_state *state, 858lookup_once(struct namei_state *state,
839 struct vnode *searchdir, 859 struct vnode *searchdir,
840 struct vnode **newsearchdir_ret, 860 struct vnode **newsearchdir_ret,
841 struct vnode **foundobj_ret) 861 struct vnode **foundobj_ret)
842{ 862{
843 struct vnode *tmpvn; /* scratch vnode */ 863 struct vnode *tmpvn; /* scratch vnode */
844 struct vnode *foundobj; /* result */ 864 struct vnode *foundobj; /* result */
845 struct mount *mp; /* mount table entry */ 865 struct mount *mp; /* mount table entry */
846 struct lwp *l = curlwp; 866 struct lwp *l = curlwp;
847 int error; 867 int error;
848 868
849 struct componentname *cnp = state->cnp; 869 struct componentname *cnp = state->cnp;
@@ -955,28 +975,28 @@ unionlookup: @@ -955,28 +975,28 @@ unionlookup:
955 } 975 }
956 976
957 /* 977 /*
958 * If creating and at end of pathname, then can consider 978 * If creating and at end of pathname, then can consider
959 * allowing file to be created. 979 * allowing file to be created.
960 */ 980 */
961 if (state->rdonly) { 981 if (state->rdonly) {
962 return EROFS; 982 return EROFS;
963 } 983 }
964 984
965 /* 985 /*
966 * We return success and a NULL foundobj to indicate 986 * We return success and a NULL foundobj to indicate
967 * that the entry doesn't currently exist, leaving a 987 * that the entry doesn't currently exist, leaving a
968 * pointer to the (possibly locked) directory vnode as 988 * pointer to the (normally, locked) directory vnode
969 * searchdir. 989 * as searchdir.
970 */ 990 */
971 *foundobj_ret = NULL; 991 *foundobj_ret = NULL;
972 return (0); 992 return (0);
973 } 993 }
974#ifdef NAMEI_DIAGNOSTIC 994#ifdef NAMEI_DIAGNOSTIC
975 printf("found\n"); 995 printf("found\n");
976#endif /* NAMEI_DIAGNOSTIC */ 996#endif /* NAMEI_DIAGNOSTIC */
977 997
978 /* 998 /*
979 * Take into account any additional components consumed by the 999 * Take into account any additional components consumed by the
980 * underlying filesystem. This will include any trailing slashes after 1000 * underlying filesystem. This will include any trailing slashes after
981 * the last component consumed. 1001 * the last component consumed.
982 */ 1002 */
@@ -1015,26 +1035,30 @@ unionlookup: @@ -1015,26 +1035,30 @@ unionlookup:
1015 return error; 1035 return error;
1016 } 1036 }
1017 VOP_UNLOCK(foundobj); 1037 VOP_UNLOCK(foundobj);
1018 vn_lock(searchdir, LK_EXCLUSIVE | LK_RETRY); 1038 vn_lock(searchdir, LK_EXCLUSIVE | LK_RETRY);
1019 vn_lock(foundobj, LK_EXCLUSIVE | LK_RETRY); 1039 vn_lock(foundobj, LK_EXCLUSIVE | LK_RETRY);
1020 } 1040 }
1021 1041
1022 *foundobj_ret = foundobj; 1042 *foundobj_ret = foundobj;
1023 return 0; 1043 return 0;
1024} 1044}
1025 1045
1026////////////////////////////// 1046//////////////////////////////
1027 1047
 1048/*
 1049 * Do a complete path search from a single root directory.
 1050 * (This is called up to twice if TRYEMULROOT is in effect.)
 1051 */
1028static int 1052static int
1029namei_oneroot(struct namei_state *state, struct vnode *forcecwd, 1053namei_oneroot(struct namei_state *state, struct vnode *forcecwd,
1030 int neverfollow, int inhibitmagic) 1054 int neverfollow, int inhibitmagic)
1031{ 1055{
1032 struct nameidata *ndp = state->ndp; 1056 struct nameidata *ndp = state->ndp;
1033 struct componentname *cnp = state->cnp; 1057 struct componentname *cnp = state->cnp;
1034 struct vnode *searchdir, *foundobj; 1058 struct vnode *searchdir, *foundobj;
1035 const char *cp; 1059 const char *cp;
1036 int error; 1060 int error;
1037 1061
1038 error = namei_start(state, forcecwd, &searchdir); 1062 error = namei_start(state, forcecwd, &searchdir);
1039 if (error) { 1063 if (error) {
1040 ndp->ni_dvp = NULL; 1064 ndp->ni_dvp = NULL;
@@ -1320,26 +1344,29 @@ namei_oneroot(struct namei_state *state, @@ -1320,26 +1344,29 @@ namei_oneroot(struct namei_state *state,
1320 if (searchdir == foundobj) { 1344 if (searchdir == foundobj) {
1321 vrele(searchdir); 1345 vrele(searchdir);
1322 } else { 1346 } else {
1323 vput(searchdir); 1347 vput(searchdir);
1324 } 1348 }
1325 searchdir = NULL; 1349 searchdir = NULL;
1326 } 1350 }
1327 1351
1328 ndp->ni_dvp = searchdir; 1352 ndp->ni_dvp = searchdir;
1329 ndp->ni_vp = foundobj; 1353 ndp->ni_vp = foundobj;
1330 return 0; 1354 return 0;
1331} 1355}
1332 1356
 1357/*
 1358 * Do namei; wrapper layer that handles TRYEMULROOT.
 1359 */
1333static int 1360static int
1334namei_tryemulroot(struct namei_state *state, struct vnode *forcecwd, 1361namei_tryemulroot(struct namei_state *state, struct vnode *forcecwd,
1335 int neverfollow, int inhibitmagic) 1362 int neverfollow, int inhibitmagic)
1336{ 1363{
1337 int error; 1364 int error;
1338 1365
1339 struct nameidata *ndp = state->ndp; 1366 struct nameidata *ndp = state->ndp;
1340 struct componentname *cnp = state->cnp; 1367 struct componentname *cnp = state->cnp;
1341 const char *savepath = NULL; 1368 const char *savepath = NULL;
1342 1369
1343 KASSERT(cnp == &ndp->ni_cnd); 1370 KASSERT(cnp == &ndp->ni_cnd);
1344 1371
1345 if (cnp->cn_flags & TRYEMULROOT) { 1372 if (cnp->cn_flags & TRYEMULROOT) {
@@ -1365,82 +1392,98 @@ namei_tryemulroot(struct namei_state *st @@ -1365,82 +1392,98 @@ namei_tryemulroot(struct namei_state *st
1365 strcpy(ndp->ni_pathbuf->pb_path, savepath); 1392 strcpy(ndp->ni_pathbuf->pb_path, savepath);
1366 pathbuf_stringcopy_put(ndp->ni_pathbuf, savepath); 1393 pathbuf_stringcopy_put(ndp->ni_pathbuf, savepath);
1367 savepath = NULL; 1394 savepath = NULL;
1368 1395
1369 goto emul_retry; 1396 goto emul_retry;
1370 } 1397 }
1371 } 1398 }
1372 if (savepath != NULL) { 1399 if (savepath != NULL) {
1373 pathbuf_stringcopy_put(ndp->ni_pathbuf, savepath); 1400 pathbuf_stringcopy_put(ndp->ni_pathbuf, savepath);
1374 } 1401 }
1375 return error; 1402 return error;
1376} 1403}
1377 1404
 1405/*
 1406 * External interface.
 1407 */
1378int 1408int
1379namei(struct nameidata *ndp) 1409namei(struct nameidata *ndp)
1380{ 1410{
1381 struct namei_state state; 1411 struct namei_state state;
1382 int error; 1412 int error;
1383 1413
1384 namei_init(&state, ndp); 1414 namei_init(&state, ndp);
1385 error = namei_tryemulroot(&state, NULL, 1415 error = namei_tryemulroot(&state, NULL,
1386 0/*!neverfollow*/, 0/*!inhibitmagic*/); 1416 0/*!neverfollow*/, 0/*!inhibitmagic*/);
1387 namei_cleanup(&state); 1417 namei_cleanup(&state);
1388 1418
1389 if (error) { 1419 if (error) {
1390 /* make sure no stray refs leak out */ 1420 /* make sure no stray refs leak out */
1391 KASSERT(ndp->ni_dvp == NULL); 1421 KASSERT(ndp->ni_dvp == NULL);
1392 KASSERT(ndp->ni_vp == NULL); 1422 KASSERT(ndp->ni_vp == NULL);
1393 } 1423 }
1394 1424
1395 return error; 1425 return error;
1396} 1426}
1397 1427
1398//////////////////////////////////////////////////////////// 1428////////////////////////////////////////////////////////////
1399 1429
1400/* 1430/*
1401 * Externally visible interfaces used by nfsd (bletch, yuk, XXX) 1431 * External interface used by nfsd. This is basically different from
 1432 * namei only in that it has the ability to pass in the "current
 1433 * directory", and uses an extra flag "neverfollow" for which there's
 1434 * no physical flag defined in namei.h. (There used to be a cut&paste
 1435 * copy of about half of namei in nfsd to allow these minor
 1436 * adjustments to exist.)
1402 * 1437 *
1403 * The "index" version differs from the "main" version in that it's 1438 * XXX: the namei interface should be adjusted so nfsd can just use
1404 * called from a different place in a different context. For now I 1439 * ordinary namei().
1405 * want to be able to shuffle code in from one call site without 
1406 * affecting the other. 
1407 * 
1408 * It turns out that the "main" version was a cut and pasted copy of 
1409 * namei with a few changes; the "index" version on the other hand 
1410 * always takes a single component and is an elaborate form of calling 
1411 * VOP_LOOKUP once. 
1412 */ 1440 */
1413 
1414int 1441int
1415lookup_for_nfsd(struct nameidata *ndp, struct vnode *forcecwd, int neverfollow) 1442lookup_for_nfsd(struct nameidata *ndp, struct vnode *forcecwd, int neverfollow)
1416{ 1443{
1417 struct namei_state state; 1444 struct namei_state state;
1418 int error; 1445 int error;
1419 1446
1420 namei_init(&state, ndp); 1447 namei_init(&state, ndp);
1421 error = namei_tryemulroot(&state, forcecwd, 1448 error = namei_tryemulroot(&state, forcecwd,
1422 neverfollow, 1/*inhibitmagic*/); 1449 neverfollow, 1/*inhibitmagic*/);
1423 namei_cleanup(&state); 1450 namei_cleanup(&state);
1424 1451
1425 if (error) { 1452 if (error) {
1426 /* make sure no stray refs leak out */ 1453 /* make sure no stray refs leak out */
1427 KASSERT(ndp->ni_dvp == NULL); 1454 KASSERT(ndp->ni_dvp == NULL);
1428 KASSERT(ndp->ni_vp == NULL); 1455 KASSERT(ndp->ni_vp == NULL);
1429 } 1456 }
1430 1457
1431 return error; 1458 return error;
1432} 1459}
1433 1460
 1461/*
 1462 * A second external interface used by nfsd. This turns out to be a
 1463 * single lookup used by the WebNFS code (ha!) to get "index.html" or
 1464 * equivalent when asked for a directory. It should eventually evolve
 1465 * into some kind of namei_once() call; for the time being it's kind
 1466 * of a mess. XXX.
 1467 *
 1468 * dholland 20110109: I don't think it works, and I don't think it
 1469 * worked before I started hacking and slashing either, and I doubt
 1470 * anyone will ever notice.
 1471 */
 1472
 1473/*
 1474 * Internals. This calls lookup_once() after setting up the assorted
 1475 * pieces of state the way they ought to be.
 1476 */
1434static int 1477static int
1435do_lookup_for_nfsd_index(struct namei_state *state, struct vnode *startdir) 1478do_lookup_for_nfsd_index(struct namei_state *state, struct vnode *startdir)
1436{ 1479{
1437 int error = 0; 1480 int error = 0;
1438 1481
1439 struct componentname *cnp = state->cnp; 1482 struct componentname *cnp = state->cnp;
1440 struct nameidata *ndp = state->ndp; 1483 struct nameidata *ndp = state->ndp;
1441 struct vnode *foundobj; 1484 struct vnode *foundobj;
1442 const char *cp; /* pointer into pathname argument */ 1485 const char *cp; /* pointer into pathname argument */
1443 1486
1444 KASSERT(cnp == &ndp->ni_cnd); 1487 KASSERT(cnp == &ndp->ni_cnd);
1445 1488
1446 cnp->cn_nameptr = ndp->ni_pnbuf; 1489 cnp->cn_nameptr = ndp->ni_pnbuf;
@@ -1484,26 +1527,32 @@ do_lookup_for_nfsd_index(struct namei_st @@ -1484,26 +1527,32 @@ do_lookup_for_nfsd_index(struct namei_st
1484 } 1527 }
1485 1528
1486 KASSERT((cnp->cn_flags & LOCKPARENT) == 0); 1529 KASSERT((cnp->cn_flags & LOCKPARENT) == 0);
1487 if ((cnp->cn_flags & LOCKLEAF) == 0) { 1530 if ((cnp->cn_flags & LOCKLEAF) == 0) {
1488 VOP_UNLOCK(foundobj); 1531 VOP_UNLOCK(foundobj);
1489 } 1532 }
1490 return (0); 1533 return (0);
1491 1534
1492bad: 1535bad:
1493 ndp->ni_vp = NULL; 1536 ndp->ni_vp = NULL;
1494 return (error); 1537 return (error);
1495} 1538}
1496 1539
 1540/*
 1541 * External interface. The partitioning between this function and the
 1542 * above isn't very clear - the above function exists mostly so code
 1543 * that uses "state->" can be shuffled around without having to change
 1544 * it to "state.".
 1545 */
1497int 1546int
1498lookup_for_nfsd_index(struct nameidata *ndp, struct vnode *startdir) 1547lookup_for_nfsd_index(struct nameidata *ndp, struct vnode *startdir)
1499{ 1548{
1500 struct namei_state state; 1549 struct namei_state state;
1501 int error; 1550 int error;
1502 1551
1503 /* 1552 /*
1504 * Note: the name sent in here (is not|should not be) allowed 1553 * Note: the name sent in here (is not|should not be) allowed
1505 * to contain a slash. 1554 * to contain a slash.
1506 */ 1555 */
1507 if (strlen(ndp->ni_pathbuf->pb_path) > NAME_MAX) { 1556 if (strlen(ndp->ni_pathbuf->pb_path) > NAME_MAX) {
1508 return ENAMETOOLONG; 1557 return ENAMETOOLONG;
1509 } 1558 }