linux/fs/smbfs/dir.c
<<
>>
Prefs
   1/*
   2 *  dir.c
   3 *
   4 *  Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke
   5 *  Copyright (C) 1997 by Volker Lendecke
   6 *
   7 *  Please add a note about your changes to smbfs in the ChangeLog file.
   8 */
   9
  10#include <linux/time.h>
  11#include <linux/errno.h>
  12#include <linux/kernel.h>
  13#include <linux/smp_lock.h>
  14#include <linux/ctype.h>
  15#include <linux/net.h>
  16#include <linux/sched.h>
  17
  18#include <linux/smb_fs.h>
  19#include <linux/smb_mount.h>
  20#include <linux/smbno.h>
  21
  22#include "smb_debug.h"
  23#include "proto.h"
  24
  25static int smb_readdir(struct file *, void *, filldir_t);
  26static int smb_dir_open(struct inode *, struct file *);
  27
  28static struct dentry *smb_lookup(struct inode *, struct dentry *, struct nameidata *);
  29static int smb_create(struct inode *, struct dentry *, int, struct nameidata *);
  30static int smb_mkdir(struct inode *, struct dentry *, int);
  31static int smb_rmdir(struct inode *, struct dentry *);
  32static int smb_unlink(struct inode *, struct dentry *);
  33static int smb_rename(struct inode *, struct dentry *,
  34                      struct inode *, struct dentry *);
  35static int smb_make_node(struct inode *,struct dentry *,int,dev_t);
  36static int smb_link(struct dentry *, struct inode *, struct dentry *);
  37
  38const struct file_operations smb_dir_operations =
  39{
  40        .read           = generic_read_dir,
  41        .readdir        = smb_readdir,
  42        .ioctl          = smb_ioctl,
  43        .open           = smb_dir_open,
  44};
  45
  46const struct inode_operations smb_dir_inode_operations =
  47{
  48        .create         = smb_create,
  49        .lookup         = smb_lookup,
  50        .unlink         = smb_unlink,
  51        .mkdir          = smb_mkdir,
  52        .rmdir          = smb_rmdir,
  53        .rename         = smb_rename,
  54        .getattr        = smb_getattr,
  55        .setattr        = smb_notify_change,
  56};
  57
  58const struct inode_operations smb_dir_inode_operations_unix =
  59{
  60        .create         = smb_create,
  61        .lookup         = smb_lookup,
  62        .unlink         = smb_unlink,
  63        .mkdir          = smb_mkdir,
  64        .rmdir          = smb_rmdir,
  65        .rename         = smb_rename,
  66        .getattr        = smb_getattr,
  67        .setattr        = smb_notify_change,
  68        .symlink        = smb_symlink,
  69        .mknod          = smb_make_node,
  70        .link           = smb_link,
  71};
  72
  73/*
  74 * Read a directory, using filldir to fill the dirent memory.
  75 * smb_proc_readdir does the actual reading from the smb server.
  76 *
  77 * The cache code is almost directly taken from ncpfs
  78 */
  79static int 
  80smb_readdir(struct file *filp, void *dirent, filldir_t filldir)
  81{
  82        struct dentry *dentry = filp->f_path.dentry;
  83        struct inode *dir = dentry->d_inode;
  84        struct smb_sb_info *server = server_from_dentry(dentry);
  85        union  smb_dir_cache *cache = NULL;
  86        struct smb_cache_control ctl;
  87        struct page *page = NULL;
  88        int result;
  89
  90        ctl.page  = NULL;
  91        ctl.cache = NULL;
  92
  93        VERBOSE("reading %s/%s, f_pos=%d\n",
  94                DENTRY_PATH(dentry),  (int) filp->f_pos);
  95
  96        result = 0;
  97
  98        lock_kernel();
  99
 100        switch ((unsigned int) filp->f_pos) {
 101        case 0:
 102                if (filldir(dirent, ".", 1, 0, dir->i_ino, DT_DIR) < 0)
 103                        goto out;
 104                filp->f_pos = 1;
 105                /* fallthrough */
 106        case 1:
 107                if (filldir(dirent, "..", 2, 1, parent_ino(dentry), DT_DIR) < 0)
 108                        goto out;
 109                filp->f_pos = 2;
 110        }
 111
 112        /*
 113         * Make sure our inode is up-to-date.
 114         */
 115        result = smb_revalidate_inode(dentry);
 116        if (result)
 117                goto out;
 118
 119
 120        page = grab_cache_page(&dir->i_data, 0);
 121        if (!page)
 122                goto read_really;
 123
 124        ctl.cache = cache = kmap(page);
 125        ctl.head  = cache->head;
 126
 127        if (!PageUptodate(page) || !ctl.head.eof) {
 128                VERBOSE("%s/%s, page uptodate=%d, eof=%d\n",
 129                         DENTRY_PATH(dentry), PageUptodate(page),ctl.head.eof);
 130                goto init_cache;
 131        }
 132
 133        if (filp->f_pos == 2) {
 134                if (jiffies - ctl.head.time >= SMB_MAX_AGE(server))
 135                        goto init_cache;
 136
 137                /*
 138                 * N.B. ncpfs checks mtime of dentry too here, we don't.
 139                 *   1. common smb servers do not update mtime on dir changes
 140                 *   2. it requires an extra smb request
 141                 *      (revalidate has the same timeout as ctl.head.time)
 142                 *
 143                 * Instead smbfs invalidates its own cache on local changes
 144                 * and remote changes are not seen until timeout.
 145                 */
 146        }
 147
 148        if (filp->f_pos > ctl.head.end)
 149                goto finished;
 150
 151        ctl.fpos = filp->f_pos + (SMB_DIRCACHE_START - 2);
 152        ctl.ofs  = ctl.fpos / SMB_DIRCACHE_SIZE;
 153        ctl.idx  = ctl.fpos % SMB_DIRCACHE_SIZE;
 154
 155        for (;;) {
 156                if (ctl.ofs != 0) {
 157                        ctl.page = find_lock_page(&dir->i_data, ctl.ofs);
 158                        if (!ctl.page)
 159                                goto invalid_cache;
 160                        ctl.cache = kmap(ctl.page);
 161                        if (!PageUptodate(ctl.page))
 162                                goto invalid_cache;
 163                }
 164                while (ctl.idx < SMB_DIRCACHE_SIZE) {
 165                        struct dentry *dent;
 166                        int res;
 167
 168                        dent = smb_dget_fpos(ctl.cache->dentry[ctl.idx],
 169                                             dentry, filp->f_pos);
 170                        if (!dent)
 171                                goto invalid_cache;
 172
 173                        res = filldir(dirent, dent->d_name.name,
 174                                      dent->d_name.len, filp->f_pos,
 175                                      dent->d_inode->i_ino, DT_UNKNOWN);
 176                        dput(dent);
 177                        if (res)
 178                                goto finished;
 179                        filp->f_pos += 1;
 180                        ctl.idx += 1;
 181                        if (filp->f_pos > ctl.head.end)
 182                                goto finished;
 183                }
 184                if (ctl.page) {
 185                        kunmap(ctl.page);
 186                        SetPageUptodate(ctl.page);
 187                        unlock_page(ctl.page);
 188                        page_cache_release(ctl.page);
 189                        ctl.page = NULL;
 190                }
 191                ctl.idx  = 0;
 192                ctl.ofs += 1;
 193        }
 194invalid_cache:
 195        if (ctl.page) {
 196                kunmap(ctl.page);
 197                unlock_page(ctl.page);
 198                page_cache_release(ctl.page);
 199                ctl.page = NULL;
 200        }
 201        ctl.cache = cache;
 202init_cache:
 203        smb_invalidate_dircache_entries(dentry);
 204        ctl.head.time = jiffies;
 205        ctl.head.eof = 0;
 206        ctl.fpos = 2;
 207        ctl.ofs = 0;
 208        ctl.idx = SMB_DIRCACHE_START;
 209        ctl.filled = 0;
 210        ctl.valid  = 1;
 211read_really:
 212        result = server->ops->readdir(filp, dirent, filldir, &ctl);
 213        if (result == -ERESTARTSYS && page)
 214                ClearPageUptodate(page);
 215        if (ctl.idx == -1)
 216                goto invalid_cache;     /* retry */
 217        ctl.head.end = ctl.fpos - 1;
 218        ctl.head.eof = ctl.valid;
 219finished:
 220        if (page) {
 221                cache->head = ctl.head;
 222                kunmap(page);
 223                if (result != -ERESTARTSYS)
 224                        SetPageUptodate(page);
 225                unlock_page(page);
 226                page_cache_release(page);
 227        }
 228        if (ctl.page) {
 229                kunmap(ctl.page);
 230                SetPageUptodate(ctl.page);
 231                unlock_page(ctl.page);
 232                page_cache_release(ctl.page);
 233        }
 234out:
 235        unlock_kernel();
 236        return result;
 237}
 238
 239static int
 240smb_dir_open(struct inode *dir, struct file *file)
 241{
 242        struct dentry *dentry = file->f_path.dentry;
 243        struct smb_sb_info *server;
 244        int error = 0;
 245
 246        VERBOSE("(%s/%s)\n", dentry->d_parent->d_name.name,
 247                file->f_path.dentry->d_name.name);
 248
 249        /*
 250         * Directory timestamps in the core protocol aren't updated
 251         * when a file is added, so we give them a very short TTL.
 252         */
 253        lock_kernel();
 254        server = server_from_dentry(dentry);
 255        if (server->opt.protocol < SMB_PROTOCOL_LANMAN2) {
 256                unsigned long age = jiffies - SMB_I(dir)->oldmtime;
 257                if (age > 2*HZ)
 258                        smb_invalid_dir_cache(dir);
 259        }
 260
 261        /*
 262         * Note: in order to allow the smbmount process to open the
 263         * mount point, we only revalidate if the connection is valid or
 264         * if the process is trying to access something other than the root.
 265         */
 266        if (server->state == CONN_VALID || !IS_ROOT(dentry))
 267                error = smb_revalidate_inode(dentry);
 268        unlock_kernel();
 269        return error;
 270}
 271
 272/*
 273 * Dentry operations routines
 274 */
 275static int smb_lookup_validate(struct dentry *, struct nameidata *);
 276static int smb_hash_dentry(struct dentry *, struct qstr *);
 277static int smb_compare_dentry(struct dentry *, struct qstr *, struct qstr *);
 278static int smb_delete_dentry(struct dentry *);
 279
 280static const struct dentry_operations smbfs_dentry_operations =
 281{
 282        .d_revalidate   = smb_lookup_validate,
 283        .d_hash         = smb_hash_dentry,
 284        .d_compare      = smb_compare_dentry,
 285        .d_delete       = smb_delete_dentry,
 286};
 287
 288static const struct dentry_operations smbfs_dentry_operations_case =
 289{
 290        .d_revalidate   = smb_lookup_validate,
 291        .d_delete       = smb_delete_dentry,
 292};
 293
 294
 295/*
 296 * This is the callback when the dcache has a lookup hit.
 297 */
 298static int
 299smb_lookup_validate(struct dentry * dentry, struct nameidata *nd)
 300{
 301        struct smb_sb_info *server = server_from_dentry(dentry);
 302        struct inode * inode = dentry->d_inode;
 303        unsigned long age = jiffies - dentry->d_time;
 304        int valid;
 305
 306        /*
 307         * The default validation is based on dentry age:
 308         * we believe in dentries for a few seconds.  (But each
 309         * successful server lookup renews the timestamp.)
 310         */
 311        valid = (age <= SMB_MAX_AGE(server));
 312#ifdef SMBFS_DEBUG_VERBOSE
 313        if (!valid)
 314                VERBOSE("%s/%s not valid, age=%lu\n", 
 315                        DENTRY_PATH(dentry), age);
 316#endif
 317
 318        if (inode) {
 319                lock_kernel();
 320                if (is_bad_inode(inode)) {
 321                        PARANOIA("%s/%s has dud inode\n", DENTRY_PATH(dentry));
 322                        valid = 0;
 323                } else if (!valid)
 324                        valid = (smb_revalidate_inode(dentry) == 0);
 325                unlock_kernel();
 326        } else {
 327                /*
 328                 * What should we do for negative dentries?
 329                 */
 330        }
 331        return valid;
 332}
 333
 334static int 
 335smb_hash_dentry(struct dentry *dir, struct qstr *this)
 336{
 337        unsigned long hash;
 338        int i;
 339
 340        hash = init_name_hash();
 341        for (i=0; i < this->len ; i++)
 342                hash = partial_name_hash(tolower(this->name[i]), hash);
 343        this->hash = end_name_hash(hash);
 344  
 345        return 0;
 346}
 347
 348static int
 349smb_compare_dentry(struct dentry *dir, struct qstr *a, struct qstr *b)
 350{
 351        int i, result = 1;
 352
 353        if (a->len != b->len)
 354                goto out;
 355        for (i=0; i < a->len; i++) {
 356                if (tolower(a->name[i]) != tolower(b->name[i]))
 357                        goto out;
 358        }
 359        result = 0;
 360out:
 361        return result;
 362}
 363
 364/*
 365 * This is the callback from dput() when d_count is going to 0.
 366 * We use this to unhash dentries with bad inodes.
 367 */
 368static int
 369smb_delete_dentry(struct dentry * dentry)
 370{
 371        if (dentry->d_inode) {
 372                if (is_bad_inode(dentry->d_inode)) {
 373                        PARANOIA("bad inode, unhashing %s/%s\n",
 374                                 DENTRY_PATH(dentry));
 375                        return 1;
 376                }
 377        } else {
 378                /* N.B. Unhash negative dentries? */
 379        }
 380        return 0;
 381}
 382
 383/*
 384 * Initialize a new dentry
 385 */
 386void
 387smb_new_dentry(struct dentry *dentry)
 388{
 389        struct smb_sb_info *server = server_from_dentry(dentry);
 390
 391        if (server->mnt->flags & SMB_MOUNT_CASE)
 392                dentry->d_op = &smbfs_dentry_operations_case;
 393        else
 394                dentry->d_op = &smbfs_dentry_operations;
 395        dentry->d_time = jiffies;
 396}
 397
 398
 399/*
 400 * Whenever a lookup succeeds, we know the parent directories
 401 * are all valid, so we want to update the dentry timestamps.
 402 * N.B. Move this to dcache?
 403 */
 404void
 405smb_renew_times(struct dentry * dentry)
 406{
 407        dget(dentry);
 408        spin_lock(&dentry->d_lock);
 409        for (;;) {
 410                struct dentry *parent;
 411
 412                dentry->d_time = jiffies;
 413                if (IS_ROOT(dentry))
 414                        break;
 415                parent = dentry->d_parent;
 416                dget(parent);
 417                spin_unlock(&dentry->d_lock);
 418                dput(dentry);
 419                dentry = parent;
 420                spin_lock(&dentry->d_lock);
 421        }
 422        spin_unlock(&dentry->d_lock);
 423        dput(dentry);
 424}
 425
 426static struct dentry *
 427smb_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 428{
 429        struct smb_fattr finfo;
 430        struct inode *inode;
 431        int error;
 432        struct smb_sb_info *server;
 433
 434        error = -ENAMETOOLONG;
 435        if (dentry->d_name.len > SMB_MAXNAMELEN)
 436                goto out;
 437
 438        /* Do not allow lookup of names with backslashes in */
 439        error = -EINVAL;
 440        if (memchr(dentry->d_name.name, '\\', dentry->d_name.len))
 441                goto out;
 442
 443        lock_kernel();
 444        error = smb_proc_getattr(dentry, &finfo);
 445#ifdef SMBFS_PARANOIA
 446        if (error && error != -ENOENT)
 447                PARANOIA("find %s/%s failed, error=%d\n",
 448                         DENTRY_PATH(dentry), error);
 449#endif
 450
 451        inode = NULL;
 452        if (error == -ENOENT)
 453                goto add_entry;
 454        if (!error) {
 455                error = -EACCES;
 456                finfo.f_ino = iunique(dentry->d_sb, 2);
 457                inode = smb_iget(dir->i_sb, &finfo);
 458                if (inode) {
 459        add_entry:
 460                        server = server_from_dentry(dentry);
 461                        if (server->mnt->flags & SMB_MOUNT_CASE)
 462                                dentry->d_op = &smbfs_dentry_operations_case;
 463                        else
 464                                dentry->d_op = &smbfs_dentry_operations;
 465
 466                        d_add(dentry, inode);
 467                        smb_renew_times(dentry);
 468                        error = 0;
 469                }
 470        }
 471        unlock_kernel();
 472out:
 473        return ERR_PTR(error);
 474}
 475
 476/*
 477 * This code is common to all routines creating a new inode.
 478 */
 479static int
 480smb_instantiate(struct dentry *dentry, __u16 fileid, int have_id)
 481{
 482        struct smb_sb_info *server = server_from_dentry(dentry);
 483        struct inode *inode;
 484        int error;
 485        struct smb_fattr fattr;
 486
 487        VERBOSE("file %s/%s, fileid=%u\n", DENTRY_PATH(dentry), fileid);
 488
 489        error = smb_proc_getattr(dentry, &fattr);
 490        if (error)
 491                goto out_close;
 492
 493        smb_renew_times(dentry);
 494        fattr.f_ino = iunique(dentry->d_sb, 2);
 495        inode = smb_iget(dentry->d_sb, &fattr);
 496        if (!inode)
 497                goto out_no_inode;
 498
 499        if (have_id) {
 500                struct smb_inode_info *ei = SMB_I(inode);
 501                ei->fileid = fileid;
 502                ei->access = SMB_O_RDWR;
 503                ei->open = server->generation;
 504        }
 505        d_instantiate(dentry, inode);
 506out:
 507        return error;
 508
 509out_no_inode:
 510        error = -EACCES;
 511out_close:
 512        if (have_id) {
 513                PARANOIA("%s/%s failed, error=%d, closing %u\n",
 514                         DENTRY_PATH(dentry), error, fileid);
 515                smb_close_fileid(dentry, fileid);
 516        }
 517        goto out;
 518}
 519
 520/* N.B. How should the mode argument be used? */
 521static int
 522smb_create(struct inode *dir, struct dentry *dentry, int mode,
 523                struct nameidata *nd)
 524{
 525        struct smb_sb_info *server = server_from_dentry(dentry);
 526        __u16 fileid;
 527        int error;
 528        struct iattr attr;
 529
 530        VERBOSE("creating %s/%s, mode=%d\n", DENTRY_PATH(dentry), mode);
 531
 532        lock_kernel();
 533        smb_invalid_dir_cache(dir);
 534        error = smb_proc_create(dentry, 0, get_seconds(), &fileid);
 535        if (!error) {
 536                if (server->opt.capabilities & SMB_CAP_UNIX) {
 537                        /* Set attributes for new file */
 538                        attr.ia_valid = ATTR_MODE;
 539                        attr.ia_mode = mode;
 540                        error = smb_proc_setattr_unix(dentry, &attr, 0, 0);
 541                }
 542                error = smb_instantiate(dentry, fileid, 1);
 543        } else {
 544                PARANOIA("%s/%s failed, error=%d\n",
 545                         DENTRY_PATH(dentry), error);
 546        }
 547        unlock_kernel();
 548        return error;
 549}
 550
 551/* N.B. How should the mode argument be used? */
 552static int
 553smb_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 554{
 555        struct smb_sb_info *server = server_from_dentry(dentry);
 556        int error;
 557        struct iattr attr;
 558
 559        lock_kernel();
 560        smb_invalid_dir_cache(dir);
 561        error = smb_proc_mkdir(dentry);
 562        if (!error) {
 563                if (server->opt.capabilities & SMB_CAP_UNIX) {
 564                        /* Set attributes for new directory */
 565                        attr.ia_valid = ATTR_MODE;
 566                        attr.ia_mode = mode;
 567                        error = smb_proc_setattr_unix(dentry, &attr, 0, 0);
 568                }
 569                error = smb_instantiate(dentry, 0, 0);
 570        }
 571        unlock_kernel();
 572        return error;
 573}
 574
 575static int
 576smb_rmdir(struct inode *dir, struct dentry *dentry)
 577{
 578        struct inode *inode = dentry->d_inode;
 579        int error;
 580
 581        /*
 582         * Close the directory if it's open.
 583         */
 584        lock_kernel();
 585        smb_close(inode);
 586
 587        /*
 588         * Check that nobody else is using the directory..
 589         */
 590        error = -EBUSY;
 591        if (!d_unhashed(dentry))
 592                goto out;
 593
 594        smb_invalid_dir_cache(dir);
 595        error = smb_proc_rmdir(dentry);
 596
 597out:
 598        unlock_kernel();
 599        return error;
 600}
 601
 602static int
 603smb_unlink(struct inode *dir, struct dentry *dentry)
 604{
 605        int error;
 606
 607        /*
 608         * Close the file if it's open.
 609         */
 610        lock_kernel();
 611        smb_close(dentry->d_inode);
 612
 613        smb_invalid_dir_cache(dir);
 614        error = smb_proc_unlink(dentry);
 615        if (!error)
 616                smb_renew_times(dentry);
 617        unlock_kernel();
 618        return error;
 619}
 620
 621static int
 622smb_rename(struct inode *old_dir, struct dentry *old_dentry,
 623           struct inode *new_dir, struct dentry *new_dentry)
 624{
 625        int error;
 626
 627        /*
 628         * Close any open files, and check whether to delete the
 629         * target before attempting the rename.
 630         */
 631        lock_kernel();
 632        if (old_dentry->d_inode)
 633                smb_close(old_dentry->d_inode);
 634        if (new_dentry->d_inode) {
 635                smb_close(new_dentry->d_inode);
 636                error = smb_proc_unlink(new_dentry);
 637                if (error) {
 638                        VERBOSE("unlink %s/%s, error=%d\n",
 639                                DENTRY_PATH(new_dentry), error);
 640                        goto out;
 641                }
 642                /* FIXME */
 643                d_delete(new_dentry);
 644        }
 645
 646        smb_invalid_dir_cache(old_dir);
 647        smb_invalid_dir_cache(new_dir);
 648        error = smb_proc_mv(old_dentry, new_dentry);
 649        if (!error) {
 650                smb_renew_times(old_dentry);
 651                smb_renew_times(new_dentry);
 652        }
 653out:
 654        unlock_kernel();
 655        return error;
 656}
 657
 658/*
 659 * FIXME: samba servers won't let you create device nodes unless uid/gid
 660 * matches the connection credentials (and we don't know which those are ...)
 661 */
 662static int
 663smb_make_node(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
 664{
 665        int error;
 666        struct iattr attr;
 667
 668        attr.ia_valid = ATTR_MODE | ATTR_UID | ATTR_GID;
 669        attr.ia_mode = mode;
 670        current_euid_egid(&attr.ia_uid, &attr.ia_gid);
 671
 672        if (!new_valid_dev(dev))
 673                return -EINVAL;
 674
 675        smb_invalid_dir_cache(dir);
 676        error = smb_proc_setattr_unix(dentry, &attr, MAJOR(dev), MINOR(dev));
 677        if (!error) {
 678                error = smb_instantiate(dentry, 0, 0);
 679        }
 680        return error;
 681}
 682
 683/*
 684 * dentry = existing file
 685 * new_dentry = new file
 686 */
 687static int
 688smb_link(struct dentry *dentry, struct inode *dir, struct dentry *new_dentry)
 689{
 690        int error;
 691
 692        DEBUG1("smb_link old=%s/%s new=%s/%s\n",
 693               DENTRY_PATH(dentry), DENTRY_PATH(new_dentry));
 694        smb_invalid_dir_cache(dir);
 695        error = smb_proc_link(server_from_dentry(dentry), dentry, new_dentry);
 696        if (!error) {
 697                smb_renew_times(dentry);
 698                error = smb_instantiate(new_dentry, 0, 0);
 699        }
 700        return error;
 701}
 702