OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [LINUX_2_4_26_OR32/] [linux/] [linux-2.4/] [fs/] [coda/] [dir.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.