mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH SERIES 2: 0/4] staging:lustre: improve mounting code
@ 2017-12-18  1:13 NeilBrown
  2017-12-18  1:13 ` [PATCH 1/4] staging: lustre: obdclass: discard FS_NEEDS_DEV flag NeilBrown
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: NeilBrown @ 2017-12-18  1:13 UTC (permalink / raw)
  To: Oleg Drokin, Andreas Dilger, James Simmons, Greg Kroah-Hartman
  Cc: lkml, lustre

These patches make improvements to the lustre code
for supporting the mount system call.

There is a user-visible change: "lustre" now appears in
/proc/filesystem with the "nodev" flag present.  Previously
it didn't have this flag, which was incorrect.

There is also a bugfix: there is a possible module-unload race
that could trigger a crash.

Thanks,
NeilBrown


---

NeilBrown (4):
      staging: lustre: obdclass: discard FS_NEEDS_DEV flag.
      staging: lustre: obdclass: remove pointless struct lustre_mount_data2
      staging: lustre: obdclass: remove vfsmount option from client_fill_super
      staging: lustre: obd_mount: fix possible race with module unload.


 .../staging/lustre/lustre/include/lustre_disk.h    |    6 +-
 .../staging/lustre/lustre/llite/llite_internal.h   |    2 -
 drivers/staging/lustre/lustre/llite/llite_lib.c    |    7 +-
 drivers/staging/lustre/lustre/llite/super25.c      |    6 +-
 drivers/staging/lustre/lustre/obdclass/obd_mount.c |   63 +++++++++-----------
 5 files changed, 38 insertions(+), 46 deletions(-)

--
Signature

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/4] staging: lustre: obdclass: discard FS_NEEDS_DEV flag.
  2017-12-18  1:13 [PATCH SERIES 2: 0/4] staging:lustre: improve mounting code NeilBrown
@ 2017-12-18  1:13 ` NeilBrown
  2017-12-18  1:13 ` [PATCH 3/4] staging: lustre: obdclass: remove vfsmount option from client_fill_super NeilBrown
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: NeilBrown @ 2017-12-18  1:13 UTC (permalink / raw)
  To: Oleg Drokin, Andreas Dilger, James Simmons, Greg Kroah-Hartman
  Cc: lkml, lustre

Lustre mounts do not need a dev, as we can see from lustre_mount()
calling mount_nodev().  So remove the flag which could cause
confusion elsewhere.

Also format lustre_fs_types so that fields line up.

Signed-off-by: NeilBrown <neilb@suse.com>
---
 drivers/staging/lustre/lustre/obdclass/obd_mount.c |   10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/staging/lustre/lustre/obdclass/obd_mount.c b/drivers/staging/lustre/lustre/obdclass/obd_mount.c
index 2a79a223b98a..d49dc72ccba2 100644
--- a/drivers/staging/lustre/lustre/obdclass/obd_mount.c
+++ b/drivers/staging/lustre/lustre/obdclass/obd_mount.c
@@ -1230,11 +1230,11 @@ static void lustre_kill_super(struct super_block *sb)
 /** Register the "lustre" fs type
  */
 static struct file_system_type lustre_fs_type = {
-	.owner	= THIS_MODULE,
-	.name	 = "lustre",
-	.mount	= lustre_mount,
-	.kill_sb      = lustre_kill_super,
-	.fs_flags	= FS_REQUIRES_DEV | FS_RENAME_DOES_D_MOVE,
+	.owner		= THIS_MODULE,
+	.name		= "lustre",
+	.mount		= lustre_mount,
+	.kill_sb	= lustre_kill_super,
+	.fs_flags	= FS_RENAME_DOES_D_MOVE,
 };
 MODULE_ALIAS_FS("lustre");
 

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 2/4] staging: lustre: obdclass: remove pointless struct lustre_mount_data2
  2017-12-18  1:13 [PATCH SERIES 2: 0/4] staging:lustre: improve mounting code NeilBrown
                   ` (2 preceding siblings ...)
  2017-12-18  1:13 ` [PATCH 4/4] staging: lustre: obd_mount: fix possible race with module unload NeilBrown
@ 2017-12-18  1:13 ` NeilBrown
  3 siblings, 0 replies; 5+ messages in thread
From: NeilBrown @ 2017-12-18  1:13 UTC (permalink / raw)
  To: Oleg Drokin, Andreas Dilger, James Simmons, Greg Kroah-Hartman
  Cc: lkml, lustre

This is used to pass a void* and NULL to lustre_fill_super().
It is easier just to pass the void*.

Signed-off-by: NeilBrown <neilb@suse.com>
---
 drivers/staging/lustre/lustre/obdclass/obd_mount.c |   19 ++++---------------
 1 file changed, 4 insertions(+), 15 deletions(-)

diff --git a/drivers/staging/lustre/lustre/obdclass/obd_mount.c b/drivers/staging/lustre/lustre/obdclass/obd_mount.c
index d49dc72ccba2..c98c7716a910 100644
--- a/drivers/staging/lustre/lustre/obdclass/obd_mount.c
+++ b/drivers/staging/lustre/lustre/obdclass/obd_mount.c
@@ -1107,20 +1107,14 @@ static int lmd_parse(char *options, struct lustre_mount_data *lmd)
 	return -EINVAL;
 }
 
-struct lustre_mount_data2 {
-	void *lmd2_data;
-	struct vfsmount *lmd2_mnt;
-};
-
 /** This is the entry point for the mount call into Lustre.
  * This is called when a server or client is mounted,
  * and this is where we start setting things up.
  * @param data Mount options (e.g. -o flock,abort_recov)
  */
-static int lustre_fill_super(struct super_block *sb, void *data, int silent)
+static int lustre_fill_super(struct super_block *sb, void *lmd2_data, int silent)
 {
 	struct lustre_mount_data *lmd;
-	struct lustre_mount_data2 *lmd2 = data;
 	struct lustre_sb_info *lsi;
 	int rc;
 
@@ -1143,7 +1137,7 @@ static int lustre_fill_super(struct super_block *sb, void *data, int silent)
 	obd_zombie_barrier();
 
 	/* Figure out the lmd from the mount options */
-	if (lmd_parse((lmd2->lmd2_data), lmd)) {
+	if (lmd_parse(lmd2_data, lmd)) {
 		lustre_put_lsi(sb);
 		rc = -EINVAL;
 		goto out;
@@ -1165,7 +1159,7 @@ static int lustre_fill_super(struct super_block *sb, void *data, int silent)
 			}
 			/* Connect and start */
 			/* (should always be ll_fill_super) */
-			rc = (*client_fill_super)(sb, lmd2->lmd2_mnt);
+			rc = (*client_fill_super)(sb, NULL);
 			/* c_f_s will call lustre_common_put_super on failure */
 		}
 	} else {
@@ -1209,12 +1203,7 @@ EXPORT_SYMBOL(lustre_register_kill_super_cb);
 static struct dentry *lustre_mount(struct file_system_type *fs_type, int flags,
 				   const char *devname, void *data)
 {
-	struct lustre_mount_data2 lmd2 = {
-		.lmd2_data = data,
-		.lmd2_mnt = NULL
-	};
-
-	return mount_nodev(fs_type, flags, &lmd2, lustre_fill_super);
+	return mount_nodev(fs_type, flags, data, lustre_fill_super);
 }
 
 static void lustre_kill_super(struct super_block *sb)

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 3/4] staging: lustre: obdclass: remove vfsmount option from client_fill_super
  2017-12-18  1:13 [PATCH SERIES 2: 0/4] staging:lustre: improve mounting code NeilBrown
  2017-12-18  1:13 ` [PATCH 1/4] staging: lustre: obdclass: discard FS_NEEDS_DEV flag NeilBrown
@ 2017-12-18  1:13 ` NeilBrown
  2017-12-18  1:13 ` [PATCH 4/4] staging: lustre: obd_mount: fix possible race with module unload NeilBrown
  2017-12-18  1:13 ` [PATCH 2/4] staging: lustre: obdclass: remove pointless struct lustre_mount_data2 NeilBrown
  3 siblings, 0 replies; 5+ messages in thread
From: NeilBrown @ 2017-12-18  1:13 UTC (permalink / raw)
  To: Oleg Drokin, Andreas Dilger, James Simmons, Greg Kroah-Hartman
  Cc: lkml, lustre

This arg is always NULL and is never used.
So discard it from this and related functions.

Signed-off-by: NeilBrown <neilb@suse.com>
---
 .../staging/lustre/lustre/include/lustre_disk.h    |    3 +--
 .../staging/lustre/lustre/llite/llite_internal.h   |    2 +-
 drivers/staging/lustre/lustre/llite/llite_lib.c    |    7 +++----
 drivers/staging/lustre/lustre/obdclass/obd_mount.c |    8 +++-----
 4 files changed, 8 insertions(+), 12 deletions(-)

diff --git a/drivers/staging/lustre/lustre/include/lustre_disk.h b/drivers/staging/lustre/lustre/include/lustre_disk.h
index 8f1a22527006..5089ec02dcad 100644
--- a/drivers/staging/lustre/lustre/include/lustre_disk.h
+++ b/drivers/staging/lustre/lustre/include/lustre_disk.h
@@ -141,8 +141,7 @@ struct lustre_sb_info {
 /* obd_mount.c */
 
 int lustre_start_mgc(struct super_block *sb);
-void lustre_register_client_fill_super(int (*cfs)(struct super_block *sb,
-						  struct vfsmount *mnt));
+void lustre_register_client_fill_super(int (*cfs)(struct super_block *sb));
 void lustre_register_kill_super_cb(void (*cfs)(struct super_block *sb));
 int lustre_common_put_super(struct super_block *sb);
 
diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h
index b133fd00c08c..99e17d0cb3d6 100644
--- a/drivers/staging/lustre/lustre/llite/llite_internal.h
+++ b/drivers/staging/lustre/lustre/llite/llite_internal.h
@@ -792,7 +792,7 @@ int ll_revalidate_it_finish(struct ptlrpc_request *request,
 extern struct super_operations lustre_super_operations;
 
 void ll_lli_init(struct ll_inode_info *lli);
-int ll_fill_super(struct super_block *sb, struct vfsmount *mnt);
+int ll_fill_super(struct super_block *sb);
 void ll_put_super(struct super_block *sb);
 void ll_kill_super(struct super_block *sb);
 struct inode *ll_inode_from_resource_lock(struct ldlm_lock *lock);
diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c
index e84719662edf..6735a6f006d2 100644
--- a/drivers/staging/lustre/lustre/llite/llite_lib.c
+++ b/drivers/staging/lustre/lustre/llite/llite_lib.c
@@ -146,8 +146,7 @@ static void ll_free_sbi(struct super_block *sb)
 	kfree(sbi);
 }
 
-static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
-				    struct vfsmount *mnt)
+static int client_common_fill_super(struct super_block *sb, char *md, char *dt)
 {
 	struct inode *root = NULL;
 	struct ll_sb_info *sbi = ll_s2sbi(sb);
@@ -867,7 +866,7 @@ void ll_lli_init(struct ll_inode_info *lli)
 	mutex_init(&lli->lli_layout_mutex);
 }
 
-int ll_fill_super(struct super_block *sb, struct vfsmount *mnt)
+int ll_fill_super(struct super_block *sb)
 {
 	struct lustre_profile *lprof = NULL;
 	struct lustre_sb_info *lsi = s2lsi(sb);
@@ -944,7 +943,7 @@ int ll_fill_super(struct super_block *sb, struct vfsmount *mnt)
 	}
 
 	/* connections, registrations, sb setup */
-	err = client_common_fill_super(sb, md, dt, mnt);
+	err = client_common_fill_super(sb, md, dt);
 	if (!err)
 		sbi->ll_client_common_fill_super_succeeded = 1;
 
diff --git a/drivers/staging/lustre/lustre/obdclass/obd_mount.c b/drivers/staging/lustre/lustre/obdclass/obd_mount.c
index c98c7716a910..8068cbbc8390 100644
--- a/drivers/staging/lustre/lustre/obdclass/obd_mount.c
+++ b/drivers/staging/lustre/lustre/obdclass/obd_mount.c
@@ -49,8 +49,7 @@
 #include <lustre_disk.h>
 #include <uapi/linux/lustre/lustre_param.h>
 
-static int (*client_fill_super)(struct super_block *sb,
-				struct vfsmount *mnt);
+static int (*client_fill_super)(struct super_block *sb);
 
 static void (*kill_super_cb)(struct super_block *sb);
 
@@ -1159,7 +1158,7 @@ static int lustre_fill_super(struct super_block *sb, void *lmd2_data, int silent
 			}
 			/* Connect and start */
 			/* (should always be ll_fill_super) */
-			rc = (*client_fill_super)(sb, NULL);
+			rc = (*client_fill_super)(sb);
 			/* c_f_s will call lustre_common_put_super on failure */
 		}
 	} else {
@@ -1186,8 +1185,7 @@ static int lustre_fill_super(struct super_block *sb, void *lmd2_data, int silent
 /* We can't call ll_fill_super by name because it lives in a module that
  * must be loaded after this one.
  */
-void lustre_register_client_fill_super(int (*cfs)(struct super_block *sb,
-						  struct vfsmount *mnt))
+void lustre_register_client_fill_super(int (*cfs)(struct super_block *sb))
 {
 	client_fill_super = cfs;
 }

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 4/4] staging: lustre: obd_mount: fix possible race with module unload.
  2017-12-18  1:13 [PATCH SERIES 2: 0/4] staging:lustre: improve mounting code NeilBrown
  2017-12-18  1:13 ` [PATCH 1/4] staging: lustre: obdclass: discard FS_NEEDS_DEV flag NeilBrown
  2017-12-18  1:13 ` [PATCH 3/4] staging: lustre: obdclass: remove vfsmount option from client_fill_super NeilBrown
@ 2017-12-18  1:13 ` NeilBrown
  2017-12-18  1:13 ` [PATCH 2/4] staging: lustre: obdclass: remove pointless struct lustre_mount_data2 NeilBrown
  3 siblings, 0 replies; 5+ messages in thread
From: NeilBrown @ 2017-12-18  1:13 UTC (permalink / raw)
  To: Oleg Drokin, Andreas Dilger, James Simmons, Greg Kroah-Hartman
  Cc: lkml, lustre

lustre_fill_super() calls client_fill_super() without holding a
reference to the module containing client_fill_super.  If that
module is unloaded at a bad time, this can crash.

To be able to get a reference to the module using
try_get_module(), we need a pointer to the module.

So replace
  lustre_register_client_fill_super() and
  lustre_register_kill_super_cb()
with a single
  lustre_register_super_ops()
which also passed a module pointer.

Then use a spinlock to ensure the module pointer isn't removed
while try_module_get() is running, and use try_module_get() to
ensure we have a reference before calling client_fill_super().

Signed-off-by: NeilBrown <neilb@suse.com>
---
 .../staging/lustre/lustre/include/lustre_disk.h    |    5 ++-
 drivers/staging/lustre/lustre/llite/super25.c      |    6 +---
 drivers/staging/lustre/lustre/obdclass/obd_mount.c |   30 +++++++++++++-------
 3 files changed, 24 insertions(+), 17 deletions(-)

diff --git a/drivers/staging/lustre/lustre/include/lustre_disk.h b/drivers/staging/lustre/lustre/include/lustre_disk.h
index 5089ec02dcad..100e993ab00b 100644
--- a/drivers/staging/lustre/lustre/include/lustre_disk.h
+++ b/drivers/staging/lustre/lustre/include/lustre_disk.h
@@ -141,8 +141,9 @@ struct lustre_sb_info {
 /* obd_mount.c */
 
 int lustre_start_mgc(struct super_block *sb);
-void lustre_register_client_fill_super(int (*cfs)(struct super_block *sb));
-void lustre_register_kill_super_cb(void (*cfs)(struct super_block *sb));
+void lustre_register_super_ops(struct module *mod,
+			       int (*cfs)(struct super_block *sb),
+			       void (*ksc)(struct super_block *sb));
 int lustre_common_put_super(struct super_block *sb);
 
 int mgc_fsname2resid(char *fsname, struct ldlm_res_id *res_id, int type);
diff --git a/drivers/staging/lustre/lustre/llite/super25.c b/drivers/staging/lustre/lustre/llite/super25.c
index 0bda111a096e..10105339790e 100644
--- a/drivers/staging/lustre/lustre/llite/super25.c
+++ b/drivers/staging/lustre/lustre/llite/super25.c
@@ -159,8 +159,7 @@ static int __init lustre_init(void)
 	if (rc != 0)
 		goto out_inode_fini_env;
 
-	lustre_register_client_fill_super(ll_fill_super);
-	lustre_register_kill_super_cb(ll_kill_super);
+	lustre_register_super_ops(THIS_MODULE, ll_fill_super, ll_kill_super);
 	lustre_register_client_process_config(ll_process_config);
 
 	return 0;
@@ -181,8 +180,7 @@ static int __init lustre_init(void)
 
 static void __exit lustre_exit(void)
 {
-	lustre_register_client_fill_super(NULL);
-	lustre_register_kill_super_cb(NULL);
+	lustre_register_super_ops(NULL, NULL, NULL);
 	lustre_register_client_process_config(NULL);
 
 	debugfs_remove(llite_root);
diff --git a/drivers/staging/lustre/lustre/obdclass/obd_mount.c b/drivers/staging/lustre/lustre/obdclass/obd_mount.c
index 8068cbbc8390..acc1ea773c9c 100644
--- a/drivers/staging/lustre/lustre/obdclass/obd_mount.c
+++ b/drivers/staging/lustre/lustre/obdclass/obd_mount.c
@@ -49,8 +49,9 @@
 #include <lustre_disk.h>
 #include <uapi/linux/lustre/lustre_param.h>
 
+static DEFINE_SPINLOCK(client_lock);
+static struct module *client_mod;
 static int (*client_fill_super)(struct super_block *sb);
-
 static void (*kill_super_cb)(struct super_block *sb);
 
 /**************** config llog ********************/
@@ -1143,10 +1144,15 @@ static int lustre_fill_super(struct super_block *sb, void *lmd2_data, int silent
 	}
 
 	if (lmd_is_client(lmd)) {
+		bool have_client = false;
 		CDEBUG(D_MOUNT, "Mounting client %s\n", lmd->lmd_profile);
 		if (!client_fill_super)
 			request_module("lustre");
-		if (!client_fill_super) {
+		spin_lock(&client_lock);
+		if (client_fill_super && try_module_get(client_mod))
+			have_client = true;
+		spin_unlock(&client_lock);
+		if (!have_client) {
 			LCONSOLE_ERROR_MSG(0x165, "Nothing registered for client mount! Is the 'lustre' module loaded?\n");
 			lustre_put_lsi(sb);
 			rc = -ENODEV;
@@ -1159,7 +1165,9 @@ static int lustre_fill_super(struct super_block *sb, void *lmd2_data, int silent
 			/* Connect and start */
 			/* (should always be ll_fill_super) */
 			rc = (*client_fill_super)(sb);
-			/* c_f_s will call lustre_common_put_super on failure */
+			/* c_f_s will call lustre_common_put_super on failure, otherwise
+			 * c_f_s will have taken another reference to the module */
+			module_put(client_mod);
 		}
 	} else {
 		CERROR("This is client-side-only module, cannot handle server mount.\n");
@@ -1185,17 +1193,17 @@ static int lustre_fill_super(struct super_block *sb, void *lmd2_data, int silent
 /* We can't call ll_fill_super by name because it lives in a module that
  * must be loaded after this one.
  */
-void lustre_register_client_fill_super(int (*cfs)(struct super_block *sb))
+void lustre_register_super_ops(struct module *mod,
+			       int (*cfs)(struct super_block *sb),
+			       void (*ksc)(struct super_block *sb))
 {
+	spin_lock(&client_lock);
+	client_mod = mod;
 	client_fill_super = cfs;
+	kill_super_cb = ksc;
+	spin_unlock(&client_lock);
 }
-EXPORT_SYMBOL(lustre_register_client_fill_super);
-
-void lustre_register_kill_super_cb(void (*cfs)(struct super_block *sb))
-{
-	kill_super_cb = cfs;
-}
-EXPORT_SYMBOL(lustre_register_kill_super_cb);
+EXPORT_SYMBOL(lustre_register_super_ops);
 
 /***************** FS registration ******************/
 static struct dentry *lustre_mount(struct file_system_type *fs_type, int flags,

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2017-12-18  1:14 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-12-18  1:13 [PATCH SERIES 2: 0/4] staging:lustre: improve mounting code NeilBrown
2017-12-18  1:13 ` [PATCH 1/4] staging: lustre: obdclass: discard FS_NEEDS_DEV flag NeilBrown
2017-12-18  1:13 ` [PATCH 3/4] staging: lustre: obdclass: remove vfsmount option from client_fill_super NeilBrown
2017-12-18  1:13 ` [PATCH 4/4] staging: lustre: obd_mount: fix possible race with module unload NeilBrown
2017-12-18  1:13 ` [PATCH 2/4] staging: lustre: obdclass: remove pointless struct lustre_mount_data2 NeilBrown

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®