diff options
Diffstat (limited to 'fs/coda/dir.c')
-rw-r--r-- | fs/coda/dir.c | 157 |
1 files changed, 49 insertions, 108 deletions
diff --git a/fs/coda/dir.c b/fs/coda/dir.c index ccd98b0f2b0b..5d8b35539601 100644 --- a/fs/coda/dir.c +++ b/fs/coda/dir.c | |||
@@ -17,7 +17,7 @@ | |||
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> | 20 | #include <linux/spinlock.h> |
21 | 21 | ||
22 | #include <asm/uaccess.h> | 22 | #include <asm/uaccess.h> |
23 | 23 | ||
@@ -116,15 +116,11 @@ static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, struc | |||
116 | goto exit; | 116 | goto exit; |
117 | } | 117 | } |
118 | 118 | ||
119 | lock_kernel(); | ||
120 | |||
121 | error = venus_lookup(dir->i_sb, coda_i2f(dir), name, length, | 119 | error = venus_lookup(dir->i_sb, coda_i2f(dir), name, length, |
122 | &type, &resfid); | 120 | &type, &resfid); |
123 | if (!error) | 121 | if (!error) |
124 | error = coda_cnode_make(&inode, &resfid, dir->i_sb); | 122 | error = coda_cnode_make(&inode, &resfid, dir->i_sb); |
125 | 123 | ||
126 | unlock_kernel(); | ||
127 | |||
128 | if (error && error != -ENOENT) | 124 | if (error && error != -ENOENT) |
129 | return ERR_PTR(error); | 125 | return ERR_PTR(error); |
130 | 126 | ||
@@ -140,28 +136,24 @@ exit: | |||
140 | 136 | ||
141 | int coda_permission(struct inode *inode, int mask) | 137 | int coda_permission(struct inode *inode, int mask) |
142 | { | 138 | { |
143 | int error = 0; | 139 | int error; |
144 | 140 | ||
145 | mask &= MAY_READ | MAY_WRITE | MAY_EXEC; | 141 | mask &= MAY_READ | MAY_WRITE | MAY_EXEC; |
146 | 142 | ||
147 | if (!mask) | 143 | if (!mask) |
148 | return 0; | 144 | return 0; |
149 | 145 | ||
150 | if ((mask & MAY_EXEC) && !execute_ok(inode)) | 146 | if ((mask & MAY_EXEC) && !execute_ok(inode)) |
151 | return -EACCES; | 147 | return -EACCES; |
152 | 148 | ||
153 | lock_kernel(); | ||
154 | |||
155 | if (coda_cache_check(inode, mask)) | 149 | if (coda_cache_check(inode, mask)) |
156 | goto out; | 150 | return 0; |
157 | 151 | ||
158 | error = venus_access(inode->i_sb, coda_i2f(inode), mask); | 152 | error = venus_access(inode->i_sb, coda_i2f(inode), mask); |
159 | 153 | ||
160 | if (!error) | 154 | if (!error) |
161 | coda_cache_enter(inode, mask); | 155 | coda_cache_enter(inode, mask); |
162 | 156 | ||
163 | out: | ||
164 | unlock_kernel(); | ||
165 | return error; | 157 | return error; |
166 | } | 158 | } |
167 | 159 | ||
@@ -200,41 +192,34 @@ static inline void coda_dir_drop_nlink(struct inode *dir) | |||
200 | /* creation routines: create, mknod, mkdir, link, symlink */ | 192 | /* creation routines: create, mknod, mkdir, link, symlink */ |
201 | 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) |
202 | { | 194 | { |
203 | int error=0; | 195 | int error; |
204 | const char *name=de->d_name.name; | 196 | const char *name=de->d_name.name; |
205 | int length=de->d_name.len; | 197 | int length=de->d_name.len; |
206 | struct inode *inode; | 198 | struct inode *inode; |
207 | struct CodaFid newfid; | 199 | struct CodaFid newfid; |
208 | struct coda_vattr attrs; | 200 | struct coda_vattr attrs; |
209 | 201 | ||
210 | lock_kernel(); | 202 | if (coda_isroot(dir) && coda_iscontrol(name, length)) |
211 | |||
212 | if (coda_isroot(dir) && coda_iscontrol(name, length)) { | ||
213 | unlock_kernel(); | ||
214 | return -EPERM; | 203 | return -EPERM; |
215 | } | ||
216 | 204 | ||
217 | error = venus_create(dir->i_sb, coda_i2f(dir), name, length, | 205 | error = venus_create(dir->i_sb, coda_i2f(dir), name, length, |
218 | 0, mode, &newfid, &attrs); | 206 | 0, mode, &newfid, &attrs); |
219 | 207 | if (error) | |
220 | if ( error ) { | 208 | goto err_out; |
221 | unlock_kernel(); | ||
222 | d_drop(de); | ||
223 | return error; | ||
224 | } | ||
225 | 209 | ||
226 | inode = coda_iget(dir->i_sb, &newfid, &attrs); | 210 | inode = coda_iget(dir->i_sb, &newfid, &attrs); |
227 | if ( IS_ERR(inode) ) { | 211 | if (IS_ERR(inode)) { |
228 | unlock_kernel(); | 212 | error = PTR_ERR(inode); |
229 | d_drop(de); | 213 | goto err_out; |
230 | return PTR_ERR(inode); | ||
231 | } | 214 | } |
232 | 215 | ||
233 | /* invalidate the directory cnode's attributes */ | 216 | /* invalidate the directory cnode's attributes */ |
234 | coda_dir_update_mtime(dir); | 217 | coda_dir_update_mtime(dir); |
235 | unlock_kernel(); | ||
236 | d_instantiate(de, inode); | 218 | d_instantiate(de, inode); |
237 | return 0; | 219 | return 0; |
220 | err_out: | ||
221 | d_drop(de); | ||
222 | return error; | ||
238 | } | 223 | } |
239 | 224 | ||
240 | 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) |
@@ -246,36 +231,29 @@ static int coda_mkdir(struct inode *dir, struct dentry *de, int mode) | |||
246 | int error; | 231 | int error; |
247 | struct CodaFid newfid; | 232 | struct CodaFid newfid; |
248 | 233 | ||
249 | lock_kernel(); | 234 | if (coda_isroot(dir) && coda_iscontrol(name, len)) |
250 | |||
251 | if (coda_isroot(dir) && coda_iscontrol(name, len)) { | ||
252 | unlock_kernel(); | ||
253 | return -EPERM; | 235 | return -EPERM; |
254 | } | ||
255 | 236 | ||
256 | attrs.va_mode = mode; | 237 | attrs.va_mode = mode; |
257 | error = venus_mkdir(dir->i_sb, coda_i2f(dir), | 238 | error = venus_mkdir(dir->i_sb, coda_i2f(dir), |
258 | name, len, &newfid, &attrs); | 239 | name, len, &newfid, &attrs); |
259 | 240 | if (error) | |
260 | if ( error ) { | 241 | goto err_out; |
261 | unlock_kernel(); | ||
262 | d_drop(de); | ||
263 | return error; | ||
264 | } | ||
265 | 242 | ||
266 | inode = coda_iget(dir->i_sb, &newfid, &attrs); | 243 | inode = coda_iget(dir->i_sb, &newfid, &attrs); |
267 | if ( IS_ERR(inode) ) { | 244 | if (IS_ERR(inode)) { |
268 | unlock_kernel(); | 245 | error = PTR_ERR(inode); |
269 | d_drop(de); | 246 | goto err_out; |
270 | return PTR_ERR(inode); | ||
271 | } | 247 | } |
272 | 248 | ||
273 | /* invalidate the directory cnode's attributes */ | 249 | /* invalidate the directory cnode's attributes */ |
274 | coda_dir_inc_nlink(dir); | 250 | coda_dir_inc_nlink(dir); |
275 | coda_dir_update_mtime(dir); | 251 | coda_dir_update_mtime(dir); |
276 | unlock_kernel(); | ||
277 | d_instantiate(de, inode); | 252 | d_instantiate(de, inode); |
278 | return 0; | 253 | return 0; |
254 | err_out: | ||
255 | d_drop(de); | ||
256 | return error; | ||
279 | } | 257 | } |
280 | 258 | ||
281 | /* 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 */ |
@@ -287,52 +265,38 @@ static int coda_link(struct dentry *source_de, struct inode *dir_inode, | |||
287 | int len = de->d_name.len; | 265 | int len = de->d_name.len; |
288 | int error; | 266 | int error; |
289 | 267 | ||
290 | lock_kernel(); | 268 | if (coda_isroot(dir_inode) && coda_iscontrol(name, len)) |
291 | |||
292 | if (coda_isroot(dir_inode) && coda_iscontrol(name, len)) { | ||
293 | unlock_kernel(); | ||
294 | return -EPERM; | 269 | return -EPERM; |
295 | } | ||
296 | 270 | ||
297 | error = venus_link(dir_inode->i_sb, coda_i2f(inode), | 271 | error = venus_link(dir_inode->i_sb, coda_i2f(inode), |
298 | coda_i2f(dir_inode), (const char *)name, len); | 272 | coda_i2f(dir_inode), (const char *)name, len); |
299 | |||
300 | if (error) { | 273 | if (error) { |
301 | d_drop(de); | 274 | d_drop(de); |
302 | goto out; | 275 | return error; |
303 | } | 276 | } |
304 | 277 | ||
305 | coda_dir_update_mtime(dir_inode); | 278 | coda_dir_update_mtime(dir_inode); |
306 | atomic_inc(&inode->i_count); | 279 | ihold(inode); |
307 | d_instantiate(de, inode); | 280 | d_instantiate(de, inode); |
308 | inc_nlink(inode); | 281 | inc_nlink(inode); |
309 | 282 | return 0; | |
310 | out: | ||
311 | unlock_kernel(); | ||
312 | return(error); | ||
313 | } | 283 | } |
314 | 284 | ||
315 | 285 | ||
316 | static int coda_symlink(struct inode *dir_inode, struct dentry *de, | 286 | static int coda_symlink(struct inode *dir_inode, struct dentry *de, |
317 | const char *symname) | 287 | const char *symname) |
318 | { | 288 | { |
319 | const char *name = de->d_name.name; | 289 | const char *name = de->d_name.name; |
320 | int len = de->d_name.len; | 290 | int len = de->d_name.len; |
321 | int symlen; | 291 | int symlen; |
322 | int error = 0; | 292 | int error; |
323 | |||
324 | lock_kernel(); | ||
325 | 293 | ||
326 | if (coda_isroot(dir_inode) && coda_iscontrol(name, len)) { | 294 | if (coda_isroot(dir_inode) && coda_iscontrol(name, len)) |
327 | unlock_kernel(); | ||
328 | return -EPERM; | 295 | return -EPERM; |
329 | } | ||
330 | 296 | ||
331 | symlen = strlen(symname); | 297 | symlen = strlen(symname); |
332 | if ( symlen > CODA_MAXPATHLEN ) { | 298 | if (symlen > CODA_MAXPATHLEN) |
333 | unlock_kernel(); | ||
334 | return -ENAMETOOLONG; | 299 | return -ENAMETOOLONG; |
335 | } | ||
336 | 300 | ||
337 | /* | 301 | /* |
338 | * This entry is now negative. Since we do not create | 302 | * This entry is now negative. Since we do not create |
@@ -343,10 +307,9 @@ static int coda_symlink(struct inode *dir_inode, struct dentry *de, | |||
343 | symname, symlen); | 307 | symname, symlen); |
344 | 308 | ||
345 | /* mtime is no good anymore */ | 309 | /* mtime is no good anymore */ |
346 | if ( !error ) | 310 | if (!error) |
347 | coda_dir_update_mtime(dir_inode); | 311 | coda_dir_update_mtime(dir_inode); |
348 | 312 | ||
349 | unlock_kernel(); | ||
350 | return error; | 313 | return error; |
351 | } | 314 | } |
352 | 315 | ||
@@ -357,17 +320,12 @@ static int coda_unlink(struct inode *dir, struct dentry *de) | |||
357 | const char *name = de->d_name.name; | 320 | const char *name = de->d_name.name; |
358 | int len = de->d_name.len; | 321 | int len = de->d_name.len; |
359 | 322 | ||
360 | lock_kernel(); | ||
361 | |||
362 | error = venus_remove(dir->i_sb, coda_i2f(dir), name, len); | 323 | error = venus_remove(dir->i_sb, coda_i2f(dir), name, len); |
363 | if ( error ) { | 324 | if (error) |
364 | unlock_kernel(); | ||
365 | return error; | 325 | return error; |
366 | } | ||
367 | 326 | ||
368 | coda_dir_update_mtime(dir); | 327 | coda_dir_update_mtime(dir); |
369 | drop_nlink(de->d_inode); | 328 | drop_nlink(de->d_inode); |
370 | unlock_kernel(); | ||
371 | return 0; | 329 | return 0; |
372 | } | 330 | } |
373 | 331 | ||
@@ -377,8 +335,6 @@ static int coda_rmdir(struct inode *dir, struct dentry *de) | |||
377 | int len = de->d_name.len; | 335 | int len = de->d_name.len; |
378 | int error; | 336 | int error; |
379 | 337 | ||
380 | lock_kernel(); | ||
381 | |||
382 | error = venus_rmdir(dir->i_sb, coda_i2f(dir), name, len); | 338 | error = venus_rmdir(dir->i_sb, coda_i2f(dir), name, len); |
383 | if (!error) { | 339 | if (!error) { |
384 | /* VFS may delete the child */ | 340 | /* VFS may delete the child */ |
@@ -389,7 +345,6 @@ static int coda_rmdir(struct inode *dir, struct dentry *de) | |||
389 | coda_dir_drop_nlink(dir); | 345 | coda_dir_drop_nlink(dir); |
390 | coda_dir_update_mtime(dir); | 346 | coda_dir_update_mtime(dir); |
391 | } | 347 | } |
392 | unlock_kernel(); | ||
393 | return error; | 348 | return error; |
394 | } | 349 | } |
395 | 350 | ||
@@ -403,15 +358,12 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
403 | int new_length = new_dentry->d_name.len; | 358 | int new_length = new_dentry->d_name.len; |
404 | int error; | 359 | int error; |
405 | 360 | ||
406 | lock_kernel(); | ||
407 | |||
408 | error = venus_rename(old_dir->i_sb, coda_i2f(old_dir), | 361 | error = venus_rename(old_dir->i_sb, coda_i2f(old_dir), |
409 | coda_i2f(new_dir), old_length, new_length, | 362 | coda_i2f(new_dir), old_length, new_length, |
410 | (const char *) old_name, (const char *)new_name); | 363 | (const char *) old_name, (const char *)new_name); |
411 | 364 | if (!error) { | |
412 | if ( !error ) { | 365 | if (new_dentry->d_inode) { |
413 | if ( new_dentry->d_inode ) { | 366 | if (S_ISDIR(new_dentry->d_inode->i_mode)) { |
414 | if ( S_ISDIR(new_dentry->d_inode->i_mode) ) { | ||
415 | coda_dir_drop_nlink(old_dir); | 367 | coda_dir_drop_nlink(old_dir); |
416 | coda_dir_inc_nlink(new_dir); | 368 | coda_dir_inc_nlink(new_dir); |
417 | } | 369 | } |
@@ -423,8 +375,6 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
423 | coda_flag_inode(new_dir, C_VATTR); | 375 | coda_flag_inode(new_dir, C_VATTR); |
424 | } | 376 | } |
425 | } | 377 | } |
426 | unlock_kernel(); | ||
427 | |||
428 | return error; | 378 | return error; |
429 | } | 379 | } |
430 | 380 | ||
@@ -594,10 +544,7 @@ static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd) | |||
594 | struct inode *inode = de->d_inode; | 544 | struct inode *inode = de->d_inode; |
595 | struct coda_inode_info *cii; | 545 | struct coda_inode_info *cii; |
596 | 546 | ||
597 | if (!inode) | 547 | if (!inode || coda_isroot(inode)) |
598 | return 1; | ||
599 | lock_kernel(); | ||
600 | if (coda_isroot(inode)) | ||
601 | goto out; | 548 | goto out; |
602 | if (is_bad_inode(inode)) | 549 | if (is_bad_inode(inode)) |
603 | goto bad; | 550 | goto bad; |
@@ -617,13 +564,12 @@ static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd) | |||
617 | goto out; | 564 | goto out; |
618 | 565 | ||
619 | /* clear the flags. */ | 566 | /* clear the flags. */ |
567 | spin_lock(&cii->c_lock); | ||
620 | cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH); | 568 | cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH); |
621 | 569 | spin_unlock(&cii->c_lock); | |
622 | bad: | 570 | bad: |
623 | unlock_kernel(); | ||
624 | return 0; | 571 | return 0; |
625 | out: | 572 | out: |
626 | unlock_kernel(); | ||
627 | return 1; | 573 | return 1; |
628 | } | 574 | } |
629 | 575 | ||
@@ -656,20 +602,19 @@ static int coda_dentry_delete(struct dentry * dentry) | |||
656 | int coda_revalidate_inode(struct dentry *dentry) | 602 | int coda_revalidate_inode(struct dentry *dentry) |
657 | { | 603 | { |
658 | struct coda_vattr attr; | 604 | struct coda_vattr attr; |
659 | int error = 0; | 605 | int error; |
660 | int old_mode; | 606 | int old_mode; |
661 | ino_t old_ino; | 607 | ino_t old_ino; |
662 | struct inode *inode = dentry->d_inode; | 608 | struct inode *inode = dentry->d_inode; |
663 | struct coda_inode_info *cii = ITOC(inode); | 609 | struct coda_inode_info *cii = ITOC(inode); |
664 | 610 | ||
665 | lock_kernel(); | 611 | if (!cii->c_flags) |
666 | if ( !cii->c_flags ) | 612 | return 0; |
667 | goto ok; | ||
668 | 613 | ||
669 | if (cii->c_flags & (C_VATTR | C_PURGE | C_FLUSH)) { | 614 | if (cii->c_flags & (C_VATTR | C_PURGE | C_FLUSH)) { |
670 | error = venus_getattr(inode->i_sb, &(cii->c_fid), &attr); | 615 | error = venus_getattr(inode->i_sb, &(cii->c_fid), &attr); |
671 | if ( error ) | 616 | if (error) |
672 | goto return_bad; | 617 | return -EIO; |
673 | 618 | ||
674 | /* this inode may be lost if: | 619 | /* this inode may be lost if: |
675 | - it's ino changed | 620 | - it's ino changed |
@@ -688,17 +633,13 @@ int coda_revalidate_inode(struct dentry *dentry) | |||
688 | /* the following can happen when a local fid is replaced | 633 | /* the following can happen when a local fid is replaced |
689 | 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 */ |
690 | if (inode->i_ino != old_ino) | 635 | if (inode->i_ino != old_ino) |
691 | goto return_bad; | 636 | return -EIO; |
692 | 637 | ||
693 | coda_flag_inode_children(inode, C_FLUSH); | 638 | coda_flag_inode_children(inode, C_FLUSH); |
639 | |||
640 | spin_lock(&cii->c_lock); | ||
694 | cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH); | 641 | cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH); |
642 | spin_unlock(&cii->c_lock); | ||
695 | } | 643 | } |
696 | |||
697 | ok: | ||
698 | unlock_kernel(); | ||
699 | return 0; | 644 | return 0; |
700 | |||
701 | return_bad: | ||
702 | unlock_kernel(); | ||
703 | return -EIO; | ||
704 | } | 645 | } |