aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>2014-12-10 18:54:34 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-12-10 20:41:16 -0500
commit705304a863cc41585508c0f476f6d3ec28cf7e00 (patch)
tree4520ccc069e5966baaae43866e925aa0a2c401fb /fs
parent72b9918ea4d7f2d8362a2defdb93e5fd25a86308 (diff)
nilfs2: fix the nilfs_iget() vs. nilfs_new_inode() races
Same story as in commit 41080b5a2401 ("nfsd race fixes: ext2") (similar ext2 fix) except that nilfs2 needs to use insert_inode_locked4() instead of insert_inode_locked() and a bug of a check for dead inodes needs to be fixed. If nilfs_iget() is called from nfsd after nilfs_new_inode() calls insert_inode_locked4(), nilfs_iget() will wait for unlock_new_inode() at the end of nilfs_mkdir()/nilfs_create()/etc to unlock the inode. If nilfs_iget() is called before nilfs_new_inode() calls insert_inode_locked4(), it will create an in-core inode and read its data from the on-disk inode. But, nilfs_iget() will find i_nlink equals zero and fail at nilfs_read_inode_common(), which will lead it to call iget_failed() and cleanly fail. However, this sanity check doesn't work as expected for reused on-disk inodes because they leave a non-zero value in i_mode field and it hinders the test of i_nlink. This patch also fixes the issue by removing the test on i_mode that nilfs2 doesn't need. Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> Cc: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/nilfs2/inode.c32
-rw-r--r--fs/nilfs2/namei.c15
2 files changed, 36 insertions, 11 deletions
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c
index e1fa69b341b9..8b5969538f39 100644
--- a/fs/nilfs2/inode.c
+++ b/fs/nilfs2/inode.c
@@ -49,6 +49,8 @@ struct nilfs_iget_args {
49 int for_gc; 49 int for_gc;
50}; 50};
51 51
52static int nilfs_iget_test(struct inode *inode, void *opaque);
53
52void nilfs_inode_add_blocks(struct inode *inode, int n) 54void nilfs_inode_add_blocks(struct inode *inode, int n)
53{ 55{
54 struct nilfs_root *root = NILFS_I(inode)->i_root; 56 struct nilfs_root *root = NILFS_I(inode)->i_root;
@@ -348,6 +350,17 @@ const struct address_space_operations nilfs_aops = {
348 .is_partially_uptodate = block_is_partially_uptodate, 350 .is_partially_uptodate = block_is_partially_uptodate,
349}; 351};
350 352
353static int nilfs_insert_inode_locked(struct inode *inode,
354 struct nilfs_root *root,
355 unsigned long ino)
356{
357 struct nilfs_iget_args args = {
358 .ino = ino, .root = root, .cno = 0, .for_gc = 0
359 };
360
361 return insert_inode_locked4(inode, ino, nilfs_iget_test, &args);
362}
363
351struct inode *nilfs_new_inode(struct inode *dir, umode_t mode) 364struct inode *nilfs_new_inode(struct inode *dir, umode_t mode)
352{ 365{
353 struct super_block *sb = dir->i_sb; 366 struct super_block *sb = dir->i_sb;
@@ -383,7 +396,7 @@ struct inode *nilfs_new_inode(struct inode *dir, umode_t mode)
383 if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) { 396 if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) {
384 err = nilfs_bmap_read(ii->i_bmap, NULL); 397 err = nilfs_bmap_read(ii->i_bmap, NULL);
385 if (err < 0) 398 if (err < 0)
386 goto failed_bmap; 399 goto failed_after_creation;
387 400
388 set_bit(NILFS_I_BMAP, &ii->i_state); 401 set_bit(NILFS_I_BMAP, &ii->i_state);
389 /* No lock is needed; iget() ensures it. */ 402 /* No lock is needed; iget() ensures it. */
@@ -399,21 +412,24 @@ struct inode *nilfs_new_inode(struct inode *dir, umode_t mode)
399 spin_lock(&nilfs->ns_next_gen_lock); 412 spin_lock(&nilfs->ns_next_gen_lock);
400 inode->i_generation = nilfs->ns_next_generation++; 413 inode->i_generation = nilfs->ns_next_generation++;
401 spin_unlock(&nilfs->ns_next_gen_lock); 414 spin_unlock(&nilfs->ns_next_gen_lock);
402 insert_inode_hash(inode); 415 if (nilfs_insert_inode_locked(inode, root, ino) < 0) {
416 err = -EIO;
417 goto failed_after_creation;
418 }
403 419
404 err = nilfs_init_acl(inode, dir); 420 err = nilfs_init_acl(inode, dir);
405 if (unlikely(err)) 421 if (unlikely(err))
406 goto failed_acl; /* never occur. When supporting 422 goto failed_after_creation; /* never occur. When supporting
407 nilfs_init_acl(), proper cancellation of 423 nilfs_init_acl(), proper cancellation of
408 above jobs should be considered */ 424 above jobs should be considered */
409 425
410 return inode; 426 return inode;
411 427
412 failed_acl: 428 failed_after_creation:
413 failed_bmap:
414 clear_nlink(inode); 429 clear_nlink(inode);
430 unlock_new_inode(inode);
415 iput(inode); /* raw_inode will be deleted through 431 iput(inode); /* raw_inode will be deleted through
416 generic_delete_inode() */ 432 nilfs_evict_inode() */
417 goto failed; 433 goto failed;
418 434
419 failed_ifile_create_inode: 435 failed_ifile_create_inode:
@@ -461,8 +477,8 @@ int nilfs_read_inode_common(struct inode *inode,
461 inode->i_atime.tv_nsec = le32_to_cpu(raw_inode->i_mtime_nsec); 477 inode->i_atime.tv_nsec = le32_to_cpu(raw_inode->i_mtime_nsec);
462 inode->i_ctime.tv_nsec = le32_to_cpu(raw_inode->i_ctime_nsec); 478 inode->i_ctime.tv_nsec = le32_to_cpu(raw_inode->i_ctime_nsec);
463 inode->i_mtime.tv_nsec = le32_to_cpu(raw_inode->i_mtime_nsec); 479 inode->i_mtime.tv_nsec = le32_to_cpu(raw_inode->i_mtime_nsec);
464 if (inode->i_nlink == 0 && inode->i_mode == 0) 480 if (inode->i_nlink == 0)
465 return -EINVAL; /* this inode is deleted */ 481 return -ESTALE; /* this inode is deleted */
466 482
467 inode->i_blocks = le64_to_cpu(raw_inode->i_blocks); 483 inode->i_blocks = le64_to_cpu(raw_inode->i_blocks);
468 ii->i_flags = le32_to_cpu(raw_inode->i_flags); 484 ii->i_flags = le32_to_cpu(raw_inode->i_flags);
diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c
index 9de78f08989e..0f84b257932c 100644
--- a/fs/nilfs2/namei.c
+++ b/fs/nilfs2/namei.c
@@ -51,9 +51,11 @@ static inline int nilfs_add_nondir(struct dentry *dentry, struct inode *inode)
51 int err = nilfs_add_link(dentry, inode); 51 int err = nilfs_add_link(dentry, inode);
52 if (!err) { 52 if (!err) {
53 d_instantiate(dentry, inode); 53 d_instantiate(dentry, inode);
54 unlock_new_inode(inode);
54 return 0; 55 return 0;
55 } 56 }
56 inode_dec_link_count(inode); 57 inode_dec_link_count(inode);
58 unlock_new_inode(inode);
57 iput(inode); 59 iput(inode);
58 return err; 60 return err;
59} 61}
@@ -182,6 +184,7 @@ out:
182out_fail: 184out_fail:
183 drop_nlink(inode); 185 drop_nlink(inode);
184 nilfs_mark_inode_dirty(inode); 186 nilfs_mark_inode_dirty(inode);
187 unlock_new_inode(inode);
185 iput(inode); 188 iput(inode);
186 goto out; 189 goto out;
187} 190}
@@ -201,11 +204,15 @@ static int nilfs_link(struct dentry *old_dentry, struct inode *dir,
201 inode_inc_link_count(inode); 204 inode_inc_link_count(inode);
202 ihold(inode); 205 ihold(inode);
203 206
204 err = nilfs_add_nondir(dentry, inode); 207 err = nilfs_add_link(dentry, inode);
205 if (!err) 208 if (!err) {
209 d_instantiate(dentry, inode);
206 err = nilfs_transaction_commit(dir->i_sb); 210 err = nilfs_transaction_commit(dir->i_sb);
207 else 211 } else {
212 inode_dec_link_count(inode);
213 iput(inode);
208 nilfs_transaction_abort(dir->i_sb); 214 nilfs_transaction_abort(dir->i_sb);
215 }
209 216
210 return err; 217 return err;
211} 218}
@@ -243,6 +250,7 @@ static int nilfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
243 250
244 nilfs_mark_inode_dirty(inode); 251 nilfs_mark_inode_dirty(inode);
245 d_instantiate(dentry, inode); 252 d_instantiate(dentry, inode);
253 unlock_new_inode(inode);
246out: 254out:
247 if (!err) 255 if (!err)
248 err = nilfs_transaction_commit(dir->i_sb); 256 err = nilfs_transaction_commit(dir->i_sb);
@@ -255,6 +263,7 @@ out_fail:
255 drop_nlink(inode); 263 drop_nlink(inode);
256 drop_nlink(inode); 264 drop_nlink(inode);
257 nilfs_mark_inode_dirty(inode); 265 nilfs_mark_inode_dirty(inode);
266 unlock_new_inode(inode);
258 iput(inode); 267 iput(inode);
259out_dir: 268out_dir:
260 drop_nlink(dir); 269 drop_nlink(dir);