aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/fsync.c
diff options
context:
space:
mode:
authorPekka Enberg <penberg@kernel.org>2011-09-19 17:46:07 +0300
committerPekka Enberg <penberg@kernel.org>2011-09-19 17:46:07 +0300
commitd20bbfab01802e195a50435940f7e4aa747c217c (patch)
tree82b0007e33c083050a4e60a49dbb2f5477b4c99d /fs/ext4/fsync.c
parentslub: doc: update the slabinfo.c file path (diff)
parentslub: explicitly document position of inserting slab to partial list (diff)
downloadlinux-dev-d20bbfab01802e195a50435940f7e4aa747c217c.tar.xz
linux-dev-d20bbfab01802e195a50435940f7e4aa747c217c.zip
Merge branch 'slab/urgent' into slab/next
Diffstat (limited to 'fs/ext4/fsync.c')
-rw-r--r--fs/ext4/fsync.c26
1 files changed, 21 insertions, 5 deletions
diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c
index da3bed3e0c29..036f78f7a1ef 100644
--- a/fs/ext4/fsync.c
+++ b/fs/ext4/fsync.c
@@ -129,15 +129,30 @@ static int ext4_sync_parent(struct inode *inode)
{
struct writeback_control wbc;
struct dentry *dentry = NULL;
+ struct inode *next;
int ret = 0;
- while (inode && ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY)) {
+ if (!ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY))
+ return 0;
+ inode = igrab(inode);
+ while (ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY)) {
ext4_clear_inode_state(inode, EXT4_STATE_NEWENTRY);
- dentry = list_entry(inode->i_dentry.next,
- struct dentry, d_alias);
- if (!dentry || !dentry->d_parent || !dentry->d_parent->d_inode)
+ dentry = NULL;
+ spin_lock(&inode->i_lock);
+ if (!list_empty(&inode->i_dentry)) {
+ dentry = list_first_entry(&inode->i_dentry,
+ struct dentry, d_alias);
+ dget(dentry);
+ }
+ spin_unlock(&inode->i_lock);
+ if (!dentry)
break;
- inode = dentry->d_parent->d_inode;
+ next = igrab(dentry->d_parent->d_inode);
+ dput(dentry);
+ if (!next)
+ break;
+ iput(inode);
+ inode = next;
ret = sync_mapping_buffers(inode->i_mapping);
if (ret)
break;
@@ -148,6 +163,7 @@ static int ext4_sync_parent(struct inode *inode)
if (ret)
break;
}
+ iput(inode);
return ret;
}