Commit 788257d6101d986ac8f2741aaa35974af47f574c
1 parent
9a311b96c3
Exists in
master
and in
39 other branches
ufs: remove the BKL
This introduces a new per-superblock mutex in UFS to replace the big kernel lock. I have been careful to avoid nested calls to lock_ufs and to get the lock order right with respect to other mutexes, in particular lock_super. I did not make any attempt to prove that the big kernel lock is not needed in a particular place in the code, which is very possible. The mutex has a significant performance impact, so it is only used on SMP or PREEMPT configurations. As Nick Piggin noticed, any allocation inside of the lock may end up deadlocking when we get to ufs_getfrag_block in the reclaim task, so we now use GFP_NOFS. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Tested-by: Nick Bowler <nbowler@elliptictech.com> Cc: Evgeniy Dushistov <dushistov@mail.ru> Cc: Nick Piggin <npiggin@gmail.com>
Showing 7 changed files with 83 additions and 108 deletions Side-by-side Diff
fs/ufs/Kconfig
fs/ufs/inode.c
... | ... | @@ -34,7 +34,6 @@ |
34 | 34 | #include <linux/stat.h> |
35 | 35 | #include <linux/string.h> |
36 | 36 | #include <linux/mm.h> |
37 | -#include <linux/smp_lock.h> | |
38 | 37 | #include <linux/buffer_head.h> |
39 | 38 | #include <linux/writeback.h> |
40 | 39 | |
... | ... | @@ -43,7 +42,7 @@ |
43 | 42 | #include "swab.h" |
44 | 43 | #include "util.h" |
45 | 44 | |
46 | -static u64 ufs_frag_map(struct inode *inode, sector_t frag); | |
45 | +static u64 ufs_frag_map(struct inode *inode, sector_t frag, bool needs_lock); | |
47 | 46 | |
48 | 47 | static int ufs_block_to_path(struct inode *inode, sector_t i_block, sector_t offsets[4]) |
49 | 48 | { |
... | ... | @@ -82,7 +81,7 @@ |
82 | 81 | * the begining of the filesystem. |
83 | 82 | */ |
84 | 83 | |
85 | -static u64 ufs_frag_map(struct inode *inode, sector_t frag) | |
84 | +static u64 ufs_frag_map(struct inode *inode, sector_t frag, bool needs_lock) | |
86 | 85 | { |
87 | 86 | struct ufs_inode_info *ufsi = UFS_I(inode); |
88 | 87 | struct super_block *sb = inode->i_sb; |
... | ... | @@ -107,7 +106,8 @@ |
107 | 106 | |
108 | 107 | p = offsets; |
109 | 108 | |
110 | - lock_kernel(); | |
109 | + if (needs_lock) | |
110 | + lock_ufs(sb); | |
111 | 111 | if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) |
112 | 112 | goto ufs2; |
113 | 113 | |
... | ... | @@ -152,7 +152,8 @@ |
152 | 152 | ret = temp + (u64) (frag & uspi->s_fpbmask); |
153 | 153 | |
154 | 154 | out: |
155 | - unlock_kernel(); | |
155 | + if (needs_lock) | |
156 | + unlock_ufs(sb); | |
156 | 157 | return ret; |
157 | 158 | } |
158 | 159 | |
159 | 160 | |
160 | 161 | |
... | ... | @@ -415,14 +416,16 @@ |
415 | 416 | int ufs_getfrag_block(struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create) |
416 | 417 | { |
417 | 418 | struct super_block * sb = inode->i_sb; |
418 | - struct ufs_sb_private_info * uspi = UFS_SB(sb)->s_uspi; | |
419 | + struct ufs_sb_info * sbi = UFS_SB(sb); | |
420 | + struct ufs_sb_private_info * uspi = sbi->s_uspi; | |
419 | 421 | struct buffer_head * bh; |
420 | 422 | int ret, err, new; |
421 | 423 | unsigned long ptr,phys; |
422 | 424 | u64 phys64 = 0; |
425 | + bool needs_lock = (sbi->mutex_owner != current); | |
423 | 426 | |
424 | 427 | if (!create) { |
425 | - phys64 = ufs_frag_map(inode, fragment); | |
428 | + phys64 = ufs_frag_map(inode, fragment, needs_lock); | |
426 | 429 | UFSD("phys64 = %llu\n", (unsigned long long)phys64); |
427 | 430 | if (phys64) |
428 | 431 | map_bh(bh_result, sb, phys64); |
... | ... | @@ -436,7 +439,8 @@ |
436 | 439 | ret = 0; |
437 | 440 | bh = NULL; |
438 | 441 | |
439 | - lock_kernel(); | |
442 | + if (needs_lock) | |
443 | + lock_ufs(sb); | |
440 | 444 | |
441 | 445 | UFSD("ENTER, ino %lu, fragment %llu\n", inode->i_ino, (unsigned long long)fragment); |
442 | 446 | if (fragment > |
... | ... | @@ -498,7 +502,9 @@ |
498 | 502 | set_buffer_new(bh_result); |
499 | 503 | map_bh(bh_result, sb, phys); |
500 | 504 | abort: |
501 | - unlock_kernel(); | |
505 | + if (needs_lock) | |
506 | + unlock_ufs(sb); | |
507 | + | |
502 | 508 | return err; |
503 | 509 | |
504 | 510 | abort_too_big: |
... | ... | @@ -506,48 +512,6 @@ |
506 | 512 | goto abort; |
507 | 513 | } |
508 | 514 | |
509 | -static struct buffer_head *ufs_getfrag(struct inode *inode, | |
510 | - unsigned int fragment, | |
511 | - int create, int *err) | |
512 | -{ | |
513 | - struct buffer_head dummy; | |
514 | - int error; | |
515 | - | |
516 | - dummy.b_state = 0; | |
517 | - dummy.b_blocknr = -1000; | |
518 | - error = ufs_getfrag_block(inode, fragment, &dummy, create); | |
519 | - *err = error; | |
520 | - if (!error && buffer_mapped(&dummy)) { | |
521 | - struct buffer_head *bh; | |
522 | - bh = sb_getblk(inode->i_sb, dummy.b_blocknr); | |
523 | - if (buffer_new(&dummy)) { | |
524 | - memset(bh->b_data, 0, inode->i_sb->s_blocksize); | |
525 | - set_buffer_uptodate(bh); | |
526 | - mark_buffer_dirty(bh); | |
527 | - } | |
528 | - return bh; | |
529 | - } | |
530 | - return NULL; | |
531 | -} | |
532 | - | |
533 | -struct buffer_head * ufs_bread (struct inode * inode, unsigned fragment, | |
534 | - int create, int * err) | |
535 | -{ | |
536 | - struct buffer_head * bh; | |
537 | - | |
538 | - UFSD("ENTER, ino %lu, fragment %u\n", inode->i_ino, fragment); | |
539 | - bh = ufs_getfrag (inode, fragment, create, err); | |
540 | - if (!bh || buffer_uptodate(bh)) | |
541 | - return bh; | |
542 | - ll_rw_block (READ, 1, &bh); | |
543 | - wait_on_buffer (bh); | |
544 | - if (buffer_uptodate(bh)) | |
545 | - return bh; | |
546 | - brelse (bh); | |
547 | - *err = -EIO; | |
548 | - return NULL; | |
549 | -} | |
550 | - | |
551 | 515 | static int ufs_writepage(struct page *page, struct writeback_control *wbc) |
552 | 516 | { |
553 | 517 | return block_write_full_page(page,ufs_getfrag_block,wbc); |
554 | 518 | |
... | ... | @@ -900,9 +864,9 @@ |
900 | 864 | int ufs_write_inode(struct inode *inode, struct writeback_control *wbc) |
901 | 865 | { |
902 | 866 | int ret; |
903 | - lock_kernel(); | |
867 | + lock_ufs(inode->i_sb); | |
904 | 868 | ret = ufs_update_inode(inode, wbc->sync_mode == WB_SYNC_ALL); |
905 | - unlock_kernel(); | |
869 | + unlock_ufs(inode->i_sb); | |
906 | 870 | return ret; |
907 | 871 | } |
908 | 872 | |
909 | 873 | |
910 | 874 | |
911 | 875 | |
... | ... | @@ -922,23 +886,23 @@ |
922 | 886 | if (want_delete) { |
923 | 887 | loff_t old_i_size; |
924 | 888 | /*UFS_I(inode)->i_dtime = CURRENT_TIME;*/ |
925 | - lock_kernel(); | |
889 | + lock_ufs(inode->i_sb); | |
926 | 890 | mark_inode_dirty(inode); |
927 | 891 | ufs_update_inode(inode, IS_SYNC(inode)); |
928 | 892 | old_i_size = inode->i_size; |
929 | 893 | inode->i_size = 0; |
930 | 894 | if (inode->i_blocks && ufs_truncate(inode, old_i_size)) |
931 | 895 | ufs_warning(inode->i_sb, __func__, "ufs_truncate failed\n"); |
932 | - unlock_kernel(); | |
896 | + unlock_ufs(inode->i_sb); | |
933 | 897 | } |
934 | 898 | |
935 | 899 | invalidate_inode_buffers(inode); |
936 | 900 | end_writeback(inode); |
937 | 901 | |
938 | 902 | if (want_delete) { |
939 | - lock_kernel(); | |
903 | + lock_ufs(inode->i_sb); | |
940 | 904 | ufs_free_inode (inode); |
941 | - unlock_kernel(); | |
905 | + unlock_ufs(inode->i_sb); | |
942 | 906 | } |
943 | 907 | } |
fs/ufs/namei.c
... | ... | @@ -29,7 +29,6 @@ |
29 | 29 | |
30 | 30 | #include <linux/time.h> |
31 | 31 | #include <linux/fs.h> |
32 | -#include <linux/smp_lock.h> | |
33 | 32 | |
34 | 33 | #include "ufs_fs.h" |
35 | 34 | #include "ufs.h" |
36 | 35 | |
37 | 36 | |
... | ... | @@ -55,16 +54,16 @@ |
55 | 54 | if (dentry->d_name.len > UFS_MAXNAMLEN) |
56 | 55 | return ERR_PTR(-ENAMETOOLONG); |
57 | 56 | |
58 | - lock_kernel(); | |
57 | + lock_ufs(dir->i_sb); | |
59 | 58 | ino = ufs_inode_by_name(dir, &dentry->d_name); |
60 | 59 | if (ino) { |
61 | 60 | inode = ufs_iget(dir->i_sb, ino); |
62 | 61 | if (IS_ERR(inode)) { |
63 | - unlock_kernel(); | |
62 | + unlock_ufs(dir->i_sb); | |
64 | 63 | return ERR_CAST(inode); |
65 | 64 | } |
66 | 65 | } |
67 | - unlock_kernel(); | |
66 | + unlock_ufs(dir->i_sb); | |
68 | 67 | d_add(dentry, inode); |
69 | 68 | return NULL; |
70 | 69 | } |
71 | 70 | |
... | ... | @@ -93,9 +92,9 @@ |
93 | 92 | inode->i_fop = &ufs_file_operations; |
94 | 93 | inode->i_mapping->a_ops = &ufs_aops; |
95 | 94 | mark_inode_dirty(inode); |
96 | - lock_kernel(); | |
95 | + lock_ufs(dir->i_sb); | |
97 | 96 | err = ufs_add_nondir(dentry, inode); |
98 | - unlock_kernel(); | |
97 | + unlock_ufs(dir->i_sb); | |
99 | 98 | } |
100 | 99 | UFSD("END: err=%d\n", err); |
101 | 100 | return err; |
102 | 101 | |
... | ... | @@ -115,9 +114,9 @@ |
115 | 114 | init_special_inode(inode, mode, rdev); |
116 | 115 | ufs_set_inode_dev(inode->i_sb, UFS_I(inode), rdev); |
117 | 116 | mark_inode_dirty(inode); |
118 | - lock_kernel(); | |
117 | + lock_ufs(dir->i_sb); | |
119 | 118 | err = ufs_add_nondir(dentry, inode); |
120 | - unlock_kernel(); | |
119 | + unlock_ufs(dir->i_sb); | |
121 | 120 | } |
122 | 121 | return err; |
123 | 122 | } |
... | ... | @@ -133,7 +132,7 @@ |
133 | 132 | if (l > sb->s_blocksize) |
134 | 133 | goto out_notlocked; |
135 | 134 | |
136 | - lock_kernel(); | |
135 | + lock_ufs(dir->i_sb); | |
137 | 136 | inode = ufs_new_inode(dir, S_IFLNK | S_IRWXUGO); |
138 | 137 | err = PTR_ERR(inode); |
139 | 138 | if (IS_ERR(inode)) |
... | ... | @@ -156,7 +155,7 @@ |
156 | 155 | |
157 | 156 | err = ufs_add_nondir(dentry, inode); |
158 | 157 | out: |
159 | - unlock_kernel(); | |
158 | + unlock_ufs(dir->i_sb); | |
160 | 159 | out_notlocked: |
161 | 160 | return err; |
162 | 161 | |
163 | 162 | |
... | ... | @@ -172,9 +171,9 @@ |
172 | 171 | struct inode *inode = old_dentry->d_inode; |
173 | 172 | int error; |
174 | 173 | |
175 | - lock_kernel(); | |
174 | + lock_ufs(dir->i_sb); | |
176 | 175 | if (inode->i_nlink >= UFS_LINK_MAX) { |
177 | - unlock_kernel(); | |
176 | + unlock_ufs(dir->i_sb); | |
178 | 177 | return -EMLINK; |
179 | 178 | } |
180 | 179 | |
... | ... | @@ -183,7 +182,7 @@ |
183 | 182 | ihold(inode); |
184 | 183 | |
185 | 184 | error = ufs_add_nondir(dentry, inode); |
186 | - unlock_kernel(); | |
185 | + unlock_ufs(dir->i_sb); | |
187 | 186 | return error; |
188 | 187 | } |
189 | 188 | |
... | ... | @@ -195,7 +194,7 @@ |
195 | 194 | if (dir->i_nlink >= UFS_LINK_MAX) |
196 | 195 | goto out; |
197 | 196 | |
198 | - lock_kernel(); | |
197 | + lock_ufs(dir->i_sb); | |
199 | 198 | inode_inc_link_count(dir); |
200 | 199 | |
201 | 200 | inode = ufs_new_inode(dir, S_IFDIR|mode); |
... | ... | @@ -216,7 +215,7 @@ |
216 | 215 | err = ufs_add_link(dentry, inode); |
217 | 216 | if (err) |
218 | 217 | goto out_fail; |
219 | - unlock_kernel(); | |
218 | + unlock_ufs(dir->i_sb); | |
220 | 219 | |
221 | 220 | d_instantiate(dentry, inode); |
222 | 221 | out: |
... | ... | @@ -228,7 +227,7 @@ |
228 | 227 | iput (inode); |
229 | 228 | out_dir: |
230 | 229 | inode_dec_link_count(dir); |
231 | - unlock_kernel(); | |
230 | + unlock_ufs(dir->i_sb); | |
232 | 231 | goto out; |
233 | 232 | } |
234 | 233 | |
... | ... | @@ -259,7 +258,7 @@ |
259 | 258 | struct inode * inode = dentry->d_inode; |
260 | 259 | int err= -ENOTEMPTY; |
261 | 260 | |
262 | - lock_kernel(); | |
261 | + lock_ufs(dir->i_sb); | |
263 | 262 | if (ufs_empty_dir (inode)) { |
264 | 263 | err = ufs_unlink(dir, dentry); |
265 | 264 | if (!err) { |
... | ... | @@ -268,7 +267,7 @@ |
268 | 267 | inode_dec_link_count(dir); |
269 | 268 | } |
270 | 269 | } |
271 | - unlock_kernel(); | |
270 | + unlock_ufs(dir->i_sb); | |
272 | 271 | return err; |
273 | 272 | } |
274 | 273 |
fs/ufs/super.c
... | ... | @@ -84,7 +84,6 @@ |
84 | 84 | #include <linux/blkdev.h> |
85 | 85 | #include <linux/init.h> |
86 | 86 | #include <linux/parser.h> |
87 | -#include <linux/smp_lock.h> | |
88 | 87 | #include <linux/buffer_head.h> |
89 | 88 | #include <linux/vfs.h> |
90 | 89 | #include <linux/log2.h> |
... | ... | @@ -96,6 +95,26 @@ |
96 | 95 | #include "swab.h" |
97 | 96 | #include "util.h" |
98 | 97 | |
98 | +void lock_ufs(struct super_block *sb) | |
99 | +{ | |
100 | +#if defined(CONFIG_SMP) || defined (CONFIG_PREEMPT) | |
101 | + struct ufs_sb_info *sbi = UFS_SB(sb); | |
102 | + | |
103 | + mutex_lock(&sbi->mutex); | |
104 | + sbi->mutex_owner = current; | |
105 | +#endif | |
106 | +} | |
107 | + | |
108 | +void unlock_ufs(struct super_block *sb) | |
109 | +{ | |
110 | +#if defined(CONFIG_SMP) || defined (CONFIG_PREEMPT) | |
111 | + struct ufs_sb_info *sbi = UFS_SB(sb); | |
112 | + | |
113 | + sbi->mutex_owner = NULL; | |
114 | + mutex_unlock(&sbi->mutex); | |
115 | +#endif | |
116 | +} | |
117 | + | |
99 | 118 | static struct inode *ufs_nfs_get_inode(struct super_block *sb, u64 ino, u32 generation) |
100 | 119 | { |
101 | 120 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; |
... | ... | @@ -313,7 +332,6 @@ |
313 | 332 | struct ufs_super_block_first * usb1; |
314 | 333 | va_list args; |
315 | 334 | |
316 | - lock_kernel(); | |
317 | 335 | uspi = UFS_SB(sb)->s_uspi; |
318 | 336 | usb1 = ubh_get_usb_first(uspi); |
319 | 337 | |
... | ... | @@ -521,7 +539,7 @@ |
521 | 539 | */ |
522 | 540 | size = uspi->s_cssize; |
523 | 541 | blks = (size + uspi->s_fsize - 1) >> uspi->s_fshift; |
524 | - base = space = kmalloc(size, GFP_KERNEL); | |
542 | + base = space = kmalloc(size, GFP_NOFS); | |
525 | 543 | if (!base) |
526 | 544 | goto failed; |
527 | 545 | sbi->s_csp = (struct ufs_csum *)space; |
... | ... | @@ -546,7 +564,7 @@ |
546 | 564 | * Read cylinder group (we read only first fragment from block |
547 | 565 | * at this time) and prepare internal data structures for cg caching. |
548 | 566 | */ |
549 | - if (!(sbi->s_ucg = kmalloc (sizeof(struct buffer_head *) * uspi->s_ncg, GFP_KERNEL))) | |
567 | + if (!(sbi->s_ucg = kmalloc (sizeof(struct buffer_head *) * uspi->s_ncg, GFP_NOFS))) | |
550 | 568 | goto failed; |
551 | 569 | for (i = 0; i < uspi->s_ncg; i++) |
552 | 570 | sbi->s_ucg[i] = NULL; |
... | ... | @@ -564,7 +582,7 @@ |
564 | 582 | ufs_print_cylinder_stuff(sb, (struct ufs_cylinder_group *) sbi->s_ucg[i]->b_data); |
565 | 583 | } |
566 | 584 | for (i = 0; i < UFS_MAX_GROUP_LOADED; i++) { |
567 | - if (!(sbi->s_ucpi[i] = kmalloc (sizeof(struct ufs_cg_private_info), GFP_KERNEL))) | |
585 | + if (!(sbi->s_ucpi[i] = kmalloc (sizeof(struct ufs_cg_private_info), GFP_NOFS))) | |
568 | 586 | goto failed; |
569 | 587 | sbi->s_cgno[i] = UFS_CGNO_EMPTY; |
570 | 588 | } |
... | ... | @@ -646,8 +664,6 @@ |
646 | 664 | |
647 | 665 | UFSD("ENTER\n"); |
648 | 666 | |
649 | - lock_kernel(); | |
650 | - | |
651 | 667 | ufs_put_cstotal(sb); |
652 | 668 | size = uspi->s_cssize; |
653 | 669 | blks = (size + uspi->s_fsize - 1) >> uspi->s_fshift; |
... | ... | @@ -676,8 +692,6 @@ |
676 | 692 | kfree (sbi->s_ucg); |
677 | 693 | kfree (base); |
678 | 694 | |
679 | - unlock_kernel(); | |
680 | - | |
681 | 695 | UFSD("EXIT\n"); |
682 | 696 | } |
683 | 697 | |
... | ... | @@ -696,8 +710,6 @@ |
696 | 710 | unsigned maxsymlen; |
697 | 711 | int ret = -EINVAL; |
698 | 712 | |
699 | - lock_kernel(); | |
700 | - | |
701 | 713 | uspi = NULL; |
702 | 714 | ubh = NULL; |
703 | 715 | flags = 0; |
... | ... | @@ -718,6 +730,7 @@ |
718 | 730 | goto failed; |
719 | 731 | } |
720 | 732 | #endif |
733 | + mutex_init(&sbi->mutex); | |
721 | 734 | /* |
722 | 735 | * Set default mount options |
723 | 736 | * Parse mount options |
... | ... | @@ -1165,7 +1178,6 @@ |
1165 | 1178 | goto failed; |
1166 | 1179 | |
1167 | 1180 | UFSD("EXIT\n"); |
1168 | - unlock_kernel(); | |
1169 | 1181 | return 0; |
1170 | 1182 | |
1171 | 1183 | dalloc_failed: |
1172 | 1184 | |
... | ... | @@ -1177,12 +1189,10 @@ |
1177 | 1189 | kfree(sbi); |
1178 | 1190 | sb->s_fs_info = NULL; |
1179 | 1191 | UFSD("EXIT (FAILED)\n"); |
1180 | - unlock_kernel(); | |
1181 | 1192 | return ret; |
1182 | 1193 | |
1183 | 1194 | failed_nomem: |
1184 | 1195 | UFSD("EXIT (NOMEM)\n"); |
1185 | - unlock_kernel(); | |
1186 | 1196 | return -ENOMEM; |
1187 | 1197 | } |
1188 | 1198 | |
1189 | 1199 | |
... | ... | @@ -1193,8 +1203,8 @@ |
1193 | 1203 | struct ufs_super_block_third * usb3; |
1194 | 1204 | unsigned flags; |
1195 | 1205 | |
1206 | + lock_ufs(sb); | |
1196 | 1207 | lock_super(sb); |
1197 | - lock_kernel(); | |
1198 | 1208 | |
1199 | 1209 | UFSD("ENTER\n"); |
1200 | 1210 | |
1201 | 1211 | |
... | ... | @@ -1213,8 +1223,8 @@ |
1213 | 1223 | sb->s_dirt = 0; |
1214 | 1224 | |
1215 | 1225 | UFSD("EXIT\n"); |
1216 | - unlock_kernel(); | |
1217 | 1226 | unlock_super(sb); |
1227 | + unlock_ufs(sb); | |
1218 | 1228 | |
1219 | 1229 | return 0; |
1220 | 1230 | } |
... | ... | @@ -1256,7 +1266,7 @@ |
1256 | 1266 | unsigned new_mount_opt, ufstype; |
1257 | 1267 | unsigned flags; |
1258 | 1268 | |
1259 | - lock_kernel(); | |
1269 | + lock_ufs(sb); | |
1260 | 1270 | lock_super(sb); |
1261 | 1271 | uspi = UFS_SB(sb)->s_uspi; |
1262 | 1272 | flags = UFS_SB(sb)->s_flags; |
... | ... | @@ -1272,7 +1282,7 @@ |
1272 | 1282 | ufs_set_opt (new_mount_opt, ONERROR_LOCK); |
1273 | 1283 | if (!ufs_parse_options (data, &new_mount_opt)) { |
1274 | 1284 | unlock_super(sb); |
1275 | - unlock_kernel(); | |
1285 | + unlock_ufs(sb); | |
1276 | 1286 | return -EINVAL; |
1277 | 1287 | } |
1278 | 1288 | if (!(new_mount_opt & UFS_MOUNT_UFSTYPE)) { |
1279 | 1289 | |
... | ... | @@ -1280,14 +1290,14 @@ |
1280 | 1290 | } else if ((new_mount_opt & UFS_MOUNT_UFSTYPE) != ufstype) { |
1281 | 1291 | printk("ufstype can't be changed during remount\n"); |
1282 | 1292 | unlock_super(sb); |
1283 | - unlock_kernel(); | |
1293 | + unlock_ufs(sb); | |
1284 | 1294 | return -EINVAL; |
1285 | 1295 | } |
1286 | 1296 | |
1287 | 1297 | if ((*mount_flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) { |
1288 | 1298 | UFS_SB(sb)->s_mount_opt = new_mount_opt; |
1289 | 1299 | unlock_super(sb); |
1290 | - unlock_kernel(); | |
1300 | + unlock_ufs(sb); | |
1291 | 1301 | return 0; |
1292 | 1302 | } |
1293 | 1303 | |
... | ... | @@ -1313,7 +1323,7 @@ |
1313 | 1323 | printk("ufs was compiled with read-only support, " |
1314 | 1324 | "can't be mounted as read-write\n"); |
1315 | 1325 | unlock_super(sb); |
1316 | - unlock_kernel(); | |
1326 | + unlock_ufs(sb); | |
1317 | 1327 | return -EINVAL; |
1318 | 1328 | #else |
1319 | 1329 | if (ufstype != UFS_MOUNT_UFSTYPE_SUN && |
1320 | 1330 | |
... | ... | @@ -1323,13 +1333,13 @@ |
1323 | 1333 | ufstype != UFS_MOUNT_UFSTYPE_UFS2) { |
1324 | 1334 | printk("this ufstype is read-only supported\n"); |
1325 | 1335 | unlock_super(sb); |
1326 | - unlock_kernel(); | |
1336 | + unlock_ufs(sb); | |
1327 | 1337 | return -EINVAL; |
1328 | 1338 | } |
1329 | 1339 | if (!ufs_read_cylinder_structures(sb)) { |
1330 | 1340 | printk("failed during remounting\n"); |
1331 | 1341 | unlock_super(sb); |
1332 | - unlock_kernel(); | |
1342 | + unlock_ufs(sb); | |
1333 | 1343 | return -EPERM; |
1334 | 1344 | } |
1335 | 1345 | sb->s_flags &= ~MS_RDONLY; |
... | ... | @@ -1337,7 +1347,7 @@ |
1337 | 1347 | } |
1338 | 1348 | UFS_SB(sb)->s_mount_opt = new_mount_opt; |
1339 | 1349 | unlock_super(sb); |
1340 | - unlock_kernel(); | |
1350 | + unlock_ufs(sb); | |
1341 | 1351 | return 0; |
1342 | 1352 | } |
1343 | 1353 | |
... | ... | @@ -1371,7 +1381,7 @@ |
1371 | 1381 | struct ufs_super_block_third *usb3; |
1372 | 1382 | u64 id = huge_encode_dev(sb->s_bdev->bd_dev); |
1373 | 1383 | |
1374 | - lock_kernel(); | |
1384 | + lock_ufs(sb); | |
1375 | 1385 | |
1376 | 1386 | usb1 = ubh_get_usb_first(uspi); |
1377 | 1387 | usb2 = ubh_get_usb_second(uspi); |
... | ... | @@ -1395,7 +1405,7 @@ |
1395 | 1405 | buf->f_fsid.val[0] = (u32)id; |
1396 | 1406 | buf->f_fsid.val[1] = (u32)(id >> 32); |
1397 | 1407 | |
1398 | - unlock_kernel(); | |
1408 | + unlock_ufs(sb); | |
1399 | 1409 | |
1400 | 1410 | return 0; |
1401 | 1411 | } |
... | ... | @@ -1405,7 +1415,7 @@ |
1405 | 1415 | static struct inode *ufs_alloc_inode(struct super_block *sb) |
1406 | 1416 | { |
1407 | 1417 | struct ufs_inode_info *ei; |
1408 | - ei = (struct ufs_inode_info *)kmem_cache_alloc(ufs_inode_cachep, GFP_KERNEL); | |
1418 | + ei = (struct ufs_inode_info *)kmem_cache_alloc(ufs_inode_cachep, GFP_NOFS); | |
1409 | 1419 | if (!ei) |
1410 | 1420 | return NULL; |
1411 | 1421 | ei->vfs_inode.i_version = 1; |
fs/ufs/truncate.c
... | ... | @@ -40,7 +40,6 @@ |
40 | 40 | #include <linux/time.h> |
41 | 41 | #include <linux/stat.h> |
42 | 42 | #include <linux/string.h> |
43 | -#include <linux/smp_lock.h> | |
44 | 43 | #include <linux/buffer_head.h> |
45 | 44 | #include <linux/blkdev.h> |
46 | 45 | #include <linux/sched.h> |
... | ... | @@ -467,7 +466,6 @@ |
467 | 466 | |
468 | 467 | block_truncate_page(inode->i_mapping, inode->i_size, ufs_getfrag_block); |
469 | 468 | |
470 | - lock_kernel(); | |
471 | 469 | while (1) { |
472 | 470 | retry = ufs_trunc_direct(inode); |
473 | 471 | retry |= ufs_trunc_indirect(inode, UFS_IND_BLOCK, |
... | ... | @@ -487,7 +485,6 @@ |
487 | 485 | |
488 | 486 | inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; |
489 | 487 | ufsi->i_lastfrag = DIRECT_FRAGMENT; |
490 | - unlock_kernel(); | |
491 | 488 | mark_inode_dirty(inode); |
492 | 489 | out: |
493 | 490 | UFSD("EXIT: err %d\n", err); |
494 | 491 | |
... | ... | @@ -510,7 +507,9 @@ |
510 | 507 | /* XXX(truncate): truncate_setsize should be called last */ |
511 | 508 | truncate_setsize(inode, attr->ia_size); |
512 | 509 | |
510 | + lock_ufs(inode->i_sb); | |
513 | 511 | error = ufs_truncate(inode, old_i_size); |
512 | + unlock_ufs(inode->i_sb); | |
514 | 513 | if (error) |
515 | 514 | return error; |
516 | 515 | } |
fs/ufs/ufs.h
... | ... | @@ -18,6 +18,8 @@ |
18 | 18 | unsigned s_cgno[UFS_MAX_GROUP_LOADED]; |
19 | 19 | unsigned short s_cg_loaded; |
20 | 20 | unsigned s_mount_opt; |
21 | + struct mutex mutex; | |
22 | + struct task_struct *mutex_owner; | |
21 | 23 | }; |
22 | 24 | |
23 | 25 | struct ufs_inode_info { |
... | ... | @@ -109,7 +111,6 @@ |
109 | 111 | extern int ufs_write_inode (struct inode *, struct writeback_control *); |
110 | 112 | extern int ufs_sync_inode (struct inode *); |
111 | 113 | extern void ufs_evict_inode (struct inode *); |
112 | -extern struct buffer_head * ufs_bread (struct inode *, unsigned, int, int *); | |
113 | 114 | extern int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create); |
114 | 115 | |
115 | 116 | /* namei.c */ |
... | ... | @@ -153,6 +154,9 @@ |
153 | 154 | { |
154 | 155 | return do_div(b, uspi->s_fpg); |
155 | 156 | } |
157 | + | |
158 | +extern void lock_ufs(struct super_block *sb); | |
159 | +extern void unlock_ufs(struct super_block *sb); | |
156 | 160 | |
157 | 161 | #endif /* _UFS_UFS_H */ |
fs/ufs/util.c