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, struct dir_context *ctx);
  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(struct dir_context *ctx, 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                      unsigned int flags);
  43
  44const struct file_operations afs_dir_file_operations = {
  45        .open           = afs_dir_open,
  46        .release        = afs_release,
  47        .iterate_shared = afs_readdir,
  48        .lock           = afs_lock,
  49        .llseek         = generic_file_llseek,
  50};
  51
  52const struct inode_operations afs_dir_inode_operations = {
  53        .create         = afs_create,
  54        .lookup         = afs_lookup,
  55        .link           = afs_link,
  56        .unlink         = afs_unlink,
  57        .symlink        = afs_symlink,
  58        .mkdir          = afs_mkdir,
  59        .rmdir          = afs_rmdir,
  60        .rename         = afs_rename,
  61        .permission     = afs_permission,
  62        .getattr        = afs_getattr,
  63        .setattr        = afs_setattr,
  64        .listxattr      = afs_listxattr,
  65};
  66
  67const struct dentry_operations afs_fs_dentry_operations = {
  68        .d_revalidate   = afs_d_revalidate,
  69        .d_delete       = afs_d_delete,
  70        .d_release      = afs_d_release,
  71        .d_automount    = afs_d_automount,
  72};
  73
  74#define AFS_DIR_HASHTBL_SIZE    128
  75#define AFS_DIR_DIRENT_SIZE     32
  76#define AFS_DIRENT_PER_BLOCK    64
  77
  78union afs_dirent {
  79        struct {
  80                uint8_t         valid;
  81                uint8_t         unused[1];
  82                __be16          hash_next;
  83                __be32          vnode;
  84                __be32          unique;
  85                uint8_t         name[16];
  86                uint8_t         overflow[4];    /* if any char of the name (inc
  87                                                 * NUL) reaches here, consume
  88                                                 * the next dirent too */
  89        } u;
  90        uint8_t extended_name[32];
  91};
  92
  93/* AFS directory page header (one at the beginning of every 2048-byte chunk) */
  94struct afs_dir_pagehdr {
  95        __be16          npages;
  96        __be16          magic;
  97#define AFS_DIR_MAGIC htons(1234)
  98        uint8_t         nentries;
  99        uint8_t         bitmap[8];
 100        uint8_t         pad[19];
 101};
 102
 103/* directory block layout */
 104union afs_dir_block {
 105
 106        struct afs_dir_pagehdr pagehdr;
 107
 108        struct {
 109                struct afs_dir_pagehdr  pagehdr;
 110                uint8_t                 alloc_ctrs[128];
 111                /* dir hash table */
 112                uint16_t                hashtable[AFS_DIR_HASHTBL_SIZE];
 113        } hdr;
 114
 115        union afs_dirent dirents[AFS_DIRENT_PER_BLOCK];
 116};
 117
 118/* layout on a linux VM page */
 119struct afs_dir_page {
 120        union afs_dir_block blocks[PAGE_SIZE / sizeof(union afs_dir_block)];
 121};
 122
 123struct afs_lookup_cookie {
 124        struct dir_context ctx;
 125        struct afs_fid  fid;
 126        struct qstr name;
 127        int             found;
 128};
 129
 130/*
 131 * check that a directory page is valid
 132 */
 133static inline bool afs_dir_check_page(struct inode *dir, struct page *page)
 134{
 135        struct afs_dir_page *dbuf;
 136        loff_t latter;
 137        int tmp, qty;
 138
 139#if 0
 140        /* check the page count */
 141        qty = desc.size / sizeof(dbuf->blocks[0]);
 142        if (qty == 0)
 143                goto error;
 144
 145        if (page->index == 0 && qty != ntohs(dbuf->blocks[0].pagehdr.npages)) {
 146                printk("kAFS: %s(%lu): wrong number of dir blocks %d!=%hu\n",
 147                       __func__, dir->i_ino, qty,
 148                       ntohs(dbuf->blocks[0].pagehdr.npages));
 149                goto error;
 150        }
 151#endif
 152
 153        /* determine how many magic numbers there should be in this page */
 154        latter = dir->i_size - page_offset(page);
 155        if (latter >= PAGE_SIZE)
 156                qty = PAGE_SIZE;
 157        else
 158                qty = latter;
 159        qty /= sizeof(union afs_dir_block);
 160
 161        /* check them */
 162        dbuf = page_address(page);
 163        for (tmp = 0; tmp < qty; tmp++) {
 164                if (dbuf->blocks[tmp].pagehdr.magic != AFS_DIR_MAGIC) {
 165                        printk("kAFS: %s(%lu): bad magic %d/%d is %04hx\n",
 166                               __func__, dir->i_ino, tmp, qty,
 167                               ntohs(dbuf->blocks[tmp].pagehdr.magic));
 168                        goto error;
 169                }
 170        }
 171
 172        SetPageChecked(page);
 173        return true;
 174
 175error:
 176        SetPageError(page);
 177        return false;
 178}
 179
 180/*
 181 * discard a page cached in the pagecache
 182 */
 183static inline void afs_dir_put_page(struct page *page)
 184{
 185        kunmap(page);
 186        put_page(page);
 187}
 188
 189/*
 190 * get a page into the pagecache
 191 */
 192static struct page *afs_dir_get_page(struct inode *dir, unsigned long index,
 193                                     struct key *key)
 194{
 195        struct page *page;
 196        _enter("{%lu},%lu", dir->i_ino, index);
 197
 198        page = read_cache_page(dir->i_mapping, index, afs_page_filler, key);
 199        if (!IS_ERR(page)) {
 200                kmap(page);
 201                if (unlikely(!PageChecked(page))) {
 202                        if (PageError(page) || !afs_dir_check_page(dir, page))
 203                                goto fail;
 204                }
 205        }
 206        return page;
 207
 208fail:
 209        afs_dir_put_page(page);
 210        _leave(" = -EIO");
 211        return ERR_PTR(-EIO);
 212}
 213
 214/*
 215 * open an AFS directory file
 216 */
 217static 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 */
 233static int afs_dir_iterate_block(struct dir_context *ctx,
 234                                 union afs_dir_block *block,
 235                                 unsigned blkoff)
 236{
 237        union afs_dirent *dire;
 238        unsigned offset, next, curr;
 239        size_t nlen;
 240        int tmp;
 241
 242        _enter("%u,%x,%p,,",(unsigned)ctx->pos,blkoff,block);
 243
 244        curr = (ctx->pos - 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                                ctx->pos = 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                if (!dir_emit(ctx, dire->u.name, nlen,
 306                              ntohl(dire->u.vnode),
 307                              ctx->actor == afs_lookup_filldir ?
 308                              ntohl(dire->u.unique) : DT_UNKNOWN)) {
 309                        _leave(" = 0 [full]");
 310                        return 0;
 311                }
 312
 313                ctx->pos = blkoff + next * sizeof(union afs_dirent);
 314        }
 315
 316        _leave(" = 1 [more]");
 317        return 1;
 318}
 319
 320/*
 321 * iterate through the data blob that lists the contents of an AFS directory
 322 */
 323static int afs_dir_iterate(struct inode *dir, struct dir_context *ctx,
 324                           struct key *key)
 325{
 326        union afs_dir_block *dblock;
 327        struct afs_dir_page *dbuf;
 328        struct page *page;
 329        unsigned blkoff, limit;
 330        int ret;
 331
 332        _enter("{%lu},%u,,", dir->i_ino, (unsigned)ctx->pos);
 333
 334        if (test_bit(AFS_VNODE_DELETED, &AFS_FS_I(dir)->flags)) {
 335                _leave(" = -ESTALE");
 336                return -ESTALE;
 337        }
 338
 339        /* round the file position up to the next entry boundary */
 340        ctx->pos += sizeof(union afs_dirent) - 1;
 341        ctx->pos &= ~(sizeof(union afs_dirent) - 1);
 342
 343        /* walk through the blocks in sequence */
 344        ret = 0;
 345        while (ctx->pos < dir->i_size) {
 346                blkoff = ctx->pos & ~(sizeof(union afs_dir_block) - 1);
 347
 348                /* fetch the appropriate page from the directory */
 349                page = afs_dir_get_page(dir, blkoff / PAGE_SIZE, key);
 350                if (IS_ERR(page)) {
 351                        ret = PTR_ERR(page);
 352                        break;
 353                }
 354
 355                limit = blkoff & ~(PAGE_SIZE - 1);
 356
 357                dbuf = page_address(page);
 358
 359                /* deal with the individual blocks stashed on this page */
 360                do {
 361                        dblock = &dbuf->blocks[(blkoff % PAGE_SIZE) /
 362                                               sizeof(union afs_dir_block)];
 363                        ret = afs_dir_iterate_block(ctx, dblock, blkoff);
 364                        if (ret != 1) {
 365                                afs_dir_put_page(page);
 366                                goto out;
 367                        }
 368
 369                        blkoff += sizeof(union afs_dir_block);
 370
 371                } while (ctx->pos < dir->i_size && blkoff < limit);
 372
 373                afs_dir_put_page(page);
 374                ret = 0;
 375        }
 376
 377out:
 378        _leave(" = %d", ret);
 379        return ret;
 380}
 381
 382/*
 383 * read an AFS directory
 384 */
 385static int afs_readdir(struct file *file, struct dir_context *ctx)
 386{
 387        return afs_dir_iterate(file_inode(file), 
 388                              ctx, file->private_data);
 389}
 390
 391/*
 392 * search the directory for a name
 393 * - if afs_dir_iterate_block() spots this function, it'll pass the FID
 394 *   uniquifier through dtype
 395 */
 396static int afs_lookup_filldir(struct dir_context *ctx, const char *name,
 397                              int nlen, loff_t fpos, u64 ino, unsigned dtype)
 398{
 399        struct afs_lookup_cookie *cookie =
 400                container_of(ctx, struct afs_lookup_cookie, ctx);
 401
 402        _enter("{%s,%u},%s,%u,,%llu,%u",
 403               cookie->name.name, cookie->name.len, name, nlen,
 404               (unsigned long long) ino, dtype);
 405
 406        /* insanity checks first */
 407        BUILD_BUG_ON(sizeof(union afs_dir_block) != 2048);
 408        BUILD_BUG_ON(sizeof(union afs_dirent) != 32);
 409
 410        if (cookie->name.len != nlen ||
 411            memcmp(cookie->name.name, name, nlen) != 0) {
 412                _leave(" = 0 [no]");
 413                return 0;
 414        }
 415
 416        cookie->fid.vnode = ino;
 417        cookie->fid.unique = dtype;
 418        cookie->found = 1;
 419
 420        _leave(" = -1 [found]");
 421        return -1;
 422}
 423
 424/*
 425 * do a lookup in a directory
 426 * - just returns the FID the dentry name maps to if found
 427 */
 428static int afs_do_lookup(struct inode *dir, struct dentry *dentry,
 429                         struct afs_fid *fid, struct key *key)
 430{
 431        struct afs_super_info *as = dir->i_sb->s_fs_info;
 432        struct afs_lookup_cookie cookie = {
 433                .ctx.actor = afs_lookup_filldir,
 434                .name = dentry->d_name,
 435                .fid.vid = as->volume->vid
 436        };
 437        int ret;
 438
 439        _enter("{%lu},%p{%pd},", dir->i_ino, dentry, dentry);
 440
 441        /* search the directory */
 442        ret = afs_dir_iterate(dir, &cookie.ctx, key);
 443        if (ret < 0) {
 444                _leave(" = %d [iter]", ret);
 445                return ret;
 446        }
 447
 448        ret = -ENOENT;
 449        if (!cookie.found) {
 450                _leave(" = -ENOENT [not found]");
 451                return -ENOENT;
 452        }
 453
 454        *fid = cookie.fid;
 455        _leave(" = 0 { vn=%u u=%u }", fid->vnode, fid->unique);
 456        return 0;
 457}
 458
 459/*
 460 * Try to auto mount the mountpoint with pseudo directory, if the autocell
 461 * operation is setted.
 462 */
 463static struct inode *afs_try_auto_mntpt(
 464        int ret, struct dentry *dentry, struct inode *dir, struct key *key,
 465        struct afs_fid *fid)
 466{
 467        const char *devname = dentry->d_name.name;
 468        struct afs_vnode *vnode = AFS_FS_I(dir);
 469        struct inode *inode;
 470
 471        _enter("%d, %p{%pd}, {%x:%u}, %p",
 472               ret, dentry, dentry, vnode->fid.vid, vnode->fid.vnode, key);
 473
 474        if (ret != -ENOENT ||
 475            !test_bit(AFS_VNODE_AUTOCELL, &vnode->flags))
 476                goto out;
 477
 478        inode = afs_iget_autocell(dir, devname, strlen(devname), key);
 479        if (IS_ERR(inode)) {
 480                ret = PTR_ERR(inode);
 481                goto out;
 482        }
 483
 484        *fid = AFS_FS_I(inode)->fid;
 485        _leave("= %p", inode);
 486        return inode;
 487
 488out:
 489        _leave("= %d", ret);
 490        return ERR_PTR(ret);
 491}
 492
 493/*
 494 * look up an entry in a directory
 495 */
 496static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
 497                                 unsigned int flags)
 498{
 499        struct afs_vnode *vnode;
 500        struct afs_fid fid;
 501        struct inode *inode;
 502        struct key *key;
 503        int ret;
 504
 505        vnode = AFS_FS_I(dir);
 506
 507        _enter("{%x:%u},%p{%pd},",
 508               vnode->fid.vid, vnode->fid.vnode, dentry, dentry);
 509
 510        ASSERTCMP(d_inode(dentry), ==, NULL);
 511
 512        if (dentry->d_name.len >= AFSNAMEMAX) {
 513                _leave(" = -ENAMETOOLONG");
 514                return ERR_PTR(-ENAMETOOLONG);
 515        }
 516
 517        if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) {
 518                _leave(" = -ESTALE");
 519                return ERR_PTR(-ESTALE);
 520        }
 521
 522        key = afs_request_key(vnode->volume->cell);
 523        if (IS_ERR(key)) {
 524                _leave(" = %ld [key]", PTR_ERR(key));
 525                return ERR_CAST(key);
 526        }
 527
 528        ret = afs_validate(vnode, key);
 529        if (ret < 0) {
 530                key_put(key);
 531                _leave(" = %d [val]", ret);
 532                return ERR_PTR(ret);
 533        }
 534
 535        ret = afs_do_lookup(dir, dentry, &fid, key);
 536        if (ret < 0) {
 537                inode = afs_try_auto_mntpt(ret, dentry, dir, key, &fid);
 538                if (!IS_ERR(inode)) {
 539                        key_put(key);
 540                        goto success;
 541                }
 542
 543                ret = PTR_ERR(inode);
 544                key_put(key);
 545                if (ret == -ENOENT) {
 546                        d_add(dentry, NULL);
 547                        _leave(" = NULL [negative]");
 548                        return NULL;
 549                }
 550                _leave(" = %d [do]", ret);
 551                return ERR_PTR(ret);
 552        }
 553        dentry->d_fsdata = (void *)(unsigned long) vnode->status.data_version;
 554
 555        /* instantiate the dentry */
 556        inode = afs_iget(dir->i_sb, key, &fid, NULL, NULL);
 557        key_put(key);
 558        if (IS_ERR(inode)) {
 559                _leave(" = %ld", PTR_ERR(inode));
 560                return ERR_CAST(inode);
 561        }
 562
 563success:
 564        d_add(dentry, inode);
 565        _leave(" = 0 { vn=%u u=%u } -> { ino=%lu v=%u }",
 566               fid.vnode,
 567               fid.unique,
 568               d_inode(dentry)->i_ino,
 569               d_inode(dentry)->i_generation);
 570
 571        return NULL;
 572}
 573
 574/*
 575 * check that a dentry lookup hit has found a valid entry
 576 * - NOTE! the hit can be a negative hit too, so we can't assume we have an
 577 *   inode
 578 */
 579static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
 580{
 581        struct afs_vnode *vnode, *dir;
 582        struct afs_fid uninitialized_var(fid);
 583        struct dentry *parent;
 584        struct key *key;
 585        void *dir_version;
 586        int ret;
 587
 588        if (flags & LOOKUP_RCU)
 589                return -ECHILD;
 590
 591        vnode = AFS_FS_I(d_inode(dentry));
 592
 593        if (d_really_is_positive(dentry))
 594                _enter("{v={%x:%u} n=%pd fl=%lx},",
 595                       vnode->fid.vid, vnode->fid.vnode, dentry,
 596                       vnode->flags);
 597        else
 598                _enter("{neg n=%pd}", dentry);
 599
 600        key = afs_request_key(AFS_FS_S(dentry->d_sb)->volume->cell);
 601        if (IS_ERR(key))
 602                key = NULL;
 603
 604        /* lock down the parent dentry so we can peer at it */
 605        parent = dget_parent(dentry);
 606        dir = AFS_FS_I(d_inode(parent));
 607
 608        /* validate the parent directory */
 609        if (test_bit(AFS_VNODE_MODIFIED, &dir->flags))
 610                afs_validate(dir, key);
 611
 612        if (test_bit(AFS_VNODE_DELETED, &dir->flags)) {
 613                _debug("%pd: parent dir deleted", dentry);
 614                goto out_bad;
 615        }
 616
 617        dir_version = (void *) (unsigned long) dir->status.data_version;
 618        if (dentry->d_fsdata == dir_version)
 619                goto out_valid; /* the dir contents are unchanged */
 620
 621        _debug("dir modified");
 622
 623        /* search the directory for this vnode */
 624        ret = afs_do_lookup(&dir->vfs_inode, dentry, &fid, key);
 625        switch (ret) {
 626        case 0:
 627                /* the filename maps to something */
 628                if (d_really_is_negative(dentry))
 629                        goto out_bad;
 630                if (is_bad_inode(d_inode(dentry))) {
 631                        printk("kAFS: afs_d_revalidate: %pd2 has bad inode\n",
 632                               dentry);
 633                        goto out_bad;
 634                }
 635
 636                /* if the vnode ID has changed, then the dirent points to a
 637                 * different file */
 638                if (fid.vnode != vnode->fid.vnode) {
 639                        _debug("%pd: dirent changed [%u != %u]",
 640                               dentry, fid.vnode,
 641                               vnode->fid.vnode);
 642                        goto not_found;
 643                }
 644
 645                /* if the vnode ID uniqifier has changed, then the file has
 646                 * been deleted and replaced, and the original vnode ID has
 647                 * been reused */
 648                if (fid.unique != vnode->fid.unique) {
 649                        _debug("%pd: file deleted (uq %u -> %u I:%u)",
 650                               dentry, fid.unique,
 651                               vnode->fid.unique,
 652                               d_inode(dentry)->i_generation);
 653                        spin_lock(&vnode->lock);
 654                        set_bit(AFS_VNODE_DELETED, &vnode->flags);
 655                        spin_unlock(&vnode->lock);
 656                        goto not_found;
 657                }
 658                goto out_valid;
 659
 660        case -ENOENT:
 661                /* the filename is unknown */
 662                _debug("%pd: dirent not found", dentry);
 663                if (d_really_is_positive(dentry))
 664                        goto not_found;
 665                goto out_valid;
 666
 667        default:
 668                _debug("failed to iterate dir %pd: %d",
 669                       parent, ret);
 670                goto out_bad;
 671        }
 672
 673out_valid:
 674        dentry->d_fsdata = dir_version;
 675        dput(parent);
 676        key_put(key);
 677        _leave(" = 1 [valid]");
 678        return 1;
 679
 680        /* the dirent, if it exists, now points to a different vnode */
 681not_found:
 682        spin_lock(&dentry->d_lock);
 683        dentry->d_flags |= DCACHE_NFSFS_RENAMED;
 684        spin_unlock(&dentry->d_lock);
 685
 686out_bad:
 687        _debug("dropping dentry %pd2", dentry);
 688        dput(parent);
 689        key_put(key);
 690
 691        _leave(" = 0 [bad]");
 692        return 0;
 693}
 694
 695/*
 696 * allow the VFS to enquire as to whether a dentry should be unhashed (mustn't
 697 * sleep)
 698 * - called from dput() when d_count is going to 0.
 699 * - return 1 to request dentry be unhashed, 0 otherwise
 700 */
 701static int afs_d_delete(const struct dentry *dentry)
 702{
 703        _enter("%pd", dentry);
 704
 705        if (dentry->d_flags & DCACHE_NFSFS_RENAMED)
 706                goto zap;
 707
 708        if (d_really_is_positive(dentry) &&
 709            (test_bit(AFS_VNODE_DELETED,   &AFS_FS_I(d_inode(dentry))->flags) ||
 710             test_bit(AFS_VNODE_PSEUDODIR, &AFS_FS_I(d_inode(dentry))->flags)))
 711                goto zap;
 712
 713        _leave(" = 0 [keep]");
 714        return 0;
 715
 716zap:
 717        _leave(" = 1 [zap]");
 718        return 1;
 719}
 720
 721/*
 722 * handle dentry release
 723 */
 724static void afs_d_release(struct dentry *dentry)
 725{
 726        _enter("%pd", dentry);
 727}
 728
 729/*
 730 * create a directory on an AFS filesystem
 731 */
 732static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 733{
 734        struct afs_file_status status;
 735        struct afs_callback cb;
 736        struct afs_server *server;
 737        struct afs_vnode *dvnode, *vnode;
 738        struct afs_fid fid;
 739        struct inode *inode;
 740        struct key *key;
 741        int ret;
 742
 743        dvnode = AFS_FS_I(dir);
 744
 745        _enter("{%x:%u},{%pd},%ho",
 746               dvnode->fid.vid, dvnode->fid.vnode, dentry, mode);
 747
 748        key = afs_request_key(dvnode->volume->cell);
 749        if (IS_ERR(key)) {
 750                ret = PTR_ERR(key);
 751                goto error;
 752        }
 753
 754        mode |= S_IFDIR;
 755        ret = afs_vnode_create(dvnode, key, dentry->d_name.name,
 756                               mode, &fid, &status, &cb, &server);
 757        if (ret < 0)
 758                goto mkdir_error;
 759
 760        inode = afs_iget(dir->i_sb, key, &fid, &status, &cb);
 761        if (IS_ERR(inode)) {
 762                /* ENOMEM at a really inconvenient time - just abandon the new
 763                 * directory on the server */
 764                ret = PTR_ERR(inode);
 765                goto iget_error;
 766        }
 767
 768        /* apply the status report we've got for the new vnode */
 769        vnode = AFS_FS_I(inode);
 770        spin_lock(&vnode->lock);
 771        vnode->update_cnt++;
 772        spin_unlock(&vnode->lock);
 773        afs_vnode_finalise_status_update(vnode, server);
 774        afs_put_server(server);
 775
 776        d_instantiate(dentry, inode);
 777        if (d_unhashed(dentry)) {
 778                _debug("not hashed");
 779                d_rehash(dentry);
 780        }
 781        key_put(key);
 782        _leave(" = 0");
 783        return 0;
 784
 785iget_error:
 786        afs_put_server(server);
 787mkdir_error:
 788        key_put(key);
 789error:
 790        d_drop(dentry);
 791        _leave(" = %d", ret);
 792        return ret;
 793}
 794
 795/*
 796 * remove a directory from an AFS filesystem
 797 */
 798static int afs_rmdir(struct inode *dir, struct dentry *dentry)
 799{
 800        struct afs_vnode *dvnode, *vnode;
 801        struct key *key;
 802        int ret;
 803
 804        dvnode = AFS_FS_I(dir);
 805
 806        _enter("{%x:%u},{%pd}",
 807               dvnode->fid.vid, dvnode->fid.vnode, dentry);
 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 (d_really_is_positive(dentry)) {
 820                vnode = AFS_FS_I(d_inode(dentry));
 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
 830rmdir_error:
 831        key_put(key);
 832error:
 833        _leave(" = %d", ret);
 834        return ret;
 835}
 836
 837/*
 838 * remove a file from an AFS filesystem
 839 */
 840static 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},{%pd}",
 849               dvnode->fid.vid, dvnode->fid.vnode, dentry);
 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 (d_really_is_positive(dentry)) {
 862                vnode = AFS_FS_I(d_inode(dentry));
 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 (d_really_is_positive(dentry)) {
 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(d_inode(dentry));
 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
 898remove_error:
 899        key_put(key);
 900error:
 901        _leave(" = %d", ret);
 902        return ret;
 903}
 904
 905/*
 906 * create a regular file on an AFS filesystem
 907 */
 908static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
 909                      bool excl)
 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},{%pd},%ho,",
 923               dvnode->fid.vid, dvnode->fid.vnode, dentry, mode);
 924
 925        key = afs_request_key(dvnode->volume->cell);
 926        if (IS_ERR(key)) {
 927                ret = PTR_ERR(key);
 928                goto error;
 929        }
 930
 931        mode |= S_IFREG;
 932        ret = afs_vnode_create(dvnode, key, dentry->d_name.name,
 933                               mode, &fid, &status, &cb, &server);
 934        if (ret < 0)
 935                goto create_error;
 936
 937        inode = afs_iget(dir->i_sb, key, &fid, &status, &cb);
 938        if (IS_ERR(inode)) {
 939                /* ENOMEM at a really inconvenient time - just abandon the new
 940                 * directory on the server */
 941                ret = PTR_ERR(inode);
 942                goto iget_error;
 943        }
 944
 945        /* apply the status report we've got for the new vnode */
 946        vnode = AFS_FS_I(inode);
 947        spin_lock(&vnode->lock);
 948        vnode->update_cnt++;
 949        spin_unlock(&vnode->lock);
 950        afs_vnode_finalise_status_update(vnode, server);
 951        afs_put_server(server);
 952
 953        d_instantiate(dentry, inode);
 954        if (d_unhashed(dentry)) {
 955                _debug("not hashed");
 956                d_rehash(dentry);
 957        }
 958        key_put(key);
 959        _leave(" = 0");
 960        return 0;
 961
 962iget_error:
 963        afs_put_server(server);
 964create_error:
 965        key_put(key);
 966error:
 967        d_drop(dentry);
 968        _leave(" = %d", ret);
 969        return ret;
 970}
 971
 972/*
 973 * create a hard link between files in an AFS filesystem
 974 */
 975static int afs_link(struct dentry *from, struct inode *dir,
 976                    struct dentry *dentry)
 977{
 978        struct afs_vnode *dvnode, *vnode;
 979        struct key *key;
 980        int ret;
 981
 982        vnode = AFS_FS_I(d_inode(from));
 983        dvnode = AFS_FS_I(dir);
 984
 985        _enter("{%x:%u},{%x:%u},{%pd}",
 986               vnode->fid.vid, vnode->fid.vnode,
 987               dvnode->fid.vid, dvnode->fid.vnode,
 988               dentry);
 989
 990        key = afs_request_key(dvnode->volume->cell);
 991        if (IS_ERR(key)) {
 992                ret = PTR_ERR(key);
 993                goto error;
 994        }
 995
 996        ret = afs_vnode_link(dvnode, vnode, key, dentry->d_name.name);
 997        if (ret < 0)
 998                goto link_error;
 999
1000        ihold(&vnode->vfs_inode);
1001        d_instantiate(dentry, &vnode->vfs_inode);
1002        key_put(key);
1003        _leave(" = 0");
1004        return 0;
1005
1006link_error:
1007        key_put(key);
1008error:
1009        d_drop(dentry);
1010        _leave(" = %d", ret);
1011        return ret;
1012}
1013
1014/*
1015 * create a symlink in an AFS filesystem
1016 */
1017static int afs_symlink(struct inode *dir, struct dentry *dentry,
1018                       const char *content)
1019{
1020        struct afs_file_status status;
1021        struct afs_server *server;
1022        struct afs_vnode *dvnode, *vnode;
1023        struct afs_fid fid;
1024        struct inode *inode;
1025        struct key *key;
1026        int ret;
1027
1028        dvnode = AFS_FS_I(dir);
1029
1030        _enter("{%x:%u},{%pd},%s",
1031               dvnode->fid.vid, dvnode->fid.vnode, dentry,
1032               content);
1033
1034        ret = -EINVAL;
1035        if (strlen(content) >= AFSPATHMAX)
1036                goto error;
1037
1038        key = afs_request_key(dvnode->volume->cell);
1039        if (IS_ERR(key)) {
1040                ret = PTR_ERR(key);
1041                goto error;
1042        }
1043
1044        ret = afs_vnode_symlink(dvnode, key, dentry->d_name.name, content,
1045                                &fid, &status, &server);
1046        if (ret < 0)
1047                goto create_error;
1048
1049        inode = afs_iget(dir->i_sb, key, &fid, &status, NULL);
1050        if (IS_ERR(inode)) {
1051                /* ENOMEM at a really inconvenient time - just abandon the new
1052                 * directory on the server */
1053                ret = PTR_ERR(inode);
1054                goto iget_error;
1055        }
1056
1057        /* apply the status report we've got for the new vnode */
1058        vnode = AFS_FS_I(inode);
1059        spin_lock(&vnode->lock);
1060        vnode->update_cnt++;
1061        spin_unlock(&vnode->lock);
1062        afs_vnode_finalise_status_update(vnode, server);
1063        afs_put_server(server);
1064
1065        d_instantiate(dentry, inode);
1066        if (d_unhashed(dentry)) {
1067                _debug("not hashed");
1068                d_rehash(dentry);
1069        }
1070        key_put(key);
1071        _leave(" = 0");
1072        return 0;
1073
1074iget_error:
1075        afs_put_server(server);
1076create_error:
1077        key_put(key);
1078error:
1079        d_drop(dentry);
1080        _leave(" = %d", ret);
1081        return ret;
1082}
1083
1084/*
1085 * rename a file in an AFS filesystem and/or move it between directories
1086 */
1087static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
1088                      struct inode *new_dir, struct dentry *new_dentry,
1089                      unsigned int flags)
1090{
1091        struct afs_vnode *orig_dvnode, *new_dvnode, *vnode;
1092        struct key *key;
1093        int ret;
1094
1095        if (flags)
1096                return -EINVAL;
1097
1098        vnode = AFS_FS_I(d_inode(old_dentry));
1099        orig_dvnode = AFS_FS_I(old_dir);
1100        new_dvnode = AFS_FS_I(new_dir);
1101
1102        _enter("{%x:%u},{%x:%u},{%x:%u},{%pd}",
1103               orig_dvnode->fid.vid, orig_dvnode->fid.vnode,
1104               vnode->fid.vid, vnode->fid.vnode,
1105               new_dvnode->fid.vid, new_dvnode->fid.vnode,
1106               new_dentry);
1107
1108        key = afs_request_key(orig_dvnode->volume->cell);
1109        if (IS_ERR(key)) {
1110                ret = PTR_ERR(key);
1111                goto error;
1112        }
1113
1114        ret = afs_vnode_rename(orig_dvnode, new_dvnode, key,
1115                               old_dentry->d_name.name,
1116                               new_dentry->d_name.name);
1117        if (ret < 0)
1118                goto rename_error;
1119        key_put(key);
1120        _leave(" = 0");
1121        return 0;
1122
1123rename_error:
1124        key_put(key);
1125error:
1126        d_drop(new_dentry);
1127        _leave(" = %d", ret);
1128        return ret;
1129}
1130