aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-09-07 17:36:57 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-07 17:36:57 -0400
commitdc0755cdb16cb129c4054c85d62bce83a18bcbcf (patch)
tree17f585ce18524ec029cb1169cdba256c83288101
parentc7c4591db64dbd1e504bc4e2806d7ef290a3c81b (diff)
parentf0d3b3ded999daae1cf451d051018038c0a05bae (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs pile 2 (of many) from Al Viro: "Mostly Miklos' series this time" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: constify dcache.c inlined helpers where possible fuse: drop dentry on failed revalidate fuse: clean up return in fuse_dentry_revalidate() fuse: use d_materialise_unique() sysfs: use check_submounts_and_drop() nfs: use check_submounts_and_drop() gfs2: use check_submounts_and_drop() afs: use check_submounts_and_drop() vfs: check unlinked ancestors before mount vfs: check submounts and drop atomically vfs: add d_walk() vfs: restructure d_genocide()
-rw-r--r--fs/afs/dir.c10
-rw-r--r--fs/dcache.c411
-rw-r--r--fs/fuse/dir.c97
-rw-r--r--fs/gfs2/dentry.c9
-rw-r--r--fs/internal.h1
-rw-r--r--fs/namespace.c11
-rw-r--r--fs/nfs/dir.c9
-rw-r--r--fs/sysfs/dir.c20
-rw-r--r--include/linux/dcache.h13
9 files changed, 323 insertions, 258 deletions
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index 34494fbead0a..0b74d3176ab7 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -685,16 +685,12 @@ not_found:
685 spin_unlock(&dentry->d_lock); 685 spin_unlock(&dentry->d_lock);
686 686
687out_bad: 687out_bad:
688 if (dentry->d_inode) { 688 /* don't unhash if we have submounts */
689 /* don't unhash if we have submounts */ 689 if (check_submounts_and_drop(dentry) != 0)
690 if (have_submounts(dentry)) 690 goto out_skip;
691 goto out_skip;
692 }
693 691
694 _debug("dropping dentry %s/%s", 692 _debug("dropping dentry %s/%s",
695 parent->d_name.name, dentry->d_name.name); 693 parent->d_name.name, dentry->d_name.name);
696 shrink_dcache_parent(dentry);
697 d_drop(dentry);
698 dput(parent); 694 dput(parent);
699 key_put(key); 695 key_put(key);
700 696
diff --git a/fs/dcache.c b/fs/dcache.c
index 5aa53bc056ba..761e31bacbc2 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1031,34 +1031,56 @@ static struct dentry *try_to_ascend(struct dentry *old, int locked, unsigned seq
1031 return new; 1031 return new;
1032} 1032}
1033 1033
1034/**
1035 * enum d_walk_ret - action to talke during tree walk
1036 * @D_WALK_CONTINUE: contrinue walk
1037 * @D_WALK_QUIT: quit walk
1038 * @D_WALK_NORETRY: quit when retry is needed
1039 * @D_WALK_SKIP: skip this dentry and its children
1040 */
1041enum d_walk_ret {
1042 D_WALK_CONTINUE,
1043 D_WALK_QUIT,
1044 D_WALK_NORETRY,
1045 D_WALK_SKIP,
1046};
1034 1047
1035/*
1036 * Search for at least 1 mount point in the dentry's subdirs.
1037 * We descend to the next level whenever the d_subdirs
1038 * list is non-empty and continue searching.
1039 */
1040
1041/** 1048/**
1042 * have_submounts - check for mounts over a dentry 1049 * d_walk - walk the dentry tree
1043 * @parent: dentry to check. 1050 * @parent: start of walk
1051 * @data: data passed to @enter() and @finish()
1052 * @enter: callback when first entering the dentry
1053 * @finish: callback when successfully finished the walk
1044 * 1054 *
1045 * Return true if the parent or its subdirectories contain 1055 * The @enter() and @finish() callbacks are called with d_lock held.
1046 * a mount point
1047 */ 1056 */
1048int have_submounts(struct dentry *parent) 1057static void d_walk(struct dentry *parent, void *data,
1058 enum d_walk_ret (*enter)(void *, struct dentry *),
1059 void (*finish)(void *))
1049{ 1060{
1050 struct dentry *this_parent; 1061 struct dentry *this_parent;
1051 struct list_head *next; 1062 struct list_head *next;
1052 unsigned seq; 1063 unsigned seq;
1053 int locked = 0; 1064 int locked = 0;
1065 enum d_walk_ret ret;
1066 bool retry = true;
1054 1067
1055 seq = read_seqbegin(&rename_lock); 1068 seq = read_seqbegin(&rename_lock);
1056again: 1069again:
1057 this_parent = parent; 1070 this_parent = parent;
1058
1059 if (d_mountpoint(parent))
1060 goto positive;
1061 spin_lock(&this_parent->d_lock); 1071 spin_lock(&this_parent->d_lock);
1072
1073 ret = enter(data, this_parent);
1074 switch (ret) {
1075 case D_WALK_CONTINUE:
1076 break;
1077 case D_WALK_QUIT:
1078 case D_WALK_SKIP:
1079 goto out_unlock;
1080 case D_WALK_NORETRY:
1081 retry = false;
1082 break;
1083 }
1062repeat: 1084repeat:
1063 next = this_parent->d_subdirs.next; 1085 next = this_parent->d_subdirs.next;
1064resume: 1086resume:
@@ -1068,12 +1090,22 @@ resume:
1068 next = tmp->next; 1090 next = tmp->next;
1069 1091
1070 spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); 1092 spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
1071 /* Have we found a mount point ? */ 1093
1072 if (d_mountpoint(dentry)) { 1094 ret = enter(data, dentry);
1095 switch (ret) {
1096 case D_WALK_CONTINUE:
1097 break;
1098 case D_WALK_QUIT:
1073 spin_unlock(&dentry->d_lock); 1099 spin_unlock(&dentry->d_lock);
1074 spin_unlock(&this_parent->d_lock); 1100 goto out_unlock;
1075 goto positive; 1101 case D_WALK_NORETRY:
1102 retry = false;
1103 break;
1104 case D_WALK_SKIP:
1105 spin_unlock(&dentry->d_lock);
1106 continue;
1076 } 1107 }
1108
1077 if (!list_empty(&dentry->d_subdirs)) { 1109 if (!list_empty(&dentry->d_subdirs)) {
1078 spin_unlock(&this_parent->d_lock); 1110 spin_unlock(&this_parent->d_lock);
1079 spin_release(&dentry->d_lock.dep_map, 1, _RET_IP_); 1111 spin_release(&dentry->d_lock.dep_map, 1, _RET_IP_);
@@ -1094,29 +1126,97 @@ resume:
1094 next = child->d_u.d_child.next; 1126 next = child->d_u.d_child.next;
1095 goto resume; 1127 goto resume;
1096 } 1128 }
1097 spin_unlock(&this_parent->d_lock); 1129 if (!locked && read_seqretry(&rename_lock, seq)) {
1098 if (!locked && read_seqretry(&rename_lock, seq)) 1130 spin_unlock(&this_parent->d_lock);
1099 goto rename_retry;
1100 if (locked)
1101 write_sequnlock(&rename_lock);
1102 return 0; /* No mount points found in tree */
1103positive:
1104 if (!locked && read_seqretry(&rename_lock, seq))
1105 goto rename_retry; 1131 goto rename_retry;
1132 }
1133 if (finish)
1134 finish(data);
1135
1136out_unlock:
1137 spin_unlock(&this_parent->d_lock);
1106 if (locked) 1138 if (locked)
1107 write_sequnlock(&rename_lock); 1139 write_sequnlock(&rename_lock);
1108 return 1; 1140 return;
1109 1141
1110rename_retry: 1142rename_retry:
1143 if (!retry)
1144 return;
1111 if (locked) 1145 if (locked)
1112 goto again; 1146 goto again;
1113 locked = 1; 1147 locked = 1;
1114 write_seqlock(&rename_lock); 1148 write_seqlock(&rename_lock);
1115 goto again; 1149 goto again;
1116} 1150}
1151
1152/*
1153 * Search for at least 1 mount point in the dentry's subdirs.
1154 * We descend to the next level whenever the d_subdirs
1155 * list is non-empty and continue searching.
1156 */
1157
1158/**
1159 * have_submounts - check for mounts over a dentry
1160 * @parent: dentry to check.
1161 *
1162 * Return true if the parent or its subdirectories contain
1163 * a mount point
1164 */
1165
1166static enum d_walk_ret check_mount(void *data, struct dentry *dentry)
1167{
1168 int *ret = data;
1169 if (d_mountpoint(dentry)) {
1170 *ret = 1;
1171 return D_WALK_QUIT;
1172 }
1173 return D_WALK_CONTINUE;
1174}
1175
1176int have_submounts(struct dentry *parent)
1177{
1178 int ret = 0;
1179
1180 d_walk(parent, &ret, check_mount, NULL);
1181
1182 return ret;
1183}
1117EXPORT_SYMBOL(have_submounts); 1184EXPORT_SYMBOL(have_submounts);
1118 1185
1119/* 1186/*
1187 * Called by mount code to set a mountpoint and check if the mountpoint is
1188 * reachable (e.g. NFS can unhash a directory dentry and then the complete
1189 * subtree can become unreachable).
1190 *
1191 * Only one of check_submounts_and_drop() and d_set_mounted() must succeed. For
1192 * this reason take rename_lock and d_lock on dentry and ancestors.
1193 */
1194int d_set_mounted(struct dentry *dentry)
1195{
1196 struct dentry *p;
1197 int ret = -ENOENT;
1198 write_seqlock(&rename_lock);
1199 for (p = dentry->d_parent; !IS_ROOT(p); p = p->d_parent) {
1200 /* Need exclusion wrt. check_submounts_and_drop() */
1201 spin_lock(&p->d_lock);
1202 if (unlikely(d_unhashed(p))) {
1203 spin_unlock(&p->d_lock);
1204 goto out;
1205 }
1206 spin_unlock(&p->d_lock);
1207 }
1208 spin_lock(&dentry->d_lock);
1209 if (!d_unlinked(dentry)) {
1210 dentry->d_flags |= DCACHE_MOUNTED;
1211 ret = 0;
1212 }
1213 spin_unlock(&dentry->d_lock);
1214out:
1215 write_sequnlock(&rename_lock);
1216 return ret;
1217}
1218
1219/*
1120 * Search the dentry child list of the specified parent, 1220 * Search the dentry child list of the specified parent,
1121 * and move any unused dentries to the end of the unused 1221 * and move any unused dentries to the end of the unused
1122 * list for prune_dcache(). We descend to the next level 1222 * list for prune_dcache(). We descend to the next level
@@ -1130,93 +1230,46 @@ EXPORT_SYMBOL(have_submounts);
1130 * drop the lock and return early due to latency 1230 * drop the lock and return early due to latency
1131 * constraints. 1231 * constraints.
1132 */ 1232 */
1133static int select_parent(struct dentry *parent, struct list_head *dispose)
1134{
1135 struct dentry *this_parent;
1136 struct list_head *next;
1137 unsigned seq;
1138 int found = 0;
1139 int locked = 0;
1140 1233
1141 seq = read_seqbegin(&rename_lock); 1234struct select_data {
1142again: 1235 struct dentry *start;
1143 this_parent = parent; 1236 struct list_head dispose;
1144 spin_lock(&this_parent->d_lock); 1237 int found;
1145repeat: 1238};
1146 next = this_parent->d_subdirs.next;
1147resume:
1148 while (next != &this_parent->d_subdirs) {
1149 struct list_head *tmp = next;
1150 struct dentry *dentry = list_entry(tmp, struct dentry, d_u.d_child);
1151 next = tmp->next;
1152
1153 spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
1154 1239
1155 /* 1240static enum d_walk_ret select_collect(void *_data, struct dentry *dentry)
1156 * move only zero ref count dentries to the dispose list. 1241{
1157 * 1242 struct select_data *data = _data;
1158 * Those which are presently on the shrink list, being processed 1243 enum d_walk_ret ret = D_WALK_CONTINUE;
1159 * by shrink_dentry_list(), shouldn't be moved. Otherwise the
1160 * loop in shrink_dcache_parent() might not make any progress
1161 * and loop forever.
1162 */
1163 if (dentry->d_lockref.count) {
1164 dentry_lru_del(dentry);
1165 } else if (!(dentry->d_flags & DCACHE_SHRINK_LIST)) {
1166 dentry_lru_move_list(dentry, dispose);
1167 dentry->d_flags |= DCACHE_SHRINK_LIST;
1168 found++;
1169 }
1170 /*
1171 * We can return to the caller if we have found some (this
1172 * ensures forward progress). We'll be coming back to find
1173 * the rest.
1174 */
1175 if (found && need_resched()) {
1176 spin_unlock(&dentry->d_lock);
1177 goto out;
1178 }
1179 1244
1180 /* 1245 if (data->start == dentry)
1181 * Descend a level if the d_subdirs list is non-empty. 1246 goto out;
1182 */
1183 if (!list_empty(&dentry->d_subdirs)) {
1184 spin_unlock(&this_parent->d_lock);
1185 spin_release(&dentry->d_lock.dep_map, 1, _RET_IP_);
1186 this_parent = dentry;
1187 spin_acquire(&this_parent->d_lock.dep_map, 0, 1, _RET_IP_);
1188 goto repeat;
1189 }
1190 1247
1191 spin_unlock(&dentry->d_lock);
1192 }
1193 /* 1248 /*
1194 * All done at this level ... ascend and resume the search. 1249 * move only zero ref count dentries to the dispose list.
1250 *
1251 * Those which are presently on the shrink list, being processed
1252 * by shrink_dentry_list(), shouldn't be moved. Otherwise the
1253 * loop in shrink_dcache_parent() might not make any progress
1254 * and loop forever.
1195 */ 1255 */
1196 if (this_parent != parent) { 1256 if (dentry->d_lockref.count) {
1197 struct dentry *child = this_parent; 1257 dentry_lru_del(dentry);
1198 this_parent = try_to_ascend(this_parent, locked, seq); 1258 } else if (!(dentry->d_flags & DCACHE_SHRINK_LIST)) {
1199 if (!this_parent) 1259 dentry_lru_move_list(dentry, &data->dispose);
1200 goto rename_retry; 1260 dentry->d_flags |= DCACHE_SHRINK_LIST;
1201 next = child->d_u.d_child.next; 1261 data->found++;
1202 goto resume; 1262 ret = D_WALK_NORETRY;
1203 } 1263 }
1264 /*
1265 * We can return to the caller if we have found some (this
1266 * ensures forward progress). We'll be coming back to find
1267 * the rest.
1268 */
1269 if (data->found && need_resched())
1270 ret = D_WALK_QUIT;
1204out: 1271out:
1205 spin_unlock(&this_parent->d_lock); 1272 return ret;
1206 if (!locked && read_seqretry(&rename_lock, seq))
1207 goto rename_retry;
1208 if (locked)
1209 write_sequnlock(&rename_lock);
1210 return found;
1211
1212rename_retry:
1213 if (found)
1214 return found;
1215 if (locked)
1216 goto again;
1217 locked = 1;
1218 write_seqlock(&rename_lock);
1219 goto again;
1220} 1273}
1221 1274
1222/** 1275/**
@@ -1225,18 +1278,90 @@ rename_retry:
1225 * 1278 *
1226 * Prune the dcache to remove unused children of the parent dentry. 1279 * Prune the dcache to remove unused children of the parent dentry.
1227 */ 1280 */
1228void shrink_dcache_parent(struct dentry * parent) 1281void shrink_dcache_parent(struct dentry *parent)
1229{ 1282{
1230 LIST_HEAD(dispose); 1283 for (;;) {
1231 int found; 1284 struct select_data data;
1285
1286 INIT_LIST_HEAD(&data.dispose);
1287 data.start = parent;
1288 data.found = 0;
1232 1289
1233 while ((found = select_parent(parent, &dispose)) != 0) { 1290 d_walk(parent, &data, select_collect, NULL);
1234 shrink_dentry_list(&dispose); 1291 if (!data.found)
1292 break;
1293
1294 shrink_dentry_list(&data.dispose);
1235 cond_resched(); 1295 cond_resched();
1236 } 1296 }
1237} 1297}
1238EXPORT_SYMBOL(shrink_dcache_parent); 1298EXPORT_SYMBOL(shrink_dcache_parent);
1239 1299
1300static enum d_walk_ret check_and_collect(void *_data, struct dentry *dentry)
1301{
1302 struct select_data *data = _data;
1303
1304 if (d_mountpoint(dentry)) {
1305 data->found = -EBUSY;
1306 return D_WALK_QUIT;
1307 }
1308
1309 return select_collect(_data, dentry);
1310}
1311
1312static void check_and_drop(void *_data)
1313{
1314 struct select_data *data = _data;
1315
1316 if (d_mountpoint(data->start))
1317 data->found = -EBUSY;
1318 if (!data->found)
1319 __d_drop(data->start);
1320}
1321
1322/**
1323 * check_submounts_and_drop - prune dcache, check for submounts and drop
1324 *
1325 * All done as a single atomic operation relative to has_unlinked_ancestor().
1326 * Returns 0 if successfully unhashed @parent. If there were submounts then
1327 * return -EBUSY.
1328 *
1329 * @dentry: dentry to prune and drop
1330 */
1331int check_submounts_and_drop(struct dentry *dentry)
1332{
1333 int ret = 0;
1334
1335 /* Negative dentries can be dropped without further checks */
1336 if (!dentry->d_inode) {
1337 d_drop(dentry);
1338 goto out;
1339 }
1340
1341 for (;;) {
1342 struct select_data data;
1343
1344 INIT_LIST_HEAD(&data.dispose);
1345 data.start = dentry;
1346 data.found = 0;
1347
1348 d_walk(dentry, &data, check_and_collect, check_and_drop);
1349 ret = data.found;
1350
1351 if (!list_empty(&data.dispose))
1352 shrink_dentry_list(&data.dispose);
1353
1354 if (ret <= 0)
1355 break;
1356
1357 cond_resched();
1358 }
1359
1360out:
1361 return ret;
1362}
1363EXPORT_SYMBOL(check_submounts_and_drop);
1364
1240/** 1365/**
1241 * __d_alloc - allocate a dcache entry 1366 * __d_alloc - allocate a dcache entry
1242 * @sb: filesystem it will belong to 1367 * @sb: filesystem it will belong to
@@ -2928,68 +3053,24 @@ int is_subdir(struct dentry *new_dentry, struct dentry *old_dentry)
2928 return result; 3053 return result;
2929} 3054}
2930 3055
2931void d_genocide(struct dentry *root) 3056static enum d_walk_ret d_genocide_kill(void *data, struct dentry *dentry)
2932{ 3057{
2933 struct dentry *this_parent; 3058 struct dentry *root = data;
2934 struct list_head *next; 3059 if (dentry != root) {
2935 unsigned seq; 3060 if (d_unhashed(dentry) || !dentry->d_inode)
2936 int locked = 0; 3061 return D_WALK_SKIP;
2937 3062
2938 seq = read_seqbegin(&rename_lock);
2939again:
2940 this_parent = root;
2941 spin_lock(&this_parent->d_lock);
2942repeat:
2943 next = this_parent->d_subdirs.next;
2944resume:
2945 while (next != &this_parent->d_subdirs) {
2946 struct list_head *tmp = next;
2947 struct dentry *dentry = list_entry(tmp, struct dentry, d_u.d_child);
2948 next = tmp->next;
2949
2950 spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
2951 if (d_unhashed(dentry) || !dentry->d_inode) {
2952 spin_unlock(&dentry->d_lock);
2953 continue;
2954 }
2955 if (!list_empty(&dentry->d_subdirs)) {
2956 spin_unlock(&this_parent->d_lock);
2957 spin_release(&dentry->d_lock.dep_map, 1, _RET_IP_);
2958 this_parent = dentry;
2959 spin_acquire(&this_parent->d_lock.dep_map, 0, 1, _RET_IP_);
2960 goto repeat;
2961 }
2962 if (!(dentry->d_flags & DCACHE_GENOCIDE)) { 3063 if (!(dentry->d_flags & DCACHE_GENOCIDE)) {
2963 dentry->d_flags |= DCACHE_GENOCIDE; 3064 dentry->d_flags |= DCACHE_GENOCIDE;
2964 dentry->d_lockref.count--; 3065 dentry->d_lockref.count--;
2965 } 3066 }
2966 spin_unlock(&dentry->d_lock);
2967 }
2968 if (this_parent != root) {
2969 struct dentry *child = this_parent;
2970 if (!(this_parent->d_flags & DCACHE_GENOCIDE)) {
2971 this_parent->d_flags |= DCACHE_GENOCIDE;
2972 this_parent->d_lockref.count--;
2973 }
2974 this_parent = try_to_ascend(this_parent, locked, seq);
2975 if (!this_parent)
2976 goto rename_retry;
2977 next = child->d_u.d_child.next;
2978 goto resume;
2979 } 3067 }
2980 spin_unlock(&this_parent->d_lock); 3068 return D_WALK_CONTINUE;
2981 if (!locked && read_seqretry(&rename_lock, seq)) 3069}
2982 goto rename_retry;
2983 if (locked)
2984 write_sequnlock(&rename_lock);
2985 return;
2986 3070
2987rename_retry: 3071void d_genocide(struct dentry *parent)
2988 if (locked) 3072{
2989 goto again; 3073 d_walk(parent, parent, d_genocide_kill, NULL);
2990 locked = 1;
2991 write_seqlock(&rename_lock);
2992 goto again;
2993} 3074}
2994 3075
2995void d_tmpfile(struct dentry *dentry, struct inode *inode) 3076void d_tmpfile(struct dentry *dentry, struct inode *inode)
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 72a5d5b04494..0e6961aae6c0 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -182,10 +182,11 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
182 struct inode *inode; 182 struct inode *inode;
183 struct dentry *parent; 183 struct dentry *parent;
184 struct fuse_conn *fc; 184 struct fuse_conn *fc;
185 int ret;
185 186
186 inode = ACCESS_ONCE(entry->d_inode); 187 inode = ACCESS_ONCE(entry->d_inode);
187 if (inode && is_bad_inode(inode)) 188 if (inode && is_bad_inode(inode))
188 return 0; 189 goto invalid;
189 else if (fuse_dentry_time(entry) < get_jiffies_64()) { 190 else if (fuse_dentry_time(entry) < get_jiffies_64()) {
190 int err; 191 int err;
191 struct fuse_entry_out outarg; 192 struct fuse_entry_out outarg;
@@ -195,20 +196,23 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
195 196
196 /* For negative dentries, always do a fresh lookup */ 197 /* For negative dentries, always do a fresh lookup */
197 if (!inode) 198 if (!inode)
198 return 0; 199 goto invalid;
199 200
201 ret = -ECHILD;
200 if (flags & LOOKUP_RCU) 202 if (flags & LOOKUP_RCU)
201 return -ECHILD; 203 goto out;
202 204
203 fc = get_fuse_conn(inode); 205 fc = get_fuse_conn(inode);
204 req = fuse_get_req_nopages(fc); 206 req = fuse_get_req_nopages(fc);
207 ret = PTR_ERR(req);
205 if (IS_ERR(req)) 208 if (IS_ERR(req))
206 return 0; 209 goto out;
207 210
208 forget = fuse_alloc_forget(); 211 forget = fuse_alloc_forget();
209 if (!forget) { 212 if (!forget) {
210 fuse_put_request(fc, req); 213 fuse_put_request(fc, req);
211 return 0; 214 ret = -ENOMEM;
215 goto out;
212 } 216 }
213 217
214 attr_version = fuse_get_attr_version(fc); 218 attr_version = fuse_get_attr_version(fc);
@@ -227,7 +231,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
227 struct fuse_inode *fi = get_fuse_inode(inode); 231 struct fuse_inode *fi = get_fuse_inode(inode);
228 if (outarg.nodeid != get_node_id(inode)) { 232 if (outarg.nodeid != get_node_id(inode)) {
229 fuse_queue_forget(fc, forget, outarg.nodeid, 1); 233 fuse_queue_forget(fc, forget, outarg.nodeid, 1);
230 return 0; 234 goto invalid;
231 } 235 }
232 spin_lock(&fc->lock); 236 spin_lock(&fc->lock);
233 fi->nlookup++; 237 fi->nlookup++;
@@ -235,7 +239,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
235 } 239 }
236 kfree(forget); 240 kfree(forget);
237 if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT) 241 if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
238 return 0; 242 goto invalid;
239 243
240 fuse_change_attributes(inode, &outarg.attr, 244 fuse_change_attributes(inode, &outarg.attr,
241 entry_attr_timeout(&outarg), 245 entry_attr_timeout(&outarg),
@@ -249,7 +253,15 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
249 dput(parent); 253 dput(parent);
250 } 254 }
251 } 255 }
252 return 1; 256 ret = 1;
257out:
258 return ret;
259
260invalid:
261 ret = 0;
262 if (check_submounts_and_drop(entry) != 0)
263 ret = 1;
264 goto out;
253} 265}
254 266
255static int invalid_nodeid(u64 nodeid) 267static int invalid_nodeid(u64 nodeid)
@@ -267,26 +279,6 @@ int fuse_valid_type(int m)
267 S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m); 279 S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
268} 280}
269 281
270/*
271 * Add a directory inode to a dentry, ensuring that no other dentry
272 * refers to this inode. Called with fc->inst_mutex.
273 */
274static struct dentry *fuse_d_add_directory(struct dentry *entry,
275 struct inode *inode)
276{
277 struct dentry *alias = d_find_alias(inode);
278 if (alias && !(alias->d_flags & DCACHE_DISCONNECTED)) {
279 /* This tries to shrink the subtree below alias */
280 fuse_invalidate_entry(alias);
281 dput(alias);
282 if (!hlist_empty(&inode->i_dentry))
283 return ERR_PTR(-EBUSY);
284 } else {
285 dput(alias);
286 }
287 return d_splice_alias(inode, entry);
288}
289
290int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name, 282int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name,
291 struct fuse_entry_out *outarg, struct inode **inode) 283 struct fuse_entry_out *outarg, struct inode **inode)
292{ 284{
@@ -345,6 +337,24 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name,
345 return err; 337 return err;
346} 338}
347 339
340static struct dentry *fuse_materialise_dentry(struct dentry *dentry,
341 struct inode *inode)
342{
343 struct dentry *newent;
344
345 if (inode && S_ISDIR(inode->i_mode)) {
346 struct fuse_conn *fc = get_fuse_conn(inode);
347
348 mutex_lock(&fc->inst_mutex);
349 newent = d_materialise_unique(dentry, inode);
350 mutex_unlock(&fc->inst_mutex);
351 } else {
352 newent = d_materialise_unique(dentry, inode);
353 }
354
355 return newent;
356}
357
348static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, 358static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
349 unsigned int flags) 359 unsigned int flags)
350{ 360{
@@ -352,7 +362,6 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
352 struct fuse_entry_out outarg; 362 struct fuse_entry_out outarg;
353 struct inode *inode; 363 struct inode *inode;
354 struct dentry *newent; 364 struct dentry *newent;
355 struct fuse_conn *fc = get_fuse_conn(dir);
356 bool outarg_valid = true; 365 bool outarg_valid = true;
357 366
358 err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name, 367 err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
@@ -368,16 +377,10 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
368 if (inode && get_node_id(inode) == FUSE_ROOT_ID) 377 if (inode && get_node_id(inode) == FUSE_ROOT_ID)
369 goto out_iput; 378 goto out_iput;
370 379
371 if (inode && S_ISDIR(inode->i_mode)) { 380 newent = fuse_materialise_dentry(entry, inode);
372 mutex_lock(&fc->inst_mutex); 381 err = PTR_ERR(newent);
373 newent = fuse_d_add_directory(entry, inode); 382 if (IS_ERR(newent))
374 mutex_unlock(&fc->inst_mutex); 383 goto out_err;
375 err = PTR_ERR(newent);
376 if (IS_ERR(newent))
377 goto out_iput;
378 } else {
379 newent = d_splice_alias(inode, entry);
380 }
381 384
382 entry = newent ? newent : entry; 385 entry = newent ? newent : entry;
383 if (outarg_valid) 386 if (outarg_valid)
@@ -1275,18 +1278,10 @@ static int fuse_direntplus_link(struct file *file,
1275 if (!inode) 1278 if (!inode)
1276 goto out; 1279 goto out;
1277 1280
1278 if (S_ISDIR(inode->i_mode)) { 1281 alias = fuse_materialise_dentry(dentry, inode);
1279 mutex_lock(&fc->inst_mutex); 1282 err = PTR_ERR(alias);
1280 alias = fuse_d_add_directory(dentry, inode); 1283 if (IS_ERR(alias))
1281 mutex_unlock(&fc->inst_mutex); 1284 goto out;
1282 err = PTR_ERR(alias);
1283 if (IS_ERR(alias)) {
1284 iput(inode);
1285 goto out;
1286 }
1287 } else {
1288 alias = d_splice_alias(inode, dentry);
1289 }
1290 1285
1291 if (alias) { 1286 if (alias) {
1292 dput(dentry); 1287 dput(dentry);
diff --git a/fs/gfs2/dentry.c b/fs/gfs2/dentry.c
index f2448ab2aac5..d3a5d4e29ba5 100644
--- a/fs/gfs2/dentry.c
+++ b/fs/gfs2/dentry.c
@@ -93,12 +93,9 @@ invalid_gunlock:
93 if (!had_lock) 93 if (!had_lock)
94 gfs2_glock_dq_uninit(&d_gh); 94 gfs2_glock_dq_uninit(&d_gh);
95invalid: 95invalid:
96 if (inode && S_ISDIR(inode->i_mode)) { 96 if (check_submounts_and_drop(dentry) != 0)
97 if (have_submounts(dentry)) 97 goto valid;
98 goto valid; 98
99 shrink_dcache_parent(dentry);
100 }
101 d_drop(dentry);
102 dput(parent); 99 dput(parent);
103 return 0; 100 return 0;
104 101
diff --git a/fs/internal.h b/fs/internal.h
index 7c5f01cf619d..d20893795526 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -126,6 +126,7 @@ extern int invalidate_inodes(struct super_block *, bool);
126 * dcache.c 126 * dcache.c
127 */ 127 */
128extern struct dentry *__d_alloc(struct super_block *, const struct qstr *); 128extern struct dentry *__d_alloc(struct super_block *, const struct qstr *);
129extern int d_set_mounted(struct dentry *dentry);
129 130
130/* 131/*
131 * read_write.c 132 * read_write.c
diff --git a/fs/namespace.c b/fs/namespace.c
index ef69fa5d2e5b..fc2b5226278d 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -611,6 +611,7 @@ static struct mountpoint *new_mountpoint(struct dentry *dentry)
611{ 611{
612 struct list_head *chain = mountpoint_hashtable + hash(NULL, dentry); 612 struct list_head *chain = mountpoint_hashtable + hash(NULL, dentry);
613 struct mountpoint *mp; 613 struct mountpoint *mp;
614 int ret;
614 615
615 list_for_each_entry(mp, chain, m_hash) { 616 list_for_each_entry(mp, chain, m_hash) {
616 if (mp->m_dentry == dentry) { 617 if (mp->m_dentry == dentry) {
@@ -626,14 +627,12 @@ static struct mountpoint *new_mountpoint(struct dentry *dentry)
626 if (!mp) 627 if (!mp)
627 return ERR_PTR(-ENOMEM); 628 return ERR_PTR(-ENOMEM);
628 629
629 spin_lock(&dentry->d_lock); 630 ret = d_set_mounted(dentry);
630 if (d_unlinked(dentry)) { 631 if (ret) {
631 spin_unlock(&dentry->d_lock);
632 kfree(mp); 632 kfree(mp);
633 return ERR_PTR(-ENOENT); 633 return ERR_PTR(ret);
634 } 634 }
635 dentry->d_flags |= DCACHE_MOUNTED; 635
636 spin_unlock(&dentry->d_lock);
637 mp->m_dentry = dentry; 636 mp->m_dentry = dentry;
638 mp->m_count = 1; 637 mp->m_count = 1;
639 list_add(&mp->m_hash, chain); 638 list_add(&mp->m_hash, chain);
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index e474ca2b2bfe..7468735d299e 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1135,14 +1135,13 @@ out_zap_parent:
1135 if (inode && S_ISDIR(inode->i_mode)) { 1135 if (inode && S_ISDIR(inode->i_mode)) {
1136 /* Purge readdir caches. */ 1136 /* Purge readdir caches. */
1137 nfs_zap_caches(inode); 1137 nfs_zap_caches(inode);
1138 /* If we have submounts, don't unhash ! */
1139 if (have_submounts(dentry))
1140 goto out_valid;
1141 if (dentry->d_flags & DCACHE_DISCONNECTED) 1138 if (dentry->d_flags & DCACHE_DISCONNECTED)
1142 goto out_valid; 1139 goto out_valid;
1143 shrink_dcache_parent(dentry);
1144 } 1140 }
1145 d_drop(dentry); 1141 /* If we have submounts, don't unhash ! */
1142 if (check_submounts_and_drop(dentry) != 0)
1143 goto out_valid;
1144
1146 dput(parent); 1145 dput(parent);
1147 dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) is invalid\n", 1146 dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) is invalid\n",
1148 __func__, dentry->d_parent->d_name.name, 1147 __func__, dentry->d_parent->d_name.name,
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 99ec5b40e977..4d83cedb9fcb 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -297,7 +297,6 @@ static int sysfs_dentry_delete(const struct dentry *dentry)
297static int sysfs_dentry_revalidate(struct dentry *dentry, unsigned int flags) 297static int sysfs_dentry_revalidate(struct dentry *dentry, unsigned int flags)
298{ 298{
299 struct sysfs_dirent *sd; 299 struct sysfs_dirent *sd;
300 int is_dir;
301 int type; 300 int type;
302 301
303 if (flags & LOOKUP_RCU) 302 if (flags & LOOKUP_RCU)
@@ -341,18 +340,15 @@ out_bad:
341 * is performed at its new name the dentry will be readded 340 * is performed at its new name the dentry will be readded
342 * to the dcache hashes. 341 * to the dcache hashes.
343 */ 342 */
344 is_dir = (sysfs_type(sd) == SYSFS_DIR);
345 mutex_unlock(&sysfs_mutex); 343 mutex_unlock(&sysfs_mutex);
346 if (is_dir) { 344
347 /* If we have submounts we must allow the vfs caches 345 /* If we have submounts we must allow the vfs caches
348 * to lie about the state of the filesystem to prevent 346 * to lie about the state of the filesystem to prevent
349 * leaks and other nasty things. 347 * leaks and other nasty things.
350 */ 348 */
351 if (have_submounts(dentry)) 349 if (check_submounts_and_drop(dentry) != 0)
352 goto out_valid; 350 goto out_valid;
353 shrink_dcache_parent(dentry); 351
354 }
355 d_drop(dentry);
356 return 0; 352 return 0;
357} 353}
358 354
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 9169b91ea2d2..fe50f3db3af9 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -212,7 +212,7 @@ struct dentry_operations {
212 212
213extern seqlock_t rename_lock; 213extern seqlock_t rename_lock;
214 214
215static inline int dname_external(struct dentry *dentry) 215static inline int dname_external(const struct dentry *dentry)
216{ 216{
217 return dentry->d_name.name != dentry->d_iname; 217 return dentry->d_name.name != dentry->d_iname;
218} 218}
@@ -253,6 +253,7 @@ extern void d_prune_aliases(struct inode *);
253 253
254/* test whether we have any submounts in a subdir tree */ 254/* test whether we have any submounts in a subdir tree */
255extern int have_submounts(struct dentry *); 255extern int have_submounts(struct dentry *);
256extern int check_submounts_and_drop(struct dentry *);
256 257
257/* 258/*
258 * This adds the entry to the hash queues. 259 * This adds the entry to the hash queues.
@@ -357,17 +358,17 @@ extern struct dentry *dget_parent(struct dentry *dentry);
357 * Returns true if the dentry passed is not currently hashed. 358 * Returns true if the dentry passed is not currently hashed.
358 */ 359 */
359 360
360static inline int d_unhashed(struct dentry *dentry) 361static inline int d_unhashed(const struct dentry *dentry)
361{ 362{
362 return hlist_bl_unhashed(&dentry->d_hash); 363 return hlist_bl_unhashed(&dentry->d_hash);
363} 364}
364 365
365static inline int d_unlinked(struct dentry *dentry) 366static inline int d_unlinked(const struct dentry *dentry)
366{ 367{
367 return d_unhashed(dentry) && !IS_ROOT(dentry); 368 return d_unhashed(dentry) && !IS_ROOT(dentry);
368} 369}
369 370
370static inline int cant_mount(struct dentry *dentry) 371static inline int cant_mount(const struct dentry *dentry)
371{ 372{
372 return (dentry->d_flags & DCACHE_CANT_MOUNT); 373 return (dentry->d_flags & DCACHE_CANT_MOUNT);
373} 374}
@@ -381,12 +382,12 @@ static inline void dont_mount(struct dentry *dentry)
381 382
382extern void dput(struct dentry *); 383extern void dput(struct dentry *);
383 384
384static inline bool d_managed(struct dentry *dentry) 385static inline bool d_managed(const struct dentry *dentry)
385{ 386{
386 return dentry->d_flags & DCACHE_MANAGED_DENTRY; 387 return dentry->d_flags & DCACHE_MANAGED_DENTRY;
387} 388}
388 389
389static inline bool d_mountpoint(struct dentry *dentry) 390static inline bool d_mountpoint(const struct dentry *dentry)
390{ 391{
391 return dentry->d_flags & DCACHE_MOUNTED; 392 return dentry->d_flags & DCACHE_MOUNTED;
392} 393}