aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorOGAWA Hirofumi <hirofumi@mail.parknet.co.jp>2008-11-06 15:53:57 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2008-11-06 18:41:21 -0500
commit9ca59f4c3d28df14a1545a1e2832f34a0a50e3ed (patch)
tree4a9d307e2a3541765cf194f27d873c6d06e5d960 /fs
parent2bdf67eb1631f30e2f3f5d49e4007c76e88877a8 (diff)
fat: ->i_pos race fix
i_pos is 64bits value, hence it's not atomic to update. Important place is fat_write_inode() only, other places without lock are just for printk(). This adds lock for "BITS_PER_LONG == 32" kernel. Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> 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/fat/inode.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 9e37ad93c730..bdd8fb7be2ca 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -542,6 +542,20 @@ static int fat_statfs(struct dentry *dentry, struct kstatfs *buf)
542 return 0; 542 return 0;
543} 543}
544 544
545static inline loff_t fat_i_pos_read(struct msdos_sb_info *sbi,
546 struct inode *inode)
547{
548 loff_t i_pos;
549#if BITS_PER_LONG == 32
550 spin_lock(&sbi->inode_hash_lock);
551#endif
552 i_pos = MSDOS_I(inode)->i_pos;
553#if BITS_PER_LONG == 32
554 spin_unlock(&sbi->inode_hash_lock);
555#endif
556 return i_pos;
557}
558
545static int fat_write_inode(struct inode *inode, int wait) 559static int fat_write_inode(struct inode *inode, int wait)
546{ 560{
547 struct super_block *sb = inode->i_sb; 561 struct super_block *sb = inode->i_sb;
@@ -551,9 +565,12 @@ static int fat_write_inode(struct inode *inode, int wait)
551 loff_t i_pos; 565 loff_t i_pos;
552 int err; 566 int err;
553 567
568 if (inode->i_ino == MSDOS_ROOT_INO)
569 return 0;
570
554retry: 571retry:
555 i_pos = MSDOS_I(inode)->i_pos; 572 i_pos = fat_i_pos_read(sbi, inode);
556 if (inode->i_ino == MSDOS_ROOT_INO || !i_pos) 573 if (!i_pos)
557 return 0; 574 return 0;
558 575
559 bh = sb_bread(sb, i_pos >> sbi->dir_per_block_bits); 576 bh = sb_bread(sb, i_pos >> sbi->dir_per_block_bits);