diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2013-11-08 12:31:16 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-11-09 00:16:06 -0500 |
commit | 42c326082d8a2c91506f951ace638deae1faf083 (patch) | |
tree | a09f795701ba868097a2285f2b386394f0d32df5 /fs/dcache.c | |
parent | dd3e2c55a45fe75f3213b17b74f9a32380f4e84b (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.c | 195 |
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) | |||
1075 | EXPORT_SYMBOL(shrink_dcache_sb); | 1075 | EXPORT_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 | */ | ||
1082 | static 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 | */ | ||
1169 | void 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 | } |
1479 | EXPORT_SYMBOL(shrink_dcache_parent); | 1369 | EXPORT_SYMBOL(shrink_dcache_parent); |
1480 | 1370 | ||
1371 | static 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 | } | ||
1406 | out: | ||
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 | */ | ||
1415 | void 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 | |||
1481 | static enum d_walk_ret check_and_collect(void *_data, struct dentry *dentry) | 1456 | static 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; |