File: /usr/src/linux/fs/coda/dir.c
1
2 /*
3 * Directory operations for Coda filesystem
4 * Original version: (C) 1996 P. Braam and M. Callahan
5 * Rewritten for Linux 2.1. (C) 1997 Carnegie Mellon University
6 *
7 * Carnegie Mellon encourages users to contribute improvements to
8 * the Coda project. Contact Peter Braam (coda@cs.cmu.edu).
9 */
10
11 #include <linux/types.h>
12 #include <linux/kernel.h>
13 #include <linux/sched.h>
14 #include <linux/fs.h>
15 #include <linux/file.h>
16 #include <linux/stat.h>
17 #include <linux/errno.h>
18 #include <linux/locks.h>
19 #include <linux/string.h>
20 #include <linux/smp_lock.h>
21
22 #include <asm/uaccess.h>
23
24 #include <linux/coda.h>
25 #include <linux/coda_linux.h>
26 #include <linux/coda_psdev.h>
27 #include <linux/coda_fs_i.h>
28 #include <linux/coda_cache.h>
29 #include <linux/coda_proc.h>
30
31 /* dir inode-ops */
32 static int coda_create(struct inode *dir, struct dentry *new, int mode);
33 static int coda_mknod(struct inode *dir, struct dentry *new, int mode, int rdev);
34 static struct dentry *coda_lookup(struct inode *dir, struct dentry *target);
35 static int coda_link(struct dentry *old_dentry, struct inode *dir_inode,
36 struct dentry *entry);
37 static int coda_unlink(struct inode *dir_inode, struct dentry *entry);
38 static int coda_symlink(struct inode *dir_inode, struct dentry *entry,
39 const char *symname);
40 static int coda_mkdir(struct inode *dir_inode, struct dentry *entry, int mode);
41 static int coda_rmdir(struct inode *dir_inode, struct dentry *entry);
42 static int coda_rename(struct inode *old_inode, struct dentry *old_dentry,
43 struct inode *new_inode, struct dentry *new_dentry);
44
45 /* dir file-ops */
46 static int coda_readdir(struct file *file, void *dirent, filldir_t filldir);
47
48 /* dentry ops */
49 static int coda_dentry_revalidate(struct dentry *de, int);
50 static int coda_dentry_delete(struct dentry *);
51
52 /* support routines */
53 static void coda_prepare_fakefile(struct file *coda_file,
54 struct dentry *open_dentry,
55 struct file *open_file);
56 static int coda_venus_readdir(struct file *filp, void *dirent,
57 filldir_t filldir);
58 int coda_fsync(struct file *, struct dentry *dentry, int datasync);
59
60 int coda_hasmknod;
61
62 struct dentry_operations coda_dentry_operations =
63 {
64 d_revalidate: coda_dentry_revalidate,
65 d_delete: coda_dentry_delete,
66 };
67
68 struct inode_operations coda_dir_inode_operations =
69 {
70 create: coda_create,
71 lookup: coda_lookup,
72 link: coda_link,
73 unlink: coda_unlink,
74 symlink: coda_symlink,
75 mkdir: coda_mkdir,
76 rmdir: coda_rmdir,
77 mknod: coda_mknod,
78 rename: coda_rename,
79 permission: coda_permission,
80 revalidate: coda_revalidate_inode,
81 setattr: coda_notify_change,
82 };
83
84 struct file_operations coda_dir_operations = {
85 read: generic_read_dir,
86 readdir: coda_readdir,
87 open: coda_open,
88 flush: coda_flush,
89 release: coda_release,
90 fsync: coda_fsync,
91 };
92
93
94 /* inode operations for directories */
95 /* access routines: lookup, readlink, permission */
96 static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry)
97 {
98 struct inode *res_inode = NULL;
99 struct ViceFid resfid = {0,0,0};
100 int dropme = 0; /* to indicate entry should not be cached */
101 int type = 0;
102 int error = 0;
103 const char *name = entry->d_name.name;
104 size_t length = entry->d_name.len;
105
106 ENTRY;
107
108 if ( length > CODA_MAXNAMLEN ) {
109 printk("name too long: lookup, %s (%*s)\n",
110 coda_i2s(dir), (int)length, name);
111 return ERR_PTR(-ENAMETOOLONG);
112 }
113
114 CDEBUG(D_INODE, "name %s, len %ld in ino %ld, fid %s\n",
115 name, (long)length, dir->i_ino, coda_i2s(dir));
116
117 /* control object, create inode on the fly */
118 if (coda_isroot(dir) && coda_iscontrol(name, length)) {
119 error = coda_cnode_makectl(&res_inode, dir->i_sb);
120 CDEBUG(D_SPECIAL,
121 "Lookup on CTL object; dir ino %ld, count %d\n",
122 dir->i_ino, atomic_read(&dir->i_count));
123 dropme = 1;
124 goto exit;
125 }
126
127 error = venus_lookup(dir->i_sb, coda_i2f(dir),
128 (const char *)name, length, &type, &resfid);
129
130 res_inode = NULL;
131 if (!error) {
132 if (type & CODA_NOCACHE) {
133 type &= (~CODA_NOCACHE);
134 CDEBUG(D_INODE, "dropme set for %s\n",
135 coda_f2s(&resfid));
136 dropme = 1;
137 }
138
139 error = coda_cnode_make(&res_inode, &resfid, dir->i_sb);
140 if (error) return ERR_PTR(error);
141 } else if (error != -ENOENT) {
142 CDEBUG(D_INODE, "error for %s(%*s)%d\n",
143 coda_i2s(dir), (int)length, name, error);
144 return ERR_PTR(error);
145 }
146 CDEBUG(D_INODE, "lookup: %s is (%s), type %d result %d, dropme %d\n",
147 name, coda_f2s(&resfid), type, error, dropme);
148
149 exit:
150 entry->d_time = 0;
151 entry->d_op = &coda_dentry_operations;
152 d_add(entry, res_inode);
153 if ( dropme ) {
154 d_drop(entry);
155 coda_flag_inode(res_inode, C_VATTR);
156 }
157 EXIT;
158 return NULL;
159 }
160
161
162 int coda_permission(struct inode *inode, int mask)
163 {
164 int error;
165
166 ENTRY;
167 coda_vfs_stat.permission++;
168
169 if ( mask == 0 )
170 return 0;
171
172 if ( coda_access_cache ) {
173 coda_permission_stat.count++;
174
175 if ( coda_cache_check(inode, mask) ) {
176 coda_permission_stat.hit_count++;
177 return 0;
178 }
179 }
180
181 CDEBUG(D_INODE, "mask is %o\n", mask);
182 error = venus_access(inode->i_sb, coda_i2f(inode), mask);
183
184 CDEBUG(D_INODE, "fid: %s, ino: %ld (mask: %o) error: %d\n",
185 coda_i2s(inode), inode->i_ino, mask, error);
186
187 if (!error)
188 coda_cache_enter(inode, mask);
189
190 return error;
191 }
192
193
194 static inline void coda_dir_changed(struct inode *dir, int link)
195 {
196 #ifdef REQUERY_VENUS_FOR_MTIME
197 /* invalidate the directory cnode's attributes so we refetch the
198 * attributes from venus next time the inode is referenced */
199 coda_flag_inode(dir, C_VATTR);
200 #else
201 /* optimistically we can also act as if our nose bleeds. The
202 * granularity of the mtime is coarse anyways so we might actually be
203 * right most of the time. Note: we only do this for directories. */
204 dir->i_mtime = CURRENT_TIME;
205 #endif
206 if (link)
207 dir->i_nlink += link;
208 }
209
210 /* creation routines: create, mknod, mkdir, link, symlink */
211 static int coda_create(struct inode *dir, struct dentry *de, int mode)
212 {
213 int error=0;
214 const char *name=de->d_name.name;
215 int length=de->d_name.len;
216 struct inode *result = NULL;
217 struct ViceFid newfid;
218 struct coda_vattr attrs;
219
220 ENTRY;
221 coda_vfs_stat.create++;
222
223 CDEBUG(D_INODE, "name: %s, length %d, mode %o\n", name, length, mode);
224
225 if (coda_isroot(dir) && coda_iscontrol(name, length))
226 return -EPERM;
227
228 error = venus_create(dir->i_sb, coda_i2f(dir), name, length,
229 0, mode, 0, &newfid, &attrs);
230
231 if ( error ) {
232 CDEBUG(D_INODE, "create: %s, result %d\n",
233 coda_f2s(&newfid), error);
234 d_drop(de);
235 return error;
236 }
237
238 error = coda_cnode_make(&result, &newfid, dir->i_sb);
239 if ( error ) {
240 d_drop(de);
241 result = NULL;
242 return error;
243 }
244
245 /* invalidate the directory cnode's attributes */
246 coda_dir_changed(dir, 0);
247 d_instantiate(de, result);
248 return 0;
249 }
250
251 static int coda_mknod(struct inode *dir, struct dentry *de, int mode, int rdev)
252 {
253 int error=0;
254 const char *name=de->d_name.name;
255 int length=de->d_name.len;
256 struct inode *result = NULL;
257 struct ViceFid newfid;
258 struct coda_vattr attrs;
259
260 if ( coda_hasmknod == 0 )
261 return -EIO;
262
263 coda_vfs_stat.create++;
264
265 CDEBUG(D_INODE, "name: %s, length %d, mode %o, rdev %x\n",
266 name, length, mode, rdev);
267
268 if (coda_isroot(dir) && coda_iscontrol(name, length))
269 return -EPERM;
270
271 error = venus_create(dir->i_sb, coda_i2f(dir), name, length,
272 0, mode, rdev, &newfid, &attrs);
273
274 if ( error ) {
275 CDEBUG(D_INODE, "mknod: %s, result %d\n",
276 coda_f2s(&newfid), error);
277 d_drop(de);
278 return error;
279 }
280
281 error = coda_cnode_make(&result, &newfid, dir->i_sb);
282 if ( error ) {
283 d_drop(de);
284 result = NULL;
285 return error;
286 }
287
288 /* invalidate the directory cnode's attributes */
289 coda_dir_changed(dir, 0);
290 d_instantiate(de, result);
291 return 0;
292 }
293
294 static int coda_mkdir(struct inode *dir, struct dentry *de, int mode)
295 {
296 struct inode *inode;
297 struct coda_vattr attr;
298 const char *name = de->d_name.name;
299 int len = de->d_name.len;
300 int error;
301 struct ViceFid newfid;
302
303 ENTRY;
304 coda_vfs_stat.mkdir++;
305
306 if (coda_isroot(dir) && coda_iscontrol(name, len))
307 return -EPERM;
308
309 CDEBUG(D_INODE, "mkdir %s (len %d) in %s, mode %o.\n",
310 name, len, coda_i2s(dir), mode);
311
312 attr.va_mode = mode;
313 error = venus_mkdir(dir->i_sb, coda_i2f(dir),
314 name, len, &newfid, &attr);
315
316 if ( error ) {
317 CDEBUG(D_INODE, "mkdir error: %s result %d\n",
318 coda_f2s(&newfid), error);
319 d_drop(de);
320 return error;
321 }
322
323 CDEBUG(D_INODE, "mkdir: new dir has fid %s.\n",
324 coda_f2s(&newfid));
325
326 error = coda_cnode_make(&inode, &newfid, dir->i_sb);
327 if ( error ) {
328 d_drop(de);
329 return error;
330 }
331
332 /* invalidate the directory cnode's attributes */
333 coda_dir_changed(dir, 1);
334 d_instantiate(de, inode);
335 return 0;
336 }
337
338 /* try to make de an entry in dir_inodde linked to source_de */
339 static int coda_link(struct dentry *source_de, struct inode *dir_inode,
340 struct dentry *de)
341 {
342 struct inode *inode = source_de->d_inode;
343 const char * name = de->d_name.name;
344 int len = de->d_name.len;
345 int error;
346
347 ENTRY;
348 coda_vfs_stat.link++;
349
350 if (coda_isroot(dir_inode) && coda_iscontrol(name, len))
351 return -EPERM;
352
353 CDEBUG(D_INODE, "old: fid: %s\n", coda_i2s(inode));
354 CDEBUG(D_INODE, "directory: %s\n", coda_i2s(dir_inode));
355
356 error = venus_link(dir_inode->i_sb, coda_i2f(inode),
357 coda_i2f(dir_inode), (const char *)name, len);
358
359 if (error) {
360 d_drop(de);
361 goto out;
362 }
363
364 coda_dir_changed(dir_inode, 0);
365 atomic_inc(&inode->i_count);
366 d_instantiate(de, inode);
367 inode->i_nlink++;
368
369 out:
370 CDEBUG(D_INODE, "link result %d\n",error);
371 EXIT;
372 return(error);
373 }
374
375
376 static int coda_symlink(struct inode *dir_inode, struct dentry *de,
377 const char *symname)
378 {
379 const char *name = de->d_name.name;
380 int len = de->d_name.len;
381 int symlen;
382 int error=0;
383
384 ENTRY;
385 coda_vfs_stat.symlink++;
386
387 if (coda_isroot(dir_inode) && coda_iscontrol(name, len))
388 return -EPERM;
389
390 symlen = strlen(symname);
391 if ( symlen > CODA_MAXPATHLEN )
392 return -ENAMETOOLONG;
393
394 CDEBUG(D_INODE, "symname: %s, length: %d\n", symname, symlen);
395
396 /*
397 * This entry is now negative. Since we do not create
398 * an inode for the entry we have to drop it.
399 */
400 d_drop(de);
401 error = venus_symlink(dir_inode->i_sb, coda_i2f(dir_inode), name, len,
402 symname, symlen);
403
404 /* mtime is no good anymore */
405 if ( !error )
406 coda_dir_changed(dir_inode, 0);
407
408 CDEBUG(D_INODE, "in symlink result %d\n",error);
409 EXIT;
410 return error;
411 }
412
413 /* destruction routines: unlink, rmdir */
414 int coda_unlink(struct inode *dir, struct dentry *de)
415 {
416 int error;
417 const char *name = de->d_name.name;
418 int len = de->d_name.len;
419
420 ENTRY;
421 coda_vfs_stat.unlink++;
422
423 CDEBUG(D_INODE, " %s in %s, dirino %ld\n", name ,
424 coda_i2s(dir), dir->i_ino);
425
426 error = venus_remove(dir->i_sb, coda_i2f(dir), name, len);
427 if ( error ) {
428 CDEBUG(D_INODE, "upc returned error %d\n", error);
429 return error;
430 }
431
432 coda_dir_changed(dir, 0);
433 de->d_inode->i_nlink--;
434
435 return 0;
436 }
437
438 int coda_rmdir(struct inode *dir, struct dentry *de)
439 {
440 const char *name = de->d_name.name;
441 int len = de->d_name.len;
442 int error;
443
444 ENTRY;
445 coda_vfs_stat.rmdir++;
446
447 if (!d_unhashed(de))
448 return -EBUSY;
449 error = venus_rmdir(dir->i_sb, coda_i2f(dir), name, len);
450
451 if ( error ) {
452 CDEBUG(D_INODE, "upc returned error %d\n", error);
453 return error;
454 }
455
456 coda_dir_changed(dir, -1);
457 de->d_inode->i_nlink--;
458 d_delete(de);
459
460 return 0;
461 }
462
463 /* rename */
464 static int coda_rename(struct inode *old_dir, struct dentry *old_dentry,
465 struct inode *new_dir, struct dentry *new_dentry)
466 {
467 const char *old_name = old_dentry->d_name.name;
468 const char *new_name = new_dentry->d_name.name;
469 int old_length = old_dentry->d_name.len;
470 int new_length = new_dentry->d_name.len;
471 int link_adjust = 0;
472 int error;
473
474 ENTRY;
475 coda_vfs_stat.rename++;
476
477 CDEBUG(D_INODE, "old: %s, (%d length), new: %s"
478 "(%d length). old:d_count: %d, new:d_count: %d\n",
479 old_name, old_length, new_name, new_length,
480 atomic_read(&old_dentry->d_count), atomic_read(&new_dentry->d_count));
481
482 error = venus_rename(old_dir->i_sb, coda_i2f(old_dir),
483 coda_i2f(new_dir), old_length, new_length,
484 (const char *) old_name, (const char *)new_name);
485
486 if ( !error ) {
487 if ( new_dentry->d_inode ) {
488 if ( S_ISDIR(new_dentry->d_inode->i_mode) )
489 link_adjust = 1;
490
491 coda_dir_changed(old_dir, -link_adjust);
492 coda_dir_changed(new_dir, link_adjust);
493 coda_flag_inode(new_dentry->d_inode, C_VATTR);
494 } else {
495 coda_flag_inode(old_dir, C_VATTR);
496 coda_flag_inode(new_dir, C_VATTR);
497 }
498 }
499
500 CDEBUG(D_INODE, "result %d\n", error);
501
502 EXIT;
503 return error;
504 }
505
506
507 /* file operations for directories */
508 int coda_readdir(struct file *file, void *dirent, filldir_t filldir)
509 {
510 int result = 0;
511 struct dentry *cdentry;
512 struct inode *cinode, *inode = file->f_dentry->d_inode;
513 struct file *cfile, fakefile;
514 struct coda_inode_info *cii = ITOC(inode);
515
516 ENTRY;
517 coda_vfs_stat.readdir++;
518
519 cfile = cii->c_container;
520 if (!cfile) BUG();
521
522 cinode = cii->c_container->f_dentry->d_inode;
523 if ( S_ISREG(cinode->i_mode) ) {
524 /* Venus: we must read Venus dirents from the file */
525 cdentry = cii->c_container->f_dentry;
526 coda_prepare_fakefile(file, cdentry, &fakefile);
527
528 result = coda_venus_readdir(&fakefile, dirent, filldir);
529
530 file->f_pos = fakefile.f_pos;
531 file->f_version = fakefile.f_version;
532 } else {
533 /* potemkin case: we are handed a directory inode */
534 result = vfs_readdir(file, filldir, dirent);
535 }
536
537 EXIT;
538 return result;
539 }
540
541 /* support routines */
542
543 /* instantiate a fake file to pass to coda_venus_readdir */
544 static void coda_prepare_fakefile(struct file *coda_file,
545 struct dentry *cont_dentry,
546 struct file *fake_file)
547 {
548 fake_file->f_dentry = cont_dentry;
549 fake_file->f_pos = coda_file->f_pos;
550 fake_file->f_version = coda_file->f_version;
551 fake_file->f_op = cont_dentry->d_inode->i_fop;
552 return ;
553 }
554
555 /*
556 * this structure is manipulated by filldir in vfs layer.
557 * the count holds the remaining amount of space in the getdents buffer,
558 * beyond the current_dir pointer.
559 *
560 * What structure is this comment referring to?? -JH
561 */
562
563 /* should be big enough to hold any single directory entry */
564 #define DIR_BUFSIZE 2048
565
566 static int coda_venus_readdir(struct file *filp, void *getdent,
567 filldir_t filldir)
568 {
569 int bufsize;
570 int offset = filp->f_pos; /* offset in the directory file */
571 int count = 0;
572 int pos = 0; /* offset in the block we read */
573 int result = 0; /* either an error or # of entries returned */
574 int errfill;
575 char *buff = NULL;
576 struct venus_dirent *vdirent;
577 int string_offset = (int) (&((struct venus_dirent *)(0))->d_name);
578 int i;
579
580 ENTRY;
581
582 CODA_ALLOC(buff, char *, DIR_BUFSIZE);
583 if ( !buff ) {
584 printk("coda_venus_readdir: out of memory.\n");
585 return -ENOMEM;
586 }
587
588 /* we use this routine to read the file into our buffer */
589 bufsize = kernel_read(filp, filp->f_pos, buff, DIR_BUFSIZE);
590 if ( bufsize < 0) {
591 printk("coda_venus_readdir: cannot read directory %d.\n",
592 bufsize);
593 result = bufsize;
594 goto exit;
595 }
596 if ( bufsize == 0) {
597 result = 0;
598 goto exit;
599 }
600
601 /* Parse and write into user space. Filldir tells us when done! */
602 CDEBUG(D_FILE, "buffsize: %d offset %d, count %d.\n",
603 bufsize, offset, count);
604
605 i = 0;
606 result = 0;
607 while ( pos + string_offset < bufsize && i < 1024) {
608 vdirent = (struct venus_dirent *) (buff + pos);
609
610 /* test if the name is fully in the buffer */
611 if ( pos + string_offset + (int) vdirent->d_namlen >= bufsize ){
612 if ( result == 0 )
613 printk("CODA: Invalid directory cfino: %ld\n",
614 filp->f_dentry->d_inode->i_ino);
615 break;
616 }
617 /* now we are certain that we can read the entry from buff */
618
619 /* if we don't have a null entry, copy it */
620 if ( vdirent->d_fileno && vdirent->d_reclen ) {
621 int namlen = vdirent->d_namlen;
622 off_t offs = filp->f_pos;
623 ino_t ino = vdirent->d_fileno;
624 char *name = vdirent->d_name;
625
626 errfill = filldir(getdent, name, namlen,
627 offs, ino, DT_UNKNOWN);
628 CDEBUG(D_FILE, "entry %d: ino %ld, namlen %d, reclen %d, type %d, pos %d, string_offs %d, name %*s, offset %d, result: %d, errfill: %d.\n", i,vdirent->d_fileno, vdirent->d_namlen, vdirent->d_reclen, vdirent->d_type, pos, string_offset, vdirent->d_namlen, vdirent->d_name, (u_int) offs, result, errfill);
629 /* errfill means no space for filling in this round */
630 if ( errfill < 0 ) {
631 result = 0;
632 break;
633 }
634 /* adjust count */
635 result++;
636 }
637 /* next one */
638 filp->f_pos += vdirent->d_reclen;
639 if ( filp->f_pos > filp->f_dentry->d_inode->i_size )
640 break;
641 if ( !vdirent->d_reclen ) {
642 printk("CODA: Invalid directory, cfino: %ld\n",
643 filp->f_dentry->d_inode->i_ino);
644 result = -EINVAL;
645 break;
646 }
647 pos += (unsigned int) vdirent->d_reclen;
648 i++;
649 }
650
651 if ( i >= 1024 ) {
652 printk("Repeating too much in readdir %ld\n",
653 filp->f_dentry->d_inode->i_ino);
654 result = -EINVAL;
655 }
656
657 exit:
658 CODA_FREE(buff, DIR_BUFSIZE);
659 return result;
660 }
661
662 /* called when a cache lookup succeeds */
663 static int coda_dentry_revalidate(struct dentry *de, int flags)
664 {
665 struct inode *inode = de->d_inode;
666 struct coda_inode_info *cii;
667 ENTRY;
668
669 if (!inode)
670 return 1;
671 lock_kernel();
672 if (coda_isroot(inode))
673 goto out;
674 if (is_bad_inode(inode))
675 goto bad;
676
677 cii = ITOC(de->d_inode);
678 if (cii->c_flags & (C_PURGE | C_FLUSH))
679 goto out;
680
681 shrink_dcache_parent(de);
682
683 /* propagate for a flush */
684 if (cii->c_flags & C_FLUSH)
685 coda_flag_inode_children(inode, C_FLUSH);
686
687 if (atomic_read(&de->d_count) > 1) {
688 /* pretend it's valid, but don't change the flags */
689 CDEBUG(D_DOWNCALL, "BOOM for: ino %ld, %s\n",
690 de->d_inode->i_ino, coda_f2s(&cii->c_fid));
691 goto out;
692 }
693
694 /* clear the flags. */
695 cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH);
696
697 bad:
698 unlock_kernel();
699 return 0;
700 out:
701 unlock_kernel();
702 return 1;
703 }
704
705 /*
706 * This is the callback from dput() when d_count is going to 0.
707 * We use this to unhash dentries with bad inodes.
708 */
709 static int coda_dentry_delete(struct dentry * dentry)
710 {
711 int flags;
712
713 if (!dentry->d_inode)
714 return 0;
715
716 flags = (ITOC(dentry->d_inode)->c_flags) & C_PURGE;
717 if (is_bad_inode(dentry->d_inode) || flags) {
718 CDEBUG(D_DOWNCALL, "bad inode, unhashing %s/%s, %ld\n",
719 dentry->d_parent->d_name.name, dentry->d_name.name,
720 dentry->d_inode->i_ino);
721 return 1;
722 }
723 return 0;
724 }
725
726
727
728 /*
729 * This is called when we want to check if the inode has
730 * changed on the server. Coda makes this easy since the
731 * cache manager Venus issues a downcall to the kernel when this
732 * happens
733 */
734 int coda_revalidate_inode(struct dentry *dentry)
735 {
736 struct coda_vattr attr;
737 int error = 0;
738 int old_mode;
739 ino_t old_ino;
740 struct inode *inode = dentry->d_inode;
741 struct coda_inode_info *cii = ITOC(inode);
742
743 ENTRY;
744 CDEBUG(D_INODE, "revalidating: %*s/%*s\n",
745 dentry->d_name.len, dentry->d_name.name,
746 dentry->d_parent->d_name.len, dentry->d_parent->d_name.name);
747
748 lock_kernel();
749 if ( !cii->c_flags )
750 goto ok;
751
752 if (cii->c_flags & (C_VATTR | C_PURGE | C_FLUSH)) {
753 error = venus_getattr(inode->i_sb, &(cii->c_fid), &attr);
754 if ( error )
755 goto return_bad_inode;
756
757 /* this inode may be lost if:
758 - it's ino changed
759 - type changes must be permitted for repair and
760 missing mount points.
761 */
762 old_mode = inode->i_mode;
763 old_ino = inode->i_ino;
764 coda_vattr_to_iattr(inode, &attr);
765
766 if ((old_mode & S_IFMT) != (inode->i_mode & S_IFMT)) {
767 printk("Coda: inode %ld, fid %s changed type!\n",
768 inode->i_ino, coda_f2s(&(cii->c_fid)));
769 }
770
771 /* the following can happen when a local fid is replaced
772 with a global one, here we lose and declare the inode bad */
773 if (inode->i_ino != old_ino)
774 goto return_bad_inode;
775
776 if ( cii->c_flags )
777 coda_flag_inode_children(inode, C_FLUSH);
778
779 cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH);
780 }
781
782 ok:
783 unlock_kernel();
784 return 0;
785
786 return_bad_inode:
787 inode->i_mapping = &inode->i_data;
788 if (cii->c_container) {
789 fput(cii->c_container);
790 cii->c_container = NULL;
791 }
792 make_bad_inode(inode);
793 unlock_kernel();
794 return -EIO;
795 }
796
797