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

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [fs/] [afs/] [dir.c] - Blame information for rev 17

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/* dir.c: AFS filesystem directory handling
2
 *
3
 * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
4
 * Written by David Howells (dhowells@redhat.com)
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version
9
 * 2 of the License, or (at your option) any later version.
10
 */
11
 
12
#include <linux/kernel.h>
13
#include <linux/module.h>
14
#include <linux/init.h>
15
#include <linux/slab.h>
16
#include <linux/fs.h>
17
#include <linux/pagemap.h>
18
#include <linux/ctype.h>
19
#include <linux/sched.h>
20
#include "internal.h"
21
 
22
static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
23
                                 struct nameidata *nd);
24
static int afs_dir_open(struct inode *inode, struct file *file);
25
static int afs_readdir(struct file *file, void *dirent, filldir_t filldir);
26
static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd);
27
static int afs_d_delete(struct dentry *dentry);
28
static void afs_d_release(struct dentry *dentry);
29
static int afs_lookup_filldir(void *_cookie, const char *name, int nlen,
30
                                  loff_t fpos, u64 ino, unsigned dtype);
31
static int afs_create(struct inode *dir, struct dentry *dentry, int mode,
32
                      struct nameidata *nd);
33
static int afs_mkdir(struct inode *dir, struct dentry *dentry, int mode);
34
static int afs_rmdir(struct inode *dir, struct dentry *dentry);
35
static int afs_unlink(struct inode *dir, struct dentry *dentry);
36
static int afs_link(struct dentry *from, struct inode *dir,
37
                    struct dentry *dentry);
38
static int afs_symlink(struct inode *dir, struct dentry *dentry,
39
                       const char *content);
40
static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
41
                      struct inode *new_dir, struct dentry *new_dentry);
42
 
43
const struct file_operations afs_dir_file_operations = {
44
        .open           = afs_dir_open,
45
        .release        = afs_release,
46
        .readdir        = afs_readdir,
47
        .lock           = afs_lock,
48
};
49
 
50
const struct inode_operations afs_dir_inode_operations = {
51
        .create         = afs_create,
52
        .lookup         = afs_lookup,
53
        .link           = afs_link,
54
        .unlink         = afs_unlink,
55
        .symlink        = afs_symlink,
56
        .mkdir          = afs_mkdir,
57
        .rmdir          = afs_rmdir,
58
        .rename         = afs_rename,
59
        .permission     = afs_permission,
60
        .getattr        = afs_getattr,
61
        .setattr        = afs_setattr,
62
};
63
 
64
static struct dentry_operations afs_fs_dentry_operations = {
65
        .d_revalidate   = afs_d_revalidate,
66
        .d_delete       = afs_d_delete,
67
        .d_release      = afs_d_release,
68
};
69
 
70
#define AFS_DIR_HASHTBL_SIZE    128
71
#define AFS_DIR_DIRENT_SIZE     32
72
#define AFS_DIRENT_PER_BLOCK    64
73
 
74
union afs_dirent {
75
        struct {
76
                uint8_t         valid;
77
                uint8_t         unused[1];
78
                __be16          hash_next;
79
                __be32          vnode;
80
                __be32          unique;
81
                uint8_t         name[16];
82
                uint8_t         overflow[4];    /* if any char of the name (inc
83
                                                 * NUL) reaches here, consume
84
                                                 * the next dirent too */
85
        } u;
86
        uint8_t extended_name[32];
87
};
88
 
89
/* AFS directory page header (one at the beginning of every 2048-byte chunk) */
90
struct afs_dir_pagehdr {
91
        __be16          npages;
92
        __be16          magic;
93
#define AFS_DIR_MAGIC htons(1234)
94
        uint8_t         nentries;
95
        uint8_t         bitmap[8];
96
        uint8_t         pad[19];
97
};
98
 
99
/* directory block layout */
100
union afs_dir_block {
101
 
102
        struct afs_dir_pagehdr pagehdr;
103
 
104
        struct {
105
                struct afs_dir_pagehdr  pagehdr;
106
                uint8_t                 alloc_ctrs[128];
107
                /* dir hash table */
108
                uint16_t                hashtable[AFS_DIR_HASHTBL_SIZE];
109
        } hdr;
110
 
111
        union afs_dirent dirents[AFS_DIRENT_PER_BLOCK];
112
};
113
 
114
/* layout on a linux VM page */
115
struct afs_dir_page {
116
        union afs_dir_block blocks[PAGE_SIZE / sizeof(union afs_dir_block)];
117
};
118
 
119
struct afs_lookup_cookie {
120
        struct afs_fid  fid;
121
        const char      *name;
122
        size_t          nlen;
123
        int             found;
124
};
125
 
126
/*
127
 * check that a directory page is valid
128
 */
129
static inline void afs_dir_check_page(struct inode *dir, struct page *page)
130
{
131
        struct afs_dir_page *dbuf;
132
        loff_t latter;
133
        int tmp, qty;
134
 
135
#if 0
136
        /* check the page count */
137
        qty = desc.size / sizeof(dbuf->blocks[0]);
138
        if (qty == 0)
139
                goto error;
140
 
141
        if (page->index == 0 && qty != ntohs(dbuf->blocks[0].pagehdr.npages)) {
142
                printk("kAFS: %s(%lu): wrong number of dir blocks %d!=%hu\n",
143
                       __FUNCTION__, dir->i_ino, qty,
144
                       ntohs(dbuf->blocks[0].pagehdr.npages));
145
                goto error;
146
        }
147
#endif
148
 
149
        /* determine how many magic numbers there should be in this page */
150
        latter = dir->i_size - page_offset(page);
151
        if (latter >= PAGE_SIZE)
152
                qty = PAGE_SIZE;
153
        else
154
                qty = latter;
155
        qty /= sizeof(union afs_dir_block);
156
 
157
        /* check them */
158
        dbuf = page_address(page);
159
        for (tmp = 0; tmp < qty; tmp++) {
160
                if (dbuf->blocks[tmp].pagehdr.magic != AFS_DIR_MAGIC) {
161
                        printk("kAFS: %s(%lu): bad magic %d/%d is %04hx\n",
162
                               __FUNCTION__, dir->i_ino, tmp, qty,
163
                               ntohs(dbuf->blocks[tmp].pagehdr.magic));
164
                        goto error;
165
                }
166
        }
167
 
168
        SetPageChecked(page);
169
        return;
170
 
171
error:
172
        SetPageChecked(page);
173
        SetPageError(page);
174
}
175
 
176
/*
177
 * discard a page cached in the pagecache
178
 */
179
static inline void afs_dir_put_page(struct page *page)
180
{
181
        kunmap(page);
182
        page_cache_release(page);
183
}
184
 
185
/*
186
 * get a page into the pagecache
187
 */
188
static struct page *afs_dir_get_page(struct inode *dir, unsigned long index,
189
                                     struct key *key)
190
{
191
        struct page *page;
192
        struct file file = {
193
                .private_data = key,
194
        };
195
 
196
        _enter("{%lu},%lu", dir->i_ino, index);
197
 
198
        page = read_mapping_page(dir->i_mapping, index, &file);
199
        if (!IS_ERR(page)) {
200
                kmap(page);
201
                if (!PageChecked(page))
202
                        afs_dir_check_page(dir, page);
203
                if (PageError(page))
204
                        goto fail;
205
        }
206
        return page;
207
 
208
fail:
209
        afs_dir_put_page(page);
210
        _leave(" = -EIO");
211
        return ERR_PTR(-EIO);
212
}
213
 
214
/*
215
 * open an AFS directory file
216
 */
217
static int afs_dir_open(struct inode *inode, struct file *file)
218
{
219
        _enter("{%lu}", inode->i_ino);
220
 
221
        BUILD_BUG_ON(sizeof(union afs_dir_block) != 2048);
222
        BUILD_BUG_ON(sizeof(union afs_dirent) != 32);
223
 
224
        if (test_bit(AFS_VNODE_DELETED, &AFS_FS_I(inode)->flags))
225
                return -ENOENT;
226
 
227
        return afs_open(inode, file);
228
}
229
 
230
/*
231
 * deal with one block in an AFS directory
232
 */
233
static int afs_dir_iterate_block(unsigned *fpos,
234
                                 union afs_dir_block *block,
235
                                 unsigned blkoff,
236
                                 void *cookie,
237
                                 filldir_t filldir)
238
{
239
        union afs_dirent *dire;
240
        unsigned offset, next, curr;
241
        size_t nlen;
242
        int tmp, ret;
243
 
244
        _enter("%u,%x,%p,,",*fpos,blkoff,block);
245
 
246
        curr = (*fpos - blkoff) / sizeof(union afs_dirent);
247
 
248
        /* walk through the block, an entry at a time */
249
        for (offset = AFS_DIRENT_PER_BLOCK - block->pagehdr.nentries;
250
             offset < AFS_DIRENT_PER_BLOCK;
251
             offset = next
252
             ) {
253
                next = offset + 1;
254
 
255
                /* skip entries marked unused in the bitmap */
256
                if (!(block->pagehdr.bitmap[offset / 8] &
257
                      (1 << (offset % 8)))) {
258
                        _debug("ENT[%Zu.%u]: unused",
259
                               blkoff / sizeof(union afs_dir_block), offset);
260
                        if (offset >= curr)
261
                                *fpos = blkoff +
262
                                        next * sizeof(union afs_dirent);
263
                        continue;
264
                }
265
 
266
                /* got a valid entry */
267
                dire = &block->dirents[offset];
268
                nlen = strnlen(dire->u.name,
269
                               sizeof(*block) -
270
                               offset * sizeof(union afs_dirent));
271
 
272
                _debug("ENT[%Zu.%u]: %s %Zu \"%s\"",
273
                       blkoff / sizeof(union afs_dir_block), offset,
274
                       (offset < curr ? "skip" : "fill"),
275
                       nlen, dire->u.name);
276
 
277
                /* work out where the next possible entry is */
278
                for (tmp = nlen; tmp > 15; tmp -= sizeof(union afs_dirent)) {
279
                        if (next >= AFS_DIRENT_PER_BLOCK) {
280
                                _debug("ENT[%Zu.%u]:"
281
                                       " %u travelled beyond end dir block"
282
                                       " (len %u/%Zu)",
283
                                       blkoff / sizeof(union afs_dir_block),
284
                                       offset, next, tmp, nlen);
285
                                return -EIO;
286
                        }
287
                        if (!(block->pagehdr.bitmap[next / 8] &
288
                              (1 << (next % 8)))) {
289
                                _debug("ENT[%Zu.%u]:"
290
                                       " %u unmarked extension (len %u/%Zu)",
291
                                       blkoff / sizeof(union afs_dir_block),
292
                                       offset, next, tmp, nlen);
293
                                return -EIO;
294
                        }
295
 
296
                        _debug("ENT[%Zu.%u]: ext %u/%Zu",
297
                               blkoff / sizeof(union afs_dir_block),
298
                               next, tmp, nlen);
299
                        next++;
300
                }
301
 
302
                /* skip if starts before the current position */
303
                if (offset < curr)
304
                        continue;
305
 
306
                /* found the next entry */
307
                ret = filldir(cookie,
308
                              dire->u.name,
309
                              nlen,
310
                              blkoff + offset * sizeof(union afs_dirent),
311
                              ntohl(dire->u.vnode),
312
                              filldir == afs_lookup_filldir ?
313
                              ntohl(dire->u.unique) : DT_UNKNOWN);
314
                if (ret < 0) {
315
                        _leave(" = 0 [full]");
316
                        return 0;
317
                }
318
 
319
                *fpos = blkoff + next * sizeof(union afs_dirent);
320
        }
321
 
322
        _leave(" = 1 [more]");
323
        return 1;
324
}
325
 
326
/*
327
 * iterate through the data blob that lists the contents of an AFS directory
328
 */
329
static int afs_dir_iterate(struct inode *dir, unsigned *fpos, void *cookie,
330
                           filldir_t filldir, struct key *key)
331
{
332
        union afs_dir_block *dblock;
333
        struct afs_dir_page *dbuf;
334
        struct page *page;
335
        unsigned blkoff, limit;
336
        int ret;
337
 
338
        _enter("{%lu},%u,,", dir->i_ino, *fpos);
339
 
340
        if (test_bit(AFS_VNODE_DELETED, &AFS_FS_I(dir)->flags)) {
341
                _leave(" = -ESTALE");
342
                return -ESTALE;
343
        }
344
 
345
        /* round the file position up to the next entry boundary */
346
        *fpos += sizeof(union afs_dirent) - 1;
347
        *fpos &= ~(sizeof(union afs_dirent) - 1);
348
 
349
        /* walk through the blocks in sequence */
350
        ret = 0;
351
        while (*fpos < dir->i_size) {
352
                blkoff = *fpos & ~(sizeof(union afs_dir_block) - 1);
353
 
354
                /* fetch the appropriate page from the directory */
355
                page = afs_dir_get_page(dir, blkoff / PAGE_SIZE, key);
356
                if (IS_ERR(page)) {
357
                        ret = PTR_ERR(page);
358
                        break;
359
                }
360
 
361
                limit = blkoff & ~(PAGE_SIZE - 1);
362
 
363
                dbuf = page_address(page);
364
 
365
                /* deal with the individual blocks stashed on this page */
366
                do {
367
                        dblock = &dbuf->blocks[(blkoff % PAGE_SIZE) /
368
                                               sizeof(union afs_dir_block)];
369
                        ret = afs_dir_iterate_block(fpos, dblock, blkoff,
370
                                                    cookie, filldir);
371
                        if (ret != 1) {
372
                                afs_dir_put_page(page);
373
                                goto out;
374
                        }
375
 
376
                        blkoff += sizeof(union afs_dir_block);
377
 
378
                } while (*fpos < dir->i_size && blkoff < limit);
379
 
380
                afs_dir_put_page(page);
381
                ret = 0;
382
        }
383
 
384
out:
385
        _leave(" = %d", ret);
386
        return ret;
387
}
388
 
389
/*
390
 * read an AFS directory
391
 */
392
static int afs_readdir(struct file *file, void *cookie, filldir_t filldir)
393
{
394
        unsigned fpos;
395
        int ret;
396
 
397
        _enter("{%Ld,{%lu}}",
398
               file->f_pos, file->f_path.dentry->d_inode->i_ino);
399
 
400
        ASSERT(file->private_data != NULL);
401
 
402
        fpos = file->f_pos;
403
        ret = afs_dir_iterate(file->f_path.dentry->d_inode, &fpos,
404
                              cookie, filldir, file->private_data);
405
        file->f_pos = fpos;
406
 
407
        _leave(" = %d", ret);
408
        return ret;
409
}
410
 
411
/*
412
 * search the directory for a name
413
 * - if afs_dir_iterate_block() spots this function, it'll pass the FID
414
 *   uniquifier through dtype
415
 */
416
static int afs_lookup_filldir(void *_cookie, const char *name, int nlen,
417
                              loff_t fpos, u64 ino, unsigned dtype)
418
{
419
        struct afs_lookup_cookie *cookie = _cookie;
420
 
421
        _enter("{%s,%Zu},%s,%u,,%llu,%u",
422
               cookie->name, cookie->nlen, name, nlen,
423
               (unsigned long long) ino, dtype);
424
 
425
        /* insanity checks first */
426
        BUILD_BUG_ON(sizeof(union afs_dir_block) != 2048);
427
        BUILD_BUG_ON(sizeof(union afs_dirent) != 32);
428
 
429
        if (cookie->nlen != nlen || memcmp(cookie->name, name, nlen) != 0) {
430
                _leave(" = 0 [no]");
431
                return 0;
432
        }
433
 
434
        cookie->fid.vnode = ino;
435
        cookie->fid.unique = dtype;
436
        cookie->found = 1;
437
 
438
        _leave(" = -1 [found]");
439
        return -1;
440
}
441
 
442
/*
443
 * do a lookup in a directory
444
 * - just returns the FID the dentry name maps to if found
445
 */
446
static int afs_do_lookup(struct inode *dir, struct dentry *dentry,
447
                         struct afs_fid *fid, struct key *key)
448
{
449
        struct afs_lookup_cookie cookie;
450
        struct afs_super_info *as;
451
        unsigned fpos;
452
        int ret;
453
 
454
        _enter("{%lu},%p{%s},", dir->i_ino, dentry, dentry->d_name.name);
455
 
456
        as = dir->i_sb->s_fs_info;
457
 
458
        /* search the directory */
459
        cookie.name     = dentry->d_name.name;
460
        cookie.nlen     = dentry->d_name.len;
461
        cookie.fid.vid  = as->volume->vid;
462
        cookie.found    = 0;
463
 
464
        fpos = 0;
465
        ret = afs_dir_iterate(dir, &fpos, &cookie, afs_lookup_filldir,
466
                              key);
467
        if (ret < 0) {
468
                _leave(" = %d [iter]", ret);
469
                return ret;
470
        }
471
 
472
        ret = -ENOENT;
473
        if (!cookie.found) {
474
                _leave(" = -ENOENT [not found]");
475
                return -ENOENT;
476
        }
477
 
478
        *fid = cookie.fid;
479
        _leave(" = 0 { vn=%u u=%u }", fid->vnode, fid->unique);
480
        return 0;
481
}
482
 
483
/*
484
 * look up an entry in a directory
485
 */
486
static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
487
                                 struct nameidata *nd)
488
{
489
        struct afs_vnode *vnode;
490
        struct afs_fid fid;
491
        struct inode *inode;
492
        struct key *key;
493
        int ret;
494
 
495
        vnode = AFS_FS_I(dir);
496
 
497
        _enter("{%x:%u},%p{%s},",
498
               vnode->fid.vid, vnode->fid.vnode, dentry, dentry->d_name.name);
499
 
500
        ASSERTCMP(dentry->d_inode, ==, NULL);
501
 
502
        if (dentry->d_name.len >= AFSNAMEMAX) {
503
                _leave(" = -ENAMETOOLONG");
504
                return ERR_PTR(-ENAMETOOLONG);
505
        }
506
 
507
        if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) {
508
                _leave(" = -ESTALE");
509
                return ERR_PTR(-ESTALE);
510
        }
511
 
512
        key = afs_request_key(vnode->volume->cell);
513
        if (IS_ERR(key)) {
514
                _leave(" = %ld [key]", PTR_ERR(key));
515
                return ERR_PTR(PTR_ERR(key));
516
        }
517
 
518
        ret = afs_validate(vnode, key);
519
        if (ret < 0) {
520
                key_put(key);
521
                _leave(" = %d [val]", ret);
522
                return ERR_PTR(ret);
523
        }
524
 
525
        ret = afs_do_lookup(dir, dentry, &fid, key);
526
        if (ret < 0) {
527
                key_put(key);
528
                if (ret == -ENOENT) {
529
                        d_add(dentry, NULL);
530
                        _leave(" = NULL [negative]");
531
                        return NULL;
532
                }
533
                _leave(" = %d [do]", ret);
534
                return ERR_PTR(ret);
535
        }
536
        dentry->d_fsdata = (void *)(unsigned long) vnode->status.data_version;
537
 
538
        /* instantiate the dentry */
539
        inode = afs_iget(dir->i_sb, key, &fid, NULL, NULL);
540
        key_put(key);
541
        if (IS_ERR(inode)) {
542
                _leave(" = %ld", PTR_ERR(inode));
543
                return ERR_PTR(PTR_ERR(inode));
544
        }
545
 
546
        dentry->d_op = &afs_fs_dentry_operations;
547
 
548
        d_add(dentry, inode);
549
        _leave(" = 0 { vn=%u u=%u } -> { ino=%lu v=%lu }",
550
               fid.vnode,
551
               fid.unique,
552
               dentry->d_inode->i_ino,
553
               dentry->d_inode->i_version);
554
 
555
        return NULL;
556
}
557
 
558
/*
559
 * check that a dentry lookup hit has found a valid entry
560
 * - NOTE! the hit can be a negative hit too, so we can't assume we have an
561
 *   inode
562
 */
563
static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
564
{
565
        struct afs_vnode *vnode, *dir;
566
        struct afs_fid fid;
567
        struct dentry *parent;
568
        struct key *key;
569
        void *dir_version;
570
        int ret;
571
 
572
        vnode = AFS_FS_I(dentry->d_inode);
573
 
574
        if (dentry->d_inode)
575
                _enter("{v={%x:%u} n=%s fl=%lx},",
576
                       vnode->fid.vid, vnode->fid.vnode, dentry->d_name.name,
577
                       vnode->flags);
578
        else
579
                _enter("{neg n=%s}", dentry->d_name.name);
580
 
581
        key = afs_request_key(AFS_FS_S(dentry->d_sb)->volume->cell);
582
        if (IS_ERR(key))
583
                key = NULL;
584
 
585
        /* lock down the parent dentry so we can peer at it */
586
        parent = dget_parent(dentry);
587
        if (!parent->d_inode)
588
                goto out_bad;
589
 
590
        dir = AFS_FS_I(parent->d_inode);
591
 
592
        /* validate the parent directory */
593
        if (test_bit(AFS_VNODE_MODIFIED, &dir->flags))
594
                afs_validate(dir, key);
595
 
596
        if (test_bit(AFS_VNODE_DELETED, &dir->flags)) {
597
                _debug("%s: parent dir deleted", dentry->d_name.name);
598
                goto out_bad;
599
        }
600
 
601
        dir_version = (void *) (unsigned long) dir->status.data_version;
602
        if (dentry->d_fsdata == dir_version)
603
                goto out_valid; /* the dir contents are unchanged */
604
 
605
        _debug("dir modified");
606
 
607
        /* search the directory for this vnode */
608
        ret = afs_do_lookup(&dir->vfs_inode, dentry, &fid, key);
609
        switch (ret) {
610
        case 0:
611
                /* the filename maps to something */
612
                if (!dentry->d_inode)
613
                        goto out_bad;
614
                if (is_bad_inode(dentry->d_inode)) {
615
                        printk("kAFS: afs_d_revalidate: %s/%s has bad inode\n",
616
                               parent->d_name.name, dentry->d_name.name);
617
                        goto out_bad;
618
                }
619
 
620
                /* if the vnode ID has changed, then the dirent points to a
621
                 * different file */
622
                if (fid.vnode != vnode->fid.vnode) {
623
                        _debug("%s: dirent changed [%u != %u]",
624
                               dentry->d_name.name, fid.vnode,
625
                               vnode->fid.vnode);
626
                        goto not_found;
627
                }
628
 
629
                /* if the vnode ID uniqifier has changed, then the file has
630
                 * been deleted and replaced, and the original vnode ID has
631
                 * been reused */
632
                if (fid.unique != vnode->fid.unique) {
633
                        _debug("%s: file deleted (uq %u -> %u I:%lu)",
634
                               dentry->d_name.name, fid.unique,
635
                               vnode->fid.unique, dentry->d_inode->i_version);
636
                        spin_lock(&vnode->lock);
637
                        set_bit(AFS_VNODE_DELETED, &vnode->flags);
638
                        spin_unlock(&vnode->lock);
639
                        goto not_found;
640
                }
641
                goto out_valid;
642
 
643
        case -ENOENT:
644
                /* the filename is unknown */
645
                _debug("%s: dirent not found", dentry->d_name.name);
646
                if (dentry->d_inode)
647
                        goto not_found;
648
                goto out_valid;
649
 
650
        default:
651
                _debug("failed to iterate dir %s: %d",
652
                       parent->d_name.name, ret);
653
                goto out_bad;
654
        }
655
 
656
out_valid:
657
        dentry->d_fsdata = dir_version;
658
out_skip:
659
        dput(parent);
660
        key_put(key);
661
        _leave(" = 1 [valid]");
662
        return 1;
663
 
664
        /* the dirent, if it exists, now points to a different vnode */
665
not_found:
666
        spin_lock(&dentry->d_lock);
667
        dentry->d_flags |= DCACHE_NFSFS_RENAMED;
668
        spin_unlock(&dentry->d_lock);
669
 
670
out_bad:
671
        if (dentry->d_inode) {
672
                /* don't unhash if we have submounts */
673
                if (have_submounts(dentry))
674
                        goto out_skip;
675
        }
676
 
677
        _debug("dropping dentry %s/%s",
678
               parent->d_name.name, dentry->d_name.name);
679
        shrink_dcache_parent(dentry);
680
        d_drop(dentry);
681
        dput(parent);
682
        key_put(key);
683
 
684
        _leave(" = 0 [bad]");
685
        return 0;
686
}
687
 
688
/*
689
 * allow the VFS to enquire as to whether a dentry should be unhashed (mustn't
690
 * sleep)
691
 * - called from dput() when d_count is going to 0.
692
 * - return 1 to request dentry be unhashed, 0 otherwise
693
 */
694
static int afs_d_delete(struct dentry *dentry)
695
{
696
        _enter("%s", dentry->d_name.name);
697
 
698
        if (dentry->d_flags & DCACHE_NFSFS_RENAMED)
699
                goto zap;
700
 
701
        if (dentry->d_inode &&
702
            test_bit(AFS_VNODE_DELETED, &AFS_FS_I(dentry->d_inode)->flags))
703
                        goto zap;
704
 
705
        _leave(" = 0 [keep]");
706
        return 0;
707
 
708
zap:
709
        _leave(" = 1 [zap]");
710
        return 1;
711
}
712
 
713
/*
714
 * handle dentry release
715
 */
716
static void afs_d_release(struct dentry *dentry)
717
{
718
        _enter("%s", dentry->d_name.name);
719
}
720
 
721
/*
722
 * create a directory on an AFS filesystem
723
 */
724
static int afs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
725
{
726
        struct afs_file_status status;
727
        struct afs_callback cb;
728
        struct afs_server *server;
729
        struct afs_vnode *dvnode, *vnode;
730
        struct afs_fid fid;
731
        struct inode *inode;
732
        struct key *key;
733
        int ret;
734
 
735
        dvnode = AFS_FS_I(dir);
736
 
737
        _enter("{%x:%u},{%s},%o",
738
               dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name, mode);
739
 
740
        ret = -ENAMETOOLONG;
741
        if (dentry->d_name.len >= AFSNAMEMAX)
742
                goto error;
743
 
744
        key = afs_request_key(dvnode->volume->cell);
745
        if (IS_ERR(key)) {
746
                ret = PTR_ERR(key);
747
                goto error;
748
        }
749
 
750
        mode |= S_IFDIR;
751
        ret = afs_vnode_create(dvnode, key, dentry->d_name.name,
752
                               mode, &fid, &status, &cb, &server);
753
        if (ret < 0)
754
                goto mkdir_error;
755
 
756
        inode = afs_iget(dir->i_sb, key, &fid, &status, &cb);
757
        if (IS_ERR(inode)) {
758
                /* ENOMEM at a really inconvenient time - just abandon the new
759
                 * directory on the server */
760
                ret = PTR_ERR(inode);
761
                goto iget_error;
762
        }
763
 
764
        /* apply the status report we've got for the new vnode */
765
        vnode = AFS_FS_I(inode);
766
        spin_lock(&vnode->lock);
767
        vnode->update_cnt++;
768
        spin_unlock(&vnode->lock);
769
        afs_vnode_finalise_status_update(vnode, server);
770
        afs_put_server(server);
771
 
772
        d_instantiate(dentry, inode);
773
        if (d_unhashed(dentry)) {
774
                _debug("not hashed");
775
                d_rehash(dentry);
776
        }
777
        key_put(key);
778
        _leave(" = 0");
779
        return 0;
780
 
781
iget_error:
782
        afs_put_server(server);
783
mkdir_error:
784
        key_put(key);
785
error:
786
        d_drop(dentry);
787
        _leave(" = %d", ret);
788
        return ret;
789
}
790
 
791
/*
792
 * remove a directory from an AFS filesystem
793
 */
794
static int afs_rmdir(struct inode *dir, struct dentry *dentry)
795
{
796
        struct afs_vnode *dvnode, *vnode;
797
        struct key *key;
798
        int ret;
799
 
800
        dvnode = AFS_FS_I(dir);
801
 
802
        _enter("{%x:%u},{%s}",
803
               dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name);
804
 
805
        ret = -ENAMETOOLONG;
806
        if (dentry->d_name.len >= AFSNAMEMAX)
807
                goto error;
808
 
809
        key = afs_request_key(dvnode->volume->cell);
810
        if (IS_ERR(key)) {
811
                ret = PTR_ERR(key);
812
                goto error;
813
        }
814
 
815
        ret = afs_vnode_remove(dvnode, key, dentry->d_name.name, true);
816
        if (ret < 0)
817
                goto rmdir_error;
818
 
819
        if (dentry->d_inode) {
820
                vnode = AFS_FS_I(dentry->d_inode);
821
                clear_nlink(&vnode->vfs_inode);
822
                set_bit(AFS_VNODE_DELETED, &vnode->flags);
823
                afs_discard_callback_on_delete(vnode);
824
        }
825
 
826
        key_put(key);
827
        _leave(" = 0");
828
        return 0;
829
 
830
rmdir_error:
831
        key_put(key);
832
error:
833
        _leave(" = %d", ret);
834
        return ret;
835
}
836
 
837
/*
838
 * remove a file from an AFS filesystem
839
 */
840
static int afs_unlink(struct inode *dir, struct dentry *dentry)
841
{
842
        struct afs_vnode *dvnode, *vnode;
843
        struct key *key;
844
        int ret;
845
 
846
        dvnode = AFS_FS_I(dir);
847
 
848
        _enter("{%x:%u},{%s}",
849
               dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name);
850
 
851
        ret = -ENAMETOOLONG;
852
        if (dentry->d_name.len >= AFSNAMEMAX)
853
                goto error;
854
 
855
        key = afs_request_key(dvnode->volume->cell);
856
        if (IS_ERR(key)) {
857
                ret = PTR_ERR(key);
858
                goto error;
859
        }
860
 
861
        if (dentry->d_inode) {
862
                vnode = AFS_FS_I(dentry->d_inode);
863
 
864
                /* make sure we have a callback promise on the victim */
865
                ret = afs_validate(vnode, key);
866
                if (ret < 0)
867
                        goto error;
868
        }
869
 
870
        ret = afs_vnode_remove(dvnode, key, dentry->d_name.name, false);
871
        if (ret < 0)
872
                goto remove_error;
873
 
874
        if (dentry->d_inode) {
875
                /* if the file wasn't deleted due to excess hard links, the
876
                 * fileserver will break the callback promise on the file - if
877
                 * it had one - before it returns to us, and if it was deleted,
878
                 * it won't
879
                 *
880
                 * however, if we didn't have a callback promise outstanding,
881
                 * or it was outstanding on a different server, then it won't
882
                 * break it either...
883
                 */
884
                vnode = AFS_FS_I(dentry->d_inode);
885
                if (test_bit(AFS_VNODE_DELETED, &vnode->flags))
886
                        _debug("AFS_VNODE_DELETED");
887
                if (test_bit(AFS_VNODE_CB_BROKEN, &vnode->flags))
888
                        _debug("AFS_VNODE_CB_BROKEN");
889
                set_bit(AFS_VNODE_CB_BROKEN, &vnode->flags);
890
                ret = afs_validate(vnode, key);
891
                _debug("nlink %d [val %d]", vnode->vfs_inode.i_nlink, ret);
892
        }
893
 
894
        key_put(key);
895
        _leave(" = 0");
896
        return 0;
897
 
898
remove_error:
899
        key_put(key);
900
error:
901
        _leave(" = %d", ret);
902
        return ret;
903
}
904
 
905
/*
906
 * create a regular file on an AFS filesystem
907
 */
908
static int afs_create(struct inode *dir, struct dentry *dentry, int mode,
909
                      struct nameidata *nd)
910
{
911
        struct afs_file_status status;
912
        struct afs_callback cb;
913
        struct afs_server *server;
914
        struct afs_vnode *dvnode, *vnode;
915
        struct afs_fid fid;
916
        struct inode *inode;
917
        struct key *key;
918
        int ret;
919
 
920
        dvnode = AFS_FS_I(dir);
921
 
922
        _enter("{%x:%u},{%s},%o,",
923
               dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name, mode);
924
 
925
        ret = -ENAMETOOLONG;
926
        if (dentry->d_name.len >= AFSNAMEMAX)
927
                goto error;
928
 
929
        key = afs_request_key(dvnode->volume->cell);
930
        if (IS_ERR(key)) {
931
                ret = PTR_ERR(key);
932
                goto error;
933
        }
934
 
935
        mode |= S_IFREG;
936
        ret = afs_vnode_create(dvnode, key, dentry->d_name.name,
937
                               mode, &fid, &status, &cb, &server);
938
        if (ret < 0)
939
                goto create_error;
940
 
941
        inode = afs_iget(dir->i_sb, key, &fid, &status, &cb);
942
        if (IS_ERR(inode)) {
943
                /* ENOMEM at a really inconvenient time - just abandon the new
944
                 * directory on the server */
945
                ret = PTR_ERR(inode);
946
                goto iget_error;
947
        }
948
 
949
        /* apply the status report we've got for the new vnode */
950
        vnode = AFS_FS_I(inode);
951
        spin_lock(&vnode->lock);
952
        vnode->update_cnt++;
953
        spin_unlock(&vnode->lock);
954
        afs_vnode_finalise_status_update(vnode, server);
955
        afs_put_server(server);
956
 
957
        d_instantiate(dentry, inode);
958
        if (d_unhashed(dentry)) {
959
                _debug("not hashed");
960
                d_rehash(dentry);
961
        }
962
        key_put(key);
963
        _leave(" = 0");
964
        return 0;
965
 
966
iget_error:
967
        afs_put_server(server);
968
create_error:
969
        key_put(key);
970
error:
971
        d_drop(dentry);
972
        _leave(" = %d", ret);
973
        return ret;
974
}
975
 
976
/*
977
 * create a hard link between files in an AFS filesystem
978
 */
979
static int afs_link(struct dentry *from, struct inode *dir,
980
                    struct dentry *dentry)
981
{
982
        struct afs_vnode *dvnode, *vnode;
983
        struct key *key;
984
        int ret;
985
 
986
        vnode = AFS_FS_I(from->d_inode);
987
        dvnode = AFS_FS_I(dir);
988
 
989
        _enter("{%x:%u},{%x:%u},{%s}",
990
               vnode->fid.vid, vnode->fid.vnode,
991
               dvnode->fid.vid, dvnode->fid.vnode,
992
               dentry->d_name.name);
993
 
994
        ret = -ENAMETOOLONG;
995
        if (dentry->d_name.len >= AFSNAMEMAX)
996
                goto error;
997
 
998
        key = afs_request_key(dvnode->volume->cell);
999
        if (IS_ERR(key)) {
1000
                ret = PTR_ERR(key);
1001
                goto error;
1002
        }
1003
 
1004
        ret = afs_vnode_link(dvnode, vnode, key, dentry->d_name.name);
1005
        if (ret < 0)
1006
                goto link_error;
1007
 
1008
        atomic_inc(&vnode->vfs_inode.i_count);
1009
        d_instantiate(dentry, &vnode->vfs_inode);
1010
        key_put(key);
1011
        _leave(" = 0");
1012
        return 0;
1013
 
1014
link_error:
1015
        key_put(key);
1016
error:
1017
        d_drop(dentry);
1018
        _leave(" = %d", ret);
1019
        return ret;
1020
}
1021
 
1022
/*
1023
 * create a symlink in an AFS filesystem
1024
 */
1025
static int afs_symlink(struct inode *dir, struct dentry *dentry,
1026
                       const char *content)
1027
{
1028
        struct afs_file_status status;
1029
        struct afs_server *server;
1030
        struct afs_vnode *dvnode, *vnode;
1031
        struct afs_fid fid;
1032
        struct inode *inode;
1033
        struct key *key;
1034
        int ret;
1035
 
1036
        dvnode = AFS_FS_I(dir);
1037
 
1038
        _enter("{%x:%u},{%s},%s",
1039
               dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name,
1040
               content);
1041
 
1042
        ret = -ENAMETOOLONG;
1043
        if (dentry->d_name.len >= AFSNAMEMAX)
1044
                goto error;
1045
 
1046
        ret = -EINVAL;
1047
        if (strlen(content) >= AFSPATHMAX)
1048
                goto error;
1049
 
1050
        key = afs_request_key(dvnode->volume->cell);
1051
        if (IS_ERR(key)) {
1052
                ret = PTR_ERR(key);
1053
                goto error;
1054
        }
1055
 
1056
        ret = afs_vnode_symlink(dvnode, key, dentry->d_name.name, content,
1057
                                &fid, &status, &server);
1058
        if (ret < 0)
1059
                goto create_error;
1060
 
1061
        inode = afs_iget(dir->i_sb, key, &fid, &status, NULL);
1062
        if (IS_ERR(inode)) {
1063
                /* ENOMEM at a really inconvenient time - just abandon the new
1064
                 * directory on the server */
1065
                ret = PTR_ERR(inode);
1066
                goto iget_error;
1067
        }
1068
 
1069
        /* apply the status report we've got for the new vnode */
1070
        vnode = AFS_FS_I(inode);
1071
        spin_lock(&vnode->lock);
1072
        vnode->update_cnt++;
1073
        spin_unlock(&vnode->lock);
1074
        afs_vnode_finalise_status_update(vnode, server);
1075
        afs_put_server(server);
1076
 
1077
        d_instantiate(dentry, inode);
1078
        if (d_unhashed(dentry)) {
1079
                _debug("not hashed");
1080
                d_rehash(dentry);
1081
        }
1082
        key_put(key);
1083
        _leave(" = 0");
1084
        return 0;
1085
 
1086
iget_error:
1087
        afs_put_server(server);
1088
create_error:
1089
        key_put(key);
1090
error:
1091
        d_drop(dentry);
1092
        _leave(" = %d", ret);
1093
        return ret;
1094
}
1095
 
1096
/*
1097
 * rename a file in an AFS filesystem and/or move it between directories
1098
 */
1099
static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
1100
                      struct inode *new_dir, struct dentry *new_dentry)
1101
{
1102
        struct afs_vnode *orig_dvnode, *new_dvnode, *vnode;
1103
        struct key *key;
1104
        int ret;
1105
 
1106
        vnode = AFS_FS_I(old_dentry->d_inode);
1107
        orig_dvnode = AFS_FS_I(old_dir);
1108
        new_dvnode = AFS_FS_I(new_dir);
1109
 
1110
        _enter("{%x:%u},{%x:%u},{%x:%u},{%s}",
1111
               orig_dvnode->fid.vid, orig_dvnode->fid.vnode,
1112
               vnode->fid.vid, vnode->fid.vnode,
1113
               new_dvnode->fid.vid, new_dvnode->fid.vnode,
1114
               new_dentry->d_name.name);
1115
 
1116
        ret = -ENAMETOOLONG;
1117
        if (new_dentry->d_name.len >= AFSNAMEMAX)
1118
                goto error;
1119
 
1120
        key = afs_request_key(orig_dvnode->volume->cell);
1121
        if (IS_ERR(key)) {
1122
                ret = PTR_ERR(key);
1123
                goto error;
1124
        }
1125
 
1126
        ret = afs_vnode_rename(orig_dvnode, new_dvnode, key,
1127
                               old_dentry->d_name.name,
1128
                               new_dentry->d_name.name);
1129
        if (ret < 0)
1130
                goto rename_error;
1131
        key_put(key);
1132
        _leave(" = 0");
1133
        return 0;
1134
 
1135
rename_error:
1136
        key_put(key);
1137
error:
1138
        d_drop(new_dentry);
1139
        _leave(" = %d", ret);
1140
        return ret;
1141
}

powered by: WebSVN 2.1.0

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