aboutsummaryrefslogtreecommitdiffstats
path: root/fs/coda/dir.c
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 /fs/coda/dir.c
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>
Diffstat (limited to 'fs/coda/dir.c')
-rw-r--r--fs/coda/dir.c149
1 files changed, 42 insertions, 107 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}