A few filesystems modify dentry.d_flags under non-obvious locking. To consolidate that field wth d_vfs_flags they need to take ->d_lock --- 25-akpm/fs/afs/dir.c | 2 ++ 25-akpm/fs/autofs4/root.c | 13 ++++++++++++- 25-akpm/fs/exportfs/expfs.c | 4 ++++ 25-akpm/fs/intermezzo/dir.c | 2 ++ 25-akpm/fs/nfs/unlink.c | 4 ++++ 5 files changed, 24 insertions(+), 1 deletion(-) diff -puN fs/nfs/unlink.c~d_flags-locking-fix fs/nfs/unlink.c --- 25/fs/nfs/unlink.c~d_flags-locking-fix 2004-05-08 03:46:06.945432360 -0700 +++ 25-akpm/fs/nfs/unlink.c 2004-05-08 03:46:06.955430840 -0700 @@ -180,7 +180,9 @@ nfs_async_unlink(struct dentry *dentry) task->tk_action = nfs_async_unlink_init; task->tk_release = nfs_async_unlink_release; + spin_lock(&dentry->d_lock); dentry->d_flags |= DCACHE_NFSFS_RENAMED; + spin_unlock(&dentry->d_lock); data->cred = rpcauth_lookupcred(clnt->cl_auth, 0); rpc_sleep_on(&nfs_delete_queue, task, NULL, NULL); @@ -210,7 +212,9 @@ nfs_complete_unlink(struct dentry *dentr return; data->count++; nfs_copy_dname(dentry, data); + spin_lock(&dentry->d_lock); dentry->d_flags &= ~DCACHE_NFSFS_RENAMED; + spin_unlock(&dentry->d_lock); if (data->task.tk_rpcwait == &nfs_delete_queue) rpc_wake_up_task(&data->task); nfs_put_unlinkdata(data); diff -puN fs/afs/dir.c~d_flags-locking-fix fs/afs/dir.c --- 25/fs/afs/dir.c~d_flags-locking-fix 2004-05-08 03:46:06.947432056 -0700 +++ 25-akpm/fs/afs/dir.c 2004-05-08 03:46:06.957430536 -0700 @@ -615,7 +615,9 @@ static int afs_d_revalidate(struct dentr /* the dirent, if it exists, now points to a different vnode */ not_found: + spin_lock(&dentry->d_lock); dentry->d_flags |= DCACHE_NFSFS_RENAMED; + spin_unlock(&dentry->d_lock); out_bad: if (inode) { diff -puN fs/autofs4/root.c~d_flags-locking-fix fs/autofs4/root.c --- 25/fs/autofs4/root.c~d_flags-locking-fix 2004-05-08 03:46:06.949431752 -0700 +++ 25-akpm/fs/autofs4/root.c 2004-05-08 03:46:06.958430384 -0700 @@ -326,7 +326,9 @@ static int try_to_fill_dentry(struct den /* Turn this into a real negative dentry? */ if (status == -ENOENT) { dentry->d_time = jiffies + AUTOFS_NEGATIVE_TIMEOUT; + spin_lock(&dentry->d_lock); dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; + spin_unlock(&dentry->d_lock); return 1; } else if (status) { /* Return a negative dentry, but leave it "pending" */ @@ -338,13 +340,17 @@ static int try_to_fill_dentry(struct den DPRINTK(("try_to_fill_entry: waiting for mount name=%.*s\n", dentry->d_name.len, dentry->d_name.name)); + spin_lock(&dentry->d_lock); dentry->d_flags |= DCACHE_AUTOFS_PENDING; + spin_unlock(&dentry->d_lock); status = autofs4_wait(sbi, dentry, NFY_MOUNT); DPRINTK(("try_to_fill_entry: mount done status=%d\n", status)); if (status) { + spin_lock(&dentry->d_lock); dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; + spin_unlock(&dentry->d_lock); return 0; } } @@ -354,7 +360,9 @@ static int try_to_fill_dentry(struct den if (!autofs4_oz_mode(sbi)) autofs4_update_usage(dentry); + spin_lock(&dentry->d_lock); dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; + spin_unlock(&dentry->d_lock); return 1; } @@ -478,8 +486,11 @@ static struct dentry *autofs4_root_looku */ dentry->d_op = &autofs4_root_dentry_operations; - if (!oz_mode) + if (!oz_mode) { + spin_lock(&dentry->d_lock); dentry->d_flags |= DCACHE_AUTOFS_PENDING; + spin_unlock(&dentry->d_lock); + } dentry->d_fsdata = NULL; d_add(dentry, NULL); diff -puN fs/intermezzo/dir.c~d_flags-locking-fix fs/intermezzo/dir.c --- 25/fs/intermezzo/dir.c~d_flags-locking-fix 2004-05-08 03:46:06.950431600 -0700 +++ 25-akpm/fs/intermezzo/dir.c 2004-05-08 03:46:06.960430080 -0700 @@ -161,7 +161,9 @@ struct dentry *presto_iget_ilookup(struc } d_instantiate(dentry, inode); + spin_lock(&dentry->d_lock); dentry->d_flags |= DCACHE_DISCONNECTED; /* NFS hack */ + spin_unlock(&dentry->d_lock); EXIT; return NULL; diff -puN fs/exportfs/expfs.c~d_flags-locking-fix fs/exportfs/expfs.c --- 25/fs/exportfs/expfs.c~d_flags-locking-fix 2004-05-08 03:46:06.953431144 -0700 +++ 25-akpm/fs/exportfs/expfs.c 2004-05-08 03:46:06.961429928 -0700 @@ -155,11 +155,15 @@ find_exported_dentry(struct super_block if (!IS_ROOT(pd)) { /* must have found a connected parent - great */ + spin_lock(&pd->d_lock); pd->d_flags &= ~DCACHE_DISCONNECTED; + spin_unlock(&pd->d_lock); noprogress = 0; } else if (pd == sb->s_root) { printk(KERN_ERR "export: Eeek filesystem root is not connected, impossible\n"); + spin_lock(&pd->d_lock); pd->d_flags &= ~DCACHE_DISCONNECTED; + spin_unlock(&pd->d_lock); noprogress = 0; } else { /* we have hit the top of a disconnected path. Try _