aboutsummaryrefslogtreecommitdiffstats
path: root/fs/dcache.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2013-11-08 12:31:16 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2013-11-09 00:16:06 -0500
commit42c326082d8a2c91506f951ace638deae1faf083 (patch)
treea09f795701ba868097a2285f2b386394f0d32df5 /fs/dcache.c
parentdd3e2c55a45fe75f3213b17b74f9a32380f4e84b (diff)
switch shrink_dcache_for_umount() to use of d_walk()
we have too many iterators in fs/dcache.c... Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/dcache.c')
-rw-r--r--fs/dcache.c195
1 files changed, 85 insertions, 110 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index c8e83d0d61ac..eb0978da1bd4 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1075,116 +1075,6 @@ void shrink_dcache_sb(struct super_block *sb)
1075EXPORT_SYMBOL(shrink_dcache_sb); 1075EXPORT_SYMBOL(shrink_dcache_sb);
1076 1076
1077/* 1077/*
1078 * destroy a single subtree of dentries for unmount
1079 * - see the comments on shrink_dcache_for_umount() for a description of the
1080 * locking
1081 */
1082static void shrink_dcache_for_umount_subtree(struct dentry *dentry)
1083{
1084 struct dentry *parent;
1085
1086 BUG_ON(!IS_ROOT(dentry));
1087
1088 for (;;) {
1089 /* descend to the first leaf in the current subtree */
1090 while (!list_empty(&dentry->d_subdirs))
1091 dentry = list_entry(dentry->d_subdirs.next,
1092 struct dentry, d_u.d_child);
1093
1094 /* consume the dentries from this leaf up through its parents
1095 * until we find one with children or run out altogether */
1096 do {
1097 struct inode *inode;
1098
1099 /*
1100 * inform the fs that this dentry is about to be
1101 * unhashed and destroyed.
1102 */
1103 if ((dentry->d_flags & DCACHE_OP_PRUNE) &&
1104 !d_unhashed(dentry))
1105 dentry->d_op->d_prune(dentry);
1106
1107 dentry_lru_del(dentry);
1108 __d_shrink(dentry);
1109
1110 if (dentry->d_lockref.count != 0) {
1111 printk(KERN_ERR
1112 "BUG: Dentry %p{i=%lx,n=%s}"
1113 " still in use (%d)"
1114 " [unmount of %s %s]\n",
1115 dentry,
1116 dentry->d_inode ?
1117 dentry->d_inode->i_ino : 0UL,
1118 dentry->d_name.name,
1119 dentry->d_lockref.count,
1120 dentry->d_sb->s_type->name,
1121 dentry->d_sb->s_id);
1122 BUG();
1123 }
1124
1125 if (IS_ROOT(dentry)) {
1126 parent = NULL;
1127 list_del(&dentry->d_u.d_child);
1128 } else {
1129 parent = dentry->d_parent;
1130 parent->d_lockref.count--;
1131 list_del(&dentry->d_u.d_child);
1132 }
1133
1134 inode = dentry->d_inode;
1135 if (inode) {
1136 dentry->d_inode = NULL;
1137 hlist_del_init(&dentry->d_alias);
1138 if (dentry->d_op && dentry->d_op->d_iput)
1139 dentry->d_op->d_iput(dentry, inode);
1140 else
1141 iput(inode);
1142 }
1143
1144 d_free(dentry);
1145
1146 /* finished when we fall off the top of the tree,
1147 * otherwise we ascend to the parent and move to the
1148 * next sibling if there is one */
1149 if (!parent)
1150 return;
1151 dentry = parent;
1152 } while (list_empty(&dentry->d_subdirs));
1153
1154 dentry = list_entry(dentry->d_subdirs.next,
1155 struct dentry, d_u.d_child);
1156 }
1157}
1158
1159/*
1160 * destroy the dentries attached to a superblock on unmounting
1161 * - we don't need to use dentry->d_lock because:
1162 * - the superblock is detached from all mountings and open files, so the
1163 * dentry trees will not be rearranged by the VFS
1164 * - s_umount is write-locked, so the memory pressure shrinker will ignore
1165 * any dentries belonging to this superblock that it comes across
1166 * - the filesystem itself is no longer permitted to rearrange the dentries
1167 * in this superblock
1168 */
1169void shrink_dcache_for_umount(struct super_block *sb)
1170{
1171 struct dentry *dentry;
1172
1173 if (down_read_trylock(&sb->s_umount))
1174 BUG();
1175
1176 dentry = sb->s_root;
1177 sb->s_root = NULL;
1178 dentry->d_lockref.count--;
1179 shrink_dcache_for_umount_subtree(dentry);
1180
1181 while (!hlist_bl_empty(&sb->s_anon)) {
1182 dentry = hlist_bl_entry(hlist_bl_first(&sb->s_anon), struct dentry, d_hash);
1183 shrink_dcache_for_umount_subtree(dentry);
1184 }
1185}
1186
1187/*
1188 * This tries to ascend one level of parenthood, but 1078 * This tries to ascend one level of parenthood, but
1189 * we can race with renaming, so we need to re-check 1079 * we can race with renaming, so we need to re-check
1190 * the parenthood after dropping the lock and check 1080 * the parenthood after dropping the lock and check
@@ -1478,6 +1368,91 @@ void shrink_dcache_parent(struct dentry *parent)
1478} 1368}
1479EXPORT_SYMBOL(shrink_dcache_parent); 1369EXPORT_SYMBOL(shrink_dcache_parent);
1480 1370
1371static enum d_walk_ret umount_collect(void *_data, struct dentry *dentry)
1372{
1373 struct select_data *data = _data;
1374 enum d_walk_ret ret = D_WALK_CONTINUE;
1375
1376 if (dentry->d_lockref.count) {
1377 dentry_lru_del(dentry);
1378 if (likely(!list_empty(&dentry->d_subdirs)))
1379 goto out;
1380 if (dentry == data->start && dentry->d_lockref.count == 1)
1381 goto out;
1382 printk(KERN_ERR
1383 "BUG: Dentry %p{i=%lx,n=%s}"
1384 " still in use (%d)"
1385 " [unmount of %s %s]\n",
1386 dentry,
1387 dentry->d_inode ?
1388 dentry->d_inode->i_ino : 0UL,
1389 dentry->d_name.name,
1390 dentry->d_lockref.count,
1391 dentry->d_sb->s_type->name,
1392 dentry->d_sb->s_id);
1393 BUG();
1394 } else if (!(dentry->d_flags & DCACHE_SHRINK_LIST)) {
1395 /*
1396 * We can't use d_lru_shrink_move() because we
1397 * need to get the global LRU lock and do the
1398 * LRU accounting.
1399 */
1400 if (dentry->d_flags & DCACHE_LRU_LIST)
1401 d_lru_del(dentry);
1402 d_shrink_add(dentry, &data->dispose);
1403 data->found++;
1404 ret = D_WALK_NORETRY;
1405 }
1406out:
1407 if (data->found && need_resched())
1408 ret = D_WALK_QUIT;
1409 return ret;
1410}
1411
1412/*
1413 * destroy the dentries attached to a superblock on unmounting
1414 */
1415void shrink_dcache_for_umount(struct super_block *sb)
1416{
1417 struct dentry *dentry;
1418
1419 if (down_read_trylock(&sb->s_umount))
1420 BUG();
1421
1422 dentry = sb->s_root;
1423 sb->s_root = NULL;
1424 for (;;) {
1425 struct select_data data;
1426
1427 INIT_LIST_HEAD(&data.dispose);
1428 data.start = dentry;
1429 data.found = 0;
1430
1431 d_walk(dentry, &data, umount_collect, NULL);
1432 if (!data.found)
1433 break;
1434
1435 shrink_dentry_list(&data.dispose);
1436 cond_resched();
1437 }
1438 d_drop(dentry);
1439 dput(dentry);
1440
1441 while (!hlist_bl_empty(&sb->s_anon)) {
1442 struct select_data data;
1443 dentry = hlist_bl_entry(hlist_bl_first(&sb->s_anon), struct dentry, d_hash);
1444
1445 INIT_LIST_HEAD(&data.dispose);
1446 data.start = NULL;
1447 data.found = 0;
1448
1449 d_walk(dentry, &data, umount_collect, NULL);
1450 if (data.found)
1451 shrink_dentry_list(&data.dispose);
1452 cond_resched();
1453 }
1454}
1455
1481static enum d_walk_ret check_and_collect(void *_data, struct dentry *dentry) 1456static enum d_walk_ret check_and_collect(void *_data, struct dentry *dentry)
1482{ 1457{
1483 struct select_data *data = _data; 1458 struct select_data *data = _data;