···12101211EXPORT_SYMBOL_GPL(do_add_mount);12121213-static void expire_mount(struct vfsmount *mnt, struct list_head *mounts,1214- struct list_head *umounts)1215-{1216- spin_lock(&vfsmount_lock);1217-1218- /*1219- * Check if mount is still attached, if not, let whoever holds it deal1220- * with the sucker1221- */1222- if (mnt->mnt_parent == mnt) {1223- spin_unlock(&vfsmount_lock);1224- return;1225- }1226-1227- /*1228- * Check that it is still dead: the count should now be 2 - as1229- * contributed by the vfsmount parent and the mntget above1230- */1231- if (!propagate_mount_busy(mnt, 2)) {1232- /* delete from the namespace */1233- touch_mnt_namespace(mnt->mnt_ns);1234- list_del_init(&mnt->mnt_list);1235- mnt->mnt_ns = NULL;1236- umount_tree(mnt, 1, umounts);1237- spin_unlock(&vfsmount_lock);1238- } else {1239- /*1240- * Someone brought it back to life whilst we didn't have any1241- * locks held so return it to the expiration list1242- */1243- list_add_tail(&mnt->mnt_expire, mounts);1244- spin_unlock(&vfsmount_lock);1245- }1246-}1247-1248-/*1249- * go through the vfsmounts we've just consigned to the graveyard to1250- * - check that they're still dead1251- * - delete the vfsmount from the appropriate namespace under lock1252- * - dispose of the corpse1253- */1254-static void expire_mount_list(struct list_head *graveyard, struct list_head *mounts)1255-{1256- struct mnt_namespace *ns;1257- struct vfsmount *mnt;1258-1259- while (!list_empty(graveyard)) {1260- LIST_HEAD(umounts);1261- mnt = list_first_entry(graveyard, struct vfsmount, mnt_expire);1262- list_del_init(&mnt->mnt_expire);1263-1264- /* don't do anything if the namespace is dead - all the1265- * vfsmounts from it are going away anyway */1266- ns = mnt->mnt_ns;1267- if (!ns || !ns->root)1268- continue;1269- get_mnt_ns(ns);1270-1271- spin_unlock(&vfsmount_lock);1272- down_write(&namespace_sem);1273- expire_mount(mnt, mounts, &umounts);1274- up_write(&namespace_sem);1275- release_mounts(&umounts);1276- mntput(mnt);1277- put_mnt_ns(ns);1278- spin_lock(&vfsmount_lock);1279- }1280-}1281-1282/*1283 * process a list of expirable mountpoints with the intent of discarding any1284 * mountpoints that aren't in use and haven't been touched since last we came···1219{1220 struct vfsmount *mnt, *next;1221 LIST_HEAD(graveyard);012221223 if (list_empty(mounts))1224 return;122501226 spin_lock(&vfsmount_lock);12271228 /* extract from the expiration list every vfsmount that matches the···1235 */1236 list_for_each_entry_safe(mnt, next, mounts, mnt_expire) {1237 if (!xchg(&mnt->mnt_expiry_mark, 1) ||1238- atomic_read(&mnt->mnt_count) != 1)1239 continue;1240-1241- mntget(mnt);1242 list_move(&mnt->mnt_expire, &graveyard);1243 }1244-1245- expire_mount_list(&graveyard, mounts);1246-001247 spin_unlock(&vfsmount_lock);0001248}12491250EXPORT_SYMBOL_GPL(mark_mounts_for_expiry);···1283 }12841285 if (!propagate_mount_busy(mnt, 1)) {1286- mntget(mnt);1287 list_move_tail(&mnt->mnt_expire, graveyard);1288 found++;1289 }···1305void shrink_submounts(struct vfsmount *mountpoint, struct list_head *mounts)1306{1307 LIST_HEAD(graveyard);1308- int found;0130901310 spin_lock(&vfsmount_lock);1311-1312 /* extract submounts of 'mountpoint' from the expiration list */1313- while ((found = select_submounts(mountpoint, &graveyard)) != 0)1314- expire_mount_list(&graveyard, mounts);1315-000001316 spin_unlock(&vfsmount_lock);001317}13181319EXPORT_SYMBOL_GPL(shrink_submounts);
···12101211EXPORT_SYMBOL_GPL(do_add_mount);12120000000000000000000000000000000000000000000000000000000000000000000001213/*1214 * process a list of expirable mountpoints with the intent of discarding any1215 * mountpoints that aren't in use and haven't been touched since last we came···1288{1289 struct vfsmount *mnt, *next;1290 LIST_HEAD(graveyard);1291+ LIST_HEAD(umounts);12921293 if (list_empty(mounts))1294 return;12951296+ down_write(&namespace_sem);1297 spin_lock(&vfsmount_lock);12981299 /* extract from the expiration list every vfsmount that matches the···1302 */1303 list_for_each_entry_safe(mnt, next, mounts, mnt_expire) {1304 if (!xchg(&mnt->mnt_expiry_mark, 1) ||1305+ propagate_mount_busy(mnt, 1))1306 continue;001307 list_move(&mnt->mnt_expire, &graveyard);1308 }1309+ while (!list_empty(&graveyard)) {1310+ mnt = list_first_entry(&graveyard, struct vfsmount, mnt_expire);1311+ touch_mnt_namespace(mnt->mnt_ns);1312+ umount_tree(mnt, 1, &umounts);1313+ }1314 spin_unlock(&vfsmount_lock);1315+ up_write(&namespace_sem);1316+1317+ release_mounts(&umounts);1318}13191320EXPORT_SYMBOL_GPL(mark_mounts_for_expiry);···1347 }13481349 if (!propagate_mount_busy(mnt, 1)) {01350 list_move_tail(&mnt->mnt_expire, graveyard);1351 found++;1352 }···1370void shrink_submounts(struct vfsmount *mountpoint, struct list_head *mounts)1371{1372 LIST_HEAD(graveyard);1373+ LIST_HEAD(umounts);1374+ struct vfsmount *mnt;13751376+ down_write(&namespace_sem);1377 spin_lock(&vfsmount_lock);01378 /* extract submounts of 'mountpoint' from the expiration list */1379+ while (select_submounts(mountpoint, &graveyard)) {1380+ while (!list_empty(&graveyard)) {1381+ mnt = list_first_entry(&graveyard, struct vfsmount,1382+ mnt_expire);1383+ touch_mnt_namespace(mnt->mnt_ns);1384+ umount_tree(mnt, 1, &umounts);1385+ }1386+ }1387 spin_unlock(&vfsmount_lock);1388+ up_write(&namespace_sem);1389+ release_mounts(&umounts);1390}13911392EXPORT_SYMBOL_GPL(shrink_submounts);