From patchwork Fri Jun 17 05:35:29 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Kent X-Patchwork-Id: 12885108 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 07CBEC43334 for ; Fri, 17 Jun 2022 05:35:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233978AbiFQFfd (ORCPT ); Fri, 17 Jun 2022 01:35:33 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60426 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229493AbiFQFfc (ORCPT ); Fri, 17 Jun 2022 01:35:32 -0400 Received: from smtp03.aussiebb.com.au (2403-5800-3-25--1003.ip6.aussiebb.net [IPv6:2403:5800:3:25::1003]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id ECF1B2CE09; Thu, 16 Jun 2022 22:35:31 -0700 (PDT) Received: from localhost (localhost [127.0.0.1]) by smtp03.aussiebb.com.au (Postfix) with ESMTP id 817721A007E; Fri, 17 Jun 2022 15:35:30 +1000 (AEST) X-Virus-Scanned: Debian amavisd-new at smtp03.aussiebb.com.au Received: from smtp03.aussiebb.com.au ([127.0.0.1]) by localhost (smtp03.aussiebb.com.au [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id DQIddVwqXtHQ; Fri, 17 Jun 2022 15:35:30 +1000 (AEST) Received: by smtp03.aussiebb.com.au (Postfix, from userid 119) id 76A1B1A009C; Fri, 17 Jun 2022 15:35:30 +1000 (AEST) Received: from donald.themaw.net (180-150-90-198.b4965a.per.nbn.aussiebb.net [180.150.90.198]) by smtp03.aussiebb.com.au (Postfix) with ESMTP id CAAAC1A007E; Fri, 17 Jun 2022 15:35:29 +1000 (AEST) Subject: [PATCH 1/6] autofs: use inode permission method for write access From: Ian Kent To: Al Viro Cc: David Howells , Miklos Szeredi , linux-fsdevel , Kernel Mailing List Date: Fri, 17 Jun 2022 13:35:29 +0800 Message-ID: <165544412955.250070.4233102297106814123.stgit@donald.themaw.net> In-Reply-To: <165544393032.250070.3426550720222448062.stgit@donald.themaw.net> References: <165544393032.250070.3426550720222448062.stgit@donald.themaw.net> User-Agent: StGit/1.1 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Eliminate some code duplication from mkdir/rmdir/symlink/unlink methods by using the inode operation .permission(). Signed-off-by: Ian Kent --- fs/autofs/root.c | 63 +++++++++++++++++++----------------------------------- 1 file changed, 22 insertions(+), 41 deletions(-) diff --git a/fs/autofs/root.c b/fs/autofs/root.c index 91fe4548c256..fef6ed991022 100644 --- a/fs/autofs/root.c +++ b/fs/autofs/root.c @@ -10,6 +10,7 @@ #include "autofs_i.h" +static int autofs_dir_permission(struct user_namespace *, struct inode *, int); static int autofs_dir_symlink(struct user_namespace *, struct inode *, struct dentry *, const char *); static int autofs_dir_unlink(struct inode *, struct dentry *); @@ -50,6 +51,7 @@ const struct file_operations autofs_dir_operations = { const struct inode_operations autofs_dir_inode_operations = { .lookup = autofs_lookup, + .permission = autofs_dir_permission, .unlink = autofs_dir_unlink, .symlink = autofs_dir_symlink, .mkdir = autofs_dir_mkdir, @@ -526,11 +528,30 @@ static struct dentry *autofs_lookup(struct inode *dir, return NULL; } +static int autofs_dir_permission(struct user_namespace *mnt_userns, + struct inode *inode, int mask) +{ + if (mask & MAY_WRITE) { + struct autofs_sb_info *sbi = autofs_sbi(inode->i_sb); + + if (!autofs_oz_mode(sbi)) + return -EACCES; + + /* autofs_oz_mode() needs to allow path walks when the + * autofs mount is catatonic but the state of an autofs + * file system needs to be preserved over restarts. + */ + if (sbi->flags & AUTOFS_SBI_CATATONIC) + return -EACCES; + } + + return generic_permission(mnt_userns, inode, mask); +} + static int autofs_dir_symlink(struct user_namespace *mnt_userns, struct inode *dir, struct dentry *dentry, const char *symname) { - struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb); struct autofs_info *ino = autofs_dentry_ino(dentry); struct autofs_info *p_ino; struct inode *inode; @@ -539,16 +560,6 @@ static int autofs_dir_symlink(struct user_namespace *mnt_userns, pr_debug("%s <- %pd\n", symname, dentry); - if (!autofs_oz_mode(sbi)) - return -EACCES; - - /* autofs_oz_mode() needs to allow path walks when the - * autofs mount is catatonic but the state of an autofs - * file system needs to be preserved over restarts. - */ - if (sbi->flags & AUTOFS_SBI_CATATONIC) - return -EACCES; - BUG_ON(!ino); autofs_clean_ino(ino); @@ -601,16 +612,6 @@ static int autofs_dir_unlink(struct inode *dir, struct dentry *dentry) struct autofs_info *ino = autofs_dentry_ino(dentry); struct autofs_info *p_ino; - if (!autofs_oz_mode(sbi)) - return -EACCES; - - /* autofs_oz_mode() needs to allow path walks when the - * autofs mount is catatonic but the state of an autofs - * file system needs to be preserved over restarts. - */ - if (sbi->flags & AUTOFS_SBI_CATATONIC) - return -EACCES; - ino->count--; p_ino = autofs_dentry_ino(dentry->d_parent); p_ino->count--; @@ -683,16 +684,6 @@ static int autofs_dir_rmdir(struct inode *dir, struct dentry *dentry) pr_debug("dentry %p, removing %pd\n", dentry, dentry); - if (!autofs_oz_mode(sbi)) - return -EACCES; - - /* autofs_oz_mode() needs to allow path walks when the - * autofs mount is catatonic but the state of an autofs - * file system needs to be preserved over restarts. - */ - if (sbi->flags & AUTOFS_SBI_CATATONIC) - return -EACCES; - if (ino->count != 1) return -ENOTEMPTY; @@ -726,16 +717,6 @@ static int autofs_dir_mkdir(struct user_namespace *mnt_userns, struct autofs_info *p_ino; struct inode *inode; - if (!autofs_oz_mode(sbi)) - return -EACCES; - - /* autofs_oz_mode() needs to allow path walks when the - * autofs mount is catatonic but the state of an autofs - * file system needs to be preserved over restarts. - */ - if (sbi->flags & AUTOFS_SBI_CATATONIC) - return -EACCES; - pr_debug("dentry %p, creating %pd\n", dentry, dentry); BUG_ON(!ino); From patchwork Fri Jun 17 05:35:35 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Kent X-Patchwork-Id: 12885109 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 27D0DC433EF for ; Fri, 17 Jun 2022 05:35:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234383AbiFQFfj (ORCPT ); Fri, 17 Jun 2022 01:35:39 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60540 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229493AbiFQFfi (ORCPT ); Fri, 17 Jun 2022 01:35:38 -0400 Received: from smtp03.aussiebb.com.au (2403-5800-3-25--1003.ip6.aussiebb.net [IPv6:2403:5800:3:25::1003]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 79AD62EA06; Thu, 16 Jun 2022 22:35:37 -0700 (PDT) Received: from localhost (localhost [127.0.0.1]) by smtp03.aussiebb.com.au (Postfix) with ESMTP id F01CD1A00A1; Fri, 17 Jun 2022 15:35:35 +1000 (AEST) X-Virus-Scanned: Debian amavisd-new at smtp03.aussiebb.com.au Received: from smtp03.aussiebb.com.au ([127.0.0.1]) by localhost (smtp03.aussiebb.com.au [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id R4NXhvugvGLU; Fri, 17 Jun 2022 15:35:35 +1000 (AEST) Received: by smtp03.aussiebb.com.au (Postfix, from userid 119) id E75FA1A009C; Fri, 17 Jun 2022 15:35:35 +1000 (AEST) Received: from donald.themaw.net (180-150-90-198.b4965a.per.nbn.aussiebb.net [180.150.90.198]) by smtp03.aussiebb.com.au (Postfix) with ESMTP id 640321A0080; Fri, 17 Jun 2022 15:35:35 +1000 (AEST) Subject: [PATCH 2/6] autofs: make dentry info count consistent From: Ian Kent To: Al Viro Cc: David Howells , Miklos Szeredi , linux-fsdevel , Kernel Mailing List Date: Fri, 17 Jun 2022 13:35:35 +0800 Message-ID: <165544413518.250070.9457530301065902098.stgit@donald.themaw.net> In-Reply-To: <165544393032.250070.3426550720222448062.stgit@donald.themaw.net> References: <165544393032.250070.3426550720222448062.stgit@donald.themaw.net> User-Agent: StGit/1.1 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org If an autofs dentry is a mount root directory there's no ->mkdir() call to set its count to one. To make the dentry info count consistent for all autofs dentries set count to one when the dentry info struct is allocated. Signed-off-by: Ian Kent --- fs/autofs/inode.c | 1 + fs/autofs/root.c | 4 ---- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c index 9edf243713eb..affa70360b1f 100644 --- a/fs/autofs/inode.c +++ b/fs/autofs/inode.c @@ -20,6 +20,7 @@ struct autofs_info *autofs_new_ino(struct autofs_sb_info *sbi) INIT_LIST_HEAD(&ino->expiring); ino->last_used = jiffies; ino->sbi = sbi; + ino->count = 1; } return ino; } diff --git a/fs/autofs/root.c b/fs/autofs/root.c index fef6ed991022..442d27d9cb1b 100644 --- a/fs/autofs/root.c +++ b/fs/autofs/root.c @@ -582,7 +582,6 @@ static int autofs_dir_symlink(struct user_namespace *mnt_userns, d_add(dentry, inode); dget(dentry); - ino->count++; p_ino = autofs_dentry_ino(dentry->d_parent); p_ino->count++; @@ -612,7 +611,6 @@ static int autofs_dir_unlink(struct inode *dir, struct dentry *dentry) struct autofs_info *ino = autofs_dentry_ino(dentry); struct autofs_info *p_ino; - ino->count--; p_ino = autofs_dentry_ino(dentry->d_parent); p_ino->count--; dput(ino->dentry); @@ -695,7 +693,6 @@ static int autofs_dir_rmdir(struct inode *dir, struct dentry *dentry) if (sbi->version < 5) autofs_clear_leaf_automount_flags(dentry); - ino->count--; p_ino = autofs_dentry_ino(dentry->d_parent); p_ino->count--; dput(ino->dentry); @@ -734,7 +731,6 @@ static int autofs_dir_mkdir(struct user_namespace *mnt_userns, autofs_set_leaf_automount_flags(dentry); dget(dentry); - ino->count++; p_ino = autofs_dentry_ino(dentry->d_parent); p_ino->count++; inc_nlink(dir); From patchwork Fri Jun 17 05:35:40 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Kent X-Patchwork-Id: 12885110 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9405AC43334 for ; Fri, 17 Jun 2022 05:35:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1379700AbiFQFfq (ORCPT ); Fri, 17 Jun 2022 01:35:46 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60722 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1379804AbiFQFfp (ORCPT ); Fri, 17 Jun 2022 01:35:45 -0400 Received: from smtp03.aussiebb.com.au (2403-5800-3-25--1003.ip6.aussiebb.net [IPv6:2403:5800:3:25::1003]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3C4D966ADE; Thu, 16 Jun 2022 22:35:43 -0700 (PDT) Received: from localhost (localhost [127.0.0.1]) by smtp03.aussiebb.com.au (Postfix) with ESMTP id B18531A009C; Fri, 17 Jun 2022 15:35:41 +1000 (AEST) X-Virus-Scanned: Debian amavisd-new at smtp03.aussiebb.com.au Received: from smtp03.aussiebb.com.au ([127.0.0.1]) by localhost (smtp03.aussiebb.com.au [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id k0pxseolj2v7; Fri, 17 Jun 2022 15:35:41 +1000 (AEST) Received: by smtp03.aussiebb.com.au (Postfix, from userid 119) id A32D41A00A2; Fri, 17 Jun 2022 15:35:41 +1000 (AEST) Received: from donald.themaw.net (180-150-90-198.b4965a.per.nbn.aussiebb.net [180.150.90.198]) by smtp03.aussiebb.com.au (Postfix) with ESMTP id 003AD1A009C; Fri, 17 Jun 2022 15:35:40 +1000 (AEST) Subject: [PATCH 3/6] autofs: use dentry info count instead of simple_empty() From: Ian Kent To: Al Viro Cc: David Howells , Miklos Szeredi , linux-fsdevel , Kernel Mailing List Date: Fri, 17 Jun 2022 13:35:40 +0800 Message-ID: <165544414075.250070.16584639554188189891.stgit@donald.themaw.net> In-Reply-To: <165544393032.250070.3426550720222448062.stgit@donald.themaw.net> References: <165544393032.250070.3426550720222448062.stgit@donald.themaw.net> User-Agent: StGit/1.1 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org The dentry info. field count is used to check if a dentry is in use during expire. But, to be used for this the count field must account for the presence of child dentries in a directory dentry. Therefore it can also be used to check for an empty directory dentry which can be done without having to to take an additional lock or account for the presence of a readdir cursor dentry as is done by simple_empty(). Signed-off-by: Ian Kent --- fs/autofs/autofs_i.h | 5 +++++ fs/autofs/expire.c | 2 +- fs/autofs/root.c | 18 ++++++++---------- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/fs/autofs/autofs_i.h b/fs/autofs/autofs_i.h index 918826eaceea..0117d6e06300 100644 --- a/fs/autofs/autofs_i.h +++ b/fs/autofs/autofs_i.h @@ -148,6 +148,11 @@ static inline int autofs_oz_mode(struct autofs_sb_info *sbi) task_pgrp(current) == sbi->oz_pgrp); } +static inline bool autofs_empty(struct autofs_info *ino) +{ + return ino->count < 2; +} + struct inode *autofs_get_inode(struct super_block *, umode_t); void autofs_free_ino(struct autofs_info *); diff --git a/fs/autofs/expire.c b/fs/autofs/expire.c index b3fefd6237c3..038b3d2d9f57 100644 --- a/fs/autofs/expire.c +++ b/fs/autofs/expire.c @@ -371,7 +371,7 @@ static struct dentry *should_expire(struct dentry *dentry, return NULL; } - if (simple_empty(dentry)) + if (autofs_empty(ino)) return NULL; /* Case 2: tree mount, expire iff entire tree is not busy */ diff --git a/fs/autofs/root.c b/fs/autofs/root.c index 442d27d9cb1b..e0fa71eb5c05 100644 --- a/fs/autofs/root.c +++ b/fs/autofs/root.c @@ -79,6 +79,7 @@ static int autofs_dir_open(struct inode *inode, struct file *file) { struct dentry *dentry = file->f_path.dentry; struct autofs_sb_info *sbi = autofs_sbi(dentry->d_sb); + struct autofs_info *ino = autofs_dentry_ino(dentry); pr_debug("file=%p dentry=%p %pd\n", file, dentry, dentry); @@ -95,7 +96,7 @@ static int autofs_dir_open(struct inode *inode, struct file *file) * it. */ spin_lock(&sbi->lookup_lock); - if (!path_is_mountpoint(&file->f_path) && simple_empty(dentry)) { + if (!path_is_mountpoint(&file->f_path) && autofs_empty(ino)) { spin_unlock(&sbi->lookup_lock); return -ENOENT; } @@ -364,7 +365,7 @@ static struct vfsmount *autofs_d_automount(struct path *path) * the mount never trigger mounts themselves (they have an * autofs trigger mount mounted on them). But v4 pseudo direct * mounts do need the leaves to trigger mounts. In this case - * we have no choice but to use the list_empty() check and + * we have no choice but to use the autofs_empty() check and * require user space behave. */ if (sbi->version > 4) { @@ -373,7 +374,7 @@ static struct vfsmount *autofs_d_automount(struct path *path) goto done; } } else { - if (!simple_empty(dentry)) { + if (!autofs_empty(ino)) { spin_unlock(&sbi->fs_lock); goto done; } @@ -428,9 +429,8 @@ static int autofs_d_manage(const struct path *path, bool rcu_walk) if (rcu_walk) { /* We don't need fs_lock in rcu_walk mode, - * just testing 'AUTOFS_INFO_NO_RCU' is enough. - * simple_empty() takes a spinlock, so leave it - * to last. + * just testing 'AUTOFS_INF_WANT_EXPIRE' is enough. + * * We only return -EISDIR when certain this isn't * a mount-trap. */ @@ -443,9 +443,7 @@ static int autofs_d_manage(const struct path *path, bool rcu_walk) inode = d_inode_rcu(dentry); if (inode && S_ISLNK(inode->i_mode)) return -EISDIR; - if (list_empty(&dentry->d_subdirs)) - return 0; - if (!simple_empty(dentry)) + if (!autofs_empty(ino)) return -EISDIR; return 0; } @@ -465,7 +463,7 @@ static int autofs_d_manage(const struct path *path, bool rcu_walk) * we can avoid needless calls ->d_automount() and avoid * an incorrect ELOOP error return. */ - if ((!path_is_mountpoint(path) && !simple_empty(dentry)) || + if ((!path_is_mountpoint(path) && !autofs_empty(ino)) || (d_really_is_positive(dentry) && d_is_symlink(dentry))) status = -EISDIR; } From patchwork Fri Jun 17 05:35:46 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Kent X-Patchwork-Id: 12885111 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id CEFD0C43334 for ; Fri, 17 Jun 2022 05:35:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1380087AbiFQFfx (ORCPT ); Fri, 17 Jun 2022 01:35:53 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60798 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1379903AbiFQFft (ORCPT ); Fri, 17 Jun 2022 01:35:49 -0400 Received: from smtp03.aussiebb.com.au (2403-5800-3-25--1003.ip6.aussiebb.net [IPv6:2403:5800:3:25::1003]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 53CB44756C; Thu, 16 Jun 2022 22:35:48 -0700 (PDT) Received: from localhost (localhost [127.0.0.1]) by smtp03.aussiebb.com.au (Postfix) with ESMTP id 047A31A00A1; Fri, 17 Jun 2022 15:35:47 +1000 (AEST) X-Virus-Scanned: Debian amavisd-new at smtp03.aussiebb.com.au Received: from smtp03.aussiebb.com.au ([127.0.0.1]) by localhost (smtp03.aussiebb.com.au [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id TxA8BIMRwdjp; Fri, 17 Jun 2022 15:35:46 +1000 (AEST) Received: by smtp03.aussiebb.com.au (Postfix, from userid 119) id ECECE1A00A2; Fri, 17 Jun 2022 15:35:46 +1000 (AEST) Received: from donald.themaw.net (180-150-90-198.b4965a.per.nbn.aussiebb.net [180.150.90.198]) by smtp03.aussiebb.com.au (Postfix) with ESMTP id 8AFC91A009C; Fri, 17 Jun 2022 15:35:46 +1000 (AEST) Subject: [PATCH 4/6] autofs: add comment about autofs_mountpoint_changed() From: Ian Kent To: Al Viro Cc: David Howells , Miklos Szeredi , linux-fsdevel , Kernel Mailing List Date: Fri, 17 Jun 2022 13:35:46 +0800 Message-ID: <165544414635.250070.10563886994408560172.stgit@donald.themaw.net> In-Reply-To: <165544393032.250070.3426550720222448062.stgit@donald.themaw.net> References: <165544393032.250070.3426550720222448062.stgit@donald.themaw.net> User-Agent: StGit/1.1 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org The function autofs_mountpoint_changed() is unusual, add a comment about two cases for which it is needed. Signed-off-by: Ian Kent --- fs/autofs/root.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/fs/autofs/root.c b/fs/autofs/root.c index e0fa71eb5c05..ca03c1cae2be 100644 --- a/fs/autofs/root.c +++ b/fs/autofs/root.c @@ -291,9 +291,26 @@ static struct dentry *autofs_mountpoint_changed(struct path *path) struct dentry *dentry = path->dentry; struct autofs_sb_info *sbi = autofs_sbi(dentry->d_sb); - /* - * If this is an indirect mount the dentry could have gone away - * as a result of an expire and a new one created. + /* If this is an indirect mount the dentry could have gone away + * and a new one created. + * + * This is unusual and I can't remember the case for which it + * was originally added now. But an example of how this can + * happen is an autofs indirect mount that has the "browse" + * option set and also has the "symlink" option in the autofs + * map entry. In this case the daemon will remove the browse + * directory and create a symlink as the mount leaving the + * struct path stale. + * + * Another not so obvious case is when a mount in an autofs + * indirect mount that uses the "nobrowse" option is being + * expired at the same time as a path walk. If the mount has + * been umounted but the mount point directory seen before + * becoming unhashed (during a lockless path walk) when a stat + * family system call is made the mount won't be re-mounted as + * it should. In this case the mount point that's been removed + * (by the daemon) will be stale and the a new mount point + * dentry created. */ if (autofs_type_indirect(sbi->type) && d_unhashed(dentry)) { struct dentry *parent = dentry->d_parent; From patchwork Fri Jun 17 05:35:51 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Kent X-Patchwork-Id: 12885112 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 93C04C433EF for ; Fri, 17 Jun 2022 05:35:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1380092AbiFQFf6 (ORCPT ); Fri, 17 Jun 2022 01:35:58 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60916 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1380083AbiFQFf4 (ORCPT ); Fri, 17 Jun 2022 01:35:56 -0400 Received: from smtp03.aussiebb.com.au (smtp03.aussiebb.com.au [121.200.0.94]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 96E5B66AEB; Thu, 16 Jun 2022 22:35:54 -0700 (PDT) Received: from localhost (localhost [127.0.0.1]) by smtp03.aussiebb.com.au (Postfix) with ESMTP id AB3DA1A009C; Fri, 17 Jun 2022 15:35:52 +1000 (AEST) X-Virus-Scanned: Debian amavisd-new at smtp03.aussiebb.com.au Received: from smtp03.aussiebb.com.au ([127.0.0.1]) by localhost (smtp03.aussiebb.com.au [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id pRJsQmS4rxnA; Fri, 17 Jun 2022 15:35:52 +1000 (AEST) Received: by smtp03.aussiebb.com.au (Postfix, from userid 119) id A24F01A00A8; Fri, 17 Jun 2022 15:35:52 +1000 (AEST) Received: from donald.themaw.net (180-150-90-198.b4965a.per.nbn.aussiebb.net [180.150.90.198]) by smtp03.aussiebb.com.au (Postfix) with ESMTP id 20BF11A009C; Fri, 17 Jun 2022 15:35:52 +1000 (AEST) Subject: [PATCH 5/6] autofs: remove unused ino field inode From: Ian Kent To: Al Viro Cc: David Howells , Miklos Szeredi , linux-fsdevel , Kernel Mailing List Date: Fri, 17 Jun 2022 13:35:51 +0800 Message-ID: <165544415191.250070.12106625168524302864.stgit@donald.themaw.net> In-Reply-To: <165544393032.250070.3426550720222448062.stgit@donald.themaw.net> References: <165544393032.250070.3426550720222448062.stgit@donald.themaw.net> User-Agent: StGit/1.1 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Remove the unused inode field of the autofs dentry info structure. Signed-off-by: Ian Kent --- fs/autofs/autofs_i.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/autofs/autofs_i.h b/fs/autofs/autofs_i.h index 0117d6e06300..d5a44fa88acf 100644 --- a/fs/autofs/autofs_i.h +++ b/fs/autofs/autofs_i.h @@ -51,8 +51,6 @@ extern struct file_system_type autofs_fs_type; */ struct autofs_info { struct dentry *dentry; - struct inode *inode; - int flags; struct completion expire_complete; From patchwork Fri Jun 17 05:35:57 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Kent X-Patchwork-Id: 12885113 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7AAD1C43334 for ; Fri, 17 Jun 2022 05:36:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1380029AbiFQFgJ (ORCPT ); Fri, 17 Jun 2022 01:36:09 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60898 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1380109AbiFQFgE (ORCPT ); Fri, 17 Jun 2022 01:36:04 -0400 Received: from smtp03.aussiebb.com.au (smtp03.aussiebb.com.au [121.200.0.94]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3F42066C8C; Thu, 16 Jun 2022 22:36:00 -0700 (PDT) Received: from localhost (localhost [127.0.0.1]) by smtp03.aussiebb.com.au (Postfix) with ESMTP id 6B1831A00A2; Fri, 17 Jun 2022 15:35:58 +1000 (AEST) X-Virus-Scanned: Debian amavisd-new at smtp03.aussiebb.com.au Received: from smtp03.aussiebb.com.au ([127.0.0.1]) by localhost (smtp03.aussiebb.com.au [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id cgjuU-QEkJUA; Fri, 17 Jun 2022 15:35:58 +1000 (AEST) Received: by smtp03.aussiebb.com.au (Postfix, from userid 119) id 63C9C1A00A4; Fri, 17 Jun 2022 15:35:58 +1000 (AEST) Received: from donald.themaw.net (180-150-90-198.b4965a.per.nbn.aussiebb.net [180.150.90.198]) by smtp03.aussiebb.com.au (Postfix) with ESMTP id AF5BA1A0085; Fri, 17 Jun 2022 15:35:57 +1000 (AEST) Subject: [PATCH 6/6] autofs: manage dentry info mount trigger flags better From: Ian Kent To: Al Viro Cc: David Howells , Miklos Szeredi , linux-fsdevel , Kernel Mailing List Date: Fri, 17 Jun 2022 13:35:57 +0800 Message-ID: <165544415748.250070.14681426149656207251.stgit@donald.themaw.net> In-Reply-To: <165544393032.250070.3426550720222448062.stgit@donald.themaw.net> References: <165544393032.250070.3426550720222448062.stgit@donald.themaw.net> User-Agent: StGit/1.1 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org The autofs managed dentry flags are left set for dentries in an autofs mount directory regardless of whether the dentry should trigger a mount (a non-empty directory or a symlink doesn't). But properly managing these flags can sometimes provide the loop termination condition needed when following mounts which now uses an -EISDIR return. Signed-off-by: Ian Kent --- fs/autofs/root.c | 97 +++++++++++++++++++++++------------------------------- 1 file changed, 42 insertions(+), 55 deletions(-) diff --git a/fs/autofs/root.c b/fs/autofs/root.c index ca03c1cae2be..d140d06c5bc6 100644 --- a/fs/autofs/root.c +++ b/fs/autofs/root.c @@ -529,9 +529,8 @@ static struct dentry *autofs_lookup(struct inode *dir, spin_lock(&sbi->lookup_lock); spin_lock(&dentry->d_lock); - /* Mark entries in the root as mount triggers */ - if (IS_ROOT(dentry->d_parent) && - autofs_type_indirect(sbi->type)) + /* Mark indirect mount entries as mount triggers */ + if (autofs_type_indirect(sbi->type)) __managed_dentry_set_managed(dentry); dentry->d_fsdata = ino; ino->dentry = dentry; @@ -567,7 +566,9 @@ static int autofs_dir_symlink(struct user_namespace *mnt_userns, struct inode *dir, struct dentry *dentry, const char *symname) { + struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb); struct autofs_info *ino = autofs_dentry_ino(dentry); + struct dentry *parent = dentry->d_parent; struct autofs_info *p_ino; struct inode *inode; size_t size = strlen(symname); @@ -602,6 +603,16 @@ static int autofs_dir_symlink(struct user_namespace *mnt_userns, dir->i_mtime = current_time(dir); + /* Symlinks don't trigger mounts */ + managed_dentry_clear_managed(dentry); + /* Clear containing directory flags if it's no longer empty */ + if (autofs_dentry_ino(parent)->count == 2) { + /* Don't set or clear type indirect root */ + if (!IS_ROOT(parent) || + !autofs_type_indirect(sbi->type)) + managed_dentry_clear_managed(parent); + } + return 0; } @@ -624,12 +635,21 @@ static int autofs_dir_unlink(struct inode *dir, struct dentry *dentry) { struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb); struct autofs_info *ino = autofs_dentry_ino(dentry); + struct dentry *parent = dentry->d_parent; struct autofs_info *p_ino; p_ino = autofs_dentry_ino(dentry->d_parent); p_ino->count--; dput(ino->dentry); + /* Set containing directory flags if it's now empty */ + if (autofs_dentry_ino(parent)->count == 1) { + /* Don't set or clear type indirect root */ + if (!IS_ROOT(parent) || + !autofs_type_indirect(sbi->type)) + managed_dentry_set_managed(parent); + } + d_inode(dentry)->i_size = 0; clear_nlink(d_inode(dentry)); @@ -643,56 +663,11 @@ static int autofs_dir_unlink(struct inode *dir, struct dentry *dentry) return 0; } -/* - * Version 4 of autofs provides a pseudo direct mount implementation - * that relies on directories at the leaves of a directory tree under - * an indirect mount to trigger mounts. To allow for this we need to - * set the DMANAGED_AUTOMOUNT and DMANAGED_TRANSIT flags on the leaves - * of the directory tree. There is no need to clear the automount flag - * following a mount or restore it after an expire because these mounts - * are always covered. However, it is necessary to ensure that these - * flags are clear on non-empty directories to avoid unnecessary calls - * during path walks. - */ -static void autofs_set_leaf_automount_flags(struct dentry *dentry) -{ - struct dentry *parent; - - /* root and dentrys in the root are already handled */ - if (IS_ROOT(dentry->d_parent)) - return; - - managed_dentry_set_managed(dentry); - - parent = dentry->d_parent; - /* only consider parents below dentrys in the root */ - if (IS_ROOT(parent->d_parent)) - return; - managed_dentry_clear_managed(parent); -} - -static void autofs_clear_leaf_automount_flags(struct dentry *dentry) -{ - struct dentry *parent; - - /* flags for dentrys in the root are handled elsewhere */ - if (IS_ROOT(dentry->d_parent)) - return; - - managed_dentry_clear_managed(dentry); - - parent = dentry->d_parent; - /* only consider parents below dentrys in the root */ - if (IS_ROOT(parent->d_parent)) - return; - if (autofs_dentry_ino(parent)->count == 2) - managed_dentry_set_managed(parent); -} - static int autofs_dir_rmdir(struct inode *dir, struct dentry *dentry) { struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb); struct autofs_info *ino = autofs_dentry_ino(dentry); + struct dentry *parent = dentry->d_parent; struct autofs_info *p_ino; pr_debug("dentry %p, removing %pd\n", dentry, dentry); @@ -705,15 +680,20 @@ static int autofs_dir_rmdir(struct inode *dir, struct dentry *dentry) d_drop(dentry); spin_unlock(&sbi->lookup_lock); - if (sbi->version < 5) - autofs_clear_leaf_automount_flags(dentry); - p_ino = autofs_dentry_ino(dentry->d_parent); p_ino->count--; dput(ino->dentry); d_inode(dentry)->i_size = 0; clear_nlink(d_inode(dentry)); + /* Set containing directory flags if it's now empty */ + if (autofs_dentry_ino(parent)->count == 1) { + /* Don't set or clear type indirect root */ + if (!IS_ROOT(parent) || + !autofs_type_indirect(sbi->type)) + managed_dentry_set_managed(parent); + } + if (dir->i_nlink) drop_nlink(dir); @@ -726,6 +706,7 @@ static int autofs_dir_mkdir(struct user_namespace *mnt_userns, { struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb); struct autofs_info *ino = autofs_dentry_ino(dentry); + struct dentry *parent = dentry->d_parent; struct autofs_info *p_ino; struct inode *inode; @@ -742,15 +723,21 @@ static int autofs_dir_mkdir(struct user_namespace *mnt_userns, return -ENOMEM; d_add(dentry, inode); - if (sbi->version < 5) - autofs_set_leaf_automount_flags(dentry); - dget(dentry); p_ino = autofs_dentry_ino(dentry->d_parent); p_ino->count++; inc_nlink(dir); dir->i_mtime = current_time(dir); + managed_dentry_set_managed(dentry); + /* Clear containing directory flags if it's no longer empty */ + if (autofs_dentry_ino(parent)->count == 2) { + /* Don't set or clear type indirect root */ + if (!IS_ROOT(parent) || + !autofs_type_indirect(sbi->type)) + managed_dentry_clear_managed(parent); + } + return 0; }