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

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


File: fs/exportfs/expfs.c
Instrumentation mode: function-decision-multicondition
TER: 0 % ( 0/260)

Start/ End/    
True False - Line Source

  1 
  2 #include <linux/fs.h>
  3 #include <linux/file.h>
  4 #include <linux/module.h>
  5 #include <linux/smp_lock.h>
  6 #include <linux/namei.h>
  7 
  8 struct export_operations export_op_default;
  9 
  10 #define   CALL(ops,fun) ((ops->fun)?(ops->fun):export_op_default.fun)
  11 
  12 #define dprintk(fmt, args...) do{}while(0)
  13 
  14 static struct dentry *
 
- 15 find_acceptable_alias(struct dentry *result,
  16       int (*acceptable)(void *context, struct dentry *dentry),
  17       void *context)
  18 {
  19    struct dentry *dentry, *toput = NULL;
  20 
    21    spin_lock(&dcache_lock);
    21   do
- 21   do-while (0)
- 21 do-while (0)
- 22    list_for_each_entry(dentry, &result->d_inode->i_dentry, d_alias) {
  23       dget_locked(dentry);
    24       spin_unlock(&dcache_lock);
    24     do
- 24     do-while (0)
- 24   do-while (0)
- 25       if (toput)
  26          dput(toput);
- 27       if (dentry != result && acceptable(context, dentry)) {
 - 27     T && T
 - 27     T && F
 - 27     F && _
  28          dput(result);
 - 29          return dentry;
  30       }
    31       spin_lock(&dcache_lock);
    31     do
- 31     do-while (0)
- 31   do-while (0)
  32       toput = dentry;
  33    }
    34    spin_unlock(&dcache_lock);
    34   do
- 34   do-while (0)
- 34 do-while (0)
  35 
- 36    if (toput)
  37       dput(toput);
 - 38    return NULL;
  39 }
  40 
  41 /**
  42  * find_exported_dentry - helper routine to implement export_operations->decode_fh
  43  * @sb:      The &super_block identifying the filesystem
  44  * @obj:   An opaque identifier of the object to be found - passed to
  45  *      get_inode
  46  * @parent:   An optional opqaue identifier of the parent of the object.
  47  * @acceptable:   A function used to test possible &dentries to see if they are
  48  *      acceptable
  49  * @context:   A parameter to @acceptable so that it knows on what basis to
  50  *      judge.
  51  *
  52  * find_exported_dentry is the central helper routine to enable file systems
  53  * to provide the decode_fh() export_operation.  It's main task is to take
  54  * an &inode, find or create an appropriate &dentry structure, and possibly
  55  * splice this into the dcache in the correct place.
  56  *
  57  * The decode_fh() operation provided by the filesystem should call
  58  * find_exported_dentry() with the same parameters that it received except
  59  * that instead of the file handle fragment, pointers to opaque identifiers
  60  * for the object and optionally its parent are passed.  The default decode_fh
  61  * routine passes one pointer to the start of the filehandle fragment, and
  62  * one 8 bytes into the fragment.  It is expected that most filesystems will
  63  * take this approach, though the offset to the parent identifier may well be
  64  * different.
  65  *
  66  * find_exported_dentry() will call get_dentry to get an dentry pointer from
  67  * the file system.  If any &dentry in the d_alias list is acceptable, it will
  68  * be returned.  Otherwise find_exported_dentry() will attempt to splice a new
  69  * &dentry into the dcache using get_name() and get_parent() to find the
  70  * appropriate place.
  71  */
  72 
  73 struct dentry *
 
- 74 find_exported_dentry(struct super_block *sb, void *obj, void *parent,
  75            int (*acceptable)(void *context, struct dentry *de),
  76            void *context)
  77 {
  78    struct dentry *result = NULL;
  79    struct dentry *target_dir;
  80    int err;
  81    struct export_operations *nops = sb->s_export_op;
  82    struct dentry *alias;
  83    int noprogress;
  84    char nbuf[NAME_MAX+1];
  85 
  86    /*
  87     * Attempt to find the inode.
  88     */
    89    result = CALL(sb->s_export_op,get_dentry)(sb,obj);
- 89 ternary-?: ( sb -> s_export_op -> get_dentry )
  90    err = -ESTALE;
- 91    if (result == NULL)
 - 92       goto err_out;
- 93    if (IS_ERR(result)) {
  94       err = PTR_ERR(result);
 - 95       goto err_out;
  96    }
  97    if (S_ISDIR(result->d_inode->i_mode) &&
- 98        (result->d_flags & DCACHE_DISCONNECTED)) {
 - 98   (T) && (T)
 - 98   (T) && (F)
 - 98   (F) && (_)
  99       /* it is an unconnected directory, we must connect it */
  100       ;
    101    } else {
- 102       if (acceptable(context, result))
 - 103          return result;
- 104       if (S_ISDIR(result->d_inode->i_mode)) {
  105          /* there is no other dentry, so fail */
 - 106          goto err_result;
  107       }
  108 
  109       alias = find_acceptable_alias(result, acceptable, context);
- 110       if (alias)
 - 111          return alias;
  112    }         
  113 
  114    /* It's a directory, or we are required to confirm the file's
  115     * location in the tree based on the parent information
  116      */
    117    dprintk("find_exported_dentry: need to look harder for %s/%d\n",sb->s_id,*(int*)obj);
- 117 do-while (0)
- 118    if (S_ISDIR(result->d_inode->i_mode))
  119       target_dir = dget(result);
    120    else {
- 121       if (parent == NULL)
 - 122          goto err_result;
  123 
    124       target_dir = CALL(sb->s_export_op,get_dentry)(sb,parent);
- 124   ternary-?: ( sb -> s_export_op -> get_dentry )
- 125       if (IS_ERR(target_dir))
  126          err = PTR_ERR(target_dir);
- 127       if (target_dir == NULL || IS_ERR(target_dir))
 - 127     T || _
 - 127     F || T
 - 127     F || F
 - 128          goto err_result;
  129    }
  130    /*
  131     * Now we need to make sure that target_dir is properly connected.
  132     * It may already be, as the flag isn't always updated when connection
  133     * happens.
  134     * So, we walk up parent links until we find a connected directory,
  135     * or we run out of directories.  Then we find the parent, find
  136     * the name of the child in that parent, and do a lookup.
  137     * This should connect the child into the parent
  138     * We then repeat.
  139     */
  140 
  141    /* it is possible that a confused file system might not let us complete 
  142     * the path to the root.  For example, if get_parent returns a directory
  143     * in which we cannot find a name for the child.  While this implies a
  144     * very sick filesystem we don't want it to cause knfsd to spin.  Hence
  145     * the noprogress counter.  If we go through the loop 10 times (2 is
  146     * probably enough) without getting anywhere, we just give up
  147     */
  148    noprogress= 0;
- 149    while (target_dir->d_flags & DCACHE_DISCONNECTED && noprogress++ < 10) {
 - 149   T && T
 - 149   T && F
 - 149   F && _
  150       struct dentry *pd = target_dir;
  151 
  152       dget(pd);
    153       spin_lock(&pd->d_lock);
    153     do
- 153     do-while (0)
- 153   do-while (0)
  154       while (!IS_ROOT(pd) &&
- 155             (pd->d_parent->d_flags&DCACHE_DISCONNECTED)) {
 - 155     !(F) && (T)
 - 155     !(T) && (_)
 - 155     !(F) && (F)
  156          struct dentry *parent = pd->d_parent;
  157 
  158          dget(parent);
    159          spin_unlock(&pd->d_lock);
    159       do
- 159       do-while (0)
- 159     do-while (0)
  160          dput(pd);
  161          pd = parent;
    162          spin_lock(&pd->d_lock);
    162       do
- 162       do-while (0)
- 162     do-while (0)
  163       }
    164       spin_unlock(&pd->d_lock);
    164     do
- 164     do-while (0)
- 164   do-while (0)
  165 
- 166       if (!IS_ROOT(pd)) {
  167          /* must have found a connected parent - great */
    168          spin_lock(&pd->d_lock);
    168       do
- 168       do-while (0)
- 168     do-while (0)
  169          pd->d_flags &= ~DCACHE_DISCONNECTED;
    170          spin_unlock(&pd->d_lock);
    170       do
- 170       do-while (0)
- 170     do-while (0)
  171          noprogress = 0;
- 172       } else if (pd == sb->s_root) {
  173          printk(KERN_ERR "export: Eeek filesystem root is not connected, impossible\n");
    174          spin_lock(&pd->d_lock);
    174       do
- 174       do-while (0)
- 174     do-while (0)
  175          pd->d_flags &= ~DCACHE_DISCONNECTED;
    176          spin_unlock(&pd->d_lock);
    176       do
- 176       do-while (0)
- 176     do-while (0)
  177          noprogress = 0;
    178       } else {
  179          /* we have hit the top of a disconnected path.  Try
  180           * to find parent and connect
  181           * note: racing with some other process renaming a
  182           * directory isn't much of a problem here.  If someone
  183           * renames the directory, it will end up properly
  184           * connected, which is what we want
  185           */
  186          struct dentry *ppd;
  187          struct dentry *npd;
  188 
  189          mutex_lock(&pd->d_inode->i_mutex);
    190          ppd = CALL(nops,get_parent)(pd);
- 190     ternary-?: ( nops -> get_parent )
  191          mutex_unlock(&pd->d_inode->i_mutex);
  192 
- 193          if (IS_ERR(ppd)) {
  194             err = PTR_ERR(ppd);
    195             dprintk("find_exported_dentry: get_parent of %ld failed, err %d\n",
- 195       do-while (0)
  196                pd->d_inode->i_ino, err);
  197             dput(pd);
 - 198             break;
  199          }
    200          dprintk("find_exported_dentry: find name of %lu in %lu\n", pd->d_inode->i_ino, ppd->d_inode->i_ino);
- 200     do-while (0)
    201          err = CALL(nops,get_name)(ppd, nbuf, pd);
- 201     ternary-?: ( nops -> get_name )
- 202          if (err) {
  203             dput(ppd);
  204             dput(pd);
- 205             if (err == -ENOENT)
  206                /* some race between get_parent and
  207                 * get_name?  just try again
  208                 */
 - 209                continue;
 - 210             break;
  211          }
    212          dprintk("find_exported_dentry: found name: %s\n", nbuf);
- 212     do-while (0)
  213          mutex_lock(&ppd->d_inode->i_mutex);
  214          npd = lookup_one_len(nbuf, ppd, strlen(nbuf));
  215          mutex_unlock(&ppd->d_inode->i_mutex);
- 216          if (IS_ERR(npd)) {
  217             err = PTR_ERR(npd);
    218             dprintk("find_exported_dentry: lookup failed: %d\n", err);
- 218       do-while (0)
  219             dput(ppd);
  220             dput(pd);
 - 221             break;
  222          }
  223          /* we didn't really want npd, we really wanted
  224           * a side-effect of the lookup.
  225           * hopefully, npd == pd, though it isn't really
  226           * a problem if it isn't
  227           */
- 228          if (npd == pd)
  229             noprogress = 0;
    230          else
  231             printk("find_exported_dentry: npd != pd\n");
  232          dput(npd);
  233          dput(ppd);
- 234          if (IS_ROOT(pd)) {
  235             /* something went wrong, we have to give up */
  236             dput(pd);
 - 237             break;
  238          }
  239       }
  240       dput(pd);
  241    }
  242 
- 243    if (target_dir->d_flags & DCACHE_DISCONNECTED) {
  244       /* something went wrong - oh-well */
- 245       if (!err)
  246          err = -ESTALE;
 - 247       goto err_target;
  248    }
  249    /* if we weren't after a directory, have one more step to go */
- 250    if (result != target_dir) {
  251       struct dentry *nresult;
    252       err = CALL(nops,get_name)(target_dir, nbuf, result);
- 252   ternary-?: ( nops -> get_name )
- 253       if (!err) {
  254          mutex_lock(&target_dir->d_inode->i_mutex);
  255          nresult = lookup_one_len(nbuf, target_dir, strlen(nbuf));
  256          mutex_unlock(&target_dir->d_inode->i_mutex);
- 257          if (!IS_ERR(nresult)) {
- 258             if (nresult->d_inode) {
  259                dput(result);
  260                result = nresult;
    261             } else
  262                dput(nresult);
  263          }
  264       }
  265    }
  266    dput(target_dir);
  267    /* now result is properly connected, it is our best bet */
- 268    if (acceptable(context, result))
 - 269       return result;
  270 
  271    alias = find_acceptable_alias(result, acceptable, context);
- 272    if (alias)
 - 273       return alias;
  274 
  275    /* drat - I just cannot find anything acceptable */
  276    dput(result);
  277    /* It might be justifiable to return ESTALE here,
  278     * but the filehandle at-least looks reasonable good
  279     * and it just be a permission problem, so returning
  280     * -EACCESS is safer
  281     */
 - 282    return ERR_PTR(-EACCES);
  283 
  284  err_target:
  285    dput(target_dir);
  286  err_result:
  287    dput(result);
  288  err_out:
 - 289    return ERR_PTR(err);
  290 }
  291 
  292 
  293 
 
- 294 static struct dentry *get_parent(struct dentry *child)
  295 {
  296    /* get_parent cannot be supported generically, the locking
  297     * is too icky.
  298     * instead, we just return EACCES.  If server reboots or inodes
  299     * get flushed, you lose
  300     */
 - 301    return ERR_PTR(-EACCES);
  302 }
  303 
  304 
  305 struct getdents_callback {
  306    char *name;      /* name that was found. It already points to a
  307                buffer NAME_MAX+1 is size */
  308    unsigned long ino;   /* the inum we are looking for */
  309    int found;      /* inode matched? */
  310    int sequence;      /* sequence counter */
  311 };
  312 
  313 /*
  314  * A rather strange filldir function to capture
  315  * the name matching the specified inode number.
  316  */
 
- 317 static int filldir_one(void * __buf, const char * name, int len,
  318          loff_t pos, ino_t ino, unsigned int d_type)
  319 {
  320    struct getdents_callback *buf = __buf;
  321    int result = 0;
  322 
  323    buf->sequence++;
- 324    if (buf->ino == ino) {
  325       memcpy(buf->name, name, len);
  326       buf->name[len] = '\0';
  327       buf->found = 1;
  328       result = -1;
  329    }
 - 330    return result;
  331 }
  332 
  333 /**
  334  * get_name - default export_operations->get_name function
  335  * @dentry: the directory in which to find a name
  336  * @name:   a pointer to a %NAME_MAX+1 char buffer to store the name
  337  * @child:  the dentry for the child directory.
  338  *
  339  * calls readdir on the parent until it finds an entry with
  340  * the same inode number as the child, and returns that.
  341  */
 
- 342 static int get_name(struct dentry *dentry, char *name,
  343          struct dentry *child)
  344 {
  345    struct inode *dir = dentry->d_inode;
  346    int error;
  347    struct file *file;
  348    struct getdents_callback buffer;
  349 
  350    error = -ENOTDIR;
- 351    if (!dir || !S_ISDIR(dir->i_mode))
 - 351   T || !(_)
 - 351   F || !(F)
 - 351   F || !(T)
 - 352       goto out;
  353    error = -EINVAL;
- 354    if (!dir->i_fop)
 - 355       goto out;
  356    /*
  357     * Open the directory ...
  358     */
  359    file = dentry_open(dget(dentry), NULL, O_RDONLY);
  360    error = PTR_ERR(file);
- 361    if (IS_ERR(file))
 - 362       goto out;
  363 
  364    error = -EINVAL;
- 365    if (!file->f_op->readdir)
 - 366       goto out_close;
  367 
  368    buffer.name = name;
  369    buffer.ino = child->d_inode->i_ino;
  370    buffer.found = 0;
  371    buffer.sequence = 0;
- 372    while (1) {
  373       int old_seq = buffer.sequence;
  374 
  375       error = vfs_readdir(file, filldir_one, &buffer);
  376 
- 377       if (error < 0)
 - 378          break;
  379 
  380       error = 0;
- 381       if (buffer.found)
 - 382          break;
  383       error = -ENOENT;
- 384       if (old_seq == buffer.sequence)
 - 385          break;
  386    }
  387 
  388 out_close:
  389    fput(file);
  390 out:
 - 391    return error;
  392 }
  393 
  394 
 
- 395 static struct dentry *export_iget(struct super_block *sb, unsigned long ino, __u32 generation)
  396 {
  397 
  398    /* iget isn't really right if the inode is currently unallocated!!
  399     * This should really all be done inside each filesystem
  400     *
  401     * ext2fs' read_inode has been strengthed to return a bad_inode if
  402     * the inode had been deleted.
  403     *
  404     * Currently we don't know the generation for parent directory, so
  405     * a generation of 0 means "accept any"
  406     */
  407    struct inode *inode;
  408    struct dentry *result;
- 409    if (ino == 0)
 - 410       return ERR_PTR(-ESTALE);
  411    inode = iget(sb, ino);
- 412    if (inode == NULL)
 - 413       return ERR_PTR(-ENOMEM);
  414    if (is_bad_inode(inode)
- 415        || (generation && inode->i_generation != generation)
 - 415   T || (_ && _)
 - 415   F || (T && T)
 - 415   F || (T && F)
 - 415   F || (F && _)
  416       ) {
  417       /* we didn't find the right inode.. */
    418       dprintk("fh_verify: Inode %lu, Bad count: %d %d or version  %u %u\n",
- 418   do-while (0)
  419          inode->i_ino,
  420          inode->i_nlink, atomic_read(&inode->i_count),
  421          inode->i_generation,