CTC++ Coverage Report - Execution Profile    #840/1532

Files Summary | Functions Summary | Execution Profile | Index | No Index
First | Previous | Next | Last


File: fs/autofs4/root.c
Instrumentation mode: function-decision-multicondition
TER: 0 % ( 0/463)

Start/ End/    
True False - Line Source

  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/capability.h>
  16 #include <linux/errno.h>
  17 #include <linux/stat.h>
  18 #include <linux/param.h>
  19 #include <linux/time.h>
  20 #include <linux/smp_lock.h>
  21 #include "autofs_i.h"
  22 
  23 static int autofs4_dir_symlink(struct inode *,struct dentry *,const char *);
  24 static int autofs4_dir_unlink(struct inode *,struct dentry *);
  25 static int autofs4_dir_rmdir(struct inode *,struct dentry *);
  26 static int autofs4_dir_mkdir(struct inode *,struct dentry *,int);
  27 static int autofs4_root_ioctl(struct inode *, struct file *,unsigned int,unsigned long);
  28 static int autofs4_dir_open(struct inode *inode, struct file *file);
  29 static int autofs4_dir_close(struct inode *inode, struct file *file);
  30 static int autofs4_dir_readdir(struct file * filp, void * dirent, filldir_t filldir);
  31 static int autofs4_root_readdir(struct file * filp, void * dirent, filldir_t filldir);
  32 static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *);
  33 static int autofs4_dcache_readdir(struct file *, void *, filldir_t);
  34 
  35 struct file_operations autofs4_root_operations = {
  36    .open      = dcache_dir_open,
  37    .release   = dcache_dir_close,
  38    .read      = generic_read_dir,
  39    .readdir   = autofs4_root_readdir,
  40    .ioctl      = autofs4_root_ioctl,
  41 };
  42 
  43 struct file_operations autofs4_dir_operations = {
  44    .open      = autofs4_dir_open,
  45    .release   = autofs4_dir_close,
  46    .read      = generic_read_dir,
  47    .readdir   = autofs4_dir_readdir,
  48 };
  49 
  50 struct inode_operations autofs4_root_inode_operations = {
  51    .lookup      = autofs4_lookup,
  52    .unlink      = autofs4_dir_unlink,
  53    .symlink   = autofs4_dir_symlink,
  54    .mkdir      = autofs4_dir_mkdir,
  55    .rmdir      = autofs4_dir_rmdir,
  56 };
  57 
  58 struct inode_operations autofs4_dir_inode_operations = {
  59    .lookup      = autofs4_lookup,
  60    .unlink      = autofs4_dir_unlink,
  61    .symlink   = autofs4_dir_symlink,
  62    .mkdir      = autofs4_dir_mkdir,
  63    .rmdir      = autofs4_dir_rmdir,
  64 };
  65 
 
- 66 static int autofs4_root_readdir(struct file *file, void *dirent,
  67             filldir_t filldir)
  68 {
  69    struct autofs_sb_info *sbi = autofs4_sbi(file->f_dentry->d_sb);
  70    int oz_mode = autofs4_oz_mode(sbi);
  71 
    72    DPRINTK("called, filp->f_pos = %lld", file->f_pos);
- 72 do-while (0)
  73 
  74    /*
  75     * Don't set reghost flag if:
  76     * 1) f_pos is larger than zero -- we've already been here.
  77     * 2) we haven't even enabled reghosting in the 1st place.
  78     * 3) this is the daemon doing a readdir
  79     */
- 80    if (oz_mode && file->f_pos == 0 && sbi->reghost_enabled)
 - 80   T && T && T
 - 80   T && T && F
 - 80   T && F && _
 - 80   F && _ && _
  81       sbi->needs_reghost = 1;
  82 
    83    DPRINTK("needs_reghost = %d", sbi->needs_reghost);
- 83 do-while (0)
  84 
 - 85    return autofs4_dcache_readdir(file, dirent, filldir);
  86 }
  87 
  88 /* Update usage from here to top of tree, so that scan of
  89    top-level directories will give a useful result */
 
- 90 static void autofs4_update_usage(struct vfsmount *mnt, struct dentry *dentry)
  91 {
  92    struct dentry *top = dentry->d_sb->s_root;
  93 
    94    spin_lock(&dcache_lock);
    94   do
- 94   do-while (0)
- 94 do-while (0)
- 95    for(; dentry != top; dentry = dentry->d_parent) {
  96       struct autofs_info *ino = autofs4_dentry_ino(dentry);
  97 
- 98       if (ino) {
  99          touch_atime(mnt, dentry);
  100          ino->last_used = jiffies;
  101       }
  102    }
    103    spin_unlock(&dcache_lock);
    103   do
- 103   do-while (0)
- 103 do-while (0)
  104 }
  105 
  106 /*
  107  * From 2.4 kernel readdir.c
  108  */
 
- 109 static int autofs4_dcache_readdir(struct file * filp, void * dirent, filldir_t filldir)
  110 {
  111    int i;
  112    struct dentry *dentry = filp->f_dentry;
  113 
  114    i = filp->f_pos;
    115    switch (i) {
 - 116       case 0:
- 117          if (filldir(dirent, ".", 1, i, dentry->d_inode->i_ino, DT_DIR) < 0)
 - 118             break;
  119          i++;
  120          filp->f_pos++;
  121          /* fallthrough */
 - 122       case 1:
- 123          if (filldir(dirent, "..", 2, i, dentry->d_parent->d_inode->i_ino, DT_DIR) < 0)
 - 124             break;
  125          i++;
  126          filp->f_pos++;
  127          /* fallthrough */
 - 128       default: {
  129          struct list_head *list;
  130          int j = i-2;
  131 
    132          spin_lock(&dcache_lock);
    132       do
- 132       do-while (0)
- 132     do-while (0)
  133          list = dentry->d_subdirs.next;
  134 
- 135          for (;;) {
- 136             if (list == &dentry->d_subdirs) {
    137                spin_unlock(&dcache_lock);
    137           do
- 137           do-while (0)
- 137         do-while (0)
 - 138                return 0;
  139             }
- 140             if (!j)
 - 141                break;
  142             j--;
  143             list = list->next;
  144          }
  145 
- 146          while(1) {
  147             struct dentry *de = list_entry(list,
  148                   struct dentry, d_u.d_child);
  149 
- 150             if (!d_unhashed(de) && de->d_inode) {
 - 150         T && T
 - 150         T && F
 - 150         F && _
    151                spin_unlock(&dcache_lock);
    151           do
- 151           do-while (0)
- 151         do-while (0)
- 152                if (filldir(dirent, de->d_name.name, de->d_name.len, filp->f_pos, de->d_inode->i_ino, DT_UNKNOWN) < 0)
 - 153                   break;
    154                spin_lock(&dcache_lock);
    154           do
- 154           do-while (0)
- 154         do-while (0)
  155             }
  156             filp->f_pos++;
  157             list = list->next;
- 158             if (list != &dentry->d_subdirs)
 - 159                continue;
    160             spin_unlock(&dcache_lock);
    160         do
- 160         do-while (0)
- 160       do-while (0)
 - 161             break;
  162          }
  163       }
  164    }
 - 165    return 0;
  166 }
  167 
 
- 168 static int autofs4_dir_open(struct inode *inode, struct file *file)
  169 {
  170    struct dentry *dentry = file->f_dentry;
  171    struct vfsmount *mnt = file->f_vfsmnt;
  172    struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
  173    int status;
  174 
    175    DPRINTK("file=%p dentry=%p %.*s",
- 175 do-while (0)
  176       file, dentry, dentry->d_name.len, dentry->d_name.name);
  177 
- 178    if (autofs4_oz_mode(sbi))
 - 179       goto out;
  180 
- 181    if (autofs4_ispending(dentry)) {
    182       DPRINTK("dentry busy");
- 182   do-while (0)
 - 183       return -EBUSY;
  184    }
  185 
- 186    if (!d_mountpoint(dentry) && dentry->d_op && dentry->d_op->d_revalidate) {
 - 186   T && T && T
 - 186   T && T && F
 - 186   T && F && _
 - 186   F && _ && _
  187       struct nameidata nd;
  188       int empty;
  189 
  190       /* In case there are stale directory dentrys from a failed mount */
    191       spin_lock(&dcache_lock);
    191     do
- 191     do-while (0)
- 191   do-while (0)
  192       empty = list_empty(&dentry->d_subdirs);
    193       spin_unlock(&dcache_lock);
    193     do
- 193     do-while (0)
- 193   do-while (0)
  194 
- 195       if (!empty)
  196          d_invalidate(dentry);
  197 
  198       nd.dentry = dentry;
  199       nd.mnt = mnt;
  200       nd.flags = LOOKUP_DIRECTORY;
  201       status = (dentry->d_op->d_revalidate)(dentry, &nd);
  202 
- 203       if (!status)
 - 204          return -ENOENT;
  205    }
  206 
- 207    if (d_mountpoint(dentry)) {
  208       struct file *fp = NULL;
  209       struct vfsmount *fp_mnt = mntget(mnt);
  210       struct dentry *fp_dentry = dget(dentry);
  211 
- 212       if (!autofs4_follow_mount(&fp_mnt, &fp_dentry)) {
  213          dput(fp_dentry);
  214          mntput(fp_mnt);
 - 215          return -ENOENT;
  216       }
  217 
  218       fp = dentry_open(fp_dentry, fp_mnt, file->f_flags);
  219       status = PTR_ERR(fp);
- 220       if (IS_ERR(fp)) {
  221          file->private_data = NULL;
 - 222          return status;
  223       }
  224       file->private_data = fp;
  225    }
  226 out:
 - 227    return 0;
  228 }
  229 
 
- 230 static int autofs4_dir_close(struct inode *inode, struct file *file)
  231 {
  232    struct dentry *dentry = file->f_dentry;
  233    struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
  234 
    235    DPRINTK("file=%p dentry=%p %.*s",
- 235 do-while (0)
  236       file, dentry, dentry->d_name.len, dentry->d_name.name);
  237 
- 238    if (autofs4_oz_mode(sbi))
 - 239       goto out;
  240 
- 241    if (autofs4_ispending(dentry)) {
    242       DPRINTK("dentry busy");
- 242   do-while (0)
 - 243       return -EBUSY;
  244    }
  245 
- 246    if (d_mountpoint(dentry)) {
  247       struct file *fp = file->private_data;
  248 
- 249       if (!fp)
 - 250          return -ENOENT;
  251 
  252       filp_close(fp, current->files);
  253       file->private_data = NULL;
  254    }
  255 out:
 - 256    return 0;
  257 }
  258 
 
- 259 static int autofs4_dir_readdir(struct file *file, void *dirent, filldir_t filldir)
  260 {
  261    struct dentry *dentry = file->f_dentry;
  262    struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
  263    int status;
  264 
    265    DPRINTK("file=%p dentry=%p %.*s",
- 265 do-while (0)
  266       file, dentry, dentry->d_name.len, dentry->d_name.name);
  267 
- 268    if (autofs4_oz_mode(sbi))
 - 269       goto out;
  270 
- 271    if (autofs4_ispending(dentry)) {
    272       DPRINTK("dentry busy");
- 272   do-while (0)
 - 273       return -EBUSY;
  274    }
  275 
- 276    if (d_mountpoint(dentry)) {
  277       struct file *fp = file->private_data;
  278 
- 279       if (!fp)
 - 280          return -ENOENT;
  281 
- 282       if (!fp->f_op || !fp->f_op->readdir)
 - 282     T || _
 - 282     F || T
 - 282     F || F
 - 283          goto out;
  284 
  285       status = vfs_readdir(fp, filldir, dirent);
  286       file->f_pos = fp->f_pos;
- 287       if (status)
  288          autofs4_copy_atime(file, fp);
 - 289       return status;
  290    }
  291 out:
 - 292    return autofs4_dcache_readdir(file, dirent, filldir);
  293 }
  294 
 
- 295 static int try_to_fill_dentry(struct vfsmount *mnt, struct dentry *dentry, int flags)
  296 {
  297    struct super_block *sb = mnt->mnt_sb;
  298    struct autofs_sb_info *sbi = autofs4_sbi(sb);
  299    struct autofs_info *de_info = autofs4_dentry_ino(dentry);
  300    int status = 0;
  301 
  302    /* Block on any pending expiry here; invalidate the dentry
  303            when expiration is done to trigger mount request with a new
  304            dentry */
- 305    if (de_info && (de_info->flags & AUTOFS_INF_EXPIRING)) {
 - 305   T && (T)
 - 305   T && (F)
 - 305   F && (_)
    306       DPRINTK("waiting for expire %p name=%.*s",
- 306   do-while (0)
  307           dentry, dentry->d_name.len, dentry->d_name.name);
  308 
  309       status = autofs4_wait(sbi, dentry, NFY_NONE);
  310       
    311       DPRINTK("expire done status=%d", status);
- 311   do-while (0)
  312       
  313       /*
  314        * If the directory still exists the mount request must
  315        * continue otherwise it can't be followed at the right
  316        * time during the walk.
  317        */
  318       status = d_invalidate(dentry);
- 319       if (status != -EBUSY)
 - 320          return 0;
  321    }
  322 
    323    DPRINTK("dentry=%p %.*s ino=%p",
- 323 do-while (0)
  324        dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_inode);
  325 
  326    /* Wait for a pending mount, triggering one if there isn't one already */
- 327    if (dentry->d_inode == NULL) {
    328       DPRINTK("waiting for mount name=%.*s",
- 328   do-while (0)
  329           dentry->d_name.len, dentry->d_name.name);
  330 
  331       status = autofs4_wait(sbi, dentry, NFY_MOUNT);
  332        
    333       DPRINTK("mount done status=%d", status);
- 333   do-while (0)
  334 
- 335       if (status && dentry->d_inode)
 - 335     T && T
 - 335     T && F
 - 335     F && _
 - 336          return 0; /* Try to get the kernel to invalidate this dentry */
  337       
  338       /* Turn this into a real negative dentry? */
- 339       if (status == -ENOENT) {
  340          dentry->d_time = jiffies + AUTOFS_NEGATIVE_TIMEOUT;
    341          spin_lock(&dentry->d_lock);
    341       do
- 341       do-while (0)
- 341     do-while (0)
  342          dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
    343          spin_unlock(&dentry->d_lock);
    343       do
- 343       do-while (0)
- 343     do-while (0)
 - 344          return 1;
- 345       } else if (status) {
  346          /* Return a negative dentry, but leave it "pending" */
 - 347          return 1;
  348       }
  349    /* Trigger mount for path component or follow link */
  350    } else if (flags & (LOOKUP_CONTINUE | LOOKUP_DIRECTORY) ||
- 351          current->link_count) {
 - 351   T || _
 - 351   F || T
 - 351   F || F
    352       DPRINTK("waiting for mount name=%.*s",
- 352   do-while (0)
  353          dentry->d_name.len, dentry->d_name.name);
  354 
    355       spin_lock(&dentry->d_lock);
    355     do
- 355     do-while (0)
- 355   do-while (0)
  356       dentry->d_flags |= DCACHE_AUTOFS_PENDING;
    357       spin_unlock(&dentry->d_lock);
    357     do
- 357     do-while (0)
- 357   do-while (0)
  358       status = autofs4_wait(sbi, dentry, NFY_MOUNT);
  359 
    360       DPRINTK("mount done status=%d", status);
- 360   do-while (0)
  361 
- 362       if (status) {
    363          spin_lock(&dentry->d_lock);
    363       do
- 363       do-while (0)
- 363     do-while (0)
  364          dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
    365          spin_unlock(&dentry->d_lock);
    365       do
- 365       do-while (0)
- 365     do-while (0)
 - 366          return 0;
  367       }
  368    }
  369 
  370    /* We don't update the usages for the autofs daemon itself, this
  371       is necessary for recursive autofs mounts */
- 372    if (!autofs4_oz_mode(sbi))
  373       autofs4_update_usage(mnt, dentry);
  374 
    375    spin_lock(&dentry->d_lock);
    375   do
- 375   do-while (0)
- 375 do-while (0)
  376    dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
    377    spin_unlock(&dentry->d_lock);
    377   do
- 377   do-while (0)
- 377 do-while (0)
 - 378    return 1;
  379 }
  380 
  381 /*
  382  * Revalidate is called on every cache lookup.  Some of those
  383  * cache lookups may actually happen while the dentry is not
  384  * yet completely filled in, and revalidate has to delay such
  385  * lookups..
  386  */
 
- 387 static int autofs4_revalidate(struct dentry * dentry, struct nameidata *nd)
  388 {
  389    struct inode * dir = dentry->d_parent->d_inode;
  390    struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
  391    int oz_mode = autofs4_oz_mode(sbi);
    392    int flags = nd ? nd->flags : 0;
- 392 ternary-?: nd
  393    int status = 1;
  394 
  395    /* Pending dentry */
- 396    if (autofs4_ispending(dentry)) {
- 397       if (!oz_mode)
  398          status = try_to_fill_dentry(nd->mnt, dentry, flags);