clean
[linux-2.4.21-pre4.git] / 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 int coda_venus_readdir(struct file *filp, filldir_t filldir,
54                               void *dirent, struct dentry *dir);
55 int coda_fsync(struct file *, struct dentry *dentry, int datasync);
56
57 int coda_hasmknod;
58
59 struct dentry_operations coda_dentry_operations =
60 {
61         d_revalidate:   coda_dentry_revalidate,
62         d_delete:       coda_dentry_delete,
63 };
64
65 struct inode_operations coda_dir_inode_operations =
66 {
67         create:         coda_create,
68         lookup:         coda_lookup,
69         link:           coda_link,
70         unlink:         coda_unlink,
71         symlink:        coda_symlink,
72         mkdir:          coda_mkdir,
73         rmdir:          coda_rmdir,
74         mknod:          coda_mknod,
75         rename:         coda_rename,
76         permission:     coda_permission,
77         revalidate:     coda_revalidate_inode,
78         setattr:        coda_notify_change,
79 };
80
81 struct file_operations coda_dir_operations = {
82         read:           generic_read_dir,
83         readdir:        coda_readdir,
84         open:           coda_open,
85         flush:          coda_flush,
86         release:        coda_release,
87         fsync:          coda_fsync,
88 };
89
90
91 /* inode operations for directories */
92 /* access routines: lookup, readlink, permission */
93 static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry)
94 {
95         struct inode *res_inode = NULL;
96         struct ViceFid resfid = {0,0,0};
97         int dropme = 0; /* to indicate entry should not be cached */
98         int type = 0;
99         int error = 0;
100         const char *name = entry->d_name.name;
101         size_t length = entry->d_name.len;
102         
103         if ( length > CODA_MAXNAMLEN ) {
104                 printk("name too long: lookup, %s (%*s)\n", 
105                        coda_i2s(dir), (int)length, name);
106                 return ERR_PTR(-ENAMETOOLONG);
107         }
108
109         CDEBUG(D_INODE, "name %s, len %ld in ino %ld, fid %s\n", 
110                name, (long)length, dir->i_ino, coda_i2s(dir));
111
112         /* control object, create inode on the fly */
113         if (coda_isroot(dir) && coda_iscontrol(name, length)) {
114                 error = coda_cnode_makectl(&res_inode, dir->i_sb);
115                 CDEBUG(D_SPECIAL, 
116                        "Lookup on CTL object; dir ino %ld, count %d\n", 
117                        dir->i_ino, atomic_read(&dir->i_count));
118                 dropme = 1;
119                 goto exit;
120         }
121
122         error = venus_lookup(dir->i_sb, coda_i2f(dir), 
123                              (const char *)name, length, &type, &resfid);
124
125         res_inode = NULL;
126         if (!error) {
127                 if (type & CODA_NOCACHE) {
128                         type &= (~CODA_NOCACHE);
129                         CDEBUG(D_INODE, "dropme set for %s\n", 
130                                coda_f2s(&resfid));
131                         dropme = 1;
132                 }
133
134                 error = coda_cnode_make(&res_inode, &resfid, dir->i_sb);
135                 if (error) return ERR_PTR(error);
136         } else if (error != -ENOENT) {
137                 CDEBUG(D_INODE, "error for %s(%*s)%d\n",
138                        coda_i2s(dir), (int)length, name, error);
139                 return ERR_PTR(error);
140         }
141         CDEBUG(D_INODE, "lookup: %s is (%s), type %d result %d, dropme %d\n",
142                name, coda_f2s(&resfid), type, error, dropme);
143
144 exit:
145         entry->d_time = 0;
146         entry->d_op = &coda_dentry_operations;
147         d_add(entry, res_inode);
148         if ( dropme ) {
149                 d_drop(entry);
150                 coda_flag_inode(res_inode, C_VATTR);
151         }
152         return NULL;
153 }
154
155
156 int coda_permission(struct inode *inode, int mask)
157 {
158         int error;
159  
160         coda_vfs_stat.permission++;
161
162         if ( mask == 0 )
163                 return 0;
164
165         if ( coda_access_cache ) {
166                 coda_permission_stat.count++;
167
168                 if ( coda_cache_check(inode, mask) ) {
169                         coda_permission_stat.hit_count++;
170                         return 0; 
171                 }
172         }
173
174         CDEBUG(D_INODE, "mask is %o\n", mask);
175         error = venus_access(inode->i_sb, coda_i2f(inode), mask);
176     
177         CDEBUG(D_INODE, "fid: %s, ino: %ld (mask: %o) error: %d\n", 
178                coda_i2s(inode), inode->i_ino, mask, error);
179
180         if (!error)
181                 coda_cache_enter(inode, mask);
182
183         return error; 
184 }
185
186
187 static inline void coda_dir_changed(struct inode *dir, int link)
188 {
189 #ifdef REQUERY_VENUS_FOR_MTIME
190         /* invalidate the directory cnode's attributes so we refetch the
191          * attributes from venus next time the inode is referenced */
192         coda_flag_inode(dir, C_VATTR);
193 #else
194         /* optimistically we can also act as if our nose bleeds. The
195          * granularity of the mtime is coarse anyways so we might actually be
196          * right most of the time. Note: we only do this for directories. */
197         dir->i_mtime = dir->i_ctime = CURRENT_TIME;
198 #endif
199         if (link)
200                 dir->i_nlink += link;
201 }
202
203 /* creation routines: create, mknod, mkdir, link, symlink */
204 static int coda_create(struct inode *dir, struct dentry *de, int mode)
205 {
206         int error=0;
207         const char *name=de->d_name.name;
208         int length=de->d_name.len;
209         struct inode *inode;
210         struct ViceFid newfid;
211         struct coda_vattr attrs;
212
213         coda_vfs_stat.create++;
214
215         CDEBUG(D_INODE, "name: %s, length %d, mode %o\n", name, length, mode);
216
217         if (coda_isroot(dir) && coda_iscontrol(name, length))
218                 return -EPERM;
219
220         error = venus_create(dir->i_sb, coda_i2f(dir), name, length, 
221                                 0, mode, 0, &newfid, &attrs);
222
223         if ( error ) {
224                 CDEBUG(D_INODE, "create: %s, result %d\n",
225                        coda_f2s(&newfid), error); 
226                 d_drop(de);
227                 return error;
228         }
229
230         inode = coda_iget(dir->i_sb, &newfid, &attrs);
231         if ( IS_ERR(inode) ) {
232                 d_drop(de);
233                 return PTR_ERR(inode);
234         }
235
236         /* invalidate the directory cnode's attributes */
237         coda_dir_changed(dir, 0);
238         d_instantiate(de, inode);
239         return 0;
240 }
241
242 static int coda_mknod(struct inode *dir, struct dentry *de, int mode, int rdev)
243 {
244         int error=0;
245         const char *name=de->d_name.name;
246         int length=de->d_name.len;
247         struct inode *inode;
248         struct ViceFid newfid;
249         struct coda_vattr attrs;
250
251         if ( coda_hasmknod == 0 )
252                 return -EIO;
253
254         coda_vfs_stat.create++;
255
256         CDEBUG(D_INODE, "name: %s, length %d, mode %o, rdev %x\n",
257                name, length, mode, rdev);
258
259         if (coda_isroot(dir) && coda_iscontrol(name, length))
260                 return -EPERM;
261
262         error = venus_create(dir->i_sb, coda_i2f(dir), name, length, 
263                                 0, mode, rdev, &newfid, &attrs);
264
265         if ( error ) {
266                 CDEBUG(D_INODE, "mknod: %s, result %d\n",
267                        coda_f2s(&newfid), error); 
268                 d_drop(de);
269                 return error;
270         }
271
272         inode = coda_iget(dir->i_sb, &newfid, &attrs);
273         if ( IS_ERR(inode) ) {
274                 d_drop(de);
275                 return PTR_ERR(inode);
276         }
277
278         /* invalidate the directory cnode's attributes */
279         coda_dir_changed(dir, 0);
280         d_instantiate(de, inode);
281         return 0;
282 }                            
283
284 static int coda_mkdir(struct inode *dir, struct dentry *de, int mode)
285 {
286         struct inode *inode;
287         struct coda_vattr attrs;
288         const char *name = de->d_name.name;
289         int len = de->d_name.len;
290         int error;
291         struct ViceFid newfid;
292
293         coda_vfs_stat.mkdir++;
294
295         if (coda_isroot(dir) && coda_iscontrol(name, len))
296                 return -EPERM;
297
298         CDEBUG(D_INODE, "mkdir %s (len %d) in %s, mode %o.\n", 
299                name, len, coda_i2s(dir), mode);
300
301         attrs.va_mode = mode;
302         error = venus_mkdir(dir->i_sb, coda_i2f(dir), 
303                                name, len, &newfid, &attrs);
304         
305         if ( error ) {
306                 CDEBUG(D_INODE, "mkdir error: %s result %d\n", 
307                        coda_f2s(&newfid), error); 
308                 d_drop(de);
309                 return error;
310         }
311          
312         CDEBUG(D_INODE, "mkdir: new dir has fid %s.\n", 
313                coda_f2s(&newfid)); 
314
315         inode = coda_iget(dir->i_sb, &newfid, &attrs);
316         if ( IS_ERR(inode) ) {
317                 d_drop(de);
318                 return PTR_ERR(inode);
319         }
320         
321         /* invalidate the directory cnode's attributes */
322         coda_dir_changed(dir, 1);
323         d_instantiate(de, inode);
324         return 0;
325 }
326
327 /* try to make de an entry in dir_inodde linked to source_de */ 
328 static int coda_link(struct dentry *source_de, struct inode *dir_inode, 
329           struct dentry *de)
330 {
331         struct inode *inode = source_de->d_inode;
332         const char * name = de->d_name.name;
333         int len = de->d_name.len;
334         int error;
335
336         coda_vfs_stat.link++;
337
338         if (coda_isroot(dir_inode) && coda_iscontrol(name, len))
339                 return -EPERM;
340
341         CDEBUG(D_INODE, "old: fid: %s\n", coda_i2s(inode));
342         CDEBUG(D_INODE, "directory: %s\n", coda_i2s(dir_inode));
343
344         error = venus_link(dir_inode->i_sb, coda_i2f(inode),
345                            coda_i2f(dir_inode), (const char *)name, len);
346
347         if (error) { 
348                 d_drop(de);
349                 goto out;
350         }
351
352         coda_dir_changed(dir_inode, 0);
353         atomic_inc(&inode->i_count);
354         d_instantiate(de, inode);
355         inode->i_nlink++;
356         
357 out:
358         CDEBUG(D_INODE, "link result %d\n",error);
359         return(error);
360 }
361
362
363 static int coda_symlink(struct inode *dir_inode, struct dentry *de,
364                         const char *symname)
365 {
366         const char *name = de->d_name.name;
367         int len = de->d_name.len;
368         int symlen;
369         int error=0;
370         
371         coda_vfs_stat.symlink++;
372
373         if (coda_isroot(dir_inode) && coda_iscontrol(name, len))
374                 return -EPERM;
375
376         symlen = strlen(symname);
377         if ( symlen > CODA_MAXPATHLEN )
378                 return -ENAMETOOLONG;
379
380         CDEBUG(D_INODE, "symname: %s, length: %d\n", symname, symlen);
381
382         /*
383          * This entry is now negative. Since we do not create
384          * an inode for the entry we have to drop it. 
385          */
386         d_drop(de);
387         error = venus_symlink(dir_inode->i_sb, coda_i2f(dir_inode), name, len, 
388                               symname, symlen);
389
390         /* mtime is no good anymore */
391         if ( !error )
392                 coda_dir_changed(dir_inode, 0);
393
394         CDEBUG(D_INODE, "in symlink result %d\n",error);
395         return error;
396 }
397
398 /* destruction routines: unlink, rmdir */
399 int coda_unlink(struct inode *dir, struct dentry *de)
400 {
401         int error;
402         const char *name = de->d_name.name;
403         int len = de->d_name.len;
404
405         coda_vfs_stat.unlink++;
406
407         CDEBUG(D_INODE, " %s in %s, dirino %ld\n", name , 
408                coda_i2s(dir), dir->i_ino);
409
410         error = venus_remove(dir->i_sb, coda_i2f(dir), name, len);
411         if ( error ) {
412                 CDEBUG(D_INODE, "upc returned error %d\n", error);
413                 return error;
414         }
415
416         coda_dir_changed(dir, 0);
417         de->d_inode->i_nlink--;
418
419         return 0;
420 }
421
422 int coda_rmdir(struct inode *dir, struct dentry *de)
423 {
424         const char *name = de->d_name.name;
425         int len = de->d_name.len;
426         int error;
427
428         coda_vfs_stat.rmdir++;
429
430         if (!d_unhashed(de))
431                 return -EBUSY;
432         error = venus_rmdir(dir->i_sb, coda_i2f(dir), name, len);
433
434         if ( error ) {
435                 CDEBUG(D_INODE, "upc returned error %d\n", error);
436                 return error;
437         }
438
439         coda_dir_changed(dir, -1);
440         de->d_inode->i_nlink--;
441         d_delete(de);
442
443         return 0;
444 }
445
446 /* rename */
447 static int coda_rename(struct inode *old_dir, struct dentry *old_dentry, 
448                        struct inode *new_dir, struct dentry *new_dentry)
449 {
450         const char *old_name = old_dentry->d_name.name;
451         const char *new_name = new_dentry->d_name.name;
452         int old_length = old_dentry->d_name.len;
453         int new_length = new_dentry->d_name.len;
454         int link_adjust = 0;
455         int error;
456
457         coda_vfs_stat.rename++;
458
459         CDEBUG(D_INODE, "old: %s, (%d length), new: %s"
460                "(%d length). old:d_count: %d, new:d_count: %d\n", 
461                old_name, old_length, new_name, new_length,
462                atomic_read(&old_dentry->d_count), atomic_read(&new_dentry->d_count));
463
464         error = venus_rename(old_dir->i_sb, coda_i2f(old_dir), 
465                              coda_i2f(new_dir), old_length, new_length, 
466                              (const char *) old_name, (const char *)new_name);
467
468         if ( !error ) {
469                 if ( new_dentry->d_inode ) {
470                         if ( S_ISDIR(new_dentry->d_inode->i_mode) )
471                                 link_adjust = 1;
472
473                         coda_dir_changed(old_dir, -link_adjust);
474                         coda_dir_changed(new_dir,  link_adjust);
475                         coda_flag_inode(new_dentry->d_inode, C_VATTR);
476                 } else {
477                         coda_flag_inode(old_dir, C_VATTR);
478                         coda_flag_inode(new_dir, C_VATTR);
479                 }
480         }
481
482         CDEBUG(D_INODE, "result %d\n", error); 
483
484         return error;
485 }
486
487
488 /* file operations for directories */
489 int coda_readdir(struct file *coda_file, void *dirent, filldir_t filldir)
490 {
491         struct dentry *coda_dentry = coda_file->f_dentry;
492         struct coda_file_info *cfi;
493         struct file *host_file;
494         int ret;
495
496         cfi = CODA_FTOC(coda_file);
497         if (!cfi || cfi->cfi_magic != CODA_MAGIC) BUG();
498         host_file = cfi->cfi_container;
499
500         coda_vfs_stat.readdir++;
501
502         down(&host_file->f_dentry->d_inode->i_sem);
503         host_file->f_pos = coda_file->f_pos;
504
505         if ( !host_file->f_op->readdir ) {
506                 /* Venus: we must read Venus dirents from the file */
507                 ret = coda_venus_readdir(host_file, filldir, dirent, coda_dentry);
508         } else {
509                 /* potemkin case: we were handed a directory inode */
510                 ret = vfs_readdir(host_file, filldir, dirent);
511         }
512
513         coda_file->f_pos = host_file->f_pos;
514         up(&host_file->f_dentry->d_inode->i_sem);
515
516         return ret;
517 }
518
519 static inline unsigned int CDT2DT(unsigned char cdt)
520 {
521         unsigned int dt;
522
523         switch(cdt) {
524         case CDT_UNKNOWN: dt = DT_UNKNOWN; break;
525         case CDT_FIFO:    dt = DT_FIFO;    break;
526         case CDT_CHR:     dt = DT_CHR;     break;
527         case CDT_DIR:     dt = DT_DIR;     break;
528         case CDT_BLK:     dt = DT_BLK;     break;
529         case CDT_REG:     dt = DT_REG;     break;
530         case CDT_LNK:     dt = DT_LNK;     break;
531         case CDT_SOCK:    dt = DT_SOCK;    break;
532         case CDT_WHT:     dt = DT_WHT;     break;
533         default:          dt = DT_UNKNOWN; break;
534         }
535         return dt;
536 }
537
538 /* support routines */
539 static int coda_venus_readdir(struct file *filp, filldir_t filldir,
540                               void *dirent, struct dentry *dir)
541 {
542         int result = 0; /* # of entries returned */
543         struct venus_dirent *vdir;
544         unsigned long vdir_size =
545             (unsigned long)(&((struct venus_dirent *)0)->d_name);
546         unsigned int type;
547         struct qstr name;
548         ino_t ino;
549         int ret, i;
550
551         vdir = (struct venus_dirent *)kmalloc(sizeof(*vdir), GFP_KERNEL);
552         if (!vdir) return -ENOMEM;
553
554         i = filp->f_pos;
555         switch(i) {
556         case 0:
557                 ret = filldir(dirent, ".", 1, 0, dir->d_inode->i_ino, DT_DIR);
558                 if (ret < 0) break;
559                 result++;
560                 filp->f_pos++;
561                 /* fallthrough */
562         case 1:
563                 ret = filldir(dirent, "..", 2, 1, dir->d_parent->d_inode->i_ino, DT_DIR);
564                 if (ret < 0) break;
565                 result++;
566                 filp->f_pos++;
567                 /* fallthrough */
568         default:
569         while (1) {
570                 /* read entries from the directory file */
571                 ret = kernel_read(filp, filp->f_pos - 2, (char *)vdir,
572                                   sizeof(*vdir));
573                 if (ret < 0) {
574                         printk("coda_venus_readdir: read dir failed %d\n", ret);
575                         break;
576                 }
577                 if (ret == 0) break; /* end of directory file reached */
578
579                 /* catch truncated reads */
580                 if (ret < vdir_size || ret < vdir_size + vdir->d_namlen) {
581                         printk("coda_venus_readdir: short read: %ld\n",
582                                filp->f_dentry->d_inode->i_ino);
583                         ret = -EBADF;
584                         break;
585                 }
586                 /* validate whether the directory file actually makes sense */
587                 if (vdir->d_reclen < vdir_size + vdir->d_namlen ||
588                     vdir->d_namlen > CODA_MAXNAMLEN) {
589                         printk("coda_venus_readdir: Invalid dir: %ld\n",
590                                filp->f_dentry->d_inode->i_ino);
591                         ret = -EBADF;
592                         break;
593                 }
594
595                 name.len = vdir->d_namlen;
596                 name.name = vdir->d_name;
597
598                 /* Make sure we skip '.' and '..', we already got those */
599                 if (name.name[0] == '.' && (name.len == 1 ||
600                     (vdir->d_name[1] == '.' && name.len == 2)))
601                         vdir->d_fileno = name.len = 0;
602
603                 /* skip null entries */
604                 if (vdir->d_fileno && name.len) {
605                         /* try to look up this entry in the dcache, that way
606                          * userspace doesn't have to worry about breaking
607                          * getcwd by having mismatched inode numbers for
608                          * internal volume mountpoints. */
609                         ino = find_inode_number(dir, &name);
610                         if (!ino) ino = vdir->d_fileno;
611
612                         type = CDT2DT(vdir->d_type);
613                         ret = filldir(dirent, name.name, name.len, filp->f_pos,
614                                       ino, type); 
615                         /* failure means no space for filling in this round */
616                         if (ret < 0) break;
617                         result++;
618                 }
619                 /* we'll always have progress because d_reclen is unsigned and
620                  * we've already established it is non-zero. */
621                 filp->f_pos += vdir->d_reclen;
622         }
623         } 
624         kfree(vdir);
625         return result ? result : ret;
626 }
627
628 /* called when a cache lookup succeeds */
629 static int coda_dentry_revalidate(struct dentry *de, int flags)
630 {
631         struct inode *inode = de->d_inode;
632         struct coda_inode_info *cii;
633
634         if (!inode)
635                 return 1;
636         lock_kernel();
637         if (coda_isroot(inode))
638                 goto out;
639         if (is_bad_inode(inode))
640                 goto bad;
641
642         cii = ITOC(de->d_inode);
643         if (!(cii->c_flags & (C_PURGE | C_FLUSH)))
644                 goto out;
645
646         shrink_dcache_parent(de);
647
648         /* propagate for a flush */
649         if (cii->c_flags & C_FLUSH) 
650                 coda_flag_inode_children(inode, C_FLUSH);
651
652         if (atomic_read(&de->d_count) > 1) {
653                 /* pretend it's valid, but don't change the flags */
654                 CDEBUG(D_DOWNCALL, "BOOM for: ino %ld, %s\n",
655                        de->d_inode->i_ino, coda_f2s(&cii->c_fid));
656                 goto out;
657         }
658
659         /* clear the flags. */
660         cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH);
661
662 bad:
663         unlock_kernel();
664         return 0;
665 out:
666         unlock_kernel();
667         return 1;
668 }
669
670 /*
671  * This is the callback from dput() when d_count is going to 0.
672  * We use this to unhash dentries with bad inodes.
673  */
674 static int coda_dentry_delete(struct dentry * dentry)
675 {
676         int flags;
677
678         if (!dentry->d_inode) 
679                 return 0;
680
681         flags = (ITOC(dentry->d_inode)->c_flags) & C_PURGE;
682         if (is_bad_inode(dentry->d_inode) || flags) {
683                 CDEBUG(D_DOWNCALL, "bad inode, unhashing %s/%s, %ld\n", 
684                        dentry->d_parent->d_name.name, dentry->d_name.name,
685                        dentry->d_inode->i_ino);
686                 return 1;
687         }
688         return 0;
689 }
690
691
692
693 /*
694  * This is called when we want to check if the inode has
695  * changed on the server.  Coda makes this easy since the
696  * cache manager Venus issues a downcall to the kernel when this 
697  * happens 
698  */
699 int coda_revalidate_inode(struct dentry *dentry)
700 {
701         struct coda_vattr attr;
702         int error = 0;
703         int old_mode;
704         ino_t old_ino;
705         struct inode *inode = dentry->d_inode;
706         struct coda_inode_info *cii = ITOC(inode);
707
708         CDEBUG(D_INODE, "revalidating: %*s/%*s\n", 
709                dentry->d_name.len, dentry->d_name.name,
710                dentry->d_parent->d_name.len, dentry->d_parent->d_name.name);
711
712         lock_kernel();
713         if ( !cii->c_flags )
714                 goto ok;
715
716         if (cii->c_flags & (C_VATTR | C_PURGE | C_FLUSH)) {
717                 error = venus_getattr(inode->i_sb, &(cii->c_fid), &attr);
718                 if ( error )
719                         goto return_bad_inode;
720
721                 /* this inode may be lost if:
722                    - it's ino changed 
723                    - type changes must be permitted for repair and
724                    missing mount points.
725                 */
726                 old_mode = inode->i_mode;
727                 old_ino = inode->i_ino;
728                 coda_vattr_to_iattr(inode, &attr);
729
730                 if ((old_mode & S_IFMT) != (inode->i_mode & S_IFMT)) {
731                         printk("Coda: inode %ld, fid %s changed type!\n",
732                                inode->i_ino, coda_f2s(&(cii->c_fid)));
733                 }
734
735                 /* the following can happen when a local fid is replaced 
736                    with a global one, here we lose and declare the inode bad */
737                 if (inode->i_ino != old_ino)
738                         goto return_bad_inode;
739                 
740                 coda_flag_inode_children(inode, C_FLUSH);
741                 cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH);
742         }
743
744 ok:
745         unlock_kernel();
746         return 0;
747
748 return_bad_inode:
749         unlock_kernel();
750         return -EIO;
751 }
752