memcg: enable accounting for mnt_cache entries
[linux-2.6-microblaze.git] / fs / namespace.c
index ab4174a..e51b63a 100644 (file)
@@ -203,7 +203,8 @@ static struct mount *alloc_vfsmnt(const char *name)
                        goto out_free_cache;
 
                if (name) {
-                       mnt->mnt_devname = kstrdup_const(name, GFP_KERNEL);
+                       mnt->mnt_devname = kstrdup_const(name,
+                                                        GFP_KERNEL_ACCOUNT);
                        if (!mnt->mnt_devname)
                                goto out_free_id;
                }
@@ -1716,8 +1717,12 @@ static inline bool may_mount(void)
 }
 
 #ifdef CONFIG_MANDATORY_FILE_LOCKING
-static inline bool may_mandlock(void)
+static bool may_mandlock(void)
 {
+       pr_warn_once("======================================================\n"
+                    "WARNING: the mand mount option is being deprecated and\n"
+                    "         will be removed in v5.15!\n"
+                    "======================================================\n");
        return capable(CAP_SYS_ADMIN);
 }
 #else
@@ -1938,6 +1943,20 @@ void drop_collected_mounts(struct vfsmount *mnt)
        namespace_unlock();
 }
 
+static bool has_locked_children(struct mount *mnt, struct dentry *dentry)
+{
+       struct mount *child;
+
+       list_for_each_entry(child, &mnt->mnt_mounts, mnt_child) {
+               if (!is_subdir(child->mnt_mountpoint, dentry))
+                       continue;
+
+               if (child->mnt.mnt_flags & MNT_LOCKED)
+                       return true;
+       }
+       return false;
+}
+
 /**
  * clone_private_mount - create a private clone of a path
  * @path: path to clone
@@ -1953,10 +1972,19 @@ struct vfsmount *clone_private_mount(const struct path *path)
        struct mount *old_mnt = real_mount(path->mnt);
        struct mount *new_mnt;
 
+       down_read(&namespace_sem);
        if (IS_MNT_UNBINDABLE(old_mnt))
-               return ERR_PTR(-EINVAL);
+               goto invalid;
+
+       if (!check_mnt(old_mnt))
+               goto invalid;
+
+       if (has_locked_children(old_mnt, path->dentry))
+               goto invalid;
 
        new_mnt = clone_mnt(old_mnt, path->dentry, CL_PRIVATE);
+       up_read(&namespace_sem);
+
        if (IS_ERR(new_mnt))
                return ERR_CAST(new_mnt);
 
@@ -1964,6 +1992,10 @@ struct vfsmount *clone_private_mount(const struct path *path)
        new_mnt->mnt_ns = MNT_NS_INTERNAL;
 
        return &new_mnt->mnt;
+
+invalid:
+       up_read(&namespace_sem);
+       return ERR_PTR(-EINVAL);
 }
 EXPORT_SYMBOL_GPL(clone_private_mount);
 
@@ -2315,19 +2347,6 @@ static int do_change_type(struct path *path, int ms_flags)
        return err;
 }
 
-static bool has_locked_children(struct mount *mnt, struct dentry *dentry)
-{
-       struct mount *child;
-       list_for_each_entry(child, &mnt->mnt_mounts, mnt_child) {
-               if (!is_subdir(child->mnt_mountpoint, dentry))
-                       continue;
-
-               if (child->mnt.mnt_flags & MNT_LOCKED)
-                       return true;
-       }
-       return false;
-}
-
 static struct mount *__do_loopback(struct path *old_path, int recurse)
 {
        struct mount *mnt = ERR_PTR(-EINVAL), *old = real_mount(old_path->mnt);
@@ -4222,7 +4241,7 @@ void __init mnt_init(void)
        int err;
 
        mnt_cache = kmem_cache_create("mnt_cache", sizeof(struct mount),
-                       0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL);
+                       0, SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_ACCOUNT, NULL);
 
        mount_hashtable = alloc_large_system_hash("Mount-cache",
                                sizeof(struct hlist_head),