Commit 4195f73d1329e49727bcceb028e58cb38376c2b0

Authored by Nick Piggin
Committed by Al Viro
1 parent 545b9fd3d7

fs: block_dump missing dentry locking

I think the block_dump output in __mark_inode_dirty is missing dentry locking.
Surely the i_dentry list can change any time, so we may not even *get* a
dentry there. If we do get one by chance, then it would appear to be able to
go away or get renamed at any time...

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

Showing 1 changed file with 24 additions and 17 deletions Side-by-side Diff

... ... @@ -64,6 +64,28 @@
64 64 clear_bit(BDI_pdflush, &bdi->state);
65 65 }
66 66  
  67 +static noinline void block_dump___mark_inode_dirty(struct inode *inode)
  68 +{
  69 + if (inode->i_ino || strcmp(inode->i_sb->s_id, "bdev")) {
  70 + struct dentry *dentry;
  71 + const char *name = "?";
  72 +
  73 + dentry = d_find_alias(inode);
  74 + if (dentry) {
  75 + spin_lock(&dentry->d_lock);
  76 + name = (const char *) dentry->d_name.name;
  77 + }
  78 + printk(KERN_DEBUG
  79 + "%s(%d): dirtied inode %lu (%s) on %s\n",
  80 + current->comm, task_pid_nr(current), inode->i_ino,
  81 + name, inode->i_sb->s_id);
  82 + if (dentry) {
  83 + spin_unlock(&dentry->d_lock);
  84 + dput(dentry);
  85 + }
  86 + }
  87 +}
  88 +
67 89 /**
68 90 * __mark_inode_dirty - internal function
69 91 * @inode: inode to mark
... ... @@ -114,23 +136,8 @@
114 136 if ((inode->i_state & flags) == flags)
115 137 return;
116 138  
117   - if (unlikely(block_dump)) {
118   - struct dentry *dentry = NULL;
119   - const char *name = "?";
120   -
121   - if (!list_empty(&inode->i_dentry)) {
122   - dentry = list_entry(inode->i_dentry.next,
123   - struct dentry, d_alias);
124   - if (dentry && dentry->d_name.name)
125   - name = (const char *) dentry->d_name.name;
126   - }
127   -
128   - if (inode->i_ino || strcmp(inode->i_sb->s_id, "bdev"))
129   - printk(KERN_DEBUG
130   - "%s(%d): dirtied inode %lu (%s) on %s\n",
131   - current->comm, task_pid_nr(current), inode->i_ino,
132   - name, inode->i_sb->s_id);
133   - }
  139 + if (unlikely(block_dump))
  140 + block_dump___mark_inode_dirty(inode);
134 141  
135 142 spin_lock(&inode_lock);
136 143 if ((inode->i_state & flags) != flags) {