nfsd race fixes: ext3
authorAl Viro <viro@zeniv.linux.org.uk>
Tue, 30 Dec 2008 07:02:50 +0000 (02:02 -0500)
committerAl Viro <viro@zeniv.linux.org.uk>
Wed, 31 Dec 2008 23:07:44 +0000 (18:07 -0500)
ext3 analog of the previous patch

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/ext3/ialloc.c
fs/ext3/namei.c

index 490bd0ed789693dbb65ec6deb318541d06ed3911..5655fbcbd11f564b82c31eea45a6c8fe33b41f58 100644 (file)
@@ -579,7 +579,10 @@ got:
        ext3_set_inode_flags(inode);
        if (IS_DIRSYNC(inode))
                handle->h_sync = 1;
-       insert_inode_hash(inode);
+       if (insert_inode_locked(inode) < 0) {
+               err = -EINVAL;
+               goto fail_drop;
+       }
        spin_lock(&sbi->s_next_gen_lock);
        inode->i_generation = sbi->s_next_generation++;
        spin_unlock(&sbi->s_next_gen_lock);
@@ -627,6 +630,7 @@ fail_drop:
        DQUOT_DROP(inode);
        inode->i_flags |= S_NOQUOTA;
        inode->i_nlink = 0;
+       unlock_new_inode(inode);
        iput(inode);
        brelse(bitmap_bh);
        return ERR_PTR(err);
index 3e5edc92aa0b088071d1711c4bcf620d585e0416..297ea8dfac7cc8a6a65a8be491b9de8ac5346bce 100644 (file)
@@ -1652,9 +1652,11 @@ static int ext3_add_nondir(handle_t *handle,
        if (!err) {
                ext3_mark_inode_dirty(handle, inode);
                d_instantiate(dentry, inode);
+               unlock_new_inode(inode);
                return 0;
        }
        drop_nlink(inode);
+       unlock_new_inode(inode);
        iput(inode);
        return err;
 }
@@ -1765,6 +1767,7 @@ retry:
        dir_block = ext3_bread (handle, inode, 0, 1, &err);
        if (!dir_block) {
                drop_nlink(inode); /* is this nlink == 0? */
+               unlock_new_inode(inode);
                ext3_mark_inode_dirty(handle, inode);
                iput (inode);
                goto out_stop;
@@ -1792,6 +1795,7 @@ retry:
        err = ext3_add_entry (handle, dentry, inode);
        if (err) {
                inode->i_nlink = 0;
+               unlock_new_inode(inode);
                ext3_mark_inode_dirty(handle, inode);
                iput (inode);
                goto out_stop;
@@ -1800,6 +1804,7 @@ retry:
        ext3_update_dx_flag(dir);
        ext3_mark_inode_dirty(handle, dir);
        d_instantiate(dentry, inode);
+       unlock_new_inode(inode);
 out_stop:
        ext3_journal_stop(handle);
        if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries))
@@ -2174,6 +2179,7 @@ retry:
                                mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS);
                if (err) {
                        drop_nlink(inode);
+                       unlock_new_inode(inode);
                        ext3_mark_inode_dirty(handle, inode);
                        iput (inode);
                        goto out_stop;
@@ -2221,7 +2227,14 @@ retry:
        inc_nlink(inode);
        atomic_inc(&inode->i_count);
 
-       err = ext3_add_nondir(handle, dentry, inode);
+       err = ext3_add_entry(handle, dentry, inode);
+       if (!err) {
+               ext3_mark_inode_dirty(handle, inode);
+               d_instantiate(dentry, inode);
+       } else {
+               drop_nlink(inode);
+               iput(inode);
+       }
        ext3_journal_stop(handle);
        if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries))
                goto retry;