aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYoshihisa Abe <yoshiabe@cs.cmu.edu>2010-10-25 02:03:45 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-10-25 11:02:40 -0400
commitf7cc02b8715618e179242ba9cc10bdc5146ae565 (patch)
tree80c1bcf6923c9982a52fbe510cb7d396fb9866fc
parentb5ce1d83a62fc109d8e815b1fc71dcdb0d26bc49 (diff)
Coda: push BKL regions into coda_upcall()
Now that shared inode state is locked using the cii->c_lock, the BKL is only used to protect the upcall queues used to communicate with the userspace cache manager. The remaining state is all local and we can push the lock further down into coda_upcall(). Signed-off-by: Yoshihisa Abe <yoshiabe@cs.cmu.edu> Signed-off-by: Jan Harkes <jaharkes@cs.cmu.edu> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/coda/dir.c149
-rw-r--r--fs/coda/file.c19
-rw-r--r--fs/coda/inode.c46
-rw-r--r--fs/coda/pioctl.c22
-rw-r--r--fs/coda/psdev.c13
-rw-r--r--fs/coda/symlink.c3
-rw-r--r--fs/coda/upcall.c32
-rw-r--r--include/linux/coda_psdev.h2
8 files changed, 96 insertions, 190 deletions
diff --git a/fs/coda/dir.c b/fs/coda/dir.c
index 69fbbea75f1b..96fbeab77f2f 100644
--- a/fs/coda/dir.c
+++ b/fs/coda/dir.c
@@ -17,7 +17,6 @@
17#include <linux/stat.h> 17#include <linux/stat.h>
18#include <linux/errno.h> 18#include <linux/errno.h>
19#include <linux/string.h> 19#include <linux/string.h>
20#include <linux/smp_lock.h>
21#include <linux/spinlock.h> 20#include <linux/spinlock.h>
22 21
23#include <asm/uaccess.h> 22#include <asm/uaccess.h>
@@ -117,15 +116,11 @@ static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, struc
117 goto exit; 116 goto exit;
118 } 117 }
119 118
120 lock_kernel();
121
122 error = venus_lookup(dir->i_sb, coda_i2f(dir), name, length, 119 error = venus_lookup(dir->i_sb, coda_i2f(dir), name, length,
123 &type, &resfid); 120 &type, &resfid);
124 if (!error) 121 if (!error)
125 error = coda_cnode_make(&inode, &resfid, dir->i_sb); 122 error = coda_cnode_make(&inode, &resfid, dir->i_sb);
126 123
127 unlock_kernel();
128
129 if (error && error != -ENOENT) 124 if (error && error != -ENOENT)
130 return ERR_PTR(error); 125 return ERR_PTR(error);
131 126
@@ -141,28 +136,24 @@ exit:
141 136
142int coda_permission(struct inode *inode, int mask) 137int coda_permission(struct inode *inode, int mask)
143{ 138{
144 int error = 0; 139 int error;
145 140
146 mask &= MAY_READ | MAY_WRITE | MAY_EXEC; 141 mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
147 142
148 if (!mask) 143 if (!mask)
149 return 0; 144 return 0;
150 145
151 if ((mask & MAY_EXEC) && !execute_ok(inode)) 146 if ((mask & MAY_EXEC) && !execute_ok(inode))
152 return -EACCES; 147 return -EACCES;
153 148
154 lock_kernel();
155
156 if (coda_cache_check(inode, mask)) 149 if (coda_cache_check(inode, mask))
157 goto out; 150 return 0;
158 151
159 error = venus_access(inode->i_sb, coda_i2f(inode), mask); 152 error = venus_access(inode->i_sb, coda_i2f(inode), mask);
160 153
161 if (!error) 154 if (!error)
162 coda_cache_enter(inode, mask); 155 coda_cache_enter(inode, mask);
163 156
164 out:
165 unlock_kernel();
166 return error; 157 return error;
167} 158}
168 159
@@ -201,41 +192,34 @@ static inline void coda_dir_drop_nlink(struct inode *dir)
201/* creation routines: create, mknod, mkdir, link, symlink */ 192/* creation routines: create, mknod, mkdir, link, symlink */
202static int coda_create(struct inode *dir, struct dentry *de, int mode, struct nameidata *nd) 193static int coda_create(struct inode *dir, struct dentry *de, int mode, struct nameidata *nd)
203{ 194{
204 int error=0; 195 int error;
205 const char *name=de->d_name.name; 196 const char *name=de->d_name.name;
206 int length=de->d_name.len; 197 int length=de->d_name.len;
207 struct inode *inode; 198 struct inode *inode;
208 struct CodaFid newfid; 199 struct CodaFid newfid;
209 struct coda_vattr attrs; 200 struct coda_vattr attrs;
210 201
211 lock_kernel(); 202 if (coda_isroot(dir) && coda_iscontrol(name, length))
212
213 if (coda_isroot(dir) && coda_iscontrol(name, length)) {
214 unlock_kernel();
215 return -EPERM; 203 return -EPERM;
216 }
217 204
218 error = venus_create(dir->i_sb, coda_i2f(dir), name, length, 205 error = venus_create(dir->i_sb, coda_i2f(dir), name, length,
219 0, mode, &newfid, &attrs); 206 0, mode, &newfid, &attrs);
220 207 if (error)
221 if ( error ) { 208 goto err_out;
222 unlock_kernel();
223 d_drop(de);
224 return error;
225 }
226 209
227 inode = coda_iget(dir->i_sb, &newfid, &attrs); 210 inode = coda_iget(dir->i_sb, &newfid, &attrs);
228 if ( IS_ERR(inode) ) { 211 if (IS_ERR(inode)) {
229 unlock_kernel(); 212 error = PTR_ERR(inode);
230 d_drop(de); 213 goto err_out;
231 return PTR_ERR(inode);
232 } 214 }
233 215
234 /* invalidate the directory cnode's attributes */ 216 /* invalidate the directory cnode's attributes */
235 coda_dir_update_mtime(dir); 217 coda_dir_update_mtime(dir);
236 unlock_kernel();
237 d_instantiate(de, inode); 218 d_instantiate(de, inode);
238 return 0; 219 return 0;
220err_out:
221 d_drop(de);
222 return error;
239} 223}
240 224
241static int coda_mkdir(struct inode *dir, struct dentry *de, int mode) 225static int coda_mkdir(struct inode *dir, struct dentry *de, int mode)
@@ -247,36 +231,29 @@ static int coda_mkdir(struct inode *dir, struct dentry *de, int mode)
247 int error; 231 int error;
248 struct CodaFid newfid; 232 struct CodaFid newfid;
249 233
250 lock_kernel(); 234 if (coda_isroot(dir) && coda_iscontrol(name, len))
251
252 if (coda_isroot(dir) && coda_iscontrol(name, len)) {
253 unlock_kernel();
254 return -EPERM; 235 return -EPERM;
255 }
256 236
257 attrs.va_mode = mode; 237 attrs.va_mode = mode;
258 error = venus_mkdir(dir->i_sb, coda_i2f(dir), 238 error = venus_mkdir(dir->i_sb, coda_i2f(dir),
259 name, len, &newfid, &attrs); 239 name, len, &newfid, &attrs);
260 240 if (error)
261 if ( error ) { 241 goto err_out;
262 unlock_kernel();
263 d_drop(de);
264 return error;
265 }
266 242
267 inode = coda_iget(dir->i_sb, &newfid, &attrs); 243 inode = coda_iget(dir->i_sb, &newfid, &attrs);
268 if ( IS_ERR(inode) ) { 244 if (IS_ERR(inode)) {
269 unlock_kernel(); 245 error = PTR_ERR(inode);
270 d_drop(de); 246 goto err_out;
271 return PTR_ERR(inode);
272 } 247 }
273 248
274 /* invalidate the directory cnode's attributes */ 249 /* invalidate the directory cnode's attributes */
275 coda_dir_inc_nlink(dir); 250 coda_dir_inc_nlink(dir);
276 coda_dir_update_mtime(dir); 251 coda_dir_update_mtime(dir);
277 unlock_kernel();
278 d_instantiate(de, inode); 252 d_instantiate(de, inode);
279 return 0; 253 return 0;
254err_out:
255 d_drop(de);
256 return error;
280} 257}
281 258
282/* try to make de an entry in dir_inodde linked to source_de */ 259/* try to make de an entry in dir_inodde linked to source_de */
@@ -288,52 +265,38 @@ static int coda_link(struct dentry *source_de, struct inode *dir_inode,
288 int len = de->d_name.len; 265 int len = de->d_name.len;
289 int error; 266 int error;
290 267
291 lock_kernel(); 268 if (coda_isroot(dir_inode) && coda_iscontrol(name, len))
292
293 if (coda_isroot(dir_inode) && coda_iscontrol(name, len)) {
294 unlock_kernel();
295 return -EPERM; 269 return -EPERM;
296 }
297 270
298 error = venus_link(dir_inode->i_sb, coda_i2f(inode), 271 error = venus_link(dir_inode->i_sb, coda_i2f(inode),
299 coda_i2f(dir_inode), (const char *)name, len); 272 coda_i2f(dir_inode), (const char *)name, len);
300
301 if (error) { 273 if (error) {
302 d_drop(de); 274 d_drop(de);
303 goto out; 275 return error;
304 } 276 }
305 277
306 coda_dir_update_mtime(dir_inode); 278 coda_dir_update_mtime(dir_inode);
307 atomic_inc(&inode->i_count); 279 atomic_inc(&inode->i_count);
308 d_instantiate(de, inode); 280 d_instantiate(de, inode);
309 inc_nlink(inode); 281 inc_nlink(inode);
310 282 return 0;
311out:
312 unlock_kernel();
313 return(error);
314} 283}
315 284
316 285
317static int coda_symlink(struct inode *dir_inode, struct dentry *de, 286static int coda_symlink(struct inode *dir_inode, struct dentry *de,
318 const char *symname) 287 const char *symname)
319{ 288{
320 const char *name = de->d_name.name; 289 const char *name = de->d_name.name;
321 int len = de->d_name.len; 290 int len = de->d_name.len;
322 int symlen; 291 int symlen;
323 int error = 0; 292 int error;
324
325 lock_kernel();
326 293
327 if (coda_isroot(dir_inode) && coda_iscontrol(name, len)) { 294 if (coda_isroot(dir_inode) && coda_iscontrol(name, len))
328 unlock_kernel();
329 return -EPERM; 295 return -EPERM;
330 }
331 296
332 symlen = strlen(symname); 297 symlen = strlen(symname);
333 if ( symlen > CODA_MAXPATHLEN ) { 298 if (symlen > CODA_MAXPATHLEN)
334 unlock_kernel();
335 return -ENAMETOOLONG; 299 return -ENAMETOOLONG;
336 }
337 300
338 /* 301 /*
339 * This entry is now negative. Since we do not create 302 * This entry is now negative. Since we do not create
@@ -344,10 +307,9 @@ static int coda_symlink(struct inode *dir_inode, struct dentry *de,
344 symname, symlen); 307 symname, symlen);
345 308
346 /* mtime is no good anymore */ 309 /* mtime is no good anymore */
347 if ( !error ) 310 if (!error)
348 coda_dir_update_mtime(dir_inode); 311 coda_dir_update_mtime(dir_inode);
349 312
350 unlock_kernel();
351 return error; 313 return error;
352} 314}
353 315
@@ -358,17 +320,12 @@ static int coda_unlink(struct inode *dir, struct dentry *de)
358 const char *name = de->d_name.name; 320 const char *name = de->d_name.name;
359 int len = de->d_name.len; 321 int len = de->d_name.len;
360 322
361 lock_kernel();
362
363 error = venus_remove(dir->i_sb, coda_i2f(dir), name, len); 323 error = venus_remove(dir->i_sb, coda_i2f(dir), name, len);
364 if ( error ) { 324 if (error)
365 unlock_kernel();
366 return error; 325 return error;
367 }
368 326
369 coda_dir_update_mtime(dir); 327 coda_dir_update_mtime(dir);
370 drop_nlink(de->d_inode); 328 drop_nlink(de->d_inode);
371 unlock_kernel();
372 return 0; 329 return 0;
373} 330}
374 331
@@ -378,8 +335,6 @@ static int coda_rmdir(struct inode *dir, struct dentry *de)
378 int len = de->d_name.len; 335 int len = de->d_name.len;
379 int error; 336 int error;
380 337
381 lock_kernel();
382
383 error = venus_rmdir(dir->i_sb, coda_i2f(dir), name, len); 338 error = venus_rmdir(dir->i_sb, coda_i2f(dir), name, len);
384 if (!error) { 339 if (!error) {
385 /* VFS may delete the child */ 340 /* VFS may delete the child */
@@ -390,7 +345,6 @@ static int coda_rmdir(struct inode *dir, struct dentry *de)
390 coda_dir_drop_nlink(dir); 345 coda_dir_drop_nlink(dir);
391 coda_dir_update_mtime(dir); 346 coda_dir_update_mtime(dir);
392 } 347 }
393 unlock_kernel();
394 return error; 348 return error;
395} 349}
396 350
@@ -404,15 +358,12 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry,
404 int new_length = new_dentry->d_name.len; 358 int new_length = new_dentry->d_name.len;
405 int error; 359 int error;
406 360
407 lock_kernel();
408
409 error = venus_rename(old_dir->i_sb, coda_i2f(old_dir), 361 error = venus_rename(old_dir->i_sb, coda_i2f(old_dir),
410 coda_i2f(new_dir), old_length, new_length, 362 coda_i2f(new_dir), old_length, new_length,
411 (const char *) old_name, (const char *)new_name); 363 (const char *) old_name, (const char *)new_name);
412 364 if (!error) {
413 if ( !error ) { 365 if (new_dentry->d_inode) {
414 if ( new_dentry->d_inode ) { 366 if (S_ISDIR(new_dentry->d_inode->i_mode)) {
415 if ( S_ISDIR(new_dentry->d_inode->i_mode) ) {
416 coda_dir_drop_nlink(old_dir); 367 coda_dir_drop_nlink(old_dir);
417 coda_dir_inc_nlink(new_dir); 368 coda_dir_inc_nlink(new_dir);
418 } 369 }
@@ -424,8 +375,6 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry,
424 coda_flag_inode(new_dir, C_VATTR); 375 coda_flag_inode(new_dir, C_VATTR);
425 } 376 }
426 } 377 }
427 unlock_kernel();
428
429 return error; 378 return error;
430} 379}
431 380
@@ -595,10 +544,7 @@ static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd)
595 struct inode *inode = de->d_inode; 544 struct inode *inode = de->d_inode;
596 struct coda_inode_info *cii; 545 struct coda_inode_info *cii;
597 546
598 if (!inode) 547 if (!inode || coda_isroot(inode))
599 return 1;
600 lock_kernel();
601 if (coda_isroot(inode))
602 goto out; 548 goto out;
603 if (is_bad_inode(inode)) 549 if (is_bad_inode(inode))
604 goto bad; 550 goto bad;
@@ -621,12 +567,9 @@ static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd)
621 spin_lock(&cii->c_lock); 567 spin_lock(&cii->c_lock);
622 cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH); 568 cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH);
623 spin_unlock(&cii->c_lock); 569 spin_unlock(&cii->c_lock);
624
625bad: 570bad:
626 unlock_kernel();
627 return 0; 571 return 0;
628out: 572out:
629 unlock_kernel();
630 return 1; 573 return 1;
631} 574}
632 575
@@ -659,20 +602,19 @@ static int coda_dentry_delete(struct dentry * dentry)
659int coda_revalidate_inode(struct dentry *dentry) 602int coda_revalidate_inode(struct dentry *dentry)
660{ 603{
661 struct coda_vattr attr; 604 struct coda_vattr attr;
662 int error = 0; 605 int error;
663 int old_mode; 606 int old_mode;
664 ino_t old_ino; 607 ino_t old_ino;
665 struct inode *inode = dentry->d_inode; 608 struct inode *inode = dentry->d_inode;
666 struct coda_inode_info *cii = ITOC(inode); 609 struct coda_inode_info *cii = ITOC(inode);
667 610
668 lock_kernel(); 611 if (!cii->c_flags)
669 if ( !cii->c_flags ) 612 return 0;
670 goto ok;
671 613
672 if (cii->c_flags & (C_VATTR | C_PURGE | C_FLUSH)) { 614 if (cii->c_flags & (C_VATTR | C_PURGE | C_FLUSH)) {
673 error = venus_getattr(inode->i_sb, &(cii->c_fid), &attr); 615 error = venus_getattr(inode->i_sb, &(cii->c_fid), &attr);
674 if ( error ) 616 if (error)
675 goto return_bad; 617 return -EIO;
676 618
677 /* this inode may be lost if: 619 /* this inode may be lost if:
678 - it's ino changed 620 - it's ino changed
@@ -691,7 +633,7 @@ int coda_revalidate_inode(struct dentry *dentry)
691 /* the following can happen when a local fid is replaced 633 /* the following can happen when a local fid is replaced
692 with a global one, here we lose and declare the inode bad */ 634 with a global one, here we lose and declare the inode bad */
693 if (inode->i_ino != old_ino) 635 if (inode->i_ino != old_ino)
694 goto return_bad; 636 return -EIO;
695 637
696 coda_flag_inode_children(inode, C_FLUSH); 638 coda_flag_inode_children(inode, C_FLUSH);
697 639
@@ -699,12 +641,5 @@ int coda_revalidate_inode(struct dentry *dentry)
699 cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH); 641 cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH);
700 spin_unlock(&cii->c_lock); 642 spin_unlock(&cii->c_lock);
701 } 643 }
702
703ok:
704 unlock_kernel();
705 return 0; 644 return 0;
706
707return_bad:
708 unlock_kernel();
709 return -EIO;
710} 645}
diff --git a/fs/coda/file.c b/fs/coda/file.c
index c4e395781d41..c8b50ba4366a 100644
--- a/fs/coda/file.c
+++ b/fs/coda/file.c
@@ -15,7 +15,6 @@
15#include <linux/stat.h> 15#include <linux/stat.h>
16#include <linux/cred.h> 16#include <linux/cred.h>
17#include <linux/errno.h> 17#include <linux/errno.h>
18#include <linux/smp_lock.h>
19#include <linux/spinlock.h> 18#include <linux/spinlock.h>
20#include <linux/string.h> 19#include <linux/string.h>
21#include <linux/slab.h> 20#include <linux/slab.h>
@@ -144,8 +143,6 @@ int coda_open(struct inode *coda_inode, struct file *coda_file)
144 if (!cfi) 143 if (!cfi)
145 return -ENOMEM; 144 return -ENOMEM;
146 145
147 lock_kernel();
148
149 error = venus_open(coda_inode->i_sb, coda_i2f(coda_inode), coda_flags, 146 error = venus_open(coda_inode->i_sb, coda_i2f(coda_inode), coda_flags,
150 &host_file); 147 &host_file);
151 if (!host_file) 148 if (!host_file)
@@ -153,7 +150,6 @@ int coda_open(struct inode *coda_inode, struct file *coda_file)
153 150
154 if (error) { 151 if (error) {
155 kfree(cfi); 152 kfree(cfi);
156 unlock_kernel();
157 return error; 153 return error;
158 } 154 }
159 155
@@ -165,8 +161,6 @@ int coda_open(struct inode *coda_inode, struct file *coda_file)
165 161
166 BUG_ON(coda_file->private_data != NULL); 162 BUG_ON(coda_file->private_data != NULL);
167 coda_file->private_data = cfi; 163 coda_file->private_data = cfi;
168
169 unlock_kernel();
170 return 0; 164 return 0;
171} 165}
172 166
@@ -177,9 +171,7 @@ int coda_release(struct inode *coda_inode, struct file *coda_file)
177 struct coda_file_info *cfi; 171 struct coda_file_info *cfi;
178 struct coda_inode_info *cii; 172 struct coda_inode_info *cii;
179 struct inode *host_inode; 173 struct inode *host_inode;
180 int err = 0; 174 int err;
181
182 lock_kernel();
183 175
184 cfi = CODA_FTOC(coda_file); 176 cfi = CODA_FTOC(coda_file);
185 BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC); 177 BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
@@ -203,8 +195,6 @@ int coda_release(struct inode *coda_inode, struct file *coda_file)
203 kfree(coda_file->private_data); 195 kfree(coda_file->private_data);
204 coda_file->private_data = NULL; 196 coda_file->private_data = NULL;
205 197
206 unlock_kernel();
207
208 /* VFS fput ignores the return value from file_operations->release, so 198 /* VFS fput ignores the return value from file_operations->release, so
209 * there is no use returning an error here */ 199 * there is no use returning an error here */
210 return 0; 200 return 0;
@@ -215,7 +205,7 @@ int coda_fsync(struct file *coda_file, int datasync)
215 struct file *host_file; 205 struct file *host_file;
216 struct inode *coda_inode = coda_file->f_path.dentry->d_inode; 206 struct inode *coda_inode = coda_file->f_path.dentry->d_inode;
217 struct coda_file_info *cfi; 207 struct coda_file_info *cfi;
218 int err = 0; 208 int err;
219 209
220 if (!(S_ISREG(coda_inode->i_mode) || S_ISDIR(coda_inode->i_mode) || 210 if (!(S_ISREG(coda_inode->i_mode) || S_ISDIR(coda_inode->i_mode) ||
221 S_ISLNK(coda_inode->i_mode))) 211 S_ISLNK(coda_inode->i_mode)))
@@ -226,11 +216,8 @@ int coda_fsync(struct file *coda_file, int datasync)
226 host_file = cfi->cfi_container; 216 host_file = cfi->cfi_container;
227 217
228 err = vfs_fsync(host_file, datasync); 218 err = vfs_fsync(host_file, datasync);
229 if ( !err && !datasync ) { 219 if (!err && !datasync)
230 lock_kernel();
231 err = venus_fsync(coda_inode->i_sb, coda_i2f(coda_inode)); 220 err = venus_fsync(coda_inode->i_sb, coda_i2f(coda_inode));
232 unlock_kernel();
233 }
234 221
235 return err; 222 return err;
236} 223}
diff --git a/fs/coda/inode.c b/fs/coda/inode.c
index 0553f3bd7b1b..b7fa3e3d772f 100644
--- a/fs/coda/inode.c
+++ b/fs/coda/inode.c
@@ -150,8 +150,6 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
150 int error; 150 int error;
151 int idx; 151 int idx;
152 152
153 lock_kernel();
154
155 idx = get_device_index((struct coda_mount_data *) data); 153 idx = get_device_index((struct coda_mount_data *) data);
156 154
157 /* Ignore errors in data, for backward compatibility */ 155 /* Ignore errors in data, for backward compatibility */
@@ -161,23 +159,26 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
161 printk(KERN_INFO "coda_read_super: device index: %i\n", idx); 159 printk(KERN_INFO "coda_read_super: device index: %i\n", idx);
162 160
163 vc = &coda_comms[idx]; 161 vc = &coda_comms[idx];
162 lock_kernel();
163
164 if (!vc->vc_inuse) { 164 if (!vc->vc_inuse) {
165 printk("coda_read_super: No pseudo device\n"); 165 printk("coda_read_super: No pseudo device\n");
166 unlock_kernel(); 166 error = -EINVAL;
167 return -EINVAL; 167 goto unlock_out;
168 } 168 }
169 169
170 if ( vc->vc_sb ) { 170 if (vc->vc_sb) {
171 printk("coda_read_super: Device already mounted\n"); 171 printk("coda_read_super: Device already mounted\n");
172 unlock_kernel(); 172 error = -EBUSY;
173 return -EBUSY; 173 goto unlock_out;
174 } 174 }
175 175
176 error = bdi_setup_and_register(&vc->bdi, "coda", BDI_CAP_MAP_COPY); 176 error = bdi_setup_and_register(&vc->bdi, "coda", BDI_CAP_MAP_COPY);
177 if (error) 177 if (error)
178 goto bdi_err; 178 goto unlock_out;
179 179
180 vc->vc_sb = sb; 180 vc->vc_sb = sb;
181 unlock_kernel();
181 182
182 sb->s_fs_info = vc; 183 sb->s_fs_info = vc;
183 sb->s_flags |= MS_NOATIME; 184 sb->s_flags |= MS_NOATIME;
@@ -206,21 +207,23 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
206 printk("coda_read_super: rootinode is %ld dev %s\n", 207 printk("coda_read_super: rootinode is %ld dev %s\n",
207 root->i_ino, root->i_sb->s_id); 208 root->i_ino, root->i_sb->s_id);
208 sb->s_root = d_alloc_root(root); 209 sb->s_root = d_alloc_root(root);
209 if (!sb->s_root) 210 if (!sb->s_root) {
211 error = -EINVAL;
210 goto error; 212 goto error;
211 unlock_kernel(); 213 }
212 return 0; 214 return 0;
213 215
214 error: 216error:
215 bdi_destroy(&vc->bdi);
216 bdi_err:
217 if (root) 217 if (root)
218 iput(root); 218 iput(root);
219 if (vc)
220 vc->vc_sb = NULL;
221 219
220 lock_kernel();
221 bdi_destroy(&vc->bdi);
222 vc->vc_sb = NULL;
223 sb->s_fs_info = NULL;
224unlock_out:
222 unlock_kernel(); 225 unlock_kernel();
223 return -EINVAL; 226 return error;
224} 227}
225 228
226static void coda_put_super(struct super_block *sb) 229static void coda_put_super(struct super_block *sb)
@@ -253,8 +256,6 @@ int coda_setattr(struct dentry *de, struct iattr *iattr)
253 struct coda_vattr vattr; 256 struct coda_vattr vattr;
254 int error; 257 int error;
255 258
256 lock_kernel();
257
258 memset(&vattr, 0, sizeof(vattr)); 259 memset(&vattr, 0, sizeof(vattr));
259 260
260 inode->i_ctime = CURRENT_TIME_SEC; 261 inode->i_ctime = CURRENT_TIME_SEC;
@@ -264,13 +265,10 @@ int coda_setattr(struct dentry *de, struct iattr *iattr)
264 /* Venus is responsible for truncating the container-file!!! */ 265 /* Venus is responsible for truncating the container-file!!! */
265 error = venus_setattr(inode->i_sb, coda_i2f(inode), &vattr); 266 error = venus_setattr(inode->i_sb, coda_i2f(inode), &vattr);
266 267
267 if ( !error ) { 268 if (!error) {
268 coda_vattr_to_iattr(inode, &vattr); 269 coda_vattr_to_iattr(inode, &vattr);
269 coda_cache_clear_inode(inode); 270 coda_cache_clear_inode(inode);
270 } 271 }
271
272 unlock_kernel();
273
274 return error; 272 return error;
275} 273}
276 274
@@ -284,12 +282,8 @@ static int coda_statfs(struct dentry *dentry, struct kstatfs *buf)
284{ 282{
285 int error; 283 int error;
286 284
287 lock_kernel();
288
289 error = venus_statfs(dentry, buf); 285 error = venus_statfs(dentry, buf);
290 286
291 unlock_kernel();
292
293 if (error) { 287 if (error) {
294 /* fake something like AFS does */ 288 /* fake something like AFS does */
295 buf->f_blocks = 9000000; 289 buf->f_blocks = 9000000;
diff --git a/fs/coda/pioctl.c b/fs/coda/pioctl.c
index 028a9a0f588b..2fd89b5c5c7b 100644
--- a/fs/coda/pioctl.c
+++ b/fs/coda/pioctl.c
@@ -23,8 +23,6 @@
23#include <linux/coda_fs_i.h> 23#include <linux/coda_fs_i.h>
24#include <linux/coda_psdev.h> 24#include <linux/coda_psdev.h>
25 25
26#include <linux/smp_lock.h>
27
28/* pioctl ops */ 26/* pioctl ops */
29static int coda_ioctl_permission(struct inode *inode, int mask); 27static int coda_ioctl_permission(struct inode *inode, int mask);
30static long coda_pioctl(struct file *filp, unsigned int cmd, 28static long coda_pioctl(struct file *filp, unsigned int cmd,
@@ -58,13 +56,9 @@ static long coda_pioctl(struct file *filp, unsigned int cmd,
58 struct inode *target_inode = NULL; 56 struct inode *target_inode = NULL;
59 struct coda_inode_info *cnp; 57 struct coda_inode_info *cnp;
60 58
61 lock_kernel();
62
63 /* get the Pioctl data arguments from user space */ 59 /* get the Pioctl data arguments from user space */
64 if (copy_from_user(&data, (void __user *)user_data, sizeof(data))) { 60 if (copy_from_user(&data, (void __user *)user_data, sizeof(data)))
65 error = -EINVAL; 61 return -EINVAL;
66 goto out;
67 }
68 62
69 /* 63 /*
70 * Look up the pathname. Note that the pathname is in 64 * Look up the pathname. Note that the pathname is in
@@ -76,13 +70,12 @@ static long coda_pioctl(struct file *filp, unsigned int cmd,
76 error = user_lpath(data.path, &path); 70 error = user_lpath(data.path, &path);
77 71
78 if (error) 72 if (error)
79 goto out; 73 return error;
80 else 74
81 target_inode = path.dentry->d_inode; 75 target_inode = path.dentry->d_inode;
82 76
83 /* return if it is not a Coda inode */ 77 /* return if it is not a Coda inode */
84 if (target_inode->i_sb != inode->i_sb) { 78 if (target_inode->i_sb != inode->i_sb) {
85 path_put(&path);
86 error = -EINVAL; 79 error = -EINVAL;
87 goto out; 80 goto out;
88 } 81 }
@@ -91,10 +84,7 @@ static long coda_pioctl(struct file *filp, unsigned int cmd,
91 cnp = ITOC(target_inode); 84 cnp = ITOC(target_inode);
92 85
93 error = venus_pioctl(inode->i_sb, &(cnp->c_fid), cmd, &data); 86 error = venus_pioctl(inode->i_sb, &(cnp->c_fid), cmd, &data);
94
95 path_put(&path);
96
97out: 87out:
98 unlock_kernel(); 88 path_put(&path);
99 return error; 89 return error;
100} 90}
diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c
index fdc2f3ef7ecd..9a9248e632c6 100644
--- a/fs/coda/psdev.c
+++ b/fs/coda/psdev.c
@@ -108,16 +108,9 @@ static ssize_t coda_psdev_write(struct file *file, const char __user *buf,
108 return -EFAULT; 108 return -EFAULT;
109 109
110 if (DOWNCALL(hdr.opcode)) { 110 if (DOWNCALL(hdr.opcode)) {
111 struct super_block *sb = NULL; 111 union outputArgs *dcbuf;
112 union outputArgs *dcbuf;
113 int size = sizeof(*dcbuf); 112 int size = sizeof(*dcbuf);
114 113
115 sb = vcp->vc_sb;
116 if ( !sb ) {
117 count = nbytes;
118 goto out;
119 }
120
121 if ( nbytes < sizeof(struct coda_out_hdr) ) { 114 if ( nbytes < sizeof(struct coda_out_hdr) ) {
122 printk("coda_downcall opc %d uniq %d, not enough!\n", 115 printk("coda_downcall opc %d uniq %d, not enough!\n",
123 hdr.opcode, hdr.unique); 116 hdr.opcode, hdr.unique);
@@ -137,9 +130,7 @@ static ssize_t coda_psdev_write(struct file *file, const char __user *buf,
137 } 130 }
138 131
139 /* what downcall errors does Venus handle ? */ 132 /* what downcall errors does Venus handle ? */
140 lock_kernel(); 133 error = coda_downcall(vcp, hdr.opcode, dcbuf);
141 error = coda_downcall(hdr.opcode, dcbuf, sb);
142 unlock_kernel();
143 134
144 CODA_FREE(dcbuf, nbytes); 135 CODA_FREE(dcbuf, nbytes);
145 if (error) { 136 if (error) {
diff --git a/fs/coda/symlink.c b/fs/coda/symlink.c
index 4513b7258458..af78f007a2b0 100644
--- a/fs/coda/symlink.c
+++ b/fs/coda/symlink.c
@@ -14,7 +14,6 @@
14#include <linux/stat.h> 14#include <linux/stat.h>
15#include <linux/errno.h> 15#include <linux/errno.h>
16#include <linux/pagemap.h> 16#include <linux/pagemap.h>
17#include <linux/smp_lock.h>
18 17
19#include <linux/coda.h> 18#include <linux/coda.h>
20#include <linux/coda_linux.h> 19#include <linux/coda_linux.h>
@@ -29,11 +28,9 @@ static int coda_symlink_filler(struct file *file, struct page *page)
29 unsigned int len = PAGE_SIZE; 28 unsigned int len = PAGE_SIZE;
30 char *p = kmap(page); 29 char *p = kmap(page);
31 30
32 lock_kernel();
33 cii = ITOC(inode); 31 cii = ITOC(inode);
34 32
35 error = venus_readlink(inode->i_sb, &cii->c_fid, p, &len); 33 error = venus_readlink(inode->i_sb, &cii->c_fid, p, &len);
36 unlock_kernel();
37 if (error) 34 if (error)
38 goto fail; 35 goto fail;
39 SetPageUptodate(page); 36 SetPageUptodate(page);
diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c
index b8893ab6f9e6..4c258cb5266d 100644
--- a/fs/coda/upcall.c
+++ b/fs/coda/upcall.c
@@ -27,6 +27,7 @@
27#include <linux/errno.h> 27#include <linux/errno.h>
28#include <linux/string.h> 28#include <linux/string.h>
29#include <linux/slab.h> 29#include <linux/slab.h>
30#include <linux/smp_lock.h>
30#include <asm/uaccess.h> 31#include <asm/uaccess.h>
31#include <linux/vmalloc.h> 32#include <linux/vmalloc.h>
32#include <linux/vfs.h> 33#include <linux/vfs.h>
@@ -667,18 +668,23 @@ static int coda_upcall(struct venus_comm *vcp,
667{ 668{
668 union outputArgs *out; 669 union outputArgs *out;
669 union inputArgs *sig_inputArgs; 670 union inputArgs *sig_inputArgs;
670 struct upc_req *req, *sig_req; 671 struct upc_req *req = NULL, *sig_req;
671 int error = 0; 672 int error;
673
674 lock_kernel();
672 675
673 if (!vcp->vc_inuse) { 676 if (!vcp->vc_inuse) {
674 printk(KERN_NOTICE "coda: Venus dead, not sending upcall\n"); 677 printk(KERN_NOTICE "coda: Venus dead, not sending upcall\n");
675 return -ENXIO; 678 error = -ENXIO;
679 goto exit;
676 } 680 }
677 681
678 /* Format the request message. */ 682 /* Format the request message. */
679 req = kmalloc(sizeof(struct upc_req), GFP_KERNEL); 683 req = kmalloc(sizeof(struct upc_req), GFP_KERNEL);
680 if (!req) 684 if (!req) {
681 return -ENOMEM; 685 error = -ENOMEM;
686 goto exit;
687 }
682 688
683 req->uc_data = (void *)buffer; 689 req->uc_data = (void *)buffer;
684 req->uc_flags = 0; 690 req->uc_flags = 0;
@@ -759,6 +765,7 @@ static int coda_upcall(struct venus_comm *vcp,
759 765
760exit: 766exit:
761 kfree(req); 767 kfree(req);
768 unlock_kernel();
762 return error; 769 return error;
763} 770}
764 771
@@ -796,21 +803,24 @@ exit:
796 * 803 *
797 * CODA_REPLACE -- replace one CodaFid with another throughout the name cache */ 804 * CODA_REPLACE -- replace one CodaFid with another throughout the name cache */
798 805
799int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb) 806int coda_downcall(struct venus_comm *vcp, int opcode, union outputArgs *out)
800{ 807{
801 struct inode *inode = NULL; 808 struct inode *inode = NULL;
802 struct CodaFid *fid, *newfid; 809 struct CodaFid *fid, *newfid;
810 struct super_block *sb;
803 811
804 /* Handle invalidation requests. */ 812 /* Handle invalidation requests. */
805 if ( !sb || !sb->s_root) 813 lock_kernel();
806 return 0; 814 sb = vcp->vc_sb;
815 if (!sb || !sb->s_root)
816 goto unlock_out;
807 817
808 switch (opcode) { 818 switch (opcode) {
809 case CODA_FLUSH: 819 case CODA_FLUSH:
810 coda_cache_clear_all(sb); 820 coda_cache_clear_all(sb);
811 shrink_dcache_sb(sb); 821 shrink_dcache_sb(sb);
812 if (sb->s_root->d_inode) 822 if (sb->s_root->d_inode)
813 coda_flag_inode(sb->s_root->d_inode, C_FLUSH); 823 coda_flag_inode(sb->s_root->d_inode, C_FLUSH);
814 break; 824 break;
815 825
816 case CODA_PURGEUSER: 826 case CODA_PURGEUSER:
@@ -855,9 +865,11 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
855 break; 865 break;
856 } 866 }
857 867
868unlock_out:
869 unlock_kernel();
870
858 if (inode) 871 if (inode)
859 iput(inode); 872 iput(inode);
860
861 return 0; 873 return 0;
862} 874}
863 875
diff --git a/include/linux/coda_psdev.h b/include/linux/coda_psdev.h
index 284b520934a0..1e60c5a41a5b 100644
--- a/include/linux/coda_psdev.h
+++ b/include/linux/coda_psdev.h
@@ -63,7 +63,7 @@ int venus_symlink(struct super_block *sb, struct CodaFid *fid,
63int venus_access(struct super_block *sb, struct CodaFid *fid, int mask); 63int venus_access(struct super_block *sb, struct CodaFid *fid, int mask);
64int venus_pioctl(struct super_block *sb, struct CodaFid *fid, 64int venus_pioctl(struct super_block *sb, struct CodaFid *fid,
65 unsigned int cmd, struct PioctlData *data); 65 unsigned int cmd, struct PioctlData *data);
66int coda_downcall(int opcode, union outputArgs *out, struct super_block *sb); 66int coda_downcall(struct venus_comm *vcp, int opcode, union outputArgs *out);
67int venus_fsync(struct super_block *sb, struct CodaFid *fid); 67int venus_fsync(struct super_block *sb, struct CodaFid *fid);
68int venus_statfs(struct dentry *dentry, struct kstatfs *sfs); 68int venus_statfs(struct dentry *dentry, struct kstatfs *sfs);
69 69