aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ufs/super.c
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2011-01-24 04:14:12 -0500
committerArnd Bergmann <arnd@arndb.de>2011-03-02 16:27:48 -0500
commit788257d6101d986ac8f2741aaa35974af47f574c (patch)
tree332d877e09d8b5de6a4bdfba8111dd04e84a722b /fs/ufs/super.c
parent9a311b96c3065f362e3348cb5d7af1a57ca6bff9 (diff)
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>
Diffstat (limited to 'fs/ufs/super.c')
-rw-r--r--fs/ufs/super.c64
1 files changed, 37 insertions, 27 deletions
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index 2c61ac5d4e48..7693d6293404 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -84,7 +84,6 @@
84#include <linux/blkdev.h> 84#include <linux/blkdev.h>
85#include <linux/init.h> 85#include <linux/init.h>
86#include <linux/parser.h> 86#include <linux/parser.h>
87#include <linux/smp_lock.h>
88#include <linux/buffer_head.h> 87#include <linux/buffer_head.h>
89#include <linux/vfs.h> 88#include <linux/vfs.h>
90#include <linux/log2.h> 89#include <linux/log2.h>
@@ -96,6 +95,26 @@
96#include "swab.h" 95#include "swab.h"
97#include "util.h" 96#include "util.h"
98 97
98void 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
108void 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
99static struct inode *ufs_nfs_get_inode(struct super_block *sb, u64 ino, u32 generation) 118static struct inode *ufs_nfs_get_inode(struct super_block *sb, u64 ino, u32 generation)
100{ 119{
101 struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; 120 struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
@@ -313,7 +332,6 @@ void ufs_panic (struct super_block * sb, const char * function,
313 struct ufs_super_block_first * usb1; 332 struct ufs_super_block_first * usb1;
314 va_list args; 333 va_list args;
315 334
316 lock_kernel();
317 uspi = UFS_SB(sb)->s_uspi; 335 uspi = UFS_SB(sb)->s_uspi;
318 usb1 = ubh_get_usb_first(uspi); 336 usb1 = ubh_get_usb_first(uspi);
319 337
@@ -521,7 +539,7 @@ static int ufs_read_cylinder_structures(struct super_block *sb)
521 */ 539 */
522 size = uspi->s_cssize; 540 size = uspi->s_cssize;
523 blks = (size + uspi->s_fsize - 1) >> uspi->s_fshift; 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 if (!base) 543 if (!base)
526 goto failed; 544 goto failed;
527 sbi->s_csp = (struct ufs_csum *)space; 545 sbi->s_csp = (struct ufs_csum *)space;
@@ -546,7 +564,7 @@ static int ufs_read_cylinder_structures(struct super_block *sb)
546 * Read cylinder group (we read only first fragment from block 564 * Read cylinder group (we read only first fragment from block
547 * at this time) and prepare internal data structures for cg caching. 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 goto failed; 568 goto failed;
551 for (i = 0; i < uspi->s_ncg; i++) 569 for (i = 0; i < uspi->s_ncg; i++)
552 sbi->s_ucg[i] = NULL; 570 sbi->s_ucg[i] = NULL;
@@ -564,7 +582,7 @@ static int ufs_read_cylinder_structures(struct super_block *sb)
564 ufs_print_cylinder_stuff(sb, (struct ufs_cylinder_group *) sbi->s_ucg[i]->b_data); 582 ufs_print_cylinder_stuff(sb, (struct ufs_cylinder_group *) sbi->s_ucg[i]->b_data);
565 } 583 }
566 for (i = 0; i < UFS_MAX_GROUP_LOADED; i++) { 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 goto failed; 586 goto failed;
569 sbi->s_cgno[i] = UFS_CGNO_EMPTY; 587 sbi->s_cgno[i] = UFS_CGNO_EMPTY;
570 } 588 }
@@ -646,8 +664,6 @@ static void ufs_put_super_internal(struct super_block *sb)
646 664
647 UFSD("ENTER\n"); 665 UFSD("ENTER\n");
648 666
649 lock_kernel();
650
651 ufs_put_cstotal(sb); 667 ufs_put_cstotal(sb);
652 size = uspi->s_cssize; 668 size = uspi->s_cssize;
653 blks = (size + uspi->s_fsize - 1) >> uspi->s_fshift; 669 blks = (size + uspi->s_fsize - 1) >> uspi->s_fshift;
@@ -676,8 +692,6 @@ static void ufs_put_super_internal(struct super_block *sb)
676 kfree (sbi->s_ucg); 692 kfree (sbi->s_ucg);
677 kfree (base); 693 kfree (base);
678 694
679 unlock_kernel();
680
681 UFSD("EXIT\n"); 695 UFSD("EXIT\n");
682} 696}
683 697
@@ -696,8 +710,6 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
696 unsigned maxsymlen; 710 unsigned maxsymlen;
697 int ret = -EINVAL; 711 int ret = -EINVAL;
698 712
699 lock_kernel();
700
701 uspi = NULL; 713 uspi = NULL;
702 ubh = NULL; 714 ubh = NULL;
703 flags = 0; 715 flags = 0;
@@ -718,6 +730,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
718 goto failed; 730 goto failed;
719 } 731 }
720#endif 732#endif
733 mutex_init(&sbi->mutex);
721 /* 734 /*
722 * Set default mount options 735 * Set default mount options
723 * Parse mount options 736 * Parse mount options
@@ -1165,7 +1178,6 @@ magic_found:
1165 goto failed; 1178 goto failed;
1166 1179
1167 UFSD("EXIT\n"); 1180 UFSD("EXIT\n");
1168 unlock_kernel();
1169 return 0; 1181 return 0;
1170 1182
1171dalloc_failed: 1183dalloc_failed:
@@ -1177,12 +1189,10 @@ failed:
1177 kfree(sbi); 1189 kfree(sbi);
1178 sb->s_fs_info = NULL; 1190 sb->s_fs_info = NULL;
1179 UFSD("EXIT (FAILED)\n"); 1191 UFSD("EXIT (FAILED)\n");
1180 unlock_kernel();
1181 return ret; 1192 return ret;
1182 1193
1183failed_nomem: 1194failed_nomem:
1184 UFSD("EXIT (NOMEM)\n"); 1195 UFSD("EXIT (NOMEM)\n");
1185 unlock_kernel();
1186 return -ENOMEM; 1196 return -ENOMEM;
1187} 1197}
1188 1198
@@ -1193,8 +1203,8 @@ static int ufs_sync_fs(struct super_block *sb, int wait)
1193 struct ufs_super_block_third * usb3; 1203 struct ufs_super_block_third * usb3;
1194 unsigned flags; 1204 unsigned flags;
1195 1205
1206 lock_ufs(sb);
1196 lock_super(sb); 1207 lock_super(sb);
1197 lock_kernel();
1198 1208
1199 UFSD("ENTER\n"); 1209 UFSD("ENTER\n");
1200 1210
@@ -1213,8 +1223,8 @@ static int ufs_sync_fs(struct super_block *sb, int wait)
1213 sb->s_dirt = 0; 1223 sb->s_dirt = 0;
1214 1224
1215 UFSD("EXIT\n"); 1225 UFSD("EXIT\n");
1216 unlock_kernel();
1217 unlock_super(sb); 1226 unlock_super(sb);
1227 unlock_ufs(sb);
1218 1228
1219 return 0; 1229 return 0;
1220} 1230}
@@ -1256,7 +1266,7 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
1256 unsigned new_mount_opt, ufstype; 1266 unsigned new_mount_opt, ufstype;
1257 unsigned flags; 1267 unsigned flags;
1258 1268
1259 lock_kernel(); 1269 lock_ufs(sb);
1260 lock_super(sb); 1270 lock_super(sb);
1261 uspi = UFS_SB(sb)->s_uspi; 1271 uspi = UFS_SB(sb)->s_uspi;
1262 flags = UFS_SB(sb)->s_flags; 1272 flags = UFS_SB(sb)->s_flags;
@@ -1272,7 +1282,7 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
1272 ufs_set_opt (new_mount_opt, ONERROR_LOCK); 1282 ufs_set_opt (new_mount_opt, ONERROR_LOCK);
1273 if (!ufs_parse_options (data, &new_mount_opt)) { 1283 if (!ufs_parse_options (data, &new_mount_opt)) {
1274 unlock_super(sb); 1284 unlock_super(sb);
1275 unlock_kernel(); 1285 unlock_ufs(sb);
1276 return -EINVAL; 1286 return -EINVAL;
1277 } 1287 }
1278 if (!(new_mount_opt & UFS_MOUNT_UFSTYPE)) { 1288 if (!(new_mount_opt & UFS_MOUNT_UFSTYPE)) {
@@ -1280,14 +1290,14 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
1280 } else if ((new_mount_opt & UFS_MOUNT_UFSTYPE) != ufstype) { 1290 } else if ((new_mount_opt & UFS_MOUNT_UFSTYPE) != ufstype) {
1281 printk("ufstype can't be changed during remount\n"); 1291 printk("ufstype can't be changed during remount\n");
1282 unlock_super(sb); 1292 unlock_super(sb);
1283 unlock_kernel(); 1293 unlock_ufs(sb);
1284 return -EINVAL; 1294 return -EINVAL;
1285 } 1295 }
1286 1296
1287 if ((*mount_flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) { 1297 if ((*mount_flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) {
1288 UFS_SB(sb)->s_mount_opt = new_mount_opt; 1298 UFS_SB(sb)->s_mount_opt = new_mount_opt;
1289 unlock_super(sb); 1299 unlock_super(sb);
1290 unlock_kernel(); 1300 unlock_ufs(sb);
1291 return 0; 1301 return 0;
1292 } 1302 }
1293 1303
@@ -1313,7 +1323,7 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
1313 printk("ufs was compiled with read-only support, " 1323 printk("ufs was compiled with read-only support, "
1314 "can't be mounted as read-write\n"); 1324 "can't be mounted as read-write\n");
1315 unlock_super(sb); 1325 unlock_super(sb);
1316 unlock_kernel(); 1326 unlock_ufs(sb);
1317 return -EINVAL; 1327 return -EINVAL;
1318#else 1328#else
1319 if (ufstype != UFS_MOUNT_UFSTYPE_SUN && 1329 if (ufstype != UFS_MOUNT_UFSTYPE_SUN &&
@@ -1323,13 +1333,13 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
1323 ufstype != UFS_MOUNT_UFSTYPE_UFS2) { 1333 ufstype != UFS_MOUNT_UFSTYPE_UFS2) {
1324 printk("this ufstype is read-only supported\n"); 1334 printk("this ufstype is read-only supported\n");
1325 unlock_super(sb); 1335 unlock_super(sb);
1326 unlock_kernel(); 1336 unlock_ufs(sb);
1327 return -EINVAL; 1337 return -EINVAL;
1328 } 1338 }
1329 if (!ufs_read_cylinder_structures(sb)) { 1339 if (!ufs_read_cylinder_structures(sb)) {
1330 printk("failed during remounting\n"); 1340 printk("failed during remounting\n");
1331 unlock_super(sb); 1341 unlock_super(sb);
1332 unlock_kernel(); 1342 unlock_ufs(sb);
1333 return -EPERM; 1343 return -EPERM;
1334 } 1344 }
1335 sb->s_flags &= ~MS_RDONLY; 1345 sb->s_flags &= ~MS_RDONLY;
@@ -1337,7 +1347,7 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
1337 } 1347 }
1338 UFS_SB(sb)->s_mount_opt = new_mount_opt; 1348 UFS_SB(sb)->s_mount_opt = new_mount_opt;
1339 unlock_super(sb); 1349 unlock_super(sb);
1340 unlock_kernel(); 1350 unlock_ufs(sb);
1341 return 0; 1351 return 0;
1342} 1352}
1343 1353
@@ -1371,7 +1381,7 @@ static int ufs_statfs(struct dentry *dentry, struct kstatfs *buf)
1371 struct ufs_super_block_third *usb3; 1381 struct ufs_super_block_third *usb3;
1372 u64 id = huge_encode_dev(sb->s_bdev->bd_dev); 1382 u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
1373 1383
1374 lock_kernel(); 1384 lock_ufs(sb);
1375 1385
1376 usb1 = ubh_get_usb_first(uspi); 1386 usb1 = ubh_get_usb_first(uspi);
1377 usb2 = ubh_get_usb_second(uspi); 1387 usb2 = ubh_get_usb_second(uspi);
@@ -1395,7 +1405,7 @@ static int ufs_statfs(struct dentry *dentry, struct kstatfs *buf)
1395 buf->f_fsid.val[0] = (u32)id; 1405 buf->f_fsid.val[0] = (u32)id;
1396 buf->f_fsid.val[1] = (u32)(id >> 32); 1406 buf->f_fsid.val[1] = (u32)(id >> 32);
1397 1407
1398 unlock_kernel(); 1408 unlock_ufs(sb);
1399 1409
1400 return 0; 1410 return 0;
1401} 1411}
@@ -1405,7 +1415,7 @@ static struct kmem_cache * ufs_inode_cachep;
1405static struct inode *ufs_alloc_inode(struct super_block *sb) 1415static struct inode *ufs_alloc_inode(struct super_block *sb)
1406{ 1416{
1407 struct ufs_inode_info *ei; 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 if (!ei) 1419 if (!ei)
1410 return NULL; 1420 return NULL;
1411 ei->vfs_inode.i_version = 1; 1421 ei->vfs_inode.i_version = 1;