aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/dcache.h
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2011-01-14 13:45:21 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2011-01-15 20:05:03 -0500
commit9875cf806403fae66b2410a3c2cc820d97731e04 (patch)
tree6f9546b400716766af95e0f78e3d600e765b2b51 /include/linux/dcache.h
parent1a8edf40e7c3eee955e0dd0316a7c9d85e36f597 (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 'include/linux/dcache.h')
-rw-r--r--include/linux/dcache.h7
1 files changed, 6 insertions, 1 deletions
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 59fcd24b1468..ee6c26d142c3 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -167,6 +167,7 @@ struct dentry_operations {
167 void (*d_release)(struct dentry *); 167 void (*d_release)(struct dentry *);
168 void (*d_iput)(struct dentry *, struct inode *); 168 void (*d_iput)(struct dentry *, struct inode *);
169 char *(*d_dname)(struct dentry *, char *, int); 169 char *(*d_dname)(struct dentry *, char *, int);
170 struct vfsmount *(*d_automount)(struct path *);
170} ____cacheline_aligned; 171} ____cacheline_aligned;
171 172
172/* 173/*
@@ -205,13 +206,17 @@ struct dentry_operations {
205 206
206#define DCACHE_CANT_MOUNT 0x0100 207#define DCACHE_CANT_MOUNT 0x0100
207#define DCACHE_GENOCIDE 0x0200 208#define DCACHE_GENOCIDE 0x0200
208#define DCACHE_MOUNTED 0x0400 /* is a mountpoint */
209 209
210#define DCACHE_OP_HASH 0x1000 210#define DCACHE_OP_HASH 0x1000
211#define DCACHE_OP_COMPARE 0x2000 211#define DCACHE_OP_COMPARE 0x2000
212#define DCACHE_OP_REVALIDATE 0x4000 212#define DCACHE_OP_REVALIDATE 0x4000
213#define DCACHE_OP_DELETE 0x8000 213#define DCACHE_OP_DELETE 0x8000
214 214
215#define DCACHE_MOUNTED 0x10000 /* is a mountpoint */
216#define DCACHE_NEED_AUTOMOUNT 0x20000 /* handle automount on this dir */
217#define DCACHE_MANAGED_DENTRY \
218 (DCACHE_MOUNTED|DCACHE_NEED_AUTOMOUNT)
219
215extern seqlock_t rename_lock; 220extern seqlock_t rename_lock;
216 221
217static inline int dname_external(struct dentry *dentry) 222static inline int dname_external(struct dentry *dentry)