diff options
author | David Woodhouse <David.Woodhouse@intel.com> | 2010-06-03 03:09:12 -0400 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2010-06-03 03:22:04 -0400 |
commit | e72e6497e74811e01d72b4c1b7537b3aea3ee857 (patch) | |
tree | d78dec67d0aaeea807e5ab32141802620ec7ae41 /fs/jffs2 | |
parent | f324e4cb2cadd9a42932c8a158e761ae31b88e72 (diff) |
jffs2: Fix NFS race by using insert_inode_locked()
New inodes need to be locked as we're creating them, so they don't get used
by other things (like NFSd) before they're ready.
Pointed out by Al Viro.
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'fs/jffs2')
-rw-r--r-- | fs/jffs2/dir.c | 12 | ||||
-rw-r--r-- | fs/jffs2/fs.c | 7 |
2 files changed, 16 insertions, 3 deletions
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index cb7ef34d384c..166062a68230 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c | |||
@@ -222,15 +222,18 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode, | |||
222 | dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(ri->ctime)); | 222 | dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(ri->ctime)); |
223 | 223 | ||
224 | jffs2_free_raw_inode(ri); | 224 | jffs2_free_raw_inode(ri); |
225 | d_instantiate(dentry, inode); | ||
226 | 225 | ||
227 | D1(printk(KERN_DEBUG "jffs2_create: Created ino #%lu with mode %o, nlink %d(%d). nrpages %ld\n", | 226 | D1(printk(KERN_DEBUG "jffs2_create: Created ino #%lu with mode %o, nlink %d(%d). nrpages %ld\n", |
228 | inode->i_ino, inode->i_mode, inode->i_nlink, | 227 | inode->i_ino, inode->i_mode, inode->i_nlink, |
229 | f->inocache->pino_nlink, inode->i_mapping->nrpages)); | 228 | f->inocache->pino_nlink, inode->i_mapping->nrpages)); |
229 | |||
230 | d_instantiate(dentry, inode); | ||
231 | unlock_new_inode(inode); | ||
230 | return 0; | 232 | return 0; |
231 | 233 | ||
232 | fail: | 234 | fail: |
233 | make_bad_inode(inode); | 235 | make_bad_inode(inode); |
236 | unlock_new_inode(inode); | ||
234 | iput(inode); | 237 | iput(inode); |
235 | jffs2_free_raw_inode(ri); | 238 | jffs2_free_raw_inode(ri); |
236 | return ret; | 239 | return ret; |
@@ -447,10 +450,12 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char | |||
447 | jffs2_complete_reservation(c); | 450 | jffs2_complete_reservation(c); |
448 | 451 | ||
449 | d_instantiate(dentry, inode); | 452 | d_instantiate(dentry, inode); |
453 | unlock_new_inode(inode); | ||
450 | return 0; | 454 | return 0; |
451 | 455 | ||
452 | fail: | 456 | fail: |
453 | make_bad_inode(inode); | 457 | make_bad_inode(inode); |
458 | unlock_new_inode(inode); | ||
454 | iput(inode); | 459 | iput(inode); |
455 | return ret; | 460 | return ret; |
456 | } | 461 | } |
@@ -592,10 +597,12 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) | |||
592 | jffs2_complete_reservation(c); | 597 | jffs2_complete_reservation(c); |
593 | 598 | ||
594 | d_instantiate(dentry, inode); | 599 | d_instantiate(dentry, inode); |
600 | unlock_new_inode(inode); | ||
595 | return 0; | 601 | return 0; |
596 | 602 | ||
597 | fail: | 603 | fail: |
598 | make_bad_inode(inode); | 604 | make_bad_inode(inode); |
605 | unlock_new_inode(inode); | ||
599 | iput(inode); | 606 | iput(inode); |
600 | return ret; | 607 | return ret; |
601 | } | 608 | } |
@@ -767,11 +774,12 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de | |||
767 | jffs2_complete_reservation(c); | 774 | jffs2_complete_reservation(c); |
768 | 775 | ||
769 | d_instantiate(dentry, inode); | 776 | d_instantiate(dentry, inode); |
770 | 777 | unlock_new_inode(inode); | |
771 | return 0; | 778 | return 0; |
772 | 779 | ||
773 | fail: | 780 | fail: |
774 | make_bad_inode(inode); | 781 | make_bad_inode(inode); |
782 | unlock_new_inode(inode); | ||
775 | iput(inode); | 783 | iput(inode); |
776 | return ret; | 784 | return ret; |
777 | } | 785 | } |
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index 86e0821fc989..26037e2d6154 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c | |||
@@ -465,7 +465,12 @@ struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_i | |||
465 | inode->i_blocks = 0; | 465 | inode->i_blocks = 0; |
466 | inode->i_size = 0; | 466 | inode->i_size = 0; |
467 | 467 | ||
468 | insert_inode_hash(inode); | 468 | if (insert_inode_locked(inode) < 0) { |
469 | make_bad_inode(inode); | ||
470 | unlock_new_inode(inode); | ||
471 | iput(inode); | ||
472 | return ERR_PTR(-EINVAL); | ||
473 | } | ||
469 | 474 | ||
470 | return inode; | 475 | return inode; |
471 | } | 476 | } |