From 0a3879cf40050f5fbd8042e1fcc74dd02d0caf49 Mon Sep 17 00:00:00 2001 From: Russ Allbery Date: Thu, 2 Apr 2009 15:12:54 -0700 Subject: [PATCH] Imported Upstream version 1.4.10+dfsg1 --- acinclude.m4 | 1 + configure | 136 ++- configure-libafs | 136 ++- configure-libafs.in | 10 +- configure.in | 10 +- src/afs/LINUX/osi_module.c | 4 +- src/afs/LINUX/osi_vm.c | 6 +- src/afs/LINUX/osi_vnodeops.c | 9 +- src/afs/OBSD/osi_groups.c | 12 +- src/afs/OBSD/osi_machdep.h | 86 +- src/afs/OBSD/osi_misc.c | 90 +- src/afs/OBSD/osi_vnodeops.c | 20 +- src/afs/VNOPS/afs_vnop_lookup.c | 21 +- src/afs/VNOPS/afs_vnop_lookup.c.orig | 1629 ++++++++++++++++++++++++++ src/afs/afs_osi.c | 4 +- src/afs/afs_vcache.c | 4 +- src/bozo/bnode.c | 3 +- src/bucoord/ubik_db_if.c | 6 +- src/budb/ol_verify.c | 6 +- src/cf/linux-test4.m4 | 14 + src/config/afs_sysnames.h | 3 + src/config/afsconfig.h.in | 3 + src/rx/UKERNEL/rx_knet.c | 3 +- src/rx/rx_kcommon.c | 6 +- src/rx/xdr.h | 2 + src/rx/xdr_arrayn.c | 9 +- src/sys/rmtsysc.c | 19 +- src/uss/uss_vol.c | 4 +- 28 files changed, 2173 insertions(+), 83 deletions(-) create mode 100644 src/afs/VNOPS/afs_vnop_lookup.c.orig diff --git a/acinclude.m4 b/acinclude.m4 index 9402d8592..e544fa7bd 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -715,6 +715,7 @@ case $AFS_SYSNAME in *_linux* | *_umlinux*) LINUX_HAVE_WRITE_BEGIN_AOP LINUX_HAVE_GRAB_CACHE_PAGE_WRITE_BEGIN LINUX_STRUCT_TASK_HAS_CRED + LINUX_STRUCT_PROC_DIR_ENTRY_HAS_OWNER LINUX_KMEM_CACHE_INIT LINUX_HAVE_BDI_INIT LINUX_HAVE_KMEM_CACHE_T diff --git a/configure b/configure index 812580f39..c74a64fbd 100755 --- a/configure +++ b/configure @@ -2183,7 +2183,7 @@ fi # Define the identity of the package. PACKAGE=openafs - VERSION=1.4.9pre2 + VERSION=1.4.10 cat >>confdefs.h <<_ACEOF @@ -2331,10 +2331,10 @@ am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -' ac_config_headers="$ac_config_headers src/config/afsconfig.h" -MACOS_VERSION=1.4.9fc2 -LINUX_PKGVER=1.4.9 -#LINUX_PKGREL=1.1 -LINUX_PKGREL=0.pre2 +MACOS_VERSION=1.4.10 +LINUX_PKGVER=1.4.10 +#LINUX_PKGREL=0.pre2 +LINUX_PKGREL=1.1 @@ -7993,6 +7993,132 @@ _ACEOF fi + { echo "$as_me:$LINENO: checking if struct proc_dir_entry_has_owner" >&5 +echo $ECHO_N "checking if struct proc_dir_entry_has_owner... $ECHO_C" >&6; } + if test "${ac_cv_linux_struct_proc_dir_entry_has_owner+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + + if test $AFS_SYSKVERS -ge 26 ; then + rm -fr conftest.dir + if test "x$ac_linux_kbuild_requires_extra_cflags" = "xyes" ; then + CFLAGS_PREFIX='EXTRA_' + fi + if mkdir conftest.dir && + cat >conftest.dir/Makefile <<_ACEOF && +${CFLAGS_PREFIX}CFLAGS += $CPPFLAGS + +obj-m += conftest.o +_ACEOF + cat >conftest.dir/conftest.c <<\_ACEOF && +/* confdefs.h */ +_ACEOF + cat confdefs.h >>conftest.dir/conftest.c && + cat >>conftest.dir/conftest.c <<\_ACEOF && +/* end confdefs.h */ +#include +#include + +void conftest(void) +{ +struct proc_dir_entry _p; +_p.owner= ""; +} + +MODULE_LICENSE("http://www.openafs.org/dl/license10.html"); +_ACEOF + echo make -C $LINUX_KERNEL_BUILD M=$SRCDIR_PARENT/conftest.dir modules KBUILD_VERBOSE=1 >&5 && + make -C $LINUX_KERNEL_BUILD M=$SRCDIR_PARENT/conftest.dir modules KBUILD_VERBOSE=1 >&5 2>conftest.err && + ! grep -i "WARNING: .* undefined!$" conftest.err >/dev/null 2>&1 + then ac_cv_linux_struct_proc_dir_entry_has_owner=yes + else + sed '/^ *+/d' conftest.err >&5 + echo "$as_me: failed using Makefile:" >&5 + sed 's/^/| /' conftest.dir/Makefile >&5 + echo "$as_me: and program was:" >&5 + sed 's/^/| /' conftest.dir/conftest.c >&5 + ac_cv_linux_struct_proc_dir_entry_has_owner=no + fi; rm -fr conftest.err conftest.dir + else + + ac_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="-I$LINUX_KERNEL_PATH/include -D__KERNEL__ -Werror-implicit-function-declaration $CPPFLAGS" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#include +#include +int +main () +{ +struct proc_dir_entry _p; +_p.owner= ""; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_linux_struct_proc_dir_entry_has_owner=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_linux_struct_proc_dir_entry_has_owner=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CPPFLAGS="$ac_save_CPPFLAGS" + fi +fi + + { echo "$as_me:$LINENO: result: $ac_cv_linux_struct_proc_dir_entry_has_owner" >&5 +echo "${ECHO_T}$ac_cv_linux_struct_proc_dir_entry_has_owner" >&6; } + if test "x$ac_cv_linux_struct_proc_dir_entry_has_owner" = "xyes"; then + +cat >>confdefs.h <<\_ACEOF +#define STRUCT_PROC_DIR_ENTRY_HAS_OWNER 1 +_ACEOF + + fi + { echo "$as_me:$LINENO: checking for new kmem_cache init function parameters" >&5 echo $ECHO_N "checking for new kmem_cache init function parameters... $ECHO_C" >&6; } if test "${ac_cv_linux_kmem_cache_init+set}" = set; then diff --git a/configure-libafs b/configure-libafs index e6b68539e..b8a008807 100755 --- a/configure-libafs +++ b/configure-libafs @@ -2182,7 +2182,7 @@ fi # Define the identity of the package. PACKAGE=openafs-libafs - VERSION=1.4.9pre2 + VERSION=1.4.10 cat >>confdefs.h <<_ACEOF @@ -2330,10 +2330,10 @@ am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -' ac_config_headers="$ac_config_headers src/config/afsconfig.h" -MACOS_VERSION=1.4.9fc2 -LINUX_PKGVER=1.4.9 -#LINUX_PKGREL=1.1 -LINUX_PKGREL=0.pre2 +MACOS_VERSION=1.4.10 +LINUX_PKGVER=1.4.10 +#LINUX_PKGREL=0.pre2 +LINUX_PKGREL=1.1 @@ -7944,6 +7944,132 @@ _ACEOF fi + { echo "$as_me:$LINENO: checking if struct proc_dir_entry_has_owner" >&5 +echo $ECHO_N "checking if struct proc_dir_entry_has_owner... $ECHO_C" >&6; } + if test "${ac_cv_linux_struct_proc_dir_entry_has_owner+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + + if test $AFS_SYSKVERS -ge 26 ; then + rm -fr conftest.dir + if test "x$ac_linux_kbuild_requires_extra_cflags" = "xyes" ; then + CFLAGS_PREFIX='EXTRA_' + fi + if mkdir conftest.dir && + cat >conftest.dir/Makefile <<_ACEOF && +${CFLAGS_PREFIX}CFLAGS += $CPPFLAGS + +obj-m += conftest.o +_ACEOF + cat >conftest.dir/conftest.c <<\_ACEOF && +/* confdefs.h */ +_ACEOF + cat confdefs.h >>conftest.dir/conftest.c && + cat >>conftest.dir/conftest.c <<\_ACEOF && +/* end confdefs.h */ +#include +#include + +void conftest(void) +{ +struct proc_dir_entry _p; +_p.owner= ""; +} + +MODULE_LICENSE("http://www.openafs.org/dl/license10.html"); +_ACEOF + echo make -C $LINUX_KERNEL_BUILD M=$SRCDIR_PARENT/conftest.dir modules KBUILD_VERBOSE=1 >&5 && + make -C $LINUX_KERNEL_BUILD M=$SRCDIR_PARENT/conftest.dir modules KBUILD_VERBOSE=1 >&5 2>conftest.err && + ! grep -i "WARNING: .* undefined!$" conftest.err >/dev/null 2>&1 + then ac_cv_linux_struct_proc_dir_entry_has_owner=yes + else + sed '/^ *+/d' conftest.err >&5 + echo "$as_me: failed using Makefile:" >&5 + sed 's/^/| /' conftest.dir/Makefile >&5 + echo "$as_me: and program was:" >&5 + sed 's/^/| /' conftest.dir/conftest.c >&5 + ac_cv_linux_struct_proc_dir_entry_has_owner=no + fi; rm -fr conftest.err conftest.dir + else + + ac_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="-I$LINUX_KERNEL_PATH/include -D__KERNEL__ -Werror-implicit-function-declaration $CPPFLAGS" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#include +#include +int +main () +{ +struct proc_dir_entry _p; +_p.owner= ""; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_linux_struct_proc_dir_entry_has_owner=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_linux_struct_proc_dir_entry_has_owner=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CPPFLAGS="$ac_save_CPPFLAGS" + fi +fi + + { echo "$as_me:$LINENO: result: $ac_cv_linux_struct_proc_dir_entry_has_owner" >&5 +echo "${ECHO_T}$ac_cv_linux_struct_proc_dir_entry_has_owner" >&6; } + if test "x$ac_cv_linux_struct_proc_dir_entry_has_owner" = "xyes"; then + +cat >>confdefs.h <<\_ACEOF +#define STRUCT_PROC_DIR_ENTRY_HAS_OWNER 1 +_ACEOF + + fi + { echo "$as_me:$LINENO: checking for new kmem_cache init function parameters" >&5 echo $ECHO_N "checking for new kmem_cache init function parameters... $ECHO_C" >&6; } if test "${ac_cv_linux_kmem_cache_init+set}" = set; then diff --git a/configure-libafs.in b/configure-libafs.in index 8c50833f5..5e10dd8a0 100644 --- a/configure-libafs.in +++ b/configure-libafs.in @@ -1,10 +1,10 @@ AC_INIT(src/libafs/Makefile.common.in) -AM_INIT_AUTOMAKE(openafs-libafs,1.4.9pre2) +AM_INIT_AUTOMAKE(openafs-libafs,1.4.10) AC_CONFIG_HEADER(src/config/afsconfig.h) -MACOS_VERSION=1.4.9fc2 -LINUX_PKGVER=1.4.9 -#LINUX_PKGREL=1.1 -LINUX_PKGREL=0.pre2 +MACOS_VERSION=1.4.10 +LINUX_PKGVER=1.4.10 +#LINUX_PKGREL=0.pre2 +LINUX_PKGREL=1.1 AC_SUBST(MACOS_VERSION) AC_SUBST(LINUX_PKGVER) diff --git a/configure.in b/configure.in index 75b37f512..7a0cd0a90 100644 --- a/configure.in +++ b/configure.in @@ -1,10 +1,10 @@ AC_INIT(src/config/stds.h) -AM_INIT_AUTOMAKE(openafs,1.4.9pre2) +AM_INIT_AUTOMAKE(openafs,1.4.10) AC_CONFIG_HEADER(src/config/afsconfig.h) -MACOS_VERSION=1.4.9fc2 -LINUX_PKGVER=1.4.9 -#LINUX_PKGREL=1.1 -LINUX_PKGREL=0.pre2 +MACOS_VERSION=1.4.10 +LINUX_PKGVER=1.4.10 +#LINUX_PKGREL=0.pre2 +LINUX_PKGREL=1.1 AC_SUBST(MACOS_VERSION) AC_SUBST(LINUX_PKGVER) diff --git a/src/afs/LINUX/osi_module.c b/src/afs/LINUX/osi_module.c index 1fc790af0..b081f9b83 100644 --- a/src/afs/LINUX/osi_module.c +++ b/src/afs/LINUX/osi_module.c @@ -15,7 +15,7 @@ #include "afs/param.h" RCSID - ("$Header: /cvs/openafs/src/afs/LINUX/osi_module.c,v 1.52.2.32 2009/03/15 18:42:34 shadow Exp $"); + ("$Header: /cvs/openafs/src/afs/LINUX/osi_module.c,v 1.52.2.33 2009/03/31 12:16:50 shadow Exp $"); #include /* early to avoid printf->printk mapping */ #include "afs/sysincludes.h" @@ -258,7 +258,9 @@ afsproc_init(void) entry1->proc_fops = &afs_syscall_fops; +#if defined(STRUCT_PROC_DIR_ENTRY_HAS_OWNER) entry1->owner = THIS_MODULE; +#endif #ifdef HAVE_KERNEL_LINUX_SEQ_FILE_H entry2 = create_proc_entry(PROC_CELLSERVDB_NAME, 0, openafs_procfs); diff --git a/src/afs/LINUX/osi_vm.c b/src/afs/LINUX/osi_vm.c index cc35ffaf2..4917f977a 100644 --- a/src/afs/LINUX/osi_vm.c +++ b/src/afs/LINUX/osi_vm.c @@ -11,7 +11,7 @@ #include "afs/param.h" RCSID - ("$Header: /cvs/openafs/src/afs/LINUX/osi_vm.c,v 1.16.2.4 2009/03/20 15:55:57 shadow Exp $"); + ("$Header: /cvs/openafs/src/afs/LINUX/osi_vm.c,v 1.16.2.5 2009/03/27 15:45:49 shadow Exp $"); #include "afs/sysincludes.h" /* Standard vendor system headers */ #include "afsincludes.h" /* Afs-based standard headers */ @@ -131,7 +131,9 @@ void osi_VM_FlushPages(struct vcache *avc, struct AFS_UCRED *credp) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - invalidate_remote_inode(AFSTOV(avc)); + struct inode *ip = AFSTOV(avc); + + truncate_inode_pages(&ip->i_data, 0); #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,15) struct inode *ip = AFSTOV(avc); diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c index 804977dbb..3054052a8 100644 --- a/src/afs/LINUX/osi_vnodeops.c +++ b/src/afs/LINUX/osi_vnodeops.c @@ -1087,8 +1087,10 @@ afs_linux_lookup(struct inode *dip, struct dentry *dp) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,10) if (code == ENOENT) return ERR_PTR(0); - else + else if ((code > 0) && (code <= MAX_ERRNO)) return ERR_PTR(-code); + else + return ERR_PTR(-EIO); #else if (code == ENOENT) code = 0; @@ -1429,7 +1431,10 @@ afs_linux_follow_link(struct dentry *dp, struct dentry *basep, if (code < 0) { dput(basep); - res = ERR_PTR(code); + if (code < -MAX_ERRNO) + res = ERR_PTR(-EIO); + else + res = ERR_PTR(code); } else { name[code] = '\0'; res = lookup_dentry(name, basep, follow); diff --git a/src/afs/OBSD/osi_groups.c b/src/afs/OBSD/osi_groups.c index f28cd3752..f8695a66d 100644 --- a/src/afs/OBSD/osi_groups.c +++ b/src/afs/OBSD/osi_groups.c @@ -19,7 +19,7 @@ #include "afs/param.h" RCSID - ("$Header: /cvs/openafs/src/afs/OBSD/osi_groups.c,v 1.5.2.1 2006/06/23 14:21:12 rees Exp $"); + ("$Header: /cvs/openafs/src/afs/OBSD/osi_groups.c,v 1.5.2.2 2009/03/27 15:55:45 shadow Exp $"); #include "afs/sysincludes.h" #include "afs/afsincludes.h" @@ -47,10 +47,12 @@ Afs_xsetgroups(p, args, retval) struct vrequest treq; AFS_STATCNT(afs_xsetgroups); - AFS_GLOCKP(p); + AFS_GLOCK(); + + p = osi_curproc(); code = afs_InitReq(&treq, p->p_rcred); - AFS_GUNLOCKP(p); + AFS_GUNLOCK(); if (code) return code; @@ -61,10 +63,10 @@ Afs_xsetgroups(p, args, retval) */ if (PagInCred(p->p_rcred) == NOPAG) { if (((treq.uid >> 24) & 0xff) == 'A') { - AFS_GLOCKP(p); + AFS_GLOCK(); /* we've already done a setpag, so now we redo it */ AddPag(p, treq.uid, &p->p_rcred); - AFS_GUNLOCKP(p); + AFS_GUNLOCK(); } } return code; diff --git a/src/afs/OBSD/osi_machdep.h b/src/afs/OBSD/osi_machdep.h index c8c96930d..84f133b8b 100644 --- a/src/afs/OBSD/osi_machdep.h +++ b/src/afs/OBSD/osi_machdep.h @@ -16,7 +16,7 @@ * afs_osi.h. */ -/* $Id: osi_machdep.h,v 1.16.2.9 2008/01/04 17:53:37 rees Exp $ */ +/* $Id: osi_machdep.h,v 1.16.2.10 2009/03/27 15:55:45 shadow Exp $ */ #ifndef _OSI_MACHDEP_H_ #define _OSI_MACHDEP_H_ @@ -54,8 +54,35 @@ #define AFS_UIOUSER UIO_USERSPACE /* malloc */ -#define AFS_KALLOC(s) afs_nbsd_Alloc(s) -#define AFS_KFREE(p, s) afs_nbsd_Free((p), (s)) +extern void *osi_obsd_Alloc(size_t asize, int cansleep); +extern void osi_obsd_Free(void *p, size_t asize); + +#ifdef afs_osi_Alloc_NoSleep +#undef afs_osi_Alloc_NoSleep +#define afs_osi_Alloc_NoSleep(asize) osi_obsd_Alloc((asize), 0) +#endif + +#ifdef AFS_KALLOC +#undef AFS_KALLOC +#define AFS_KALLOC(s) osi_obsd_Alloc((s), 1 /* cansleep */) +#endif + +#ifdef AFS_KFREE +#undef AFS_KFREE +#define AFS_KFREE(p, s) (osi_obsd_Free((p), (s))) +#endif + +#ifdef AFS_OBSD42_ENV +/* removed, live with it */ +#define BSD_KMALLOC(p, ptype, msize, mtype, mflags) \ + (p) = malloc((msize), (mtype), (mflags)) + +#define BSD_KFREE(p, mflags) \ + free((p), (mflags)) +#else +#define BSD_KMALLOC MALLOC +#define BSD_KFREE KFREE +#endif /* AFS_OBSD42_ENV */ /* proc, cred */ #define AFS_PROC struct proc @@ -92,11 +119,11 @@ extern time_t osi_Time(); /* This is not always in scope yet */ struct vcache; -extern int afs_nbsd_lookupname(char *fnamep, enum uio_seg segflg, +extern int afs_obsd_lookupname(char *fnamep, enum uio_seg segflg, int followlink, struct vnode **compvpp); -extern void afs_nbsd_getnewvnode(struct vcache *tvc); -extern void *afs_nbsd_Alloc(size_t asize); -extern void afs_nbsd_Free(void *p, size_t asize); +extern void afs_obsd_getnewvnode(struct vcache *tvc); +extern void *afs_obsd_Alloc(size_t asize); +extern void afs_obsd_Free(void *p, size_t asize); extern int afs_vget(); #undef gop_lookupname @@ -111,6 +138,49 @@ extern int afs_vget(); #ifdef KERNEL +#ifdef AFS_OBSD44_ENV +/* Revert to classical, BSD locks */ + +extern struct lock afs_global_lock; +extern struct proc *afs_global_owner; + +#ifdef AFS_GLOBAL_SUNLOCK + +#if defined(LOCKDEBUG) + +#define AFS_GLOCK() \ + do { \ + _lockmgr(&afs_global_lock, LK_EXCLUSIVE, NULL, __FILE__, __LINE__); \ + } while(0); +#define AFS_GUNLOCK() \ + do { \ + _lockmgr(&afs_global_lock, LK_RELEASE, NULL, __FILE__, __LINE__); \ + } while(0); + +#else + +#define AFS_GLOCK() \ + do { \ + lockmgr(&afs_global_lock, LK_EXCLUSIVE, NULL); \ + } while(0); +#define AFS_GUNLOCK() \ + do { \ + lockmgr(&afs_global_lock, LK_RELEASE, NULL); \ + } while(0); +#endif /* LOCKDEBUG */ +#define ISAFS_GLOCK() (lockstatus(&afs_global_lock) == LK_EXCLUSIVE) +#else +extern struct lock afs_global_lock; +#define AFS_GLOCKP(p) +#define AFS_GUNLOCKP(p) +#define AFS_ASSERT_GLOCK() +#define ISAFS_GLOCK() 1 +#endif + +#else +/* I don't see doing locks this way for older kernels, either, + * but, smart folks wrote this + */ #define AFS_GLOCK() AFS_GLOCKP(curproc) #define AFS_GUNLOCK() AFS_GUNLOCKP(curproc) #ifdef AFS_GLOBAL_SUNLOCK @@ -139,6 +209,8 @@ extern struct lock afs_global_lock; #define ISAFS_GLOCK() 1 #endif +#endif /* AFS_OBSD44_ENV */ + #undef SPLVAR #define SPLVAR int splvar #undef NETPRI diff --git a/src/afs/OBSD/osi_misc.c b/src/afs/OBSD/osi_misc.c index 4b816bb15..bb7e839e0 100644 --- a/src/afs/OBSD/osi_misc.c +++ b/src/afs/OBSD/osi_misc.c @@ -1,7 +1,7 @@ /* * osi_misc.c * - * $Id: osi_misc.c,v 1.4 2003/10/09 16:13:16 rees Exp $ + * $Id: osi_misc.c,v 1.4.2.1 2009/03/27 15:55:45 shadow Exp $ */ /* @@ -47,10 +47,12 @@ such damages. #include "afs/param.h" RCSID - ("$Header: /cvs/openafs/src/afs/OBSD/osi_misc.c,v 1.4 2003/10/09 16:13:16 rees Exp $"); + ("$Header: /cvs/openafs/src/afs/OBSD/osi_misc.c,v 1.4.2.1 2009/03/27 15:55:45 shadow Exp $"); #include "afs/sysincludes.h" /* Standard vendor system headers */ #include "afs/afsincludes.h" /* Afs-based standard headers */ +#include +#include /* * afs_suser() returns true if the caller is superuser, false otherwise. @@ -74,20 +76,94 @@ afs_osi_suser(void *credp) #endif } +/* + * reworked for netbsd and openbsd at 4.0/4.4 + */ + +#if defined(AFS_OBSD42_ENV) +/* ripped out MALLOC/FREE */ + void * -afs_nbsd_Alloc(size_t asize) +osi_obsd_Alloc(size_t asize, int cansleep) { - void *p; + void *p; + int glocked; + + if (cansleep) { + glocked = ISAFS_GLOCK(); + if (glocked) + AFS_GUNLOCK(); + p = malloc(asize, M_AFSGENERIC, M_WAITOK); + if (glocked) + AFS_GLOCK(); + } else { + p = malloc(asize, M_AFSGENERIC, M_NOWAIT); + } + + return (p); +} +void +osi_obsd_Free(void *p, size_t asize) +{ + free(p, M_AFSGENERIC); +} + +#else +void * +osi_obsd_Alloc(size_t asize, int cansleep) +{ + void *p; + int glocked; + + if (cansleep) { + glocked = ISAFS_GLOCK(); + if (glocked) + AFS_GUNLOCK(); MALLOC(p, void *, asize, M_AFSGENERIC, M_WAITOK); - return p; + if (glocked) + AFS_GLOCK(); + } else { + MALLOC(p, void *, asize, M_AFSGENERIC, M_NOWAIT); + } + + return (p); } void -afs_nbsd_Free(void *p, size_t asize) +osi_obsd_Free(void *p, size_t asize) { - FREE(p, M_AFSGENERIC); + FREE(p, M_AFSGENERIC); } +#endif + +#if 0 /* XXX */ +/* I speculate this usage may be more correct than definitions + * in afs_osi_alloc.c, which I discarded successfully for FreeBSD 7+, + * and am trying to discard for NetBSD 4.x, but until tested, I'm + * not rocking the boat. Matt. + */ + +void +osi_FreeLargeSpace(void *p) +{ + osi_obsd_Free(p, 0); +} + +void +osi_FreeSmallSpace(void *p) +{ + osi_obsd_Free(p, 0); +} + +void * +osi_AllocLargeSpace(size_t size) +{ + AFS_ASSERT_GLOCK(); + AFS_STATCNT(osi_AllocLargeSpace); + return (osi_obsd_Alloc(size, 1)); +} +#endif int afs_syscall_icreate(dev, near_inode, param1, param2, param3, param4, retval) diff --git a/src/afs/OBSD/osi_vnodeops.c b/src/afs/OBSD/osi_vnodeops.c index c28613e63..6d95d6329 100644 --- a/src/afs/OBSD/osi_vnodeops.c +++ b/src/afs/OBSD/osi_vnodeops.c @@ -3,7 +3,7 @@ * Original NetBSD version for Transarc afs by John Kohl * OpenBSD version by Jim Rees * - * $Id: osi_vnodeops.c,v 1.18.2.5 2008/01/08 17:06:59 rees Exp $ + * $Id: osi_vnodeops.c,v 1.18.2.6 2009/03/27 15:55:45 shadow Exp $ */ /* @@ -99,7 +99,7 @@ NONINFRINGEMENT. #include "afs/param.h" RCSID - ("$Header: /cvs/openafs/src/afs/OBSD/osi_vnodeops.c,v 1.18.2.5 2008/01/08 17:06:59 rees Exp $"); + ("$Header: /cvs/openafs/src/afs/OBSD/osi_vnodeops.c,v 1.18.2.6 2009/03/27 15:55:45 shadow Exp $"); #include "afs/sysincludes.h" /* Standard vendor system headers */ #include "afs/afsincludes.h" /* Afs-based standard headers */ @@ -160,7 +160,11 @@ int afs_nbsd_advlock(void *); /* Global vfs data structures for AFS. */ int (**afs_vnodeop_p) __P((void *)); struct vnodeopv_entry_desc afs_vnodeop_entries[] = { +#ifdef AFS_OBSD44_ENV /* feel free to zero in on this */ + {&vop_default_desc, eopnotsupp}, +#else {&vop_default_desc, vn_default_error}, +#endif {&vop_lookup_desc, afs_nbsd_lookup}, /* lookup */ {&vop_create_desc, afs_nbsd_create}, /* create */ {&vop_mknod_desc, afs_nbsd_mknod}, /* mknod */ @@ -207,11 +211,11 @@ struct vnodeopv_desc afs_vnodeop_opv_desc = #define GETNAME() \ struct componentname *cnp = ap->a_cnp; \ char *name; \ - MALLOC(name, char *, cnp->cn_namelen+1, M_TEMP, M_WAITOK); \ + BSD_KMALLOC(name, char *, cnp->cn_namelen+1, M_TEMP, M_WAITOK); \ bcopy(cnp->cn_nameptr, name, cnp->cn_namelen); \ name[cnp->cn_namelen] = '\0' -#define DROPNAME() FREE(name, M_TEMP) +#define DROPNAME() BSD_KFREE(name, M_TEMP) #ifdef AFS_OBSD36_ENV #define DROPCNP(cnp) pool_put(&namei_pool, (cnp)->cn_pnbuf) @@ -687,10 +691,10 @@ afs_nbsd_rename(void *v) if ((code = vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY, curproc))) goto abortit; - MALLOC(fname, char *, fcnp->cn_namelen + 1, M_TEMP, M_WAITOK); + BSD_KMALLOC(fname, char *, fcnp->cn_namelen + 1, M_TEMP, M_WAITOK); bcopy(fcnp->cn_nameptr, fname, fcnp->cn_namelen); fname[fcnp->cn_namelen] = '\0'; - MALLOC(tname, char *, tcnp->cn_namelen + 1, M_TEMP, M_WAITOK); + BSD_KMALLOC(tname, char *, tcnp->cn_namelen + 1, M_TEMP, M_WAITOK); bcopy(tcnp->cn_nameptr, tname, tcnp->cn_namelen); tname[tcnp->cn_namelen] = '\0'; @@ -702,8 +706,8 @@ afs_nbsd_rename(void *v) AFS_GUNLOCK(); VOP_UNLOCK(fvp, 0, curproc); - FREE(fname, M_TEMP); - FREE(tname, M_TEMP); + BSD_KFREE(fname, M_TEMP); + BSD_KFREE(tname, M_TEMP); if (code) goto abortit; /* XXX */ if (tdvp == tvp) diff --git a/src/afs/VNOPS/afs_vnop_lookup.c b/src/afs/VNOPS/afs_vnop_lookup.c index 06a2e8fbe..2e276eefb 100644 --- a/src/afs/VNOPS/afs_vnop_lookup.c +++ b/src/afs/VNOPS/afs_vnop_lookup.c @@ -538,8 +538,6 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp) int nskip; /* # of slots in the LRU queue to skip */ struct vcache *lruvcp; /* vcache ptr of our goal pos in LRU queue */ struct dcache *dcp; /* chunk containing the dir block */ - char *statMemp; /* status memory block */ - char *cbfMemp; /* callback and fid memory block */ afs_size_t temp; /* temp for holding chunk length, &c. */ struct AFSFid *fidsp; /* file IDs were collecting */ struct AFSCallBack *cbsp; /* call back pointers */ @@ -597,13 +595,11 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp) * one for fids and callbacks, and one for stat info. Well set * up our pointers to the memory from there, too. */ - statMemp = osi_AllocLargeSpace(nentries * sizeof(AFSFetchStatus)); - statsp = (struct AFSFetchStatus *)statMemp; - cbfMemp = - osi_AllocLargeSpace(nentries * - (sizeof(AFSCallBack) + sizeof(AFSFid))); - fidsp = (AFSFid *) cbfMemp; - cbsp = (AFSCallBack *) (cbfMemp + nentries * sizeof(AFSFid)); + statsp = (AFSFetchStatus *) + osi_Alloc(AFSCBMAX * sizeof(AFSFetchStatus)); + fidsp = (AFSFid *) osi_AllocLargeSpace(nentries * sizeof(AFSFid)); + cbsp = (AFSCallBack *) + osi_Alloc(AFSCBMAX * sizeof(AFSCallBack)); /* next, we must iterate over the directory, starting from the specified * cookie offset (dirCookie), and counting out nentries file entries. @@ -1081,7 +1077,7 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp) afs_PutVolume(volp, READ_LOCK); /* If we did the InlineBulk RPC pull out the return code */ - if (inlinebulk) { + if (inlinebulk && code == 0) { if ((&statsp[0])->errorCode) { afs_Analyze(tcp, (&statsp[0])->errorCode, &adp->fid, areqp, AFS_STATS_FS_RPCIDX_BULKSTATUS, SHARED_LOCK, NULL); @@ -1091,8 +1087,9 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp) code = 0; } done2: - osi_FreeLargeSpace(statMemp); - osi_FreeLargeSpace(cbfMemp); + osi_FreeLargeSpace((char *)fidsp); + osi_Free((char *)statsp, AFSCBMAX * sizeof(AFSFetchStatus)); + osi_Free((char *)cbsp, AFSCBMAX * sizeof(AFSCallBack)); return code; } diff --git a/src/afs/VNOPS/afs_vnop_lookup.c.orig b/src/afs/VNOPS/afs_vnop_lookup.c.orig new file mode 100644 index 000000000..06a2e8fbe --- /dev/null +++ b/src/afs/VNOPS/afs_vnop_lookup.c.orig @@ -0,0 +1,1629 @@ +/* + * Copyright 2000, International Business Machines Corporation and others. + * All Rights Reserved. + * + * This software has been released under the terms of the IBM Public + * License. For details, see the LICENSE file in the top-level source + * directory or online at http://www.openafs.org/dl/license10.html + */ + +/* + * Implements: + * afs_lookup + * EvalMountPoint + * afs_DoBulkStat + */ + +#include +#include "afs/param.h" + +RCSID + ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_lookup.c,v 1.50.2.22 2008/08/26 14:02:14 shadow Exp $"); + +#include "afs/sysincludes.h" /* Standard vendor system headers */ +#include "afsincludes.h" /* Afs-based standard headers */ +#include "afs/afs_stats.h" /* statistics */ +#include "afs/afs_cbqueue.h" +#include "afs/nfsclient.h" +#include "afs/exporter.h" +#include "afs/afs_osidnlc.h" + + +extern struct DirEntry *afs_dir_GetBlob(); + + +afs_int32 afs_bkvolpref = 0; +afs_int32 afs_bulkStatsDone; +static int bulkStatCounter = 0; /* counter for bulk stat seq. numbers */ +int afs_fakestat_enable = 0; /* 1: fakestat-all, 2: fakestat-crosscell */ + + +/* this would be faster if it did comparison as int32word, but would be + * dependant on byte-order and alignment, and I haven't figured out + * what "@sys" is in binary... */ +#define AFS_EQ_ATSYS(name) (((name)[0]=='@')&&((name)[1]=='s')&&((name)[2]=='y')&&((name)[3]=='s')&&(!(name)[4])) + +/* call under write lock, evaluate mvid field from a mt pt. + * avc is the vnode of the mount point object; must be write-locked. + * advc is the vnode of the containing directory (optional; if NULL and + * EvalMountPoint succeeds, caller must initialize *avolpp->dotdot) + * avolpp is where we return a pointer to the volume named by the mount pt, if success + * areq is the identity of the caller. + * + * NOTE: this function returns a held volume structure in *volpp if it returns 0! + */ +int +EvalMountPoint(register struct vcache *avc, struct vcache *advc, + struct volume **avolpp, register struct vrequest *areq) +{ + afs_int32 code; + struct volume *tvp = 0; + struct VenusFid tfid; + struct cell *tcell; + char *cpos, *volnamep; + char type, *buf; + afs_int32 prefetch; /* 1=>None 2=>RO 3=>BK */ + afs_int32 mtptCell, assocCell = 0, hac = 0; + afs_int32 samecell, roname, len; + + AFS_STATCNT(EvalMountPoint); +#ifdef notdef + if (avc->mvid && (avc->states & CMValid)) + return 0; /* done while racing */ +#endif + *avolpp = NULL; + code = afs_HandleLink(avc, areq); + if (code) + return code; + + /* Determine which cell and volume the mointpoint goes to */ + type = avc->linkData[0]; /* '#'=>Regular '%'=>RW */ + cpos = afs_strchr(&avc->linkData[1], ':'); /* if cell name present */ + if (cpos) { + volnamep = cpos + 1; + *cpos = 0; + tcell = afs_GetCellByName(&avc->linkData[1], READ_LOCK); + *cpos = ':'; + } else { + volnamep = &avc->linkData[1]; + tcell = afs_GetCell(avc->fid.Cell, READ_LOCK); + } + if (!tcell) + return ENODEV; + + mtptCell = tcell->cellNum; /* The cell for the mountpoint */ + if (tcell->lcellp) { + hac = 1; /* has associated cell */ + assocCell = tcell->lcellp->cellNum; /* The associated cell */ + } + afs_PutCell(tcell, READ_LOCK); + + /* Is volume name a ".backup" or ".readonly" name */ + len = strlen(volnamep); + roname = ((len > 9) && (strcmp(&volnamep[len - 9], ".readonly") == 0)) + || ((len > 7) && (strcmp(&volnamep[len - 7], ".backup") == 0)); + + /* When we cross mountpoint, do we stay in the same cell */ + samecell = (avc->fid.Cell == mtptCell) || (hac + && (avc->fid.Cell == + assocCell)); + + /* Decide whether to prefetch the BK, or RO. Also means we want the BK or + * RO. + * If this is a regular mountpoint with a RW volume name + * - If BK preference is enabled AND we remain within the same cell AND + * start from a BK volume, then we will want to prefetch the BK volume. + * - If we cross a cell boundary OR start from a RO volume, then we will + * want to prefetch the RO volume. + */ + if ((type == '#') && !roname) { + if (afs_bkvolpref && samecell && (avc->states & CBackup)) + prefetch = 3; /* Prefetch the BK */ + else if (!samecell || (avc->states & CRO)) + prefetch = 2; /* Prefetch the RO */ + else + prefetch = 1; /* Do not prefetch */ + } else { + prefetch = 1; /* Do not prefetch */ + } + + /* Get the volume struct. Unless this volume name has ".readonly" or + * ".backup" in it, this will get the volume struct for the RW volume. + * The RO volume will be prefetched if requested (but not returned). + */ + tvp = afs_GetVolumeByName(volnamep, mtptCell, prefetch, areq, WRITE_LOCK); + + /* If no volume was found in this cell, try the associated linked cell */ + if (!tvp && hac && areq->volumeError) { + tvp = + afs_GetVolumeByName(volnamep, assocCell, prefetch, areq, + WRITE_LOCK); + } + + /* Still not found. If we are looking for the RO, then perhaps the RW + * doesn't exist? Try adding ".readonly" to volname and look for that. + * Don't know why we do this. Would have still found it in above call - jpm. + */ + if (!tvp && (prefetch == 2) && len < AFS_SMALLOCSIZ - 10) { + buf = (char *)osi_AllocSmallSpace(len + 10); + + strcpy(buf, volnamep); + afs_strcat(buf, ".readonly"); + + tvp = afs_GetVolumeByName(buf, mtptCell, 1, areq, WRITE_LOCK); + + /* Try the associated linked cell if failed */ + if (!tvp && hac && areq->volumeError) { + tvp = afs_GetVolumeByName(buf, assocCell, 1, areq, WRITE_LOCK); + } + osi_FreeSmallSpace(buf); + } + + if (!tvp) + return ENODEV; /* Couldn't find the volume */ + + /* Don't cross mountpoint from a BK to a BK volume */ + if ((avc->states & CBackup) && (tvp->states & VBackup)) { + afs_PutVolume(tvp, WRITE_LOCK); + return ENODEV; + } + + /* If we want (prefetched) the BK and it exists, then drop the RW volume + * and get the BK. + * Otherwise, if we want (prefetched0 the RO and it exists, then drop the + * RW volume and get the RO. + * Otherwise, go with the RW. + */ + if ((prefetch == 3) && tvp->backVol) { + tfid.Fid.Volume = tvp->backVol; /* remember BK volume */ + tfid.Cell = tvp->cell; + afs_PutVolume(tvp, WRITE_LOCK); /* release old volume */ + tvp = afs_GetVolume(&tfid, areq, WRITE_LOCK); /* get the new one */ + if (!tvp) + return ENODEV; /* oops, can't do it */ + } else if ((prefetch >= 2) && tvp->roVol) { + tfid.Fid.Volume = tvp->roVol; /* remember RO volume */ + tfid.Cell = tvp->cell; + afs_PutVolume(tvp, WRITE_LOCK); /* release old volume */ + tvp = afs_GetVolume(&tfid, areq, WRITE_LOCK); /* get the new one */ + if (!tvp) + return ENODEV; /* oops, can't do it */ + } + + if (avc->mvid == 0) + avc->mvid = + (struct VenusFid *)osi_AllocSmallSpace(sizeof(struct VenusFid)); + avc->mvid->Cell = tvp->cell; + avc->mvid->Fid.Volume = tvp->volume; + avc->mvid->Fid.Vnode = 1; + avc->mvid->Fid.Unique = 1; + avc->states |= CMValid; + + /* Used to: if the mount point is stored within a backup volume, + * then we should only update the parent pointer information if + * there's none already set, so as to avoid updating a volume's .. + * info with something in an OldFiles directory. + * + * Next two lines used to be under this if: + * + * if (!(avc->states & CBackup) || tvp->dotdot.Fid.Volume == 0) + * + * Now: update mount point back pointer on every call, so that we handle + * multiple mount points better. This way, when du tries to go back + * via chddir(".."), it will end up exactly where it started, yet + * cd'ing via a new path to a volume will reset the ".." pointer + * to the new path. + */ + tvp->mtpoint = avc->fid; /* setup back pointer to mtpoint */ + if (advc) + tvp->dotdot = advc->fid; + + *avolpp = tvp; + return 0; +} + +/* + * afs_InitFakeStat + * + * Must be called on an afs_fakestat_state object before calling + * afs_EvalFakeStat or afs_PutFakeStat. Calling afs_PutFakeStat + * without calling afs_EvalFakeStat is legal, as long as this + * function is called. + */ +void +afs_InitFakeStat(struct afs_fakestat_state *state) +{ + if (!afs_fakestat_enable) + return; + + state->valid = 1; + state->did_eval = 0; + state->need_release = 0; +} + +/* + * afs_EvalFakeStat_int + * + * The actual implementation of afs_EvalFakeStat and afs_TryEvalFakeStat, + * which is called by those wrapper functions. + * + * Only issues RPCs if canblock is non-zero. + */ +static int +afs_EvalFakeStat_int(struct vcache **avcp, struct afs_fakestat_state *state, + struct vrequest *areq, int canblock) +{ + struct vcache *tvc, *root_vp; + struct volume *tvolp = NULL; + int code = 0; + + if (!afs_fakestat_enable) + return 0; + + osi_Assert(state->valid == 1); + osi_Assert(state->did_eval == 0); + state->did_eval = 1; + + tvc = *avcp; + if (tvc->mvstat != 1) + return 0; + + /* Is the call to VerifyVCache really necessary? */ + code = afs_VerifyVCache(tvc, areq); + if (code) + goto done; + if (canblock) { + ObtainWriteLock(&tvc->lock, 599); + code = EvalMountPoint(tvc, NULL, &tvolp, areq); + ReleaseWriteLock(&tvc->lock); + if (code) + goto done; + if (tvolp) { + tvolp->dotdot = tvc->fid; + tvolp->dotdot.Fid.Vnode = tvc->parentVnode; + tvolp->dotdot.Fid.Unique = tvc->parentUnique; + } + } + if (tvc->mvid && (tvc->states & CMValid)) { + if (!canblock) { + afs_int32 retry; + + do { + retry = 0; + ObtainWriteLock(&afs_xvcache, 597); + root_vp = afs_FindVCache(tvc->mvid, &retry, IS_WLOCK); + if (root_vp && retry) { + ReleaseWriteLock(&afs_xvcache); + afs_PutVCache(root_vp); + } + } while (root_vp && retry); + ReleaseWriteLock(&afs_xvcache); + } else { + root_vp = afs_GetVCache(tvc->mvid, areq, NULL, NULL); + } + if (!root_vp) { + code = canblock ? ENOENT : 0; + goto done; + } +#ifdef AFS_DARWIN80_ENV + root_vp->m.Type = VDIR; + AFS_GUNLOCK(); + code = afs_darwin_finalizevnode(root_vp, NULL, NULL, 0); + AFS_GLOCK(); + if (code) goto done; + vnode_ref(AFSTOV(root_vp)); +#endif + if (tvolp) { + /* Is this always kosher? Perhaps we should instead use + * NBObtainWriteLock to avoid potential deadlock. + */ + ObtainWriteLock(&root_vp->lock, 598); + if (!root_vp->mvid) + root_vp->mvid = osi_AllocSmallSpace(sizeof(struct VenusFid)); + *root_vp->mvid = tvolp->dotdot; + ReleaseWriteLock(&root_vp->lock); + } + state->need_release = 1; + state->root_vp = root_vp; + *avcp = root_vp; + code = 0; + } else { + code = canblock ? ENOENT : 0; + } + + done: + if (tvolp) + afs_PutVolume(tvolp, WRITE_LOCK); + return code; +} + +/* + * afs_EvalFakeStat + * + * Automatically does the equivalent of EvalMountPoint for vcache entries + * which are mount points. Remembers enough state to properly release + * the volume root vcache when afs_PutFakeStat() is called. + * + * State variable must be initialized by afs_InitFakeState() beforehand. + * + * Returns 0 when everything succeeds and *avcp points to the vcache entry + * that should be used for the real vnode operation. Returns non-zero if + * something goes wrong and the error code should be returned to the user. + */ +int +afs_EvalFakeStat(struct vcache **avcp, struct afs_fakestat_state *state, + struct vrequest *areq) +{ + return afs_EvalFakeStat_int(avcp, state, areq, 1); +} + +/* + * afs_TryEvalFakeStat + * + * Same as afs_EvalFakeStat, but tries not to talk to remote servers + * and only evaluate the mount point if all the data is already in + * local caches. + * + * Returns 0 if everything succeeds and *avcp points to a valid + * vcache entry (possibly evaluated). + */ +int +afs_TryEvalFakeStat(struct vcache **avcp, struct afs_fakestat_state *state, + struct vrequest *areq) +{ + return afs_EvalFakeStat_int(avcp, state, areq, 0); +} + +/* + * afs_PutFakeStat + * + * Perform any necessary cleanup at the end of a vnode op, given that + * afs_InitFakeStat was previously called with this state. + */ +void +afs_PutFakeStat(struct afs_fakestat_state *state) +{ + if (!afs_fakestat_enable) + return; + + osi_Assert(state->valid == 1); + if (state->need_release) + afs_PutVCache(state->root_vp); + state->valid = 0; +} + +int +afs_ENameOK(register char *aname) +{ + register int tlen; + + AFS_STATCNT(ENameOK); + tlen = strlen(aname); + if (tlen >= 4 && strcmp(aname + tlen - 4, "@sys") == 0) + return 0; + return 1; +} + +static int +afs_getsysname(register struct vrequest *areq, register struct vcache *adp, + register char *bufp, int *num, char **sysnamelist[]) +{ + register struct unixuser *au; + register afs_int32 error; + + AFS_STATCNT(getsysname); + + *sysnamelist = afs_sysnamelist; + + if (!afs_nfsexporter) + strcpy(bufp, (*sysnamelist)[0]); + else { + au = afs_GetUser(areq->uid, adp->fid.Cell, 0); + if (au->exporter) { + error = EXP_SYSNAME(au->exporter, (char *)0, sysnamelist, num); + if (error) { + strcpy(bufp, "@sys"); + afs_PutUser(au, 0); + return -1; + } else { + strcpy(bufp, (*sysnamelist)[0]); + } + } else + strcpy(bufp, afs_sysname); + afs_PutUser(au, 0); + } + return 0; +} + +void +Check_AtSys(register struct vcache *avc, const char *aname, + struct sysname_info *state, struct vrequest *areq) +{ + int num = 0; + char **sysnamelist[MAXNUMSYSNAMES]; + + if (AFS_EQ_ATSYS(aname)) { + state->offset = 0; + state->name = (char *)osi_AllocLargeSpace(AFS_SMALLOCSIZ); + state->allocked = 1; + state->index = + afs_getsysname(areq, avc, state->name, &num, sysnamelist); + } else { + state->offset = -1; + state->allocked = 0; + state->index = 0; + state->name = (char *)aname; + } +} + +int +Next_AtSys(register struct vcache *avc, struct vrequest *areq, + struct sysname_info *state) +{ + int num = afs_sysnamecount; + char **sysnamelist[MAXNUMSYSNAMES]; + + if (state->index == -1) + return 0; /* No list */ + + /* Check for the initial state of aname != "@sys" in Check_AtSys */ + if (state->offset == -1 && state->allocked == 0) { + register char *tname; + + /* Check for .*@sys */ + for (tname = state->name; *tname; tname++) + /*Move to the end of the string */ ; + + if ((tname > state->name + 4) && (AFS_EQ_ATSYS(tname - 4))) { + state->offset = (tname - 4) - state->name; + tname = (char *)osi_AllocLargeSpace(AFS_LRALLOCSIZ); + strncpy(tname, state->name, state->offset); + state->name = tname; + state->allocked = 1; + num = 0; + state->index = + afs_getsysname(areq, avc, state->name + state->offset, &num, + sysnamelist); + return 1; + } else + return 0; /* .*@sys doesn't match either */ + } else { + register struct unixuser *au; + register afs_int32 error; + + *sysnamelist = afs_sysnamelist; + + if (afs_nfsexporter) { + au = afs_GetUser(areq->uid, avc->fid.Cell, 0); + if (au->exporter) { + error = + EXP_SYSNAME(au->exporter, (char *)0, sysnamelist, &num); + if (error) { + return 0; + } + } + afs_PutUser(au, 0); + } + if (++(state->index) >= num || !(*sysnamelist)[(unsigned int)state->index]) + return 0; /* end of list */ + } + strcpy(state->name + state->offset, (*sysnamelist)[(unsigned int)state->index]); + return 1; +} + +extern int BlobScan(struct dcache * afile, afs_int32 ablob); + +/* called with an unlocked directory and directory cookie. Areqp + * describes who is making the call. + * Scans the next N (about 30, typically) directory entries, and does + * a bulk stat call to stat them all. + * + * Must be very careful when merging in RPC responses, since we dont + * want to overwrite newer info that was added by a file system mutating + * call that ran concurrently with our bulk stat call. + * + * We do that, as described below, by not merging in our info (always + * safe to skip the merge) if the status info is valid in the vcache entry. + * + * If adapt ever implements the bulk stat RPC, then this code will need to + * ensure that vcaches created for failed RPC's to older servers have the + * CForeign bit set. + */ +static struct vcache *BStvc = NULL; + +int +afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp) +{ + int nentries; /* # of entries to prefetch */ + int nskip; /* # of slots in the LRU queue to skip */ + struct vcache *lruvcp; /* vcache ptr of our goal pos in LRU queue */ + struct dcache *dcp; /* chunk containing the dir block */ + char *statMemp; /* status memory block */ + char *cbfMemp; /* callback and fid memory block */ + afs_size_t temp; /* temp for holding chunk length, &c. */ + struct AFSFid *fidsp; /* file IDs were collecting */ + struct AFSCallBack *cbsp; /* call back pointers */ + struct AFSCallBack *tcbp; /* temp callback ptr */ + struct AFSFetchStatus *statsp; /* file status info */ + struct AFSVolSync volSync; /* vol sync return info */ + struct vcache *tvcp; /* temp vcp */ + struct afs_q *tq; /* temp queue variable */ + AFSCBFids fidParm; /* file ID parm for bulk stat */ + AFSBulkStats statParm; /* stat info parm for bulk stat */ + int fidIndex = 0; /* which file were stating */ + struct conn *tcp = 0; /* conn for call */ + AFSCBs cbParm; /* callback parm for bulk stat */ + struct server *hostp = 0; /* host we got callback from */ + long startTime; /* time we started the call, + * for callback expiration base + */ + afs_size_t statSeqNo = 0; /* Valued of file size to detect races */ + int code; /* error code */ + long newIndex; /* new index in the dir */ + struct DirEntry *dirEntryp; /* dir entry we are examining */ + int i; + struct VenusFid afid; /* file ID we are using now */ + struct VenusFid tfid; /* another temp. file ID */ + afs_int32 retry; /* handle low-level SGI MP race conditions */ + long volStates; /* flags from vol structure */ + struct volume *volp = 0; /* volume ptr */ + struct VenusFid dotdot; + int flagIndex = 0; /* First file with bulk fetch flag set */ + int inlinebulk = 0; /* Did we use InlineBulk RPC or not? */ + XSTATS_DECLS; +#ifdef AFS_DARWIN80_ENV + panic("bulkstatus doesn't work on AFS_DARWIN80_ENV. don't call it"); +#endif + /* first compute some basic parameters. We dont want to prefetch more + * than a fraction of the cache in any given call, and we want to preserve + * a portion of the LRU queue in any event, so as to avoid thrashing + * the entire stat cache (we will at least leave some of it alone). + * presently dont stat more than 1/8 the cache in any one call. */ + nentries = afs_cacheStats / 8; + + /* dont bother prefetching more than one calls worth of info */ + if (nentries > AFSCBMAX) + nentries = AFSCBMAX; + + /* heuristic to make sure that things fit in 4K. This means that + * we shouldnt make it any bigger than 47 entries. I am typically + * going to keep it a little lower, since we don't want to load + * too much of the stat cache. + */ + if (nentries > 30) + nentries = 30; + + /* now, to reduce the stack size, well allocate two 4K blocks, + * one for fids and callbacks, and one for stat info. Well set + * up our pointers to the memory from there, too. + */ + statMemp = osi_AllocLargeSpace(nentries * sizeof(AFSFetchStatus)); + statsp = (struct AFSFetchStatus *)statMemp; + cbfMemp = + osi_AllocLargeSpace(nentries * + (sizeof(AFSCallBack) + sizeof(AFSFid))); + fidsp = (AFSFid *) cbfMemp; + cbsp = (AFSCallBack *) (cbfMemp + nentries * sizeof(AFSFid)); + + /* next, we must iterate over the directory, starting from the specified + * cookie offset (dirCookie), and counting out nentries file entries. + * We skip files that already have stat cache entries, since we + * dont want to bulk stat files that are already in the cache. + */ + tagain: + code = afs_VerifyVCache(adp, areqp); + if (code) + goto done2; + + dcp = afs_GetDCache(adp, (afs_size_t) 0, areqp, &temp, &temp, 1); + if (!dcp) { + code = ENOENT; + goto done2; + } + + /* lock the directory cache entry */ + ObtainReadLock(&adp->lock); + ObtainReadLock(&dcp->lock); + + /* + * Make sure that the data in the cache is current. There are two + * cases we need to worry about: + * 1. The cache data is being fetched by another process. + * 2. The cache data is no longer valid + */ + while ((adp->states & CStatd) + && (dcp->dflags & DFFetching) + && hsame(adp->m.DataVersion, dcp->f.versionNo)) { + afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAIT, ICL_TYPE_STRING, + __FILE__, ICL_TYPE_INT32, __LINE__, ICL_TYPE_POINTER, dcp, + ICL_TYPE_INT32, dcp->dflags); + ReleaseReadLock(&dcp->lock); + ReleaseReadLock(&adp->lock); + afs_osi_Sleep(&dcp->validPos); + ObtainReadLock(&adp->lock); + ObtainReadLock(&dcp->lock); + } + if (!(adp->states & CStatd) + || !hsame(adp->m.DataVersion, dcp->f.versionNo)) { + ReleaseReadLock(&dcp->lock); + ReleaseReadLock(&adp->lock); + afs_PutDCache(dcp); + goto tagain; + } + + /* Generate a sequence number so we can tell whether we should + * store the attributes when processing the response. This number is + * stored in the file size when we set the CBulkFetching bit. If the + * CBulkFetching is still set and this value hasn't changed, then + * we know we were the last to set CBulkFetching bit for this file, + * and it is safe to set the status information for this file. + */ + statSeqNo = bulkStatCounter++; + + /* now we have dir data in the cache, so scan the dir page */ + fidIndex = 0; + flagIndex = 0; + while (1) { /* Should probably have some constant bound */ + /* look for first safe entry to examine in the directory. BlobScan + * looks for a the 1st allocated dir after the dirCookie slot. + */ + newIndex = BlobScan(dcp, (dirCookie >> 5)); + if (newIndex == 0) + break; + + /* remember the updated directory cookie */ + dirCookie = newIndex << 5; + + /* get a ptr to the dir entry */ + dirEntryp = + (struct DirEntry *)afs_dir_GetBlob(dcp, newIndex); + if (!dirEntryp) + break; + + /* dont copy more than we have room for */ + if (fidIndex >= nentries) { + DRelease((struct buffer *)dirEntryp, 0); + break; + } + + /* now, if the dir entry looks good, copy it out to our list. Vnode + * 0 means deleted, although it should also be free were it deleted. + */ + if (dirEntryp->fid.vnode != 0) { + /* dont copy entries we have in our cache. This check will + * also make us skip "." and probably "..", unless it has + * disappeared from the cache since we did our namei call. + */ + tfid.Cell = adp->fid.Cell; + tfid.Fid.Volume = adp->fid.Fid.Volume; + tfid.Fid.Vnode = ntohl(dirEntryp->fid.vnode); + tfid.Fid.Unique = ntohl(dirEntryp->fid.vunique); + do { + retry = 0; + ObtainWriteLock(&afs_xvcache, 130); + tvcp = afs_FindVCache(&tfid, &retry, IS_WLOCK /* no stats | LRU */ ); + if (tvcp && retry) { + ReleaseWriteLock(&afs_xvcache); + afs_PutVCache(tvcp); + } + } while (tvcp && retry); + if (!tvcp) { /* otherwise, create manually */ + tvcp = afs_NewVCache(&tfid, hostp); + if (tvcp) + { + ObtainWriteLock(&tvcp->lock, 505); + ReleaseWriteLock(&afs_xvcache); + afs_RemoveVCB(&tfid); + ReleaseWriteLock(&tvcp->lock); + } else { + ReleaseWriteLock(&afs_xvcache); + } + } else { + ReleaseWriteLock(&afs_xvcache); + } + if (!tvcp) + { + DRelease((struct buffer *)dirEntryp, 0); + ReleaseReadLock(&dcp->lock); + ReleaseReadLock(&adp->lock); + afs_PutDCache(dcp); + goto done; /* can happen if afs_NewVCache fails */ + } + +#ifdef AFS_DARWIN80_ENV + if (tvcp->states & CVInit) { + /* XXX don't have status yet, so creating the vnode is + not yet useful. we would get CDeadVnode set, and the + upcoming PutVCache will cause the vcache to be flushed & + freed, which in turn means the bulkstatus results won't + be used */ + } +#endif + /* WARNING: afs_DoBulkStat uses the Length field to store a + * sequence number for each bulk status request. Under no + * circumstances should afs_DoBulkStat store a sequence number + * if the new length will be ignored when afs_ProcessFS is + * called with new stats. */ +#ifdef AFS_SGI_ENV + if (!(tvcp->states & (CStatd | CBulkFetching)) + && (tvcp->execsOrWriters <= 0) + && !afs_DirtyPages(tvcp) + && !AFS_VN_MAPPED((vnode_t *) tvcp)) +#else + if (!(tvcp->states & (CStatd | CBulkFetching)) + && (tvcp->execsOrWriters <= 0) + && !afs_DirtyPages(tvcp)) +#endif + + { + /* this entry doesnt exist in the cache, and is not + * already being fetched by someone else, so add it to the + * list of file IDs to obtain. + * + * We detect a callback breaking race condition by checking the + * CBulkFetching state bit and the value in the file size. + * It is safe to set the status only if the CBulkFetching + * flag is still set and the value in the file size does + * not change. + * + * Don't fetch status for dirty files. We need to + * preserve the value of the file size. We could + * flush the pages, but it wouldn't be worthwhile. + */ + memcpy((char *)(fidsp + fidIndex), (char *)&tfid.Fid, + sizeof(*fidsp)); + tvcp->states |= CBulkFetching; + tvcp->m.Length = statSeqNo; + fidIndex++; + } + afs_PutVCache(tvcp); + } + + /* if dir vnode has non-zero entry */ + /* move to the next dir entry by adding in the # of entries + * used by this dir entry. + */ + temp = afs_dir_NameBlobs(dirEntryp->name) << 5; + DRelease((struct buffer *)dirEntryp, 0); + if (temp <= 0) + break; + dirCookie += temp; + } /* while loop over all dir entries */ + + /* now release the dir lock and prepare to make the bulk RPC */ + ReleaseReadLock(&dcp->lock); + ReleaseReadLock(&adp->lock); + + /* release the chunk */ + afs_PutDCache(dcp); + + /* dont make a null call */ + if (fidIndex == 0) + goto done; + + do { + /* setup the RPC parm structures */ + fidParm.AFSCBFids_len = fidIndex; + fidParm.AFSCBFids_val = fidsp; + statParm.AFSBulkStats_len = fidIndex; + statParm.AFSBulkStats_val = statsp; + cbParm.AFSCBs_len = fidIndex; + cbParm.AFSCBs_val = cbsp; + + /* start the timer; callback expirations are relative to this */ + startTime = osi_Time(); + + tcp = afs_Conn(&adp->fid, areqp, SHARED_LOCK); + if (tcp) { + hostp = tcp->srvr->server; + XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_BULKSTATUS); + RX_AFS_GUNLOCK(); + + if (!(tcp->srvr->server->flags & SNO_INLINEBULK)) { + code = + RXAFS_InlineBulkStatus(tcp->id, &fidParm, &statParm, + &cbParm, &volSync); + if (code == RXGEN_OPCODE) { + tcp->srvr->server->flags |= SNO_INLINEBULK; + inlinebulk = 0; + code = + RXAFS_BulkStatus(tcp->id, &fidParm, &statParm, + &cbParm, &volSync); + } else + inlinebulk = 1; + } else { + inlinebulk = 0; + code = + RXAFS_BulkStatus(tcp->id, &fidParm, &statParm, &cbParm, + &volSync); + } + RX_AFS_GLOCK(); + XSTATS_END_TIME; + } else + code = -1; + } while (afs_Analyze + (tcp, code, &adp->fid, areqp, AFS_STATS_FS_RPCIDX_BULKSTATUS, + SHARED_LOCK, NULL)); + + /* now, if we didnt get the info, bail out. */ + if (code) + goto done; + + /* we need vol flags to create the entries properly */ + dotdot.Fid.Volume = 0; + volp = afs_GetVolume(&adp->fid, areqp, READ_LOCK); + if (volp) { + volStates = volp->states; + if (volp->dotdot.Fid.Volume != 0) + dotdot = volp->dotdot; + } else + volStates = 0; + + /* find the place to merge the info into We do this by skipping + * nskip entries in the LRU queue. The more we skip, the more + * we preserve, since the head of the VLRU queue is the most recently + * referenced file. + */ + reskip: + nskip = afs_cacheStats / 2; /* preserved fraction of the cache */ + ObtainReadLock(&afs_xvcache); + if (QEmpty(&VLRU)) { + /* actually a serious error, probably should panic. Probably will + * panic soon, oh well. */ + ReleaseReadLock(&afs_xvcache); + afs_warnuser("afs_DoBulkStat: VLRU empty!"); + goto done; + } + if ((VLRU.next->prev != &VLRU) || (VLRU.prev->next != &VLRU)) { + refpanic("Bulkstat VLRU inconsistent"); + } + for (tq = VLRU.next; tq != &VLRU; tq = QNext(tq)) { + if (--nskip <= 0) + break; + else if (QNext(QPrev(tq)) != tq) { + BStvc = QTOV(tq); + refpanic("BulkStat VLRU inconsistent"); + } + } + if (tq != &VLRU) + lruvcp = QTOV(tq); + else + lruvcp = QTOV(VLRU.next); + + /* now we have to hold this entry, so that it does not get moved + * into the free list while we're running. It could still get + * moved within the lru queue, but hopefully that will be rare; it + * doesn't hurt nearly as much. + */ + retry = 0; + osi_vnhold(lruvcp, &retry); + ReleaseReadLock(&afs_xvcache); /* could be read lock */ + if (retry) + goto reskip; + + /* otherwise, merge in the info. We have to be quite careful here, + * since we need to ensure that we don't merge old info over newer + * stuff in a stat cache entry. We're very conservative here: we don't + * do the merge at all unless we ourselves create the stat cache + * entry. That's pretty safe, and should work pretty well, since we + * typically expect to do the stat cache creation ourselves. + * + * We also have to take into account racing token revocations. + */ + for (i = 0; i < fidIndex; i++) { + if ((&statsp[i])->errorCode) + continue; + afid.Cell = adp->fid.Cell; + afid.Fid.Volume = adp->fid.Fid.Volume; + afid.Fid.Vnode = fidsp[i].Vnode; + afid.Fid.Unique = fidsp[i].Unique; + do { + retry = 0; + ObtainReadLock(&afs_xvcache); + tvcp = afs_FindVCache(&afid, &retry, 0 /* !stats&!lru */ ); + ReleaseReadLock(&afs_xvcache); + } while (tvcp && retry); + + /* The entry may no longer exist */ + if (tvcp == NULL) { + continue; + } + + /* now we have the entry held, but we need to fill it in */ + ObtainWriteLock(&tvcp->lock, 131); + + /* if CBulkFetching is not set, or if the file size no longer + * matches the value we placed there when we set the CBulkFetching + * flag, then someone else has done something with this node, + * and we may not have the latest status information for this + * file. Leave the entry alone. + */ + if (!(tvcp->states & CBulkFetching) || (tvcp->m.Length != statSeqNo)) { + flagIndex++; + ReleaseWriteLock(&tvcp->lock); + afs_PutVCache(tvcp); + continue; + } + + /* now copy ".." entry back out of volume structure, if necessary */ + if (tvcp->mvstat == 2 && (dotdot.Fid.Volume != 0)) { + if (!tvcp->mvid) + tvcp->mvid = (struct VenusFid *) + osi_AllocSmallSpace(sizeof(struct VenusFid)); + *tvcp->mvid = dotdot; + } + + ObtainWriteLock(&afs_xvcache, 132); + if ((VLRU.next->prev != &VLRU) || (VLRU.prev->next != &VLRU)) { + refpanic("Bulkstat VLRU inconsistent2"); + } + if ((QNext(QPrev(&tvcp->vlruq)) != &tvcp->vlruq) + || (QPrev(QNext(&tvcp->vlruq)) != &tvcp->vlruq)) { + refpanic("Bulkstat VLRU inconsistent4"); + } + if ((QNext(QPrev(&lruvcp->vlruq)) != &lruvcp->vlruq) + || (QPrev(QNext(&lruvcp->vlruq)) != &lruvcp->vlruq)) { + refpanic("Bulkstat VLRU inconsistent5"); + } + + if (tvcp != lruvcp) { /* if they are == don't move it, don't corrupt vlru */ + QRemove(&tvcp->vlruq); + QAdd(&lruvcp->vlruq, &tvcp->vlruq); + } + + if ((VLRU.next->prev != &VLRU) || (VLRU.prev->next != &VLRU)) { + refpanic("Bulkstat VLRU inconsistent3"); + } + if ((QNext(QPrev(&tvcp->vlruq)) != &tvcp->vlruq) + || (QPrev(QNext(&tvcp->vlruq)) != &tvcp->vlruq)) { + refpanic("Bulkstat VLRU inconsistent5"); + } + if ((QNext(QPrev(&lruvcp->vlruq)) != &lruvcp->vlruq) + || (QPrev(QNext(&lruvcp->vlruq)) != &lruvcp->vlruq)) { + refpanic("Bulkstat VLRU inconsistent6"); + } + ReleaseWriteLock(&afs_xvcache); + + ObtainWriteLock(&afs_xcbhash, 494); + + /* We need to check the flags again. We may have missed + * something while we were waiting for a lock. + */ + if (!(tvcp->states & CBulkFetching) || (tvcp->m.Length != statSeqNo)) { + flagIndex++; + ReleaseWriteLock(&tvcp->lock); + ReleaseWriteLock(&afs_xcbhash); + afs_PutVCache(tvcp); + continue; + } + + /* now merge in the resulting status back into the vnode. + * We only do this if the entry looks clear. + */ + afs_ProcessFS(tvcp, &statsp[i], areqp); +#if defined(AFS_LINUX22_ENV) + afs_fill_inode(AFSTOV(tvcp), NULL); /* reset inode operations */ +#endif + + /* do some accounting for bulk stats: mark this entry as + * loaded, so we can tell if we use it before it gets + * recycled. + */ + tvcp->states |= CBulkStat; + tvcp->states &= ~CBulkFetching; + flagIndex++; + afs_bulkStatsDone++; + + /* merge in vol info */ + if (volStates & VRO) + tvcp->states |= CRO; + if (volStates & VBackup) + tvcp->states |= CBackup; + if (volStates & VForeign) + tvcp->states |= CForeign; + + /* merge in the callback info */ + tvcp->states |= CTruth; + + /* get ptr to the callback we are interested in */ + tcbp = cbsp + i; + + if (tcbp->ExpirationTime != 0) { + tvcp->cbExpires = tcbp->ExpirationTime + startTime; + tvcp->callback = hostp; + tvcp->states |= CStatd; + afs_QueueCallback(tvcp, CBHash(tcbp->ExpirationTime), volp); + } else if (tvcp->states & CRO) { + /* ordinary callback on a read-only volume -- AFS 3.2 style */ + tvcp->cbExpires = 3600 + startTime; + tvcp->callback = hostp; + tvcp->states |= CStatd; + afs_QueueCallback(tvcp, CBHash(3600), volp); + } else { + tvcp->callback = 0; + tvcp->states &= ~(CStatd | CUnique); + afs_DequeueCallback(tvcp); + if ((tvcp->states & CForeign) || (vType(tvcp) == VDIR)) + osi_dnlc_purgedp(tvcp); /* if it (could be) a directory */ + } + ReleaseWriteLock(&afs_xcbhash); + + ReleaseWriteLock(&tvcp->lock); + /* finally, we're done with the entry */ + afs_PutVCache(tvcp); + } /* for all files we got back */ + + /* finally return the pointer into the LRU queue */ + afs_PutVCache(lruvcp); + + done: + /* Be sure to turn off the CBulkFetching flags */ + for (i = flagIndex; i < fidIndex; i++) { + afid.Cell = adp->fid.Cell; + afid.Fid.Volume = adp->fid.Fid.Volume; + afid.Fid.Vnode = fidsp[i].Vnode; + afid.Fid.Unique = fidsp[i].Unique; + do { + retry = 0; + ObtainReadLock(&afs_xvcache); + tvcp = afs_FindVCache(&afid, &retry, 0 /* !stats&!lru */ ); + ReleaseReadLock(&afs_xvcache); + } while (tvcp && retry); + if (tvcp != NULL && (tvcp->states & CBulkFetching) + && (tvcp->m.Length == statSeqNo)) { + tvcp->states &= ~CBulkFetching; + } + if (tvcp != NULL) { + afs_PutVCache(tvcp); + } + } + if (volp) + afs_PutVolume(volp, READ_LOCK); + + /* If we did the InlineBulk RPC pull out the return code */ + if (inlinebulk) { + if ((&statsp[0])->errorCode) { + afs_Analyze(tcp, (&statsp[0])->errorCode, &adp->fid, areqp, + AFS_STATS_FS_RPCIDX_BULKSTATUS, SHARED_LOCK, NULL); + code = (&statsp[0])->errorCode; + } + } else { + code = 0; + } + done2: + osi_FreeLargeSpace(statMemp); + osi_FreeLargeSpace(cbfMemp); + return code; +} + +/* was: (AFS_DEC_ENV) || defined(AFS_OSF30_ENV) || defined(AFS_NCR_ENV) */ +#ifdef AFS_DARWIN80_ENV +#define AFSDOBULK 0 +#else +static int AFSDOBULK = 1; +#endif + +int +#ifdef AFS_OSF_ENV +afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, struct AFS_UCRED *acred, int opflag, int wantparent) +#elif defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) +afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, struct pathname *pnp, int flags, struct vnode *rdir, struct AFS_UCRED *acred) +#elif defined(UKERNEL) +afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, struct AFS_UCRED *acred, int flags) +#else +afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, struct AFS_UCRED *acred) +#endif +{ + struct vrequest treq; + char *tname = NULL; + register struct vcache *tvc = 0; + register afs_int32 code; + register afs_int32 bulkcode = 0; + int pass = 0, hit = 0; + int force_eval = afs_fakestat_enable ? 0 : 1; + long dirCookie; + extern afs_int32 afs_mariner; /*Writing activity to log? */ + afs_hyper_t versionNo; + int no_read_access = 0; + struct sysname_info sysState; /* used only for @sys checking */ + int dynrootRetry = 1; + struct afs_fakestat_state fakestate; + int tryEvalOnly = 0; + OSI_VC_CONVERT(adp); + + AFS_STATCNT(afs_lookup); + afs_InitFakeStat(&fakestate); + + if ((code = afs_InitReq(&treq, acred))) + goto done; + +#ifdef AFS_OSF_ENV + ndp->ni_dvp = AFSTOV(adp); +#endif /* AFS_OSF_ENV */ + + if (afs_fakestat_enable && adp->mvstat == 1) { + if (strcmp(aname, ".directory") == 0) + tryEvalOnly = 1; + } + +#if defined(AFS_DARWIN_ENV) + /* Workaround for MacOSX Finder, which tries to look for + * .DS_Store and Contents under every directory. + */ + if (afs_fakestat_enable && adp->mvstat == 1) { + if (strcmp(aname, ".DS_Store") == 0) + tryEvalOnly = 1; + if (strcmp(aname, "Contents") == 0) + tryEvalOnly = 1; + } +#endif + + if (tryEvalOnly) + code = afs_TryEvalFakeStat(&adp, &fakestate, &treq); + else + code = afs_EvalFakeStat(&adp, &fakestate, &treq); + if (tryEvalOnly && adp->mvstat == 1) + code = ENOENT; + if (code) + goto done; + + *avcp = NULL; /* Since some callers don't initialize it */ + + /* come back to here if we encounter a non-existent object in a read-only + * volume's directory */ + + redo: + *avcp = NULL; /* Since some callers don't initialize it */ + bulkcode = 0; + + if (!(adp->states & CStatd)) { + if ((code = afs_VerifyVCache2(adp, &treq))) { + goto done; + } + } else + code = 0; + + /* watch for ".." in a volume root */ + if (adp->mvstat == 2 && aname[0] == '.' && aname[1] == '.' && !aname[2]) { + /* looking up ".." in root via special hacks */ + if (adp->mvid == (struct VenusFid *)0 || adp->mvid->Fid.Volume == 0) { +#ifdef AFS_OSF_ENV + extern struct vcache *afs_globalVp; + if (adp == afs_globalVp) { + struct vnode *rvp = AFSTOV(adp); +/* + ndp->ni_vp = rvp->v_vfsp->vfs_vnodecovered; + ndp->ni_dvp = ndp->ni_vp; + VN_HOLD(*avcp); +*/ + code = ENODEV; + goto done; + } +#endif + code = ENODEV; + goto done; + } + /* otherwise we have the fid here, so we use it */ + tvc = afs_GetVCache(adp->mvid, &treq, NULL, NULL); + afs_Trace3(afs_iclSetp, CM_TRACE_GETVCDOTDOT, ICL_TYPE_FID, adp->mvid, + ICL_TYPE_POINTER, tvc, ICL_TYPE_INT32, code); + *avcp = tvc; + code = (tvc ? 0 : ENOENT); + hit = 1; + if (tvc && !VREFCOUNT_GT(tvc, 0)) { + osi_Panic("TT1"); + } + if (code) { + /*printf("LOOKUP GETVCDOTDOT -> %d\n", code); */ + } + goto done; + } + + /* now check the access */ + if (treq.uid != adp->last_looker) { + if (!afs_AccessOK(adp, PRSFS_LOOKUP, &treq, CHECK_MODE_BITS)) { + *avcp = NULL; + code = EACCES; + goto done; + } else + adp->last_looker = treq.uid; + } + + /* Check for read access as well. We need read access in order to + * stat files, but not to stat subdirectories. */ + if (!afs_AccessOK(adp, PRSFS_READ, &treq, CHECK_MODE_BITS)) + no_read_access = 1; + + /* special case lookup of ".". Can we check for it sooner in this code, + * for instance, way up before "redo:" ?? + * I'm not fiddling with the LRUQ here, either, perhaps I should, or else + * invent a lightweight version of GetVCache. + */ + if (aname[0] == '.' && !aname[1]) { /* special case */ + ObtainReadLock(&afs_xvcache); + osi_vnhold(adp, 0); + ReleaseReadLock(&afs_xvcache); +#ifdef AFS_DARWIN80_ENV + vnode_get(AFSTOV(adp)); +#endif + code = 0; + *avcp = tvc = adp; + hit = 1; + if (adp && !VREFCOUNT_GT(adp, 0)) { + osi_Panic("TT2"); + } + goto done; + } + + Check_AtSys(adp, aname, &sysState, &treq); + tname = sysState.name; + + /* 1st Check_AtSys and lookup by tname is required here, for now, + * because the dnlc is *not* told to remove entries for the parent + * dir of file/dir op that afs_LocalHero likes, but dnlc is informed + * if the cached entry for the parent dir is invalidated for a + * non-local change. + * Otherwise, we'd be able to do a dnlc lookup on an entry ending + * w/@sys and know the dnlc was consistent with reality. */ + tvc = osi_dnlc_lookup(adp, tname, WRITE_LOCK); + *avcp = tvc; /* maybe wasn't initialized, but it is now */ + if (tvc) { + if (no_read_access && vType(tvc) != VDIR && vType(tvc) != VLNK) { + /* need read access on dir to stat non-directory / non-link */ +#ifndef AFS_FBSD80_ENV + afs_PutVCache(tvc); +#endif + *avcp = NULL; + code = EACCES; + goto done; + } +#ifdef AFS_LINUX22_ENV + if (tvc->mvstat == 2) { /* we don't trust the dnlc for root vcaches */ + AFS_RELE(AFSTOV(tvc)); + *avcp = 0; + } else { + code = 0; + hit = 1; + goto done; + } +#else /* non - LINUX */ + code = 0; + hit = 1; + goto done; +#endif /* linux22 */ + } + + { /* sub-block just to reduce stack usage */ + register struct dcache *tdc; + afs_size_t dirOffset, dirLen; + struct VenusFid tfid; + + /* now we have to lookup the next fid */ + tdc = + afs_GetDCache(adp, (afs_size_t) 0, &treq, &dirOffset, &dirLen, 1); + if (!tdc) { + *avcp = NULL; /* redundant, but harmless */ + code = EIO; + goto done; + } + + /* now we will just call dir package with appropriate inode. + * Dirs are always fetched in their entirety for now */ + ObtainReadLock(&adp->lock); + ObtainReadLock(&tdc->lock); + + /* + * Make sure that the data in the cache is current. There are two + * cases we need to worry about: + * 1. The cache data is being fetched by another process. + * 2. The cache data is no longer valid + */ + while ((adp->states & CStatd) + && (tdc->dflags & DFFetching) + && hsame(adp->m.DataVersion, tdc->f.versionNo)) { + ReleaseReadLock(&tdc->lock); + ReleaseReadLock(&adp->lock); + afs_osi_Sleep(&tdc->validPos); + ObtainReadLock(&adp->lock); + ObtainReadLock(&tdc->lock); + } + if (!(adp->states & CStatd) + || !hsame(adp->m.DataVersion, tdc->f.versionNo)) { + ReleaseReadLock(&tdc->lock); + ReleaseReadLock(&adp->lock); + afs_PutDCache(tdc); + if (tname && tname != aname) + osi_FreeLargeSpace(tname); + goto redo; + } + + /* Save the version number for when we call osi_dnlc_enter */ + hset(versionNo, tdc->f.versionNo); + + /* + * check for, and handle "@sys" if it's there. We should be able + * to avoid the alloc and the strcpy with a little work, but it's + * not pressing. If there aren't any remote users (ie, via the + * NFS translator), we have a slightly easier job. + * the faster way to do this is to check for *aname == '@' and if + * it's there, check for @sys, otherwise, assume there's no @sys + * then, if the lookup fails, check for .*@sys... + */ + /* above now implemented by Check_AtSys and Next_AtSys */ + + /* lookup the name in the appropriate dir, and return a cache entry + * on the resulting fid */ + code = + afs_dir_LookupOffset(tdc, sysState.name, &tfid.Fid, + &dirCookie); + + /* If the first lookup doesn't succeed, maybe it's got @sys in the name */ + while (code == ENOENT && Next_AtSys(adp, &treq, &sysState)) + code = + afs_dir_LookupOffset(tdc, sysState.name, &tfid.Fid, + &dirCookie); + tname = sysState.name; + + ReleaseReadLock(&tdc->lock); + afs_PutDCache(tdc); + + if (code == ENOENT && afs_IsDynroot(adp) && dynrootRetry) { + ReleaseReadLock(&adp->lock); + dynrootRetry = 0; + if (tname[0] == '.') + afs_LookupAFSDB(tname + 1); + else + afs_LookupAFSDB(tname); + if (tname && tname != aname) + osi_FreeLargeSpace(tname); + goto redo; + } else { + ReleaseReadLock(&adp->lock); + } + + /* new fid has same cell and volume */ + tfid.Cell = adp->fid.Cell; + tfid.Fid.Volume = adp->fid.Fid.Volume; + afs_Trace4(afs_iclSetp, CM_TRACE_LOOKUP, ICL_TYPE_POINTER, adp, + ICL_TYPE_STRING, tname, ICL_TYPE_FID, &tfid, + ICL_TYPE_INT32, code); + + if (code) { + if (code != ENOENT) { + printf("LOOKUP dirLookupOff -> %d\n", code); + } + goto done; + } + + /* prefetch some entries, if the dir is currently open. The variable + * dirCookie tells us where to start prefetching from. + */ + if (AFSDOBULK && adp->opens > 0 && !(adp->states & CForeign) + && !afs_IsDynroot(adp)) { + afs_int32 retry; + /* if the entry is not in the cache, or is in the cache, + * but hasn't been statd, then do a bulk stat operation. + */ + do { + retry = 0; + ObtainReadLock(&afs_xvcache); + tvc = afs_FindVCache(&tfid, &retry, 0 /* !stats,!lru */ ); + ReleaseReadLock(&afs_xvcache); + } while (tvc && retry); + + if (!tvc || !(tvc->states & CStatd)) + bulkcode = afs_DoBulkStat(adp, dirCookie, &treq); + else + bulkcode = 0; + + /* if the vcache isn't usable, release it */ + if (tvc && !(tvc->states & CStatd)) { +#ifndef AFS_FBSD80_ENV + afs_PutVCache(tvc); +#endif + tvc = NULL; + } + } else { + tvc = NULL; + bulkcode = 0; + } + + /* now get the status info, if we don't already have it */ + /* This is kind of weird, but we might wind up accidentally calling + * RXAFS_Lookup because we happened upon a file which legitimately + * has a 0 uniquifier. That is the result of allowing unique to wrap + * to 0. This was fixed in AFS 3.4. For CForeign, Unique == 0 means that + * the file has not yet been looked up. + */ + if (!tvc) { + afs_int32 cached = 0; + if (!tfid.Fid.Unique && (adp->states & CForeign)) { + tvc = afs_LookupVCache(&tfid, &treq, &cached, adp, tname); + } + if (!tvc && !bulkcode) { /* lookup failed or wasn't called */ + tvc = afs_GetVCache(&tfid, &treq, &cached, NULL); + } + } /* if !tvc */ + } /* sub-block just to reduce stack usage */ + + if (tvc) { + if (adp->states & CForeign) + tvc->states |= CForeign; + tvc->parentVnode = adp->fid.Fid.Vnode; + tvc->parentUnique = adp->fid.Fid.Unique; + tvc->states &= ~CBulkStat; + + if (afs_fakestat_enable == 2 && tvc->mvstat == 1) { + ObtainSharedLock(&tvc->lock, 680); + if (!tvc->linkData) { + UpgradeSToWLock(&tvc->lock, 681); + code = afs_HandleLink(tvc, &treq); + ConvertWToRLock(&tvc->lock); + } else { + ConvertSToRLock(&tvc->lock); + code = 0; + } + if (!code && !afs_strchr(tvc->linkData, ':')) + force_eval = 1; + ReleaseReadLock(&tvc->lock); + } + if (tvc->mvstat == 1 && (tvc->states & CMValid) && tvc->mvid != NULL) + force_eval = 1; /* This is now almost for free, get it correct */ + +#if defined(UKERNEL) && defined(AFS_WEB_ENHANCEMENTS) + if (!(flags & AFS_LOOKUP_NOEVAL)) + /* don't eval mount points */ +#endif /* UKERNEL && AFS_WEB_ENHANCEMENTS */ + if (tvc->mvstat == 1 && force_eval) { + /* a mt point, possibly unevaluated */ + struct volume *tvolp; + + ObtainWriteLock(&tvc->lock, 133); + code = EvalMountPoint(tvc, adp, &tvolp, &treq); + ReleaseWriteLock(&tvc->lock); + + if (code) { +#ifndef AFS_FBSD80_ENV + afs_PutVCache(tvc); +#endif + if (tvolp) + afs_PutVolume(tvolp, WRITE_LOCK); + goto done; + } + + /* next, we want to continue using the target of the mt point */ + if (tvc->mvid && (tvc->states & CMValid)) { + struct vcache *uvc; + /* now lookup target, to set .. pointer */ + afs_Trace2(afs_iclSetp, CM_TRACE_LOOKUP1, + ICL_TYPE_POINTER, tvc, ICL_TYPE_FID, + &tvc->fid); + uvc = tvc; /* remember for later */ + + if (tvolp && (tvolp->states & VForeign)) { + /* XXXX tvolp has ref cnt on but not locked! XXX */ + tvc = + afs_GetRootVCache(tvc->mvid, &treq, NULL, tvolp); + } else { + tvc = afs_GetVCache(tvc->mvid, &treq, NULL, NULL); + } +#ifndef AFS_FBSD80_ENV + afs_PutVCache(uvc); /* we're done with it */ +#endif + + if (!tvc) { + code = ENOENT; + if (tvolp) { + afs_PutVolume(tvolp, WRITE_LOCK); + } + goto done; + } + + /* now, if we came via a new mt pt (say because of a new + * release of a R/O volume), we must reevaluate the .. + * ptr to point back to the appropriate place */ + if (tvolp) { + ObtainWriteLock(&tvc->lock, 134); + if (tvc->mvid == NULL) { + tvc->mvid = (struct VenusFid *) + osi_AllocSmallSpace(sizeof(struct VenusFid)); + } + /* setup backpointer */ + *tvc->mvid = tvolp->dotdot; + ReleaseWriteLock(&tvc->lock); + afs_PutVolume(tvolp, WRITE_LOCK); + } + } else { +#ifndef AFS_FBSD80_ENV + afs_PutVCache(tvc); +#endif + code = ENOENT; + if (tvolp) + afs_PutVolume(tvolp, WRITE_LOCK); + goto done; + } + } + *avcp = tvc; + if (tvc && !VREFCOUNT_GT(tvc, 0)) { + osi_Panic("TT3"); + } + code = 0; + } else { + /* if we get here, we found something in a directory that couldn't + * be located (a Multics "connection failure"). If the volume is + * read-only, we try flushing this entry from the cache and trying + * again. */ + if (pass == 0) { + struct volume *tv; + tv = afs_GetVolume(&adp->fid, &treq, READ_LOCK); + if (tv) { + if (tv->states & VRO) { + pass = 1; /* try this *once* */ + ObtainWriteLock(&afs_xcbhash, 495); + afs_DequeueCallback(adp); + /* re-stat to get later version */ + adp->states &= ~CStatd; + ReleaseWriteLock(&afs_xcbhash); + osi_dnlc_purgedp(adp); + afs_PutVolume(tv, READ_LOCK); + goto redo; + } + afs_PutVolume(tv, READ_LOCK); + } + } + code = ENOENT; + } + + done: + /* put the network buffer back, if need be */ + if (tname != aname && tname) + osi_FreeLargeSpace(tname); + if (code == 0) { +#ifdef AFS_OSF_ENV + /* Handle RENAME; only need to check rename "." */ + if (opflag == RENAME && wantparent && *ndp->ni_next == 0) { + if (!FidCmp(&(tvc->fid), &(adp->fid))) { + afs_PutVCache(*avcp); + *avcp = NULL; + afs_PutFakeStat(&fakestate); + return afs_CheckCode(EISDIR, &treq, 18); + } + } +#endif /* AFS_OSF_ENV */ + + if (afs_mariner) + afs_AddMarinerName(aname, tvc); + +#if defined(UKERNEL) && defined(AFS_WEB_ENHANCEMENTS) + if (!(flags & AFS_LOOKUP_NOEVAL)) + /* Here we don't enter the name into the DNLC because we want the + * evaluated mount dir to be there (the vcache for the mounted volume) + * rather than the vc of the mount point itself. we can still find the + * mount point's vc in the vcache by its fid. */ +#endif /* UKERNEL && AFS_WEB_ENHANCEMENTS */ + if (!hit && force_eval) { + osi_dnlc_enter(adp, aname, tvc, &versionNo); + } else { +#ifdef AFS_LINUX20_ENV + /* So Linux inode cache is up to date. */ + code = afs_VerifyVCache(tvc, &treq); +#else + afs_PutFakeStat(&fakestate); + return 0; /* can't have been any errors if hit and !code */ +#endif + } + } + if (bulkcode) + code = bulkcode; + + code = afs_CheckCode(code, &treq, 19); + if (code) { + /* If there is an error, make sure *avcp is null. + * Alphas panic otherwise - defect 10719. + */ + *avcp = NULL; + } + + afs_PutFakeStat(&fakestate); + return code; +} diff --git a/src/afs/afs_osi.c b/src/afs/afs_osi.c index 5bbf8c9bc..228b42317 100644 --- a/src/afs/afs_osi.c +++ b/src/afs/afs_osi.c @@ -11,7 +11,7 @@ #include "afs/param.h" RCSID - ("$Header: /cvs/openafs/src/afs/afs_osi.c,v 1.48.2.19 2009/01/15 13:27:43 shadow Exp $"); + ("$Header: /cvs/openafs/src/afs/afs_osi.c,v 1.48.2.20 2009/03/27 15:55:43 shadow Exp $"); #include "afs/sysincludes.h" /* Standard vendor system headers */ #include "afsincludes.h" /* Afs-based standard headers */ @@ -435,6 +435,8 @@ afs_osi_Alloc(size_t x) return osi_linux_alloc(x, 1); #elif defined(AFS_FBSD_ENV) return osi_fbsd_alloc(x, 1); +#elif defined(AFS_OBSD_ENV) + return osi_obsd_Alloc(x, 1); #else size = x; tm = (struct osimem *)AFS_KALLOC(size); diff --git a/src/afs/afs_vcache.c b/src/afs/afs_vcache.c index 0f4210f7d..2a3a8e8bf 100644 --- a/src/afs/afs_vcache.c +++ b/src/afs/afs_vcache.c @@ -39,7 +39,7 @@ #include "afs/param.h" RCSID - ("$Header: /cvs/openafs/src/afs/afs_vcache.c,v 1.65.2.54 2009/03/25 19:34:59 shadow Exp $"); + ("$Header: /cvs/openafs/src/afs/afs_vcache.c,v 1.65.2.55 2009/03/31 12:41:47 shadow Exp $"); #include "afs/sysincludes.h" /*Standard vendor system headers */ #include "afsincludes.h" /*AFS-based standard headers */ @@ -784,7 +784,7 @@ afs_AllocVCache(void) /* track the peak */ if (afsd_dynamic_vcaches && afs_maxvcount < afs_vcount) { afs_maxvcount = afs_vcount; - printf("peak vnodes: %d\n", afs_maxvcount); + /*printf("peak vnodes: %d\n", afs_maxvcount);*/ } #endif afs_stats_cmperf.vcacheXAllocs++; /* count in case we have a leak */ diff --git a/src/bozo/bnode.c b/src/bozo/bnode.c index 35a89c48d..663320e7a 100644 --- a/src/bozo/bnode.c +++ b/src/bozo/bnode.c @@ -11,7 +11,7 @@ #include RCSID - ("$Header: /cvs/openafs/src/bozo/bnode.c,v 1.17.2.10 2009/02/17 04:32:30 shadow Exp $"); + ("$Header: /cvs/openafs/src/bozo/bnode.c,v 1.17.2.11 2009/03/26 14:30:46 shadow Exp $"); #include #include @@ -753,6 +753,7 @@ SendNotifierData(register int fd, register struct bnode_proc *tp) if (write(fd, buffer, len) < 0) { return -1; } + return 0; } int diff --git a/src/bucoord/ubik_db_if.c b/src/bucoord/ubik_db_if.c index b7b209f7a..c9a5037bb 100644 --- a/src/bucoord/ubik_db_if.c +++ b/src/bucoord/ubik_db_if.c @@ -13,7 +13,7 @@ #include RCSID - ("$Header: /cvs/openafs/src/bucoord/ubik_db_if.c,v 1.10.2.4 2009/01/22 19:33:26 shadow Exp $"); + ("$Header: /cvs/openafs/src/bucoord/ubik_db_if.c,v 1.10.2.5 2009/03/27 13:46:13 shadow Exp $"); #include #include @@ -883,7 +883,7 @@ vldbClientInit(noAuthFlag, localauth, cellName, cstruct, ttoken) afs_com_err(whoami, code, 0, "; Can't get AFS tokens - running unauthenticated"); } else { - if ((ttoken->kvno < 0) || (ttoken->kvno > 255)) + if ((ttoken->kvno < 0) || (ttoken->kvno > 256)) afs_com_err(whoami, 0, "Funny kvno (%d) in ticket, proceeding", ttoken->kvno); @@ -1026,7 +1026,7 @@ udbClientInit(noAuthFlag, localauth, cellName) afs_com_err(whoami, code, "; Can't get tokens - running unauthenticated"); } else { - if ((token.kvno < 0) || (token.kvno > 255)) + if ((token.kvno < 0) || (token.kvno > 256)) afs_com_err(whoami, 0, "Unexpected kvno (%d) in ticket - proceeding", token.kvno); diff --git a/src/budb/ol_verify.c b/src/budb/ol_verify.c index 11c7dde8b..43bd71190 100644 --- a/src/budb/ol_verify.c +++ b/src/budb/ol_verify.c @@ -13,7 +13,7 @@ #include RCSID - ("$Header: /cvs/openafs/src/budb/ol_verify.c,v 1.13.2.2 2007/10/30 15:23:50 shadow Exp $"); + ("$Header: /cvs/openafs/src/budb/ol_verify.c,v 1.13.2.3 2009/03/26 14:30:44 shadow Exp $"); #include #ifdef AFS_NT40_ENV @@ -1495,8 +1495,8 @@ DbVerify(call, status, orphans, host) * do a simple sanity check on the database header */ -check_header(callerst) - char *callerst; +void +check_header(char *callerst) { static int iteration_count = 0; afs_int32 eof; diff --git a/src/cf/linux-test4.m4 b/src/cf/linux-test4.m4 index 409dd0575..b8093a1b9 100644 --- a/src/cf/linux-test4.m4 +++ b/src/cf/linux-test4.m4 @@ -1138,3 +1138,17 @@ _u =_t.cred->uid ;], if test "x$ac_cv_linux_struct_task_has_cred" = "xyes"; then AC_DEFINE([STRUCT_TASK_HAS_CRED], 1, [define if struct task has a cred pointer]) fi]) + +AC_DEFUN([LINUX_STRUCT_PROC_DIR_ENTRY_HAS_OWNER], [ + AC_MSG_CHECKING([if struct proc_dir_entry_has_owner]) + AC_CACHE_VAL([ac_cv_linux_struct_proc_dir_entry_has_owner], [ + AC_TRY_KBUILD( +[#include ], +[struct proc_dir_entry _p; +_p.owner= "";], + ac_cv_linux_struct_proc_dir_entry_has_owner=yes, + ac_cv_linux_struct_proc_dir_entry_has_owner=no)]) + AC_MSG_RESULT($ac_cv_linux_struct_proc_dir_entry_has_owner) + if test "x$ac_cv_linux_struct_proc_dir_entry_has_owner" = "xyes"; then + AC_DEFINE([STRUCT_PROC_DIR_ENTRY_HAS_OWNER], 1, [define if struct proc_dir_entry has an owner member]) + fi]) diff --git a/src/config/afs_sysnames.h b/src/config/afs_sysnames.h index 77f16d924..09961fd84 100644 --- a/src/config/afs_sysnames.h +++ b/src/config/afs_sysnames.h @@ -246,6 +246,9 @@ #define SYS_NAME_ID_i386_obsd39 2608 #define SYS_NAME_ID_i386_obsd40 2609 #define SYS_NAME_ID_i386_obsd41 2610 +#define SYS_NAME_ID_i386_obsd42 2611 +#define SYS_NAME_ID_i386_obsd43 2612 +#define SYS_NAME_ID_i386_obsd44 2613 #define SYS_NAME_ID_amd64_linux2 2700 #define SYS_NAME_ID_amd64_linux22 2701 diff --git a/src/config/afsconfig.h.in b/src/config/afsconfig.h.in index 9cbe02bc8..e64dd9ead 100644 --- a/src/config/afsconfig.h.in +++ b/src/config/afsconfig.h.in @@ -672,6 +672,9 @@ static /**/const char *const rcsid[] = { (char *)rcsid, "\100(#)" msg } /* define if your struct nameidata has path */ #undef STRUCT_NAMEIDATA_HAS_PATH +/* define if struct proc_dir_entry has an owner member */ +#undef STRUCT_PROC_DIR_ENTRY_HAS_OWNER + /* define if you struct sockaddr sa_len */ #undef STRUCT_SOCKADDR_HAS_SA_LEN diff --git a/src/rx/UKERNEL/rx_knet.c b/src/rx/UKERNEL/rx_knet.c index edd699228..7349866f8 100644 --- a/src/rx/UKERNEL/rx_knet.c +++ b/src/rx/UKERNEL/rx_knet.c @@ -11,7 +11,7 @@ #include "afs/param.h" RCSID - ("$Header: /cvs/openafs/src/rx/UKERNEL/rx_knet.c,v 1.10.2.4 2008/03/10 22:35:36 shadow Exp $"); + ("$Header: /cvs/openafs/src/rx/UKERNEL/rx_knet.c,v 1.10.2.5 2009/03/26 14:30:42 shadow Exp $"); #include "rx/rx_kcommon.h" @@ -161,6 +161,7 @@ rx_ServerProc(void *unused) /* assert(newcall != NULL); */ } AFS_GLOCK(); + return NULL; } /* diff --git a/src/rx/rx_kcommon.c b/src/rx/rx_kcommon.c index 187406f75..70560bf19 100644 --- a/src/rx/rx_kcommon.c +++ b/src/rx/rx_kcommon.c @@ -15,7 +15,7 @@ #include "afs/param.h" RCSID - ("$Header: /cvs/openafs/src/rx/rx_kcommon.c,v 1.44.2.20 2008/08/22 04:32:01 shadow Exp $"); + ("$Header: /cvs/openafs/src/rx/rx_kcommon.c,v 1.44.2.21 2009/03/27 15:55:45 shadow Exp $"); #include "rx/rx_kcommon.h" @@ -996,10 +996,12 @@ rxk_NewSocketHost(afs_uint32 ahost, short aport) } nam->m_len = sizeof(myaddr); memcpy(mtod(nam, caddr_t), &myaddr, sizeof(myaddr)); -#ifdef AFS_SGI65_ENV +#if defined(AFS_SGI65_ENV) BHV_PDATA(&bhv) = (void *)newSocket; code = sobind(&bhv, nam); m_freem(nam); +#elif defined(AFS_OBSD44_ENV) + code = sobind(newSocket, nam, osi_curproc()); #else code = sobind(newSocket, nam); #endif diff --git a/src/rx/xdr.h b/src/rx/xdr.h index d28a17ef7..8de3ffd14 100644 --- a/src/rx/xdr.h +++ b/src/rx/xdr.h @@ -96,11 +96,13 @@ #define osi_free afs_osi_Free /* keep here for now, 64 bit issues */ +#ifndef AFS_OBSD44_ENV extern void *afs_osi_Alloc(size_t x); #ifndef afs_osi_Alloc_NoSleep extern void *afs_osi_Alloc_NoSleep(size_t x); #endif extern void afs_osi_Free(void *x, size_t asize); +#endif #endif #ifndef major /* ouch! */ diff --git a/src/rx/xdr_arrayn.c b/src/rx/xdr_arrayn.c index c9fc91b68..a54f1184a 100644 --- a/src/rx/xdr_arrayn.c +++ b/src/rx/xdr_arrayn.c @@ -26,11 +26,17 @@ * 2550 Garcia Avenue * Mountain View, California 94043 */ + #include #include RCSID - ("$Header: /cvs/openafs/src/rx/xdr_arrayn.c,v 1.8.2.2 2005/04/03 18:15:51 shadow Exp $"); + ("$Header: /cvs/openafs/src/rx/xdr_arrayn.c,v 1.8.2.3 2009/03/27 15:55:46 shadow Exp $"); + +#if defined(AFS_OBSD44_ENV) && defined(KERNEL) && !defined(UKERNEL) +/* XXX osi_alloc, please find and fix */ +#include "osi_machdep.h" +#endif #if !defined(NeXT) @@ -44,6 +50,7 @@ RCSID */ #if defined(KERNEL) && !defined(UKERNEL) + #include #ifdef AFS_LINUX20_ENV #include "h/string.h" diff --git a/src/sys/rmtsysc.c b/src/sys/rmtsysc.c index c9eeed8ec..c43cf9120 100644 --- a/src/sys/rmtsysc.c +++ b/src/sys/rmtsysc.c @@ -241,8 +241,14 @@ pioctl(char *path, afs_int32 cmd, struct ViceIoctl *data, afs_int32 follow) InData.rmtbulk_len = data->in_size; InData.rmtbulk_val = inbuffer; inparam_conversion(cmd, InData.rmtbulk_val, 0); - OutData.rmtbulk_len = data->out_size; - OutData.rmtbulk_val = data->out; + + OutData.rmtbulk_len = MAXBUFFERLEN * sizeof(*OutData.rmtbulk_val); + OutData.rmtbulk_val = malloc(OutData.rmtbulk_len); + if (!OutData.rmtbulk_val) { + free(inbuffer); + return -1; + } + /* We always need to pass absolute pathnames to the remote pioctl since we * lose the current directory value when doing an rpc call. Below we * prepend the current absolute path directory, if the name is relative */ @@ -279,8 +285,15 @@ pioctl(char *path, afs_int32 cmd, struct ViceIoctl *data, afs_int32 follow) if (!errorcode) { /* Do the conversions back to the host order; store the results back * on the same buffer */ - outparam_conversion(cmd, OutData.rmtbulk_val, 1); + if (data->out_size < OutData.rmtbulk_len) { + errno = EINVAL; + errorcode = -1; + } else { + memcpy(data->out, OutData.rmtbulk_val, data->out_size); + outparam_conversion(cmd, data->out, 1); + } } + free(OutData.rmtbulk_val); free(inbuffer); return errorcode; } diff --git a/src/uss/uss_vol.c b/src/uss/uss_vol.c index 85a14fc24..8efadaf2b 100644 --- a/src/uss/uss_vol.c +++ b/src/uss/uss_vol.c @@ -19,7 +19,7 @@ #include RCSID - ("$Header: /cvs/openafs/src/uss/uss_vol.c,v 1.10.2.2 2007/10/30 15:24:09 shadow Exp $"); + ("$Header: /cvs/openafs/src/uss/uss_vol.c,v 1.10.2.3 2009/03/27 15:47:43 shadow Exp $"); #include "uss_vol.h" /*Interface to this module */ #include "uss_common.h" /*Common definitions */ @@ -180,7 +180,7 @@ InitThisModule(a_noAuthFlag, a_confDir, a_cellName) /* * We got a ticket, go for an authenticated connection. */ - if (ttoken.kvno >= 0 && ttoken.kvno <= 255) + if (ttoken.kvno >= 0 && ttoken.kvno <= 256) scIndex = 2; /*Kerberos */ else { fprintf(stderr, "%s: Funny kvno (%d) in ticket, proceeding\n", -- 2.39.5