~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/fs/coda/dir.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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/stat.h>
 16 #include <linux/errno.h>
 17 #include <linux/locks.h>
 18 #include <linux/string.h>
 19 #include <linux/smp_lock.h>
 20 
 21 #include <asm/uaccess.h>
 22 
 23 #include <linux/coda.h>
 24 #include <linux/coda_linux.h>
 25 #include <linux/coda_psdev.h>
 26 #include <linux/coda_fs_i.h>
 27 #include <linux/coda_cache.h>
 28 #include <linux/coda_proc.h>
 29 
 30 /* dir inode-ops */
 31 static int coda_create(struct inode *dir, struct dentry *new, int mode);
 32 static int coda_mknod(struct inode *dir, struct dentry *new, int mode, int rdev);
 33 static struct dentry *coda_lookup(struct inode *dir, struct dentry *target);
 34 static int coda_link(struct dentry *old_dentry, struct inode *dir_inode, 
 35                      struct dentry *entry);
 36 static int coda_unlink(struct inode *dir_inode, struct dentry *entry);
 37 static int coda_symlink(struct inode *dir_inode, struct dentry *entry,
 38                         const char *symname);
 39 static int coda_mkdir(struct inode *dir_inode, struct dentry *entry, int mode);
 40 static int coda_rmdir(struct inode *dir_inode, struct dentry *entry);
 41 static int coda_rename(struct inode *old_inode, struct dentry *old_dentry, 
 42                        struct inode *new_inode, struct dentry *new_dentry);
 43 
 44 /* dir file-ops */
 45 static int coda_readdir(struct file *file, void *dirent, filldir_t filldir);
 46 
 47 /* dentry ops */
 48 static int coda_dentry_revalidate(struct dentry *de, int);
 49 static int coda_dentry_delete(struct dentry *);
 50 
 51 /* support routines */
 52 static void coda_prepare_fakefile(struct inode *coda_inode,
 53                                   struct file *coda_file, 
 54                                   struct inode *open_inode,
 55                                   struct file *open_file,
 56                                   struct dentry *open_dentry);
 57 static int coda_venus_readdir(struct file *filp, void *dirent, 
 58                               filldir_t filldir);
 59 int coda_fsync(struct file *, struct dentry *dentry, int datasync);
 60 
 61 int coda_hasmknod;
 62 
 63 struct dentry_operations coda_dentry_operations =
 64 {
 65         d_revalidate:   coda_dentry_revalidate,
 66         d_delete:       coda_dentry_delete,
 67 };
 68 
 69 struct inode_operations coda_dir_inode_operations =
 70 {
 71         create:         coda_create,
 72         lookup:         coda_lookup,
 73         link:           coda_link,
 74         unlink:         coda_unlink,
 75         symlink:        coda_symlink,
 76         mkdir:          coda_mkdir,
 77         rmdir:          coda_rmdir,
 78         mknod:          coda_mknod,
 79         rename:         coda_rename,
 80         permission:     coda_permission,
 81         revalidate:     coda_revalidate_inode,
 82         setattr:        coda_notify_change,
 83 };
 84 
 85 struct file_operations coda_dir_operations = {
 86         read:           generic_read_dir,
 87         readdir:        coda_readdir,
 88         open:           coda_open,
 89         release:        coda_release,
 90         fsync:          coda_fsync,
 91 };
 92 
 93 
 94 /* inode operations for directories */
 95 /* acces 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 
142                 /* make sure we drop unexpected weird fid's */
143                 if (coda_f2i(&resfid) != res_inode->i_ino &&
144                     !coda_fid_is_weird(&resfid))
145                         dropme = 1;
146         } else if (error != -ENOENT) {
147                 CDEBUG(D_INODE, "error for %s(%*s)%d\n",
148                        coda_i2s(dir), (int)length, name, error);
149                 return ERR_PTR(error);
150         }
151         CDEBUG(D_INODE, "lookup: %s is (%s), type %d result %d, dropme %d\n",
152                name, coda_f2s(&resfid), type, error, dropme);
153 
154 exit:
155         entry->d_time = 0;
156         entry->d_op = &coda_dentry_operations;
157         d_add(entry, res_inode);
158         if ( dropme ) {
159                 d_drop(entry);
160                 coda_flag_inode(res_inode, C_VATTR);
161         }
162         EXIT;
163         return NULL;
164 }
165 
166 
167 int coda_permission(struct inode *inode, int mask)
168 {
169         int error;
170  
171         ENTRY;
172         coda_vfs_stat.permission++;
173 
174         if ( mask == 0 )
175                 return 0;
176 
177         if ( coda_access_cache ) {
178                 coda_permission_stat.count++;
179 
180                 if ( coda_cache_check(inode, mask) ) {
181                         coda_permission_stat.hit_count++;
182                         return 0; 
183                 }
184         }
185 
186         CDEBUG(D_INODE, "mask is %o\n", mask);
187         error = venus_access(inode->i_sb, coda_i2f(inode), mask);
188     
189         CDEBUG(D_INODE, "fid: %s, ino: %ld (mask: %o) error: %d\n", 
190                coda_i2s(inode), inode->i_ino, mask, error);
191 
192         if (!error)
193                 coda_cache_enter(inode, mask);
194 
195         return error; 
196 }
197 
198 
199 static inline void coda_dir_changed(struct inode *dir, int link)
200 {
201 #ifdef REQUERY_VENUS_FOR_MTIME
202         /* invalidate the directory cnode's attributes so we refetch the
203          * attributes from venus next time the inode is referenced */
204         coda_flag_inode(dir, C_VATTR);
205 #else
206         /* optimistically we can also act as if our nose bleeds. The
207          * granularity of the mtime is coarse anyways so we might actually be
208          * right most of the time. Note: we only do this for directories. */
209         dir->i_mtime = CURRENT_TIME;
210 #endif
211         if (link)
212                 dir->i_nlink += link;
213 }
214 
215 /* creation routines: create, mknod, mkdir, link, symlink */
216 static int coda_create(struct inode *dir, struct dentry *de, int mode)
217 {
218         int error=0;
219         const char *name=de->d_name.name;
220         int length=de->d_name.len;
221         struct inode *result = NULL;
222         struct ViceFid newfid;
223         struct coda_vattr attrs;
224 
225         ENTRY;
226         coda_vfs_stat.create++;
227 
228         CDEBUG(D_INODE, "name: %s, length %d, mode %o\n", name, length, mode);
229 
230         if (coda_isroot(dir) && coda_iscontrol(name, length))
231                 return -EPERM;
232 
233         error = venus_create(dir->i_sb, coda_i2f(dir), name, length, 
234                                 0, mode, 0, &newfid, &attrs);
235 
236         if ( error ) {
237                 CDEBUG(D_INODE, "create: %s, result %d\n",
238                        coda_f2s(&newfid), error); 
239                 d_drop(de);
240                 return error;
241         }
242 
243         error = coda_cnode_make(&result, &newfid, dir->i_sb);
244         if ( error ) {
245                 d_drop(de);
246                 result = NULL;
247                 return error;
248         }
249 
250         /* invalidate the directory cnode's attributes */
251         coda_dir_changed(dir, 0);
252         d_instantiate(de, result);
253         return 0;
254 }
255 
256 static int coda_mknod(struct inode *dir, struct dentry *de, int mode, int rdev)
257 {
258         int error=0;
259         const char *name=de->d_name.name;
260         int length=de->d_name.len;
261         struct inode *result = NULL;
262         struct ViceFid newfid;
263         struct coda_vattr attrs;
264 
265         if ( coda_hasmknod == 0 )
266                 return -EIO;
267 
268         coda_vfs_stat.create++;
269 
270         CDEBUG(D_INODE, "name: %s, length %d, mode %o, rdev %x\n",
271                name, length, mode, rdev);
272 
273         if (coda_isroot(dir) && coda_iscontrol(name, length))
274                 return -EPERM;
275 
276         error = venus_create(dir->i_sb, coda_i2f(dir), name, length, 
277                                 0, mode, rdev, &newfid, &attrs);
278 
279         if ( error ) {
280                 CDEBUG(D_INODE, "mknod: %s, result %d\n",
281                        coda_f2s(&newfid), error); 
282                 d_drop(de);
283                 return error;
284         }
285 
286         error = coda_cnode_make(&result, &newfid, dir->i_sb);
287         if ( error ) {
288                 d_drop(de);
289                 result = NULL;
290                 return error;
291         }
292 
293         /* invalidate the directory cnode's attributes */
294         coda_dir_changed(dir, 0);
295         d_instantiate(de, result);
296         return 0;
297 }                            
298 
299 static int coda_mkdir(struct inode *dir, struct dentry *de, int mode)
300 {
301         struct inode *inode;
302         struct coda_vattr attr;
303         const char *name = de->d_name.name;
304         int len = de->d_name.len;
305         int error;
306         struct ViceFid newfid;
307 
308         ENTRY;
309         coda_vfs_stat.mkdir++;
310 
311         if (coda_isroot(dir) && coda_iscontrol(name, len))
312                 return -EPERM;
313 
314         CDEBUG(D_INODE, "mkdir %s (len %d) in %s, mode %o.\n", 
315                name, len, coda_i2s(dir), mode);
316 
317         attr.va_mode = mode;
318         error = venus_mkdir(dir->i_sb, coda_i2f(dir), 
319                                name, len, &newfid, &attr);
320         
321         if ( error ) {
322                 CDEBUG(D_INODE, "mkdir error: %s result %d\n", 
323                        coda_f2s(&newfid), error); 
324                 d_drop(de);
325                 return error;
326         }
327          
328         CDEBUG(D_INODE, "mkdir: new dir has fid %s.\n", 
329                coda_f2s(&newfid)); 
330 
331         error = coda_cnode_make(&inode, &newfid, dir->i_sb);
332         if ( error ) {
333                 d_drop(de);
334                 return error;
335         }
336         
337         /* invalidate the directory cnode's attributes */
338         coda_dir_changed(dir, 1);
339         d_instantiate(de, inode);
340         return 0;
341 }
342 
343 /* try to make de an entry in dir_inodde linked to source_de */ 
344 static int coda_link(struct dentry *source_de, struct inode *dir_inode, 
345           struct dentry *de)
346 {
347         struct inode *inode = source_de->d_inode;
348         const char * name = de->d_name.name;
349         int len = de->d_name.len;
350         int error;
351 
352         ENTRY;
353         coda_vfs_stat.link++;
354 
355         if (coda_isroot(dir_inode) && coda_iscontrol(name, len))
356                 return -EPERM;
357 
358         CDEBUG(D_INODE, "old: fid: %s\n", coda_i2s(inode));
359         CDEBUG(D_INODE, "directory: %s\n", coda_i2s(dir_inode));
360 
361         error = venus_link(dir_inode->i_sb, coda_i2f(inode),
362                            coda_i2f(dir_inode), (const char *)name, len);
363 
364         if (error) { 
365                 d_drop(de);
366                 goto out;
367         }
368 
369         coda_dir_changed(dir_inode, 0);
370         atomic_inc(&inode->i_count);
371         d_instantiate(de, inode);
372         inode->i_nlink++;
373         
374 out:
375         CDEBUG(D_INODE, "link result %d\n",error);
376         EXIT;
377         return(error);
378 }
379 
380 
381 static int coda_symlink(struct inode *dir_inode, struct dentry *de,
382                         const char *symname)
383 {
384         const char *name = de->d_name.name;
385         int len = de->d_name.len;
386         int symlen;
387         int error=0;
388         
389         ENTRY;
390         coda_vfs_stat.symlink++;
391 
392         if (coda_isroot(dir_inode) && coda_iscontrol(name, len))
393                 return -EPERM;
394 
395         symlen = strlen(symname);
396         if ( symlen > CODA_MAXPATHLEN )
397                 return -ENAMETOOLONG;
398 
399         CDEBUG(D_INODE, "symname: %s, length: %d\n", symname, symlen);
400 
401         /*
402          * This entry is now negative. Since we do not create
403          * an inode for the entry we have to drop it. 
404          */
405         d_drop(de);
406         error = venus_symlink(dir_inode->i_sb, coda_i2f(dir_inode), name, len, 
407                               symname, symlen);
408 
409         /* mtime is no good anymore */
410         if ( !error )
411                 coda_dir_changed(dir_inode, 0);
412 
413         CDEBUG(D_INODE, "in symlink result %d\n",error);
414         EXIT;
415         return error;
416 }
417 
418 /* destruction routines: unlink, rmdir */
419 int coda_unlink(struct inode *dir, struct dentry *de)
420 {
421         int error;
422         const char *name = de->d_name.name;
423         int len = de->d_name.len;
424 
425         ENTRY;
426         coda_vfs_stat.unlink++;
427 
428         CDEBUG(D_INODE, " %s in %s, dirino %ld\n", name , 
429                coda_i2s(dir), dir->i_ino);
430 
431         error = venus_remove(dir->i_sb, coda_i2f(dir), name, len);
432         if ( error ) {
433                 CDEBUG(D_INODE, "upc returned error %d\n", error);
434                 return error;
435         }
436 
437         coda_dir_changed(dir, 0);
438         de->d_inode->i_nlink--;
439 
440         return 0;
441 }
442 
443 int coda_rmdir(struct inode *dir, struct dentry *de)
444 {
445         const char *name = de->d_name.name;
446         int len = de->d_name.len;
447         int error;
448 
449         ENTRY;
450         coda_vfs_stat.rmdir++;
451 
452         if (!d_unhashed(de))
453                 return -EBUSY;
454         error = venus_rmdir(dir->i_sb, coda_i2f(dir), name, len);
455 
456         if ( error ) {
457                 CDEBUG(D_INODE, "upc returned error %d\n", error);
458                 return error;
459         }
460 
461         coda_dir_changed(dir, -1);
462         de->d_inode->i_nlink--;
463         d_delete(de);
464 
465         return 0;
466 }
467 
468 /* rename */
469 static int coda_rename(struct inode *old_dir, struct dentry *old_dentry, 
470                        struct inode *new_dir, struct dentry *new_dentry)
471 {
472         const char *old_name = old_dentry->d_name.name;
473         const char *new_name = new_dentry->d_name.name;
474         int old_length = old_dentry->d_name.len;
475         int new_length = new_dentry->d_name.len;
476         int link_adjust = 0;
477         int error;
478 
479         ENTRY;
480         coda_vfs_stat.rename++;
481 
482         CDEBUG(D_INODE, "old: %s, (%d length), new: %s"
483                "(%d length). old:d_count: %d, new:d_count: %d\n", 
484                old_name, old_length, new_name, new_length,
485                atomic_read(&old_dentry->d_count), atomic_read(&new_dentry->d_count));
486 
487         error = venus_rename(old_dir->i_sb, coda_i2f(old_dir), 
488                              coda_i2f(new_dir), old_length, new_length, 
489                              (const char *) old_name, (const char *)new_name);
490 
491         if ( !error ) {
492                 if ( new_dentry->d_inode ) {
493                         if ( S_ISDIR(new_dentry->d_inode->i_mode) )
494                                 link_adjust = 1;
495 
496                         coda_dir_changed(old_dir, -link_adjust);
497                         coda_dir_changed(new_dir,  link_adjust);
498                         coda_flag_inode(new_dentry->d_inode, C_VATTR);
499                 } else {
500                         coda_flag_inode(old_dir, C_VATTR);
501                         coda_flag_inode(new_dir, C_VATTR);
502                 }
503         }
504 
505         CDEBUG(D_INODE, "result %d\n", error); 
506 
507         EXIT;
508         return error;
509 }
510 
511 
512 /* file operations for directories */
513 int coda_readdir(struct file *file, void *dirent,  filldir_t filldir)
514 {
515         int result = 0;
516         struct file open_file;
517         struct dentry open_dentry;
518         struct inode *inode=file->f_dentry->d_inode, *container;
519 
520         ENTRY;
521         coda_vfs_stat.readdir++;
522 
523         if ( inode->i_mapping == &inode->i_data ) {
524                 CDEBUG(D_FILE, "no container inode.\n");
525                 return -EIO;
526         }
527 
528         container = inode->i_mapping->host;
529 
530         coda_prepare_fakefile(inode, file, container, &open_file, &open_dentry);
531 
532         if ( S_ISREG(container->i_mode) ) {
533                 /* Venus: we must read Venus dirents from the file */
534                 result = coda_venus_readdir(&open_file, dirent, filldir);
535         } else {
536                 /* potemkin case: we are handed a directory inode */
537                 result = vfs_readdir(&open_file, filldir, dirent);
538         }
539 
540         /* we only have to restore the file position (and f_version?) */
541         file->f_pos = open_file.f_pos;
542         file->f_version = open_file.f_version;
543 
544         EXIT;
545         return result;
546 }
547 
548 /* grab the ext2 inode of the container file */
549 static int coda_inode_grab(dev_t dev, ino_t ino, struct inode **ind)
550 {
551         struct super_block *sbptr;
552 
553         sbptr = get_super(dev);
554 
555         if ( !sbptr ) {
556                 printk("coda_inode_grab: coda_find_super returns NULL.\n");
557                 return -ENXIO;
558         }
559                 
560         *ind = NULL;
561         *ind = iget(sbptr, ino);
562 
563         if ( *ind == NULL ) {
564                 printk("coda_inode_grab: iget(dev: %d, ino: %ld) "
565                        "returns NULL.\n", dev, (long)ino);
566                 return -ENOENT;
567         }
568         CDEBUG(D_FILE, "ino: %ld, ops at %p\n", (long)ino, (*ind)->i_op);
569         return 0;
570 }
571 
572 /* ask venus to cache the file and return the inode of the container file,
573    put this inode pointer in the cnode for future read/writes */
574 int coda_open(struct inode *i, struct file *f)
575 {
576         ino_t ino;
577         dev_t dev;
578         int error = 0;
579         struct inode *cont_inode = NULL, *old_container;
580         unsigned short flags = f->f_flags & (~O_EXCL);
581         unsigned short coda_flags = coda_flags_to_cflags(flags);
582         struct coda_cred *cred;
583         struct coda_inode_info *cii;
584 
585         lock_kernel();
586         ENTRY;
587         coda_vfs_stat.open++;
588 
589         CDEBUG(D_SPECIAL, "OPEN inode number: %ld, count %d, flags %o.\n", 
590                f->f_dentry->d_inode->i_ino, atomic_read(&f->f_dentry->d_count), flags);
591 
592         error = venus_open(i->i_sb, coda_i2f(i), coda_flags, &ino, &dev); 
593         if (error) {
594                 CDEBUG(D_FILE, "venus: dev %d, inode %ld, out->result %d\n",
595                        dev, (long)ino, error);
596                 unlock_kernel();
597                 return error;
598         }
599 
600         /* coda_upcall returns ino number of cached object, get inode */
601         CDEBUG(D_FILE, "cache file dev %d, ino %ld\n", dev, (long)ino);
602         error = coda_inode_grab(dev, ino, &cont_inode);
603         
604         if ( error || !cont_inode ){
605                 printk("coda_open: coda_inode_grab error %d.", error);
606                 if (cont_inode) 
607                         iput(cont_inode);
608                 unlock_kernel();
609                 return error;
610         }
611 
612         CODA_ALLOC(cred, struct coda_cred *, sizeof(*cred));
613         coda_load_creds(cred);
614         f->private_data = cred;
615 
616         if ( i->i_mapping != &i->i_data ) {
617                 old_container = i->i_mapping->host;
618                 i->i_mapping = &i->i_data;
619                 iput(old_container);
620         }
621         i->i_mapping = cont_inode->i_mapping;
622 
623         cii = ITOC(i);
624         cii->c_contcount++;
625 
626         CDEBUG(D_FILE, "result %d, coda i->i_count is %d, cii->contcount is %d for ino %ld\n", 
627                error, atomic_read(&i->i_count), cii->c_contcount, i->i_ino);
628         CDEBUG(D_FILE, "cache ino: %ld, count %d, ops %p\n", 
629                cont_inode->i_ino, atomic_read(&cont_inode->i_count),
630                cont_inode->i_op);
631         EXIT;
632         unlock_kernel();
633         return 0;
634 }
635 
636 int coda_release(struct inode *i, struct file *f)
637 {
638         struct inode *container = NULL;
639         int error = 0;
640         unsigned short flags = (f->f_flags) & (~O_EXCL);
641         unsigned short cflags = coda_flags_to_cflags(flags);
642         struct coda_cred *cred;
643         struct coda_inode_info *cii;
644 
645         lock_kernel();
646         ENTRY;
647         coda_vfs_stat.release++;
648 
649         cred = (struct coda_cred *)f->private_data;
650 
651         if (i->i_mapping != &i->i_data)
652                 container = i->i_mapping->host;
653 
654         cii = ITOC(i);
655         CDEBUG(D_FILE, "RELEASE coda (ino %ld, ct %d, cc %d) cache (ino %ld, ct %d)\n",
656                 i->i_ino, atomic_read(&i->i_count), cii->c_contcount,
657                 (container ? container->i_ino : 0),
658                 (container ? atomic_read(&container->i_count) : -99));
659 
660         if (--cii->c_contcount == 0 && container) {
661                 i->i_mapping = &i->i_data;
662                 iput(container);
663         }
664 
665         error = venus_release(i->i_sb, coda_i2f(i), cflags, cred);
666 
667         f->private_data = NULL;
668         if (cred)
669                 CODA_FREE(cred, sizeof(*cred));
670 
671         CDEBUG(D_FILE, "coda_release: result: %d\n", error);
672         unlock_kernel();
673         return error;
674 }
675 
676 /* support routines */
677 
678 /* instantiate a fake file and dentry to pass to coda_venus_readdir */
679 static void coda_prepare_fakefile(struct inode *i, struct file *coda_file, 
680                                   struct inode *cont_inode,
681                                   struct file *cont_file,
682                                   struct dentry *cont_dentry)
683 {
684         cont_file->f_dentry = cont_dentry;
685         cont_file->f_dentry->d_inode = cont_inode;
686         cont_file->f_pos = coda_file->f_pos;
687         cont_file->f_version = coda_file->f_version;
688         cont_file->f_op = cont_inode->i_fop;
689         return ;
690 }
691 
692 /* 
693  * this structure is manipulated by filldir in vfs layer.
694  * the count holds the remaining amount of space in the getdents buffer,
695  * beyond the current_dir pointer.
696  *
697  * What structure is this comment referring to?? -JH
698  */
699 
700 /* should be big enough to hold any single directory entry */
701 #define DIR_BUFSIZE 2048
702 
703 static int coda_venus_readdir(struct file *filp, void *getdent, 
704                               filldir_t filldir)
705 {
706         int bufsize;
707         int offset = filp->f_pos; /* offset in the directory file */
708         int count = 0;
709         int pos = 0;      /* offset in the block we read */
710         int result = 0; /* either an error or # of entries returned */
711         int errfill;
712         char *buff = NULL;
713         struct venus_dirent *vdirent;
714         int string_offset = (int) (&((struct venus_dirent *)(0))->d_name);
715         int i;
716 
717         ENTRY;        
718 
719         CODA_ALLOC(buff, char *, DIR_BUFSIZE);
720         if ( !buff ) { 
721                 printk("coda_venus_readdir: out of memory.\n");
722                 return -ENOMEM;
723         }
724 
725         /* we use this routine to read the file into our buffer */
726         bufsize = kernel_read(filp, filp->f_pos, buff, DIR_BUFSIZE);
727         if ( bufsize < 0) {
728                 printk("coda_venus_readdir: cannot read directory %d.\n",
729                        bufsize);
730                 result = bufsize;
731                 goto exit;
732         }
733         if ( bufsize == 0) {
734                 result = 0;
735                 goto exit;
736         }
737         
738         /* Parse and write into user space. Filldir tells us when done! */
739         CDEBUG(D_FILE, "buffsize: %d offset %d, count %d.\n", 
740                bufsize, offset, count);
741 
742         i = 0;
743         result = 0; 
744         while ( pos + string_offset < bufsize && i < 1024) {
745                 vdirent = (struct venus_dirent *) (buff + pos);
746 
747                 /* test if the name is fully in the buffer */
748                 if ( pos + string_offset + (int) vdirent->d_namlen >= bufsize ){
749                         if ( result == 0 )
750                                 printk("CODA: Invalid directory cfino: %ld\n", 
751                                        filp->f_dentry->d_inode->i_ino);
752                         break;
753                 }
754                 /* now we are certain that we can read the entry from buff */
755 
756                 /* if we don't have a null entry, copy it */
757                 if ( vdirent->d_fileno && vdirent->d_reclen ) {
758                         int namlen  = vdirent->d_namlen;
759                         off_t offs  = filp->f_pos; 
760                         ino_t ino   = vdirent->d_fileno;
761                         char *name  = vdirent->d_name;
762 
763                         errfill = filldir(getdent,  name, namlen, 
764                                           offs, ino, DT_UNKNOWN); 
765 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);
766                         /* errfill means no space for filling in this round */
767                         if ( errfill < 0 ) {
768                                 result = 0;
769                                 break;
770                         }
771                         /* adjust count */
772                         result++;
773                 }
774                 /* next one */
775                 filp->f_pos += vdirent->d_reclen;
776                 if ( filp->f_pos > filp->f_dentry->d_inode->i_size )
777                         break; 
778                 if ( !vdirent->d_reclen ) {
779                         printk("CODA: Invalid directory, cfino: %ld\n", 
780                                filp->f_dentry->d_inode->i_ino);
781                         result = -EINVAL;
782                         break;
783                 }
784                 pos += (unsigned int) vdirent->d_reclen;
785                 i++;
786         } 
787 
788        if ( i >= 1024 ) {
789                printk("Repeating too much in readdir %ld\n", 
790                       filp->f_dentry->d_inode->i_ino);
791                result = -EINVAL;
792        }
793 
794 exit:
795         CODA_FREE(buff, DIR_BUFSIZE);
796         return result;
797 }
798 
799 /* called when a cache lookup succeeds */
800 static int coda_dentry_revalidate(struct dentry *de, int flags)
801 {
802         struct inode *inode = de->d_inode;
803         struct coda_inode_info *cii;
804         ENTRY;
805 
806         if (!inode)
807                 return 1;
808         lock_kernel();
809         if (coda_isroot(inode))
810                 goto out;
811         if (is_bad_inode(inode))
812                 goto bad;
813 
814         cii = ITOC(de->d_inode);
815         if (! (cii->c_flags & (C_PURGE | C_FLUSH)) )
816                 goto out;
817 
818         shrink_dcache_parent(de);
819 
820         /* propagate for a flush */
821         if (cii->c_flags & C_FLUSH) 
822                 coda_flag_inode_children(inode, C_FLUSH);
823 
824         if (atomic_read(&de->d_count) > 1) {
825                 /* pretend it's valid, but don't change the flags */
826                 CDEBUG(D_DOWNCALL, "BOOM for: ino %ld, %s\n",
827                        de->d_inode->i_ino, coda_f2s(&cii->c_fid));
828                 goto out;
829         }
830 
831         /* clear the flags. */
832         cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH);
833 
834 bad:
835         unlock_kernel();
836         return 0;
837 out:
838         unlock_kernel();
839         return 1;
840 }
841 
842 /*
843  * This is the callback from dput() when d_count is going to 0.
844  * We use this to unhash dentries with bad inodes.
845  */
846 static int coda_dentry_delete(struct dentry * dentry)
847 {
848         int flags;
849 
850         if (!dentry->d_inode) 
851                 return 0;
852 
853         flags = (ITOC(dentry->d_inode)->c_flags) & C_PURGE;
854         if (is_bad_inode(dentry->d_inode) || flags) {
855                 CDEBUG(D_DOWNCALL, "bad inode, unhashing %s/%s, %ld\n", 
856                        dentry->d_parent->d_name.name, dentry->d_name.name,
857                        dentry->d_inode->i_ino);
858                 return 1;
859         }
860         return 0;
861 }
862 
863 
864 
865 /*
866  * This is called when we want to check if the inode has
867  * changed on the server.  Coda makes this easy since the
868  * cache manager Venus issues a downcall to the kernel when this 
869  * happens 
870  */
871 int coda_revalidate_inode(struct dentry *dentry)
872 {
873         struct coda_vattr attr;
874         int error = 0;
875         int old_mode;
876         ino_t old_ino;
877         struct inode *inode = dentry->d_inode, *container;
878         struct coda_inode_info *cii = ITOC(inode);
879 
880         ENTRY;
881         CDEBUG(D_INODE, "revalidating: %*s/%*s\n", 
882                dentry->d_name.len, dentry->d_name.name,
883                dentry->d_parent->d_name.len, dentry->d_parent->d_name.name);
884 
885         lock_kernel();
886         if ( cii->c_flags == 0 )
887                 goto ok;
888 
889         if (cii->c_flags & (C_VATTR | C_PURGE | C_FLUSH)) {
890                 error = venus_getattr(inode->i_sb, &(cii->c_fid), &attr);
891                 if ( error )
892                         goto return_bad_inode;
893 
894                 /* this inode may be lost if:
895                    - it's ino changed 
896                    - type changes must be permitted for repair and
897                    missing mount points.
898                 */
899                 old_mode = inode->i_mode;
900                 old_ino = inode->i_ino;
901                 coda_vattr_to_iattr(inode, &attr);
902 
903                 if ((old_mode & S_IFMT) != (inode->i_mode & S_IFMT)) {
904                         printk("Coda: inode %ld, fid %s changed type!\n",
905                                inode->i_ino, coda_f2s(&(cii->c_fid)));
906                 }
907 
908                 /* the following can happen when a local fid is replaced 
909                    with a global one, here we lose and declare the inode bad */
910                 if (inode->i_ino != old_ino)
911                         goto return_bad_inode;
912                 
913                 if ( cii->c_flags ) 
914                         coda_flag_inode_children(inode, C_FLUSH);
915                 
916                 cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH);
917         }
918 
919 ok:
920         unlock_kernel();
921         return 0;
922 
923 return_bad_inode:
924         if ( inode->i_mapping != &inode->i_data ) {
925                 container = inode->i_mapping->host;
926                 inode->i_mapping = &inode->i_data;
927                 iput(container);
928         }
929         make_bad_inode(inode);
930         unlock_kernel();
931         return -EIO;
932 }
933 
934 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.