[rh7] mnt_ns: introduce global list of mount namespaces for debug

Submitted by Konstantin Khorenko on July 16, 2018, 9:42 a.m.

Details

Message ID 20180716094254.4200-1-khorenko@virtuozzo.com
State New
Series "mnt_ns: introduce global list of mount namespaces for debug"
Headers show

Commit Message

Konstantin Khorenko July 16, 2018, 9:42 a.m.
We've got several cases when ploop could not be unmounted resulting in
-EBUSY. Sometimes we could find what holds it sometimes not, so let's
introduce the global list of mount namespaces: it will make it easier to
debug such cases.

https://jira.sw.ru/browse/PSBM-80869

Signed-off-by: Konstantin Khorenko <khorenko@virtuozzo.com>
---
 fs/mount.h     |  1 +
 fs/namespace.c | 10 ++++++++++
 2 files changed, 11 insertions(+)

Patch hide | download patch | download mbox

diff --git a/fs/mount.h b/fs/mount.h
index f3f39baf9a06..0c4448dbe5d1 100644
--- a/fs/mount.h
+++ b/fs/mount.h
@@ -16,6 +16,7 @@  struct mnt_namespace {
 	u64 event;
 	RH_KABI_EXTEND(unsigned int	mounts) /* # of mounts in the namespace */
 	RH_KABI_EXTEND(unsigned int	pending_mounts)
+	struct list_head	mntns_list;
 };
 
 struct mnt_pcp {
diff --git a/fs/namespace.c b/fs/namespace.c
index 377ba4f36639..9533d45da5b3 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -3125,6 +3125,7 @@  static void free_mnt_ns(struct mnt_namespace *ns)
 	proc_free_inum(ns->proc_inum);
 	dec_mnt_namespaces(ns->ucounts);
 	put_user_ns(ns->user_ns);
+	list_del(&ns->mntns_list);
 	kfree(ns);
 }
 
@@ -3136,6 +3137,7 @@  static void free_mnt_ns(struct mnt_namespace *ns)
  * is effectively never, so we can ignore the possibility.
  */
 static atomic64_t mnt_ns_seq = ATOMIC64_INIT(1);
+static LIST_HEAD(all_mntns_list); /* protected by namespace_sem */
 
 static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *user_ns)
 {
@@ -3162,6 +3164,7 @@  static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *user_ns)
 	atomic_set(&new_ns->count, 1);
 	new_ns->root = NULL;
 	INIT_LIST_HEAD(&new_ns->list);
+	INIT_LIST_HEAD(&new_ns->mntns_list);
 	init_waitqueue_head(&new_ns->poll);
 	new_ns->event = 0;
 	new_ns->user_ns = get_user_ns(user_ns);
@@ -3199,6 +3202,8 @@  struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
 		return new_ns;
 
 	namespace_lock();
+	list_add_tail(&new_ns->mntns_list, &all_mntns_list);
+
 	/* First pass: copy the tree topology */
 	copy_flags = CL_COPY_UNBINDABLE | CL_EXPIRE;
 	if (user_ns != ns->user_ns)
@@ -3262,6 +3267,9 @@  static struct mnt_namespace *create_mnt_ns(struct vfsmount *m)
 		new_ns->root = mnt;
 		new_ns->mounts++;
 		list_add(&mnt->mnt_list, &new_ns->list);
+		namespace_lock();
+		list_add_tail(&new_ns->mntns_list, &all_mntns_list);
+		namespace_unlock();
 	} else {
 		mntput(m);
 	}
@@ -3557,7 +3565,9 @@  void put_mnt_ns(struct mnt_namespace *ns)
 	if (!atomic_dec_and_test(&ns->count))
 		return;
 	drop_collected_mounts(&ns->root->mnt);
+	namespace_lock();
 	free_mnt_ns(ns);
+	namespace_unlock();
 }
 
 struct vfsmount *kern_mount_data(struct file_system_type *type, void *data)

Comments

Konstantin Khorenko July 16, 2018, 10:16 a.m.
Please disregard.

--
Best regards,

Konstantin Khorenko,
Virtuozzo Linux Kernel Team

On 07/16/2018 12:42 PM, Konstantin Khorenko wrote:
> We've got several cases when ploop could not be unmounted resulting in
> -EBUSY. Sometimes we could find what holds it sometimes not, so let's
> introduce the global list of mount namespaces: it will make it easier to
> debug such cases.
>
> https://jira.sw.ru/browse/PSBM-80869
>
> Signed-off-by: Konstantin Khorenko <khorenko@virtuozzo.com>
> ---
>  fs/mount.h     |  1 +
>  fs/namespace.c | 10 ++++++++++
>  2 files changed, 11 insertions(+)
>
> diff --git a/fs/mount.h b/fs/mount.h
> index f3f39baf9a06..0c4448dbe5d1 100644
> --- a/fs/mount.h
> +++ b/fs/mount.h
> @@ -16,6 +16,7 @@ struct mnt_namespace {
>  	u64 event;
>  	RH_KABI_EXTEND(unsigned int	mounts) /* # of mounts in the namespace */
>  	RH_KABI_EXTEND(unsigned int	pending_mounts)
> +	struct list_head	mntns_list;
>  };
>
>  struct mnt_pcp {
> diff --git a/fs/namespace.c b/fs/namespace.c
> index 377ba4f36639..9533d45da5b3 100644
> --- a/fs/namespace.c
> +++ b/fs/namespace.c
> @@ -3125,6 +3125,7 @@ static void free_mnt_ns(struct mnt_namespace *ns)
>  	proc_free_inum(ns->proc_inum);
>  	dec_mnt_namespaces(ns->ucounts);
>  	put_user_ns(ns->user_ns);
> +	list_del(&ns->mntns_list);
>  	kfree(ns);
>  }
>
> @@ -3136,6 +3137,7 @@ static void free_mnt_ns(struct mnt_namespace *ns)
>   * is effectively never, so we can ignore the possibility.
>   */
>  static atomic64_t mnt_ns_seq = ATOMIC64_INIT(1);
> +static LIST_HEAD(all_mntns_list); /* protected by namespace_sem */
>
>  static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *user_ns)
>  {
> @@ -3162,6 +3164,7 @@ static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *user_ns)
>  	atomic_set(&new_ns->count, 1);
>  	new_ns->root = NULL;
>  	INIT_LIST_HEAD(&new_ns->list);
> +	INIT_LIST_HEAD(&new_ns->mntns_list);
>  	init_waitqueue_head(&new_ns->poll);
>  	new_ns->event = 0;
>  	new_ns->user_ns = get_user_ns(user_ns);
> @@ -3199,6 +3202,8 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
>  		return new_ns;
>
>  	namespace_lock();
> +	list_add_tail(&new_ns->mntns_list, &all_mntns_list);
> +
>  	/* First pass: copy the tree topology */
>  	copy_flags = CL_COPY_UNBINDABLE | CL_EXPIRE;
>  	if (user_ns != ns->user_ns)
> @@ -3262,6 +3267,9 @@ static struct mnt_namespace *create_mnt_ns(struct vfsmount *m)
>  		new_ns->root = mnt;
>  		new_ns->mounts++;
>  		list_add(&mnt->mnt_list, &new_ns->list);
> +		namespace_lock();
> +		list_add_tail(&new_ns->mntns_list, &all_mntns_list);
> +		namespace_unlock();
>  	} else {
>  		mntput(m);
>  	}
> @@ -3557,7 +3565,9 @@ void put_mnt_ns(struct mnt_namespace *ns)
>  	if (!atomic_dec_and_test(&ns->count))
>  		return;
>  	drop_collected_mounts(&ns->root->mnt);
> +	namespace_lock();
>  	free_mnt_ns(ns);
> +	namespace_unlock();
>  }
>
>  struct vfsmount *kern_mount_data(struct file_system_type *type, void *data)
>