LCOV - code coverage report
Current view: top level - lkbce/fs/autofs4 - expire.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 286 286 100.0 %
Date: 2017-01-25 Functions: 12 12 100.0 %

          Line data    Source code
       1             : /* -*- c -*- --------------------------------------------------------------- *
       2             :  *
       3             :  * linux/fs/autofs/expire.c
       4             :  *
       5             :  *  Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
       6             :  *  Copyright 1999-2000 Jeremy Fitzhardinge <jeremy@goop.org>
       7             :  *  Copyright 2001-2006 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 "autofs_i.h"
      16             : 
      17           1 : static unsigned long now;
      18             : 
      19             : /* Check if a dentry can be expired */
      20             : static inline int autofs4_can_expire(struct dentry *dentry,
      21             :                                         unsigned long timeout, int do_now)
      22             : {
      23          44 :         struct autofs_info *ino = autofs4_dentry_ino(dentry);
      24          11 : 
      25             :         /* dentry in the process of being deleted */
      26          22 :         if (ino == NULL)
      27          11 :                 return 0;
      28             : 
      29             :         /* No point expiring a pending mount */
      30          22 :         if (ino->flags & AUTOFS_INF_PENDING)
      31          11 :                 return 0;
      32             : 
      33          22 :         if (!do_now) {
      34             :                 /* Too young to die */
      35          44 :                 if (!timeout || time_after(ino->last_used + timeout, now))
      36          11 :                         return 0;
      37             : 
      38             :                 /* update last_used here :-
      39             :                    - obviously makes sense if it is in use now
      40             :                    - less obviously, prevents rapid-fire expire
      41             :                      attempts if expire fails the first time */
      42          11 :                 ino->last_used = now;
      43             :         }
      44          11 :         return 1;
      45             : }
      46             : 
      47             : /* Check a mount point for busyness */
      48             : static int autofs4_mount_busy(struct vfsmount *mnt, struct dentry *dentry)
      49             : {
      50          18 :         struct dentry *top = dentry;
      51          27 :         struct path path = {.mnt = mnt, .dentry = dentry};
      52          18 :         int status = 1;
      53           9 : 
      54           9 :         DPRINTK("dentry %p %.*s",
      55           9 :                 dentry, (int)dentry->d_name.len, dentry->d_name.name);
      56           9 : 
      57          18 :         path_get(&path);
      58           9 : 
      59          36 :         if (!follow_down(&path))
      60          18 :                 goto done;
      61           9 : 
      62          36 :         if (is_autofs4_dentry(path.dentry)) {
      63          27 :                 struct autofs_sb_info *sbi = autofs4_sbi(path.dentry->d_sb);
      64             : 
      65             :                 /* This is an autofs submount, we can't expire it */
      66          36 :                 if (autofs_type_indirect(sbi->type))
      67           9 :                         goto done;
      68             : 
      69             :                 /*
      70             :                  * Otherwise it's an offset mount and we need to check
      71             :                  * if we can umount its mount, if there is one.
      72             :                  */
      73          36 :                 if (!d_mountpoint(path.dentry)) {
      74           9 :                         status = 0;
      75           9 :                         goto done;
      76             :                 }
      77             :         }
      78             : 
      79             :         /* Update the expiry counter if fs is busy */
      80          54 :         if (!may_umount_tree(path.mnt)) {
      81          45 :                 struct autofs_info *ino = autofs4_dentry_ino(top);
      82           9 :                 ino->last_used = jiffies;
      83           9 :                 goto done;
      84             :         }
      85             : 
      86          18 :         status = 0;
      87          18 : done:
      88             :         DPRINTK("returning = %d", status);
      89          45 :         path_put(&path);
      90          45 :         return status;
      91             : }
      92             : 
      93             : /*
      94             :  * Calculate next entry in top down tree traversal.
      95             :  * From next_mnt in namespace.c - elegant.
      96             :  */
      97             : static struct dentry *next_dentry(struct dentry *p, struct dentry *root)
      98             : {
      99          24 :         struct list_head *next = p->d_subdirs.next;
     100          12 : 
     101          24 :         if (next == &p->d_subdirs) {
     102          12 :                 while (1) {
     103          24 :                         if (p == root)
     104          12 :                                 return NULL;
     105          12 :                         next = p->d_u.d_child.next;
     106          24 :                         if (next != &p->d_parent->d_subdirs)
     107          12 :                                 break;
     108          12 :                         p = p->d_parent;
     109          12 :                 }
     110          12 :         }
     111          48 :         return list_entry(next, struct dentry, d_u.d_child);
     112             : }
     113             : 
     114             : /*
     115             :  * Check a direct mount point for busyness.
     116             :  * Direct mounts have similar expiry semantics to tree mounts.
     117             :  * The tree is not busy iff no mountpoints are busy and there are no
     118             :  * autofs submounts.
     119             :  */
     120             : static int autofs4_direct_busy(struct vfsmount *mnt,
     121             :                                 struct dentry *top,
     122             :                                 unsigned long timeout,
     123           2 :                                 int do_now)
     124           2 : {
     125           2 :         DPRINTK("top %p %.*s",
     126           2 :                 top, (int) top->d_name.len, top->d_name.name);
     127             : 
     128             :         /* If it's busy update the expiry counters */
     129           6 :         if (!may_umount_tree(mnt)) {
     130           6 :                 struct autofs_info *ino = autofs4_dentry_ino(top);
     131           4 :                 if (ino)
     132           2 :                         ino->last_used = jiffies;
     133           2 :                 return 1;
     134             :         }
     135             : 
     136             :         /* Timeout of a direct mount is determined by its top dentry */
     137           8 :         if (!autofs4_can_expire(top, timeout, do_now))
     138           2 :                 return 1;
     139             : 
     140           2 :         return 0;
     141             : }
     142             : 
     143             : /* Check a directory tree of mount points for busyness
     144             :  * The tree is not busy iff no mountpoints are busy
     145             :  */
     146             : static int autofs4_tree_busy(struct vfsmount *mnt,
     147             :                              struct dentry *top,
     148             :                              unsigned long timeout,
     149           3 :                              int do_now)
     150           3 : {
     151          12 :         struct autofs_info *top_ino = autofs4_dentry_ino(top);
     152           3 :         struct dentry *p;
     153           3 : 
     154           3 :         DPRINTK("top %p %.*s",
     155           3 :                 top, (int)top->d_name.len, top->d_name.name);
     156           3 : 
     157           3 :         /* Negative dentry - give up */
     158          18 :         if (!simple_positive(top))
     159           6 :                 return 1;
     160           3 : 
     161           9 :         spin_lock(&dcache_lock);
     162          30 :         for (p = top; p; p = next_dentry(p, top)) {
     163           3 :                 /* Negative dentry - give up */
     164          21 :                 if (!simple_positive(p))
     165           3 :                         continue;
     166             : 
     167             :                 DPRINTK("dentry %p %.*s",
     168             :                         p, (int) p->d_name.len, p->d_name.name);
     169             : 
     170           9 :                 p = dget(p);
     171           6 :                 spin_unlock(&dcache_lock);
     172             : 
     173             :                 /*
     174             :                  * Is someone visiting anywhere in the subtree ?
     175             :                  * If there's no mount we need to check the usage
     176             :                  * count for the autofs dentry.
     177             :                  * If the fs is busy update the expiry counter.
     178             :                  */
     179          12 :                 if (d_mountpoint(p)) {
     180          24 :                         if (autofs4_mount_busy(mnt, p)) {
     181           3 :                                 top_ino->last_used = jiffies;
     182           3 :                                 dput(p);
     183           3 :                                 return 1;
     184             :                         }
     185             :                 } else {
     186           9 :                         struct autofs_info *ino = autofs4_dentry_ino(p);
     187           9 :                         unsigned int ino_count = atomic_read(&ino->count);
     188             : 
     189             :                         /*
     190             :                          * Clean stale dentries below that have not been
     191             :                          * invalidated after a mount fail during lookup
     192             :                          */
     193           3 :                         d_invalidate(p);
     194             : 
     195             :                         /* allow for dget above and top is already dgot */
     196           6 :                         if (p == top)
     197           3 :                                 ino_count += 2;
     198             :                         else
     199           3 :                                 ino_count++;
     200             : 
     201          12 :                         if (atomic_read(&p->d_count) > ino_count) {
     202           3 :                                 top_ino->last_used = jiffies;
     203           3 :                                 dput(p);
     204           3 :                                 return 1;
     205             :                         }
     206             :                 }
     207           6 :                 dput(p);
     208          12 :                 spin_lock(&dcache_lock);
     209             :         }
     210           9 :         spin_unlock(&dcache_lock);
     211             : 
     212             :         /* Timeout of a tree mount is ultimately determined by its top dentry */
     213          12 :         if (!autofs4_can_expire(top, timeout, do_now))
     214           3 :                 return 1;
     215             : 
     216           3 :         return 0;
     217             : }
     218             : 
     219             : static struct dentry *autofs4_check_leaves(struct vfsmount *mnt,
     220             :                                            struct dentry *parent,
     221             :                                            unsigned long timeout,
     222           3 :                                            int do_now)
     223           3 : {
     224           3 :         struct dentry *p;
     225           3 : 
     226           3 :         DPRINTK("parent %p %.*s",
     227             :                 parent, (int)parent->d_name.len, parent->d_name.name);
     228             : 
     229           6 :         spin_lock(&dcache_lock);
     230          30 :         for (p = parent; p; p = next_dentry(p, parent)) {
     231           3 :                 /* Negative dentry - give up */
     232          21 :                 if (!simple_positive(p))
     233           3 :                         continue;
     234             : 
     235             :                 DPRINTK("dentry %p %.*s",
     236             :                         p, (int) p->d_name.len, p->d_name.name);
     237             : 
     238           9 :                 p = dget(p);
     239           6 :                 spin_unlock(&dcache_lock);
     240             : 
     241          12 :                 if (d_mountpoint(p)) {
     242             :                         /* Can we umount this guy */
     243          24 :                         if (autofs4_mount_busy(mnt, p))
     244           3 :                                 goto cont;
     245             : 
     246             :                         /* Can we expire this guy */
     247          12 :                         if (autofs4_can_expire(p, timeout, do_now))
     248           3 :                                 return p;
     249             :                 }
     250             : cont:
     251           9 :                 dput(p);
     252          18 :                 spin_lock(&dcache_lock);
     253             :         }
     254           9 :         spin_unlock(&dcache_lock);
     255           9 :         return NULL;
     256             : }
     257             : 
     258             : /* Check if we can expire a direct mount (possibly a tree) */
     259             : struct dentry *autofs4_expire_direct(struct super_block *sb,
     260             :                                      struct vfsmount *mnt,
     261             :                                      struct autofs_sb_info *sbi,
     262           2 :                                      int how)
     263           2 : {
     264           2 :         unsigned long timeout;
     265          10 :         struct dentry *root = dget(sb->s_root);
     266           4 :         int do_now = how & AUTOFS_EXP_IMMEDIATE;
     267           2 : 
     268           6 :         if (!root)
     269           4 :                 return NULL;
     270             : 
     271           2 :         now = jiffies;
     272           2 :         timeout = sbi->exp_timeout;
     273             : 
     274           4 :         spin_lock(&sbi->fs_lock);
     275          10 :         if (!autofs4_direct_busy(mnt, root, timeout, do_now)) {
     276           6 :                 struct autofs_info *ino = autofs4_dentry_ino(root);
     277           8 :                 if (d_mountpoint(root)) {
     278           2 :                         ino->flags |= AUTOFS_INF_MOUNTPOINT;
     279           2 :                         root->d_mounted--;
     280             :                 }
     281           2 :                 ino->flags |= AUTOFS_INF_EXPIRING;
     282           6 :                 autofs4_add_expiring(root);
     283           4 :                 init_completion(&ino->expire_complete);
     284           4 :                 spin_unlock(&sbi->fs_lock);
     285           2 :                 return root;
     286             :         }
     287           4 :         spin_unlock(&sbi->fs_lock);
     288           2 :         dput(root);
     289             : 
     290           2 :         return NULL;
     291             : }
     292             : 
     293             : /*
     294             :  * Find an eligible tree to time-out
     295             :  * A tree is eligible if :-
     296             :  *  - it is unused by any user process
     297             :  *  - it has been unused for exp_timeout time
     298             :  */
     299             : struct dentry *autofs4_expire_indirect(struct super_block *sb,
     300             :                                        struct vfsmount *mnt,
     301             :                                        struct autofs_sb_info *sbi,
     302           3 :                                        int how)
     303           3 : {
     304           3 :         unsigned long timeout;
     305           6 :         struct dentry *root = sb->s_root;
     306           6 :         struct dentry *expired = NULL;
     307           3 :         struct list_head *next;
     308           6 :         int do_now = how & AUTOFS_EXP_IMMEDIATE;
     309           6 :         int exp_leaves = how & AUTOFS_EXP_LEAVES;
     310           3 :         struct autofs_info *ino;
     311           3 :         unsigned int ino_count;
     312           3 : 
     313           9 :         if (!root)
     314           6 :                 return NULL;
     315           3 : 
     316           6 :         now = jiffies;
     317           6 :         timeout = sbi->exp_timeout;
     318           3 : 
     319           9 :         spin_lock(&dcache_lock);
     320           6 :         next = root->d_subdirs.next;
     321           3 : 
     322           3 :         /* On exit from the loop expire is set to a dgot dentry
     323           3 :          * to expire or it's NULL */
     324           9 :         while ( next != &root->d_subdirs ) {
     325           9 :                 struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child);
     326           3 : 
     327             :                 /* Negative dentry - give up */
     328          15 :                 if (!simple_positive(dentry)) {
     329           3 :                         next = next->next;
     330           3 :                         continue;
     331             :                 }
     332             : 
     333           9 :                 dentry = dget(dentry);
     334           6 :                 spin_unlock(&dcache_lock);
     335             : 
     336           6 :                 spin_lock(&sbi->fs_lock);
     337           6 :                 ino = autofs4_dentry_ino(dentry);
     338             : 
     339             :                 /*
     340             :                  * Case 1: (i) indirect mount or top level pseudo direct mount
     341             :                  *         (autofs-4.1).
     342             :                  *         (ii) indirect mount with offset mount, check the "/"
     343             :                  *         offset (autofs-5.0+).
     344             :                  */
     345          12 :                 if (d_mountpoint(dentry)) {
     346             :                         DPRINTK("checking mountpoint %p %.*s",
     347             :                                 dentry, (int)dentry->d_name.len, dentry->d_name.name);
     348             : 
     349             :                         /* Path walk currently on this dentry? */
     350           9 :                         ino_count = atomic_read(&ino->count) + 2;
     351          12 :                         if (atomic_read(&dentry->d_count) > ino_count)
     352           3 :                                 goto next;
     353             : 
     354             :                         /* Can we umount this guy */
     355          24 :                         if (autofs4_mount_busy(mnt, dentry))
     356           3 :                                 goto next;
     357             : 
     358             :                         /* Can we expire this guy */
     359          12 :                         if (autofs4_can_expire(dentry, timeout, do_now)) {
     360           3 :                                 expired = dentry;
     361           3 :                                 goto found;
     362             :                         }
     363           3 :                         goto next;
     364             :                 }
     365             : 
     366           9 :                 if (simple_empty(dentry))
     367           3 :                         goto next;
     368             : 
     369             :                 /* Case 2: tree mount, expire iff entire tree is not busy */
     370           6 :                 if (!exp_leaves) {
     371             :                         /* Path walk currently on this dentry? */
     372           9 :                         ino_count = atomic_read(&ino->count) + 1;
     373          12 :                         if (atomic_read(&dentry->d_count) > ino_count)
     374           3 :                                 goto next;
     375             : 
     376          21 :                         if (!autofs4_tree_busy(mnt, dentry, timeout, do_now)) {
     377           3 :                                 expired = dentry;
     378           3 :                                 goto found;
     379             :                         }
     380             :                 /*
     381             :                  * Case 3: pseudo direct mount, expire individual leaves
     382             :                  *         (autofs-4.1).
     383             :                  */
     384             :                 } else {
     385             :                         /* Path walk currently on this dentry? */
     386           9 :                         ino_count = atomic_read(&ino->count) + 1;
     387          12 :                         if (atomic_read(&dentry->d_count) > ino_count)
     388           3 :                                 goto next;
     389             : 
     390           9 :                         expired = autofs4_check_leaves(mnt, dentry, timeout, do_now);
     391           6 :                         if (expired) {
     392           3 :                                 dput(dentry);
     393           3 :                                 goto found;
     394             :                         }
     395             :                 }
     396             : next:
     397          48 :                 spin_unlock(&sbi->fs_lock);
     398           9 :                 dput(dentry);
     399           6 :                 spin_lock(&dcache_lock);
     400           3 :                 next = next->next;
     401             :         }
     402           9 :         spin_unlock(&dcache_lock);
     403           3 :         return NULL;
     404           9 : 
     405             : found:
     406             :         DPRINTK("returning %p %.*s",
     407             :                 expired, (int)expired->d_name.len, expired->d_name.name);
     408          18 :         ino = autofs4_dentry_ino(expired);
     409           3 :         ino->flags |= AUTOFS_INF_EXPIRING;
     410           9 :         autofs4_add_expiring(expired);
     411           6 :         init_completion(&ino->expire_complete);
     412           6 :         spin_unlock(&sbi->fs_lock);
     413           6 :         spin_lock(&dcache_lock);
     414           6 :         list_move(&expired->d_parent->d_subdirs, &expired->d_u.d_child);
     415           6 :         spin_unlock(&dcache_lock);
     416           3 :         return expired;
     417             : }
     418             : 
     419             : int autofs4_expire_wait(struct dentry *dentry)
     420             : {
     421           8 :         struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
     422           8 :         struct autofs_info *ino = autofs4_dentry_ino(dentry);
     423           2 :         int status;
     424           2 : 
     425           2 :         /* Block on any pending expire */
     426           6 :         spin_lock(&sbi->fs_lock);
     427           4 :         if (ino->flags & AUTOFS_INF_EXPIRING) {
     428           4 :                 spin_unlock(&sbi->fs_lock);
     429             : 
     430             :                 DPRINTK("waiting for expire %p name=%.*s",
     431             :                          dentry, dentry->d_name.len, dentry->d_name.name);
     432             : 
     433          26 :                 status = autofs4_wait(sbi, dentry, NFY_NONE);
     434           2 :                 wait_for_completion(&ino->expire_complete);
     435             : 
     436             :                 DPRINTK("expire done status=%d", status);
     437             : 
     438          12 :                 if (d_unhashed(dentry) && IS_DEADDIR(dentry->d_inode))
     439           2 :                         return -EAGAIN;
     440             : 
     441           2 :                 return status;
     442             :         }
     443           4 :         spin_unlock(&sbi->fs_lock);
     444             : 
     445           2 :         return 0;
     446             : }
     447             : 
     448             : /* Perform an expiry operation */
     449             : int autofs4_expire_run(struct super_block *sb,
     450             :                       struct vfsmount *mnt,
     451             :                       struct autofs_sb_info *sbi,
     452           1 :                       struct autofs_packet_expire __user *pkt_p)
     453           1 : {
     454           1 :         struct autofs_packet_expire pkt;
     455           1 :         struct autofs_info *ino;
     456           1 :         struct dentry *dentry;
     457           1 :         int ret = 0;
     458             : 
     459           1 :         memset(&pkt,0,sizeof pkt);
     460             : 
     461           1 :         pkt.hdr.proto_version = sbi->version;
     462           1 :         pkt.hdr.type = autofs_ptype_expire;
     463             : 
     464           6 :         if ((dentry = autofs4_expire_indirect(sb, mnt, sbi, 0)) == NULL)
     465           1 :                 return -EAGAIN;
     466             : 
     467           1 :         pkt.len = dentry->d_name.len;
     468           1 :         memcpy(pkt.name, dentry->d_name.name, pkt.len);
     469           1 :         pkt.name[pkt.len] = '\0';
     470           1 :         dput(dentry);
     471             : 
     472           4 :         if ( copy_to_user(pkt_p, &pkt, sizeof(struct autofs_packet_expire)) )
     473           1 :                 ret = -EFAULT;
     474             : 
     475           2 :         spin_lock(&sbi->fs_lock);
     476           2 :         ino = autofs4_dentry_ino(dentry);
     477           1 :         ino->flags &= ~AUTOFS_INF_EXPIRING;
     478           3 :         autofs4_del_expiring(dentry);
     479           1 :         complete_all(&ino->expire_complete);
     480           2 :         spin_unlock(&sbi->fs_lock);
     481             : 
     482           1 :         return ret;
     483             : }
     484             : 
     485             : int autofs4_do_expire_multi(struct super_block *sb, struct vfsmount *mnt,
     486             :                             struct autofs_sb_info *sbi, int when)
     487             : {
     488           2 :         struct dentry *dentry;
     489           4 :         int ret = -EAGAIN;
     490           2 : 
     491          10 :         if (autofs_type_trigger(sbi->type))
     492          10 :                 dentry = autofs4_expire_direct(sb, mnt, sbi, when);
     493             :         else
     494           8 :                 dentry = autofs4_expire_indirect(sb, mnt, sbi, when);
     495             : 
     496           8 :         if (dentry) {
     497          10 :                 struct autofs_info *ino = autofs4_dentry_ino(dentry);
     498             : 
     499             :                 /* This is synchronous because it makes the daemon a
     500             :                    little easier */
     501          26 :                 ret = autofs4_wait(sbi, dentry, NFY_EXPIRE);
     502             : 
     503           4 :                 spin_lock(&sbi->fs_lock);
     504           4 :                 if (ino->flags & AUTOFS_INF_MOUNTPOINT) {
     505           2 :                         sb->s_root->d_mounted++;
     506           2 :                         ino->flags &= ~AUTOFS_INF_MOUNTPOINT;
     507             :                 }
     508           2 :                 ino->flags &= ~AUTOFS_INF_EXPIRING;
     509           6 :                 autofs4_del_expiring(dentry);
     510           2 :                 complete_all(&ino->expire_complete);
     511           4 :                 spin_unlock(&sbi->fs_lock);
     512           2 :                 dput(dentry);
     513             :         }
     514             : 
     515           6 :         return ret;
     516             : }
     517             : 
     518             : /* Call repeatedly until it returns -EAGAIN, meaning there's nothing
     519             :    more to be done */
     520             : int autofs4_expire_multi(struct super_block *sb, struct vfsmount *mnt,
     521             :                         struct autofs_sb_info *sbi, int __user *arg)
     522             : {
     523           2 :         int do_now = 0;
     524           1 : 
     525          14 :         if (arg && get_user(do_now, arg))
     526           3 :                 return -EFAULT;
     527             : 
     528           9 :         return autofs4_do_expire_multi(sb, mnt, sbi, do_now);
     529             : }
     530             : 

Generated by: LCOV version 1.10