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