aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namespace.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/namespace.c')
-rw-r--r--fs/namespace.c157
1 files changed, 114 insertions, 43 deletions
diff --git a/fs/namespace.c b/fs/namespace.c
index c13072a5f1ee..6ede3a539ed8 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -8,16 +8,17 @@
8 * Heavily rewritten. 8 * Heavily rewritten.
9 */ 9 */
10 10
11#include <linux/config.h>
12#include <linux/syscalls.h> 11#include <linux/syscalls.h>
13#include <linux/slab.h> 12#include <linux/slab.h>
14#include <linux/sched.h> 13#include <linux/sched.h>
15#include <linux/smp_lock.h> 14#include <linux/smp_lock.h>
16#include <linux/init.h> 15#include <linux/init.h>
16#include <linux/kernel.h>
17#include <linux/quotaops.h> 17#include <linux/quotaops.h>
18#include <linux/acct.h> 18#include <linux/acct.h>
19#include <linux/capability.h> 19#include <linux/capability.h>
20#include <linux/module.h> 20#include <linux/module.h>
21#include <linux/sysfs.h>
21#include <linux/seq_file.h> 22#include <linux/seq_file.h>
22#include <linux/namespace.h> 23#include <linux/namespace.h>
23#include <linux/namei.h> 24#include <linux/namei.h>
@@ -29,15 +30,6 @@
29 30
30extern int __init init_rootfs(void); 31extern int __init init_rootfs(void);
31 32
32#ifdef CONFIG_SYSFS
33extern int __init sysfs_init(void);
34#else
35static inline int sysfs_init(void)
36{
37 return 0;
38}
39#endif
40
41/* spinlock for vfsmount related operations, inplace of dcache_lock */ 33/* spinlock for vfsmount related operations, inplace of dcache_lock */
42__cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock); 34__cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock);
43 35
@@ -526,10 +518,8 @@ void umount_tree(struct vfsmount *mnt, int propagate, struct list_head *kill)
526{ 518{
527 struct vfsmount *p; 519 struct vfsmount *p;
528 520
529 for (p = mnt; p; p = next_mnt(p, mnt)) { 521 for (p = mnt; p; p = next_mnt(p, mnt))
530 list_del(&p->mnt_hash); 522 list_move(&p->mnt_hash, kill);
531 list_add(&p->mnt_hash, kill);
532 }
533 523
534 if (propagate) 524 if (propagate)
535 propagate_umount(kill); 525 propagate_umount(kill);
@@ -585,8 +575,8 @@ static int do_umount(struct vfsmount *mnt, int flags)
585 */ 575 */
586 576
587 lock_kernel(); 577 lock_kernel();
588 if ((flags & MNT_FORCE) && sb->s_op->umount_begin) 578 if (sb->s_op->umount_begin)
589 sb->s_op->umount_begin(sb); 579 sb->s_op->umount_begin(mnt, flags);
590 unlock_kernel(); 580 unlock_kernel();
591 581
592 /* 582 /*
@@ -1172,13 +1162,46 @@ static void expire_mount(struct vfsmount *mnt, struct list_head *mounts,
1172} 1162}
1173 1163
1174/* 1164/*
1165 * go through the vfsmounts we've just consigned to the graveyard to
1166 * - check that they're still dead
1167 * - delete the vfsmount from the appropriate namespace under lock
1168 * - dispose of the corpse
1169 */
1170static void expire_mount_list(struct list_head *graveyard, struct list_head *mounts)
1171{
1172 struct namespace *namespace;
1173 struct vfsmount *mnt;
1174
1175 while (!list_empty(graveyard)) {
1176 LIST_HEAD(umounts);
1177 mnt = list_entry(graveyard->next, struct vfsmount, mnt_expire);
1178 list_del_init(&mnt->mnt_expire);
1179
1180 /* don't do anything if the namespace is dead - all the
1181 * vfsmounts from it are going away anyway */
1182 namespace = mnt->mnt_namespace;
1183 if (!namespace || !namespace->root)
1184 continue;
1185 get_namespace(namespace);
1186
1187 spin_unlock(&vfsmount_lock);
1188 down_write(&namespace_sem);
1189 expire_mount(mnt, mounts, &umounts);
1190 up_write(&namespace_sem);
1191 release_mounts(&umounts);
1192 mntput(mnt);
1193 put_namespace(namespace);
1194 spin_lock(&vfsmount_lock);
1195 }
1196}
1197
1198/*
1175 * process a list of expirable mountpoints with the intent of discarding any 1199 * process a list of expirable mountpoints with the intent of discarding any
1176 * mountpoints that aren't in use and haven't been touched since last we came 1200 * mountpoints that aren't in use and haven't been touched since last we came
1177 * here 1201 * here
1178 */ 1202 */
1179void mark_mounts_for_expiry(struct list_head *mounts) 1203void mark_mounts_for_expiry(struct list_head *mounts)
1180{ 1204{
1181 struct namespace *namespace;
1182 struct vfsmount *mnt, *next; 1205 struct vfsmount *mnt, *next;
1183 LIST_HEAD(graveyard); 1206 LIST_HEAD(graveyard);
1184 1207
@@ -1202,38 +1225,79 @@ void mark_mounts_for_expiry(struct list_head *mounts)
1202 list_move(&mnt->mnt_expire, &graveyard); 1225 list_move(&mnt->mnt_expire, &graveyard);
1203 } 1226 }
1204 1227
1205 /* 1228 expire_mount_list(&graveyard, mounts);
1206 * go through the vfsmounts we've just consigned to the graveyard to
1207 * - check that they're still dead
1208 * - delete the vfsmount from the appropriate namespace under lock
1209 * - dispose of the corpse
1210 */
1211 while (!list_empty(&graveyard)) {
1212 LIST_HEAD(umounts);
1213 mnt = list_entry(graveyard.next, struct vfsmount, mnt_expire);
1214 list_del_init(&mnt->mnt_expire);
1215 1229
1216 /* don't do anything if the namespace is dead - all the 1230 spin_unlock(&vfsmount_lock);
1217 * vfsmounts from it are going away anyway */ 1231}
1218 namespace = mnt->mnt_namespace; 1232
1219 if (!namespace || !namespace->root) 1233EXPORT_SYMBOL_GPL(mark_mounts_for_expiry);
1234
1235/*
1236 * Ripoff of 'select_parent()'
1237 *
1238 * search the list of submounts for a given mountpoint, and move any
1239 * shrinkable submounts to the 'graveyard' list.
1240 */
1241static int select_submounts(struct vfsmount *parent, struct list_head *graveyard)
1242{
1243 struct vfsmount *this_parent = parent;
1244 struct list_head *next;
1245 int found = 0;
1246
1247repeat:
1248 next = this_parent->mnt_mounts.next;
1249resume:
1250 while (next != &this_parent->mnt_mounts) {
1251 struct list_head *tmp = next;
1252 struct vfsmount *mnt = list_entry(tmp, struct vfsmount, mnt_child);
1253
1254 next = tmp->next;
1255 if (!(mnt->mnt_flags & MNT_SHRINKABLE))
1220 continue; 1256 continue;
1221 get_namespace(namespace); 1257 /*
1258 * Descend a level if the d_mounts list is non-empty.
1259 */
1260 if (!list_empty(&mnt->mnt_mounts)) {
1261 this_parent = mnt;
1262 goto repeat;
1263 }
1222 1264
1223 spin_unlock(&vfsmount_lock); 1265 if (!propagate_mount_busy(mnt, 1)) {
1224 down_write(&namespace_sem); 1266 mntget(mnt);
1225 expire_mount(mnt, mounts, &umounts); 1267 list_move_tail(&mnt->mnt_expire, graveyard);
1226 up_write(&namespace_sem); 1268 found++;
1227 release_mounts(&umounts); 1269 }
1228 mntput(mnt); 1270 }
1229 put_namespace(namespace); 1271 /*
1230 spin_lock(&vfsmount_lock); 1272 * All done at this level ... ascend and resume the search
1273 */
1274 if (this_parent != parent) {
1275 next = this_parent->mnt_child.next;
1276 this_parent = this_parent->mnt_parent;
1277 goto resume;
1231 } 1278 }
1279 return found;
1280}
1281
1282/*
1283 * process a list of expirable mountpoints with the intent of discarding any
1284 * submounts of a specific parent mountpoint
1285 */
1286void shrink_submounts(struct vfsmount *mountpoint, struct list_head *mounts)
1287{
1288 LIST_HEAD(graveyard);
1289 int found;
1290
1291 spin_lock(&vfsmount_lock);
1292
1293 /* extract submounts of 'mountpoint' from the expiration list */
1294 while ((found = select_submounts(mountpoint, &graveyard)) != 0)
1295 expire_mount_list(&graveyard, mounts);
1232 1296
1233 spin_unlock(&vfsmount_lock); 1297 spin_unlock(&vfsmount_lock);
1234} 1298}
1235 1299
1236EXPORT_SYMBOL_GPL(mark_mounts_for_expiry); 1300EXPORT_SYMBOL_GPL(shrink_submounts);
1237 1301
1238/* 1302/*
1239 * Some copy_from_user() implementations do not return the exact number of 1303 * Some copy_from_user() implementations do not return the exact number of
@@ -1750,6 +1814,7 @@ void __init mnt_init(unsigned long mempages)
1750 struct list_head *d; 1814 struct list_head *d;
1751 unsigned int nr_hash; 1815 unsigned int nr_hash;
1752 int i; 1816 int i;
1817 int err;
1753 1818
1754 init_rwsem(&namespace_sem); 1819 init_rwsem(&namespace_sem);
1755 1820
@@ -1790,8 +1855,14 @@ void __init mnt_init(unsigned long mempages)
1790 d++; 1855 d++;
1791 i--; 1856 i--;
1792 } while (i); 1857 } while (i);
1793 sysfs_init(); 1858 err = sysfs_init();
1794 subsystem_register(&fs_subsys); 1859 if (err)
1860 printk(KERN_WARNING "%s: sysfs_init error: %d\n",
1861 __FUNCTION__, err);
1862 err = subsystem_register(&fs_subsys);
1863 if (err)
1864 printk(KERN_WARNING "%s: subsystem_register error: %d\n",
1865 __FUNCTION__, err);
1795 init_rootfs(); 1866 init_rootfs();
1796 init_mount_tree(); 1867 init_mount_tree();
1797} 1868}