vfs: keep list of mounts for each superblock
authorMiklos Szeredi <mszeredi@suse.cz>
Mon, 21 Nov 2011 11:11:30 +0000 (12:11 +0100)
committerAl Viro <viro@zeniv.linux.org.uk>
Sat, 7 Jan 2012 04:20:12 +0000 (23:20 -0500)
Keep track of vfsmounts belonging to a superblock.  List is protected
by vfsmount_lock.

Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Tested-by: Toshiyuki Okajima <toshi.okajima@jp.fujitsu.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/mount.h
fs/namespace.c
fs/super.c
include/linux/fs.h

index 0921b51e27e240123302cb654a26d051fd04740c..4ef36d93e5a241822e10c21f93dc72d7137d32ec 100644 (file)
@@ -29,6 +29,7 @@ struct mount {
 #endif
        struct list_head mnt_mounts;    /* list of children, anchored here */
        struct list_head mnt_child;     /* and going through their mnt_child */
+       struct list_head mnt_instance;  /* mount instance on sb->s_mounts */
        const char *mnt_devname;        /* Name of device e.g. /dev/dsk/hda1 */
        struct list_head mnt_list;
        struct list_head mnt_expire;    /* link in fs-specific expiry list */
index db65e2e4921f22833eedb38934c1ee4f07e09c7a..145217b088d1e82f27eeb07139533b9644295b93 100644 (file)
@@ -671,6 +671,9 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void
        mnt->mnt.mnt_sb = root->d_sb;
        mnt->mnt_mountpoint = mnt->mnt.mnt_root;
        mnt->mnt_parent = mnt;
+       br_write_lock(vfsmount_lock);
+       list_add_tail(&mnt->mnt_instance, &root->d_sb->s_mounts);
+       br_write_unlock(vfsmount_lock);
        return &mnt->mnt;
 }
 EXPORT_SYMBOL_GPL(vfs_kern_mount);
@@ -699,6 +702,9 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root,
                mnt->mnt.mnt_root = dget(root);
                mnt->mnt_mountpoint = mnt->mnt.mnt_root;
                mnt->mnt_parent = mnt;
+               br_write_lock(vfsmount_lock);
+               list_add_tail(&mnt->mnt_instance, &sb->s_mounts);
+               br_write_unlock(vfsmount_lock);
 
                if (flag & CL_SLAVE) {
                        list_add(&mnt->mnt_slave, &old->mnt_slave_list);
@@ -781,6 +787,7 @@ put_again:
                acct_auto_close_mnt(&mnt->mnt);
                goto put_again;
        }
+       list_del(&mnt->mnt_instance);
        br_write_unlock(vfsmount_lock);
        mntfree(mnt);
 }
index 0413f51a9f0f98ca2962f38f346b2cb4595eefc3..993ca8f128d60b0cf9ab1bac2fcb2077343ba1a1 100644 (file)
@@ -142,6 +142,7 @@ static struct super_block *alloc_super(struct file_system_type *type)
                INIT_LIST_HEAD(&s->s_dentry_lru);
                INIT_LIST_HEAD(&s->s_inode_lru);
                spin_lock_init(&s->s_inode_lru_lock);
+               INIT_LIST_HEAD(&s->s_mounts);
                init_rwsem(&s->s_umount);
                mutex_init(&s->s_lock);
                lockdep_set_class(&s->s_umount, &type->s_umount_key);
@@ -200,6 +201,7 @@ static inline void destroy_super(struct super_block *s)
        free_percpu(s->s_files);
 #endif
        security_sb_free(s);
+       WARN_ON(!list_empty(&s->s_mounts));
        kfree(s->s_subtype);
        kfree(s->s_options);
        kfree(s);
index cc1021fd19efafbb3099ac91e60937b96138a4eb..03385acd71e8e4aee4570934b72e63a512915fcd 100644 (file)
@@ -1428,6 +1428,7 @@ struct super_block {
 #else
        struct list_head        s_files;
 #endif
+       struct list_head        s_mounts;       /* list of mounts; _not_ for fs use */
        /* s_dentry_lru, s_nr_dentry_unused protected by dcache.c lru locks */
        struct list_head        s_dentry_lru;   /* unused dentry lru */
        int                     s_nr_dentry_unused;     /* # of dentry on lru */