diff options
Diffstat (limited to 'fs/coda/dir.c')
-rw-r--r-- | fs/coda/dir.c | 149 |
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 | ||
142 | int coda_permission(struct inode *inode, int mask) | 137 | int 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 */ |
202 | static int coda_create(struct inode *dir, struct dentry *de, int mode, struct nameidata *nd) | 193 | static 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; |
220 | err_out: | ||
221 | d_drop(de); | ||
222 | return error; | ||
239 | } | 223 | } |
240 | 224 | ||
241 | static int coda_mkdir(struct inode *dir, struct dentry *de, int mode) | 225 | static 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; |
254 | err_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; | |
311 | out: | ||
312 | unlock_kernel(); | ||
313 | return(error); | ||
314 | } | 283 | } |
315 | 284 | ||
316 | 285 | ||
317 | static int coda_symlink(struct inode *dir_inode, struct dentry *de, | 286 | static 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 | |||
625 | bad: | 570 | bad: |
626 | unlock_kernel(); | ||
627 | return 0; | 571 | return 0; |
628 | out: | 572 | out: |
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) | |||
659 | int coda_revalidate_inode(struct dentry *dentry) | 602 | int 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 | |||
703 | ok: | ||
704 | unlock_kernel(); | ||
705 | return 0; | 644 | return 0; |
706 | |||
707 | return_bad: | ||
708 | unlock_kernel(); | ||
709 | return -EIO; | ||
710 | } | 645 | } |