#include <linux/cleancache.h>
 #include <linux/fsnotify.h>
 #include <linux/lockdep.h>
+#include <linux/user_namespace.h>
 #include "internal.h"
 
 
        list_lru_destroy(&s->s_inode_lru);
        security_sb_free(s);
        WARN_ON(!list_empty(&s->s_mounts));
+       put_user_ns(s->s_user_ns);
        kfree(s->s_subtype);
        kfree(s->s_options);
        call_rcu(&s->rcu, destroy_super_rcu);
  *     alloc_super     -       create new superblock
  *     @type:  filesystem type superblock should belong to
  *     @flags: the mount flags
+ *     @user_ns: User namespace for the super_block
  *
  *     Allocates and initializes a new &struct super_block.  alloc_super()
  *     returns a pointer new superblock or %NULL if allocation had failed.
  */
-static struct super_block *alloc_super(struct file_system_type *type, int flags)
+static struct super_block *alloc_super(struct file_system_type *type, int flags,
+                                      struct user_namespace *user_ns)
 {
        struct super_block *s = kzalloc(sizeof(struct super_block),  GFP_USER);
        static const struct super_operations default_op;
                return NULL;
 
        INIT_LIST_HEAD(&s->s_mounts);
+       s->s_user_ns = get_user_ns(user_ns);
 
        if (security_sb_alloc(s))
                goto fail;
 EXPORT_SYMBOL(generic_shutdown_super);
 
 /**
- *     sget    -       find or create a superblock
+ *     sget_userns -   find or create a superblock
  *     @type:  filesystem type superblock should belong to
  *     @test:  comparison callback
  *     @set:   setup callback
  *     @flags: mount flags
+ *     @user_ns: User namespace for the super_block
  *     @data:  argument to each of them
  */
-struct super_block *sget(struct file_system_type *type,
+struct super_block *sget_userns(struct file_system_type *type,
                        int (*test)(struct super_block *,void *),
                        int (*set)(struct super_block *,void *),
-                       int flags,
+                       int flags, struct user_namespace *user_ns,
                        void *data)
 {
        struct super_block *s = NULL;
                hlist_for_each_entry(old, &type->fs_supers, s_instances) {
                        if (!test(old, data))
                                continue;
+                       if (user_ns != old->s_user_ns) {
+                               spin_unlock(&sb_lock);
+                               if (s) {
+                                       up_write(&s->s_umount);
+                                       destroy_super(s);
+                               }
+                               return ERR_PTR(-EBUSY);
+                       }
                        if (!grab_super(old))
                                goto retry;
                        if (s) {
        }
        if (!s) {
                spin_unlock(&sb_lock);
-               s = alloc_super(type, flags);
+               s = alloc_super(type, flags, user_ns);
                if (!s)
                        return ERR_PTR(-ENOMEM);
                goto retry;
        return s;
 }
 
+EXPORT_SYMBOL(sget_userns);
+
+/**
+ *     sget    -       find or create a superblock
+ *     @type:    filesystem type superblock should belong to
+ *     @test:    comparison callback
+ *     @set:     setup callback
+ *     @flags:   mount flags
+ *     @data:    argument to each of them
+ */
+struct super_block *sget(struct file_system_type *type,
+                       int (*test)(struct super_block *,void *),
+                       int (*set)(struct super_block *,void *),
+                       int flags,
+                       void *data)
+{
+       struct user_namespace *user_ns = current_user_ns();
+
+       /* Ensure the requestor has permissions over the target filesystem */
+       if (!(flags & MS_KERNMOUNT) && !ns_capable(user_ns, CAP_SYS_ADMIN))
+               return ERR_PTR(-EPERM);
+
+       return sget_userns(type, test, set, flags, user_ns, data);
+}
+
 EXPORT_SYMBOL(sget);
 
 void drop_super(struct super_block *sb)
        if (!(flags & MS_KERNMOUNT) && !ns_capable(user_ns, CAP_SYS_ADMIN))
                return ERR_PTR(-EPERM);
 
-       sb = sget(fs_type, ns_test_super, ns_set_super, flags, ns);
+       sb = sget_userns(fs_type, ns_test_super, ns_set_super, flags,
+                        user_ns, ns);
        if (IS_ERR(sb))
                return ERR_CAST(sb);
 
 
        struct workqueue_struct *s_dio_done_wq;
        struct hlist_head s_pins;
 
+       /*
+        * Owning user namespace and default context in which to
+        * interpret filesystem uids, gids, quotas, device nodes,
+        * xattrs and security labels.
+        */
+       struct user_namespace *s_user_ns;
+
        /*
         * Keep the lru lists last in the structure so they always sit on their
         * own individual cachelines.
 int set_anon_super(struct super_block *s, void *data);
 int get_anon_bdev(dev_t *);
 void free_anon_bdev(dev_t);
+struct super_block *sget_userns(struct file_system_type *type,
+                       int (*test)(struct super_block *,void *),
+                       int (*set)(struct super_block *,void *),
+                       int flags, struct user_namespace *user_ns,
+                       void *data);
 struct super_block *sget(struct file_system_type *type,
                        int (*test)(struct super_block *,void *),
                        int (*set)(struct super_block *,void *),