aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2010-09-12 13:05:56 -0400
committerArnd Bergmann <arnd@arndb.de>2010-10-04 15:10:45 -0400
commit4f819a7899b06afcd7623ab9d00fd81503ad3e24 (patch)
tree4506a992e9207f6374803e89d9a0e9b9a9b33ddb
parent3768744cfea7b995dce27f02341161fbfdfee80c (diff)
BKL: Remove BKL from isofs
As in other file systems, we can replace the big kernel lock with a private mutex in isofs. This means we can now access multiple file systems concurrently, but it also means that we serialize readdir and lookup across sleeping operations which previously released the big kernel lock. This should not matter though, as these operations are in practice serialized through the hardware access. The isofs_get_blocks functions now does not take any lock any more, it used to recursively get the BKL. After looking at the code for hours, I convinced myself that it was never needed here anyway, because it only reads constant fields of the inode and writes to a buffer head array that is at this time only visible to the caller. The get_sb and fill_super operations do not need the locking at all because they operate on a file system that is either about to be created or to be destroyed but in either case is not visible to other threads. Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-rw-r--r--fs/isofs/dir.c6
-rw-r--r--fs/isofs/inode.c17
-rw-r--r--fs/isofs/isofs.h1
-rw-r--r--fs/isofs/namei.c8
-rw-r--r--fs/isofs/rock.c10
5 files changed, 15 insertions, 27 deletions
diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c
index e0aca9a0ac68..0542b6eedf80 100644
--- a/fs/isofs/dir.c
+++ b/fs/isofs/dir.c
@@ -10,7 +10,6 @@
10 * 10 *
11 * isofs directory handling functions 11 * isofs directory handling functions
12 */ 12 */
13#include <linux/smp_lock.h>
14#include <linux/gfp.h> 13#include <linux/gfp.h>
15#include "isofs.h" 14#include "isofs.h"
16 15
@@ -255,18 +254,19 @@ static int isofs_readdir(struct file *filp,
255 char *tmpname; 254 char *tmpname;
256 struct iso_directory_record *tmpde; 255 struct iso_directory_record *tmpde;
257 struct inode *inode = filp->f_path.dentry->d_inode; 256 struct inode *inode = filp->f_path.dentry->d_inode;
257 struct isofs_sb_info *sbi = ISOFS_SB(inode->i_sb);
258 258
259 tmpname = (char *)__get_free_page(GFP_KERNEL); 259 tmpname = (char *)__get_free_page(GFP_KERNEL);
260 if (tmpname == NULL) 260 if (tmpname == NULL)
261 return -ENOMEM; 261 return -ENOMEM;
262 262
263 lock_kernel(); 263 mutex_lock(&sbi->s_mutex);
264 tmpde = (struct iso_directory_record *) (tmpname+1024); 264 tmpde = (struct iso_directory_record *) (tmpname+1024);
265 265
266 result = do_isofs_readdir(inode, filp, dirent, filldir, tmpname, tmpde); 266 result = do_isofs_readdir(inode, filp, dirent, filldir, tmpname, tmpde);
267 267
268 free_page((unsigned long) tmpname); 268 free_page((unsigned long) tmpname);
269 unlock_kernel(); 269 mutex_unlock(&sbi->s_mutex);
270 return result; 270 return result;
271} 271}
272 272
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index 05baf7721e8c..09ff41a752a0 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -17,7 +17,6 @@
17#include <linux/slab.h> 17#include <linux/slab.h>
18#include <linux/nls.h> 18#include <linux/nls.h>
19#include <linux/ctype.h> 19#include <linux/ctype.h>
20#include <linux/smp_lock.h>
21#include <linux/statfs.h> 20#include <linux/statfs.h>
22#include <linux/cdrom.h> 21#include <linux/cdrom.h>
23#include <linux/parser.h> 22#include <linux/parser.h>
@@ -44,11 +43,7 @@ static void isofs_put_super(struct super_block *sb)
44 struct isofs_sb_info *sbi = ISOFS_SB(sb); 43 struct isofs_sb_info *sbi = ISOFS_SB(sb);
45 44
46#ifdef CONFIG_JOLIET 45#ifdef CONFIG_JOLIET
47 lock_kernel();
48
49 unload_nls(sbi->s_nls_iocharset); 46 unload_nls(sbi->s_nls_iocharset);
50
51 unlock_kernel();
52#endif 47#endif
53 48
54 kfree(sbi); 49 kfree(sbi);
@@ -571,15 +566,11 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
571 int table, error = -EINVAL; 566 int table, error = -EINVAL;
572 unsigned int vol_desc_start; 567 unsigned int vol_desc_start;
573 568
574 lock_kernel();
575
576 save_mount_options(s, data); 569 save_mount_options(s, data);
577 570
578 sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); 571 sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
579 if (!sbi) { 572 if (!sbi)
580 unlock_kernel();
581 return -ENOMEM; 573 return -ENOMEM;
582 }
583 s->s_fs_info = sbi; 574 s->s_fs_info = sbi;
584 575
585 if (!parse_options((char *)data, &opt)) 576 if (!parse_options((char *)data, &opt))
@@ -827,6 +818,7 @@ root_found:
827 sbi->s_utf8 = opt.utf8; 818 sbi->s_utf8 = opt.utf8;
828 sbi->s_nocompress = opt.nocompress; 819 sbi->s_nocompress = opt.nocompress;
829 sbi->s_overriderockperm = opt.overriderockperm; 820 sbi->s_overriderockperm = opt.overriderockperm;
821 mutex_init(&sbi->s_mutex);
830 /* 822 /*
831 * It would be incredibly stupid to allow people to mark every file 823 * It would be incredibly stupid to allow people to mark every file
832 * on the disk as suid, so we merely allow them to set the default 824 * on the disk as suid, so we merely allow them to set the default
@@ -904,7 +896,6 @@ root_found:
904 896
905 kfree(opt.iocharset); 897 kfree(opt.iocharset);
906 898
907 unlock_kernel();
908 return 0; 899 return 0;
909 900
910 /* 901 /*
@@ -944,7 +935,6 @@ out_freesbi:
944 kfree(opt.iocharset); 935 kfree(opt.iocharset);
945 kfree(sbi); 936 kfree(sbi);
946 s->s_fs_info = NULL; 937 s->s_fs_info = NULL;
947 unlock_kernel();
948 return error; 938 return error;
949} 939}
950 940
@@ -983,8 +973,6 @@ int isofs_get_blocks(struct inode *inode, sector_t iblock_s,
983 int section, rv, error; 973 int section, rv, error;
984 struct iso_inode_info *ei = ISOFS_I(inode); 974 struct iso_inode_info *ei = ISOFS_I(inode);
985 975
986 lock_kernel();
987
988 error = -EIO; 976 error = -EIO;
989 rv = 0; 977 rv = 0;
990 if (iblock < 0 || iblock != iblock_s) { 978 if (iblock < 0 || iblock != iblock_s) {
@@ -1060,7 +1048,6 @@ int isofs_get_blocks(struct inode *inode, sector_t iblock_s,
1060 1048
1061 error = 0; 1049 error = 0;
1062abort: 1050abort:
1063 unlock_kernel();
1064 return rv != 0 ? rv : error; 1051 return rv != 0 ? rv : error;
1065} 1052}
1066 1053
diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h
index 7d33de84f52a..2882dc089f87 100644
--- a/fs/isofs/isofs.h
+++ b/fs/isofs/isofs.h
@@ -55,6 +55,7 @@ struct isofs_sb_info {
55 gid_t s_gid; 55 gid_t s_gid;
56 uid_t s_uid; 56 uid_t s_uid;
57 struct nls_table *s_nls_iocharset; /* Native language support table */ 57 struct nls_table *s_nls_iocharset; /* Native language support table */
58 struct mutex s_mutex; /* replaces BKL, please remove if possible */
58}; 59};
59 60
60#define ISOFS_INVALID_MODE ((mode_t) -1) 61#define ISOFS_INVALID_MODE ((mode_t) -1)
diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c
index ab438beb867c..0d23abfd4280 100644
--- a/fs/isofs/namei.c
+++ b/fs/isofs/namei.c
@@ -6,7 +6,6 @@
6 * (C) 1991 Linus Torvalds - minix filesystem 6 * (C) 1991 Linus Torvalds - minix filesystem
7 */ 7 */
8 8
9#include <linux/smp_lock.h>
10#include <linux/gfp.h> 9#include <linux/gfp.h>
11#include "isofs.h" 10#include "isofs.h"
12 11
@@ -168,6 +167,7 @@ struct dentry *isofs_lookup(struct inode *dir, struct dentry *dentry, struct nam
168 int found; 167 int found;
169 unsigned long uninitialized_var(block); 168 unsigned long uninitialized_var(block);
170 unsigned long uninitialized_var(offset); 169 unsigned long uninitialized_var(offset);
170 struct isofs_sb_info *sbi = ISOFS_SB(dir->i_sb);
171 struct inode *inode; 171 struct inode *inode;
172 struct page *page; 172 struct page *page;
173 173
@@ -177,7 +177,7 @@ struct dentry *isofs_lookup(struct inode *dir, struct dentry *dentry, struct nam
177 if (!page) 177 if (!page)
178 return ERR_PTR(-ENOMEM); 178 return ERR_PTR(-ENOMEM);
179 179
180 lock_kernel(); 180 mutex_lock(&sbi->s_mutex);
181 found = isofs_find_entry(dir, dentry, 181 found = isofs_find_entry(dir, dentry,
182 &block, &offset, 182 &block, &offset,
183 page_address(page), 183 page_address(page),
@@ -188,10 +188,10 @@ struct dentry *isofs_lookup(struct inode *dir, struct dentry *dentry, struct nam
188 if (found) { 188 if (found) {
189 inode = isofs_iget(dir->i_sb, block, offset); 189 inode = isofs_iget(dir->i_sb, block, offset);
190 if (IS_ERR(inode)) { 190 if (IS_ERR(inode)) {
191 unlock_kernel(); 191 mutex_unlock(&sbi->s_mutex);
192 return ERR_CAST(inode); 192 return ERR_CAST(inode);
193 } 193 }
194 } 194 }
195 unlock_kernel(); 195 mutex_unlock(&sbi->s_mutex);
196 return d_splice_alias(inode, dentry); 196 return d_splice_alias(inode, dentry);
197} 197}
diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c
index 96a685c550fd..f9cd04db6eab 100644
--- a/fs/isofs/rock.c
+++ b/fs/isofs/rock.c
@@ -8,7 +8,6 @@
8 8
9#include <linux/slab.h> 9#include <linux/slab.h>
10#include <linux/pagemap.h> 10#include <linux/pagemap.h>
11#include <linux/smp_lock.h>
12 11
13#include "isofs.h" 12#include "isofs.h"
14#include "rock.h" 13#include "rock.h"
@@ -661,6 +660,7 @@ static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
661{ 660{
662 struct inode *inode = page->mapping->host; 661 struct inode *inode = page->mapping->host;
663 struct iso_inode_info *ei = ISOFS_I(inode); 662 struct iso_inode_info *ei = ISOFS_I(inode);
663 struct isofs_sb_info *sbi = ISOFS_SB(inode->i_sb);
664 char *link = kmap(page); 664 char *link = kmap(page);
665 unsigned long bufsize = ISOFS_BUFFER_SIZE(inode); 665 unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
666 struct buffer_head *bh; 666 struct buffer_head *bh;
@@ -673,12 +673,12 @@ static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
673 struct rock_state rs; 673 struct rock_state rs;
674 int ret; 674 int ret;
675 675
676 if (!ISOFS_SB(inode->i_sb)->s_rock) 676 if (!sbi->s_rock)
677 goto error; 677 goto error;
678 678
679 init_rock_state(&rs, inode); 679 init_rock_state(&rs, inode);
680 block = ei->i_iget5_block; 680 block = ei->i_iget5_block;
681 lock_kernel(); 681 mutex_lock(&sbi->s_mutex);
682 bh = sb_bread(inode->i_sb, block); 682 bh = sb_bread(inode->i_sb, block);
683 if (!bh) 683 if (!bh)
684 goto out_noread; 684 goto out_noread;
@@ -748,7 +748,7 @@ repeat:
748 goto fail; 748 goto fail;
749 brelse(bh); 749 brelse(bh);
750 *rpnt = '\0'; 750 *rpnt = '\0';
751 unlock_kernel(); 751 mutex_unlock(&sbi->s_mutex);
752 SetPageUptodate(page); 752 SetPageUptodate(page);
753 kunmap(page); 753 kunmap(page);
754 unlock_page(page); 754 unlock_page(page);
@@ -765,7 +765,7 @@ out_bad_span:
765 printk("symlink spans iso9660 blocks\n"); 765 printk("symlink spans iso9660 blocks\n");
766fail: 766fail:
767 brelse(bh); 767 brelse(bh);
768 unlock_kernel(); 768 mutex_unlock(&sbi->s_mutex);
769error: 769error:
770 SetPageError(page); 770 SetPageError(page);
771 kunmap(page); 771 kunmap(page);