linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/6] autofs - fix inconsistent use of now variable
@ 2018-06-19  3:01 Ian Kent
  2018-06-19  3:02 ` [PATCH 2/6] autofs - fix clearing AUTOFS_EXP_LEAVES in autofs_expire_indirect() Ian Kent
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Ian Kent @ 2018-06-19  3:01 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-fsdevel, autofs mailing list, Kernel Mailing List

The global variable "now" in fs/autofs/expire.c is used in
an inconsistent way, sometimes using jiffies directly, and
sometimes using the "now" variable, and setting it isn't done
consistently either.

But the autofs dentry info last_used field is only updated
during path walks or during expire so jiffies can be used
directly and the global variable "now" removed.

Signed-off-by: Ian Kent <raven@themaw.net>
---
 fs/autofs/expire.c |   10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/fs/autofs/expire.c b/fs/autofs/expire.c
index b332d3f6e730..295feec10ea6 100644
--- a/fs/autofs/expire.c
+++ b/fs/autofs/expire.c
@@ -10,8 +10,6 @@
 
 #include "autofs_i.h"
 
-static unsigned long now;
-
 /* Check if a dentry can be expired */
 static inline int autofs_can_expire(struct dentry *dentry,
 				    unsigned long timeout, int do_now)
@@ -24,7 +22,7 @@ static inline int autofs_can_expire(struct dentry *dentry,
 
 	if (!do_now) {
 		/* Too young to die */
-		if (!timeout || time_after(ino->last_used + timeout, now))
+		if (!timeout || time_after(ino->last_used + timeout, jiffies))
 			return 0;
 	}
 	return 1;
@@ -307,7 +305,6 @@ struct dentry *autofs_expire_direct(struct super_block *sb,
 	if (!root)
 		return NULL;
 
-	now = jiffies;
 	timeout = sbi->exp_timeout;
 
 	if (!autofs_direct_busy(mnt, root, timeout, do_now)) {
@@ -442,7 +439,6 @@ struct dentry *autofs_expire_indirect(struct super_block *sb,
 	if (!root)
 		return NULL;
 
-	now = jiffies;
 	timeout = sbi->exp_timeout;
 
 	dentry = NULL;
@@ -575,7 +571,7 @@ int autofs_expire_run(struct super_block *sb,
 	spin_lock(&sbi->fs_lock);
 	ino = autofs_dentry_ino(dentry);
 	/* avoid rapid-fire expire attempts if expiry fails */
-	ino->last_used = now;
+	ino->last_used = jiffies;
 	ino->flags &= ~(AUTOFS_INF_EXPIRING|AUTOFS_INF_WANT_EXPIRE);
 	complete_all(&ino->expire_complete);
 	spin_unlock(&sbi->fs_lock);
@@ -605,7 +601,7 @@ int autofs_do_expire_multi(struct super_block *sb, struct vfsmount *mnt,
 
 		spin_lock(&sbi->fs_lock);
 		/* avoid rapid-fire expire attempts if expiry fails */
-		ino->last_used = now;
+		ino->last_used = jiffies;
 		ino->flags &= ~(AUTOFS_INF_EXPIRING|AUTOFS_INF_WANT_EXPIRE);
 		complete_all(&ino->expire_complete);
 		spin_unlock(&sbi->fs_lock);

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/6] autofs - fix clearing AUTOFS_EXP_LEAVES in autofs_expire_indirect()
  2018-06-19  3:01 [PATCH 1/6] autofs - fix inconsistent use of now variable Ian Kent
@ 2018-06-19  3:02 ` Ian Kent
  2018-06-19  3:02 ` [PATCH 3/6] autofs - make autofs_expire_direct() static Ian Kent
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Ian Kent @ 2018-06-19  3:02 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-fsdevel, autofs mailing list, Kernel Mailing List

The expire flag AUTOFS_EXP_LEAVES is cleared before the second
call to should_expire() in autofs_expire_indirect() but the
parameter passed in the second call is incorrect.

Fortunately AUTOFS_EXP_LEAVES expire flag has not been used for
a long time but might be needed in the future so fix it rather
than remove the expire leaves functionality.

Signed-off-by: Ian Kent <raven@themaw.net>
---
 fs/autofs/expire.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/autofs/expire.c b/fs/autofs/expire.c
index 295feec10ea6..41855cdc5630 100644
--- a/fs/autofs/expire.c
+++ b/fs/autofs/expire.c
@@ -467,7 +467,7 @@ struct dentry *autofs_expire_indirect(struct super_block *sb,
 		 * things have changed.
 		 */
 		flags &= ~AUTOFS_EXP_LEAVES;
-		found = should_expire(expired, mnt, timeout, how);
+		found = should_expire(expired, mnt, timeout, flags);
 		if (!found || found != expired)
 			/* Something has changed, continue */
 			goto next;

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 3/6] autofs - make autofs_expire_direct() static
  2018-06-19  3:01 [PATCH 1/6] autofs - fix inconsistent use of now variable Ian Kent
  2018-06-19  3:02 ` [PATCH 2/6] autofs - fix clearing AUTOFS_EXP_LEAVES in autofs_expire_indirect() Ian Kent
@ 2018-06-19  3:02 ` Ian Kent
  2018-06-19  3:02 ` [PATCH 4/6] autofs - make autofs_expire_indirect() static Ian Kent
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Ian Kent @ 2018-06-19  3:02 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-fsdevel, autofs mailing list, Kernel Mailing List

autofs_expire_direct() isn't used outside of fs/autofs/expire.c
so make it static.

Signed-off-by: Ian Kent <raven@themaw.net>
---
 fs/autofs/autofs_i.h |    3 ---
 fs/autofs/expire.c   |    8 ++++----
 2 files changed, 4 insertions(+), 7 deletions(-)

diff --git a/fs/autofs/autofs_i.h b/fs/autofs/autofs_i.h
index 9400a9f6318a..4192f8002f89 100644
--- a/fs/autofs/autofs_i.h
+++ b/fs/autofs/autofs_i.h
@@ -154,9 +154,6 @@ int autofs_do_expire_multi(struct super_block *sb, struct vfsmount *mnt,
 			   struct autofs_sb_info *sbi, int when);
 int autofs_expire_multi(struct super_block *, struct vfsmount *,
 			struct autofs_sb_info *, int __user *);
-struct dentry *autofs_expire_direct(struct super_block *sb,
-				    struct vfsmount *mnt,
-				    struct autofs_sb_info *sbi, int how);
 struct dentry *autofs_expire_indirect(struct super_block *sb,
 				      struct vfsmount *mnt,
 				      struct autofs_sb_info *sbi, int how);
diff --git a/fs/autofs/expire.c b/fs/autofs/expire.c
index 41855cdc5630..64e6eba2c628 100644
--- a/fs/autofs/expire.c
+++ b/fs/autofs/expire.c
@@ -292,10 +292,10 @@ static struct dentry *autofs_check_leaves(struct vfsmount *mnt,
 }
 
 /* Check if we can expire a direct mount (possibly a tree) */
-struct dentry *autofs_expire_direct(struct super_block *sb,
-				    struct vfsmount *mnt,
-				    struct autofs_sb_info *sbi,
-				    int how)
+static struct dentry *autofs_expire_direct(struct super_block *sb,
+					   struct vfsmount *mnt,
+					   struct autofs_sb_info *sbi,
+					   int how)
 {
 	unsigned long timeout;
 	struct dentry *root = dget(sb->s_root);

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 4/6] autofs - make autofs_expire_indirect() static
  2018-06-19  3:01 [PATCH 1/6] autofs - fix inconsistent use of now variable Ian Kent
  2018-06-19  3:02 ` [PATCH 2/6] autofs - fix clearing AUTOFS_EXP_LEAVES in autofs_expire_indirect() Ian Kent
  2018-06-19  3:02 ` [PATCH 3/6] autofs - make autofs_expire_direct() static Ian Kent
@ 2018-06-19  3:02 ` Ian Kent
  2018-06-19  3:02 ` [PATCH 5/6] autofs - make expire flags usage consistent with v5 params Ian Kent
  2018-06-19  3:02 ` [PATCH 6/6] autofs - add AUTOFS_EXP_FORCED flag Ian Kent
  4 siblings, 0 replies; 6+ messages in thread
From: Ian Kent @ 2018-06-19  3:02 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-fsdevel, autofs mailing list, Kernel Mailing List

autofs_expire_indirect() isn't used outside of fs/autofs/expire.c
so make it static.

Signed-off-by: Ian Kent <raven@themaw.net>
---
 fs/autofs/autofs_i.h |    3 ---
 fs/autofs/expire.c   |    8 ++++----
 2 files changed, 4 insertions(+), 7 deletions(-)

diff --git a/fs/autofs/autofs_i.h b/fs/autofs/autofs_i.h
index 4192f8002f89..b1f70bc45ca3 100644
--- a/fs/autofs/autofs_i.h
+++ b/fs/autofs/autofs_i.h
@@ -154,9 +154,6 @@ int autofs_do_expire_multi(struct super_block *sb, struct vfsmount *mnt,
 			   struct autofs_sb_info *sbi, int when);
 int autofs_expire_multi(struct super_block *, struct vfsmount *,
 			struct autofs_sb_info *, int __user *);
-struct dentry *autofs_expire_indirect(struct super_block *sb,
-				      struct vfsmount *mnt,
-				      struct autofs_sb_info *sbi, int how);
 
 /* Device node initialization */
 
diff --git a/fs/autofs/expire.c b/fs/autofs/expire.c
index 64e6eba2c628..5fb47a4ca48c 100644
--- a/fs/autofs/expire.c
+++ b/fs/autofs/expire.c
@@ -424,10 +424,10 @@ static struct dentry *should_expire(struct dentry *dentry,
  *  - it is unused by any user process
  *  - it has been unused for exp_timeout time
  */
-struct dentry *autofs_expire_indirect(struct super_block *sb,
-				      struct vfsmount *mnt,
-				      struct autofs_sb_info *sbi,
-				      int how)
+static struct dentry *autofs_expire_indirect(struct super_block *sb,
+					     struct vfsmount *mnt,
+					     struct autofs_sb_info *sbi,
+					     int how)
 {
 	unsigned long timeout;
 	struct dentry *root = sb->s_root;

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 5/6] autofs - make expire flags usage consistent with v5 params
  2018-06-19  3:01 [PATCH 1/6] autofs - fix inconsistent use of now variable Ian Kent
                   ` (2 preceding siblings ...)
  2018-06-19  3:02 ` [PATCH 4/6] autofs - make autofs_expire_indirect() static Ian Kent
@ 2018-06-19  3:02 ` Ian Kent
  2018-06-19  3:02 ` [PATCH 6/6] autofs - add AUTOFS_EXP_FORCED flag Ian Kent
  4 siblings, 0 replies; 6+ messages in thread
From: Ian Kent @ 2018-06-19  3:02 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-fsdevel, autofs mailing list, Kernel Mailing List

Make the usage of the expire flags consistent by naming
the expire flags the same as it is named in the version
5 miscelaneous ioctl parameters and only check the bit
flags when needed.

Signed-off-by: Ian Kent <raven@themaw.net>
---
 fs/autofs/autofs_i.h |    2 +-
 fs/autofs/expire.c   |   61 +++++++++++++++++++++++---------------------------
 2 files changed, 29 insertions(+), 34 deletions(-)

diff --git a/fs/autofs/autofs_i.h b/fs/autofs/autofs_i.h
index b1f70bc45ca3..b5e0870acdcb 100644
--- a/fs/autofs/autofs_i.h
+++ b/fs/autofs/autofs_i.h
@@ -151,7 +151,7 @@ int autofs_expire_run(struct super_block *, struct vfsmount *,
 		      struct autofs_sb_info *,
 		      struct autofs_packet_expire __user *);
 int autofs_do_expire_multi(struct super_block *sb, struct vfsmount *mnt,
-			   struct autofs_sb_info *sbi, int when);
+			   struct autofs_sb_info *sbi, unsigned int how);
 int autofs_expire_multi(struct super_block *, struct vfsmount *,
 			struct autofs_sb_info *, int __user *);
 
diff --git a/fs/autofs/expire.c b/fs/autofs/expire.c
index 5fb47a4ca48c..dfb666c5b8a2 100644
--- a/fs/autofs/expire.c
+++ b/fs/autofs/expire.c
@@ -12,7 +12,7 @@
 
 /* Check if a dentry can be expired */
 static inline int autofs_can_expire(struct dentry *dentry,
-				    unsigned long timeout, int do_now)
+				    unsigned long timeout, unsigned int how)
 {
 	struct autofs_info *ino = autofs_dentry_ino(dentry);
 
@@ -20,7 +20,7 @@ static inline int autofs_can_expire(struct dentry *dentry,
 	if (ino == NULL)
 		return 0;
 
-	if (!do_now) {
+	if (!(how & AUTOFS_EXP_IMMEDIATE)) {
 		/* Too young to die */
 		if (!timeout || time_after(ino->last_used + timeout, jiffies))
 			return 0;
@@ -185,7 +185,7 @@ static struct dentry *get_next_positive_dentry(struct dentry *prev,
 static int autofs_direct_busy(struct vfsmount *mnt,
 			      struct dentry *top,
 			      unsigned long timeout,
-			      int do_now)
+			      unsigned int how)
 {
 	pr_debug("top %p %pd\n", top, top);
 
@@ -200,7 +200,7 @@ static int autofs_direct_busy(struct vfsmount *mnt,
 	}
 
 	/* Timeout of a direct mount is determined by its top dentry */
-	if (!autofs_can_expire(top, timeout, do_now))
+	if (!autofs_can_expire(top, timeout, how))
 		return 1;
 
 	return 0;
@@ -213,7 +213,7 @@ static int autofs_direct_busy(struct vfsmount *mnt,
 static int autofs_tree_busy(struct vfsmount *mnt,
 			    struct dentry *top,
 			    unsigned long timeout,
-			    int do_now)
+			    unsigned int how)
 {
 	struct autofs_info *top_ino = autofs_dentry_ino(top);
 	struct dentry *p;
@@ -259,7 +259,7 @@ static int autofs_tree_busy(struct vfsmount *mnt,
 	}
 
 	/* Timeout of a tree mount is ultimately determined by its top dentry */
-	if (!autofs_can_expire(top, timeout, do_now))
+	if (!autofs_can_expire(top, timeout, how))
 		return 1;
 
 	return 0;
@@ -268,7 +268,7 @@ static int autofs_tree_busy(struct vfsmount *mnt,
 static struct dentry *autofs_check_leaves(struct vfsmount *mnt,
 					  struct dentry *parent,
 					  unsigned long timeout,
-					  int do_now)
+					  unsigned int how)
 {
 	struct dentry *p;
 
@@ -284,7 +284,7 @@ static struct dentry *autofs_check_leaves(struct vfsmount *mnt,
 				continue;
 
 			/* Can we expire this guy */
-			if (autofs_can_expire(p, timeout, do_now))
+			if (autofs_can_expire(p, timeout, how))
 				return p;
 		}
 	}
@@ -295,19 +295,18 @@ static struct dentry *autofs_check_leaves(struct vfsmount *mnt,
 static struct dentry *autofs_expire_direct(struct super_block *sb,
 					   struct vfsmount *mnt,
 					   struct autofs_sb_info *sbi,
-					   int how)
+					   unsigned int how)
 {
-	unsigned long timeout;
 	struct dentry *root = dget(sb->s_root);
-	int do_now = how & AUTOFS_EXP_IMMEDIATE;
 	struct autofs_info *ino;
+	unsigned long timeout;
 
 	if (!root)
 		return NULL;
 
 	timeout = sbi->exp_timeout;
 
-	if (!autofs_direct_busy(mnt, root, timeout, do_now)) {
+	if (!autofs_direct_busy(mnt, root, timeout, how)) {
 		spin_lock(&sbi->fs_lock);
 		ino = autofs_dentry_ino(root);
 		/* No point expiring a pending mount */
@@ -318,7 +317,7 @@ static struct dentry *autofs_expire_direct(struct super_block *sb,
 		ino->flags |= AUTOFS_INF_WANT_EXPIRE;
 		spin_unlock(&sbi->fs_lock);
 		synchronize_rcu();
-		if (!autofs_direct_busy(mnt, root, timeout, do_now)) {
+		if (!autofs_direct_busy(mnt, root, timeout, how)) {
 			spin_lock(&sbi->fs_lock);
 			ino->flags |= AUTOFS_INF_EXPIRING;
 			init_completion(&ino->expire_complete);
@@ -343,10 +342,8 @@ static struct dentry *autofs_expire_direct(struct super_block *sb,
 static struct dentry *should_expire(struct dentry *dentry,
 				    struct vfsmount *mnt,
 				    unsigned long timeout,
-				    int how)
+				    unsigned int how)
 {
-	int do_now = how & AUTOFS_EXP_IMMEDIATE;
-	int exp_leaves = how & AUTOFS_EXP_LEAVES;
 	struct autofs_info *ino = autofs_dentry_ino(dentry);
 	unsigned int ino_count;
 
@@ -368,7 +365,7 @@ static struct dentry *should_expire(struct dentry *dentry,
 			return NULL;
 
 		/* Can we expire this guy */
-		if (autofs_can_expire(dentry, timeout, do_now))
+		if (autofs_can_expire(dentry, timeout, how))
 			return dentry;
 		return NULL;
 	}
@@ -379,7 +376,7 @@ static struct dentry *should_expire(struct dentry *dentry,
 		 * A symlink can't be "busy" in the usual sense so
 		 * just check last used for expire timeout.
 		 */
-		if (autofs_can_expire(dentry, timeout, do_now))
+		if (autofs_can_expire(dentry, timeout, how))
 			return dentry;
 		return NULL;
 	}
@@ -388,13 +385,13 @@ static struct dentry *should_expire(struct dentry *dentry,
 		return NULL;
 
 	/* Case 2: tree mount, expire iff entire tree is not busy */
-	if (!exp_leaves) {
+	if (!(how & AUTOFS_EXP_LEAVES)) {
 		/* Path walk currently on this dentry? */
 		ino_count = atomic_read(&ino->count) + 1;
 		if (d_count(dentry) > ino_count)
 			return NULL;
 
-		if (!autofs_tree_busy(mnt, dentry, timeout, do_now))
+		if (!autofs_tree_busy(mnt, dentry, timeout, how))
 			return dentry;
 	/*
 	 * Case 3: pseudo direct mount, expire individual leaves
@@ -408,7 +405,7 @@ static struct dentry *should_expire(struct dentry *dentry,
 		if (d_count(dentry) > ino_count)
 			return NULL;
 
-		expired = autofs_check_leaves(mnt, dentry, timeout, do_now);
+		expired = autofs_check_leaves(mnt, dentry, timeout, how);
 		if (expired) {
 			if (expired == dentry)
 				dput(dentry);
@@ -427,7 +424,7 @@ static struct dentry *should_expire(struct dentry *dentry,
 static struct dentry *autofs_expire_indirect(struct super_block *sb,
 					     struct vfsmount *mnt,
 					     struct autofs_sb_info *sbi,
-					     int how)
+					     unsigned int how)
 {
 	unsigned long timeout;
 	struct dentry *root = sb->s_root;
@@ -443,8 +440,6 @@ static struct dentry *autofs_expire_indirect(struct super_block *sb,
 
 	dentry = NULL;
 	while ((dentry = get_next_positive_subdir(dentry, root))) {
-		int flags = how;
-
 		spin_lock(&sbi->fs_lock);
 		ino = autofs_dentry_ino(dentry);
 		if (ino->flags & AUTOFS_INF_WANT_EXPIRE) {
@@ -453,7 +448,7 @@ static struct dentry *autofs_expire_indirect(struct super_block *sb,
 		}
 		spin_unlock(&sbi->fs_lock);
 
-		expired = should_expire(dentry, mnt, timeout, flags);
+		expired = should_expire(dentry, mnt, timeout, how);
 		if (!expired)
 			continue;
 
@@ -466,8 +461,8 @@ static struct dentry *autofs_expire_indirect(struct super_block *sb,
 		/* Make sure a reference is not taken on found if
 		 * things have changed.
 		 */
-		flags &= ~AUTOFS_EXP_LEAVES;
-		found = should_expire(expired, mnt, timeout, flags);
+		how &= ~AUTOFS_EXP_LEAVES;
+		found = should_expire(expired, mnt, timeout, how);
 		if (!found || found != expired)
 			/* Something has changed, continue */
 			goto next;
@@ -580,15 +575,15 @@ int autofs_expire_run(struct super_block *sb,
 }
 
 int autofs_do_expire_multi(struct super_block *sb, struct vfsmount *mnt,
-			   struct autofs_sb_info *sbi, int when)
+			   struct autofs_sb_info *sbi, unsigned int how)
 {
 	struct dentry *dentry;
 	int ret = -EAGAIN;
 
 	if (autofs_type_trigger(sbi->type))
-		dentry = autofs_expire_direct(sb, mnt, sbi, when);
+		dentry = autofs_expire_direct(sb, mnt, sbi, how);
 	else
-		dentry = autofs_expire_indirect(sb, mnt, sbi, when);
+		dentry = autofs_expire_indirect(sb, mnt, sbi, how);
 
 	if (dentry) {
 		struct autofs_info *ino = autofs_dentry_ino(dentry);
@@ -618,10 +613,10 @@ int autofs_do_expire_multi(struct super_block *sb, struct vfsmount *mnt,
 int autofs_expire_multi(struct super_block *sb, struct vfsmount *mnt,
 			struct autofs_sb_info *sbi, int __user *arg)
 {
-	int do_now = 0;
+	unsigned int how = 0;
 
-	if (arg && get_user(do_now, arg))
+	if (arg && get_user(how, arg))
 		return -EFAULT;
 
-	return autofs_do_expire_multi(sb, mnt, sbi, do_now);
+	return autofs_do_expire_multi(sb, mnt, sbi, how);
 }

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 6/6] autofs - add AUTOFS_EXP_FORCED flag
  2018-06-19  3:01 [PATCH 1/6] autofs - fix inconsistent use of now variable Ian Kent
                   ` (3 preceding siblings ...)
  2018-06-19  3:02 ` [PATCH 5/6] autofs - make expire flags usage consistent with v5 params Ian Kent
@ 2018-06-19  3:02 ` Ian Kent
  4 siblings, 0 replies; 6+ messages in thread
From: Ian Kent @ 2018-06-19  3:02 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-fsdevel, autofs mailing list, Kernel Mailing List

The user space automount(8) daemon is meant to perform a forced
expire when sent a SIGUSR2.

But since the expiration is routed through the kernel and the
kernel doesn't send an expire request if the mount is busy this
hasn't worked at least since autofs version 5.

Add an AUTOFS_EXP_FORCED flag to allow implemention of the feature
and bump the protocol version so user space can check if it's
implemented if needed.

Signed-off-by: Ian Kent <raven@themaw.net>
---
 fs/autofs/expire.c           |   62 ++++++++++++++++++++++++++++++++++--------
 include/uapi/linux/auto_fs.h |    8 +++--
 2 files changed, 55 insertions(+), 15 deletions(-)

diff --git a/fs/autofs/expire.c b/fs/autofs/expire.c
index dfb666c5b8a2..d441244b79df 100644
--- a/fs/autofs/expire.c
+++ b/fs/autofs/expire.c
@@ -29,7 +29,8 @@ static inline int autofs_can_expire(struct dentry *dentry,
 }
 
 /* Check a mount point for busyness */
-static int autofs_mount_busy(struct vfsmount *mnt, struct dentry *dentry)
+static int autofs_mount_busy(struct vfsmount *mnt,
+			     struct dentry *dentry, unsigned int how)
 {
 	struct dentry *top = dentry;
 	struct path path = {.mnt = mnt, .dentry = dentry};
@@ -50,6 +51,12 @@ static int autofs_mount_busy(struct vfsmount *mnt, struct dentry *dentry)
 			goto done;
 	}
 
+	/* Not a submount, has a forced expire been requested */
+	if (how & AUTOFS_EXP_FORCED) {
+		status = 0;
+		goto done;
+	}
+
 	/* Update the expiry counter if fs is busy */
 	if (!may_umount_tree(path.mnt)) {
 		struct autofs_info *ino;
@@ -189,6 +196,10 @@ static int autofs_direct_busy(struct vfsmount *mnt,
 {
 	pr_debug("top %p %pd\n", top, top);
 
+	/* Forced expire, user space handles busy mounts */
+	if (how & AUTOFS_EXP_FORCED)
+		return 0;
+
 	/* If it's busy update the expiry counters */
 	if (!may_umount_tree(mnt)) {
 		struct autofs_info *ino;
@@ -235,7 +246,7 @@ static int autofs_tree_busy(struct vfsmount *mnt,
 		 * If the fs is busy update the expiry counter.
 		 */
 		if (d_mountpoint(p)) {
-			if (autofs_mount_busy(mnt, p)) {
+			if (autofs_mount_busy(mnt, p, how)) {
 				top_ino->last_used = jiffies;
 				dput(p);
 				return 1;
@@ -258,6 +269,10 @@ static int autofs_tree_busy(struct vfsmount *mnt,
 		}
 	}
 
+	/* Forced expire, user space handles busy mounts */
+	if (how & AUTOFS_EXP_FORCED)
+		return 0;
+
 	/* Timeout of a tree mount is ultimately determined by its top dentry */
 	if (!autofs_can_expire(top, timeout, how))
 		return 1;
@@ -280,9 +295,15 @@ static struct dentry *autofs_check_leaves(struct vfsmount *mnt,
 
 		if (d_mountpoint(p)) {
 			/* Can we umount this guy */
-			if (autofs_mount_busy(mnt, p))
+			if (autofs_mount_busy(mnt, p, how))
 				continue;
 
+			/* This isn't a submount so if a forced expire
+			 * has been requested, user space handles busy
+			 * mounts */
+			if (how & AUTOFS_EXP_FORCED)
+				return p;
+
 			/* Can we expire this guy */
 			if (autofs_can_expire(p, timeout, how))
 				return p;
@@ -361,9 +382,15 @@ static struct dentry *should_expire(struct dentry *dentry,
 		pr_debug("checking mountpoint %p %pd\n", dentry, dentry);
 
 		/* Can we umount this guy */
-		if (autofs_mount_busy(mnt, dentry))
+		if (autofs_mount_busy(mnt, dentry, how))
 			return NULL;
 
+		/* This isn't a submount so if a forced expire
+		 * has been requested, user space handles busy
+		 * mounts */
+		if (how & AUTOFS_EXP_FORCED)
+			return dentry;
+
 		/* Can we expire this guy */
 		if (autofs_can_expire(dentry, timeout, how))
 			return dentry;
@@ -372,6 +399,11 @@ static struct dentry *should_expire(struct dentry *dentry,
 
 	if (d_really_is_positive(dentry) && d_is_symlink(dentry)) {
 		pr_debug("checking symlink %p %pd\n", dentry, dentry);
+
+		/* Forced expire, user space handles busy mounts */
+		if (how & AUTOFS_EXP_FORCED)
+			return dentry;
+
 		/*
 		 * A symlink can't be "busy" in the usual sense so
 		 * just check last used for expire timeout.
@@ -386,10 +418,13 @@ static struct dentry *should_expire(struct dentry *dentry,
 
 	/* Case 2: tree mount, expire iff entire tree is not busy */
 	if (!(how & AUTOFS_EXP_LEAVES)) {
-		/* Path walk currently on this dentry? */
-		ino_count = atomic_read(&ino->count) + 1;
-		if (d_count(dentry) > ino_count)
-			return NULL;
+		/* Not a forced expire? */
+		if (!(how & AUTOFS_EXP_FORCED)) {
+			/* ref-walk currently on this dentry? */
+			ino_count = atomic_read(&ino->count) + 1;
+			if (d_count(dentry) > ino_count)
+				return NULL;
+		}
 
 		if (!autofs_tree_busy(mnt, dentry, timeout, how))
 			return dentry;
@@ -398,12 +433,15 @@ static struct dentry *should_expire(struct dentry *dentry,
 	 *	   (autofs-4.1).
 	 */
 	} else {
-		/* Path walk currently on this dentry? */
 		struct dentry *expired;
 
-		ino_count = atomic_read(&ino->count) + 1;
-		if (d_count(dentry) > ino_count)
-			return NULL;
+		/* Not a forced expire? */
+		if (!(how & AUTOFS_EXP_FORCED)) {
+			/* ref-walk currently on this dentry? */
+			ino_count = atomic_read(&ino->count) + 1;
+			if (d_count(dentry) > ino_count)
+				return NULL;
+		}
 
 		expired = autofs_check_leaves(mnt, dentry, timeout, how);
 		if (expired) {
diff --git a/include/uapi/linux/auto_fs.h b/include/uapi/linux/auto_fs.h
index e13eec3dfb2f..df31aa9c9a8c 100644
--- a/include/uapi/linux/auto_fs.h
+++ b/include/uapi/linux/auto_fs.h
@@ -23,7 +23,7 @@
 #define AUTOFS_MIN_PROTO_VERSION	3
 #define AUTOFS_MAX_PROTO_VERSION	5
 
-#define AUTOFS_PROTO_SUBVERSION		2
+#define AUTOFS_PROTO_SUBVERSION		3
 
 /*
  * The wait_queue_token (autofs_wqt_t) is part of a structure which is passed
@@ -90,8 +90,10 @@ enum {
 /* autofs version 4 and later definitions */
 
 /* Mask for expire behaviour */
-#define AUTOFS_EXP_IMMEDIATE		1
-#define AUTOFS_EXP_LEAVES		2
+#define AUTOFS_EXP_NORMAL		0x00
+#define AUTOFS_EXP_IMMEDIATE		0x01
+#define AUTOFS_EXP_LEAVES		0x02
+#define AUTOFS_EXP_FORCED		0x04
 
 #define AUTOFS_TYPE_ANY			0U
 #define AUTOFS_TYPE_INDIRECT		1U

^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2018-06-19  3:03 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-06-19  3:01 [PATCH 1/6] autofs - fix inconsistent use of now variable Ian Kent
2018-06-19  3:02 ` [PATCH 2/6] autofs - fix clearing AUTOFS_EXP_LEAVES in autofs_expire_indirect() Ian Kent
2018-06-19  3:02 ` [PATCH 3/6] autofs - make autofs_expire_direct() static Ian Kent
2018-06-19  3:02 ` [PATCH 4/6] autofs - make autofs_expire_indirect() static Ian Kent
2018-06-19  3:02 ` [PATCH 5/6] autofs - make expire flags usage consistent with v5 params Ian Kent
2018-06-19  3:02 ` [PATCH 6/6] autofs - add AUTOFS_EXP_FORCED flag Ian Kent

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).