diff options
author | Mikulas Patocka <mikulas@artax.karlin.mff.cuni.cz> | 2011-05-08 14:42:54 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-09 12:04:23 -0400 |
commit | 7dd29d8d865efdb00c0542a5d2c87af8c52ea6c7 (patch) | |
tree | 71f404ed317e2d1b689af088ece1c32c3b1535c8 /fs | |
parent | 637b424bf8747e50bab6648ab919632d6efd6c28 (diff) |
HPFS: Introduce a global mutex and lock it on every callback from VFS.
Introduce a global mutex and lock it on every callback from VFS.
Performance doesn't matter, reviewing the whole code for locking correctness
would be too complicated, so simply lock it all.
Signed-off-by: Mikulas Patocka <mikulas@artax.karlin.mff.cuni.cz>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/hpfs/buffer.c | 8 | ||||
-rw-r--r-- | fs/hpfs/file.c | 27 | ||||
-rw-r--r-- | fs/hpfs/hpfs_fn.h | 24 | ||||
-rw-r--r-- | fs/hpfs/super.c | 10 |
4 files changed, 51 insertions, 18 deletions
diff --git a/fs/hpfs/buffer.c b/fs/hpfs/buffer.c index 793cb9d943d2..7cef5d5c3608 100644 --- a/fs/hpfs/buffer.c +++ b/fs/hpfs/buffer.c | |||
@@ -32,6 +32,8 @@ void *hpfs_map_sector(struct super_block *s, unsigned secno, struct buffer_head | |||
32 | { | 32 | { |
33 | struct buffer_head *bh; | 33 | struct buffer_head *bh; |
34 | 34 | ||
35 | hpfs_lock_assert(s); | ||
36 | |||
35 | cond_resched(); | 37 | cond_resched(); |
36 | 38 | ||
37 | *bhp = bh = sb_bread(s, secno); | 39 | *bhp = bh = sb_bread(s, secno); |
@@ -50,6 +52,8 @@ void *hpfs_get_sector(struct super_block *s, unsigned secno, struct buffer_head | |||
50 | struct buffer_head *bh; | 52 | struct buffer_head *bh; |
51 | /*return hpfs_map_sector(s, secno, bhp, 0);*/ | 53 | /*return hpfs_map_sector(s, secno, bhp, 0);*/ |
52 | 54 | ||
55 | hpfs_lock_assert(s); | ||
56 | |||
53 | cond_resched(); | 57 | cond_resched(); |
54 | 58 | ||
55 | if ((*bhp = bh = sb_getblk(s, secno)) != NULL) { | 59 | if ((*bhp = bh = sb_getblk(s, secno)) != NULL) { |
@@ -70,6 +74,8 @@ void *hpfs_map_4sectors(struct super_block *s, unsigned secno, struct quad_buffe | |||
70 | struct buffer_head *bh; | 74 | struct buffer_head *bh; |
71 | char *data; | 75 | char *data; |
72 | 76 | ||
77 | hpfs_lock_assert(s); | ||
78 | |||
73 | cond_resched(); | 79 | cond_resched(); |
74 | 80 | ||
75 | if (secno & 3) { | 81 | if (secno & 3) { |
@@ -125,6 +131,8 @@ void *hpfs_get_4sectors(struct super_block *s, unsigned secno, | |||
125 | { | 131 | { |
126 | cond_resched(); | 132 | cond_resched(); |
127 | 133 | ||
134 | hpfs_lock_assert(s); | ||
135 | |||
128 | if (secno & 3) { | 136 | if (secno & 3) { |
129 | printk("HPFS: hpfs_get_4sectors: unaligned read\n"); | 137 | printk("HPFS: hpfs_get_4sectors: unaligned read\n"); |
130 | return NULL; | 138 | return NULL; |
diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c index 9b9eb6933e43..09a642f853e1 100644 --- a/fs/hpfs/file.c +++ b/fs/hpfs/file.c | |||
@@ -48,38 +48,46 @@ static secno hpfs_bmap(struct inode *inode, unsigned file_secno) | |||
48 | static void hpfs_truncate(struct inode *i) | 48 | static void hpfs_truncate(struct inode *i) |
49 | { | 49 | { |
50 | if (IS_IMMUTABLE(i)) return /*-EPERM*/; | 50 | if (IS_IMMUTABLE(i)) return /*-EPERM*/; |
51 | hpfs_lock(i->i_sb); | 51 | hpfs_lock_assert(i->i_sb); |
52 | |||
52 | hpfs_i(i)->i_n_secs = 0; | 53 | hpfs_i(i)->i_n_secs = 0; |
53 | i->i_blocks = 1 + ((i->i_size + 511) >> 9); | 54 | i->i_blocks = 1 + ((i->i_size + 511) >> 9); |
54 | hpfs_i(i)->mmu_private = i->i_size; | 55 | hpfs_i(i)->mmu_private = i->i_size; |
55 | hpfs_truncate_btree(i->i_sb, i->i_ino, 1, ((i->i_size + 511) >> 9)); | 56 | hpfs_truncate_btree(i->i_sb, i->i_ino, 1, ((i->i_size + 511) >> 9)); |
56 | hpfs_write_inode(i); | 57 | hpfs_write_inode(i); |
57 | hpfs_i(i)->i_n_secs = 0; | 58 | hpfs_i(i)->i_n_secs = 0; |
58 | hpfs_unlock(i->i_sb); | ||
59 | } | 59 | } |
60 | 60 | ||
61 | static int hpfs_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create) | 61 | static int hpfs_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create) |
62 | { | 62 | { |
63 | int r; | ||
63 | secno s; | 64 | secno s; |
65 | hpfs_lock(inode->i_sb); | ||
64 | s = hpfs_bmap(inode, iblock); | 66 | s = hpfs_bmap(inode, iblock); |
65 | if (s) { | 67 | if (s) { |
66 | map_bh(bh_result, inode->i_sb, s); | 68 | map_bh(bh_result, inode->i_sb, s); |
67 | return 0; | 69 | goto ret_0; |
68 | } | 70 | } |
69 | if (!create) return 0; | 71 | if (!create) goto ret_0; |
70 | if (iblock<<9 != hpfs_i(inode)->mmu_private) { | 72 | if (iblock<<9 != hpfs_i(inode)->mmu_private) { |
71 | BUG(); | 73 | BUG(); |
72 | return -EIO; | 74 | r = -EIO; |
75 | goto ret_r; | ||
73 | } | 76 | } |
74 | if ((s = hpfs_add_sector_to_btree(inode->i_sb, inode->i_ino, 1, inode->i_blocks - 1)) == -1) { | 77 | if ((s = hpfs_add_sector_to_btree(inode->i_sb, inode->i_ino, 1, inode->i_blocks - 1)) == -1) { |
75 | hpfs_truncate_btree(inode->i_sb, inode->i_ino, 1, inode->i_blocks - 1); | 78 | hpfs_truncate_btree(inode->i_sb, inode->i_ino, 1, inode->i_blocks - 1); |
76 | return -ENOSPC; | 79 | r = -ENOSPC; |
80 | goto ret_r; | ||
77 | } | 81 | } |
78 | inode->i_blocks++; | 82 | inode->i_blocks++; |
79 | hpfs_i(inode)->mmu_private += 512; | 83 | hpfs_i(inode)->mmu_private += 512; |
80 | set_buffer_new(bh_result); | 84 | set_buffer_new(bh_result); |
81 | map_bh(bh_result, inode->i_sb, s); | 85 | map_bh(bh_result, inode->i_sb, s); |
82 | return 0; | 86 | ret_0: |
87 | r = 0; | ||
88 | ret_r: | ||
89 | hpfs_unlock(inode->i_sb); | ||
90 | return r; | ||
83 | } | 91 | } |
84 | 92 | ||
85 | static int hpfs_writepage(struct page *page, struct writeback_control *wbc) | 93 | static int hpfs_writepage(struct page *page, struct writeback_control *wbc) |
@@ -130,8 +138,11 @@ static ssize_t hpfs_file_write(struct file *file, const char __user *buf, | |||
130 | ssize_t retval; | 138 | ssize_t retval; |
131 | 139 | ||
132 | retval = do_sync_write(file, buf, count, ppos); | 140 | retval = do_sync_write(file, buf, count, ppos); |
133 | if (retval > 0) | 141 | if (retval > 0) { |
142 | hpfs_lock(file->f_path.dentry->d_sb); | ||
134 | hpfs_i(file->f_path.dentry->d_inode)->i_dirty = 1; | 143 | hpfs_i(file->f_path.dentry->d_inode)->i_dirty = 1; |
144 | hpfs_unlock(file->f_path.dentry->d_sb); | ||
145 | } | ||
135 | return retval; | 146 | return retval; |
136 | } | 147 | } |
137 | 148 | ||
diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h index c15adbca07ff..89a4714b44c7 100644 --- a/fs/hpfs/hpfs_fn.h +++ b/fs/hpfs/hpfs_fn.h | |||
@@ -63,6 +63,7 @@ struct hpfs_inode_info { | |||
63 | }; | 63 | }; |
64 | 64 | ||
65 | struct hpfs_sb_info { | 65 | struct hpfs_sb_info { |
66 | struct mutex hpfs_mutex; /* global hpfs lock */ | ||
66 | ino_t sb_root; /* inode number of root dir */ | 67 | ino_t sb_root; /* inode number of root dir */ |
67 | unsigned sb_fs_size; /* file system size, sectors */ | 68 | unsigned sb_fs_size; /* file system size, sectors */ |
68 | unsigned sb_bitmaps; /* sector number of bitmap list */ | 69 | unsigned sb_bitmaps; /* sector number of bitmap list */ |
@@ -346,21 +347,26 @@ static inline time32_t gmt_to_local(struct super_block *s, time_t t) | |||
346 | /* | 347 | /* |
347 | * Locking: | 348 | * Locking: |
348 | * | 349 | * |
349 | * hpfs_lock() is a leftover from the big kernel lock. | 350 | * hpfs_lock() locks the whole filesystem. It must be taken |
350 | * Right now, these functions are empty and only left | 351 | * on any method called by the VFS. |
351 | * for documentation purposes. The file system no longer | ||
352 | * works on SMP systems, so the lock is not needed | ||
353 | * any more. | ||
354 | * | 352 | * |
355 | * If someone is interested in making it work again, this | 353 | * We don't do any per-file locking anymore, it is hard to |
356 | * would be the place to start by adding a per-superblock | 354 | * review and HPFS is not performance-sensitive anyway. |
357 | * mutex and fixing all the bugs and performance issues | ||
358 | * caused by that. | ||
359 | */ | 355 | */ |
360 | static inline void hpfs_lock(struct super_block *s) | 356 | static inline void hpfs_lock(struct super_block *s) |
361 | { | 357 | { |
358 | struct hpfs_sb_info *sbi = hpfs_sb(s); | ||
359 | mutex_lock(&sbi->hpfs_mutex); | ||
362 | } | 360 | } |
363 | 361 | ||
364 | static inline void hpfs_unlock(struct super_block *s) | 362 | static inline void hpfs_unlock(struct super_block *s) |
365 | { | 363 | { |
364 | struct hpfs_sb_info *sbi = hpfs_sb(s); | ||
365 | mutex_unlock(&sbi->hpfs_mutex); | ||
366 | } | ||
367 | |||
368 | static inline void hpfs_lock_assert(struct super_block *s) | ||
369 | { | ||
370 | struct hpfs_sb_info *sbi = hpfs_sb(s); | ||
371 | WARN_ON(!mutex_is_locked(&sbi->hpfs_mutex)); | ||
366 | } | 372 | } |
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c index 501ea86e40a4..41232c2d60dc 100644 --- a/fs/hpfs/super.c +++ b/fs/hpfs/super.c | |||
@@ -102,9 +102,12 @@ static void hpfs_put_super(struct super_block *s) | |||
102 | { | 102 | { |
103 | struct hpfs_sb_info *sbi = hpfs_sb(s); | 103 | struct hpfs_sb_info *sbi = hpfs_sb(s); |
104 | 104 | ||
105 | hpfs_lock(s); | ||
106 | unmark_dirty(s); | ||
107 | hpfs_unlock(s); | ||
108 | |||
105 | kfree(sbi->sb_cp_table); | 109 | kfree(sbi->sb_cp_table); |
106 | kfree(sbi->sb_bmp_dir); | 110 | kfree(sbi->sb_bmp_dir); |
107 | unmark_dirty(s); | ||
108 | s->s_fs_info = NULL; | 111 | s->s_fs_info = NULL; |
109 | kfree(sbi); | 112 | kfree(sbi); |
110 | } | 113 | } |
@@ -490,6 +493,9 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent) | |||
490 | sbi->sb_bmp_dir = NULL; | 493 | sbi->sb_bmp_dir = NULL; |
491 | sbi->sb_cp_table = NULL; | 494 | sbi->sb_cp_table = NULL; |
492 | 495 | ||
496 | mutex_init(&sbi->hpfs_mutex); | ||
497 | hpfs_lock(s); | ||
498 | |||
493 | mutex_init(&sbi->hpfs_creation_de); | 499 | mutex_init(&sbi->hpfs_creation_de); |
494 | 500 | ||
495 | uid = current_uid(); | 501 | uid = current_uid(); |
@@ -669,6 +675,7 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent) | |||
669 | root->i_blocks = 5; | 675 | root->i_blocks = 5; |
670 | hpfs_brelse4(&qbh); | 676 | hpfs_brelse4(&qbh); |
671 | } | 677 | } |
678 | hpfs_unlock(s); | ||
672 | return 0; | 679 | return 0; |
673 | 680 | ||
674 | bail4: brelse(bh2); | 681 | bail4: brelse(bh2); |
@@ -676,6 +683,7 @@ bail3: brelse(bh1); | |||
676 | bail2: brelse(bh0); | 683 | bail2: brelse(bh0); |
677 | bail1: | 684 | bail1: |
678 | bail0: | 685 | bail0: |
686 | hpfs_unlock(s); | ||
679 | kfree(sbi->sb_bmp_dir); | 687 | kfree(sbi->sb_bmp_dir); |
680 | kfree(sbi->sb_cp_table); | 688 | kfree(sbi->sb_cp_table); |
681 | s->s_fs_info = NULL; | 689 | s->s_fs_info = NULL; |