diff options
author | OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> | 2008-11-06 15:53:57 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-11-06 18:41:21 -0500 |
commit | 9ca59f4c3d28df14a1545a1e2832f34a0a50e3ed (patch) | |
tree | 4a9d307e2a3541765cf194f27d873c6d06e5d960 /fs/fat | |
parent | 2bdf67eb1631f30e2f3f5d49e4007c76e88877a8 (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/fat')
-rw-r--r-- | fs/fat/inode.c | 21 |
1 files changed, 19 insertions, 2 deletions
diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 9e37ad93c73..bdd8fb7be2c 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 | ||
545 | static 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 | |||
545 | static int fat_write_inode(struct inode *inode, int wait) | 559 | static 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 | |||
554 | retry: | 571 | retry: |
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); |