aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/filesystems/Locking2
-rw-r--r--Documentation/filesystems/vfs.txt14
-rw-r--r--fs/dcache.c5
-rw-r--r--fs/namei.c226
-rw-r--r--include/linux/dcache.h7
-rw-r--r--include/linux/fs.h2
6 files changed, 198 insertions, 58 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
23locking rules: 24locking 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
29d_release: no no yes no 30d_release: no no yes no
30d_iput: no no yes no 31d_iput: no no yes no
31d_dname: no no no no 32d_dname: no no no no
33d_automount: no no yes no
32 34
33--------------------------- inode_operations --------------------------- 35--------------------------- inode_operations ---------------------------
34prototypes: 36prototypes:
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
933Example : 947Example :
934 948
935static char *pipefs_dname(struct dentry *dent, char *buffer, int buflen) 949static char *pipefs_dname(struct dentry *dent, char *buffer, int buflen)
diff --git a/fs/dcache.c b/fs/dcache.c
index 0c6d5c549d84..51f7bb6463af 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1380,8 +1380,11 @@ EXPORT_SYMBOL(d_set_d_op);
1380static void __d_instantiate(struct dentry *dentry, struct inode *inode) 1380static void __d_instantiate(struct dentry *dentry, struct inode *inode)
1381{ 1381{
1382 spin_lock(&dentry->d_lock); 1382 spin_lock(&dentry->d_lock);
1383 if (inode) 1383 if (inode) {
1384 if (unlikely(IS_AUTOMOUNT(inode)))
1385 dentry->d_flags |= DCACHE_NEED_AUTOMOUNT;
1384 list_add(&dentry->d_alias, &inode->i_dentry); 1386 list_add(&dentry->d_alias, &inode->i_dentry);
1387 }
1385 dentry->d_inode = inode; 1388 dentry->d_inode = inode;
1386 dentry_rcuwalk_barrier(dentry); 1389 dentry_rcuwalk_barrier(dentry);
1387 spin_unlock(&dentry->d_lock); 1390 spin_unlock(&dentry->d_lock);
diff --git a/fs/namei.c b/fs/namei.c
index 529e917ad2fc..16109da68bbf 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -896,51 +896,120 @@ int follow_up(struct path *path)
896} 896}
897 897
898/* 898/*
899 * serialization is taken care of in namespace.c 899 * Perform an automount
900 * - return -EISDIR to tell follow_managed() to stop and return the path we
901 * were called with.
900 */ 902 */
901static void __follow_mount_rcu(struct nameidata *nd, struct path *path, 903static int follow_automount(struct path *path, unsigned flags,
902 struct inode **inode) 904 bool *need_mntput)
903{ 905{
904 while (d_mountpoint(path->dentry)) { 906 struct vfsmount *mnt;
905 struct vfsmount *mounted; 907
906 mounted = __lookup_mnt(path->mnt, path->dentry, 1); 908 if (!path->dentry->d_op || !path->dentry->d_op->d_automount)
907 if (!mounted) 909 return -EREMOTE;
908 return; 910
909 path->mnt = mounted; 911 /* We want to mount if someone is trying to open/create a file of any
910 path->dentry = mounted->mnt_root; 912 * type under the mountpoint, wants to traverse through the mountpoint
911 nd->seq = read_seqcount_begin(&path->dentry->d_seq); 913 * or wants to open the mounted directory.
912 *inode = path->dentry->d_inode; 914 *
915 * We don't want to mount if someone's just doing a stat and they've
916 * set AT_SYMLINK_NOFOLLOW - unless they're stat'ing a directory and
917 * appended a '/' to the name.
918 */
919 if (!(flags & LOOKUP_FOLLOW) &&
920 !(flags & (LOOKUP_CONTINUE | LOOKUP_DIRECTORY |
921 LOOKUP_OPEN | LOOKUP_CREATE)))
922 return -EISDIR;
923
924 current->total_link_count++;
925 if (current->total_link_count >= 40)
926 return -ELOOP;
927
928 mnt = path->dentry->d_op->d_automount(path);
929 if (IS_ERR(mnt)) {
930 /*
931 * The filesystem is allowed to return -EISDIR here to indicate
932 * it doesn't want to automount. For instance, autofs would do
933 * this so that its userspace daemon can mount on this dentry.
934 *
935 * However, we can only permit this if it's a terminal point in
936 * the path being looked up; if it wasn't then the remainder of
937 * the path is inaccessible and we should say so.
938 */
939 if (PTR_ERR(mnt) == -EISDIR && (flags & LOOKUP_CONTINUE))
940 return -EREMOTE;
941 return PTR_ERR(mnt);
913 } 942 }
914} 943 if (!mnt) /* mount collision */
944 return 0;
915 945
916static int __follow_mount(struct path *path) 946 if (mnt->mnt_sb == path->mnt->mnt_sb &&
917{ 947 mnt->mnt_root == path->dentry) {
918 int res = 0; 948 mntput(mnt);
919 while (d_mountpoint(path->dentry)) { 949 return -ELOOP;
920 struct vfsmount *mounted = lookup_mnt(path);
921 if (!mounted)
922 break;
923 dput(path->dentry);
924 if (res)
925 mntput(path->mnt);
926 path->mnt = mounted;
927 path->dentry = dget(mounted->mnt_root);
928 res = 1;
929 } 950 }
930 return res; 951
952 dput(path->dentry);
953 if (*need_mntput)
954 mntput(path->mnt);
955 path->mnt = mnt;
956 path->dentry = dget(mnt->mnt_root);
957 *need_mntput = true;
958 return 0;
931} 959}
932 960
933static void follow_mount(struct path *path) 961/*
962 * Handle a dentry that is managed in some way.
963 * - Flagged as mountpoint
964 * - Flagged as automount point
965 *
966 * This may only be called in refwalk mode.
967 *
968 * Serialization is taken care of in namespace.c
969 */
970static int follow_managed(struct path *path, unsigned flags)
934{ 971{
935 while (d_mountpoint(path->dentry)) { 972 unsigned managed;
936 struct vfsmount *mounted = lookup_mnt(path); 973 bool need_mntput = false;
937 if (!mounted) 974 int ret;
938 break; 975
939 dput(path->dentry); 976 /* Given that we're not holding a lock here, we retain the value in a
940 mntput(path->mnt); 977 * local variable for each dentry as we look at it so that we don't see
941 path->mnt = mounted; 978 * the components of that value change under us */
942 path->dentry = dget(mounted->mnt_root); 979 while (managed = ACCESS_ONCE(path->dentry->d_flags),
980 managed &= DCACHE_MANAGED_DENTRY,
981 unlikely(managed != 0)) {
982 /* Transit to a mounted filesystem. */
983 if (managed & DCACHE_MOUNTED) {
984 struct vfsmount *mounted = lookup_mnt(path);
985 if (mounted) {
986 dput(path->dentry);
987 if (need_mntput)
988 mntput(path->mnt);
989 path->mnt = mounted;
990 path->dentry = dget(mounted->mnt_root);
991 need_mntput = true;
992 continue;
993 }
994
995 /* Something is mounted on this dentry in another
996 * namespace and/or whatever was mounted there in this
997 * namespace got unmounted before we managed to get the
998 * vfsmount_lock */
999 }
1000
1001 /* Handle an automount point */
1002 if (managed & DCACHE_NEED_AUTOMOUNT) {
1003 ret = follow_automount(path, flags, &need_mntput);
1004 if (ret < 0)
1005 return ret == -EISDIR ? 0 : ret;
1006 continue;
1007 }
1008
1009 /* We didn't change the current path point */
1010 break;
943 } 1011 }
1012 return 0;
944} 1013}
945 1014
946int follow_down(struct path *path) 1015int follow_down(struct path *path)
@@ -958,13 +1027,37 @@ int follow_down(struct path *path)
958 return 0; 1027 return 0;
959} 1028}
960 1029
1030/*
1031 * Skip to top of mountpoint pile in rcuwalk mode. We abort the rcu-walk if we
1032 * meet an automount point and we're not walking to "..". True is returned to
1033 * continue, false to abort.
1034 */
1035static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
1036 struct inode **inode, bool reverse_transit)
1037{
1038 while (d_mountpoint(path->dentry)) {
1039 struct vfsmount *mounted;
1040 mounted = __lookup_mnt(path->mnt, path->dentry, 1);
1041 if (!mounted)
1042 break;
1043 path->mnt = mounted;
1044 path->dentry = mounted->mnt_root;
1045 nd->seq = read_seqcount_begin(&path->dentry->d_seq);
1046 *inode = path->dentry->d_inode;
1047 }
1048
1049 if (unlikely(path->dentry->d_flags & DCACHE_NEED_AUTOMOUNT))
1050 return reverse_transit;
1051 return true;
1052}
1053
961static int follow_dotdot_rcu(struct nameidata *nd) 1054static int follow_dotdot_rcu(struct nameidata *nd)
962{ 1055{
963 struct inode *inode = nd->inode; 1056 struct inode *inode = nd->inode;
964 1057
965 set_root_rcu(nd); 1058 set_root_rcu(nd);
966 1059
967 while(1) { 1060 while (1) {
968 if (nd->path.dentry == nd->root.dentry && 1061 if (nd->path.dentry == nd->root.dentry &&
969 nd->path.mnt == nd->root.mnt) { 1062 nd->path.mnt == nd->root.mnt) {
970 break; 1063 break;
@@ -987,12 +1080,28 @@ static int follow_dotdot_rcu(struct nameidata *nd)
987 nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq); 1080 nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq);
988 inode = nd->path.dentry->d_inode; 1081 inode = nd->path.dentry->d_inode;
989 } 1082 }
990 __follow_mount_rcu(nd, &nd->path, &inode); 1083 __follow_mount_rcu(nd, &nd->path, &inode, true);
991 nd->inode = inode; 1084 nd->inode = inode;
992 1085
993 return 0; 1086 return 0;
994} 1087}
995 1088
1089/*
1090 * Skip to top of mountpoint pile in refwalk mode for follow_dotdot()
1091 */
1092static void follow_mount(struct path *path)
1093{
1094 while (d_mountpoint(path->dentry)) {
1095 struct vfsmount *mounted = lookup_mnt(path);
1096 if (!mounted)
1097 break;
1098 dput(path->dentry);
1099 mntput(path->mnt);
1100 path->mnt = mounted;
1101 path->dentry = dget(mounted->mnt_root);
1102 }
1103}
1104
996static void follow_dotdot(struct nameidata *nd) 1105static void follow_dotdot(struct nameidata *nd)
997{ 1106{
998 set_root(nd); 1107 set_root(nd);
@@ -1057,12 +1166,14 @@ static int do_lookup(struct nameidata *nd, struct qstr *name,
1057 struct vfsmount *mnt = nd->path.mnt; 1166 struct vfsmount *mnt = nd->path.mnt;
1058 struct dentry *dentry, *parent = nd->path.dentry; 1167 struct dentry *dentry, *parent = nd->path.dentry;
1059 struct inode *dir; 1168 struct inode *dir;
1169 int err;
1170
1060 /* 1171 /*
1061 * See if the low-level filesystem might want 1172 * See if the low-level filesystem might want
1062 * to use its own hash.. 1173 * to use its own hash..
1063 */ 1174 */
1064 if (unlikely(parent->d_flags & DCACHE_OP_HASH)) { 1175 if (unlikely(parent->d_flags & DCACHE_OP_HASH)) {
1065 int err = parent->d_op->d_hash(parent, nd->inode, name); 1176 err = parent->d_op->d_hash(parent, nd->inode, name);
1066 if (err < 0) 1177 if (err < 0)
1067 return err; 1178 return err;
1068 } 1179 }
@@ -1092,20 +1203,25 @@ static int do_lookup(struct nameidata *nd, struct qstr *name,
1092done2: 1203done2:
1093 path->mnt = mnt; 1204 path->mnt = mnt;
1094 path->dentry = dentry; 1205 path->dentry = dentry;
1095 __follow_mount_rcu(nd, path, inode); 1206 if (likely(__follow_mount_rcu(nd, path, inode, false)))
1096 } else { 1207 return 0;
1097 dentry = __d_lookup(parent, name); 1208 if (nameidata_drop_rcu(nd))
1098 if (!dentry) 1209 return -ECHILD;
1099 goto need_lookup; 1210 /* fallthru */
1211 }
1212 dentry = __d_lookup(parent, name);
1213 if (!dentry)
1214 goto need_lookup;
1100found: 1215found:
1101 if (dentry->d_flags & DCACHE_OP_REVALIDATE) 1216 if (dentry->d_flags & DCACHE_OP_REVALIDATE)
1102 goto need_revalidate; 1217 goto need_revalidate;
1103done: 1218done:
1104 path->mnt = mnt; 1219 path->mnt = mnt;
1105 path->dentry = dentry; 1220 path->dentry = dentry;
1106 __follow_mount(path); 1221 err = follow_managed(path, nd->flags);
1107 *inode = path->dentry->d_inode; 1222 if (unlikely(err < 0))
1108 } 1223 return err;
1224 *inode = path->dentry->d_inode;
1109 return 0; 1225 return 0;
1110 1226
1111need_lookup: 1227need_lookup:
@@ -2203,11 +2319,9 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
2203 if (open_flag & O_EXCL) 2319 if (open_flag & O_EXCL)
2204 goto exit_dput; 2320 goto exit_dput;
2205 2321
2206 if (__follow_mount(path)) { 2322 error = follow_managed(path, nd->flags);
2207 error = -ELOOP; 2323 if (error < 0)
2208 if (open_flag & O_NOFOLLOW) 2324 goto exit_dput;
2209 goto exit_dput;
2210 }
2211 2325
2212 error = -ENOENT; 2326 error = -ENOENT;
2213 if (!path->dentry->d_inode) 2327 if (!path->dentry->d_inode)
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)
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 3984f2358d1f..4c00ed53be8f 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -242,6 +242,7 @@ struct inodes_stat_t {
242#define S_SWAPFILE 256 /* Do not truncate: swapon got its bmaps */ 242#define S_SWAPFILE 256 /* Do not truncate: swapon got its bmaps */
243#define S_PRIVATE 512 /* Inode is fs-internal */ 243#define S_PRIVATE 512 /* Inode is fs-internal */
244#define S_IMA 1024 /* Inode has an associated IMA struct */ 244#define S_IMA 1024 /* Inode has an associated IMA struct */
245#define S_AUTOMOUNT 2048 /* Automount/referral quasi-directory */
245 246
246/* 247/*
247 * Note that nosuid etc flags are inode-specific: setting some file-system 248 * Note that nosuid etc flags are inode-specific: setting some file-system
@@ -277,6 +278,7 @@ struct inodes_stat_t {
277#define IS_SWAPFILE(inode) ((inode)->i_flags & S_SWAPFILE) 278#define IS_SWAPFILE(inode) ((inode)->i_flags & S_SWAPFILE)
278#define IS_PRIVATE(inode) ((inode)->i_flags & S_PRIVATE) 279#define IS_PRIVATE(inode) ((inode)->i_flags & S_PRIVATE)
279#define IS_IMA(inode) ((inode)->i_flags & S_IMA) 280#define IS_IMA(inode) ((inode)->i_flags & S_IMA)
281#define IS_AUTOMOUNT(inode) ((inode)->i_flags & S_AUTOMOUNT)
280 282
281/* the read-only stuff doesn't really belong here, but any other place is 283/* the read-only stuff doesn't really belong here, but any other place is
282 probably as bad and I don't want to create yet another include file. */ 284 probably as bad and I don't want to create yet another include file. */