LCOV - code coverage report
Current view: top level - fs/autofs - expire.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 7 218 3.2 %
Date: 2022-03-28 16:04:14 Functions: 1 12 8.3 %
Branches: 3 178 1.7 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-or-later
       2                 :            : /*
       3                 :            :  * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
       4                 :            :  * Copyright 1999-2000 Jeremy Fitzhardinge <jeremy@goop.org>
       5                 :            :  * Copyright 2001-2006 Ian Kent <raven@themaw.net>
       6                 :            :  */
       7                 :            : 
       8                 :            : #include "autofs_i.h"
       9                 :            : 
      10                 :            : /* Check if a dentry can be expired */
      11                 :          0 : static inline int autofs_can_expire(struct dentry *dentry,
      12                 :            :                                     unsigned long timeout, unsigned int how)
      13                 :            : {
      14                 :          0 :         struct autofs_info *ino = autofs_dentry_ino(dentry);
      15                 :            : 
      16                 :            :         /* dentry in the process of being deleted */
      17   [ #  #  #  #  :          0 :         if (ino == NULL)
          #  #  #  #  #  
                      # ]
      18                 :            :                 return 0;
      19                 :            : 
      20   [ #  #  #  #  :          0 :         if (!(how & AUTOFS_EXP_IMMEDIATE)) {
          #  #  #  #  #  
                      # ]
      21                 :            :                 /* Too young to die */
      22   [ #  #  #  #  :          0 :                 if (!timeout || time_after(ino->last_used + timeout, jiffies))
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
      23                 :            :                         return 0;
      24                 :            :         }
      25                 :            :         return 1;
      26                 :            : }
      27                 :            : 
      28                 :            : /* Check a mount point for busyness */
      29                 :          0 : static int autofs_mount_busy(struct vfsmount *mnt,
      30                 :            :                              struct dentry *dentry, unsigned int how)
      31                 :            : {
      32                 :          0 :         struct dentry *top = dentry;
      33                 :          0 :         struct path path = {.mnt = mnt, .dentry = dentry};
      34                 :          0 :         int status = 1;
      35                 :            : 
      36                 :          0 :         pr_debug("dentry %p %pd\n", dentry, dentry);
      37                 :            : 
      38                 :          0 :         path_get(&path);
      39                 :            : 
      40         [ #  # ]:          0 :         if (!follow_down_one(&path))
      41                 :          0 :                 goto done;
      42                 :            : 
      43         [ #  # ]:          0 :         if (is_autofs_dentry(path.dentry)) {
      44         [ #  # ]:          0 :                 struct autofs_sb_info *sbi = autofs_sbi(path.dentry->d_sb);
      45                 :            : 
      46                 :            :                 /* This is an autofs submount, we can't expire it */
      47         [ #  # ]:          0 :                 if (autofs_type_indirect(sbi->type))
      48                 :          0 :                         goto done;
      49                 :            :         }
      50                 :            : 
      51                 :            :         /* Not a submount, has a forced expire been requested */
      52         [ #  # ]:          0 :         if (how & AUTOFS_EXP_FORCED) {
      53                 :          0 :                 status = 0;
      54                 :          0 :                 goto done;
      55                 :            :         }
      56                 :            : 
      57                 :            :         /* Update the expiry counter if fs is busy */
      58         [ #  # ]:          0 :         if (!may_umount_tree(path.mnt)) {
      59                 :          0 :                 struct autofs_info *ino;
      60                 :            : 
      61                 :          0 :                 ino = autofs_dentry_ino(top);
      62                 :          0 :                 ino->last_used = jiffies;
      63                 :          0 :                 goto done;
      64                 :            :         }
      65                 :            : 
      66                 :            :         status = 0;
      67                 :          0 : done:
      68                 :          0 :         pr_debug("returning = %d\n", status);
      69                 :          0 :         path_put(&path);
      70                 :          0 :         return status;
      71                 :            : }
      72                 :            : 
      73                 :            : /* p->d_lock held */
      74                 :          0 : static struct dentry *positive_after(struct dentry *p, struct dentry *child)
      75                 :            : {
      76         [ #  # ]:          0 :         if (child)
      77                 :          0 :                 child = list_next_entry(child, d_child);
      78                 :            :         else
      79                 :          0 :                 child = list_first_entry(&p->d_subdirs, struct dentry, d_child);
      80                 :            : 
      81         [ #  # ]:          0 :         list_for_each_entry_from(child, &p->d_subdirs, d_child) {
      82                 :          0 :                 spin_lock_nested(&child->d_lock, DENTRY_D_LOCK_NESTED);
      83         [ #  # ]:          0 :                 if (simple_positive(child)) {
      84         [ #  # ]:          0 :                         dget_dlock(child);
      85                 :          0 :                         spin_unlock(&child->d_lock);
      86                 :          0 :                         return child;
      87                 :            :                 }
      88                 :          0 :                 spin_unlock(&child->d_lock);
      89                 :            :         }
      90                 :            : 
      91                 :            :         return NULL;
      92                 :            : }
      93                 :            : 
      94                 :            : /*
      95                 :            :  * Calculate and dget next entry in the subdirs list under root.
      96                 :            :  */
      97                 :          0 : static struct dentry *get_next_positive_subdir(struct dentry *prev,
      98                 :            :                                                struct dentry *root)
      99                 :            : {
     100                 :          0 :         struct autofs_sb_info *sbi = autofs_sbi(root->d_sb);
     101                 :          0 :         struct dentry *q;
     102                 :            : 
     103                 :          0 :         spin_lock(&sbi->lookup_lock);
     104                 :          0 :         spin_lock(&root->d_lock);
     105                 :          0 :         q = positive_after(root, prev);
     106                 :          0 :         spin_unlock(&root->d_lock);
     107                 :          0 :         spin_unlock(&sbi->lookup_lock);
     108                 :          0 :         dput(prev);
     109                 :          0 :         return q;
     110                 :            : }
     111                 :            : 
     112                 :            : /*
     113                 :            :  * Calculate and dget next entry in top down tree traversal.
     114                 :            :  */
     115                 :          0 : static struct dentry *get_next_positive_dentry(struct dentry *prev,
     116                 :            :                                                struct dentry *root)
     117                 :            : {
     118         [ #  # ]:          0 :         struct autofs_sb_info *sbi = autofs_sbi(root->d_sb);
     119                 :          0 :         struct dentry *p = prev, *ret = NULL, *d = NULL;
     120                 :            : 
     121         [ #  # ]:          0 :         if (prev == NULL)
     122         [ #  # ]:          0 :                 return dget(root);
     123                 :            : 
     124                 :          0 :         spin_lock(&sbi->lookup_lock);
     125                 :          0 :         spin_lock(&p->d_lock);
     126                 :          0 :         while (1) {
     127                 :          0 :                 struct dentry *parent;
     128                 :            : 
     129                 :          0 :                 ret = positive_after(p, d);
     130         [ #  # ]:          0 :                 if (ret || p == root)
     131                 :            :                         break;
     132                 :          0 :                 parent = p->d_parent;
     133                 :          0 :                 spin_unlock(&p->d_lock);
     134                 :          0 :                 spin_lock(&parent->d_lock);
     135                 :          0 :                 d = p;
     136                 :          0 :                 p = parent;
     137                 :            :         }
     138                 :          0 :         spin_unlock(&p->d_lock);
     139                 :          0 :         spin_unlock(&sbi->lookup_lock);
     140                 :          0 :         dput(prev);
     141                 :          0 :         return ret;
     142                 :            : }
     143                 :            : 
     144                 :            : /*
     145                 :            :  * Check a direct mount point for busyness.
     146                 :            :  * Direct mounts have similar expiry semantics to tree mounts.
     147                 :            :  * The tree is not busy iff no mountpoints are busy and there are no
     148                 :            :  * autofs submounts.
     149                 :            :  */
     150                 :          0 : static int autofs_direct_busy(struct vfsmount *mnt,
     151                 :            :                               struct dentry *top,
     152                 :            :                               unsigned long timeout,
     153                 :            :                               unsigned int how)
     154                 :            : {
     155                 :          0 :         pr_debug("top %p %pd\n", top, top);
     156                 :            : 
     157                 :            :         /* Forced expire, user space handles busy mounts */
     158         [ #  # ]:          0 :         if (how & AUTOFS_EXP_FORCED)
     159                 :            :                 return 0;
     160                 :            : 
     161                 :            :         /* If it's busy update the expiry counters */
     162         [ #  # ]:          0 :         if (!may_umount_tree(mnt)) {
     163                 :          0 :                 struct autofs_info *ino;
     164                 :            : 
     165         [ #  # ]:          0 :                 ino = autofs_dentry_ino(top);
     166         [ #  # ]:          0 :                 if (ino)
     167                 :          0 :                         ino->last_used = jiffies;
     168                 :          0 :                 return 1;
     169                 :            :         }
     170                 :            : 
     171                 :            :         /* Timeout of a direct mount is determined by its top dentry */
     172         [ #  # ]:          0 :         if (!autofs_can_expire(top, timeout, how))
     173                 :          0 :                 return 1;
     174                 :            : 
     175                 :            :         return 0;
     176                 :            : }
     177                 :            : 
     178                 :            : /*
     179                 :            :  * Check a directory tree of mount points for busyness
     180                 :            :  * The tree is not busy iff no mountpoints are busy
     181                 :            :  */
     182                 :          0 : static int autofs_tree_busy(struct vfsmount *mnt,
     183                 :            :                             struct dentry *top,
     184                 :            :                             unsigned long timeout,
     185                 :            :                             unsigned int how)
     186                 :            : {
     187         [ #  # ]:          0 :         struct autofs_info *top_ino = autofs_dentry_ino(top);
     188                 :          0 :         struct dentry *p;
     189                 :            : 
     190                 :          0 :         pr_debug("top %p %pd\n", top, top);
     191                 :            : 
     192                 :            :         /* Negative dentry - give up */
     193         [ #  # ]:          0 :         if (!simple_positive(top))
     194                 :            :                 return 1;
     195                 :            : 
     196                 :            :         p = NULL;
     197         [ #  # ]:          0 :         while ((p = get_next_positive_dentry(p, top))) {
     198                 :          0 :                 pr_debug("dentry %p %pd\n", p, p);
     199                 :            : 
     200                 :            :                 /*
     201                 :            :                  * Is someone visiting anywhere in the subtree ?
     202                 :            :                  * If there's no mount we need to check the usage
     203                 :            :                  * count for the autofs dentry.
     204                 :            :                  * If the fs is busy update the expiry counter.
     205                 :            :                  */
     206         [ #  # ]:          0 :                 if (d_mountpoint(p)) {
     207         [ #  # ]:          0 :                         if (autofs_mount_busy(mnt, p, how)) {
     208                 :          0 :                                 top_ino->last_used = jiffies;
     209                 :          0 :                                 dput(p);
     210                 :          0 :                                 return 1;
     211                 :            :                         }
     212                 :            :                 } else {
     213         [ #  # ]:          0 :                         struct autofs_info *ino = autofs_dentry_ino(p);
     214         [ #  # ]:          0 :                         unsigned int ino_count = READ_ONCE(ino->count);
     215                 :            : 
     216                 :            :                         /* allow for dget above and top is already dgot */
     217         [ #  # ]:          0 :                         if (p == top)
     218                 :          0 :                                 ino_count += 2;
     219                 :            :                         else
     220                 :          0 :                                 ino_count++;
     221                 :            : 
     222         [ #  # ]:          0 :                         if (d_count(p) > ino_count) {
     223                 :          0 :                                 top_ino->last_used = jiffies;
     224                 :          0 :                                 dput(p);
     225                 :          0 :                                 return 1;
     226                 :            :                         }
     227                 :            :                 }
     228                 :            :         }
     229                 :            : 
     230                 :            :         /* Forced expire, user space handles busy mounts */
     231         [ #  # ]:          0 :         if (how & AUTOFS_EXP_FORCED)
     232                 :            :                 return 0;
     233                 :            : 
     234                 :            :         /* Timeout of a tree mount is ultimately determined by its top dentry */
     235         [ #  # ]:          0 :         if (!autofs_can_expire(top, timeout, how))
     236                 :          0 :                 return 1;
     237                 :            : 
     238                 :            :         return 0;
     239                 :            : }
     240                 :            : 
     241                 :          0 : static struct dentry *autofs_check_leaves(struct vfsmount *mnt,
     242                 :            :                                           struct dentry *parent,
     243                 :            :                                           unsigned long timeout,
     244                 :            :                                           unsigned int how)
     245                 :            : {
     246                 :          0 :         struct dentry *p;
     247                 :            : 
     248                 :          0 :         pr_debug("parent %p %pd\n", parent, parent);
     249                 :            : 
     250                 :          0 :         p = NULL;
     251         [ #  # ]:          0 :         while ((p = get_next_positive_dentry(p, parent))) {
     252                 :          0 :                 pr_debug("dentry %p %pd\n", p, p);
     253                 :            : 
     254         [ #  # ]:          0 :                 if (d_mountpoint(p)) {
     255                 :            :                         /* Can we umount this guy */
     256         [ #  # ]:          0 :                         if (autofs_mount_busy(mnt, p, how))
     257                 :          0 :                                 continue;
     258                 :            : 
     259                 :            :                         /* This isn't a submount so if a forced expire
     260                 :            :                          * has been requested, user space handles busy
     261                 :            :                          * mounts */
     262         [ #  # ]:          0 :                         if (how & AUTOFS_EXP_FORCED)
     263                 :          0 :                                 return p;
     264                 :            : 
     265                 :            :                         /* Can we expire this guy */
     266         [ #  # ]:          0 :                         if (autofs_can_expire(p, timeout, how))
     267                 :          0 :                                 return p;
     268                 :            :                 }
     269                 :            :         }
     270                 :            :         return NULL;
     271                 :            : }
     272                 :            : 
     273                 :            : /* Check if we can expire a direct mount (possibly a tree) */
     274                 :            : static struct dentry *autofs_expire_direct(struct super_block *sb,
     275                 :            :                                            struct vfsmount *mnt,
     276                 :            :                                            struct autofs_sb_info *sbi,
     277                 :            :                                            unsigned int how)
     278                 :            : {
     279                 :            :         struct dentry *root = dget(sb->s_root);
     280                 :            :         struct autofs_info *ino;
     281                 :            :         unsigned long timeout;
     282                 :            : 
     283                 :            :         if (!root)
     284                 :            :                 return NULL;
     285                 :            : 
     286                 :            :         timeout = sbi->exp_timeout;
     287                 :            : 
     288                 :            :         if (!autofs_direct_busy(mnt, root, timeout, how)) {
     289                 :            :                 spin_lock(&sbi->fs_lock);
     290                 :            :                 ino = autofs_dentry_ino(root);
     291                 :            :                 /* No point expiring a pending mount */
     292                 :            :                 if (ino->flags & AUTOFS_INF_PENDING) {
     293                 :            :                         spin_unlock(&sbi->fs_lock);
     294                 :            :                         goto out;
     295                 :            :                 }
     296                 :            :                 ino->flags |= AUTOFS_INF_WANT_EXPIRE;
     297                 :            :                 spin_unlock(&sbi->fs_lock);
     298                 :            :                 synchronize_rcu();
     299                 :            :                 if (!autofs_direct_busy(mnt, root, timeout, how)) {
     300                 :            :                         spin_lock(&sbi->fs_lock);
     301                 :            :                         ino->flags |= AUTOFS_INF_EXPIRING;
     302                 :            :                         init_completion(&ino->expire_complete);
     303                 :            :                         spin_unlock(&sbi->fs_lock);
     304                 :            :                         return root;
     305                 :            :                 }
     306                 :            :                 spin_lock(&sbi->fs_lock);
     307                 :            :                 ino->flags &= ~AUTOFS_INF_WANT_EXPIRE;
     308                 :            :                 spin_unlock(&sbi->fs_lock);
     309                 :            :         }
     310                 :            : out:
     311                 :            :         dput(root);
     312                 :            : 
     313                 :            :         return NULL;
     314                 :            : }
     315                 :            : 
     316                 :            : /* Check if 'dentry' should expire, or return a nearby
     317                 :            :  * dentry that is suitable.
     318                 :            :  * If returned dentry is different from arg dentry,
     319                 :            :  * then a dget() reference was taken, else not.
     320                 :            :  */
     321                 :          0 : static struct dentry *should_expire(struct dentry *dentry,
     322                 :            :                                     struct vfsmount *mnt,
     323                 :            :                                     unsigned long timeout,
     324                 :            :                                     unsigned int how)
     325                 :            : {
     326         [ #  # ]:          0 :         struct autofs_info *ino = autofs_dentry_ino(dentry);
     327                 :          0 :         unsigned int ino_count;
     328                 :            : 
     329                 :            :         /* No point expiring a pending mount */
     330         [ #  # ]:          0 :         if (ino->flags & AUTOFS_INF_PENDING)
     331                 :            :                 return NULL;
     332                 :            : 
     333                 :            :         /*
     334                 :            :          * Case 1: (i) indirect mount or top level pseudo direct mount
     335                 :            :          *         (autofs-4.1).
     336                 :            :          *         (ii) indirect mount with offset mount, check the "/"
     337                 :            :          *         offset (autofs-5.0+).
     338                 :            :          */
     339         [ #  # ]:          0 :         if (d_mountpoint(dentry)) {
     340                 :          0 :                 pr_debug("checking mountpoint %p %pd\n", dentry, dentry);
     341                 :            : 
     342                 :            :                 /* Can we umount this guy */
     343         [ #  # ]:          0 :                 if (autofs_mount_busy(mnt, dentry, how))
     344                 :            :                         return NULL;
     345                 :            : 
     346                 :            :                 /* This isn't a submount so if a forced expire
     347                 :            :                  * has been requested, user space handles busy
     348                 :            :                  * mounts */
     349         [ #  # ]:          0 :                 if (how & AUTOFS_EXP_FORCED)
     350                 :            :                         return dentry;
     351                 :            : 
     352                 :            :                 /* Can we expire this guy */
     353         [ #  # ]:          0 :                 if (autofs_can_expire(dentry, timeout, how))
     354                 :            :                         return dentry;
     355                 :          0 :                 return NULL;
     356                 :            :         }
     357                 :            : 
     358   [ #  #  #  # ]:          0 :         if (d_really_is_positive(dentry) && d_is_symlink(dentry)) {
     359                 :          0 :                 pr_debug("checking symlink %p %pd\n", dentry, dentry);
     360                 :            : 
     361                 :            :                 /* Forced expire, user space handles busy mounts */
     362         [ #  # ]:          0 :                 if (how & AUTOFS_EXP_FORCED)
     363                 :            :                         return dentry;
     364                 :            : 
     365                 :            :                 /*
     366                 :            :                  * A symlink can't be "busy" in the usual sense so
     367                 :            :                  * just check last used for expire timeout.
     368                 :            :                  */
     369         [ #  # ]:          0 :                 if (autofs_can_expire(dentry, timeout, how))
     370                 :            :                         return dentry;
     371                 :          0 :                 return NULL;
     372                 :            :         }
     373                 :            : 
     374         [ #  # ]:          0 :         if (simple_empty(dentry))
     375                 :            :                 return NULL;
     376                 :            : 
     377                 :            :         /* Case 2: tree mount, expire iff entire tree is not busy */
     378         [ #  # ]:          0 :         if (!(how & AUTOFS_EXP_LEAVES)) {
     379                 :            :                 /* Not a forced expire? */
     380         [ #  # ]:          0 :                 if (!(how & AUTOFS_EXP_FORCED)) {
     381                 :            :                         /* ref-walk currently on this dentry? */
     382         [ #  # ]:          0 :                         ino_count = READ_ONCE(ino->count) + 1;
     383         [ #  # ]:          0 :                         if (d_count(dentry) > ino_count)
     384                 :            :                                 return NULL;
     385                 :            :                 }
     386                 :            : 
     387         [ #  # ]:          0 :                 if (!autofs_tree_busy(mnt, dentry, timeout, how))
     388                 :          0 :                         return dentry;
     389                 :            :         /*
     390                 :            :          * Case 3: pseudo direct mount, expire individual leaves
     391                 :            :          *         (autofs-4.1).
     392                 :            :          */
     393                 :            :         } else {
     394                 :          0 :                 struct dentry *expired;
     395                 :            : 
     396                 :            :                 /* Not a forced expire? */
     397         [ #  # ]:          0 :                 if (!(how & AUTOFS_EXP_FORCED)) {
     398                 :            :                         /* ref-walk currently on this dentry? */
     399         [ #  # ]:          0 :                         ino_count = READ_ONCE(ino->count) + 1;
     400         [ #  # ]:          0 :                         if (d_count(dentry) > ino_count)
     401                 :            :                                 return NULL;
     402                 :            :                 }
     403                 :            : 
     404                 :          0 :                 expired = autofs_check_leaves(mnt, dentry, timeout, how);
     405         [ #  # ]:          0 :                 if (expired) {
     406         [ #  # ]:          0 :                         if (expired == dentry)
     407                 :          0 :                                 dput(dentry);
     408                 :          0 :                         return expired;
     409                 :            :                 }
     410                 :            :         }
     411                 :            :         return NULL;
     412                 :            : }
     413                 :            : 
     414                 :            : /*
     415                 :            :  * Find an eligible tree to time-out
     416                 :            :  * A tree is eligible if :-
     417                 :            :  *  - it is unused by any user process
     418                 :            :  *  - it has been unused for exp_timeout time
     419                 :            :  */
     420                 :            : static struct dentry *autofs_expire_indirect(struct super_block *sb,
     421                 :            :                                              struct vfsmount *mnt,
     422                 :            :                                              struct autofs_sb_info *sbi,
     423                 :            :                                              unsigned int how)
     424                 :            : {
     425                 :            :         unsigned long timeout;
     426                 :            :         struct dentry *root = sb->s_root;
     427                 :            :         struct dentry *dentry;
     428                 :            :         struct dentry *expired;
     429                 :            :         struct dentry *found;
     430                 :            :         struct autofs_info *ino;
     431                 :            : 
     432                 :            :         if (!root)
     433                 :            :                 return NULL;
     434                 :            : 
     435                 :            :         timeout = sbi->exp_timeout;
     436                 :            : 
     437                 :            :         dentry = NULL;
     438                 :            :         while ((dentry = get_next_positive_subdir(dentry, root))) {
     439                 :            :                 spin_lock(&sbi->fs_lock);
     440                 :            :                 ino = autofs_dentry_ino(dentry);
     441                 :            :                 if (ino->flags & AUTOFS_INF_WANT_EXPIRE) {
     442                 :            :                         spin_unlock(&sbi->fs_lock);
     443                 :            :                         continue;
     444                 :            :                 }
     445                 :            :                 spin_unlock(&sbi->fs_lock);
     446                 :            : 
     447                 :            :                 expired = should_expire(dentry, mnt, timeout, how);
     448                 :            :                 if (!expired)
     449                 :            :                         continue;
     450                 :            : 
     451                 :            :                 spin_lock(&sbi->fs_lock);
     452                 :            :                 ino = autofs_dentry_ino(expired);
     453                 :            :                 ino->flags |= AUTOFS_INF_WANT_EXPIRE;
     454                 :            :                 spin_unlock(&sbi->fs_lock);
     455                 :            :                 synchronize_rcu();
     456                 :            : 
     457                 :            :                 /* Make sure a reference is not taken on found if
     458                 :            :                  * things have changed.
     459                 :            :                  */
     460                 :            :                 how &= ~AUTOFS_EXP_LEAVES;
     461                 :            :                 found = should_expire(expired, mnt, timeout, how);
     462                 :            :                 if (found != expired) { // something has changed, continue
     463                 :            :                         dput(found);
     464                 :            :                         goto next;
     465                 :            :                 }
     466                 :            : 
     467                 :            :                 if (expired != dentry)
     468                 :            :                         dput(dentry);
     469                 :            : 
     470                 :            :                 spin_lock(&sbi->fs_lock);
     471                 :            :                 goto found;
     472                 :            : next:
     473                 :            :                 spin_lock(&sbi->fs_lock);
     474                 :            :                 ino->flags &= ~AUTOFS_INF_WANT_EXPIRE;
     475                 :            :                 spin_unlock(&sbi->fs_lock);
     476                 :            :                 if (expired != dentry)
     477                 :            :                         dput(expired);
     478                 :            :         }
     479                 :            :         return NULL;
     480                 :            : 
     481                 :            : found:
     482                 :            :         pr_debug("returning %p %pd\n", expired, expired);
     483                 :            :         ino->flags |= AUTOFS_INF_EXPIRING;
     484                 :            :         init_completion(&ino->expire_complete);
     485                 :            :         spin_unlock(&sbi->fs_lock);
     486                 :            :         return expired;
     487                 :            : }
     488                 :            : 
     489                 :         52 : int autofs_expire_wait(const struct path *path, int rcu_walk)
     490                 :            : {
     491                 :         52 :         struct dentry *dentry = path->dentry;
     492         [ -  + ]:         52 :         struct autofs_sb_info *sbi = autofs_sbi(dentry->d_sb);
     493         [ -  + ]:         52 :         struct autofs_info *ino = autofs_dentry_ino(dentry);
     494                 :         52 :         int status;
     495                 :         52 :         int state;
     496                 :            : 
     497                 :            :         /* Block on any pending expire */
     498         [ -  + ]:         52 :         if (!(ino->flags & AUTOFS_INF_WANT_EXPIRE))
     499                 :            :                 return 0;
     500         [ #  # ]:          0 :         if (rcu_walk)
     501                 :            :                 return -ECHILD;
     502                 :            : 
     503                 :          0 : retry:
     504                 :          0 :         spin_lock(&sbi->fs_lock);
     505                 :          0 :         state = ino->flags & (AUTOFS_INF_WANT_EXPIRE | AUTOFS_INF_EXPIRING);
     506         [ #  # ]:          0 :         if (state == AUTOFS_INF_WANT_EXPIRE) {
     507                 :          0 :                 spin_unlock(&sbi->fs_lock);
     508                 :            :                 /*
     509                 :            :                  * Possibly being selected for expire, wait until
     510                 :            :                  * it's selected or not.
     511                 :            :                  */
     512                 :          0 :                 schedule_timeout_uninterruptible(HZ/10);
     513                 :          0 :                 goto retry;
     514                 :            :         }
     515         [ #  # ]:          0 :         if (state & AUTOFS_INF_EXPIRING) {
     516                 :          0 :                 spin_unlock(&sbi->fs_lock);
     517                 :            : 
     518                 :          0 :                 pr_debug("waiting for expire %p name=%pd\n", dentry, dentry);
     519                 :            : 
     520                 :          0 :                 status = autofs_wait(sbi, path, NFY_NONE);
     521                 :          0 :                 wait_for_completion(&ino->expire_complete);
     522                 :            : 
     523                 :          0 :                 pr_debug("expire done status=%d\n", status);
     524                 :            : 
     525         [ #  # ]:          0 :                 if (d_unhashed(dentry))
     526                 :            :                         return -EAGAIN;
     527                 :            : 
     528                 :          0 :                 return status;
     529                 :            :         }
     530                 :          0 :         spin_unlock(&sbi->fs_lock);
     531                 :            : 
     532                 :          0 :         return 0;
     533                 :            : }
     534                 :            : 
     535                 :            : /* Perform an expiry operation */
     536                 :          0 : int autofs_expire_run(struct super_block *sb,
     537                 :            :                       struct vfsmount *mnt,
     538                 :            :                       struct autofs_sb_info *sbi,
     539                 :            :                       struct autofs_packet_expire __user *pkt_p)
     540                 :            : {
     541                 :          0 :         struct autofs_packet_expire pkt;
     542                 :          0 :         struct autofs_info *ino;
     543                 :          0 :         struct dentry *dentry;
     544                 :          0 :         int ret = 0;
     545                 :            : 
     546                 :          0 :         memset(&pkt, 0, sizeof(pkt));
     547                 :            : 
     548                 :          0 :         pkt.hdr.proto_version = sbi->version;
     549                 :          0 :         pkt.hdr.type = autofs_ptype_expire;
     550                 :            : 
     551                 :          0 :         dentry = autofs_expire_indirect(sb, mnt, sbi, 0);
     552         [ #  # ]:          0 :         if (!dentry)
     553                 :            :                 return -EAGAIN;
     554                 :            : 
     555                 :          0 :         pkt.len = dentry->d_name.len;
     556                 :          0 :         memcpy(pkt.name, dentry->d_name.name, pkt.len);
     557                 :          0 :         pkt.name[pkt.len] = '\0';
     558                 :            : 
     559         [ #  # ]:          0 :         if (copy_to_user(pkt_p, &pkt, sizeof(struct autofs_packet_expire)))
     560                 :          0 :                 ret = -EFAULT;
     561                 :            : 
     562                 :          0 :         spin_lock(&sbi->fs_lock);
     563                 :          0 :         ino = autofs_dentry_ino(dentry);
     564                 :            :         /* avoid rapid-fire expire attempts if expiry fails */
     565                 :          0 :         ino->last_used = jiffies;
     566                 :          0 :         ino->flags &= ~(AUTOFS_INF_EXPIRING|AUTOFS_INF_WANT_EXPIRE);
     567                 :          0 :         complete_all(&ino->expire_complete);
     568                 :          0 :         spin_unlock(&sbi->fs_lock);
     569                 :            : 
     570                 :          0 :         dput(dentry);
     571                 :            : 
     572                 :          0 :         return ret;
     573                 :            : }
     574                 :            : 
     575                 :          0 : int autofs_do_expire_multi(struct super_block *sb, struct vfsmount *mnt,
     576                 :            :                            struct autofs_sb_info *sbi, unsigned int how)
     577                 :            : {
     578                 :          0 :         struct dentry *dentry;
     579                 :          0 :         int ret = -EAGAIN;
     580                 :            : 
     581         [ #  # ]:          0 :         if (autofs_type_trigger(sbi->type))
     582                 :          0 :                 dentry = autofs_expire_direct(sb, mnt, sbi, how);
     583                 :            :         else
     584                 :          0 :                 dentry = autofs_expire_indirect(sb, mnt, sbi, how);
     585                 :            : 
     586         [ #  # ]:          0 :         if (dentry) {
     587                 :          0 :                 struct autofs_info *ino = autofs_dentry_ino(dentry);
     588                 :          0 :                 const struct path path = { .mnt = mnt, .dentry = dentry };
     589                 :            : 
     590                 :            :                 /* This is synchronous because it makes the daemon a
     591                 :            :                  * little easier
     592                 :            :                  */
     593                 :          0 :                 ret = autofs_wait(sbi, &path, NFY_EXPIRE);
     594                 :            : 
     595                 :          0 :                 spin_lock(&sbi->fs_lock);
     596                 :            :                 /* avoid rapid-fire expire attempts if expiry fails */
     597                 :          0 :                 ino->last_used = jiffies;
     598                 :          0 :                 ino->flags &= ~(AUTOFS_INF_EXPIRING|AUTOFS_INF_WANT_EXPIRE);
     599                 :          0 :                 complete_all(&ino->expire_complete);
     600                 :          0 :                 spin_unlock(&sbi->fs_lock);
     601                 :          0 :                 dput(dentry);
     602                 :            :         }
     603                 :            : 
     604                 :          0 :         return ret;
     605                 :            : }
     606                 :            : 
     607                 :            : /*
     608                 :            :  * Call repeatedly until it returns -EAGAIN, meaning there's nothing
     609                 :            :  * more to be done.
     610                 :            :  */
     611                 :          0 : int autofs_expire_multi(struct super_block *sb, struct vfsmount *mnt,
     612                 :            :                         struct autofs_sb_info *sbi, int __user *arg)
     613                 :            : {
     614                 :          0 :         unsigned int how = 0;
     615                 :            : 
     616   [ #  #  #  # ]:          0 :         if (arg && get_user(how, arg))
     617                 :            :                 return -EFAULT;
     618                 :            : 
     619                 :          0 :         return autofs_do_expire_multi(sb, mnt, sbi, how);
     620                 :            : }

Generated by: LCOV version 1.14