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