From 2eca7aef7b2940e4ef5f9901ce28481af6edb6dd Mon Sep 17 00:00:00 2001 From: Marc Dionne Date: Fri, 28 Jan 2011 20:59:17 -0500 Subject: [PATCH] Linux: 2.6.38: deal with dcache_lock removal dcache_lock is gone in 2.6.38, and some of the vfs locking rules have changed. Of interest for openafs: - inode->i_lock protects the d_alias list - dentry->d_lock protects d_unhashed() Add a new configure test for dcache_lock, and replace its use by the appropriate new lock(s). Change-Id: Ic8d860d4f9f6438e966c15f5178c0d82343e3e1c Reviewed-on: http://gerrit.openafs.org/3771 Tested-by: BuildBot Reviewed-by: Derrick Brashear --- acinclude.m4 | 1 + src/afs/LINUX/osi_vcache.c | 35 +++++++++++++++++++++++++++++++++-- src/afs/afs_daemons.c | 8 ++++++++ src/cf/linux-test4.m4 | 11 +++++++++++ 4 files changed, 53 insertions(+), 2 deletions(-) diff --git a/acinclude.m4 b/acinclude.m4 index 68a296d69..804154758 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -903,6 +903,7 @@ case $AFS_SYSNAME in *_linux* | *_umlinux*) LINUX_KEY_ALLOC_NEEDS_CRED LINUX_INIT_WORK_HAS_DATA LINUX_REGISTER_SYSCTL_TABLE_NOFLAG + LINUX_HAVE_DCACHE_LOCK dnl If we are guaranteed that keyrings will work - that is dnl a) The kernel has keyrings enabled diff --git a/src/afs/LINUX/osi_vcache.c b/src/afs/LINUX/osi_vcache.c index 10fb5cf06..21ad7c209 100644 --- a/src/afs/LINUX/osi_vcache.c +++ b/src/afs/LINUX/osi_vcache.c @@ -18,6 +18,7 @@ osi_TryEvictVCache(struct vcache *avc, int *slept) { int code; struct dentry *dentry; + struct inode *inode = AFSTOV(avc); struct list_head *cur, *head; /* First, see if we can evict the inode from the dcache */ @@ -25,8 +26,10 @@ osi_TryEvictVCache(struct vcache *avc, int *slept) { *slept = 1; ReleaseWriteLock(&afs_xvcache); AFS_GUNLOCK(); + +#if defined(HAVE_DCACHE_LOCK) spin_lock(&dcache_lock); - head = &(AFSTOV(avc))->i_dentry; + head = &inode->i_dentry; restart: cur = head; @@ -35,7 +38,6 @@ restart: if (d_unhashed(dentry)) continue; - dget_locked(dentry); spin_unlock(&dcache_lock); @@ -49,6 +51,35 @@ restart: goto restart; } spin_unlock(&dcache_lock); +#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(); ObtainWriteLock(&afs_xvcache, 733); diff --git a/src/afs/afs_daemons.c b/src/afs/afs_daemons.c index fb89d44fb..8938ea837 100644 --- a/src/afs/afs_daemons.c +++ b/src/afs/afs_daemons.c @@ -409,7 +409,11 @@ afs_CheckRootVolume(void) 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 @@ -421,7 +425,11 @@ afs_CheckRootVolume(void) #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 --git a/src/cf/linux-test4.m4 b/src/cf/linux-test4.m4 index 5a87f748a..6f0fd115f 100644 --- a/src/cf/linux-test4.m4 +++ b/src/cf/linux-test4.m4 @@ -571,3 +571,14 @@ AC_DEFUN([LINUX_HAVE_TRY_TO_FREEZE], [ []) ]) + +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], + []) +]) + -- 2.39.5