diff options
author | David Howells <dhowells@redhat.com> | 2011-01-14 13:45:21 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2011-01-15 20:05:03 -0500 |
commit | 9875cf806403fae66b2410a3c2cc820d97731e04 (patch) | |
tree | 6f9546b400716766af95e0f78e3d600e765b2b51 /Documentation/filesystems | |
parent | 1a8edf40e7c3eee955e0dd0316a7c9d85e36f597 (diff) |
Add a dentry op to handle automounting rather than abusing follow_link()
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
dentry flag (DCACHE_NEED_AUTOMOUNT).
This also makes it easier to add an AT_ flag to suppress terminal segment
automount during pathwalk and removes the need for the kludge code in the
pathwalk algorithm to handle directories with follow_link() semantics.
The ->d_automount() dentry operation:
struct vfsmount *(*d_automount)(struct path *mountpoint);
takes a pointer to the directory to be mounted upon, which is expected to
provide sufficient data to determine what should be mounted. If successful, it
should return the vfsmount struct it creates (which it should also have added
to the namespace using do_add_mount() or similar). If there's a collision with
another automount attempt, NULL should be returned. If the directory specified
by the parameter should be used directly rather than being mounted upon,
-EISDIR should be returned. In any other case, an error code should be
returned.
The ->d_automount() operation is called with no locks held and may sleep. At
this point the pathwalk algorithm will be in ref-walk mode.
Within fs/namei.c itself, a new pathwalk subroutine (follow_automount()) is
added to handle mountpoints. It will return -EREMOTE if the automount flag was
set, but no d_automount() op was supplied, -ELOOP if we've encountered too many
symlinks or mountpoints, -EISDIR if the walk point should be used without
mounting and 0 if successful. The path will be updated to point to the mounted
filesystem if a successful automount took place.
__follow_mount() is replaced by follow_managed() which is more generic
(especially with the patch that adds ->d_manage()). This handles transits from
directories during pathwalk, including automounting and skipping over
mountpoints (and holding processes with the next patch).
__follow_mount_rcu() will jump out of RCU-walk mode if it encounters an
automount point with nothing mounted on it.
follow_dotdot*() does not handle automounts as you don't want to trigger them
whilst following "..".
I've also extracted the mount/don't-mount logic from autofs4 and included it
here. It makes the mount go ahead anyway if someone calls open() or creat(),
tries to traverse the directory, tries to chdir/chroot/etc. into the directory,
or sticks a '/' on the end of the pathname. If they do a stat(), however,
they'll only trigger the automount if they didn't also say O_NOFOLLOW.
I've also added an inode flag (S_AUTOMOUNT) so that filesystems can mark their
inodes as automount points. This flag is automatically propagated to the
dentry as DCACHE_NEED_AUTOMOUNT by __d_instantiate(). This saves NFS and could
save AFS a private flag bit apiece, but is not strictly necessary. It would be
preferable to do the propagation in d_set_d_op(), but that doesn't normally
have access to the inode.
[AV: fixed breakage in case if __follow_mount_rcu() fails and nameidata_drop_rcu()
succeeds in RCU case of do_lookup(); we need to fall through to non-RCU case after
that, rather than just returning with ungrabbed *path]
Signed-off-by: David Howells <dhowells@redhat.com>
Was-Acked-by: Ian Kent <raven@themaw.net>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'Documentation/filesystems')
-rw-r--r-- | Documentation/filesystems/Locking | 2 | ||||
-rw-r--r-- | Documentation/filesystems/vfs.txt | 14 |
2 files changed, 16 insertions, 0 deletions
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index 977d8919cc69..5f0c52a07386 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking | |||
@@ -19,6 +19,7 @@ prototypes: | |||
19 | void (*d_release)(struct dentry *); | 19 | void (*d_release)(struct dentry *); |
20 | void (*d_iput)(struct dentry *, struct inode *); | 20 | void (*d_iput)(struct dentry *, struct inode *); |
21 | char *(*d_dname)((struct dentry *dentry, char *buffer, int buflen); | 21 | char *(*d_dname)((struct dentry *dentry, char *buffer, int buflen); |
22 | struct vfsmount *(*d_automount)(struct path *path); | ||
22 | 23 | ||
23 | locking rules: | 24 | locking rules: |
24 | rename_lock ->d_lock may block rcu-walk | 25 | rename_lock ->d_lock may block rcu-walk |
@@ -29,6 +30,7 @@ d_delete: no yes no no | |||
29 | d_release: no no yes no | 30 | d_release: no no yes no |
30 | d_iput: no no yes no | 31 | d_iput: no no yes no |
31 | d_dname: no no no no | 32 | d_dname: no no no no |
33 | d_automount: no no yes no | ||
32 | 34 | ||
33 | --------------------------- inode_operations --------------------------- | 35 | --------------------------- inode_operations --------------------------- |
34 | prototypes: | 36 | prototypes: |
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index cae6d27c9f5b..726a4f6fa3c9 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt | |||
@@ -864,6 +864,7 @@ struct dentry_operations { | |||
864 | void (*d_release)(struct dentry *); | 864 | void (*d_release)(struct dentry *); |
865 | void (*d_iput)(struct dentry *, struct inode *); | 865 | void (*d_iput)(struct dentry *, struct inode *); |
866 | char *(*d_dname)(struct dentry *, char *, int); | 866 | char *(*d_dname)(struct dentry *, char *, int); |
867 | struct vfsmount *(*d_automount)(struct path *); | ||
867 | }; | 868 | }; |
868 | 869 | ||
869 | d_revalidate: called when the VFS needs to revalidate a dentry. This | 870 | d_revalidate: called when the VFS needs to revalidate a dentry. This |
@@ -930,6 +931,19 @@ struct dentry_operations { | |||
930 | at the end of the buffer, and returns a pointer to the first char. | 931 | at the end of the buffer, and returns a pointer to the first char. |
931 | dynamic_dname() helper function is provided to take care of this. | 932 | dynamic_dname() helper function is provided to take care of this. |
932 | 933 | ||
934 | d_automount: called when an automount dentry is to be traversed (optional). | ||
935 | This should create a new VFS mount record, mount it on the directory | ||
936 | and return the record to the caller. The caller is supplied with a | ||
937 | path parameter giving the automount directory to describe the automount | ||
938 | target and the parent VFS mount record to provide inheritable mount | ||
939 | parameters. NULL should be returned if someone else managed to make | ||
940 | the automount first. If the automount failed, then an error code | ||
941 | should be returned. | ||
942 | |||
943 | This function is only used if DCACHE_NEED_AUTOMOUNT is set on the | ||
944 | dentry. This is set by __d_instantiate() if S_AUTOMOUNT is set on the | ||
945 | inode being added. | ||
946 | |||
933 | Example : | 947 | Example : |
934 | 948 | ||
935 | static char *pipefs_dname(struct dentry *dent, char *buffer, int buflen) | 949 | static char *pipefs_dname(struct dentry *dent, char *buffer, int buflen) |