Merge branch 'work.namespace' into for-linus
authorAl Viro <viro@zeniv.linux.org.uk>
Fri, 23 Dec 2016 04:04:31 +0000 (23:04 -0500)
committerAl Viro <viro@zeniv.linux.org.uk>
Fri, 23 Dec 2016 04:04:31 +0000 (23:04 -0500)
1  2 
fs/namespace.c

diff --combined fs/namespace.c
index f7e28f8ea04d2a629ae7c5ead8b84ca71913cc8a,141d5776c70e30814829ce13cc2ca1fa3f7cefd6..b5b1259e064f8d9661110ba1f1f73d1a0ff19d51
@@@ -96,10 -96,6 +96,6 @@@ static inline struct hlist_head *mp_has
        return &mountpoint_hashtable[tmp & mp_hash_mask];
  }
  
- /*
-  * allocation is serialized by namespace_sem, but we need the spinlock to
-  * serialize with freeing.
-  */
  static int mnt_alloc_id(struct mount *mnt)
  {
        int res;
@@@ -678,7 -674,7 +674,7 @@@ out
   *
   * lookup_mnt takes a reference to the found vfsmount.
   */
 -struct vfsmount *lookup_mnt(struct path *path)
 +struct vfsmount *lookup_mnt(const struct path *path)
  {
        struct mount *child_mnt;
        struct vfsmount *m;
@@@ -1034,6 -1030,8 +1030,8 @@@ static struct mount *clone_mnt(struct m
                if (IS_MNT_SLAVE(old))
                        list_add(&mnt->mnt_slave, &old->mnt_slave);
                mnt->mnt_master = old->mnt_master;
+       } else {
+               CLEAR_MNT_SHARED(mnt);
        }
        if (flag & CL_MAKE_SHARED)
                set_mnt_shared(mnt);
@@@ -1159,36 -1157,7 +1157,36 @@@ struct vfsmount *mntget(struct vfsmoun
  }
  EXPORT_SYMBOL(mntget);
  
 -struct vfsmount *mnt_clone_internal(struct path *path)
 +/* path_is_mountpoint() - Check if path is a mount in the current
 + *                          namespace.
 + *
 + *  d_mountpoint() can only be used reliably to establish if a dentry is
 + *  not mounted in any namespace and that common case is handled inline.
 + *  d_mountpoint() isn't aware of the possibility there may be multiple
 + *  mounts using a given dentry in a different namespace. This function
 + *  checks if the passed in path is a mountpoint rather than the dentry
 + *  alone.
 + */
 +bool path_is_mountpoint(const struct path *path)
 +{
 +      unsigned seq;
 +      bool res;
 +
 +      if (!d_mountpoint(path->dentry))
 +              return false;
 +
 +      rcu_read_lock();
 +      do {
 +              seq = read_seqbegin(&mount_lock);
 +              res = __path_is_mountpoint(path);
 +      } while (read_seqretry(&mount_lock, seq));
 +      rcu_read_unlock();
 +
 +      return res;
 +}
 +EXPORT_SYMBOL(path_is_mountpoint);
 +
 +struct vfsmount *mnt_clone_internal(const struct path *path)
  {
        struct mount *p;
        p = clone_mnt(real_mount(path->mnt), path->dentry, CL_PRIVATE);
@@@ -1787,7 -1756,7 +1785,7 @@@ out
  
  /* Caller should check returned pointer for errors */
  
 -struct vfsmount *collect_mounts(struct path *path)
 +struct vfsmount *collect_mounts(const struct path *path)
  {
        struct mount *tree;
        namespace_lock();
@@@ -1820,7 -1789,7 +1818,7 @@@ void drop_collected_mounts(struct vfsmo
   *
   * Release with mntput().
   */
 -struct vfsmount *clone_private_mount(struct path *path)
 +struct vfsmount *clone_private_mount(const struct path *path)
  {
        struct mount *old_mnt = real_mount(path->mnt);
        struct mount *new_mnt;
        if (IS_MNT_UNBINDABLE(old_mnt))
                return ERR_PTR(-EINVAL);
  
-       down_read(&namespace_sem);
        new_mnt = clone_mnt(old_mnt, path->dentry, CL_PRIVATE);
-       up_read(&namespace_sem);
        if (IS_ERR(new_mnt))
                return ERR_CAST(new_mnt);
  
@@@ -3026,7 -2993,7 +3022,7 @@@ bool is_path_reachable(struct mount *mn
        return &mnt->mnt == root->mnt && is_subdir(dentry, root->dentry);
  }
  
 -bool path_is_under(struct path *path1, struct path *path2)
 +bool path_is_under(const struct path *path1, const struct path *path2)
  {
        bool res;
        read_seqlock_excl(&mount_lock);