linux-bk/fs/autofs4/root.c
<<
>>
Prefs
   1/* -*- c -*- --------------------------------------------------------------- *
   2 *
   3 * linux/fs/autofs/root.c
   4 *
   5 *  Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
   6 *  Copyright 1999-2000 Jeremy Fitzhardinge <jeremy@goop.org>
   7 *  Copyright 2001-2003 Ian Kent <raven@themaw.net>
   8 *
   9 * This file is part of the Linux kernel and is made available under
  10 * the terms of the GNU General Public License, version 2, or at your
  11 * option, any later version, incorporated herein by reference.
  12 *
  13 * ------------------------------------------------------------------------- */
  14
  15#include <linux/errno.h>
  16#include <linux/stat.h>
  17#include <linux/param.h>
  18#include <linux/time.h>
  19#include <linux/smp_lock.h>
  20#include "autofs_i.h"
  21
  22static int autofs4_dir_symlink(struct inode *,struct dentry *,const char *);
  23static int autofs4_dir_unlink(struct inode *,struct dentry *);
  24static int autofs4_dir_rmdir(struct inode *,struct dentry *);
  25static int autofs4_dir_mkdir(struct inode *,struct dentry *,int);
  26static int autofs4_root_ioctl(struct inode *, struct file *,unsigned int,unsigned long);
  27static int autofs4_dir_open(struct inode *inode, struct file *file);
  28static int autofs4_dir_close(struct inode *inode, struct file *file);
  29static int autofs4_dir_readdir(struct file * filp, void * dirent, filldir_t filldir);
  30static int autofs4_root_readdir(struct file * filp, void * dirent, filldir_t filldir);
  31static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *);
  32static int autofs4_dcache_readdir(struct file *, void *, filldir_t);
  33
  34struct file_operations autofs4_root_operations = {
  35        .open           = dcache_dir_open,
  36        .release        = dcache_dir_close,
  37        .read           = generic_read_dir,
  38        .readdir        = autofs4_root_readdir,
  39        .ioctl          = autofs4_root_ioctl,
  40};
  41
  42struct file_operations autofs4_dir_operations = {
  43        .open           = autofs4_dir_open,
  44        .release        = autofs4_dir_close,
  45        .read           = generic_read_dir,
  46        .readdir        = autofs4_dir_readdir,
  47};
  48
  49struct inode_operations autofs4_root_inode_operations = {
  50        .lookup         = autofs4_lookup,
  51        .unlink         = autofs4_dir_unlink,
  52        .symlink        = autofs4_dir_symlink,
  53        .mkdir          = autofs4_dir_mkdir,
  54        .rmdir          = autofs4_dir_rmdir,
  55};
  56
  57struct inode_operations autofs4_dir_inode_operations = {
  58        .lookup         = autofs4_lookup,
  59        .unlink         = autofs4_dir_unlink,
  60        .symlink        = autofs4_dir_symlink,
  61        .mkdir          = autofs4_dir_mkdir,
  62        .rmdir          = autofs4_dir_rmdir,
  63};
  64
  65static int autofs4_root_readdir(struct file *file, void *dirent,
  66                                filldir_t filldir)
  67{
  68        struct autofs_sb_info *sbi = autofs4_sbi(file->f_dentry->d_sb);
  69        int oz_mode = autofs4_oz_mode(sbi);
  70
  71        DPRINTK("called, filp->f_pos = %lld", file->f_pos);
  72
  73        /*
  74         * Don't set reghost flag if:
  75         * 1) f_pos is larger than zero -- we've already been here.
  76         * 2) we haven't even enabled reghosting in the 1st place.
  77         * 3) this is the daemon doing a readdir
  78         */
  79        if (oz_mode && file->f_pos == 0 && sbi->reghost_enabled)
  80                sbi->needs_reghost = 1;
  81
  82        DPRINTK("needs_reghost = %d", sbi->needs_reghost);
  83
  84        return autofs4_dcache_readdir(file, dirent, filldir);
  85}
  86
  87/* Update usage from here to top of tree, so that scan of
  88   top-level directories will give a useful result */
  89static void autofs4_update_usage(struct dentry *dentry)
  90{
  91        struct dentry *top = dentry->d_sb->s_root;
  92
  93        spin_lock(&dcache_lock);
  94        for(; dentry != top; dentry = dentry->d_parent) {
  95                struct autofs_info *ino = autofs4_dentry_ino(dentry);
  96
  97                if (ino) {
  98                        update_atime(dentry->d_inode);
  99                        ino->last_used = jiffies;
 100                }
 101        }
 102        spin_unlock(&dcache_lock);
 103}
 104
 105/*
 106 * From 2.4 kernel readdir.c
 107 */
 108static int autofs4_dcache_readdir(struct file * filp, void * dirent, filldir_t filldir)
 109{
 110        int i;
 111        struct dentry *dentry = filp->f_dentry;
 112
 113        i = filp->f_pos;
 114        switch (i) {
 115                case 0:
 116                        if (filldir(dirent, ".", 1, i, dentry->d_inode->i_ino, DT_DIR) < 0)
 117                                break;
 118                        i++;
 119                        filp->f_pos++;
 120                        /* fallthrough */
 121                case 1:
 122                        if (filldir(dirent, "..", 2, i, dentry->d_parent->d_inode->i_ino, DT_DIR) < 0)
 123                                break;
 124                        i++;
 125                        filp->f_pos++;
 126                        /* fallthrough */
 127                default: {
 128                        struct list_head *list;
 129                        int j = i-2;
 130
 131                        spin_lock(&dcache_lock);
 132                        list = dentry->d_subdirs.next;
 133
 134                        for (;;) {
 135                                if (list == &dentry->d_subdirs) {
 136                                        spin_unlock(&dcache_lock);
 137                                        return 0;
 138                                }
 139                                if (!j)
 140                                        break;
 141                                j--;
 142                                list = list->next;
 143                        }
 144
 145                        while(1) {
 146                                struct dentry *de = list_entry(list, struct dentry, d_child);
 147
 148                                if (!d_unhashed(de) && de->d_inode) {
 149                                        spin_unlock(&dcache_lock);
 150                                        if (filldir(dirent, de->d_name.name, de->d_name.len, filp->f_pos, de->d_inode->i_ino, DT_UNKNOWN) < 0)
 151                                                break;
 152                                        spin_lock(&dcache_lock);
 153                                }
 154                                filp->f_pos++;
 155                                list = list->next;
 156                                if (list != &dentry->d_subdirs)
 157                                        continue;
 158                                spin_unlock(&dcache_lock);
 159                                break;
 160                        }
 161                }
 162        }
 163        return 0;
 164}
 165
 166static int autofs4_dir_open(struct inode *inode, struct file *file)
 167{
 168        struct dentry *dentry = file->f_dentry;
 169        struct vfsmount *mnt = file->f_vfsmnt;
 170        struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
 171        int status;
 172
 173        DPRINTK("file=%p dentry=%p %.*s",
 174                file, dentry, dentry->d_name.len, dentry->d_name.name);
 175
 176        if (autofs4_oz_mode(sbi))
 177                goto out;
 178
 179        if (autofs4_ispending(dentry)) {
 180                DPRINTK("dentry busy");
 181                return -EBUSY;
 182        }
 183
 184        if (!d_mountpoint(dentry) && dentry->d_op && dentry->d_op->d_revalidate) {
 185                struct nameidata nd;
 186                int empty;
 187
 188                /* In case there are stale directory dentrys from a failed mount */
 189                spin_lock(&dcache_lock);
 190                empty = list_empty(&dentry->d_subdirs);
 191                spin_unlock(&dcache_lock);
 192
 193                if (!empty)
 194                        d_invalidate(dentry);
 195
 196                nd.flags = LOOKUP_DIRECTORY;
 197                status = (dentry->d_op->d_revalidate)(dentry, &nd);
 198
 199                if (!status)
 200                        return -ENOENT;
 201        }
 202
 203        if (d_mountpoint(dentry)) {
 204                struct file *fp = NULL;
 205                struct vfsmount *fp_mnt = mntget(mnt);
 206                struct dentry *fp_dentry = dget(dentry);
 207
 208                while (follow_down(&fp_mnt, &fp_dentry) && d_mountpoint(fp_dentry));
 209
 210                fp = dentry_open(fp_dentry, fp_mnt, file->f_flags);
 211                status = PTR_ERR(fp);
 212                if (IS_ERR(fp)) {
 213                        file->private_data = NULL;
 214                        return status;
 215                }
 216                file->private_data = fp;
 217        }
 218out:
 219        return 0;
 220}
 221
 222static int autofs4_dir_close(struct inode *inode, struct file *file)
 223{
 224        struct dentry *dentry = file->f_dentry;
 225        struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
 226
 227        DPRINTK("file=%p dentry=%p %.*s",
 228                file, dentry, dentry->d_name.len, dentry->d_name.name);
 229
 230        if (autofs4_oz_mode(sbi))
 231                goto out;
 232
 233        if (autofs4_ispending(dentry)) {
 234                DPRINTK("dentry busy");
 235                return -EBUSY;
 236        }
 237
 238        if (d_mountpoint(dentry)) {
 239                struct file *fp = file->private_data;
 240
 241                if (!fp)
 242                        return -ENOENT;
 243
 244                filp_close(fp, current->files);
 245                file->private_data = NULL;
 246        }
 247out:
 248        return 0;
 249}
 250
 251static int autofs4_dir_readdir(struct file *file, void *dirent, filldir_t filldir)
 252{
 253        struct dentry *dentry = file->f_dentry;
 254        struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
 255        int status;
 256
 257        DPRINTK("file=%p dentry=%p %.*s",
 258                file, dentry, dentry->d_name.len, dentry->d_name.name);
 259
 260        if (autofs4_oz_mode(sbi))
 261                goto out;
 262
 263        if (autofs4_ispending(dentry)) {
 264                DPRINTK("dentry busy");
 265                return -EBUSY;
 266        }
 267
 268        if (d_mountpoint(dentry)) {
 269                struct file *fp = file->private_data;
 270
 271                if (!fp)
 272                        return -ENOENT;
 273
 274                if (!fp->f_op || !fp->f_op->readdir)
 275                        goto out;
 276
 277                status = vfs_readdir(fp, filldir, dirent);
 278                file->f_pos = fp->f_pos;
 279                if (status)
 280                        autofs4_copy_atime(file, fp);
 281                return status;
 282        }
 283out:
 284        return autofs4_dcache_readdir(file, dirent, filldir);
 285}
 286
 287static int try_to_fill_dentry(struct dentry *dentry, 
 288                              struct super_block *sb,
 289                              struct autofs_sb_info *sbi, int flags)
 290{
 291        struct autofs_info *de_info = autofs4_dentry_ino(dentry);
 292        int status = 0;
 293
 294        /* Block on any pending expiry here; invalidate the dentry
 295           when expiration is done to trigger mount request with a new
 296           dentry */
 297        if (de_info && (de_info->flags & AUTOFS_INF_EXPIRING)) {
 298                DPRINTK("waiting for expire %p name=%.*s",
 299                         dentry, dentry->d_name.len, dentry->d_name.name);
 300
 301                status = autofs4_wait(sbi, dentry, NFY_NONE);
 302                
 303                DPRINTK("expire done status=%d", status);
 304                
 305                return 0;
 306        }
 307
 308        DPRINTK("dentry=%p %.*s ino=%p",
 309                 dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_inode);
 310
 311        /* Wait for a pending mount, triggering one if there isn't one already */
 312        if (dentry->d_inode == NULL) {
 313                DPRINTK("waiting for mount name=%.*s",
 314                         dentry->d_name.len, dentry->d_name.name);
 315
 316                status = autofs4_wait(sbi, dentry, NFY_MOUNT);
 317                 
 318                DPRINTK("mount done status=%d", status);
 319
 320                if (status && dentry->d_inode)
 321                        return 0; /* Try to get the kernel to invalidate this dentry */
 322                
 323                /* Turn this into a real negative dentry? */
 324                if (status == -ENOENT) {
 325                        dentry->d_time = jiffies + AUTOFS_NEGATIVE_TIMEOUT;
 326                        spin_lock(&dentry->d_lock);
 327                        dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
 328                        spin_unlock(&dentry->d_lock);
 329                        return 1;
 330                } else if (status) {
 331                        /* Return a negative dentry, but leave it "pending" */
 332                        return 1;
 333                }
 334        /* Trigger mount for path component or follow link */
 335        } else if (flags & (LOOKUP_CONTINUE | LOOKUP_DIRECTORY) ||
 336                        current->link_count) {
 337                DPRINTK("waiting for mount name=%.*s",
 338                        dentry->d_name.len, dentry->d_name.name);
 339
 340                spin_lock(&dentry->d_lock);
 341                dentry->d_flags |= DCACHE_AUTOFS_PENDING;
 342                spin_unlock(&dentry->d_lock);
 343                status = autofs4_wait(sbi, dentry, NFY_MOUNT);
 344
 345                DPRINTK("mount done status=%d", status);
 346
 347                if (status) {
 348                        spin_lock(&dentry->d_lock);
 349                        dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
 350                        spin_unlock(&dentry->d_lock);
 351                        return 0;
 352                }
 353        }
 354
 355        /* We don't update the usages for the autofs daemon itself, this
 356           is necessary for recursive autofs mounts */
 357        if (!autofs4_oz_mode(sbi))
 358                autofs4_update_usage(dentry);
 359
 360        spin_lock(&dentry->d_lock);
 361        dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
 362        spin_unlock(&dentry->d_lock);
 363        return 1;
 364}
 365
 366/*
 367 * Revalidate is called on every cache lookup.  Some of those
 368 * cache lookups may actually happen while the dentry is not
 369 * yet completely filled in, and revalidate has to delay such
 370 * lookups..
 371 */
 372static int autofs4_revalidate(struct dentry * dentry, struct nameidata *nd)
 373{
 374        struct inode * dir = dentry->d_parent->d_inode;
 375        struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
 376        int oz_mode = autofs4_oz_mode(sbi);
 377        int flags = nd ? nd->flags : 0;
 378        int status = 1;
 379
 380        /* Pending dentry */
 381        if (autofs4_ispending(dentry)) {
 382                if (!oz_mode)
 383                        status = try_to_fill_dentry(dentry, dir->i_sb, sbi, flags);
 384                return status;
 385        }
 386
 387        /* Negative dentry.. invalidate if "old" */
 388        if (dentry->d_inode == NULL)
 389                return (dentry->d_time - jiffies <= AUTOFS_NEGATIVE_TIMEOUT);
 390
 391        /* Check for a non-mountpoint directory with no contents */
 392        spin_lock(&dcache_lock);
 393        if (S_ISDIR(dentry->d_inode->i_mode) &&
 394            !d_mountpoint(dentry) && 
 395            list_empty(&dentry->d_subdirs)) {
 396                DPRINTK("dentry=%p %.*s, emptydir",
 397                         dentry, dentry->d_name.len, dentry->d_name.name);
 398                spin_unlock(&dcache_lock);
 399                if (!oz_mode)
 400                        status = try_to_fill_dentry(dentry, dir->i_sb, sbi, flags);
 401                return status;
 402        }
 403        spin_unlock(&dcache_lock);
 404
 405        /* Update the usage list */
 406        if (!oz_mode)
 407                autofs4_update_usage(dentry);
 408
 409        return 1;
 410}
 411
 412static void autofs4_dentry_release(struct dentry *de)
 413{
 414        struct autofs_info *inf;
 415
 416        DPRINTK("releasing %p", de);
 417
 418        inf = autofs4_dentry_ino(de);
 419        de->d_fsdata = NULL;
 420
 421        if (inf) {
 422                inf->dentry = NULL;
 423                inf->inode = NULL;
 424
 425                autofs4_free_ino(inf);
 426        }
 427}
 428
 429/* For dentries of directories in the root dir */
 430static struct dentry_operations autofs4_root_dentry_operations = {
 431        .d_revalidate   = autofs4_revalidate,
 432        .d_release      = autofs4_dentry_release,
 433};
 434
 435/* For other dentries */
 436static struct dentry_operations autofs4_dentry_operations = {
 437        .d_revalidate   = autofs4_revalidate,
 438        .d_release      = autofs4_dentry_release,
 439};
 440
 441/* Lookups in the root directory */
 442static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 443{
 444        struct autofs_sb_info *sbi;
 445        int oz_mode;
 446
 447        DPRINTK("name = %.*s",
 448                dentry->d_name.len, dentry->d_name.name);
 449
 450        if (dentry->d_name.len > NAME_MAX)
 451                return ERR_PTR(-ENAMETOOLONG);/* File name too long to exist */
 452
 453        sbi = autofs4_sbi(dir->i_sb);
 454
 455        oz_mode = autofs4_oz_mode(sbi);
 456        DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d",
 457                 current->pid, process_group(current), sbi->catatonic, oz_mode);
 458
 459        /*
 460         * Mark the dentry incomplete, but add it. This is needed so
 461         * that the VFS layer knows about the dentry, and we can count
 462         * on catching any lookups through the revalidate.
 463         *
 464         * Let all the hard work be done by the revalidate function that
 465         * needs to be able to do this anyway..
 466         *
 467         * We need to do this before we release the directory semaphore.
 468         */
 469        dentry->d_op = &autofs4_root_dentry_operations;
 470
 471        if (!oz_mode) {
 472                spin_lock(&dentry->d_lock);
 473                dentry->d_flags |= DCACHE_AUTOFS_PENDING;
 474                spin_unlock(&dentry->d_lock);
 475        }
 476        dentry->d_fsdata = NULL;
 477        d_add(dentry, NULL);
 478
 479        if (dentry->d_op && dentry->d_op->d_revalidate) {
 480                up(&dir->i_sem);
 481                (dentry->d_op->d_revalidate)(dentry, nd);
 482                down(&dir->i_sem);
 483        }
 484
 485        /*
 486         * If we are still pending, check if we had to handle
 487         * a signal. If so we can force a restart..
 488         */
 489        if (dentry->d_flags & DCACHE_AUTOFS_PENDING) {
 490                /* See if we were interrupted */
 491                if (signal_pending(current)) {
 492                        sigset_t *sigset = &current->pending.signal;
 493                        if (sigismember (sigset, SIGKILL) ||
 494                            sigismember (sigset, SIGQUIT) ||
 495                            sigismember (sigset, SIGINT)) {
 496                            return ERR_PTR(-ERESTARTNOINTR);
 497                        }
 498                }
 499        }
 500
 501        /*
 502         * If this dentry is unhashed, then we shouldn't honour this
 503         * lookup even if the dentry is positive.  Returning ENOENT here
 504         * doesn't do the right thing for all system calls, but it should
 505         * be OK for the operations we permit from an autofs.
 506         */
 507        if ( dentry->d_inode && d_unhashed(dentry) )
 508                return ERR_PTR(-ENOENT);
 509
 510        return NULL;
 511}
 512
 513static int autofs4_dir_symlink(struct inode *dir, 
 514                               struct dentry *dentry,
 515                               const char *symname)
 516{
 517        struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
 518        struct autofs_info *ino = autofs4_dentry_ino(dentry);
 519        struct inode *inode;
 520        char *cp;
 521
 522        DPRINTK("%s <- %.*s", symname,
 523                dentry->d_name.len, dentry->d_name.name);
 524
 525        if (!autofs4_oz_mode(sbi))
 526                return -EACCES;
 527
 528        ino = autofs4_init_ino(ino, sbi, S_IFLNK | 0555);
 529        if (ino == NULL)
 530                return -ENOSPC;
 531
 532        ino->size = strlen(symname);
 533        ino->u.symlink = cp = kmalloc(ino->size + 1, GFP_KERNEL);
 534
 535        if (cp == NULL) {
 536                kfree(ino);
 537                return -ENOSPC;
 538        }
 539
 540        strcpy(cp, symname);
 541
 542        inode = autofs4_get_inode(dir->i_sb, ino);
 543        d_instantiate(dentry, inode);
 544
 545        if (dir == dir->i_sb->s_root->d_inode)
 546                dentry->d_op = &autofs4_root_dentry_operations;
 547        else
 548                dentry->d_op = &autofs4_dentry_operations;
 549
 550        dentry->d_fsdata = ino;
 551        ino->dentry = dget(dentry);
 552        ino->inode = inode;
 553
 554        dir->i_mtime = CURRENT_TIME;
 555
 556        return 0;
 557}
 558
 559/*
 560 * NOTE!
 561 *
 562 * Normal filesystems would do a "d_delete()" to tell the VFS dcache
 563 * that the file no longer exists. However, doing that means that the
 564 * VFS layer can turn the dentry into a negative dentry.  We don't want
 565 * this, because since the unlink is probably the result of an expire.
 566 * We simply d_drop it, which allows the dentry lookup to remount it
 567 * if necessary.
 568 *
 569 * If a process is blocked on the dentry waiting for the expire to finish,
 570 * it will invalidate the dentry and try to mount with a new one.
 571 *
 572 * Also see autofs4_dir_rmdir()..
 573 */
 574static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry)
 575{
 576        struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
 577        struct autofs_info *ino = autofs4_dentry_ino(dentry);
 578        
 579        /* This allows root to remove symlinks */
 580        if ( !autofs4_oz_mode(sbi) && !capable(CAP_SYS_ADMIN) )
 581                return -EACCES;
 582
 583        dput(ino->dentry);
 584
 585        dentry->d_inode->i_size = 0;
 586        dentry->d_inode->i_nlink = 0;
 587
 588        dir->i_mtime = CURRENT_TIME;
 589
 590        d_drop(dentry);
 591
 592        return 0;
 593}
 594
 595static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry)
 596{
 597        struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
 598        struct autofs_info *ino = autofs4_dentry_ino(dentry);
 599        
 600        if (!autofs4_oz_mode(sbi))
 601                return -EACCES;
 602
 603        spin_lock(&dcache_lock);
 604        if (!list_empty(&dentry->d_subdirs)) {
 605                spin_unlock(&dcache_lock);
 606                return -ENOTEMPTY;
 607        }
 608        __d_drop(dentry);
 609        spin_unlock(&dcache_lock);
 610
 611        dput(ino->dentry);
 612
 613        dentry->d_inode->i_size = 0;
 614        dentry->d_inode->i_nlink = 0;
 615
 616        if (dir->i_nlink)
 617                dir->i_nlink--;
 618
 619        return 0;
 620}
 621
 622static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 623{
 624        struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
 625        struct autofs_info *ino = autofs4_dentry_ino(dentry);
 626        struct inode *inode;
 627
 628        if ( !autofs4_oz_mode(sbi) )
 629                return -EACCES;
 630
 631        DPRINTK("dentry %p, creating %.*s",
 632                dentry, dentry->d_name.len, dentry->d_name.name);
 633
 634        ino = autofs4_init_ino(ino, sbi, S_IFDIR | 0555);
 635        if (ino == NULL)
 636                return -ENOSPC;
 637
 638        inode = autofs4_get_inode(dir->i_sb, ino);
 639        d_instantiate(dentry, inode);
 640
 641        if (dir == dir->i_sb->s_root->d_inode)
 642                dentry->d_op = &autofs4_root_dentry_operations;
 643        else
 644                dentry->d_op = &autofs4_dentry_operations;
 645
 646        dentry->d_fsdata = ino;
 647        ino->dentry = dget(dentry);
 648        ino->inode = inode;
 649        dir->i_nlink++;
 650        dir->i_mtime = CURRENT_TIME;
 651
 652        return 0;
 653}
 654
 655/* Get/set timeout ioctl() operation */
 656static inline int autofs4_get_set_timeout(struct autofs_sb_info *sbi,
 657                                         unsigned long __user *p)
 658{
 659        int rv;
 660        unsigned long ntimeout;
 661
 662        if ( (rv = get_user(ntimeout, p)) ||
 663             (rv = put_user(sbi->exp_timeout/HZ, p)) )
 664                return rv;
 665
 666        if ( ntimeout > ULONG_MAX/HZ )
 667                sbi->exp_timeout = 0;
 668        else
 669                sbi->exp_timeout = ntimeout * HZ;
 670
 671        return 0;
 672}
 673
 674/* Return protocol version */
 675static inline int autofs4_get_protover(struct autofs_sb_info *sbi, int __user *p)
 676{
 677        return put_user(sbi->version, p);
 678}
 679
 680/* Return protocol sub version */
 681static inline int autofs4_get_protosubver(struct autofs_sb_info *sbi, int __user *p)
 682{
 683        return put_user(sbi->sub_version, p);
 684}
 685
 686/*
 687 * Tells the daemon whether we need to reghost or not. Also, clears
 688 * the reghost_needed flag.
 689 */
 690static inline int autofs4_ask_reghost(struct autofs_sb_info *sbi, int __user *p)
 691{
 692        int status;
 693
 694        DPRINTK("returning %d", sbi->needs_reghost);
 695
 696        status = put_user(sbi->needs_reghost, p);
 697        if ( status )
 698                return status;
 699
 700        sbi->needs_reghost = 0;
 701        return 0;
 702}
 703
 704/*
 705 * Enable / Disable reghosting ioctl() operation
 706 */
 707static inline int autofs4_toggle_reghost(struct autofs_sb_info *sbi, int __user *p)
 708{
 709        int status;
 710        int val;
 711
 712        status = get_user(val, p);
 713
 714        DPRINTK("reghost = %d", val);
 715
 716        if (status)
 717                return status;
 718
 719        /* turn on/off reghosting, with the val */
 720        sbi->reghost_enabled = val;
 721        return 0;
 722}
 723
 724/*
 725* Tells the daemon whether it can umount the autofs mount.
 726*/
 727static inline int autofs4_ask_umount(struct vfsmount *mnt, int __user *p)
 728{
 729        int status = 0;
 730
 731        if (may_umount(mnt) == 0)
 732                status = 1;
 733
 734        DPRINTK("returning %d", status);
 735
 736        status = put_user(status, p);
 737
 738        return status;
 739}
 740
 741/* Identify autofs4_dentries - this is so we can tell if there's
 742   an extra dentry refcount or not.  We only hold a refcount on the
 743   dentry if its non-negative (ie, d_inode != NULL)
 744*/
 745int is_autofs4_dentry(struct dentry *dentry)
 746{
 747        return dentry && dentry->d_inode &&
 748                (dentry->d_op == &autofs4_root_dentry_operations ||
 749                 dentry->d_op == &autofs4_dentry_operations) &&
 750                dentry->d_fsdata != NULL;
 751}
 752
 753/*
 754 * ioctl()'s on the root directory is the chief method for the daemon to
 755 * generate kernel reactions
 756 */
 757static int autofs4_root_ioctl(struct inode *inode, struct file *filp,
 758                             unsigned int cmd, unsigned long arg)
 759{
 760        struct autofs_sb_info *sbi = autofs4_sbi(inode->i_sb);
 761        void __user *p = (void __user *)arg;
 762
 763        DPRINTK("cmd = 0x%08x, arg = 0x%08lx, sbi = %p, pgrp = %u",
 764                cmd,arg,sbi,process_group(current));
 765
 766        if ( _IOC_TYPE(cmd) != _IOC_TYPE(AUTOFS_IOC_FIRST) ||
 767             _IOC_NR(cmd) - _IOC_NR(AUTOFS_IOC_FIRST) >= AUTOFS_IOC_COUNT )
 768                return -ENOTTY;
 769        
 770        if ( !autofs4_oz_mode(sbi) && !capable(CAP_SYS_ADMIN) )
 771                return -EPERM;
 772        
 773        switch(cmd) {
 774        case AUTOFS_IOC_READY:  /* Wait queue: go ahead and retry */
 775                return autofs4_wait_release(sbi,(autofs_wqt_t)arg,0);
 776        case AUTOFS_IOC_FAIL:   /* Wait queue: fail with ENOENT */
 777                return autofs4_wait_release(sbi,(autofs_wqt_t)arg,-ENOENT);
 778        case AUTOFS_IOC_CATATONIC: /* Enter catatonic mode (daemon shutdown) */
 779                autofs4_catatonic_mode(sbi);
 780                return 0;
 781        case AUTOFS_IOC_PROTOVER: /* Get protocol version */
 782                return autofs4_get_protover(sbi, p);
 783        case AUTOFS_IOC_PROTOSUBVER: /* Get protocol sub version */
 784                return autofs4_get_protosubver(sbi, p);
 785        case AUTOFS_IOC_SETTIMEOUT:
 786                return autofs4_get_set_timeout(sbi, p);
 787
 788        case AUTOFS_IOC_TOGGLEREGHOST:
 789                return autofs4_toggle_reghost(sbi, p);
 790        case AUTOFS_IOC_ASKREGHOST:
 791                return autofs4_ask_reghost(sbi, p);
 792
 793        case AUTOFS_IOC_ASKUMOUNT:
 794                return autofs4_ask_umount(filp->f_vfsmnt, p);
 795
 796        /* return a single thing to expire */
 797        case AUTOFS_IOC_EXPIRE:
 798                return autofs4_expire_run(inode->i_sb,filp->f_vfsmnt,sbi, p);
 799        /* same as above, but can send multiple expires through pipe */
 800        case AUTOFS_IOC_EXPIRE_MULTI:
 801                return autofs4_expire_multi(inode->i_sb,filp->f_vfsmnt,sbi, p);
 802
 803        default:
 804                return -ENOSYS;
 805        }
 806}
 807
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.