diff options
Diffstat (limited to 'fs/coda/dir.c')
-rw-r--r-- | fs/coda/dir.c | 184 |
1 files changed, 65 insertions, 119 deletions
diff --git a/fs/coda/dir.c b/fs/coda/dir.c index ccd98b0f2b0b..2b8dae4d121e 100644 --- a/fs/coda/dir.c +++ b/fs/coda/dir.c | |||
@@ -17,15 +17,15 @@ | |||
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 | #include <linux/namei.h> | ||
21 | 22 | ||
22 | #include <asm/uaccess.h> | 23 | #include <asm/uaccess.h> |
23 | 24 | ||
24 | #include <linux/coda.h> | 25 | #include <linux/coda.h> |
25 | #include <linux/coda_linux.h> | ||
26 | #include <linux/coda_psdev.h> | 26 | #include <linux/coda_psdev.h> |
27 | #include <linux/coda_fs_i.h> | 27 | #include "coda_linux.h" |
28 | #include <linux/coda_cache.h> | 28 | #include "coda_cache.h" |
29 | 29 | ||
30 | #include "coda_int.h" | 30 | #include "coda_int.h" |
31 | 31 | ||
@@ -47,7 +47,7 @@ static int coda_readdir(struct file *file, void *buf, filldir_t filldir); | |||
47 | 47 | ||
48 | /* dentry ops */ | 48 | /* dentry ops */ |
49 | static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd); | 49 | static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd); |
50 | static int coda_dentry_delete(struct dentry *); | 50 | static int coda_dentry_delete(const struct dentry *); |
51 | 51 | ||
52 | /* support routines */ | 52 | /* support routines */ |
53 | static int coda_venus_readdir(struct file *coda_file, void *buf, | 53 | static int coda_venus_readdir(struct file *coda_file, void *buf, |
@@ -60,7 +60,7 @@ static int coda_return_EIO(void) | |||
60 | } | 60 | } |
61 | #define CODA_EIO_ERROR ((void *) (coda_return_EIO)) | 61 | #define CODA_EIO_ERROR ((void *) (coda_return_EIO)) |
62 | 62 | ||
63 | static const struct dentry_operations coda_dentry_operations = | 63 | const struct dentry_operations coda_dentry_operations = |
64 | { | 64 | { |
65 | .d_revalidate = coda_dentry_revalidate, | 65 | .d_revalidate = coda_dentry_revalidate, |
66 | .d_delete = coda_dentry_delete, | 66 | .d_delete = coda_dentry_delete, |
@@ -116,21 +116,15 @@ 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 | ||
131 | exit: | 127 | exit: |
132 | entry->d_op = &coda_dentry_operations; | ||
133 | |||
134 | if (inode && (type & CODA_NOCACHE)) | 128 | if (inode && (type & CODA_NOCACHE)) |
135 | coda_flag_inode(inode, C_VATTR | C_PURGE); | 129 | coda_flag_inode(inode, C_VATTR | C_PURGE); |
136 | 130 | ||
@@ -138,30 +132,29 @@ exit: | |||
138 | } | 132 | } |
139 | 133 | ||
140 | 134 | ||
141 | int coda_permission(struct inode *inode, int mask) | 135 | int coda_permission(struct inode *inode, int mask, unsigned int flags) |
142 | { | 136 | { |
143 | int error = 0; | 137 | int error; |
138 | |||
139 | if (flags & IPERM_FLAG_RCU) | ||
140 | return -ECHILD; | ||
144 | 141 | ||
145 | mask &= MAY_READ | MAY_WRITE | MAY_EXEC; | 142 | mask &= MAY_READ | MAY_WRITE | MAY_EXEC; |
146 | 143 | ||
147 | if (!mask) | 144 | if (!mask) |
148 | return 0; | 145 | return 0; |
149 | 146 | ||
150 | if ((mask & MAY_EXEC) && !execute_ok(inode)) | 147 | if ((mask & MAY_EXEC) && !execute_ok(inode)) |
151 | return -EACCES; | 148 | return -EACCES; |
152 | 149 | ||
153 | lock_kernel(); | ||
154 | |||
155 | if (coda_cache_check(inode, mask)) | 150 | if (coda_cache_check(inode, mask)) |
156 | goto out; | 151 | return 0; |
157 | 152 | ||
158 | error = venus_access(inode->i_sb, coda_i2f(inode), mask); | 153 | error = venus_access(inode->i_sb, coda_i2f(inode), mask); |
159 | 154 | ||
160 | if (!error) | 155 | if (!error) |
161 | coda_cache_enter(inode, mask); | 156 | coda_cache_enter(inode, mask); |
162 | 157 | ||
163 | out: | ||
164 | unlock_kernel(); | ||
165 | return error; | 158 | return error; |
166 | } | 159 | } |
167 | 160 | ||
@@ -200,41 +193,34 @@ static inline void coda_dir_drop_nlink(struct inode *dir) | |||
200 | /* creation routines: create, mknod, mkdir, link, symlink */ | 193 | /* creation routines: create, mknod, mkdir, link, symlink */ |
201 | static int coda_create(struct inode *dir, struct dentry *de, int mode, struct nameidata *nd) | 194 | static int coda_create(struct inode *dir, struct dentry *de, int mode, struct nameidata *nd) |
202 | { | 195 | { |
203 | int error=0; | 196 | int error; |
204 | const char *name=de->d_name.name; | 197 | const char *name=de->d_name.name; |
205 | int length=de->d_name.len; | 198 | int length=de->d_name.len; |
206 | struct inode *inode; | 199 | struct inode *inode; |
207 | struct CodaFid newfid; | 200 | struct CodaFid newfid; |
208 | struct coda_vattr attrs; | 201 | struct coda_vattr attrs; |
209 | 202 | ||
210 | lock_kernel(); | 203 | if (coda_isroot(dir) && coda_iscontrol(name, length)) |
211 | |||
212 | if (coda_isroot(dir) && coda_iscontrol(name, length)) { | ||
213 | unlock_kernel(); | ||
214 | return -EPERM; | 204 | return -EPERM; |
215 | } | ||
216 | 205 | ||
217 | error = venus_create(dir->i_sb, coda_i2f(dir), name, length, | 206 | error = venus_create(dir->i_sb, coda_i2f(dir), name, length, |
218 | 0, mode, &newfid, &attrs); | 207 | 0, mode, &newfid, &attrs); |
219 | 208 | if (error) | |
220 | if ( error ) { | 209 | goto err_out; |
221 | unlock_kernel(); | ||
222 | d_drop(de); | ||
223 | return error; | ||
224 | } | ||
225 | 210 | ||
226 | inode = coda_iget(dir->i_sb, &newfid, &attrs); | 211 | inode = coda_iget(dir->i_sb, &newfid, &attrs); |
227 | if ( IS_ERR(inode) ) { | 212 | if (IS_ERR(inode)) { |
228 | unlock_kernel(); | 213 | error = PTR_ERR(inode); |
229 | d_drop(de); | 214 | goto err_out; |
230 | return PTR_ERR(inode); | ||
231 | } | 215 | } |
232 | 216 | ||
233 | /* invalidate the directory cnode's attributes */ | 217 | /* invalidate the directory cnode's attributes */ |
234 | coda_dir_update_mtime(dir); | 218 | coda_dir_update_mtime(dir); |
235 | unlock_kernel(); | ||
236 | d_instantiate(de, inode); | 219 | d_instantiate(de, inode); |
237 | return 0; | 220 | return 0; |
221 | err_out: | ||
222 | d_drop(de); | ||
223 | return error; | ||
238 | } | 224 | } |
239 | 225 | ||
240 | static int coda_mkdir(struct inode *dir, struct dentry *de, int mode) | 226 | static int coda_mkdir(struct inode *dir, struct dentry *de, int mode) |
@@ -246,36 +232,29 @@ static int coda_mkdir(struct inode *dir, struct dentry *de, int mode) | |||
246 | int error; | 232 | int error; |
247 | struct CodaFid newfid; | 233 | struct CodaFid newfid; |
248 | 234 | ||
249 | lock_kernel(); | 235 | if (coda_isroot(dir) && coda_iscontrol(name, len)) |
250 | |||
251 | if (coda_isroot(dir) && coda_iscontrol(name, len)) { | ||
252 | unlock_kernel(); | ||
253 | return -EPERM; | 236 | return -EPERM; |
254 | } | ||
255 | 237 | ||
256 | attrs.va_mode = mode; | 238 | attrs.va_mode = mode; |
257 | error = venus_mkdir(dir->i_sb, coda_i2f(dir), | 239 | error = venus_mkdir(dir->i_sb, coda_i2f(dir), |
258 | name, len, &newfid, &attrs); | 240 | name, len, &newfid, &attrs); |
259 | 241 | if (error) | |
260 | if ( error ) { | 242 | goto err_out; |
261 | unlock_kernel(); | ||
262 | d_drop(de); | ||
263 | return error; | ||
264 | } | ||
265 | 243 | ||
266 | inode = coda_iget(dir->i_sb, &newfid, &attrs); | 244 | inode = coda_iget(dir->i_sb, &newfid, &attrs); |
267 | if ( IS_ERR(inode) ) { | 245 | if (IS_ERR(inode)) { |
268 | unlock_kernel(); | 246 | error = PTR_ERR(inode); |
269 | d_drop(de); | 247 | goto err_out; |
270 | return PTR_ERR(inode); | ||
271 | } | 248 | } |
272 | 249 | ||
273 | /* invalidate the directory cnode's attributes */ | 250 | /* invalidate the directory cnode's attributes */ |
274 | coda_dir_inc_nlink(dir); | 251 | coda_dir_inc_nlink(dir); |
275 | coda_dir_update_mtime(dir); | 252 | coda_dir_update_mtime(dir); |
276 | unlock_kernel(); | ||
277 | d_instantiate(de, inode); | 253 | d_instantiate(de, inode); |
278 | return 0; | 254 | return 0; |
255 | err_out: | ||
256 | d_drop(de); | ||
257 | return error; | ||
279 | } | 258 | } |
280 | 259 | ||
281 | /* try to make de an entry in dir_inodde linked to source_de */ | 260 | /* try to make de an entry in dir_inodde linked to source_de */ |
@@ -287,52 +266,38 @@ static int coda_link(struct dentry *source_de, struct inode *dir_inode, | |||
287 | int len = de->d_name.len; | 266 | int len = de->d_name.len; |
288 | int error; | 267 | int error; |
289 | 268 | ||
290 | lock_kernel(); | 269 | 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; | 270 | return -EPERM; |
295 | } | ||
296 | 271 | ||
297 | error = venus_link(dir_inode->i_sb, coda_i2f(inode), | 272 | error = venus_link(dir_inode->i_sb, coda_i2f(inode), |
298 | coda_i2f(dir_inode), (const char *)name, len); | 273 | coda_i2f(dir_inode), (const char *)name, len); |
299 | |||
300 | if (error) { | 274 | if (error) { |
301 | d_drop(de); | 275 | d_drop(de); |
302 | goto out; | 276 | return error; |
303 | } | 277 | } |
304 | 278 | ||
305 | coda_dir_update_mtime(dir_inode); | 279 | coda_dir_update_mtime(dir_inode); |
306 | atomic_inc(&inode->i_count); | 280 | ihold(inode); |
307 | d_instantiate(de, inode); | 281 | d_instantiate(de, inode); |
308 | inc_nlink(inode); | 282 | inc_nlink(inode); |
309 | 283 | return 0; | |
310 | out: | ||
311 | unlock_kernel(); | ||
312 | return(error); | ||
313 | } | 284 | } |
314 | 285 | ||
315 | 286 | ||
316 | static int coda_symlink(struct inode *dir_inode, struct dentry *de, | 287 | static int coda_symlink(struct inode *dir_inode, struct dentry *de, |
317 | const char *symname) | 288 | const char *symname) |
318 | { | 289 | { |
319 | const char *name = de->d_name.name; | 290 | const char *name = de->d_name.name; |
320 | int len = de->d_name.len; | 291 | int len = de->d_name.len; |
321 | int symlen; | 292 | int symlen; |
322 | int error = 0; | 293 | int error; |
323 | |||
324 | lock_kernel(); | ||
325 | 294 | ||
326 | if (coda_isroot(dir_inode) && coda_iscontrol(name, len)) { | 295 | if (coda_isroot(dir_inode) && coda_iscontrol(name, len)) |
327 | unlock_kernel(); | ||
328 | return -EPERM; | 296 | return -EPERM; |
329 | } | ||
330 | 297 | ||
331 | symlen = strlen(symname); | 298 | symlen = strlen(symname); |
332 | if ( symlen > CODA_MAXPATHLEN ) { | 299 | if (symlen > CODA_MAXPATHLEN) |
333 | unlock_kernel(); | ||
334 | return -ENAMETOOLONG; | 300 | return -ENAMETOOLONG; |
335 | } | ||
336 | 301 | ||
337 | /* | 302 | /* |
338 | * This entry is now negative. Since we do not create | 303 | * This entry is now negative. Since we do not create |
@@ -343,10 +308,9 @@ static int coda_symlink(struct inode *dir_inode, struct dentry *de, | |||
343 | symname, symlen); | 308 | symname, symlen); |
344 | 309 | ||
345 | /* mtime is no good anymore */ | 310 | /* mtime is no good anymore */ |
346 | if ( !error ) | 311 | if (!error) |
347 | coda_dir_update_mtime(dir_inode); | 312 | coda_dir_update_mtime(dir_inode); |
348 | 313 | ||
349 | unlock_kernel(); | ||
350 | return error; | 314 | return error; |
351 | } | 315 | } |
352 | 316 | ||
@@ -357,17 +321,12 @@ static int coda_unlink(struct inode *dir, struct dentry *de) | |||
357 | const char *name = de->d_name.name; | 321 | const char *name = de->d_name.name; |
358 | int len = de->d_name.len; | 322 | int len = de->d_name.len; |
359 | 323 | ||
360 | lock_kernel(); | ||
361 | |||
362 | error = venus_remove(dir->i_sb, coda_i2f(dir), name, len); | 324 | error = venus_remove(dir->i_sb, coda_i2f(dir), name, len); |
363 | if ( error ) { | 325 | if (error) |
364 | unlock_kernel(); | ||
365 | return error; | 326 | return error; |
366 | } | ||
367 | 327 | ||
368 | coda_dir_update_mtime(dir); | 328 | coda_dir_update_mtime(dir); |
369 | drop_nlink(de->d_inode); | 329 | drop_nlink(de->d_inode); |
370 | unlock_kernel(); | ||
371 | return 0; | 330 | return 0; |
372 | } | 331 | } |
373 | 332 | ||
@@ -377,8 +336,6 @@ static int coda_rmdir(struct inode *dir, struct dentry *de) | |||
377 | int len = de->d_name.len; | 336 | int len = de->d_name.len; |
378 | int error; | 337 | int error; |
379 | 338 | ||
380 | lock_kernel(); | ||
381 | |||
382 | error = venus_rmdir(dir->i_sb, coda_i2f(dir), name, len); | 339 | error = venus_rmdir(dir->i_sb, coda_i2f(dir), name, len); |
383 | if (!error) { | 340 | if (!error) { |
384 | /* VFS may delete the child */ | 341 | /* VFS may delete the child */ |
@@ -389,7 +346,6 @@ static int coda_rmdir(struct inode *dir, struct dentry *de) | |||
389 | coda_dir_drop_nlink(dir); | 346 | coda_dir_drop_nlink(dir); |
390 | coda_dir_update_mtime(dir); | 347 | coda_dir_update_mtime(dir); |
391 | } | 348 | } |
392 | unlock_kernel(); | ||
393 | return error; | 349 | return error; |
394 | } | 350 | } |
395 | 351 | ||
@@ -403,15 +359,12 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
403 | int new_length = new_dentry->d_name.len; | 359 | int new_length = new_dentry->d_name.len; |
404 | int error; | 360 | int error; |
405 | 361 | ||
406 | lock_kernel(); | ||
407 | |||
408 | error = venus_rename(old_dir->i_sb, coda_i2f(old_dir), | 362 | error = venus_rename(old_dir->i_sb, coda_i2f(old_dir), |
409 | coda_i2f(new_dir), old_length, new_length, | 363 | coda_i2f(new_dir), old_length, new_length, |
410 | (const char *) old_name, (const char *)new_name); | 364 | (const char *) old_name, (const char *)new_name); |
411 | 365 | if (!error) { | |
412 | if ( !error ) { | 366 | if (new_dentry->d_inode) { |
413 | if ( new_dentry->d_inode ) { | 367 | 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); | 368 | coda_dir_drop_nlink(old_dir); |
416 | coda_dir_inc_nlink(new_dir); | 369 | coda_dir_inc_nlink(new_dir); |
417 | } | 370 | } |
@@ -423,8 +376,6 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
423 | coda_flag_inode(new_dir, C_VATTR); | 376 | coda_flag_inode(new_dir, C_VATTR); |
424 | } | 377 | } |
425 | } | 378 | } |
426 | unlock_kernel(); | ||
427 | |||
428 | return error; | 379 | return error; |
429 | } | 380 | } |
430 | 381 | ||
@@ -591,13 +542,14 @@ out: | |||
591 | /* called when a cache lookup succeeds */ | 542 | /* called when a cache lookup succeeds */ |
592 | static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd) | 543 | static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd) |
593 | { | 544 | { |
594 | struct inode *inode = de->d_inode; | 545 | struct inode *inode; |
595 | struct coda_inode_info *cii; | 546 | struct coda_inode_info *cii; |
596 | 547 | ||
597 | if (!inode) | 548 | if (nd->flags & LOOKUP_RCU) |
598 | return 1; | 549 | return -ECHILD; |
599 | lock_kernel(); | 550 | |
600 | if (coda_isroot(inode)) | 551 | inode = de->d_inode; |
552 | if (!inode || coda_isroot(inode)) | ||
601 | goto out; | 553 | goto out; |
602 | if (is_bad_inode(inode)) | 554 | if (is_bad_inode(inode)) |
603 | goto bad; | 555 | goto bad; |
@@ -612,18 +564,17 @@ static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd) | |||
612 | if (cii->c_flags & C_FLUSH) | 564 | if (cii->c_flags & C_FLUSH) |
613 | coda_flag_inode_children(inode, C_FLUSH); | 565 | coda_flag_inode_children(inode, C_FLUSH); |
614 | 566 | ||
615 | if (atomic_read(&de->d_count) > 1) | 567 | if (de->d_count > 1) |
616 | /* pretend it's valid, but don't change the flags */ | 568 | /* pretend it's valid, but don't change the flags */ |
617 | goto out; | 569 | goto out; |
618 | 570 | ||
619 | /* clear the flags. */ | 571 | /* clear the flags. */ |
572 | spin_lock(&cii->c_lock); | ||
620 | cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH); | 573 | cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH); |
621 | 574 | spin_unlock(&cii->c_lock); | |
622 | bad: | 575 | bad: |
623 | unlock_kernel(); | ||
624 | return 0; | 576 | return 0; |
625 | out: | 577 | out: |
626 | unlock_kernel(); | ||
627 | return 1; | 578 | return 1; |
628 | } | 579 | } |
629 | 580 | ||
@@ -631,7 +582,7 @@ out: | |||
631 | * This is the callback from dput() when d_count is going to 0. | 582 | * This is the callback from dput() when d_count is going to 0. |
632 | * We use this to unhash dentries with bad inodes. | 583 | * We use this to unhash dentries with bad inodes. |
633 | */ | 584 | */ |
634 | static int coda_dentry_delete(struct dentry * dentry) | 585 | static int coda_dentry_delete(const struct dentry * dentry) |
635 | { | 586 | { |
636 | int flags; | 587 | int flags; |
637 | 588 | ||
@@ -656,20 +607,19 @@ static int coda_dentry_delete(struct dentry * dentry) | |||
656 | int coda_revalidate_inode(struct dentry *dentry) | 607 | int coda_revalidate_inode(struct dentry *dentry) |
657 | { | 608 | { |
658 | struct coda_vattr attr; | 609 | struct coda_vattr attr; |
659 | int error = 0; | 610 | int error; |
660 | int old_mode; | 611 | int old_mode; |
661 | ino_t old_ino; | 612 | ino_t old_ino; |
662 | struct inode *inode = dentry->d_inode; | 613 | struct inode *inode = dentry->d_inode; |
663 | struct coda_inode_info *cii = ITOC(inode); | 614 | struct coda_inode_info *cii = ITOC(inode); |
664 | 615 | ||
665 | lock_kernel(); | 616 | if (!cii->c_flags) |
666 | if ( !cii->c_flags ) | 617 | return 0; |
667 | goto ok; | ||
668 | 618 | ||
669 | if (cii->c_flags & (C_VATTR | C_PURGE | C_FLUSH)) { | 619 | if (cii->c_flags & (C_VATTR | C_PURGE | C_FLUSH)) { |
670 | error = venus_getattr(inode->i_sb, &(cii->c_fid), &attr); | 620 | error = venus_getattr(inode->i_sb, &(cii->c_fid), &attr); |
671 | if ( error ) | 621 | if (error) |
672 | goto return_bad; | 622 | return -EIO; |
673 | 623 | ||
674 | /* this inode may be lost if: | 624 | /* this inode may be lost if: |
675 | - it's ino changed | 625 | - it's ino changed |
@@ -688,17 +638,13 @@ int coda_revalidate_inode(struct dentry *dentry) | |||
688 | /* the following can happen when a local fid is replaced | 638 | /* the following can happen when a local fid is replaced |
689 | with a global one, here we lose and declare the inode bad */ | 639 | with a global one, here we lose and declare the inode bad */ |
690 | if (inode->i_ino != old_ino) | 640 | if (inode->i_ino != old_ino) |
691 | goto return_bad; | 641 | return -EIO; |
692 | 642 | ||
693 | coda_flag_inode_children(inode, C_FLUSH); | 643 | coda_flag_inode_children(inode, C_FLUSH); |
644 | |||
645 | spin_lock(&cii->c_lock); | ||
694 | cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH); | 646 | cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH); |
647 | spin_unlock(&cii->c_lock); | ||
695 | } | 648 | } |
696 | |||
697 | ok: | ||
698 | unlock_kernel(); | ||
699 | return 0; | 649 | return 0; |
700 | |||
701 | return_bad: | ||
702 | unlock_kernel(); | ||
703 | return -EIO; | ||
704 | } | 650 | } |