aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namespace.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/namespace.c')
-rw-r--r--fs/namespace.c143
1 files changed, 112 insertions, 31 deletions
diff --git a/fs/namespace.c b/fs/namespace.c
index bf478addb852..b3ed212ea416 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -86,6 +86,15 @@ struct vfsmount *alloc_vfsmnt(const char *name)
86 return mnt; 86 return mnt;
87} 87}
88 88
89int simple_set_mnt(struct vfsmount *mnt, struct super_block *sb)
90{
91 mnt->mnt_sb = sb;
92 mnt->mnt_root = dget(sb->s_root);
93 return 0;
94}
95
96EXPORT_SYMBOL(simple_set_mnt);
97
89void free_vfsmnt(struct vfsmount *mnt) 98void free_vfsmnt(struct vfsmount *mnt)
90{ 99{
91 kfree(mnt->mnt_devname); 100 kfree(mnt->mnt_devname);
@@ -517,10 +526,8 @@ void umount_tree(struct vfsmount *mnt, int propagate, struct list_head *kill)
517{ 526{
518 struct vfsmount *p; 527 struct vfsmount *p;
519 528
520 for (p = mnt; p; p = next_mnt(p, mnt)) { 529 for (p = mnt; p; p = next_mnt(p, mnt))
521 list_del(&p->mnt_hash); 530 list_move(&p->mnt_hash, kill);
522 list_add(&p->mnt_hash, kill);
523 }
524 531
525 if (propagate) 532 if (propagate)
526 propagate_umount(kill); 533 propagate_umount(kill);
@@ -576,8 +583,8 @@ static int do_umount(struct vfsmount *mnt, int flags)
576 */ 583 */
577 584
578 lock_kernel(); 585 lock_kernel();
579 if ((flags & MNT_FORCE) && sb->s_op->umount_begin) 586 if (sb->s_op->umount_begin)
580 sb->s_op->umount_begin(sb); 587 sb->s_op->umount_begin(mnt, flags);
581 unlock_kernel(); 588 unlock_kernel();
582 589
583 /* 590 /*
@@ -1163,13 +1170,46 @@ static void expire_mount(struct vfsmount *mnt, struct list_head *mounts,
1163} 1170}
1164 1171
1165/* 1172/*
1173 * go through the vfsmounts we've just consigned to the graveyard to
1174 * - check that they're still dead
1175 * - delete the vfsmount from the appropriate namespace under lock
1176 * - dispose of the corpse
1177 */
1178static void expire_mount_list(struct list_head *graveyard, struct list_head *mounts)
1179{
1180 struct namespace *namespace;
1181 struct vfsmount *mnt;
1182
1183 while (!list_empty(graveyard)) {
1184 LIST_HEAD(umounts);
1185 mnt = list_entry(graveyard->next, struct vfsmount, mnt_expire);
1186 list_del_init(&mnt->mnt_expire);
1187
1188 /* don't do anything if the namespace is dead - all the
1189 * vfsmounts from it are going away anyway */
1190 namespace = mnt->mnt_namespace;
1191 if (!namespace || !namespace->root)
1192 continue;
1193 get_namespace(namespace);
1194
1195 spin_unlock(&vfsmount_lock);
1196 down_write(&namespace_sem);
1197 expire_mount(mnt, mounts, &umounts);
1198 up_write(&namespace_sem);
1199 release_mounts(&umounts);
1200 mntput(mnt);
1201 put_namespace(namespace);
1202 spin_lock(&vfsmount_lock);
1203 }
1204}
1205
1206/*
1166 * process a list of expirable mountpoints with the intent of discarding any 1207 * process a list of expirable mountpoints with the intent of discarding any
1167 * mountpoints that aren't in use and haven't been touched since last we came 1208 * mountpoints that aren't in use and haven't been touched since last we came
1168 * here 1209 * here
1169 */ 1210 */
1170void mark_mounts_for_expiry(struct list_head *mounts) 1211void mark_mounts_for_expiry(struct list_head *mounts)
1171{ 1212{
1172 struct namespace *namespace;
1173 struct vfsmount *mnt, *next; 1213 struct vfsmount *mnt, *next;
1174 LIST_HEAD(graveyard); 1214 LIST_HEAD(graveyard);
1175 1215
@@ -1193,38 +1233,79 @@ void mark_mounts_for_expiry(struct list_head *mounts)
1193 list_move(&mnt->mnt_expire, &graveyard); 1233 list_move(&mnt->mnt_expire, &graveyard);
1194 } 1234 }
1195 1235
1196 /* 1236 expire_mount_list(&graveyard, mounts);
1197 * go through the vfsmounts we've just consigned to the graveyard to
1198 * - check that they're still dead
1199 * - delete the vfsmount from the appropriate namespace under lock
1200 * - dispose of the corpse
1201 */
1202 while (!list_empty(&graveyard)) {
1203 LIST_HEAD(umounts);
1204 mnt = list_entry(graveyard.next, struct vfsmount, mnt_expire);
1205 list_del_init(&mnt->mnt_expire);
1206 1237
1207 /* don't do anything if the namespace is dead - all the 1238 spin_unlock(&vfsmount_lock);
1208 * vfsmounts from it are going away anyway */ 1239}
1209 namespace = mnt->mnt_namespace; 1240
1210 if (!namespace || !namespace->root) 1241EXPORT_SYMBOL_GPL(mark_mounts_for_expiry);
1242
1243/*
1244 * Ripoff of 'select_parent()'
1245 *
1246 * search the list of submounts for a given mountpoint, and move any
1247 * shrinkable submounts to the 'graveyard' list.
1248 */
1249static int select_submounts(struct vfsmount *parent, struct list_head *graveyard)
1250{
1251 struct vfsmount *this_parent = parent;
1252 struct list_head *next;
1253 int found = 0;
1254
1255repeat:
1256 next = this_parent->mnt_mounts.next;
1257resume:
1258 while (next != &this_parent->mnt_mounts) {
1259 struct list_head *tmp = next;
1260 struct vfsmount *mnt = list_entry(tmp, struct vfsmount, mnt_child);
1261
1262 next = tmp->next;
1263 if (!(mnt->mnt_flags & MNT_SHRINKABLE))
1211 continue; 1264 continue;
1212 get_namespace(namespace); 1265 /*
1266 * Descend a level if the d_mounts list is non-empty.
1267 */
1268 if (!list_empty(&mnt->mnt_mounts)) {
1269 this_parent = mnt;
1270 goto repeat;
1271 }
1213 1272
1214 spin_unlock(&vfsmount_lock); 1273 if (!propagate_mount_busy(mnt, 1)) {
1215 down_write(&namespace_sem); 1274 mntget(mnt);
1216 expire_mount(mnt, mounts, &umounts); 1275 list_move_tail(&mnt->mnt_expire, graveyard);
1217 up_write(&namespace_sem); 1276 found++;
1218 release_mounts(&umounts); 1277 }
1219 mntput(mnt);
1220 put_namespace(namespace);
1221 spin_lock(&vfsmount_lock);
1222 } 1278 }
1279 /*
1280 * All done at this level ... ascend and resume the search
1281 */
1282 if (this_parent != parent) {
1283 next = this_parent->mnt_child.next;
1284 this_parent = this_parent->mnt_parent;
1285 goto resume;
1286 }
1287 return found;
1288}
1289
1290/*
1291 * process a list of expirable mountpoints with the intent of discarding any
1292 * submounts of a specific parent mountpoint
1293 */
1294void shrink_submounts(struct vfsmount *mountpoint, struct list_head *mounts)
1295{
1296 LIST_HEAD(graveyard);
1297 int found;
1298
1299 spin_lock(&vfsmount_lock);
1300
1301 /* extract submounts of 'mountpoint' from the expiration list */
1302 while ((found = select_submounts(mountpoint, &graveyard)) != 0)
1303 expire_mount_list(&graveyard, mounts);
1223 1304
1224 spin_unlock(&vfsmount_lock); 1305 spin_unlock(&vfsmount_lock);
1225} 1306}
1226 1307
1227EXPORT_SYMBOL_GPL(mark_mounts_for_expiry); 1308EXPORT_SYMBOL_GPL(shrink_submounts);
1228 1309
1229/* 1310/*
1230 * Some copy_from_user() implementations do not return the exact number of 1311 * Some copy_from_user() implementations do not return the exact number of