]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] (4/) BKL removal in d_move()
authorAlexander Viro <viro@math.psu.edu>
Wed, 22 May 2002 05:46:23 +0000 (22:46 -0700)
committerLinus Torvalds <torvalds@penguin.transmeta.com>
Wed, 22 May 2002 05:46:23 +0000 (22:46 -0700)
... is finally done.

Documentation/filesystems/porting
fs/dcache.c
fs/namei.c

index 304e81ae3b1d16dcb9df0adea173cd17c4d9fb9b..3b8ca9ddb8208d84acf3d52a029f8529f34bd68f 100644 (file)
@@ -198,3 +198,20 @@ e.g.
 ->revalidate() is gone.  If your filesystem had it - provide ->getattr()
 and let it call whatever you had as ->revlidate() + (for symlinks that
 had ->revalidate()) add calls in ->follow_link()/->readlink().
+
+---
+[mandatory]
+
+->d_parent changes are not protected by BKL anymore.  Read access is safe
+if at least one of the following is true:
+       * filesystem has no cross-directory rename()
+       * dcache_lock is held
+       * dparent_lock is held (shared)
+       * we know that parent had been locked (e.g. we are looking at
+->d_parent of ->lookup() argument).
+       * we are called from ->rename().
+Audit your code and add locking if needed.  Notice that any place that is
+not protected by the conditions above is risky even in the old tree - you
+had been relying on BKL and that's prone to screwups.  Old tree had quite
+a few holes of that kind - unprotected access to ->d_parent leading to
+anything from oops to silent memory corruption.
index 662a240d2ee5a330896f7fcb589dd4dda97d3e70..88c946451a69403e502a3de11ee4fd408186746b 100644 (file)
@@ -32,9 +32,6 @@
 spinlock_t dcache_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 rwlock_t dparent_lock __cacheline_aligned_in_smp = RW_LOCK_UNLOCKED;
 
-/* Right now the dcache depends on the kernel lock */
-#define check_lock()   if (!kernel_locked()) BUG()
-
 static kmem_cache_t *dentry_cache; 
 
 /*
@@ -812,7 +809,6 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
        struct dentry *new = NULL;
 
        if (inode && S_ISDIR(inode->i_mode)) {
-               lock_kernel(); /* for d_move */
                spin_lock(&dcache_lock);
                if (!list_empty(&inode->i_dentry)) {
                        new = list_entry(inode->i_dentry.next, struct dentry, d_alias);
@@ -828,7 +824,6 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
                        spin_unlock(&dcache_lock);
                        d_rehash(dentry);
                }
-               unlock_kernel();
        } else
                d_add(dentry, inode);
        return new;
@@ -1012,7 +1007,6 @@ static inline void switch_names(struct dentry * dentry, struct dentry * target)
 {
        const unsigned char *old_name, *new_name;
 
-       check_lock();
        memcpy(dentry->d_iname, target->d_iname, DNAME_INLINE_LEN); 
        old_name = target->d_name.name;
        new_name = dentry->d_name.name;
@@ -1051,8 +1045,6 @@ static inline void switch_names(struct dentry * dentry, struct dentry * target)
   
 void d_move(struct dentry * dentry, struct dentry * target)
 {
-       check_lock();
-
        if (!dentry->d_inode)
                printk(KERN_WARNING "VFS: moving negative dcache entry\n");
 
index 5b6e0cf59ec8c918f0fd83f40e0875cb1e39554c..d4cea0318dc4c77c370bfdeb985208b909227d16 100644 (file)
@@ -1866,11 +1866,8 @@ int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
                        d_rehash(new_dentry);
                dput(new_dentry);
        }
-       if (!error) {
-               lock_kernel();
+       if (!error)
                d_move(old_dentry,new_dentry);
-               unlock_kernel();
-       }
        return error;
 }
 
@@ -1890,11 +1887,8 @@ int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
                error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
        if (!error) {
                /* The following d_move() should become unconditional */
-               if (!(old_dir->i_sb->s_type->fs_flags & FS_ODD_RENAME)) {
-                       lock_kernel();
+               if (!(old_dir->i_sb->s_type->fs_flags & FS_ODD_RENAME))
                        d_move(old_dentry, new_dentry);
-                       unlock_kernel();
-               }
        }
        if (target)
                up(&target->i_sem);