Linux: 2.6.38: deal with dcache_lock removal
authorMarc Dionne <marc.c.dionne@gmail.com>
Sat, 29 Jan 2011 01:59:17 +0000 (20:59 -0500)
committerDerrick Brashear <shadow@dementia.org>
Wed, 9 Feb 2011 02:58:56 +0000 (18:58 -0800)
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 <buildbot@rampaginggeek.com>
Reviewed-by: Derrick Brashear <shadow@dementia.org>

acinclude.m4
src/afs/LINUX/osi_vcache.c
src/afs/afs_daemons.c
src/cf/linux-test4.m4

index 68a296d..8041547 100644 (file)
@@ -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
index 10fb5cf..21ad7c2 100644 (file)
@@ -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);
index fb89d44..8938ea8 100644 (file)
@@ -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);
 
index 5a87f74..6f0fd11 100644 (file)
@@ -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 <linux/dcache.h> ],
+                       [printk("%p", &dcache_lock);],
+                       [HAVE_DCACHE_LOCK],
+                       [define if dcache_lock exists],
+                       [])
+])
+