diff -Naur openafs_1.4.14.orig/acinclude.m4 openafs_1.4.14/acinclude.m4 --- openafs_1.4.14.orig/acinclude.m4 2010-12-17 16:58:42.000000000 +0100 +++ openafs_1.4.14/acinclude.m4 2011-03-29 08:33:49.040187976 +0200 @@ -749,6 +749,7 @@ LINUX_FS_STRUCT_SUPER_HAS_ALLOC_INODE LINUX_FS_STRUCT_SUPER_HAS_EVICT_INODE LINUX_FS_STRUCT_SUPER_BLOCK_HAS_S_BDI + AC_CHECK_LINUX_STRUCT([super_block], [s_d_op], [fs.h]) LINUX_STRUCT_BDI_HAS_NAME LINUX_FS_STRUCT_ADDRESS_SPACE_HAS_PAGE_LOCK LINUX_FS_STRUCT_ADDRESS_SPACE_HAS_GFP_MASK @@ -768,6 +769,7 @@ LINUX_WRITE_INODE_RETURN_TYPE LINUX_IOP_I_CREATE_TAKES_NAMEIDATA LINUX_IOP_I_LOOKUP_TAKES_NAMEIDATA + LINUX_IOP_I_PERMISSION_TAKES_FLAGS LINUX_IOP_I_PERMISSION_TAKES_NAMEIDATA LINUX_IOP_I_PUT_LINK_TAKES_COOKIE LINUX_DOP_D_REVALIDATE_TAKES_NAMEIDATA @@ -815,6 +817,8 @@ LINUX_GENERIC_FILE_AIO_READ LINUX_INIT_WORK_HAS_DATA LINUX_REGISTER_SYSCTL_TABLE_NOFLAG + LINUX_HAVE_DCACHE_LOCK + LINUX_D_COUNT_IS_INT LINUX_SYSCTL_TABLE_CHECKING LINUX_STRUCT_CTL_TABLE_HAS_CTL_NAME LINUX_HAVE_IGET diff -Naur openafs_1.4.14.orig/configure.in openafs_1.4.14/configure.in --- openafs_1.4.14.orig/configure.in 2010-12-17 16:58:42.000000000 +0100 +++ openafs_1.4.14/configure.in 2011-03-29 08:33:49.039188017 +0200 @@ -108,12 +108,6 @@ src/mpp/Makefile \ src/null/Makefile \ src/package/Makefile \ -src/packaging/MacOS/OpenAFS-debug.Description.plist \ -src/packaging/MacOS/OpenAFS-debug.Info.plist \ -src/packaging/MacOS/OpenAFS.Description.plist \ -src/packaging/MacOS/OpenAFS.Info.plist \ -src/packaging/MacOS/OpenAFS.info \ -src/packaging/MacOS/buildpkg.sh \ src/packaging/RedHat/openafs.spec \ src/pam/Makefile \ src/pinstall/Makefile \ diff -Naur openafs_1.4.14.orig/src/afs/afs_daemons.c openafs_1.4.14/src/afs/afs_daemons.c --- openafs_1.4.14.orig/src/afs/afs_daemons.c 2010-12-17 16:58:42.000000000 +0100 +++ openafs_1.4.14/src/afs/afs_daemons.c 2011-03-29 08:33:49.174182467 +0200 @@ -376,7 +376,11 @@ dp = d_find_alias(AFSTOV(afs_globalVp)); #if defined(AFS_LINUX24_ENV) +#if defined(HAVE_DCACHE_LOCK) spin_lock(&dcache_lock); +#else + spin_lock(&AFSTOV(vcp)->i_lock); +#endif #if defined(AFS_LINUX26_ENV) spin_lock(&dp->d_lock); #endif @@ -388,7 +392,11 @@ #if defined(AFS_LINUX26_ENV) spin_unlock(&dp->d_lock); #endif +#if defined(HAVE_DCACHE_LOCK) spin_unlock(&dcache_lock); +#else + spin_unlock(&AFSTOV(vcp)->i_lock); +#endif #endif dput(dp); diff -Naur openafs_1.4.14.orig/src/afs/afs.h openafs_1.4.14/src/afs/afs.h --- openafs_1.4.14.orig/src/afs/afs.h 2010-12-17 16:58:42.000000000 +0100 +++ openafs_1.4.14/src/afs/afs.h 2011-03-29 08:33:49.171182590 +0200 @@ -75,7 +75,7 @@ #define PIGGYSIZE 1350 /* max piggyback size */ #define MAXVOLS 128 /* max vols we can store */ #define MAXSYSNAME 128 /* max sysname (i.e. @sys) size */ -#define MAXNUMSYSNAMES 16 /* max that current constants allow */ +#define MAXNUMSYSNAMES 32 /* max that current constants allow */ #define NOTOKTIMEOUT (2*3600) /* time after which to timeout conns sans tokens */ #define NOPAG 0xffffffff #define AFS_NCBRS 300 /* max # of call back return entries */ diff -Naur openafs_1.4.14.orig/src/afs/afs_vcache.c openafs_1.4.14/src/afs/afs_vcache.c --- openafs_1.4.14.orig/src/afs/afs_vcache.c 2010-12-17 16:58:42.000000000 +0100 +++ openafs_1.4.14/src/afs/afs_vcache.c 2011-03-29 08:33:49.170182631 +0200 @@ -673,12 +673,15 @@ #if defined(AFS_LINUX22_ENV) if (tvc != afs_globalVp && VREFCOUNT(tvc) > 1 && tvc->opens == 0) { struct dentry *dentry; + struct inode *inode = AFSTOV(tvc); struct list_head *cur, *head; AFS_GUNLOCK(); + +#if defined(HAVE_DCACHE_LOCK) #if defined(AFS_LINUX24_ENV) spin_lock(&dcache_lock); #endif - head = &(AFSTOV(tvc))->i_dentry; + head = &inode->i_dentry; restart: cur = head; @@ -687,7 +690,6 @@ if (d_unhashed(dentry)) continue; - dget_locked(dentry); #if defined(AFS_LINUX24_ENV) @@ -707,6 +709,35 @@ #if defined(AFS_LINUX24_ENV) spin_unlock(&dcache_lock); #endif +#else /* HAVE_DCACHE_LOCK */ + spin_lock(&inode->i_lock); + head = &inode->i_dentry; + +restart: + cur = head; + while ((cur = cur->next) != head) { + dentry = list_entry(cur, struct dentry, d_alias); + + spin_lock(&dentry->d_lock); + if (d_unhashed(dentry)) { + spin_unlock(&dentry->d_lock); + continue; + } + spin_unlock(&dentry->d_lock); + dget(dentry); + + spin_unlock(&inode->i_lock); + if (d_invalidate(dentry) == -EBUSY) { + dput(dentry); + /* perhaps lock and try to continue? (use cur as head?) */ + goto inuse; + } + dput(dentry); + spin_lock(&inode->i_lock); + goto restart; + } + spin_unlock(&inode->i_lock); +#endif /* HAVE_DCACHE_LOCK */ inuse: AFS_GLOCK(); } diff -Naur openafs_1.4.14.orig/src/afs/LINUX/osi_compat.h openafs_1.4.14/src/afs/LINUX/osi_compat.h --- openafs_1.4.14.orig/src/afs/LINUX/osi_compat.h 2010-12-17 16:58:42.000000000 +0100 +++ openafs_1.4.14/src/afs/LINUX/osi_compat.h 2011-03-29 08:33:49.171182590 +0200 @@ -135,7 +135,6 @@ #else #define KALLOC_TYPE GFP_KERNEL #endif - #endif static inline int diff -Naur openafs_1.4.14.orig/src/afs/LINUX/osi_groups.c openafs_1.4.14/src/afs/LINUX/osi_groups.c --- openafs_1.4.14.orig/src/afs/LINUX/osi_groups.c 2010-12-17 16:58:42.000000000 +0100 +++ openafs_1.4.14/src/afs/LINUX/osi_groups.c 2011-03-29 08:33:49.171182590 +0200 @@ -230,7 +230,7 @@ { struct key *old; char desc[20]; - unsigned long not_in_quota; + unsigned long flags; int code = -EINVAL; if (!__key_type_keyring) @@ -239,24 +239,31 @@ if (!keyring) { /* create an empty session keyring */ - not_in_quota = KEY_ALLOC_IN_QUOTA; sprintf(desc, "_ses.%u", current->tgid); + /* if we're root, don't count the keyring against our quota. This + * avoids starvation issues when dealing with PAM modules that always + * setpag() as root */ + if (current_uid() == 0) + flags = KEY_ALLOC_NOT_IN_QUOTA; + else + flags = KEY_ALLOC_IN_QUOTA; + #if defined(KEY_ALLOC_NEEDS_STRUCT_TASK) keyring = key_alloc(__key_type_keyring, desc, current_uid(), current_gid(), current, (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL, - not_in_quota); + flags); #elif defined(KEY_ALLOC_NEEDS_CRED) keyring = key_alloc(__key_type_keyring, desc, current_uid(), current_gid(), current_cred(), (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL, - not_in_quota); + flags); #else keyring = key_alloc(__key_type_keyring, desc, current_uid(), current_gid(), (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL, - not_in_quota); + flags); #endif if (IS_ERR(keyring)) { code = PTR_ERR(keyring); @@ -338,9 +345,9 @@ #ifdef LINUX_KEYRING_SUPPORT if (code == 0) { - (void) install_session_keyring(NULL); + code = install_session_keyring(NULL); - if (current_session_keyring()) { + if (code == 0 && current_session_keyring()) { struct key *key; key_perm_t perm; @@ -348,17 +355,22 @@ perm |= KEY_USR_VIEW | KEY_USR_SEARCH; #if defined(KEY_ALLOC_NEEDS_STRUCT_TASK) - key = key_alloc(&key_type_afs_pag, "_pag", 0, 0, current, perm, 1); + key = key_alloc(&key_type_afs_pag, "_pag", 0, 0, current, + perm, KEY_ALLOC_NOT_IN_QUOTA); #elif defined(KEY_ALLOC_NEEDS_CRED) - key = key_alloc(&key_type_afs_pag, "_pag", 0, 0, current_cred(), perm, 1); + key = key_alloc(&key_type_afs_pag, "_pag", 0, 0, current_cred(), + perm, KEY_ALLOC_NOT_IN_QUOTA); #else - key = key_alloc(&key_type_afs_pag, "_pag", 0, 0, perm, 1); + key = key_alloc(&key_type_afs_pag, "_pag", 0, 0, perm, + KEY_ALLOC_NOT_IN_QUOTA); #endif if (!IS_ERR(key)) { key_instantiate_and_link(key, (void *) newpag, sizeof(afs_uint32), current_session_keyring(), NULL); key_put(key); + } else { + code = PTR_ERR(key); } } } diff -Naur openafs_1.4.14.orig/src/afs/LINUX/osi_vfsops.c openafs_1.4.14/src/afs/LINUX/osi_vfsops.c --- openafs_1.4.14.orig/src/afs/LINUX/osi_vfsops.c 2010-12-17 16:58:42.000000000 +0100 +++ openafs_1.4.14/src/afs/LINUX/osi_vfsops.c 2011-03-29 08:33:49.172182549 +0200 @@ -140,6 +140,11 @@ sb->s_blocksize_bits = 10; sb->s_magic = AFS_VFSMAGIC; sb->s_op = &afs_sops; /* Super block (vfs) ops */ + +#if defined(STRUCT_SUPER_BLOCK_HAS_S_D_OP) + sb->s_d_op = &afs_dentry_operations; +#endif + /* used for inodes backing_dev_info field, also */ afs_backing_dev_info = osi_Alloc(sizeof(struct backing_dev_info)); #if defined(HAVE_BDI_INIT) @@ -227,7 +232,9 @@ #else afsp->s_root = d_alloc_root(ip, NULL); #endif +#if !defined(STRUCT_SUPER_BLOCK_HAS_S_D_OP) afsp->s_root->d_op = &afs_dentry_operations; +#endif } else code = ENOENT; } diff -Naur openafs_1.4.14.orig/src/afs/LINUX/osi_vnodeops.c openafs_1.4.14/src/afs/LINUX/osi_vnodeops.c --- openafs_1.4.14.orig/src/afs/LINUX/osi_vnodeops.c 2010-12-17 16:58:42.000000000 +0100 +++ openafs_1.4.14/src/afs/LINUX/osi_vnodeops.c 2011-03-29 08:33:49.172182549 +0200 @@ -865,10 +865,16 @@ int valid; struct afs_fakestat_state fakestate; +#ifdef LOOKUP_RCU + /* We don't support RCU path walking */ + if (nd->flags & LOOKUP_RCU) + return -ECHILD; +#endif #ifdef AFS_LINUX24_ENV lock_kernel(); #endif AFS_GLOCK(); + afs_InitFakeStat(&fakestate); if (dp->d_inode) { @@ -1067,7 +1073,9 @@ afs_getattr(vcp, &vattr, credp); afs_fill_inode(ip, &vattr); insert_inode_hash(ip); +#if !defined(STRUCT_SUPER_BLOCK_HAS_S_D_OP) dp->d_op = &afs_dentry_operations; +#endif dp->d_time = hgetlo(VTOAFS(dip)->m.DataVersion); d_instantiate(dp, ip); } @@ -1123,7 +1131,9 @@ ) insert_inode_hash(ip); } +#if !defined(STRUCT_SUPER_BLOCK_HAS_S_D_OP) dp->d_op = &afs_dentry_operations; +#endif dp->d_time = hgetlo(VTOAFS(dip)->m.DataVersion); AFS_GUNLOCK(); @@ -1315,7 +1325,9 @@ afs_getattr(tvcp, &vattr, credp); afs_fill_inode(ip, &vattr); +#if !defined(STRUCT_SUPER_BLOCK_HAS_S_D_OP) dp->d_op = &afs_dentry_operations; +#endif dp->d_time = hgetlo(VTOAFS(dip)->m.DataVersion); d_instantiate(dp, ip); } @@ -1384,9 +1396,18 @@ #endif #if defined(AFS_LINUX24_ENV) +#if defined(D_COUNT_INT) + spin_lock(&olddp->d_lock); + if (olddp->d_count > 1) { + spin_unlock(&olddp->d_lock); + shrink_dcache_parent(olddp); + } else + spin_unlock(&olddp->d_lock); +#else if (atomic_read(&olddp->d_count) > 1) shrink_dcache_parent(olddp); #endif +#endif AFS_GLOCK(); code = afs_rename(VTOAFS(oldip), oldname, VTOAFS(newip), newname, credp); @@ -1786,16 +1807,25 @@ * Check access rights - returns error if can't check or permission denied. */ static int -#ifdef IOP_PERMISSION_TAKES_NAMEIDATA +#if defined(IOP_PERMISSION_TAKES_FLAGS) +afs_linux_permission(struct inode *ip, int mode, unsigned int flags) +#elif defined(IOP_PERMISSION_TAKES_NAMEIDATA) afs_linux_permission(struct inode *ip, int mode, struct nameidata *nd) #else afs_linux_permission(struct inode *ip, int mode) #endif { int code; - cred_t *credp = crref(); + cred_t *credp; int tmp = 0; +#if defined(IOP_PERMISSION_TAKES_FLAGS) + /* We don't support RCU path walking */ + if (flags & IPERM_FLAG_RCU) + return -ECHILD; +#endif + + credp = crref(); AFS_GLOCK(); if (mode & MAY_EXEC) tmp |= VEXEC; diff -Naur openafs_1.4.14.orig/src/afs/Makefile.in openafs_1.4.14/src/afs/Makefile.in --- openafs_1.4.14.orig/src/afs/Makefile.in 2010-12-17 16:58:42.000000000 +0100 +++ openafs_1.4.14/src/afs/Makefile.in 2011-03-29 08:33:49.180182219 +0200 @@ -13,7 +13,7 @@ all: depinstall depinstall: ${TOP_INCDIR}/afs/afs.h ${TOP_INCDIR}/afs/osi_inode.h ${TOP_INCDIR}/afs/afs_stats.h \ - ${TOP_INCDIR}/afs/exporter.h ${TOP_INCDIR}/afs/nfsclient.h afszcm.cat AFS_component_version_number.c ${TOP_INCDIR}/afs/unified_afs.h ${TOP_INCDIR}/afs/sysctl.h + ${TOP_INCDIR}/afs/exporter.h ${TOP_INCDIR}/afs/nfsclient.h afszcm.cat AFS_component_version_number.c ${TOP_INCDIR}/afs/unified_afs.h afs_trace.h afs_trace.msf: afs_trace.et ${COMPILE_ET} -v 2 -p ${srcdir} afs_trace.et @@ -39,7 +39,7 @@ gencat afszcm.cat afs_trace.msf ;; \ esac -install: ${DESTDIR}${includedir}/afs/afs.h ${DESTDIR}${includedir}/afs/osi_inode.h ${DESTDIR}${includedir}/afs/afs_stats.h ${DESTDIR}${includedir}/afs/exporter.h ${DESTDIR}${includedir}/afs/nfsclient.h ${DESTDIR}${includedir}/afs/unified_afs.h ${DESTDIR}${includedir}/afs/sysctl.h +install: ${DESTDIR}${includedir}/afs/afs.h ${DESTDIR}${includedir}/afs/osi_inode.h ${DESTDIR}${includedir}/afs/afs_stats.h ${DESTDIR}${includedir}/afs/exporter.h ${DESTDIR}${includedir}/afs/nfsclient.h ${DESTDIR}${includedir}/afs/unified_afs.h case ${SYS_NAME} in \ *linux* ) \ ${INSTALL} ${MKAFS_OSTYPE}/osi_vfs.h ${DESTDIR}${includedir}/afs || true ;;\ @@ -123,7 +123,7 @@ ${INSTALL} $? $@ -dest: ${DEST}/include/afs/afs.h ${DEST}/include/afs/osi_inode.h ${DEST}/include/afs/afs_stats.h ${DEST}/include/afs/exporter.h ${DEST}/include/afs/nfsclient.h ${DEST}/include/afs/unified_afs.h ${DEST}/include/afs/sysctl.h +dest: ${DEST}/include/afs/afs.h ${DEST}/include/afs/osi_inode.h ${DEST}/include/afs/afs_stats.h ${DEST}/include/afs/exporter.h ${DEST}/include/afs/nfsclient.h ${DEST}/include/afs/unified_afs.h case ${SYS_NAME} in \ i386_fbsd* ) \ echo skipping afszcm.cat install for ${SYS_NAME} ;; \ diff -Naur openafs_1.4.14.orig/src/afs/sysincludes.h openafs_1.4.14/src/afs/sysincludes.h --- openafs_1.4.14.orig/src/afs/sysincludes.h 2010-12-17 16:58:42.000000000 +0100 +++ openafs_1.4.14/src/afs/sysincludes.h 2011-03-29 08:33:49.174182467 +0200 @@ -79,7 +79,10 @@ #include #endif #ifndef KEY_ALLOC_IN_QUOTA -#define KEY_ALLOC_IN_QUOTA 1 +/* Before these flags were added in Linux commit v2.6.18-rc1~816, + * key_alloc just took a boolean not_in_quota */ +#define KEY_ALLOC_IN_QUOTA 0 +#define KEY_ALLOC_NOT_IN_QUOTA 1 #endif #endif #endif diff -Naur openafs_1.4.14.orig/src/afs/VNOPS/afs_vnop_flock.c openafs_1.4.14/src/afs/VNOPS/afs_vnop_flock.c --- openafs_1.4.14.orig/src/afs/VNOPS/afs_vnop_flock.c 2010-12-17 16:58:42.000000000 +0100 +++ openafs_1.4.14/src/afs/VNOPS/afs_vnop_flock.c 2011-03-29 08:33:49.177182342 +0200 @@ -539,24 +539,8 @@ #else ) { #endif - /* this next check is safer when left out, but more applications work - * with it in. However, they fail in race conditions. The question is - * what to do for people who don't have source to their application; - * this way at least, they can get work done */ -#ifdef AFS_LINUX24_ENV - if (af->l_len == OFFSET_MAX) - af->l_len = 0; /* since some systems indicate it as EOF */ -#else - if (af->l_len == 0x7fffffff) - af->l_len = 0; /* since some systems indicate it as EOF */ -#ifdef AFS_LINUX_64BIT_KERNEL - if (af->l_len == LONG_MAX) - af->l_len = 0; /* since some systems indicate it as EOF */ -#endif -#endif - /* Java VMs ask for l_len=(long)-1 regardless of OS/CPU; bottom 32 bits - * sometimes get masked off by OS */ - if ((sizeof(af->l_len) == 8) && (af->l_len == 0x7ffffffffffffffe)) + /* Java VMs ask for l_len=(long)-1 regardless of OS/CPU */ + if ((sizeof(af->l_len) == 8) && (af->l_len == 0x7fffffffffffffffLL)) af->l_len = 0; /* next line makes byte range locks always succeed, * even when they should block */ diff -Naur openafs_1.4.14.orig/src/bozo/bosoprocs.c openafs_1.4.14/src/bozo/bosoprocs.c --- openafs_1.4.14.orig/src/bozo/bosoprocs.c 2010-12-17 16:58:42.000000000 +0100 +++ openafs_1.4.14/src/bozo/bosoprocs.c 2011-03-29 08:33:49.123184563 +0200 @@ -1315,7 +1315,7 @@ struct bozo_bosEntryStats bozo_bosEntryStats[] = { {NULL, 1, 1, 0755, 02}, /* AFSDIR_SERVER_AFS_DIRPATH */ - {NULL, 1, 1, 0755, 02}, /* AFSDIR_SERVER_ETC_DIRPATH */ + {NULL, 1, 1, 0700, 02}, /* AFSDIR_SERVER_ETC_DIRPATH */ {NULL, 1, 1, 0755, 02}, /* AFSDIR_SERVER_BIN_DIRPATH */ {NULL, 1, 1, 0755, 02}, /* AFSDIR_SERVER_LOGS_DIRPATH */ {NULL, 1, 0, 0700, 07}, /* AFSDIR_SERVER_BACKUP_DIRPATH */ diff -Naur openafs_1.4.14.orig/src/cf/linux-test1.m4 openafs_1.4.14/src/cf/linux-test1.m4 --- openafs_1.4.14.orig/src/cf/linux-test1.m4 2010-12-17 16:58:42.000000000 +0100 +++ openafs_1.4.14/src/cf/linux-test1.m4 2011-03-29 08:33:49.219180616 +0200 @@ -84,3 +84,28 @@ ac_linux_kbuild_requires_extra_cflags=yes) CPPFLAGS="$save_CPPFLAGS" AC_MSG_RESULT($ac_linux_kbuild_requires_extra_cflags)]) + +dnl AC_CHECK_LINUX_BUILD([msg], [var], [includes], [code], [define], [CFLAGS]) +AC_DEFUN([AC_CHECK_LINUX_BUILD], + [AS_VAR_PUSHDEF([ac_linux_build], [$2])dnl + AC_CACHE_CHECK([$1], [ac_linux_build], + [save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $7" + AC_TRY_KBUILD([$3], [$4], + AS_VAR_SET([ac_linux_build], [yes]), + AS_VAR_SET([ac_linux_build], [no])) + CPPFLAGS="$save_CPPFLAGS" + ]) + AS_IF([test AS_VAR_GET([ac_linux_build]) = yes], + [AC_DEFINE([$5],1,[$6])]) + ]) + +dnl AC_CHECK_LINUX_STRUCT([structure], [element], [includes]) +AC_DEFUN([AC_CHECK_LINUX_STRUCT], + [AC_CHECK_LINUX_BUILD([for $2 in struct $1], + [ac_cv_linux_struct_$1_has_$2], + [#include ], + [struct $1 _test; printk("%x\n", &_test.$2); ], + AS_TR_CPP(STRUCT_$1_HAS_$2), + [Define if kernel struct $1 has the $2 element]) + ]) diff -Naur openafs_1.4.14.orig/src/cf/linux-test4.m4 openafs_1.4.14/src/cf/linux-test4.m4 --- openafs_1.4.14.orig/src/cf/linux-test4.m4 2010-12-17 16:58:42.000000000 +0100 +++ openafs_1.4.14/src/cf/linux-test4.m4 2011-03-29 08:33:49.220180575 +0200 @@ -675,18 +675,30 @@ AC_DEFUN([LINUX_IOP_I_PERMISSION_TAKES_NAMEIDATA], [ - AC_MSG_CHECKING([whether inode_operations.permission takes a nameidata]) - AC_CACHE_VAL([ac_cv_linux_func_i_permission_takes_nameidata], [ - AC_TRY_KBUILD( + AC_CHECK_LINUX_BUILD([whether inode_operations.permission takes a nameidata], + [ac_cv_linux_func_i_permission_takes_nameidata], [#include #include ], [struct inode _inode; -struct dentry _dentry; struct nameidata _nameidata; (void)_inode.i_op->permission(&_inode, 0, &_nameidata);], - ac_cv_linux_func_i_permission_takes_nameidata=yes, - ac_cv_linux_func_i_permission_takes_nameidata=no)]) - AC_MSG_RESULT($ac_cv_linux_func_i_permission_takes_nameidata)]) + [IOP_PERMISSION_TAKES_NAMEIDATA], + [define if your iops.permission takes a nameidata argument], + [-Werror]) +]) + + +AC_DEFUN([LINUX_IOP_I_PERMISSION_TAKES_FLAGS], [ + AC_CHECK_LINUX_BUILD([whether inode_operations.permission takes flags], + [ac_cv_linux_func_i_permission_takes_flags], + [#include ], + [struct inode _inode; + unsigned int flags = 0; + (void)_inode.i_op->permission(&_inode, 0, flags);], + [IOP_PERMISSION_TAKES_FLAGS], + [define if your iops.permission takes a flags argument], + [-Werror]) +]) AC_DEFUN([LINUX_IOP_I_PUT_LINK_TAKES_COOKIE], [ @@ -1304,3 +1316,26 @@ if test "x$ac_cv_linux_inode_setattr" = "xyes"; then AC_DEFINE([HAVE_LINUX_INODE_SETATTR], 1, [define if your kernel has inode_setattr()]) fi]) + +AC_DEFUN([LINUX_HAVE_DCACHE_LOCK], [ + AC_CHECK_LINUX_BUILD([for dcache_lock], + [ac_cv_linux_have_dcache_lock], + [#include ], + [printk("%p", &dcache_lock);], + [HAVE_DCACHE_LOCK], + [define if dcache_lock exists], + []) +]) + + +AC_DEFUN([LINUX_D_COUNT_IS_INT], [ + AC_CHECK_LINUX_BUILD([if dentry->d_count is an int], + [ac_cv_linux_d_count_int], + [#include ], + [struct dentry _d; + dget(&_d); + _d.d_count = 1;], + [D_COUNT_INT], + [define if dentry->d_count is an int], + [-Werror]) +]) diff -Naur openafs_1.4.14.orig/src/cf/osconf.m4 openafs_1.4.14/src/cf/osconf.m4 --- openafs_1.4.14.orig/src/cf/osconf.m4 2010-12-17 16:58:42.000000000 +0100 +++ openafs_1.4.14/src/cf/osconf.m4 2011-03-29 08:33:49.220180575 +0200 @@ -4,9 +4,8 @@ dnl defaults, override in case below as needed XCFLAGS='${DBG} ${OPTMZ}' SHLIB_SUFFIX="so" -CC="cc" -CCOBJ="cc" -MT_CC="cc" +CCOBJ=$CC +MT_CC=$CC XLIBS="${LIB_AFSDB} ${XBSA_XLIBS}" dnl debugging and optimization flag defaults @@ -350,9 +349,8 @@ ;; i386_umlinux22) - CC="gcc -pipe" - CCOBJ="gcc -pipe" - MT_CC="gcc -pipe" + CCOBJ="${CC} -pipe" + MT_CC="${CC} -pipe" KERN_OPTMZ=-O2 LEX="flex -l" MT_CFLAGS='-DAFS_PTHREAD_ENV -pthread -D_REENTRANT ${XCFLAGS}' @@ -367,9 +365,8 @@ ;; i386_linux*) - CC="gcc -pipe" - CCOBJ="gcc -pipe" - MT_CC="gcc -pipe" + CCOBJ="${CC} -pipe" + MT_CC="${CC} -pipe" KERN_OPTMZ=-O2 LEX="flex -l" MT_CFLAGS='-DAFS_PTHREAD_ENV -pthread -D_REENTRANT ${XCFLAGS}' @@ -388,9 +385,8 @@ ;; i386_umlinux24) - CC="gcc -pipe" - CCOBJ="gcc -pipe" - MT_CC="gcc -pipe" + CCOBJ="${CC} -pipe" + MT_CC="${CC} -pipe" KERN_OPTMZ=-O2 LEX="flex -l" MT_CFLAGS='-DAFS_PTHREAD_ENV -pthread -D_REENTRANT ${XCFLAGS}' @@ -409,9 +405,8 @@ ;; i386_umlinux26) - CC="gcc -pipe" - CCOBJ="gcc -pipe" - MT_CC="gcc -pipe" + CCOBJ="${CC} -pipe" + MT_CC="${CC} -pipe" KERN_OPTMZ=-O2 LEX="flex -l" MT_CFLAGS='-DAFS_PTHREAD_ENV -pthread -D_REENTRANT ${XCFLAGS}' @@ -665,8 +660,7 @@ ;; s390_linux22) - CC="gcc" - CCOBJ="gcc" + CCOBJ="$CC" LD="ld" KERN_OPTMZ=-O2 LEX="flex -l" @@ -683,8 +677,7 @@ ;; s390_linux24|s390_linux26) - CC="gcc" - CCOBJ="gcc" + CCOBJ="$CC" LD="ld" KERN_OPTMZ=-O2 LEX="flex -l" @@ -701,8 +694,7 @@ ;; s390x_linux24|s390x_linux26) - CC="gcc" - CCOBJ="gcc -fPIC" + CCOBJ="$CC -fPIC" LD="ld" KERN_OPTMZ=-O2 LEX="flex -l" @@ -780,7 +772,7 @@ SHLIB_LINKER="${CC} -shared" ;; - sparc64_linux*) + sparc*_linux*) KERN_OPTMZ=-O2 LEX="flex -l" MT_CFLAGS='-DAFS_PTHREAD_ENV -pthread -D_REENTRANT ${XCFLAGS}' @@ -795,20 +787,6 @@ YACC="bison -y" SHLIB_LINKER="${MT_CC} -shared" ;; - - sparc_linux22) - KERN_OPTMZ=-O2 - LEX="flex -l" - MT_CFLAGS='-DAFS_PTHREAD_ENV -pthread -D_REENTRANT ${XCFLAGS}' - MT_LIBS="-lpthread" - PAM_CFLAGS="-O2 -Dlinux -DLINUX_PAM -fPIC" - SHLIB_CFLAGS="-fPIC" - SHLIB_LDFLAGS="-shared -Xlinker -x" - TXLIBS="-lncurses" - XCFLAGS="-O2 -D_LARGEFILE64_SOURCE" - YACC="bison -y" - SHLIB_LINKER="${MT_CC} -shared" - ;; sun4_413) CCXPG2="/usr/xpg2bin/cc" diff -Naur openafs_1.4.14.orig/src/ptserver/db_verify.c openafs_1.4.14/src/ptserver/db_verify.c --- openafs_1.4.14.orig/src/ptserver/db_verify.c 2010-12-17 16:58:42.000000000 +0100 +++ openafs_1.4.14/src/ptserver/db_verify.c 2011-03-29 08:33:49.217180698 +0200 @@ -1179,9 +1179,6 @@ if ((id < 0) && (flags & PRGRP)) { int count = 0; afs_int32 na; -#if defined(SUPERGROUPS) - afs_int32 ng; -#endif int i; for (i = 0; i < PRSIZE; i++) { afs_int32 uid = ntohl(e.entries[i]); @@ -1200,43 +1197,6 @@ id); #endif } -#if defined(SUPERGROUPS) -#define g (*((struct prentryg *)&e)) - ng = ntohl(g.nextsg); - for (i = 0; i < SGSIZE; i++) { - afs_int32 uid = ntohl(g.supergroup[i]); - if (uid == 0) - break; - if (uid == PRBADID) - continue; - fprintf(rc, "au %d %d\n", uid, id); - count++; - } - while (ng) { - struct prentry c; - code = pr_Read(ng, (char *)&c, sizeof(c)); - if (code) - return code; - - if ((id == ntohl(c.id)) && (c.flags & htonl(PRCONT))) { - for (i = 0; i < COSIZE; i++) { - afs_int32 uid = ntohl(c.entries[i]); - if (uid == 0) - break; - if (uid == PRBADID) - continue; - fprintf(rc, "au %d %d\n", uid, id); - count++; - } - } else { - fprintf(stderr, "Skipping continuation block at %d\n", - ng); - break; - } - ng = ntohl(c.next); - } -#undef g -#endif /* SUPERGROUPS */ na = ntohl(e.next); while (na) { struct prentry c; diff -Naur openafs_1.4.14.orig/src/rxdebug/rxdebug.c openafs_1.4.14/src/rxdebug/rxdebug.c --- openafs_1.4.14.orig/src/rxdebug/rxdebug.c 2010-12-17 16:58:42.000000000 +0100 +++ openafs_1.4.14/src/rxdebug/rxdebug.c 2011-03-29 08:33:49.209181027 +0200 @@ -449,7 +449,7 @@ printf("\n Received %d bytes in %d packets\n", tconn.secStats.bytesReceived, tconn.secStats.packetsReceived); - printf(" Sent %d bytes in %d packets\n", + printf(" Sent %u bytes in %u packets\n", tconn.secStats.bytesSent, tconn.secStats.packetsSent); } else diff -Naur openafs_1.4.14.orig/src/tviced/Makefile.in openafs_1.4.14/src/tviced/Makefile.in --- openafs_1.4.14.orig/src/tviced/Makefile.in 2010-12-17 16:58:42.000000000 +0100 +++ openafs_1.4.14/src/tviced/Makefile.in 2011-03-29 08:33:49.183182096 +0200 @@ -38,8 +38,7 @@ DIROBJS=buffer.o dir.o salvage.o VOLOBJS= vnode.o volume.o vutil.o partition.o fssync.o purge.o \ - clone.o devname.o common.o ihandle.o listinodes.o namei_ops.o \ - fstab.o + clone.o devname.o common.o ihandle.o listinodes.o namei_ops.o FSINTOBJS= afsaux.o afscbint.cs.o afsint.ss.o afsint.xdr.o diff -Naur openafs_1.4.14.orig/src/ubik/recovery.c openafs_1.4.14/src/ubik/recovery.c --- openafs_1.4.14.orig/src/ubik/recovery.c 2010-12-17 16:58:42.000000000 +0100 +++ openafs_1.4.14/src/ubik/recovery.c 2011-03-29 08:33:49.208181069 +0200 @@ -207,6 +207,7 @@ sizeof(afs_int32)); if (code != sizeof(afs_int32)) break; + opcode = ntohl(opcode); if (opcode == LOGNEW) { /* handle begin trans */ tpos += sizeof(afs_int32); @@ -231,7 +232,7 @@ if (code != 3 * sizeof(afs_int32)) break; /* otherwise, skip over the data bytes, too */ - tpos += buffer[2] + 3 * sizeof(afs_int32); + tpos += ntohl(buffer[2]) + 3 * sizeof(afs_int32); } else { ubik_dprint("corrupt log opcode (%d) at position %d\n", opcode, tpos); @@ -250,6 +251,7 @@ sizeof(afs_int32)); if (code != sizeof(afs_int32)) break; + opcode = ntohl(opcode); if (opcode == LOGNEW) { /* handle begin trans */ tpos += sizeof(afs_int32); diff -Naur openafs_1.4.14.orig/src/util/Makefile.in openafs_1.4.14/src/util/Makefile.in --- openafs_1.4.14.orig/src/util/Makefile.in 2010-12-17 16:58:42.000000000 +0100 +++ openafs_1.4.14/src/util/Makefile.in 2011-03-29 08:33:49.222180493 +0200 @@ -12,7 +12,7 @@ objects = assert.o base64.o casestrcpy.o ktime.o volparse.o hostparse.o \ hputil.o kreltime.o isathing.o get_krbrlm.o uuid.o serverLog.o \ - dirpath.o fileutil.o netutils.o flipbase64.o fstab.o \ + dirpath.o fileutil.o netutils.o flipbase64.o \ afs_atomlist.o afs_lhash.o snprintf.o strlcat.o strlcpy.o \ daemon.o rxkstats.o ${REGEX_OBJ} @@ -392,4 +392,4 @@ assert.c base64.c casestrcpy.c ktime.c volparse.c hostparse.c \ hputil.c kreltime.c isathing.c get_krbrlm.c uuid.c serverLog.c \ dirpath.c fileutil.c netutils.c flipbase64.c \ - afs_atomlist.c afs_lhash.c snprintf.c fstab.c + afs_atomlist.c afs_lhash.c snprintf.c diff -Naur openafs_1.4.14.orig/src/venus/fstrace.c openafs_1.4.14/src/venus/fstrace.c --- openafs_1.4.14.orig/src/venus/fstrace.c 2010-12-17 16:58:42.000000000 +0100 +++ openafs_1.4.14/src/venus/fstrace.c 2011-03-29 08:33:49.228180245 +0200 @@ -1464,7 +1464,7 @@ */ #ifndef RPC_NLS_FORMAT -#define RPC_NLS_FORMAT "%s.cat" +#define RPC_NLS_FORMAT "/usr/share/openafs/%s.cat" #endif dce1_error_inq_text(status_to_convert, error_text, status) @@ -1481,7 +1481,8 @@ char component_name[4]; char *facility_name; char filename_prefix[7]; - char nls_filename[11]; + /* strlen("/usr/share/openafs/") + 6 + strlen(".cat") + 1 */ + char nls_filename[19 + 6 + 4 + 1]; char alt_filename[80]; char *message; #if defined(AFS_64BITPOINTER_ENV) diff -Naur openafs_1.4.14.orig/src/viced/callback.c openafs_1.4.14/src/viced/callback.c --- openafs_1.4.14.orig/src/viced/callback.c 2010-12-17 16:58:42.000000000 +0100 +++ openafs_1.4.14/src/viced/callback.c 2011-03-29 08:33:49.240179753 +0200 @@ -292,8 +292,6 @@ struct VCBParams *parms); static int MultiBreakVolumeLaterCallBack(struct host *host, int isheld, struct VCBParams *parms); -static int lih_r(register struct host *host, register int held, - register struct host *hostp); static int GetSomeSpace_r(struct host *hostp, int locked); static int ClearHostCallbacks_r(struct host *hp, int locked); @@ -1577,68 +1575,88 @@ return (ntimedout > 0); } -static struct host *lih_host; -static int lih_host_held; +/** + * parameters to pass to lih*_r from h_Enumerate_r when trying to find a host + * from which to clear callbacks. + */ +struct lih_params { + /** + * Points to the least interesting host found; try to clear callbacks on + * this host after h_Enumerate_r(lih*_r)'ing. + */ + struct host *lih; -static int -lih_r(register struct host *host, register int held, - register struct host *hostp) -{ - if (host->cblist - && ((hostp && host != hostp) || (!held && !h_OtherHolds_r(host))) - && (!lih_host || host->ActiveCall < lih_host->ActiveCall)) { - if (lih_host != NULL && lih_host_held) { - h_Release_r(lih_host); - } - lih_host = host; - lih_host_held = !held; - held = 1; - } - return held; -} + /** + * The last host we got from lih*_r, but we couldn't clear its callbacks + * for some reason. Choose the next-best host after this one (with the + * current lih*_r, this means to only select hosts that have an ActiveCall + * newer than lastlih). + */ + struct host *lastlih; + + /** + * 1 if lih was held, 0 if it was not and should be released. + */ + int lih_held; +}; /* This version does not allow 'host' to be selected unless its ActiveCall - * is newer than 'hostp' which is the host with the oldest ActiveCall from - * the last pass (if it is provided). We filter out any hosts that are - * are held by other threads. + * is newer than 'params->lastlih' which is the host with the oldest + * ActiveCall from the last pass (if it is provided). We filter out any hosts + * that are are held by other threads. + * + * There is a small problem here, but it may not be easily fixable. Say we + * select some host A, and give it back to GetSomeSpace_r. GSS_r for some + * reason cannot clear the callbacks on A, and so calls us again with + * lastlih = A. Suppose there is another host B that has the same ActiveCall + * time as A. We will now skip over host B, since + * 'hostB->ActiveCall > hostA->ActiveCall' is not true. This could result in + * us prematurely going to the GSS_r 2nd or 3rd pass, and making us a little + * inefficient. This should be pretty rare, though, except perhaps in cases + * with very small numbers of hosts. + * + * Also filter out any hosts with HOSTDELETED set. h_Enumerate_r should in + * theory not give these to us anyway, but be paranoid. */ static int -lih0_r(register struct host *host, register int held, - register struct host *hostp) +lih0_r(struct host *host, int held, void *rock) { + struct lih_params *params = (struct lih_params *)rock; + if (host->cblist - && (hostp && host != hostp) + && (!(host->hostFlags & HOSTDELETED)) && (!held && !h_OtherHolds_r(host)) - && (!lih_host || host->ActiveCall < lih_host->ActiveCall) - && (!hostp || host->ActiveCall > hostp->ActiveCall)) { - if (lih_host != NULL && lih_host_held) { - h_Release_r(lih_host); + && (!params->lih || host->ActiveCall < params->lih->ActiveCall) + && (!params->lastlih || host->ActiveCall > params->lastlih->ActiveCall)) { + + if (params->lih && !params->lih_held) { + h_Release_r(params->lih); /* release prev host */ } - lih_host = host; - lih_host_held = !held; + + params->lih = host; + params->lih_held = held; held = 1; } return held; } -/* This version does not allow 'host' to be selected unless its ActiveCall - * is newer than 'hostp' which is the host with the oldest ActiveCall from - * the last pass (if it is provided). In this second varient, we do not - * prevent held hosts from being selected. - */ +/* same as lih0_r, except we do not prevent held hosts from being selected. */ static int -lih1_r(register struct host *host, register int held, - register struct host *hostp) +lih1_r(struct host *host, int held, void *rock) { + struct lih_params *params = (struct lih_params *)rock; + if (host->cblist - && (hostp && host != hostp) - && (!lih_host || host->ActiveCall < lih_host->ActiveCall) - && (!hostp || host->ActiveCall > hostp->ActiveCall)) { - if (lih_host != NULL && lih_host_held) { - h_Release_r(lih_host); + && (!(host->hostFlags & HOSTDELETED)) + && (!params->lih || host->ActiveCall < params->lih->ActiveCall) + && (!params->lastlih || host->ActiveCall > params->lastlih->ActiveCall)) { + + if (params->lih && !params->lih_held) { + h_Release_r(params->lih); /* release prev host */ } - lih_host = host; - lih_host_held = !held; + + params->lih = host; + params->lih_held = held; held = 1; } return held; @@ -1659,8 +1677,10 @@ static int GetSomeSpace_r(struct host *hostp, int locked) { - register struct host *hp, *hp1, *hp2; + struct host *hp; + struct lih_params params; int i = 0; + int lastlih_held = 1; cbstuff.GotSomeSpaces++; ViceLog(5, @@ -1671,38 +1691,43 @@ } i = 0; - hp1 = NULL; - hp2 = hostList; + params.lastlih = NULL; + do { - lih_host = 0; - h_Enumerate_r(i == 0 ? lih0_r : lih1_r, hp2, (char *)hp1); - hp = lih_host; + params.lih = NULL; + + h_Enumerate_r(i == 0 ? lih0_r : lih1_r, hostList, ¶ms); + + hp = params.lih; + if (params.lastlih && !lastlih_held) { + h_Release_r(params.lastlih); + lastlih_held = 1; + } + params.lastlih = NULL; + if (hp) { - /* set in lih_r! private copy before giving up H_LOCK */ - int lih_host_held2=lih_host_held; + /* note that 'hp' was held by lih*_r; we will need to release it */ cbstuff.GSS4++; if ((hp != hostp) && !ClearHostCallbacks_r(hp, 0 /* not locked or held */ )) { - if (lih_host_held2) + if (!params.lih_held) { h_Release_r(hp); + } return 0; } - if (lih_host_held2) { - h_Release_r(hp); - hp = NULL; - } - hp1 = hp; - hp2 = hostList; + + params.lastlih = hp; + lastlih_held = params.lih_held; + /* params.lastlih will be released on the next iteration, after + * h_Enumerate_r */ + } else { /* * Next time try getting callbacks from any host even if - * it's deleted (that's actually great since we can freely - * remove its callbacks) or it's held since the only other - * option is starvation for the file server (i.e. until the - * callback timeout arrives). + * it's held, since the only other option is starvation for + * the file server (i.e. until the callback timeout arrives). */ i++; - hp1 = NULL; - hp2 = hostList; + params.lastlih = NULL; cbstuff.GSS1++; ViceLog(5, ("GSS: Try harder for longest inactive host cnt= %d\n", @@ -2159,10 +2184,10 @@ if (host->callback_rxcon) rx_DestroyConnection(host->callback_rxcon); host->callback_rxcon = conns[multi_i]; - hashDelete_r(host->host, host->port, host); + h_DeleteHostFromAddrHashTable_r(host->host, host->port, host); host->host = interfaces[multi_i].addr; host->port = interfaces[multi_i].port; - hashInsert_r(host->host, host->port, host); + h_AddHostToAddrHashTable_r(host->host, host->port, host); connSuccess = conns[multi_i]; rx_SetConnDeadTime(host->callback_rxcon, 50); rx_SetConnHardDeadTime(host->callback_rxcon, AFS_HARDDEADTIME); @@ -2252,11 +2277,11 @@ H_LOCK; if (host->callback_rxcon) rx_DestroyConnection(host->callback_rxcon); - hashDelete_r(host->host, host->port, host); + h_DeleteHostFromAddrHashTable_r(host->host, host->port, host); host->callback_rxcon = conns[multi_i]; host->host = interfaces[multi_i].addr; host->port = interfaces[multi_i].port; - hashInsert_r(host->host, host->port, host); + h_AddHostToAddrHashTable_r(host->host, host->port, host); connSuccess = conns[multi_i]; rx_SetConnDeadTime(host->callback_rxcon, 50); rx_SetConnHardDeadTime(host->callback_rxcon, AFS_HARDDEADTIME); diff -Naur openafs_1.4.14.orig/src/viced/host.c openafs_1.4.14/src/viced/host.c --- openafs_1.4.14.orig/src/viced/host.c 2010-12-17 16:58:42.000000000 +0100 +++ openafs_1.4.14/src/viced/host.c 2011-03-29 08:33:49.239179794 +0200 @@ -10,7 +10,6 @@ #include #include - #include #include #include @@ -503,15 +502,17 @@ if (!h_OtherHolds_r(host)) { /* must avoid masking this until after h_OtherHolds_r runs * but it should be run before h_TossStuff_r */ - (host)->holds[h_holdSlot()] &= ~h_holdbit(); + h_Decrement_r(host); if ((host->hostFlags & HOSTDELETED) || (host->hostFlags & CLIENTDELETED)) { h_TossStuff_r(host); } - } else - (host)->holds[h_holdSlot()] &= ~h_holdbit(); - } else - (host)->holds[h_holdSlot()] &= ~h_holdbit(); + } else { + h_Decrement_r(host); + } + } else { + h_Decrement_r(host); + } return 0; } @@ -766,7 +767,7 @@ host->host = rxr_HostOf(r_con); host->port = rxr_PortOf(r_con); - hashInsert_r(host->host, host->port, host); + h_AddHostToAddrHashTable_r(host->host, host->port, host); if (consolePort == 0) { /* find the portal number for console */ #if defined(AFS_OSF_ENV) @@ -887,12 +888,10 @@ assert(host); if (!(host->hostFlags & HOSTDELETED) && host->interface && afs_uuid_equal(&host->interface->uuid, uuidp)) { - break; + return host; } - host = NULL; } - return host; - + return NULL; } /*h_Lookup */ @@ -913,23 +912,39 @@ { register struct client **cp, *client; int i; + int code; - /* if somebody still has this host held */ - for (i = 0; (i < h_maxSlots) && (!(host)->holds[i]); i++); - if (i != h_maxSlots) - return; + /* make sure host doesn't go away over h_NBLock_r */ + h_Hold_r(host); + + code = h_NBLock_r(host); + + /* don't use h_Release_r, since that may call h_TossStuff_r again */ + h_Decrement_r(host); /* if somebody still has this host locked */ - if (h_NBLock_r(host) != 0) { + if (code != 0) { char hoststr[16]; ViceLog(0, - ("Warning: h_TossStuff_r failed; Host %s:%d was locked.\n", - afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port))); + ("Warning: h_TossStuff_r failed; Host 0x%lx (%s:%d) was locked.\n", + (unsigned long) host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port))); return; } else { h_Unlock_r(host); } + /* if somebody still has this host held */ + /* we must check this _after_ h_NBLock_r, since h_NBLock_r can drop and + * reacquire H_LOCK */ + for (i = 0; (i < h_maxSlots) && (!(host)->holds[i]); i++); + if (i != h_maxSlots) { + char hoststr[16]; + ViceLog(0, + ("Warning: h_TossStuff_r failed; Host 0x%lx (%s:%d) was held.\n", + (unsigned long) host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port))); + return; + } + /* ASSUMPTION: rxi_FreeConnection() does not yield */ for (cp = &host->FirstClient; (client = *cp);) { if ((host->hostFlags & HOSTDELETED) || client->deleted) { @@ -938,8 +953,8 @@ if (code < 0) { char hoststr[16]; ViceLog(0, - ("Warning: h_TossStuff_r failed: Host %s:%d client %x was locked.\n", - afs_inet_ntoa_r(host->host, hoststr), + ("Warning: h_TossStuff_r failed: Host 0x%lx (%s:%d) client %x was locked.\n", + (unsigned long) host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port), client)); return; } @@ -947,8 +962,8 @@ if (client->refCount) { char hoststr[16]; ViceLog(0, - ("Warning: h_TossStuff_r failed: Host %s:%d client %x refcount %d.\n", - afs_inet_ntoa_r(host->host, hoststr), + ("Warning: h_TossStuff_r failed: Host 0x%lx (%s:%d) client %x refcount %d.\n", + (unsigned long) host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port), client, client->refCount)); /* This is the same thing we do if the host is locked */ ReleaseWriteLock(&client->lock); @@ -970,9 +985,7 @@ host->hostFlags &= ~CLIENTDELETED; if (host->hostFlags & HOSTDELETED) { - register struct h_AddrHashChain **ahp, *ath; register struct rx_connection *rxconn; - afsUUID *uuidp; struct AddrPort hostAddrPort; int i; @@ -991,44 +1004,22 @@ /* if alternate addresses do not exist */ if (!(host->interface)) { - for (ahp = &hostAddrHashTable[h_HashIndex(host->host)]; (ath = *ahp); - ahp = &ath->next) { - assert(ath->hostPtr); - if (ath->hostPtr == host) { - *ahp = ath->next; - free(ath); - break; - } - } + h_DeleteHostFromAddrHashTable_r(host->host, host->port, host); } else { - register struct h_UuidHashChain **uhp, *uth; - /* delete the hash entry for the UUID */ - uuidp = &host->interface->uuid; - for (uhp = &hostUuidHashTable[h_UuidHashIndex(uuidp)]; (uth = *uhp); - uhp = &uth->next) { - assert(uth->hostPtr); - if (uth->hostPtr == host) { - *uhp = uth->next; - free(uth); - break; - } - } - /* delete the hash entry for each alternate addresses */ + h_DeleteHostFromUuidHashTable_r(host); + h_DeleteHostFromAddrHashTable_r(host->host, host->port, host); + /* delete the hash entry for each valid alternate addresses */ for (i = 0; i < host->interface->numberOfInterfaces; i++) { hostAddrPort = host->interface->interface[i]; - - if (!hostAddrPort.valid) - continue; - - for (ahp = &hostAddrHashTable[h_HashIndex(hostAddrPort.addr)]; (ath = *ahp); - ahp = &ath->next) { - assert(ath->hostPtr); - if (ath->hostPtr == host) { - *ahp = ath->next; - free(ath); - break; - } - } + /* + * if the interface addr/port is the primary, we already + * removed it. If the addr/port is not valid, its not + * in the hash table. + */ + if (hostAddrPort.valid && + (host->host != hostAddrPort.addr || + host->port != hostAddrPort.port)) + h_DeleteHostFromAddrHashTable_r(hostAddrPort.addr, hostAddrPort.port, host); } free(host->interface); host->interface = NULL; @@ -1184,65 +1175,124 @@ /* inserts a new HashChain structure corresponding to this UUID */ void -hashInsertUuid_r(struct afsUUID *uuid, struct host *host) +h_AddHostToUuidHashTable_r(struct afsUUID *uuid, struct host *host) { int index; struct h_UuidHashChain *chain; + char uuid1[128], uuid2[128]; + char hoststr[16]; /* hash into proper bucket */ index = h_UuidHashIndex(uuid); /* don't add the same entry multiple times */ for (chain = hostUuidHashTable[index]; chain; chain = chain->next) { + if (!chain->hostPtr) + continue; + if (chain->hostPtr->interface && - afs_uuid_equal(&chain->hostPtr->interface->uuid, uuid)) + afs_uuid_equal(&chain->hostPtr->interface->uuid, uuid)) { + if (LogLevel >= 125) { + afsUUID_to_string(&chain->hostPtr->interface->uuid, uuid1, 127); + afsUUID_to_string(uuid, uuid2, 127); + ViceLog(125, ("h_AddHostToUuidHashTable_r: host 0x%lx (uuid %s) exists as %s:%d (uuid %s)\n", + (unsigned long) host, uuid1, + afs_inet_ntoa_r(chain->hostPtr->host, hoststr), + ntohs(chain->hostPtr->port), uuid2)); + } return; + } } /* insert into beginning of list for this bucket */ chain = (struct h_UuidHashChain *)malloc(sizeof(struct h_UuidHashChain)); if (!chain) { - ViceLog(0, ("Failed malloc in hashInsertUuid_r\n")); + ViceLog(0, ("Failed malloc in h_AddHostToUuidHashTable_r\n")); assert(0); } - assert(chain); chain->hostPtr = host; chain->next = hostUuidHashTable[index]; hostUuidHashTable[index] = chain; + if (LogLevel < 125) + return; + afsUUID_to_string(uuid, uuid2, 127); + ViceLog(125, + ("h_AddHostToUuidHashTable_r: host 0x%lx (%s:%d) added as uuid %s\n", + (unsigned long) host, afs_inet_ntoa_r(chain->hostPtr->host, hoststr), + ntohs(chain->hostPtr->port), uuid)); } +/* deletes a HashChain structure corresponding to this host */ +int +h_DeleteHostFromUuidHashTable_r(struct host *host) +{ + int index; + register struct h_UuidHashChain **uhp, *uth; + char uuid1[128]; + char hoststr[16]; + + if (!host->interface) + return 0; + + /* hash into proper bucket */ + index = h_UuidHashIndex(&host->interface->uuid); + + if (LogLevel >= 125) + afsUUID_to_string(&host->interface->uuid, uuid1, 127); + for (uhp = &hostUuidHashTable[index]; (uth = *uhp); uhp = &uth->next) { + assert(uth->hostPtr); + if (uth->hostPtr == host) { + ViceLog(125, + ("h_DeleteHostFromUuidHashTable_r: host 0x%lx (uuid %s %s:%d)\n", + (unsigned long) host, uuid1, afs_inet_ntoa_r(host->host, hoststr), + ntohs(host->port))); + *uhp = uth->next; + free(uth); + return 1; + } + } + ViceLog(125, + ("h_DeleteHostFromUuidHashTable_r: host 0x%lx (uuid %s %s:%d) not found\n", + (unsigned long) host, uuid1, afs_inet_ntoa_r(host->host, hoststr), + ntohs(host->port))); + return 0; +} /* inserts a new HashChain structure corresponding to this address */ void -hashInsert_r(afs_uint32 addr, afs_uint16 port, struct host *host) +h_AddHostToAddrHashTable_r(afs_uint32 addr, afs_uint16 port, struct host *host) { int index; struct h_AddrHashChain *chain; int found = 0; - char hoststr[16]; + char hoststr[16], hoststr2[16]; /* hash into proper bucket */ index = h_HashIndex(addr); /* don't add the same entry multiple times */ for (chain = hostAddrHashTable[index]; chain; chain = chain->next) { - if (chain->addr == addr && chain->port == port) { - if (chain->hostPtr == host) - found = 1; - else if (!(host->hostFlags & HOSTDELETED)) - ViceLog(125, ("Addr %s:%d assigned to %x and %x.\n", - afs_inet_ntoa_r(addr, hoststr), ntohs(port), - host, chain)); + if (chain->hostPtr == host) { + if (chain->addr != addr || chain->port != port) { + ViceLog(0, + ("h_AddHostToAddrHashTable_r: host 0x%lx exists as %s:%d when adding %s:%d\n", + (unsigned long) host, afs_inet_ntoa_r(chain->addr, hoststr), + ntohs(chain->port), afs_inet_ntoa_r(addr, hoststr2), + ntohs(port))); + } else + ViceLog(125, + ("h_AddHostToAddrHashTable_r: host 0x%lx (%s:%d) already hashed\n", + (unsigned long) host, afs_inet_ntoa_r(chain->addr, hoststr), + ntohs(chain->port))); + + return; } } - if (found) - return; - /* insert into beginning of list for this bucket */ chain = (struct h_AddrHashChain *)malloc(sizeof(struct h_AddrHashChain)); if (!chain) { - ViceLog(0, ("Failed malloc in hashInsert_r\n")); + ViceLog(0, ("Failed malloc in h_AddHostToAddrHashTable_r\n")); assert(0); } chain->hostPtr = host; @@ -1250,13 +1300,14 @@ chain->addr = addr; chain->port = port; hostAddrHashTable[index] = chain; + ViceLog(125, ("h_AddHostToAddrHashTable_r: host 0x%lx added as %s:%d\n", + (unsigned long) host, afs_inet_ntoa_r(addr, hoststr), ntohs(port))); } /* - * This is called with host locked and held. At this point, the - * hostAddrHashTable should not have entries for the alternate - * interfaces. This function has to insert these entries in the - * hostAddrHashTable. + * This is called with host locked and held. + * It is called to either validate or add an additional interface + * address/port on the specified host. * * All addresses are in network byte order. */ @@ -1279,22 +1330,25 @@ for (i = 0; i < number; i++) { if (host->interface->interface[i].addr == addr && host->interface->interface[i].port == port) { - ViceLog(125, ("addInterfaceAddr : host %x (%s:%d) addr %s:%d : found, valid: %d\n", - host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port), - afs_inet_ntoa_r(addr, hoststr2), ntohs(port), - host->interface->interface[i].valid)); + ViceLog(125, + ("addInterfaceAddr : found host 0x%lx (%s:%d) adding %s:%d%s\n", + (unsigned long) host, afs_inet_ntoa_r(host->host, hoststr), + ntohs(host->port), afs_inet_ntoa_r(addr, hoststr2), + ntohs(port), host->interface->interface[i].valid ? "" : + ", validating")); if (host->interface->interface[i].valid == 0) { - hashInsert_r(addr, port, host); host->interface->interface[i].valid = 1; + h_AddHostToAddrHashTable_r(addr, port, host); } return 0; } } - ViceLog(125, ("addInterfaceAddr : host %x (%s:%d) addr %s:%d : not found, adding\n", - host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port), - afs_inet_ntoa_r(addr, hoststr2), ntohs(port))); + ViceLog(125, ("addInterfaceAddr : host 0x%lx (%s:%d) adding %s:%d\n", + (unsigned long) host, afs_inet_ntoa_r(host->host, hoststr), + ntohs(host->port), afs_inet_ntoa_r(addr, hoststr2), + ntohs(port))); interface = (struct Interface *) malloc(sizeof(struct Interface) + (sizeof(struct AddrPort) * number)); @@ -1306,9 +1360,12 @@ interface->uuid = host->interface->uuid; for (i = 0; i < number; i++) interface->interface[i] = host->interface->interface[i]; + + /* Add the new valid interface */ interface->interface[number].addr = addr; interface->interface[number].port = port; interface->interface[number].valid = 1; + h_AddHostToAddrHashTable_r(addr, port, host); free(host->interface); host->interface = interface; @@ -1317,10 +1374,7 @@ /* - * This is called with host locked and held. At this point, the - * hostAddrHashTable should not be having entries for the alternate - * interfaces. This function has to insert these entries in the - * hostAddrHashTable. + * This is called with host locked and held. * * All addresses are in network byte order. */ @@ -1329,16 +1383,16 @@ { int i; int number; - int found; struct Interface *interface; char hoststr[16], hoststr2[16]; assert(host); assert(host->interface); - ViceLog(125, ("removeInterfaceAddr : host %x (%s:%d) addr %s:%d\n", - host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port), - afs_inet_ntoa_r(addr, hoststr2), ntohs(port))); + ViceLog(125, ("removeInterfaceAddr : host 0x%lx (%s:%d) addr %s:%d\n", + (unsigned long) host, afs_inet_ntoa_r(host->host, hoststr), + ntohs(host->port), afs_inet_ntoa_r(addr, hoststr2), + ntohs(port))); /* * Make sure this address is on the list of known addresses @@ -1346,26 +1400,62 @@ */ interface = host->interface; number = host->interface->numberOfInterfaces; - for (i = 0, found = 0; i < number && !found; i++) { - if (interface->interface[i].addr == addr && - interface->interface[i].port == port) { - found = 1; - interface->interface[i].valid = 0; - } - } - if (found) { - number--; - for (; i < number; i++) { - interface->interface[i] = interface->interface[i+1]; + for (i = 0; i < number; i++) { + if (interface->interface[i].addr == addr && + interface->interface[i].port == port) { + if (interface->interface[i].valid) + h_DeleteHostFromAddrHashTable_r(addr, port, host); + number--; + for (; i < number; i++) { + interface->interface[i] = interface->interface[i+1]; + } + interface->numberOfInterfaces = number; + return 0; } - interface->numberOfInterfaces = number; - } + } + /* not found */ + return 0; +} + +/* + * This is called with host locked and held. + * + * All addresses are in network byte order. + */ +int +invalidateInterfaceAddr_r(struct host *host, afs_uint32 addr, afs_uint16 port) +{ + int i; + int number; + struct Interface *interface; + char hoststr[16], hoststr2[16]; + + assert(host); + assert(host->interface); + + ViceLog(125, ("invalidateInterfaceAddr : host 0x%lx (%s:%d) addr %s:%d\n", + (unsigned long) host, afs_inet_ntoa_r(host->host, hoststr), + ntohs(host->port), afs_inet_ntoa_r(addr, hoststr2), + ntohs(port))); /* - * Remove the hash table entry for this address + * Make sure this address is on the list of known addresses + * for this host. */ - hashDelete_r(addr, port, host); - + interface = host->interface; + number = host->interface->numberOfInterfaces; + for (i = 0; i < number; i++) { + if (interface->interface[i].addr == addr && + interface->interface[i].port == port) { + if (interface->interface[i].valid) { + h_DeleteHostFromAddrHashTable_r(addr, port, host); + interface->interface[i].valid = 0; + } + return 0; + } + } + + /* not found */ return 0; } @@ -1383,62 +1473,53 @@ { int i; char hoststr[16], hoststr2[16]; + struct rx_connection *rxconn; - if (!host->interface) { + if (!host->interface || host->interface->numberOfInterfaces == 1) { if (host->host == addr && host->port == port) { ViceLog(25, - ("Removing only address for host %x (%s:%d), deleting host.\n", - host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port))); + ("Removing only address for host 0x%lx (%s:%d), deleting host.\n", + (unsigned long) host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port))); host->hostFlags |= HOSTDELETED; + /* + * Do not remove the primary addr/port from the hash table. + * It will be ignored due to the HOSTDELETED flag and will + * be removed when h_TossStuff_r() cleans up the HOSTDELETED + * host. Removing it here will only result in a search for + * the host/addr/port in the hash chain which will fail. + */ + } else { + ViceLog(0, + ("Removing address that does not belong to host 0x%lx (%s:%d).\n", + (unsigned long) host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port))); } } else { - removeInterfaceAddr_r(host, host->host, host->port); - if (host->interface->numberOfInterfaces == 0) { - ViceLog(25, - ("Removed only address for host %x (%s:%d), no alternate interfaces, deleting host.\n", - host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port))); - host->hostFlags |= HOSTDELETED; - } else { + if (host->host == addr && host->port == port) { + removeInterfaceAddr_r(host, addr, port); for (i=0; i < host->interface->numberOfInterfaces; i++) { if (host->interface->interface[i].valid) { ViceLog(25, - ("Removed address for host %x (%s:%d), new primary interface %s:%d.\n", - host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port), + ("Removed address for host 0x%lx (%s:%d), new primary interface %s:%d.\n", + (unsigned long) host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port), afs_inet_ntoa_r(host->interface->interface[i].addr, hoststr2), ntohs(host->interface->interface[i].port))); host->host = host->interface->interface[i].addr; host->port = host->interface->interface[i].port; - hashInsert_r(host->host, host->port, host); + h_AddHostToAddrHashTable_r(host->host, host->port, host); break; } } if (i == host->interface->numberOfInterfaces) { ViceLog(25, - ("Removed only address for host %x (%s:%d), no valid alternate interfaces, deleting host.\n", - host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port))); + ("Removed only address for host 0x%lx (%s:%d), no valid alternate interfaces, deleting host.\n", + (unsigned long) host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port))); host->hostFlags |= HOSTDELETED; + /* addr/port was removed from the hash table */ + host->host = 0; + host->port = 0; } else { - struct rx_connection *rxconn; - - rxconn = host->callback_rxcon; - host->callback_rxcon = NULL; - - if (rxconn) { - struct client *client; - /* - * If rx_DestroyConnection calls h_FreeConnection we will - * deadlock on the host_glock_mutex. Work around the problem - * by unhooking the client from the connection before - * destroying the connection. - */ - client = rx_GetSpecific(rxconn, rxcon_client_key); - rx_SetSpecific(rxconn, rxcon_client_key, (void *)0); - rx_DestroyConnection(rxconn); - rxconn = NULL; - } - if (!sc) sc = rxnull_NewClientSecurityObject(); host->callback_rxcon = @@ -1446,6 +1527,9 @@ rx_SetConnDeadTime(host->callback_rxcon, 50); rx_SetConnHardDeadTime(host->callback_rxcon, AFS_HARDDEADTIME); } + } else { + /* not the primary addr/port, just invalidate it */ + invalidateInterfaceAddr_r(host, addr, port); } } @@ -1527,8 +1611,8 @@ * waited for the lock. */ h_Unlock_r(host); ViceLog(125, - ("Host %s:%d starting h_Lookup again\n", - afs_inet_ntoa_r(host->host, hoststr), + ("Host 0x%lx (%s:%d) starting h_Lookup again\n", + (unsigned long) host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port))); if (!*heldp) h_Release_r(host); @@ -1594,8 +1678,8 @@ * that we maintain some extra callback state information */ if (host->interface) { ViceLog(0, - ("Host %x (%s:%d) used to support WhoAreYou, deleting.\n", - host, + ("Host 0x%lx (%s:%d) used to support WhoAreYou, deleting.\n", + (unsigned long) host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port))); host->hostFlags |= HOSTDELETED; @@ -1646,8 +1730,8 @@ removeAddress_r(host, haddr, hport); } else { ViceLog(25, - ("Uuid doesn't match host %x (%s:%d).\n", - host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port))); + ("Uuid doesn't match host 0x%lx (%s:%d).\n", + (unsigned long) host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port))); removeAddress_r(host, host->host, host->port); } @@ -1684,8 +1768,8 @@ * callback connection, and destroy the old one. */ struct rx_connection *rxconn; - ViceLog(0,("CB: ProbeUuid for host %x (%s:%d) failed %d\n", - host, + ViceLog(0,("CB: ProbeUuid for host 0x%lx (%s:%d) failed %d\n", + (unsigned long) host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port),code2)); /* @@ -1736,8 +1820,8 @@ goto gethost_out; } else { ViceLog(0, - ("CB: WhoAreYou failed for host %x (%s:%d), error %d\n", - host, afs_inet_ntoa_r(host->host, hoststr), + ("CB: WhoAreYou failed for host 0x%lx (%s:%d), error %d\n", + (unsigned long) host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port), code)); host->hostFlags |= VENUSDOWN; } @@ -1754,14 +1838,14 @@ if (!(host->hostFlags & ALTADDR)) { /* another thread is doing the initialisation */ ViceLog(125, - ("Host %s:%d waiting for host-init to complete\n", - afs_inet_ntoa_r(host->host, hoststr), + ("Host 0x%lx (%s:%d) waiting for host-init to complete\n", + (unsigned long) host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port))); h_Lock_r(host); h_Unlock_r(host); ViceLog(125, - ("Host %s:%d starting h_Lookup again\n", - afs_inet_ntoa_r(host->host, hoststr), + ("Host 0x%lx (%s:%d) starting h_Lookup again\n", + (unsigned long) host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port))); if (!*heldp) h_Release_r(host); @@ -1782,8 +1866,8 @@ if (host->interface) afsUUID_to_string(&host->interface->uuid, uuid2, 127); ViceLog(0, - ("CB: new identity for host %s:%d, deleting(%x %x %s %s)\n", - afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port), + ("CB: new identity for host 0x%lx (%s:%d), deleting(%x %x %s %s)\n", + (unsigned long) host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port), identP->valid, host->interface, identP->valid ? uuid1 : "", host->interface ? uuid2 : "")); @@ -1829,8 +1913,8 @@ if (!pident) rx_SetSpecific(tcon, rxcon_ident_key, identP); ViceLog(25, - ("Host %s:%d does not support WhoAreYou.\n", - afs_inet_ntoa_r(host->host, hoststr), + ("Host 0x%lx (%s:%d) does not support WhoAreYou.\n", + (unsigned long) host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port))); code = 0; } else if (code == 0) { @@ -1850,8 +1934,8 @@ if (!pident) rx_SetSpecific(tcon, rxcon_ident_key, identP); ViceLog(25, - ("WhoAreYou success on %s:%d\n", - afs_inet_ntoa_r(host->host, hoststr), + ("WhoAreYou success on 0x%lx (%s:%d)\n", + (unsigned long) host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port))); } if (code == 0 && !identP->valid) { @@ -1906,8 +1990,8 @@ * MultiProbeAlternateAddress_r() will remove the * alternate interfaces that do not have the same * Uuid. */ - ViceLog(0,("CB: ProbeUuid for %s:%d failed %d\n", - afs_inet_ntoa_r(oldHost->host, hoststr), + ViceLog(0,("CB: ProbeUuid for 0x%lx (%s:%d) failed %d\n", + (unsigned long) oldHost, afs_inet_ntoa_r(oldHost->host, hoststr), ntohs(oldHost->port),code2)); MultiProbeAlternateAddress_r(oldHost); probefail = 1; @@ -1927,8 +2011,8 @@ struct rx_connection *rxconn; ViceLog(25, - ("CB: Host %x (%s:%d) has new addr %s:%d\n", - oldHost, + ("CB: Host 0x%lx (%s:%d) has new addr %s:%d\n", + (unsigned long) oldHost, afs_inet_ntoa_r(oldHost->host, hoststr2), ntohs(oldHost->port), afs_inet_ntoa_r(haddr, hoststr), @@ -1947,23 +2031,24 @@ */ removeInterfaceAddr_r(oldHost, oldHost->host, oldHost->port); } else { - int i, found; + int i; struct Interface *interface = oldHost->interface; int number = oldHost->interface->numberOfInterfaces; - for (i = 0, found = 0; i < number; i++) { + for (i = 0; i < number; i++) { if (interface->interface[i].addr == haddr && interface->interface[i].port != hport) { - found = 1; + /* + * We have just been contacted by a client + * that has been seen from behind a NAT + * and at least one other address. + */ + removeInterfaceAddr_r(oldHost, haddr, + interface->interface[i].port); break; } } - if (found) { - /* We have just been contacted by a client that has been - * seen from behind a NAT and at least one other address. - */ - removeInterfaceAddr_r(oldHost, haddr, interface->interface[i].port); - } } + h_AddHostToAddrHashTable_r(haddr, hport, oldHost); oldHost->host = haddr; oldHost->port = hport; rxconn = oldHost->callback_rxcon; @@ -1982,7 +2067,7 @@ /* the new host is held and locked */ } else { /* This really is a new host */ - hashInsertUuid_r(&identP->uuid, host); + h_AddHostToUuidHashTable_r(&identP->uuid, host); cb_conn = host->callback_rxcon; rx_GetConnection(cb_conn); H_UNLOCK; @@ -1994,8 +2079,8 @@ H_LOCK; if (code == 0) { ViceLog(25, - ("InitCallBackState3 success on %s:%d\n", - afs_inet_ntoa_r(host->host, hoststr), + ("InitCallBackState3 success on 0x%lx (%s:%d)\n", + (unsigned long) host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port))); assert(interfValid == 1); initInterfaceAddr_r(host, &interf); @@ -2004,13 +2089,13 @@ } if (code) { ViceLog(0, - ("CB: RCallBackConnectBack failed for host %x (%s:%d)\n", - host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port))); + ("CB: RCallBackConnectBack failed for host 0x%lx (%s:%d)\n", + (unsigned long) host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port))); host->hostFlags |= VENUSDOWN; } else { ViceLog(125, - ("CB: RCallBackConnectBack succeeded for host %x (%s:%d)\n", - host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port))); + ("CB: RCallBackConnectBack succeeded for host 0x%lx (%s:%d)\n", + (unsigned long) host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port))); host->hostFlags |= RESETDONE; } } @@ -2358,8 +2443,8 @@ if (code) { char hoststr[16]; ViceLog(0, - ("pr_GetCPS failed(%d) for user %d, host %s:%d\n", - code, viceid, afs_inet_ntoa_r(client->host->host, + ("pr_GetCPS failed(%d) for user %d, host 0x%lx (%s:%d)\n", + code, viceid, (unsigned long) client->host, afs_inet_ntoa_r(client->host->host, hoststr), ntohs(client->host->port))); @@ -3012,7 +3097,7 @@ * back state, because break delayed callbacks (called when a * message is received from the workstation) will always send a * break all call backs to the workstation if there is no - *callback. + * callback. */ } } else { @@ -3105,7 +3190,7 @@ * back state, because break delayed callbacks (called when a * message is received from the workstation) will always send a * break all call backs to the workstation if there is no - *callback. + * callback. */ } } else { @@ -3178,9 +3263,8 @@ /* * This is called with host locked and held. At this point, the - * hostAddrHashTable should not have any entries for the alternate - * interfaces. This function has to insert these entries in the - * hostAddrHashTable. + * hostAddrHashTable has an entry for the primary addr/port inserted + * by h_Alloc_r(). No other interfaces should be considered valid. * * The addresses in the interfaceAddr list are in host byte order. */ @@ -3298,7 +3382,8 @@ * are coming from fully connected hosts (no NAT/PATs) */ interface->interface[i].port = port7001; - interface->interface[i].valid = 1; /* valid until a conflict is found */ + interface->interface[i].valid = + (interf->addr_in[i] == myAddr && port7001 == myPort) ? 1 : 0; } interface->uuid = interf->uuid; @@ -3306,13 +3391,15 @@ assert(!host->interface); host->interface = interface; - afsUUID_to_string(&interface->uuid, uuidstr, 127); - - ViceLog(125, ("--- uuid %s\n", uuidstr)); - for (i = 0; i < host->interface->numberOfInterfaces; i++) { - ViceLog(125, ("--- alt address %s:%d\n", - afs_inet_ntoa_r(host->interface->interface[i].addr, hoststr), - ntohs(host->interface->interface[i].port))); + if (LogLevel >= 125) { + afsUUID_to_string(&interface->uuid, uuidstr, 127); + + ViceLog(125, ("--- uuid %s\n", uuidstr)); + for (i = 0; i < host->interface->numberOfInterfaces; i++) { + ViceLog(125, ("--- alt address %s:%d\n", + afs_inet_ntoa_r(host->interface->interface[i].addr, hoststr), + ntohs(host->interface->interface[i].port))); + } } return 0; @@ -3321,24 +3408,32 @@ /* deleted a HashChain structure for this address and host */ /* returns 1 on success */ int -hashDelete_r(afs_uint32 addr, afs_uint16 port, struct host * - host) +h_DeleteHostFromAddrHashTable_r(afs_uint32 addr, afs_uint16 port, + struct host *host) { - int flag = 0; + char hoststr[16]; register struct h_AddrHashChain **hp, *th; - for (hp = &hostAddrHashTable[h_HashIndex(addr)]; (th = *hp);) { + if (addr == 0 && port == 0) + return 1; + + for (hp = &hostAddrHashTable[h_HashIndex(addr)]; (th = *hp); + hp = &th->next) { assert(th->hostPtr); if (th->hostPtr == host && th->addr == addr && th->port == port) { + ViceLog(125, ("h_DeleteHostFromAddrHashTable_r: host 0x%lx (%s:%d)\n", + (unsigned long) host, afs_inet_ntoa_r(host->host, hoststr), + ntohs(host->port))); *hp = th->next; free(th); - flag = 1; - break; - } else { - hp = &th->next; - } + return 1; + } } - return flag; + ViceLog(125, + ("h_DeleteHostFromAddrHashTable_r: host 0x%lx (%s:%d) not found\n", + (unsigned long) host, afs_inet_ntoa_r(host->host, hoststr), + ntohs(host->port))); + return 0; } @@ -3355,9 +3450,9 @@ if (host->interface) { /* check alternate addresses */ number = host->interface->numberOfInterfaces; - if (number == 0) + if (number == 0) { ViceLog(level, ("no-addresses ")); - else { + } else { for (i = 0; i < number; i++) ViceLog(level, ("%s:%d ", afs_inet_ntoa_r(host->interface->interface[i].addr, hoststr), ntohs(host->interface->interface[i].port))); diff -Naur openafs_1.4.14.orig/src/viced/host.h openafs_1.4.14/src/viced/host.h --- openafs_1.4.14.orig/src/viced/host.h 2010-12-17 16:58:42.000000000 +0100 +++ openafs_1.4.14/src/viced/host.h 2011-03-29 08:33:49.239179794 +0200 @@ -176,6 +176,7 @@ #define h_holdbit() ( 1<holds[h_holdSlot()] |= h_holdbit()) +#define h_Decrement_r(host) ((host)->holds[h_holdSlot()] &= ~h_holdbit()) extern int h_Release(register struct host *host); extern int h_Release_r(register struct host *host); @@ -207,8 +208,6 @@ extern struct host *h_Alloc_r(register struct rx_connection *r_con); extern int h_Lookup_r(afs_uint32 hostaddr, afs_uint16 hport, int *heldp, struct host **hostp); -extern void hashInsert_r(afs_uint32 addr, afs_uint16 port, - struct host* host); extern struct host *h_LookupUuid_r(afsUUID * uuidp); extern void h_Enumerate(int (*proc) (), char *param); extern struct host *h_GetHost_r(struct rx_connection *tcon, int *heldp); @@ -222,9 +221,9 @@ extern void h_GetWorkStats(); extern void h_flushhostcps(register afs_uint32 hostaddr, register afs_uint16 hport); -extern void hashInsertUuid_r(struct afsUUID *uuid, struct host *host); -extern void hashInsert_r(afs_uint32 addr, afs_uint16 port, struct host *host); -extern int hashDelete_r(afs_uint32 addr, afs_uint16 port, struct host *host); +extern void h_AddHostToUuidHashTable_r(struct afsUUID *uuid, struct host *host); +extern void h_AddHostToAddrHashTable_r(afs_uint32 addr, afs_uint16 port, struct host *host); +extern int h_DeleteHostFromAddrHashTable_r(afs_uint32 addr, afs_uint16 port, struct host *host); extern int initInterfaceAddr_r(struct host *host, struct interfaceAddr *interf); extern int addInterfaceAddr_r(struct host *host, afs_uint32 addr, afs_uint16 port); extern int removeInterfaceAddr_r(struct host *host, afs_uint32 addr, afs_uint16 port); diff -Naur openafs_1.4.14.orig/src/vol/vol-salvage.c openafs_1.4.14/src/vol/vol-salvage.c --- openafs_1.4.14.orig/src/vol/vol-salvage.c 2010-12-17 16:58:42.000000000 +0100 +++ openafs_1.4.14/src/vol/vol-salvage.c 2011-03-29 08:33:49.104185344 +0200 @@ -188,6 +188,9 @@ #include "viceinode.h" #include "salvage.h" #include "volinodes.h" /* header magic number, etc. stuff */ +#include +#include + #ifdef AFS_NT40_ENV #include #endif @@ -3459,6 +3462,372 @@ return; } +/** + * Get a new FID that can be used to create a new file. + * + * @param[in] volHeader vol header for the volume + * @param[in] class what type of vnode we'll be creating (vLarge or vSmall) + * @param[out] afid the FID that we can use (only Vnode and Unique are set) + * @param[inout] maxunique max uniquifier for all vnodes in the volume; + * updated to the new max unique if we create a new + * vnode + */ +static void +GetNewFID(VolumeDiskData *volHeader, VnodeClass class, AFSFid *afid, + Unique *maxunique) +{ + int i; + for (i = 0; i < vnodeInfo[class].nVnodes; i++) { + if (vnodeInfo[class].vnodes[i].type == vNull) { + break; + } + } + if (i == vnodeInfo[class].nVnodes) { + /* no free vnodes; make a new one */ + vnodeInfo[class].nVnodes++; + vnodeInfo[class].vnodes = realloc(vnodeInfo[class].vnodes, + sizeof(struct VnodeEssence) * (i+1)); + vnodeInfo[class].vnodes[i].type = vNull; + } + + afid->Vnode = bitNumberToVnodeNumber(i, class); + + if (volHeader->uniquifier < (*maxunique + 1)) { + /* header uniq is bad; it will get bumped by 2000 later */ + afid->Unique = *maxunique + 1 + 2000; + (*maxunique)++; + } else { + /* header uniq seems okay; just use that */ + afid->Unique = *maxunique = volHeader->uniquifier++; + } +} + +/** + * Create a vnode for a README file explaining not to use a recreated-root vol. + * + * @param[in] volHeader vol header for the volume + * @param[in] alinkH ihandle for i/o for the volume + * @param[in] vid volume id + * @param[inout] maxunique max uniquifier for all vnodes in the volume; + * updated to the new max unique if we create a new + * vnode + * @param[out] afid FID for the new readme vnode + * @param[out] ainode the inode for the new readme file + * + * @return operation status + * @retval 0 success + * @retval -1 error + */ +static int +CreateReadme(VolumeDiskData *volHeader, IHandle_t *alinkH, + VolumeId vid, Unique *maxunique, AFSFid *afid, Inode *ainode) +{ + Inode readmeinode; + struct VnodeDiskObject *rvnode = NULL; + afs_sfsize_t bytes; + IHandle_t *readmeH = NULL; + struct VnodeEssence *vep; + afs_fsize_t length; + time_t now = time(NULL); + + /* Try to make the note brief, but informative. Only administrators should + * be able to read this file at first, so we can hopefully assume they + * know what AFS is, what a volume is, etc. */ + char readme[] = +"This volume has been salvaged, but has lost its original root directory.\n" +"The root directory that exists now has been recreated from orphan files\n" +"from the rest of the volume. This recreated root directory may interfere\n" +"with old cached data on clients, and there is no way the salvager can\n" +"reasonably prevent that. So, it is recommended that you do not continue to\n" +"use this volume, but only copy the salvaged data to a new volume.\n" +"Continuing to use this volume as it exists now may cause some clients to\n" +"behave oddly when accessing this volume.\n" +"\n\t -- Your friendly neighborhood OpenAFS salvager\n"; + /* ^ the person reading this probably just lost some data, so they could + * use some cheering up. */ + + /* -1 for the trailing NUL */ + length = sizeof(readme) - 1; + + GetNewFID(volHeader, vSmall, afid, maxunique); + + vep = &vnodeInfo[vSmall].vnodes[vnodeIdToBitNumber(afid->Vnode)]; + + /* create the inode and write the contents */ + readmeinode = IH_CREATE(alinkH, fileSysDevice, fileSysPath, 0, vid, + afid->Vnode, afid->Unique, 1); + if (!VALID_INO(readmeinode)) { + Log("CreateReadme: readme IH_CREATE failed\n"); + goto error; + } + + IH_INIT(readmeH, fileSysDevice, vid, readmeinode); + bytes = IH_IWRITE(readmeH, 0, readme, length); + IH_RELEASE(readmeH); + + if (bytes != length) { + Log("CreateReadme: IWRITE failed (%d/%d)\n", (int)bytes, + (int)sizeof(readme)); + goto error; + } + + /* create the vnode and write it out */ + rvnode = malloc(SIZEOF_SMALLDISKVNODE); + if (!rvnode) { + Log("CreateRootDir: error alloc'ing memory\n"); + goto error; + } + + rvnode->type = vFile; + rvnode->cloned = 0; + rvnode->modeBits = 0777; + rvnode->linkCount = 1; + VNDISK_SET_LEN(rvnode, length); + rvnode->uniquifier = afid->Unique; + rvnode->dataVersion = 1; + VNDISK_SET_INO(rvnode, readmeinode); + rvnode->unixModifyTime = rvnode->serverModifyTime = now; + rvnode->author = 0; + rvnode->owner = 0; + rvnode->parent = 1; + rvnode->group = 0; + rvnode->vnodeMagic = VnodeClassInfo[vSmall].magic; + + bytes = IH_IWRITE(vnodeInfo[vSmall].handle, + vnodeIndexOffset(&VnodeClassInfo[vSmall], afid->Vnode), + (char*)rvnode, SIZEOF_SMALLDISKVNODE); + + if (bytes != SIZEOF_SMALLDISKVNODE) { + Log("CreateReadme: IH_IWRITE failed (%d/%d)\n", (int)bytes, + (int)SIZEOF_SMALLDISKVNODE); + goto error; + } + + /* update VnodeEssence for new readme vnode */ + vnodeInfo[vSmall].nAllocatedVnodes++; + vep->count = 0; + vep->blockCount = nBlocks(length); + vnodeInfo[vSmall].volumeBlockCount += vep->blockCount; + vep->parent = rvnode->parent; + vep->unique = rvnode->uniquifier; + vep->modeBits = rvnode->modeBits; + vep->InodeNumber = VNDISK_GET_INO(rvnode); + vep->type = rvnode->type; + vep->author = rvnode->author; + vep->owner = rvnode->owner; + vep->group = rvnode->group; + + free(rvnode); + rvnode = NULL; + + vep->claimed = 1; + vep->changed = 0; + vep->salvaged = 1; + vep->todelete = 0; + + *ainode = readmeinode; + + return 0; + + error: + if (IH_DEC(alinkH, readmeinode, vid)) { + Log("CreateReadme (recovery): IH_DEC failed\n"); + } + + if (rvnode) { + free(rvnode); + rvnode = NULL; + } + + return -1; +} + +/** + * create a root dir for a volume that lacks one. + * + * @param[in] volHeader vol header for the volume + * @param[in] alinkH ihandle for disk access for this volume group + * @param[in] vid volume id we're dealing with + * @param[out] rootdir populated with info about the new root dir + * @param[inout] maxunique max uniquifier for all vnodes in the volume; + * updated to the new max unique if we create a new + * vnode + * + * @return operation status + * @retval 0 success + * @retval -1 error + */ +static int +CreateRootDir(VolumeDiskData *volHeader, IHandle_t *alinkH, VolumeId vid, + struct DirSummary *rootdir, Unique *maxunique) +{ + FileVersion dv; + int decroot = 0, decreadme = 0; + AFSFid did, readmeid; + afs_fsize_t length; + Inode rootinode; + struct VnodeDiskObject *rootvnode = NULL; + struct acl_accessList *ACL; + Inode *ip; + afs_sfsize_t bytes; + struct VnodeEssence *vep; + Inode readmeinode; + time_t now = time(NULL); + + if (!vnodeInfo[vLarge].vnodes && !vnodeInfo[vSmall].vnodes) { + Log("Not creating new root dir; volume appears to lack any vnodes\n"); + goto error; + } + + if (!vnodeInfo[vLarge].vnodes) { + /* We don't have any large vnodes in the volume; allocate room + * for one so we can recreate the root dir */ + vnodeInfo[vLarge].nVnodes = 1; + vnodeInfo[vLarge].vnodes = calloc(1, sizeof(struct VnodeEssence)); + vnodeInfo[vLarge].inodes = calloc(1, sizeof(Inode)); + + assert(vnodeInfo[vLarge].vnodes); + assert(vnodeInfo[vLarge].inodes); + } + + vep = &vnodeInfo[vLarge].vnodes[vnodeIdToBitNumber(1)]; + ip = &vnodeInfo[vLarge].inodes[vnodeIdToBitNumber(1)]; + if (vep->type != vNull) { + Log("Not creating new root dir; existing vnode 1 is non-null\n"); + goto error; + } + + if (CreateReadme(volHeader, alinkH, vid, maxunique, &readmeid, &readmeinode)) { + goto error; + } + decreadme = 1; + + /* set the DV to a very high number, so it is unlikely that we collide + * with a cached DV */ + dv = 1 << 30; + + rootinode = IH_CREATE(alinkH, fileSysDevice, fileSysPath, 0, vid, 1, 1, dv); + if (!VALID_INO(rootinode)) { + Log("CreateRootDir: IH_CREATE failed\n"); + goto error; + } + decroot = 1; + + SetSalvageDirHandle(&rootdir->dirHandle, vid, fileSysDevice, rootinode); + did.Volume = vid; + did.Vnode = 1; + did.Unique = 1; + if (MakeDir(&rootdir->dirHandle, (afs_int32*)&did, (afs_int32*)&did)) { + Log("CreateRootDir: MakeDir failed\n"); + goto error; + } + if (Create(&rootdir->dirHandle, "README.ROOTDIR", &readmeid)) { + Log("CreateRootDir: Create failed\n"); + goto error; + } + DFlush(); + length = Length(&rootdir->dirHandle); + DZap((void *)&rootdir->dirHandle); + + /* create the new root dir vnode */ + rootvnode = malloc(SIZEOF_LARGEDISKVNODE); + if (!rootvnode) { + Log("CreateRootDir: malloc failed\n"); + goto error; + } + + /* only give 'rl' permissions to 'system:administrators'. We do this to + * try to catch the attention of an administrator, that they should not + * be writing to this directory or continue to use it. */ + ACL = VVnodeDiskACL(rootvnode); + ACL->size = sizeof(struct acl_accessList); + ACL->version = ACL_ACLVERSION; + ACL->total = 1; + ACL->positive = 1; + ACL->negative = 0; + ACL->entries[0].id = -204; /* system:administrators */ + ACL->entries[0].rights = PRSFS_READ | PRSFS_LOOKUP; + + rootvnode->type = vDirectory; + rootvnode->cloned = 0; + rootvnode->modeBits = 0777; + rootvnode->linkCount = 2; + VNDISK_SET_LEN(rootvnode, length); + rootvnode->uniquifier = 1; + rootvnode->dataVersion = dv; + VNDISK_SET_INO(rootvnode, rootinode); + rootvnode->unixModifyTime = rootvnode->serverModifyTime = now; + rootvnode->author = 0; + rootvnode->owner = 0; + rootvnode->parent = 0; + rootvnode->group = 0; + rootvnode->vnodeMagic = VnodeClassInfo[vLarge].magic; + + /* write it out to disk */ + bytes = IH_IWRITE(vnodeInfo[vLarge].handle, + vnodeIndexOffset(&VnodeClassInfo[vLarge], 1), + (char*)rootvnode, SIZEOF_LARGEDISKVNODE); + + if (bytes != SIZEOF_LARGEDISKVNODE) { + /* just cast to int and don't worry about printing real 64-bit ints; + * a large disk vnode isn't anywhere near the 32-bit limit */ + Log("CreateRootDir: IH_IWRITE failed (%d/%d)\n", (int)bytes, + (int)SIZEOF_LARGEDISKVNODE); + goto error; + } + + /* update VnodeEssence for the new root vnode */ + vnodeInfo[vLarge].nAllocatedVnodes++; + vep->count = 0; + vep->blockCount = nBlocks(length); + vnodeInfo[vLarge].volumeBlockCount += vep->blockCount; + vep->parent = rootvnode->parent; + vep->unique = rootvnode->uniquifier; + vep->modeBits = rootvnode->modeBits; + vep->InodeNumber = VNDISK_GET_INO(rootvnode); + vep->type = rootvnode->type; + vep->author = rootvnode->author; + vep->owner = rootvnode->owner; + vep->group = rootvnode->group; + + free(rootvnode); + rootvnode = NULL; + + vep->claimed = 0; + vep->changed = 0; + vep->salvaged = 1; + vep->todelete = 0; + + /* update DirSummary for the new root vnode */ + rootdir->vnodeNumber = 1; + rootdir->unique = 1; + rootdir->haveDot = 1; + rootdir->haveDotDot = 1; + rootdir->rwVid = vid; + rootdir->copied = 0; + rootdir->parent = 0; + rootdir->name = strdup("."); + rootdir->vname = volHeader->name; + rootdir->ds_linkH = alinkH; + + *ip = rootinode; + + return 0; + + error: + if (decroot && IH_DEC(alinkH, rootinode, vid)) { + Log("CreateRootDir (recovery): IH_DEC (root) failed\n"); + } + if (decreadme && IH_DEC(alinkH, readmeinode, vid)) { + Log("CreateRootDir (recovery): IH_DEC (readme) failed\n"); + } + if (rootvnode) { + free(rootvnode); + rootvnode = NULL; + } + return -1; +} + int SalvageVolume(register struct InodeSummary *rwIsp, IHandle_t * alinkH) { @@ -3482,6 +3851,7 @@ VnodeId LFVnode, ThisVnode; Unique LFUnique, ThisUnique; char npath[128]; + int newrootdir = 0; vid = rwIsp->volSummary->header.id; IH_INIT(h, fileSysDevice, vid, rwIsp->volSummary->header.volumeInfo); @@ -3511,6 +3881,18 @@ return 0; } + if (!rootdirfound && (orphans == ORPH_ATTACH) && !Testing) { + + Log("Cannot find root directory for volume %u; attempting to create " + "a new one\n", vid); + + code = CreateRootDir(&volHeader, alinkH, vid, &rootdir, &maxunique); + if (code == 0) { + rootdirfound = 1; + newrootdir = 1; + } + } + /* Parse each vnode looking for orphaned vnodes and * connect them to the tree as orphaned (if requested). */ @@ -3532,8 +3914,20 @@ */ if (class == vLarge) { /* directory vnode */ pv = vnodeIdToBitNumber(vep->parent); - if (vnodeInfo[vLarge].vnodes[pv].unique != 0) - vnodeInfo[vLarge].vnodes[pv].count++; + if (vnodeInfo[vLarge].vnodes[pv].unique != 0) { + if (vep->parent == 1 && newrootdir) { + /* this vnode's parent was the volume root, and + * we just created the volume root. So, the parent + * dir didn't exist during JudgeEntry, so the link + * count was not inc'd there, so don't dec it here. + */ + + /* noop */ + + } else { + vnodeInfo[vLarge].vnodes[pv].count++; + } + } } if (!rootdirfound) @@ -3731,6 +4125,12 @@ volHeader.uniquifier = (maxunique + 1 + 2000); } + if (newrootdir) { + Log("*** WARNING: Root directory recreated, but volume is fragile! " + "Only use this salvaged volume to copy data to another volume; " + "do not continue to use this volume (%u) as-is.\n", vid); + } + /* Turn off the inUse bit; the volume's been salvaged! */ volHeader.inUse = 0; /* clear flag indicating inUse@last crash */ volHeader.needsSalvaged = 0; /* clear 'damaged' flag */ diff -Naur openafs_1.4.14.orig/src/vol/volume.c openafs_1.4.14/src/vol/volume.c --- openafs_1.4.14.orig/src/vol/volume.c 2010-12-17 16:58:42.000000000 +0100 +++ openafs_1.4.14/src/vol/volume.c 2011-03-29 08:33:49.104185344 +0200 @@ -979,6 +979,20 @@ V_inUse(vp) = 1; V_offlineMessage(vp)[0] = '\0'; } + if (!V_inUse(vp)) { + *ec = VNOVOL; + /* mimic e.g. GetVolume errors */ + if (!V_blessed(vp)) + Log("Volume %u offline: not blessed\n", V_id(vp)); + else if (!V_inService(vp)) + Log("Volume %u offline: not in service\n", V_id(vp)); + else { + Log("Volume %u offline: needs salvage\n", V_id(vp)); + *ec = VOFFLINE; + } + VPutVolume_r(vp); + vp = NULL; + } } return vp; diff -Naur openafs_1.4.14.orig/src/volser/dumpstuff.c openafs_1.4.14/src/volser/dumpstuff.c --- openafs_1.4.14.orig/src/volser/dumpstuff.c 2010-12-17 16:58:42.000000000 +0100 +++ openafs_1.4.14/src/volser/dumpstuff.c 2011-03-29 08:33:49.236179917 +0200 @@ -45,6 +45,7 @@ #include "dump.h" #include #include +#include #include "volser.h" #include "volint.h" diff -Naur openafs_1.4.14.orig/src/volser/volprocs.c openafs_1.4.14/src/volser/volprocs.c --- openafs_1.4.14.orig/src/volser/volprocs.c 2010-12-17 16:58:42.000000000 +0100 +++ openafs_1.4.14/src/volser/volprocs.c 2011-03-29 08:33:49.236179917 +0200 @@ -95,7 +95,7 @@ /* this call unlocks all of the partition locks we've set */ int -VPFullUnlock() +VPFullUnlock_r(void) { register struct DiskPartition64 *tp; for (tp = DiskPartitionList; tp; tp = tp->next) { @@ -107,6 +107,16 @@ return 0; } +int +VPFullUnlock(void) +{ + int code; + VOL_LOCK; + code = VPFullUnlock_r(); + VOL_UNLOCK; + return code; +} + /* get partition id from a name */ afs_int32 PartitionID(char *aname) @@ -2642,7 +2652,7 @@ { transDebugInfo *pntr; afs_int32 allocSize = 50; - struct volser_trans *tt, *allTrans; + struct volser_trans *tt, *nt, *allTrans; transInfo->transDebugEntries_val = (transDebugInfo *) malloc(allocSize * sizeof(transDebugInfo)); @@ -2655,9 +2665,8 @@ allTrans = TransList(); if (allTrans == (struct volser_trans *)0) goto done; /*no active transactions */ - for (tt = allTrans; tt; tt = tt->next) { /*copy relevant info into pntr */ - THOLD(tt); /* do not delete tt while copying info */ - VTRANS_UNLOCK; + for (tt = allTrans; tt; tt = nt) { /*copy relevant info into pntr */ + nt = tt->next; VTRANS_OBJ_LOCK(tt); pntr->tid = tt->tid; pntr->time = tt->time; @@ -2694,8 +2703,6 @@ /*set pntr to right position */ } - TRELE(tt); - VTRANS_LOCK; } done: VTRANS_UNLOCK;