aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ufs/namei.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/namei.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/namei.c')
-rw-r--r--fs/ufs/namei.c35
1 files changed, 17 insertions, 18 deletions
diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c
index 12f39b9e4437..205030a707fe 100644
--- a/fs/ufs/namei.c
+++ b/fs/ufs/namei.c
@@ -29,7 +29,6 @@
29 29
30#include <linux/time.h> 30#include <linux/time.h>
31#include <linux/fs.h> 31#include <linux/fs.h>
32#include <linux/smp_lock.h>
33 32
34#include "ufs_fs.h" 33#include "ufs_fs.h"
35#include "ufs.h" 34#include "ufs.h"
@@ -55,16 +54,16 @@ static struct dentry *ufs_lookup(struct inode * dir, struct dentry *dentry, stru
55 if (dentry->d_name.len > UFS_MAXNAMLEN) 54 if (dentry->d_name.len > UFS_MAXNAMLEN)
56 return ERR_PTR(-ENAMETOOLONG); 55 return ERR_PTR(-ENAMETOOLONG);
57 56
58 lock_kernel(); 57 lock_ufs(dir->i_sb);
59 ino = ufs_inode_by_name(dir, &dentry->d_name); 58 ino = ufs_inode_by_name(dir, &dentry->d_name);
60 if (ino) { 59 if (ino) {
61 inode = ufs_iget(dir->i_sb, ino); 60 inode = ufs_iget(dir->i_sb, ino);
62 if (IS_ERR(inode)) { 61 if (IS_ERR(inode)) {
63 unlock_kernel(); 62 unlock_ufs(dir->i_sb);
64 return ERR_CAST(inode); 63 return ERR_CAST(inode);
65 } 64 }
66 } 65 }
67 unlock_kernel(); 66 unlock_ufs(dir->i_sb);
68 d_add(dentry, inode); 67 d_add(dentry, inode);
69 return NULL; 68 return NULL;
70} 69}
@@ -93,9 +92,9 @@ static int ufs_create (struct inode * dir, struct dentry * dentry, int mode,
93 inode->i_fop = &ufs_file_operations; 92 inode->i_fop = &ufs_file_operations;
94 inode->i_mapping->a_ops = &ufs_aops; 93 inode->i_mapping->a_ops = &ufs_aops;
95 mark_inode_dirty(inode); 94 mark_inode_dirty(inode);
96 lock_kernel(); 95 lock_ufs(dir->i_sb);
97 err = ufs_add_nondir(dentry, inode); 96 err = ufs_add_nondir(dentry, inode);
98 unlock_kernel(); 97 unlock_ufs(dir->i_sb);
99 } 98 }
100 UFSD("END: err=%d\n", err); 99 UFSD("END: err=%d\n", err);
101 return err; 100 return err;
@@ -115,9 +114,9 @@ static int ufs_mknod (struct inode * dir, struct dentry *dentry, int mode, dev_t
115 init_special_inode(inode, mode, rdev); 114 init_special_inode(inode, mode, rdev);
116 ufs_set_inode_dev(inode->i_sb, UFS_I(inode), rdev); 115 ufs_set_inode_dev(inode->i_sb, UFS_I(inode), rdev);
117 mark_inode_dirty(inode); 116 mark_inode_dirty(inode);
118 lock_kernel(); 117 lock_ufs(dir->i_sb);
119 err = ufs_add_nondir(dentry, inode); 118 err = ufs_add_nondir(dentry, inode);
120 unlock_kernel(); 119 unlock_ufs(dir->i_sb);
121 } 120 }
122 return err; 121 return err;
123} 122}
@@ -133,7 +132,7 @@ static int ufs_symlink (struct inode * dir, struct dentry * dentry,
133 if (l > sb->s_blocksize) 132 if (l > sb->s_blocksize)
134 goto out_notlocked; 133 goto out_notlocked;
135 134
136 lock_kernel(); 135 lock_ufs(dir->i_sb);
137 inode = ufs_new_inode(dir, S_IFLNK | S_IRWXUGO); 136 inode = ufs_new_inode(dir, S_IFLNK | S_IRWXUGO);
138 err = PTR_ERR(inode); 137 err = PTR_ERR(inode);
139 if (IS_ERR(inode)) 138 if (IS_ERR(inode))
@@ -156,7 +155,7 @@ static int ufs_symlink (struct inode * dir, struct dentry * dentry,
156 155
157 err = ufs_add_nondir(dentry, inode); 156 err = ufs_add_nondir(dentry, inode);
158out: 157out:
159 unlock_kernel(); 158 unlock_ufs(dir->i_sb);
160out_notlocked: 159out_notlocked:
161 return err; 160 return err;
162 161
@@ -172,9 +171,9 @@ static int ufs_link (struct dentry * old_dentry, struct inode * dir,
172 struct inode *inode = old_dentry->d_inode; 171 struct inode *inode = old_dentry->d_inode;
173 int error; 172 int error;
174 173
175 lock_kernel(); 174 lock_ufs(dir->i_sb);
176 if (inode->i_nlink >= UFS_LINK_MAX) { 175 if (inode->i_nlink >= UFS_LINK_MAX) {
177 unlock_kernel(); 176 unlock_ufs(dir->i_sb);
178 return -EMLINK; 177 return -EMLINK;
179 } 178 }
180 179
@@ -183,7 +182,7 @@ static int ufs_link (struct dentry * old_dentry, struct inode * dir,
183 ihold(inode); 182 ihold(inode);
184 183
185 error = ufs_add_nondir(dentry, inode); 184 error = ufs_add_nondir(dentry, inode);
186 unlock_kernel(); 185 unlock_ufs(dir->i_sb);
187 return error; 186 return error;
188} 187}
189 188
@@ -195,7 +194,7 @@ static int ufs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
195 if (dir->i_nlink >= UFS_LINK_MAX) 194 if (dir->i_nlink >= UFS_LINK_MAX)
196 goto out; 195 goto out;
197 196
198 lock_kernel(); 197 lock_ufs(dir->i_sb);
199 inode_inc_link_count(dir); 198 inode_inc_link_count(dir);
200 199
201 inode = ufs_new_inode(dir, S_IFDIR|mode); 200 inode = ufs_new_inode(dir, S_IFDIR|mode);
@@ -216,7 +215,7 @@ static int ufs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
216 err = ufs_add_link(dentry, inode); 215 err = ufs_add_link(dentry, inode);
217 if (err) 216 if (err)
218 goto out_fail; 217 goto out_fail;
219 unlock_kernel(); 218 unlock_ufs(dir->i_sb);
220 219
221 d_instantiate(dentry, inode); 220 d_instantiate(dentry, inode);
222out: 221out:
@@ -228,7 +227,7 @@ out_fail:
228 iput (inode); 227 iput (inode);
229out_dir: 228out_dir:
230 inode_dec_link_count(dir); 229 inode_dec_link_count(dir);
231 unlock_kernel(); 230 unlock_ufs(dir->i_sb);
232 goto out; 231 goto out;
233} 232}
234 233
@@ -259,7 +258,7 @@ static int ufs_rmdir (struct inode * dir, struct dentry *dentry)
259 struct inode * inode = dentry->d_inode; 258 struct inode * inode = dentry->d_inode;
260 int err= -ENOTEMPTY; 259 int err= -ENOTEMPTY;
261 260
262 lock_kernel(); 261 lock_ufs(dir->i_sb);
263 if (ufs_empty_dir (inode)) { 262 if (ufs_empty_dir (inode)) {
264 err = ufs_unlink(dir, dentry); 263 err = ufs_unlink(dir, dentry);
265 if (!err) { 264 if (!err) {
@@ -268,7 +267,7 @@ static int ufs_rmdir (struct inode * dir, struct dentry *dentry)
268 inode_dec_link_count(dir); 267 inode_dec_link_count(dir);
269 } 268 }
270 } 269 }
271 unlock_kernel(); 270 unlock_ufs(dir->i_sb);
272 return err; 271 return err;
273} 272}
274 273