From: David Howells <dhowells@redhat.com>
To: viro@ZenIV.linux.org.uk
Cc: linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org,
samba-technical@lists.samba.org, linux-kernel@vger.kernel.org,
dhowells@redhat.com, linux-fsdevel@vger.kernel.org,
linux-ext4@vger.kernel.org
Subject: [PATCH 12/18] xstat: Add a dentry op to handle automounting rather than abusing follow_link() [ver #6]
Date: Thu, 15 Jul 2010 03:17:24 +0100 [thread overview]
Message-ID: <20100715021723.5544.85730.stgit@warthog.procyon.org.uk> (raw)
In-Reply-To: <20100715021709.5544.64506.stgit@warthog.procyon.org.uk>
Add a dentry op (d_automount) to handle automounting directories rather than
abusing the follow_link() inode operation. The operation is keyed off a new
inode flag (S_AUTOMOUNT).
This makes it easier to add an AT_ flag to suppress terminal segment automount
during pathwalk. It should also remove the need for the kludge code in the
pathwalk algorithm to handle directories with follow_link() semantics.
I've only changed __follow_mount() to handle automount points, but it might be
necessary to change follow_mount() too. The latter is only used from
follow_dotdot(), but any automounts on ".." should be pinned whilst we're using
a child of it.
Note that autofs4's use of follow_mount() will need examining if this patch is
committed.
Signed-off-by: David Howells <dhowells@redhat.com>
---
Documentation/filesystems/Locking | 2 +
Documentation/filesystems/vfs.txt | 13 ++++++
fs/namei.c | 85 +++++++++++++++++++++++++++++--------
fs/stat.c | 2 +
include/linux/dcache.h | 5 ++
include/linux/fs.h | 2 +
6 files changed, 91 insertions(+), 18 deletions(-)
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index 96d4293..ccbfa98 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -16,6 +16,7 @@ prototypes:
void (*d_release)(struct dentry *);
void (*d_iput)(struct dentry *, struct inode *);
char *(*d_dname)((struct dentry *dentry, char *buffer, int buflen);
+ struct vfsmount *(*d_automount)(struct path *path);
locking rules:
none have BKL
@@ -27,6 +28,7 @@ d_delete: yes no yes no
d_release: no no no yes
d_iput: no no no yes
d_dname: no no no no
+d_automount: no no no yes
--------------------------- inode_operations ---------------------------
prototypes:
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index 94677e7..31a9e8f 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -851,6 +851,7 @@ struct dentry_operations {
void (*d_release)(struct dentry *);
void (*d_iput)(struct dentry *, struct inode *);
char *(*d_dname)(struct dentry *, char *, int);
+ struct vfsmount *(*d_automount)(struct path *);
};
d_revalidate: called when the VFS needs to revalidate a dentry. This
@@ -885,6 +886,18 @@ struct dentry_operations {
at the end of the buffer, and returns a pointer to the first char.
dynamic_dname() helper function is provided to take care of this.
+ d_automount: called when an automount dentry is to be traversed (optional).
+ This should create a new VFS mount record, mount it on the directory
+ and return the record to the caller. The caller is supplied with a
+ path parameter giving the automount directory to describe the automount
+ target and the parent VFS mount record to provide inheritable mount
+ parameters. NULL should be returned if someone else managed to make
+ the automount first. If the automount failed, then an error code
+ should be returned.
+
+ This function is only used if S_AUTOMOUNT is set on the inode to which
+ the dentry refers.
+
Example :
static char *pipefs_dname(struct dentry *dent, char *buffer, int buflen)
diff --git a/fs/namei.c b/fs/namei.c
index 868d0cb..fcec3c6 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -617,24 +617,71 @@ int follow_up(struct path *path)
return 1;
}
+/*
+ * Perform an automount
+ */
+static int follow_automount(struct path *path, int res)
+{
+ struct vfsmount *mnt;
+
+ if (!path->dentry->d_op || !path->dentry->d_op->d_automount)
+ return -EREMOTE;
+
+ current->total_link_count++;
+ if (current->total_link_count >= 40)
+ return -ELOOP;
+
+ mnt = path->dentry->d_op->d_automount(path);
+ if (IS_ERR(mnt))
+ return PTR_ERR(mnt);
+ if (!mnt) /* mount collision */
+ return 0;
+
+ if (mnt->mnt_sb == path->mnt->mnt_sb &&
+ mnt->mnt_root == path->dentry) {
+ mntput(mnt);
+ return -ELOOP;
+ }
+
+ dput(path->dentry);
+ if (res)
+ mntput(path->mnt);
+ path->mnt = mnt;
+ path->dentry = dget(mnt->mnt_root);
+ return 0;
+}
+
/* no need for dcache_lock, as serialization is taken care in
* namespace.c
*/
-static int __follow_mount(struct path *path)
+static int __follow_mount(struct path *path, unsigned nofollow)
{
- int res = 0;
- while (d_mountpoint(path->dentry)) {
- struct vfsmount *mounted = lookup_mnt(path);
- if (!mounted)
+ struct vfsmount *mounted;
+ int ret, res = 0;
+ for (;;) {
+ while (d_mountpoint(path->dentry)) {
+ if (nofollow)
+ return -ELOOP;
+ mounted = lookup_mnt(path);
+ if (!mounted)
+ break;
+ dput(path->dentry);
+ if (res)
+ mntput(path->mnt);
+ path->mnt = mounted;
+ path->dentry = dget(mounted->mnt_root);
+ res = 1;
+ }
+ if (!d_automount_point(path->dentry))
break;
- dput(path->dentry);
- if (res)
- mntput(path->mnt);
- path->mnt = mounted;
- path->dentry = dget(mounted->mnt_root);
+ if (nofollow)
+ return -ELOOP;
+ ret = follow_automount(path, res);
+ if (ret < 0)
+ return ret;
res = 1;
}
- return res;
+ return 0;
}
static void follow_mount(struct path *path)
@@ -702,6 +749,8 @@ static int do_lookup(struct nameidata *nd, struct qstr *name,
struct vfsmount *mnt = nd->path.mnt;
struct dentry *dentry, *parent;
struct inode *dir;
+ int ret;
+
/*
* See if the low-level filesystem might want
* to use its own hash..
@@ -720,8 +769,10 @@ static int do_lookup(struct nameidata *nd, struct qstr *name,
done:
path->mnt = mnt;
path->dentry = dentry;
- __follow_mount(path);
- return 0;
+ ret = __follow_mount(path, 0);
+ if (unlikely(ret < 0))
+ path_put(path);
+ return ret;
need_lookup:
parent = nd->path.dentry;
@@ -1721,11 +1772,9 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
if (open_flag & O_EXCL)
goto exit_dput;
- if (__follow_mount(path)) {
- error = -ELOOP;
- if (open_flag & O_NOFOLLOW)
- goto exit_dput;
- }
+ error = __follow_mount(path, open_flag & O_NOFOLLOW);
+ if (error < 0)
+ goto exit_dput;
error = -ENOENT;
if (!path->dentry->d_inode)
diff --git a/fs/stat.c b/fs/stat.c
index 89d72fc..bb0f538 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -43,6 +43,8 @@ void generic_fillattr(struct inode *inode, struct kstat *stat)
stat->blocks = inode->i_blocks;
stat->blksize = (1 << inode->i_blkbits);
stat->inode_flags = inode->i_sb->s_type->inode_flags;
+ if (IS_AUTOMOUNT(inode))
+ stat->inode_flags |= FS_AUTOMOUNT_FL;
stat->result_mask |= XSTAT_REQUEST__BASIC_STATS & ~XSTAT_REQUEST_RDEV;
if (unlikely(S_ISBLK(stat->mode) || S_ISCHR(stat->mode)))
stat->result_mask |= XSTAT_REQUEST_RDEV;
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index eebb617..5380bff 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -139,6 +139,7 @@ struct dentry_operations {
void (*d_release)(struct dentry *);
void (*d_iput)(struct dentry *, struct inode *);
char *(*d_dname)(struct dentry *, char *, int);
+ struct vfsmount *(*d_automount)(struct path *);
};
/* the dentry parameter passed to d_hash and d_compare is the parent
@@ -157,6 +158,7 @@ d_compare: no yes yes no
d_delete: no yes no no
d_release: no no no yes
d_iput: no no no yes
+d_automount: no no no yes
*/
/* d_flags entries */
@@ -389,6 +391,9 @@ static inline int d_mountpoint(struct dentry *dentry)
return dentry->d_mounted;
}
+#define d_automount_point(dentry) \
+ (dentry->d_inode && IS_AUTOMOUNT(dentry->d_inode))
+
extern struct vfsmount *lookup_mnt(struct path *);
extern struct dentry *lookup_create(struct nameidata *nd, int is_dir);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 951c36b..579ad9d 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -235,6 +235,7 @@ struct inodes_stat_t {
#define S_NOCMTIME 128 /* Do not update file c/mtime */
#define S_SWAPFILE 256 /* Do not truncate: swapon got its bmaps */
#define S_PRIVATE 512 /* Inode is fs-internal */
+#define S_AUTOMOUNT 1024 /* Automount/referral quasi-directory */
/*
* Note that nosuid etc flags are inode-specific: setting some file-system
@@ -269,6 +270,7 @@ struct inodes_stat_t {
#define IS_NOCMTIME(inode) ((inode)->i_flags & S_NOCMTIME)
#define IS_SWAPFILE(inode) ((inode)->i_flags & S_SWAPFILE)
#define IS_PRIVATE(inode) ((inode)->i_flags & S_PRIVATE)
+#define IS_AUTOMOUNT(inode) ((inode)->i_flags & S_AUTOMOUNT)
/* the read-only stuff doesn't really belong here, but any other place is
probably as bad and I don't want to create yet another include file. */
next prev parent reply other threads:[~2010-07-15 2:17 UTC|newest]
Thread overview: 133+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-07-15 2:17 [PATCH 00/18] Extended file stat functions [ver #6] David Howells
2010-07-15 2:17 ` [PATCH 01/18] Mark arguments to certain syscalls as being const " David Howells
2010-07-15 2:17 ` [PATCH 02/18] xstat: Add a pair of system calls to make extended file stats available " David Howells
2010-07-15 20:35 ` Arnd Bergmann
2010-07-15 21:53 ` David Howells
2010-07-16 6:22 ` Mark Harris
2010-07-16 10:24 ` David Howells
2010-07-16 11:02 ` Arnd Bergmann
2010-07-16 12:38 ` David Howells
2010-07-16 13:32 ` Arnd Bergmann
2010-07-17 5:51 ` Mark Harris
2010-07-17 9:00 ` Arnd Bergmann
[not found] ` <20100717055130.GA2053-EJgEOVOPJGBzbRFIqnYvSA@public.gmane.org>
2010-07-17 9:49 ` David Howells
2010-07-16 10:46 ` Arnd Bergmann
2010-07-16 15:10 ` David Howells
2010-07-18 8:48 ` Christoph Hellwig
2010-07-22 10:52 ` Jan Engelhardt
2010-07-22 12:25 ` David Howells
2010-07-19 14:05 ` David Howells
2010-07-19 15:17 ` Linus Torvalds
2010-07-19 16:15 ` David Howells
2010-07-19 16:51 ` Linus Torvalds
2010-07-19 17:26 ` David Howells
2010-07-19 17:46 ` Linus Torvalds
2010-07-20 8:28 ` Andreas Dilger
2010-07-22 10:35 ` Jan Engelhardt
2010-07-22 12:14 ` David Howells
2010-07-22 12:17 ` Volker Lendecke
2010-07-22 13:05 ` Jan Engelhardt
2010-07-22 15:14 ` Linus Torvalds
2010-07-22 15:36 ` Volker Lendecke
2010-07-22 15:47 ` Linus Torvalds
2010-07-22 16:06 ` Greg Freemyer
2010-07-22 16:07 ` Greg Freemyer
2010-07-22 16:25 ` Jan Engelhardt
2010-07-22 16:27 ` Jeremy Allison
2010-07-22 16:40 ` Linus Torvalds
2010-07-22 16:58 ` Trond Myklebust
2010-07-22 18:02 ` Jeremy Allison
2010-07-22 18:04 ` Volker Lendecke
2010-07-22 18:07 ` Jeremy Allison
2010-07-22 18:59 ` Trond Myklebust
2010-07-30 17:55 ` Phil Pishioneri
2010-07-30 18:11 ` Trond Myklebust
2010-07-30 18:19 ` Phil Pishioneri
2010-07-31 18:41 ` Andreas Dilger
2010-07-31 18:48 ` Jan Engelhardt
2010-07-31 19:03 ` Trond Myklebust
2010-07-31 21:20 ` Jan Engelhardt
2010-08-01 13:17 ` Jeff Layton
2010-07-22 18:05 ` Jan Engelhardt
[not found] ` <alpine.LSU.2.01.1007222004430.4215-SHaQjdQMGhDmsUXKMKRlFA@public.gmane.org>
2010-07-22 18:07 ` Jeremy Allison
2010-07-22 19:18 ` John Stoffel
2010-07-22 17:03 ` Jan Engelhardt
2010-07-22 17:16 ` Trond Myklebust
2010-07-22 17:36 ` Jan Engelhardt
2010-07-22 17:24 ` Linus Torvalds
2010-07-22 18:15 ` Jeremy Allison
2010-07-22 18:21 ` Benny Halevy
2010-07-22 18:45 ` Greg Freemyer
2010-07-22 19:53 ` Benny Halevy
2010-07-22 18:41 ` Greg Freemyer
2010-07-28 1:15 ` Neil Brown
2010-07-28 17:28 ` David Howells
2010-07-28 23:04 ` Neil Brown
2010-07-30 18:38 ` J. Bruce Fields
2010-08-01 13:40 ` Jeff Layton
2010-08-02 14:09 ` Greg Freemyer
2010-08-02 14:42 ` Jeff Layton
2010-07-29 16:15 ` David Howells
2010-08-03 1:13 ` Neil Brown
2010-07-22 17:12 ` Jim Rees
2010-07-22 17:32 ` Linus Torvalds
2010-07-23 1:03 ` tridge
2010-07-23 1:21 ` Ted Ts'o
2010-07-23 2:12 ` tridge
2010-07-23 9:14 ` Björn Jacke
2010-07-30 21:22 ` utz lehmann
2010-07-31 8:08 ` Jan Engelhardt
2010-07-31 14:43 ` utz lehmann
2010-08-01 13:25 ` Jeff Layton
2010-08-05 23:52 ` Jeremy Allison
2010-08-06 3:38 ` Neil Brown
2010-08-06 3:55 ` Steve French
2010-08-06 11:18 ` Jeff Layton
2010-08-06 23:30 ` Neil Brown
2010-08-06 23:58 ` Steve French
2010-08-07 0:29 ` Neil Brown
2010-08-07 2:42 ` Steve French
2010-08-07 2:54 ` Steve French
2010-08-07 3:32 ` Neil Brown
2010-08-07 10:34 ` Jeff Layton
2010-08-07 11:04 ` Neil Brown
2010-08-08 12:12 ` Jeremy Allison
2010-08-08 12:53 ` Jeff Layton
2010-08-08 13:05 ` Jeremy Allison
2010-08-13 12:54 ` J. Bruce Fields
2010-08-13 17:54 ` Jeremy Allison
2010-08-13 18:09 ` Steve French
2010-08-13 19:06 ` Jan Engelhardt
2010-08-13 19:19 ` Jeremy Allison
2010-08-16 18:04 ` J. Bruce Fields
2010-08-16 18:08 ` J. Bruce Fields
2010-08-16 19:07 ` Jeremy Allison
2010-08-08 23:07 ` Neil Brown
[not found] ` <AANLkTimwIq0pBhCeOjOVjB0y <1280603032.3125.24.camel@heimdal.trondhjem.org>
[not found] ` <1280603032.3125.24.camel-rJ7iovZKK19ZJLDQqaL3InhyD016LWXt@public.gmane.org>
2010-08-01 16:18 ` utz lehmann
2010-07-22 15:46 ` Jan Engelhardt
2010-07-22 16:06 ` David Howells
[not found] ` <AANLkTikBCXK6uEw <AANLkTimdFCGSKLn7aGMpBMIauHTsHY7hpAAmpo6uTcnD@mail.gmail.com>
2010-07-31 16:53 ` David Howells
2010-07-31 18:05 ` utz lehmann
2010-07-31 19:26 ` David Howells
2010-07-15 2:17 ` [PATCH 03/18] AFS: Use i_generation not i_version for the vnode uniquifier " David Howells
2010-07-15 2:17 ` [PATCH 04/18] xstat: AFS: Return extended attributes " David Howells
2010-07-15 2:17 ` [PATCH 05/18] xstat: eCryptFS: " David Howells
2010-07-15 2:17 ` [PATCH 06/18] xstat: Ext4: " David Howells
2010-07-15 2:17 ` [PATCH 07/18] xstat: NFS: " David Howells
2010-07-15 2:17 ` [PATCH 08/18] xstat: CIFS: " David Howells
2010-07-15 2:17 ` [PATCH 09/18] xstat: Make special system filesystems return FS_SPECIAL_FL " David Howells
2010-07-18 8:49 ` Christoph Hellwig
2010-07-19 14:09 ` David Howells
2010-07-27 13:41 ` David Howells
2010-07-15 2:17 ` [PATCH 10/18] xstat: Make network filesystems return FS_REMOTE_FL " David Howells
2010-07-15 2:17 ` [PATCH 11/18] xstat: Make automounter filesystems return FS_AUTOMOUNT_FL " David Howells
2010-07-15 2:17 ` David Howells [this message]
2010-07-18 8:50 ` [PATCH 12/18] xstat: Add a dentry op to handle automounting rather than abusing follow_link() " Christoph Hellwig
2010-07-19 14:10 ` David Howells
2010-07-15 2:17 ` [PATCH 13/18] xstat: AFS: Use d_automount() " David Howells
2010-07-15 2:17 ` [PATCH 14/18] xstat: NFS: " David Howells
2010-07-15 2:17 ` [PATCH 15/18] xstat: CIFS: " David Howells
2010-07-15 2:17 ` [PATCH 16/18] xstat: Remove the automount through follow_link() kludge code from pathwalk " David Howells
2010-07-15 2:17 ` [PATCH 17/18] xstat: Add an AT_NO_AUTOMOUNT flag to suppress terminal automount " David Howells
[not found] ` <20100715021709.5544.64506.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
2010-07-15 2:17 ` [PATCH 18/18] xstat: Provide a mechanism to gather extra results for [f]xstat() " David Howells
[not found] ` <20100715021730.5544.68442.stgit-S6HVgzuS8uM4Awkfq6JHfwNdhmdF6hFW@public.gmane.org>
2010-07-18 8:51 ` Christoph Hellwig
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20100715021723.5544.85730.stgit@warthog.procyon.org.uk \
--to=dhowells@redhat.com \
--cc=linux-cifs@vger.kernel.org \
--cc=linux-ext4@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-nfs@vger.kernel.org \
--cc=samba-technical@lists.samba.org \
--cc=viro@ZenIV.linux.org.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).