aboutsummaryrefslogtreecommitdiffstats
path: root/fs/hpfs
diff options
context:
space:
mode:
authorMikulas Patocka <mikulas@artax.karlin.mff.cuni.cz>2011-05-08 14:42:54 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-05-09 12:04:23 -0400
commit7dd29d8d865efdb00c0542a5d2c87af8c52ea6c7 (patch)
tree71f404ed317e2d1b689af088ece1c32c3b1535c8 /fs/hpfs
parent637b424bf8747e50bab6648ab919632d6efd6c28 (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/hpfs')
-rw-r--r--fs/hpfs/buffer.c8
-rw-r--r--fs/hpfs/file.c27
-rw-r--r--fs/hpfs/hpfs_fn.h24
-rw-r--r--fs/hpfs/super.c10
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)
48static void hpfs_truncate(struct inode *i) 48static 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
61static int hpfs_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create) 61static 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
85static int hpfs_writepage(struct page *page, struct writeback_control *wbc) 93static 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
65struct hpfs_sb_info { 65struct 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 */
360static inline void hpfs_lock(struct super_block *s) 356static 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
364static inline void hpfs_unlock(struct super_block *s) 362static 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
368static 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
674bail4: brelse(bh2); 681bail4: brelse(bh2);
@@ -676,6 +683,7 @@ bail3: brelse(bh1);
676bail2: brelse(bh0); 683bail2: brelse(bh0);
677bail1: 684bail1:
678bail0: 685bail0:
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;