ceph-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/4] ceph: new mount device syntax
@ 2021-07-02  6:48 Venky Shankar
  2021-07-02  6:48 ` [PATCH v2 1/4] ceph: new device mount syntax Venky Shankar
                   ` (4 more replies)
  0 siblings, 5 replies; 20+ messages in thread
From: Venky Shankar @ 2021-07-02  6:48 UTC (permalink / raw)
  To: jlayton, idryomov, lhenriques; +Cc: pdonnell, ceph-devel, Venky Shankar

v2:
 - doc suggestions/fixes by Jeff
 - parse_fsid -> ceph_parse_fsid
 - avoid kstrdup whereever possible, also fixes a memleak
 - fail mount when mon_addr is unavailable (for new syntax)
 - use dout() instead of invalfc() during new syntax check

This series introduces changes Ceph File System mount device string.
Old mount device syntax (source) has the following problems:

mounts to the same cluster but with different fsnames
and/or creds have identical device string which can
confuse xfstests.

Userspace mount helper tool resolves monitor addresses
and fill in mon addrs automatically, but that means the
device shown in /proc/mounts is different than what was
used for mounting.

New device syntax is as follows:

  cephuser@fsid.mycephfs2=/path

Note, there is no "monitor address" in the device string.
That gets passed in as mount option. This keeps the device
string same when monitor addresses change (on remounts).

Also note that the userspace mount helper tool is backward
compatible. I.e., the mount helper will fallback to using
old syntax after trying to mount with the new syntax.

Venky Shankar (4):
  ceph: new device mount syntax
  ceph: validate cluster FSID for new device syntax
  ceph: record updated mon_addr on remount
  doc: document new CephFS mount device syntax

 Documentation/filesystems/ceph.rst |  25 +++++-
 fs/ceph/super.c                    | 137 ++++++++++++++++++++++++++---
 fs/ceph/super.h                    |   4 +
 include/linux/ceph/libceph.h       |   1 +
 net/ceph/ceph_common.c             |   5 +-
 5 files changed, 157 insertions(+), 15 deletions(-)

-- 
2.27.0


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

* [PATCH v2 1/4] ceph: new device mount syntax
  2021-07-02  6:48 [PATCH v2 0/4] ceph: new mount device syntax Venky Shankar
@ 2021-07-02  6:48 ` Venky Shankar
  2021-07-02 10:38   ` Luis Henriques
  2021-07-02  6:48 ` [PATCH v2 2/4] ceph: validate cluster FSID for new device syntax Venky Shankar
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 20+ messages in thread
From: Venky Shankar @ 2021-07-02  6:48 UTC (permalink / raw)
  To: jlayton, idryomov, lhenriques; +Cc: pdonnell, ceph-devel, Venky Shankar

Old mount device syntax (source) has the following problems:

- mounts to the same cluster but with different fsnames
  and/or creds have identical device string which can
  confuse xfstests.

- Userspace mount helper tool resolves monitor addresses
  and fill in mon addrs automatically, but that means the
  device shown in /proc/mounts is different than what was
  used for mounting.

New device syntax is as follows:

  cephuser@fsid.mycephfs2=/path

Note, there is no "monitor address" in the device string.
That gets passed in as mount option. This keeps the device
string same when monitor addresses change (on remounts).

Also note that the userspace mount helper tool is backward
compatible. I.e., the mount helper will fallback to using
old syntax after trying to mount with the new syntax.

Signed-off-by: Venky Shankar <vshankar@redhat.com>
---
 fs/ceph/super.c | 122 ++++++++++++++++++++++++++++++++++++++++++++----
 fs/ceph/super.h |   3 ++
 2 files changed, 115 insertions(+), 10 deletions(-)

diff --git a/fs/ceph/super.c b/fs/ceph/super.c
index 9b1b7f4cfdd4..0b324e43c9f4 100644
--- a/fs/ceph/super.c
+++ b/fs/ceph/super.c
@@ -145,6 +145,7 @@ enum {
 	Opt_mds_namespace,
 	Opt_recover_session,
 	Opt_source,
+	Opt_mon_addr,
 	/* string args above */
 	Opt_dirstat,
 	Opt_rbytes,
@@ -196,6 +197,7 @@ static const struct fs_parameter_spec ceph_mount_parameters[] = {
 	fsparam_u32	("rsize",			Opt_rsize),
 	fsparam_string	("snapdirname",			Opt_snapdirname),
 	fsparam_string	("source",			Opt_source),
+	fsparam_string	("mon_addr",			Opt_mon_addr),
 	fsparam_u32	("wsize",			Opt_wsize),
 	fsparam_flag_no	("wsync",			Opt_wsync),
 	{}
@@ -226,10 +228,70 @@ static void canonicalize_path(char *path)
 	path[j] = '\0';
 }
 
+static int ceph_parse_old_source(const char *dev_name, const char *dev_name_end,
+				 struct fs_context *fc)
+{
+	int r;
+	struct ceph_parse_opts_ctx *pctx = fc->fs_private;
+	struct ceph_mount_options *fsopt = pctx->opts;
+
+	if (*dev_name_end != ':')
+		return invalfc(fc, "separator ':' missing in source");
+
+	r = ceph_parse_mon_ips(dev_name, dev_name_end - dev_name,
+			       pctx->copts, fc->log.log);
+	if (r)
+		return r;
+
+	fsopt->new_dev_syntax = false;
+	return 0;
+}
+
+static int ceph_parse_new_source(const char *dev_name, const char *dev_name_end,
+				 struct fs_context *fc)
+{
+	struct ceph_parse_opts_ctx *pctx = fc->fs_private;
+	struct ceph_mount_options *fsopt = pctx->opts;
+	char *fsid_start, *fs_name_start;
+
+	if (*dev_name_end != '=') {
+		dout("separator '=' missing in source");
+		return -EINVAL;
+	}
+
+	fsid_start = strchr(dev_name, '@');
+	if (!fsid_start)
+		return invalfc(fc, "missing cluster fsid");
+	++fsid_start; /* start of cluster fsid */
+
+	fs_name_start = strchr(fsid_start, '.');
+	if (!fs_name_start)
+		return invalfc(fc, "missing file system name");
+
+	++fs_name_start; /* start of file system name */
+	fsopt->mds_namespace = kstrndup(fs_name_start,
+					dev_name_end - fs_name_start, GFP_KERNEL);
+	if (!fsopt->mds_namespace)
+		return -ENOMEM;
+	dout("file system (mds namespace) '%s'\n", fsopt->mds_namespace);
+
+	fsopt->new_dev_syntax = true;
+	return 0;
+}
+
 /*
- * Parse the source parameter.  Distinguish the server list from the path.
+ * Parse the source parameter for new device format. Distinguish the device
+ * spec from the path. Try parsing new device format and fallback to old
+ * format if needed.
  *
- * The source will look like:
+ * New device syntax will looks like:
+ *     <device_spec>=/<path>
+ * where
+ *     <device_spec> is name@fsid.fsname
+ *     <path> is optional, but if present must begin with '/'
+ * (monitor addresses are passed via mount option)
+ *
+ * Old device syntax is:
  *     <server_spec>[,<server_spec>...]:[<path>]
  * where
  *     <server_spec> is <ip>[:<port>]
@@ -262,22 +324,48 @@ static int ceph_parse_source(struct fs_parameter *param, struct fs_context *fc)
 		dev_name_end = dev_name + strlen(dev_name);
 	}
 
-	dev_name_end--;		/* back up to ':' separator */
-	if (dev_name_end < dev_name || *dev_name_end != ':')
-		return invalfc(fc, "No path or : separator in source");
+	dev_name_end--;		/* back up to separator */
+	if (dev_name_end < dev_name)
+		return invalfc(fc, "path missing in source");
 
 	dout("device name '%.*s'\n", (int)(dev_name_end - dev_name), dev_name);
 	if (fsopt->server_path)
 		dout("server path '%s'\n", fsopt->server_path);
 
-	ret = ceph_parse_mon_ips(param->string, dev_name_end - dev_name,
-				 pctx->copts, fc->log.log);
+	dout("trying new device syntax");
+	ret = ceph_parse_new_source(dev_name, dev_name_end, fc);
+	if (ret == 0)
+		goto done;
+
+	dout("trying old device syntax");
+	ret = ceph_parse_old_source(dev_name, dev_name_end, fc);
 	if (ret)
-		return ret;
+		goto out;
 
+ done:
 	fc->source = param->string;
 	param->string = NULL;
-	return 0;
+ out:
+	return ret;
+}
+
+static int ceph_parse_mon_addr(struct fs_parameter *param,
+			       struct fs_context *fc)
+{
+	int r;
+	struct ceph_parse_opts_ctx *pctx = fc->fs_private;
+	struct ceph_mount_options *fsopt = pctx->opts;
+
+	kfree(fsopt->mon_addr);
+	fsopt->mon_addr = param->string;
+	param->string = NULL;
+
+	strreplace(fsopt->mon_addr, '/', ',');
+	r = ceph_parse_mon_ips(fsopt->mon_addr, strlen(fsopt->mon_addr),
+			       pctx->copts, fc->log.log);
+        // since its used in ceph_show_options()
+	strreplace(fsopt->mon_addr, ',', '/');
+	return r;
 }
 
 static int ceph_parse_mount_param(struct fs_context *fc,
@@ -322,6 +410,8 @@ static int ceph_parse_mount_param(struct fs_context *fc,
 		if (fc->source)
 			return invalfc(fc, "Multiple sources specified");
 		return ceph_parse_source(param, fc);
+	case Opt_mon_addr:
+		return ceph_parse_mon_addr(param, fc);
 	case Opt_wsize:
 		if (result.uint_32 < PAGE_SIZE ||
 		    result.uint_32 > CEPH_MAX_WRITE_SIZE)
@@ -473,6 +563,7 @@ static void destroy_mount_options(struct ceph_mount_options *args)
 	kfree(args->mds_namespace);
 	kfree(args->server_path);
 	kfree(args->fscache_uniq);
+	kfree(args->mon_addr);
 	kfree(args);
 }
 
@@ -516,6 +607,10 @@ static int compare_mount_options(struct ceph_mount_options *new_fsopt,
 	if (ret)
 		return ret;
 
+	ret = strcmp_null(fsopt1->mon_addr, fsopt2->mon_addr);
+	if (ret)
+		return ret;
+
 	return ceph_compare_options(new_opt, fsc->client);
 }
 
@@ -571,9 +666,13 @@ static int ceph_show_options(struct seq_file *m, struct dentry *root)
 	if ((fsopt->flags & CEPH_MOUNT_OPT_NOCOPYFROM) == 0)
 		seq_puts(m, ",copyfrom");
 
-	if (fsopt->mds_namespace)
+	/* dump mds_namespace when old device syntax is in use */
+	if (fsopt->mds_namespace && !fsopt->new_dev_syntax)
 		seq_show_option(m, "mds_namespace", fsopt->mds_namespace);
 
+	if (fsopt->mon_addr)
+		seq_printf(m, ",mon_addr=%s", fsopt->mon_addr);
+
 	if (fsopt->flags & CEPH_MOUNT_OPT_CLEANRECOVER)
 		seq_show_option(m, "recover_session", "clean");
 
@@ -1048,6 +1147,7 @@ static int ceph_setup_bdi(struct super_block *sb, struct ceph_fs_client *fsc)
 static int ceph_get_tree(struct fs_context *fc)
 {
 	struct ceph_parse_opts_ctx *pctx = fc->fs_private;
+	struct ceph_mount_options *fsopt = pctx->opts;
 	struct super_block *sb;
 	struct ceph_fs_client *fsc;
 	struct dentry *res;
@@ -1059,6 +1159,8 @@ static int ceph_get_tree(struct fs_context *fc)
 
 	if (!fc->source)
 		return invalfc(fc, "No source");
+	if (fsopt->new_dev_syntax && !fsopt->mon_addr)
+		return invalfc(fc, "No monitor address");
 
 	/* create client (which we may/may not use) */
 	fsc = create_fs_client(pctx->opts, pctx->copts);
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index c48bb30c8d70..8f71184b7c85 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -87,6 +87,8 @@ struct ceph_mount_options {
 	unsigned int max_readdir;       /* max readdir result (entries) */
 	unsigned int max_readdir_bytes; /* max readdir result (bytes) */
 
+	bool new_dev_syntax;
+
 	/*
 	 * everything above this point can be memcmp'd; everything below
 	 * is handled in compare_mount_options()
@@ -96,6 +98,7 @@ struct ceph_mount_options {
 	char *mds_namespace;  /* default NULL */
 	char *server_path;    /* default NULL (means "/") */
 	char *fscache_uniq;   /* default NULL */
+	char *mon_addr;
 };
 
 struct ceph_fs_client {
-- 
2.27.0


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

* [PATCH v2 2/4] ceph: validate cluster FSID for new device syntax
  2021-07-02  6:48 [PATCH v2 0/4] ceph: new mount device syntax Venky Shankar
  2021-07-02  6:48 ` [PATCH v2 1/4] ceph: new device mount syntax Venky Shankar
@ 2021-07-02  6:48 ` Venky Shankar
  2021-07-02 10:44   ` Luis Henriques
  2021-07-02  6:48 ` [PATCH v2 3/4] ceph: record updated mon_addr on remount Venky Shankar
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 20+ messages in thread
From: Venky Shankar @ 2021-07-02  6:48 UTC (permalink / raw)
  To: jlayton, idryomov, lhenriques; +Cc: pdonnell, ceph-devel, Venky Shankar

The new device syntax requires the cluster FSID as part
of the device string. Use this FSID to verify if it matches
the cluster FSID we get back from the monitor, failing the
mount on mismatch.

Also, rename parse_fsid() to ceph_parse_fsid() as it is too
generic.

Signed-off-by: Venky Shankar <vshankar@redhat.com>
---
 fs/ceph/super.c              | 9 +++++++++
 fs/ceph/super.h              | 1 +
 include/linux/ceph/libceph.h | 1 +
 net/ceph/ceph_common.c       | 5 +++--
 4 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/fs/ceph/super.c b/fs/ceph/super.c
index 0b324e43c9f4..03e5f4bb2b6f 100644
--- a/fs/ceph/super.c
+++ b/fs/ceph/super.c
@@ -268,6 +268,9 @@ static int ceph_parse_new_source(const char *dev_name, const char *dev_name_end,
 	if (!fs_name_start)
 		return invalfc(fc, "missing file system name");
 
+	if (ceph_parse_fsid(fsid_start, &fsopt->fsid))
+		return invalfc(fc, "invalid fsid format");
+
 	++fs_name_start; /* start of file system name */
 	fsopt->mds_namespace = kstrndup(fs_name_start,
 					dev_name_end - fs_name_start, GFP_KERNEL);
@@ -750,6 +753,12 @@ static struct ceph_fs_client *create_fs_client(struct ceph_mount_options *fsopt,
 	}
 	opt = NULL; /* fsc->client now owns this */
 
+	/* help learn fsid */
+	if (fsopt->new_dev_syntax) {
+		ceph_check_fsid(fsc->client, &fsopt->fsid);
+		fsc->client->have_fsid = true;
+	}
+
 	fsc->client->extra_mon_dispatch = extra_mon_dispatch;
 	ceph_set_opt(fsc->client, ABORT_ON_FULL);
 
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index 8f71184b7c85..ce5fb90a01a4 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -99,6 +99,7 @@ struct ceph_mount_options {
 	char *server_path;    /* default NULL (means "/") */
 	char *fscache_uniq;   /* default NULL */
 	char *mon_addr;
+	struct ceph_fsid fsid;
 };
 
 struct ceph_fs_client {
diff --git a/include/linux/ceph/libceph.h b/include/linux/ceph/libceph.h
index 409d8c29bc4f..75d059b79d90 100644
--- a/include/linux/ceph/libceph.h
+++ b/include/linux/ceph/libceph.h
@@ -296,6 +296,7 @@ extern bool libceph_compatible(void *data);
 extern const char *ceph_msg_type_name(int type);
 extern int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid);
 extern void *ceph_kvmalloc(size_t size, gfp_t flags);
+extern int ceph_parse_fsid(const char *str, struct ceph_fsid *fsid);
 
 struct fs_parameter;
 struct fc_log;
diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c
index 97d6ea763e32..da480757fcca 100644
--- a/net/ceph/ceph_common.c
+++ b/net/ceph/ceph_common.c
@@ -217,7 +217,7 @@ void *ceph_kvmalloc(size_t size, gfp_t flags)
 	return p;
 }
 
-static int parse_fsid(const char *str, struct ceph_fsid *fsid)
+int ceph_parse_fsid(const char *str, struct ceph_fsid *fsid)
 {
 	int i = 0;
 	char tmp[3];
@@ -247,6 +247,7 @@ static int parse_fsid(const char *str, struct ceph_fsid *fsid)
 	dout("parse_fsid ret %d got fsid %pU\n", err, fsid);
 	return err;
 }
+EXPORT_SYMBOL(ceph_parse_fsid);
 
 /*
  * ceph options
@@ -465,7 +466,7 @@ int ceph_parse_param(struct fs_parameter *param, struct ceph_options *opt,
 		break;
 
 	case Opt_fsid:
-		err = parse_fsid(param->string, &opt->fsid);
+		err = ceph_parse_fsid(param->string, &opt->fsid);
 		if (err) {
 			error_plog(&log, "Failed to parse fsid: %d", err);
 			return err;
-- 
2.27.0


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

* [PATCH v2 3/4] ceph: record updated mon_addr on remount
  2021-07-02  6:48 [PATCH v2 0/4] ceph: new mount device syntax Venky Shankar
  2021-07-02  6:48 ` [PATCH v2 1/4] ceph: new device mount syntax Venky Shankar
  2021-07-02  6:48 ` [PATCH v2 2/4] ceph: validate cluster FSID for new device syntax Venky Shankar
@ 2021-07-02  6:48 ` Venky Shankar
  2021-07-02  6:48 ` [PATCH v2 4/4] doc: document new CephFS mount device syntax Venky Shankar
  2021-07-02 18:05 ` [PATCH v2 0/4] ceph: new " Patrick Donnelly
  4 siblings, 0 replies; 20+ messages in thread
From: Venky Shankar @ 2021-07-02  6:48 UTC (permalink / raw)
  To: jlayton, idryomov, lhenriques; +Cc: pdonnell, ceph-devel, Venky Shankar

Note that the new monitors are just shown in /proc/mounts.
Ceph does not (re)connect to new monitors yet.

Signed-off-by: Venky Shankar <vshankar@redhat.com>
---
 fs/ceph/super.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/fs/ceph/super.c b/fs/ceph/super.c
index 03e5f4bb2b6f..52f03505bb86 100644
--- a/fs/ceph/super.c
+++ b/fs/ceph/super.c
@@ -1255,6 +1255,12 @@ static int ceph_reconfigure_fc(struct fs_context *fc)
 	else
 		ceph_clear_mount_opt(fsc, ASYNC_DIROPS);
 
+	if (strcmp(fsc->mount_options->mon_addr, fsopt->mon_addr)) {
+		kfree(fsc->mount_options->mon_addr);
+		fsc->mount_options->mon_addr = fsopt->mon_addr;
+		fsopt->mon_addr = NULL;
+	}
+
 	sync_filesystem(fc->root->d_sb);
 	return 0;
 }
-- 
2.27.0


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

* [PATCH v2 4/4] doc: document new CephFS mount device syntax
  2021-07-02  6:48 [PATCH v2 0/4] ceph: new mount device syntax Venky Shankar
                   ` (2 preceding siblings ...)
  2021-07-02  6:48 ` [PATCH v2 3/4] ceph: record updated mon_addr on remount Venky Shankar
@ 2021-07-02  6:48 ` Venky Shankar
  2021-07-02 18:08   ` Patrick Donnelly
  2021-07-02 18:05 ` [PATCH v2 0/4] ceph: new " Patrick Donnelly
  4 siblings, 1 reply; 20+ messages in thread
From: Venky Shankar @ 2021-07-02  6:48 UTC (permalink / raw)
  To: jlayton, idryomov, lhenriques; +Cc: pdonnell, ceph-devel, Venky Shankar

Signed-off-by: Venky Shankar <vshankar@redhat.com>
---
 Documentation/filesystems/ceph.rst | 25 ++++++++++++++++++++++---
 1 file changed, 22 insertions(+), 3 deletions(-)

diff --git a/Documentation/filesystems/ceph.rst b/Documentation/filesystems/ceph.rst
index 7d2ef4e27273..830ea8969d9d 100644
--- a/Documentation/filesystems/ceph.rst
+++ b/Documentation/filesystems/ceph.rst
@@ -82,7 +82,7 @@ Mount Syntax
 
 The basic mount syntax is::
 
- # mount -t ceph monip[:port][,monip2[:port]...]:/[subdir] mnt
+ # mount -t ceph user@fsid.fs_name=/[subdir] mnt -o mon_addr=monip1[:port][/monip2[:port]]
 
 You only need to specify a single monitor, as the client will get the
 full list when it connects.  (However, if the monitor you specify
@@ -90,16 +90,35 @@ happens to be down, the mount won't succeed.)  The port can be left
 off if the monitor is using the default.  So if the monitor is at
 1.2.3.4::
 
- # mount -t ceph 1.2.3.4:/ /mnt/ceph
+ # mount -t ceph cephuser@07fe3187-00d9-42a3-814b-72a4d5e7d5be.cephfs=/ /mnt/ceph -o mon_addr=1.2.3.4
 
 is sufficient.  If /sbin/mount.ceph is installed, a hostname can be
-used instead of an IP address.
+used instead of an IP address and the cluster FSID can be left out
+(as the mount helper will fill it in by reading the ceph configuration
+file)::
 
+  # mount -t ceph cephuser@cephfs=/ /mnt/ceph -o mon_addr=mon-addr
 
+Multiple monitor addresses can be passed by separating each address with a slash (`/`)::
+
+  # mount -t ceph cephuser@cephfs=/ /mnt/ceph -o mon_addr=192.168.1.100/192.168.1.101
+
+When using the mount helper, monitor address can be read from ceph
+configuration file if available. Note that, the cluster FSID (passed as part
+of the device string) is validated by checking it with the FSID reported by
+the monitor.
 
 Mount Options
 =============
 
+  mon_addr=ip_address[:port][/ip_address[:port]]
+	Monitor address to the cluster. This is used to bootstrap the
+        connection to the cluster. Once connection is established, the
+        monitor addresses in the monitor map are followed.
+
+  fsid=cluster-id
+	FSID of the cluster
+
   ip=A.B.C.D[:N]
 	Specify the IP and/or port the client should bind to locally.
 	There is normally not much reason to do this.  If the IP is not
-- 
2.27.0


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

* Re: [PATCH v2 1/4] ceph: new device mount syntax
  2021-07-02  6:48 ` [PATCH v2 1/4] ceph: new device mount syntax Venky Shankar
@ 2021-07-02 10:38   ` Luis Henriques
  2021-07-02 11:05     ` Venky Shankar
  0 siblings, 1 reply; 20+ messages in thread
From: Luis Henriques @ 2021-07-02 10:38 UTC (permalink / raw)
  To: Venky Shankar; +Cc: jlayton, idryomov, pdonnell, ceph-devel

On Fri, Jul 02, 2021 at 12:18:18PM +0530, Venky Shankar wrote:
> Old mount device syntax (source) has the following problems:
> 
> - mounts to the same cluster but with different fsnames
>   and/or creds have identical device string which can
>   confuse xfstests.
> 
> - Userspace mount helper tool resolves monitor addresses
>   and fill in mon addrs automatically, but that means the
>   device shown in /proc/mounts is different than what was
>   used for mounting.
> 
> New device syntax is as follows:
> 
>   cephuser@fsid.mycephfs2=/path
> 
> Note, there is no "monitor address" in the device string.
> That gets passed in as mount option. This keeps the device
> string same when monitor addresses change (on remounts).
> 
> Also note that the userspace mount helper tool is backward
> compatible. I.e., the mount helper will fallback to using
> old syntax after trying to mount with the new syntax.
> 
> Signed-off-by: Venky Shankar <vshankar@redhat.com>
> ---
>  fs/ceph/super.c | 122 ++++++++++++++++++++++++++++++++++++++++++++----
>  fs/ceph/super.h |   3 ++
>  2 files changed, 115 insertions(+), 10 deletions(-)
> 
> diff --git a/fs/ceph/super.c b/fs/ceph/super.c
> index 9b1b7f4cfdd4..0b324e43c9f4 100644
> --- a/fs/ceph/super.c
> +++ b/fs/ceph/super.c
> @@ -145,6 +145,7 @@ enum {
>  	Opt_mds_namespace,
>  	Opt_recover_session,
>  	Opt_source,
> +	Opt_mon_addr,
>  	/* string args above */
>  	Opt_dirstat,
>  	Opt_rbytes,
> @@ -196,6 +197,7 @@ static const struct fs_parameter_spec ceph_mount_parameters[] = {
>  	fsparam_u32	("rsize",			Opt_rsize),
>  	fsparam_string	("snapdirname",			Opt_snapdirname),
>  	fsparam_string	("source",			Opt_source),
> +	fsparam_string	("mon_addr",			Opt_mon_addr),
>  	fsparam_u32	("wsize",			Opt_wsize),
>  	fsparam_flag_no	("wsync",			Opt_wsync),
>  	{}
> @@ -226,10 +228,70 @@ static void canonicalize_path(char *path)
>  	path[j] = '\0';
>  }
>  
> +static int ceph_parse_old_source(const char *dev_name, const char *dev_name_end,
> +				 struct fs_context *fc)
> +{
> +	int r;
> +	struct ceph_parse_opts_ctx *pctx = fc->fs_private;
> +	struct ceph_mount_options *fsopt = pctx->opts;
> +
> +	if (*dev_name_end != ':')
> +		return invalfc(fc, "separator ':' missing in source");
> +
> +	r = ceph_parse_mon_ips(dev_name, dev_name_end - dev_name,
> +			       pctx->copts, fc->log.log);
> +	if (r)
> +		return r;
> +
> +	fsopt->new_dev_syntax = false;
> +	return 0;
> +}
> +
> +static int ceph_parse_new_source(const char *dev_name, const char *dev_name_end,
> +				 struct fs_context *fc)
> +{
> +	struct ceph_parse_opts_ctx *pctx = fc->fs_private;
> +	struct ceph_mount_options *fsopt = pctx->opts;
> +	char *fsid_start, *fs_name_start;
> +
> +	if (*dev_name_end != '=') {
> +		dout("separator '=' missing in source");
> +		return -EINVAL;
> +	}
> +
> +	fsid_start = strchr(dev_name, '@');
> +	if (!fsid_start)
> +		return invalfc(fc, "missing cluster fsid");
> +	++fsid_start; /* start of cluster fsid */
> +
> +	fs_name_start = strchr(fsid_start, '.');
> +	if (!fs_name_start)
> +		return invalfc(fc, "missing file system name");
> +
> +	++fs_name_start; /* start of file system name */
> +	fsopt->mds_namespace = kstrndup(fs_name_start,
> +					dev_name_end - fs_name_start, GFP_KERNEL);
> +	if (!fsopt->mds_namespace)
> +		return -ENOMEM;
> +	dout("file system (mds namespace) '%s'\n", fsopt->mds_namespace);
> +
> +	fsopt->new_dev_syntax = true;
> +	return 0;
> +}
> +
>  /*
> - * Parse the source parameter.  Distinguish the server list from the path.
> + * Parse the source parameter for new device format. Distinguish the device
> + * spec from the path. Try parsing new device format and fallback to old
> + * format if needed.
>   *
> - * The source will look like:
> + * New device syntax will looks like:
> + *     <device_spec>=/<path>
> + * where
> + *     <device_spec> is name@fsid.fsname
> + *     <path> is optional, but if present must begin with '/'
> + * (monitor addresses are passed via mount option)
> + *
> + * Old device syntax is:
>   *     <server_spec>[,<server_spec>...]:[<path>]
>   * where
>   *     <server_spec> is <ip>[:<port>]
> @@ -262,22 +324,48 @@ static int ceph_parse_source(struct fs_parameter *param, struct fs_context *fc)
>  		dev_name_end = dev_name + strlen(dev_name);
>  	}
>  
> -	dev_name_end--;		/* back up to ':' separator */
> -	if (dev_name_end < dev_name || *dev_name_end != ':')
> -		return invalfc(fc, "No path or : separator in source");
> +	dev_name_end--;		/* back up to separator */
> +	if (dev_name_end < dev_name)
> +		return invalfc(fc, "path missing in source");
>  
>  	dout("device name '%.*s'\n", (int)(dev_name_end - dev_name), dev_name);
>  	if (fsopt->server_path)
>  		dout("server path '%s'\n", fsopt->server_path);
>  
> -	ret = ceph_parse_mon_ips(param->string, dev_name_end - dev_name,
> -				 pctx->copts, fc->log.log);
> +	dout("trying new device syntax");
> +	ret = ceph_parse_new_source(dev_name, dev_name_end, fc);
> +	if (ret == 0)
> +		goto done;
> +
> +	dout("trying old device syntax");
> +	ret = ceph_parse_old_source(dev_name, dev_name_end, fc);
>  	if (ret)
> -		return ret;
> +		goto out;

Do we really need this goto?  My (personal) preference would be to drop
this one and simply return.   And maybe it's even possible to drop the
previous 'goto done' too.

> + done:
>  	fc->source = param->string;
>  	param->string = NULL;
> -	return 0;
> + out:
> +	return ret;
> +}
> +
> +static int ceph_parse_mon_addr(struct fs_parameter *param,
> +			       struct fs_context *fc)
> +{
> +	int r;
> +	struct ceph_parse_opts_ctx *pctx = fc->fs_private;
> +	struct ceph_mount_options *fsopt = pctx->opts;
> +
> +	kfree(fsopt->mon_addr);
> +	fsopt->mon_addr = param->string;
> +	param->string = NULL;
> +
> +	strreplace(fsopt->mon_addr, '/', ',');
> +	r = ceph_parse_mon_ips(fsopt->mon_addr, strlen(fsopt->mon_addr),
> +			       pctx->copts, fc->log.log);
> +        // since its used in ceph_show_options()

(nit: use c-style comments...? yeah, again personal preference :-)

> +	strreplace(fsopt->mon_addr, ',', '/');

This is ugly.  Have you considered modifying ceph_parse_mon_ips() (and
ceph_parse_ips()) to receive a delimiter as a parameter?

> +	return r;
>  }
>  
>  static int ceph_parse_mount_param(struct fs_context *fc,
> @@ -322,6 +410,8 @@ static int ceph_parse_mount_param(struct fs_context *fc,
>  		if (fc->source)
>  			return invalfc(fc, "Multiple sources specified");
>  		return ceph_parse_source(param, fc);
> +	case Opt_mon_addr:
> +		return ceph_parse_mon_addr(param, fc);
>  	case Opt_wsize:
>  		if (result.uint_32 < PAGE_SIZE ||
>  		    result.uint_32 > CEPH_MAX_WRITE_SIZE)
> @@ -473,6 +563,7 @@ static void destroy_mount_options(struct ceph_mount_options *args)
>  	kfree(args->mds_namespace);
>  	kfree(args->server_path);
>  	kfree(args->fscache_uniq);
> +	kfree(args->mon_addr);
>  	kfree(args);
>  }
>  
> @@ -516,6 +607,10 @@ static int compare_mount_options(struct ceph_mount_options *new_fsopt,
>  	if (ret)
>  		return ret;
>  
> +	ret = strcmp_null(fsopt1->mon_addr, fsopt2->mon_addr);
> +	if (ret)
> +		return ret;
> +
>  	return ceph_compare_options(new_opt, fsc->client);
>  }
>  
> @@ -571,9 +666,13 @@ static int ceph_show_options(struct seq_file *m, struct dentry *root)
>  	if ((fsopt->flags & CEPH_MOUNT_OPT_NOCOPYFROM) == 0)
>  		seq_puts(m, ",copyfrom");
>  
> -	if (fsopt->mds_namespace)
> +	/* dump mds_namespace when old device syntax is in use */
> +	if (fsopt->mds_namespace && !fsopt->new_dev_syntax)
>  		seq_show_option(m, "mds_namespace", fsopt->mds_namespace);

I haven't really tested it, but... what happens if we set mds_namespace
*and* we're using the new syntax?  Or, in another words, what should
happen?

Cheers,
--
Luís

>  
> +	if (fsopt->mon_addr)
> +		seq_printf(m, ",mon_addr=%s", fsopt->mon_addr);
> +
>  	if (fsopt->flags & CEPH_MOUNT_OPT_CLEANRECOVER)
>  		seq_show_option(m, "recover_session", "clean");
>  
> @@ -1048,6 +1147,7 @@ static int ceph_setup_bdi(struct super_block *sb, struct ceph_fs_client *fsc)
>  static int ceph_get_tree(struct fs_context *fc)
>  {
>  	struct ceph_parse_opts_ctx *pctx = fc->fs_private;
> +	struct ceph_mount_options *fsopt = pctx->opts;
>  	struct super_block *sb;
>  	struct ceph_fs_client *fsc;
>  	struct dentry *res;
> @@ -1059,6 +1159,8 @@ static int ceph_get_tree(struct fs_context *fc)
>  
>  	if (!fc->source)
>  		return invalfc(fc, "No source");
> +	if (fsopt->new_dev_syntax && !fsopt->mon_addr)
> +		return invalfc(fc, "No monitor address");
>  
>  	/* create client (which we may/may not use) */
>  	fsc = create_fs_client(pctx->opts, pctx->copts);
> diff --git a/fs/ceph/super.h b/fs/ceph/super.h
> index c48bb30c8d70..8f71184b7c85 100644
> --- a/fs/ceph/super.h
> +++ b/fs/ceph/super.h
> @@ -87,6 +87,8 @@ struct ceph_mount_options {
>  	unsigned int max_readdir;       /* max readdir result (entries) */
>  	unsigned int max_readdir_bytes; /* max readdir result (bytes) */
>  
> +	bool new_dev_syntax;
> +
>  	/*
>  	 * everything above this point can be memcmp'd; everything below
>  	 * is handled in compare_mount_options()
> @@ -96,6 +98,7 @@ struct ceph_mount_options {
>  	char *mds_namespace;  /* default NULL */
>  	char *server_path;    /* default NULL (means "/") */
>  	char *fscache_uniq;   /* default NULL */
> +	char *mon_addr;
>  };
>  
>  struct ceph_fs_client {
> -- 
> 2.27.0
> 

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

* Re: [PATCH v2 2/4] ceph: validate cluster FSID for new device syntax
  2021-07-02  6:48 ` [PATCH v2 2/4] ceph: validate cluster FSID for new device syntax Venky Shankar
@ 2021-07-02 10:44   ` Luis Henriques
  2021-07-02 10:48     ` Luis Henriques
  2021-07-02 11:10     ` Venky Shankar
  0 siblings, 2 replies; 20+ messages in thread
From: Luis Henriques @ 2021-07-02 10:44 UTC (permalink / raw)
  To: Venky Shankar; +Cc: jlayton, idryomov, pdonnell, ceph-devel

On Fri, Jul 02, 2021 at 12:18:19PM +0530, Venky Shankar wrote:
> The new device syntax requires the cluster FSID as part
> of the device string. Use this FSID to verify if it matches
> the cluster FSID we get back from the monitor, failing the
> mount on mismatch.
> 
> Also, rename parse_fsid() to ceph_parse_fsid() as it is too
> generic.
> 
> Signed-off-by: Venky Shankar <vshankar@redhat.com>
> ---
>  fs/ceph/super.c              | 9 +++++++++
>  fs/ceph/super.h              | 1 +
>  include/linux/ceph/libceph.h | 1 +
>  net/ceph/ceph_common.c       | 5 +++--
>  4 files changed, 14 insertions(+), 2 deletions(-)
> 
> diff --git a/fs/ceph/super.c b/fs/ceph/super.c
> index 0b324e43c9f4..03e5f4bb2b6f 100644
> --- a/fs/ceph/super.c
> +++ b/fs/ceph/super.c
> @@ -268,6 +268,9 @@ static int ceph_parse_new_source(const char *dev_name, const char *dev_name_end,
>  	if (!fs_name_start)
>  		return invalfc(fc, "missing file system name");
>  
> +	if (ceph_parse_fsid(fsid_start, &fsopt->fsid))
> +		return invalfc(fc, "invalid fsid format");
> +
>  	++fs_name_start; /* start of file system name */
>  	fsopt->mds_namespace = kstrndup(fs_name_start,
>  					dev_name_end - fs_name_start, GFP_KERNEL);
> @@ -750,6 +753,12 @@ static struct ceph_fs_client *create_fs_client(struct ceph_mount_options *fsopt,
>  	}
>  	opt = NULL; /* fsc->client now owns this */
>  
> +	/* help learn fsid */
> +	if (fsopt->new_dev_syntax) {
> +		ceph_check_fsid(fsc->client, &fsopt->fsid);

This call to ceph_check_fsid() made me wonder what would happen if I use
the wrong fsid with the new syntax.  And the result is:

[   41.882334] libceph: mon0 (1)192.168.155.1:40594 session established
[   41.884537] libceph: bad fsid, had d52783e6-efc2-4dce-ad01-aa3272fa5f66 got 90bdb539-9d95-402e-8f23-b0e26cba8b1b
[   41.885955] libceph: bad fsid, had d52783e6-efc2-4dce-ad01-aa3272fa5f66 got 90bdb539-9d95-402e-8f23-b0e26cba8b1b
[   41.889313] libceph: bad fsid, had d52783e6-efc2-4dce-ad01-aa3272fa5f66 got 90bdb539-9d95-402e-8f23-b0e26cba8b1b
[   41.892578] libceph: osdc handle_map corrupt msg

... followed by a msg dump.

I guess this means that manually setting the fsid requires changes to the
messenger (I've only tested with v1) so that it gracefully handles this
scenario.

Cheers,
--
Luís

> +		fsc->client->have_fsid = true;
> +	}
> +
>  	fsc->client->extra_mon_dispatch = extra_mon_dispatch;
>  	ceph_set_opt(fsc->client, ABORT_ON_FULL);
>  
> diff --git a/fs/ceph/super.h b/fs/ceph/super.h
> index 8f71184b7c85..ce5fb90a01a4 100644
> --- a/fs/ceph/super.h
> +++ b/fs/ceph/super.h
> @@ -99,6 +99,7 @@ struct ceph_mount_options {
>  	char *server_path;    /* default NULL (means "/") */
>  	char *fscache_uniq;   /* default NULL */
>  	char *mon_addr;
> +	struct ceph_fsid fsid;
>  };
>  
>  struct ceph_fs_client {
> diff --git a/include/linux/ceph/libceph.h b/include/linux/ceph/libceph.h
> index 409d8c29bc4f..75d059b79d90 100644
> --- a/include/linux/ceph/libceph.h
> +++ b/include/linux/ceph/libceph.h
> @@ -296,6 +296,7 @@ extern bool libceph_compatible(void *data);
>  extern const char *ceph_msg_type_name(int type);
>  extern int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid);
>  extern void *ceph_kvmalloc(size_t size, gfp_t flags);
> +extern int ceph_parse_fsid(const char *str, struct ceph_fsid *fsid);
>  
>  struct fs_parameter;
>  struct fc_log;
> diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c
> index 97d6ea763e32..da480757fcca 100644
> --- a/net/ceph/ceph_common.c
> +++ b/net/ceph/ceph_common.c
> @@ -217,7 +217,7 @@ void *ceph_kvmalloc(size_t size, gfp_t flags)
>  	return p;
>  }
>  
> -static int parse_fsid(const char *str, struct ceph_fsid *fsid)
> +int ceph_parse_fsid(const char *str, struct ceph_fsid *fsid)
>  {
>  	int i = 0;
>  	char tmp[3];
> @@ -247,6 +247,7 @@ static int parse_fsid(const char *str, struct ceph_fsid *fsid)
>  	dout("parse_fsid ret %d got fsid %pU\n", err, fsid);
>  	return err;
>  }
> +EXPORT_SYMBOL(ceph_parse_fsid);
>  
>  /*
>   * ceph options
> @@ -465,7 +466,7 @@ int ceph_parse_param(struct fs_parameter *param, struct ceph_options *opt,
>  		break;
>  
>  	case Opt_fsid:
> -		err = parse_fsid(param->string, &opt->fsid);
> +		err = ceph_parse_fsid(param->string, &opt->fsid);
>  		if (err) {
>  			error_plog(&log, "Failed to parse fsid: %d", err);
>  			return err;
> -- 
> 2.27.0
> 


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

* Re: [PATCH v2 2/4] ceph: validate cluster FSID for new device syntax
  2021-07-02 10:44   ` Luis Henriques
@ 2021-07-02 10:48     ` Luis Henriques
  2021-07-02 11:10     ` Venky Shankar
  1 sibling, 0 replies; 20+ messages in thread
From: Luis Henriques @ 2021-07-02 10:48 UTC (permalink / raw)
  To: Venky Shankar; +Cc: jlayton, idryomov, pdonnell, ceph-devel

On Fri, Jul 02, 2021 at 11:44:05AM +0100, Luis Henriques wrote:
> On Fri, Jul 02, 2021 at 12:18:19PM +0530, Venky Shankar wrote:
> > The new device syntax requires the cluster FSID as part
> > of the device string. Use this FSID to verify if it matches
> > the cluster FSID we get back from the monitor, failing the
> > mount on mismatch.
> > 
> > Also, rename parse_fsid() to ceph_parse_fsid() as it is too
> > generic.
> > 
> > Signed-off-by: Venky Shankar <vshankar@redhat.com>
> > ---
> >  fs/ceph/super.c              | 9 +++++++++
> >  fs/ceph/super.h              | 1 +
> >  include/linux/ceph/libceph.h | 1 +
> >  net/ceph/ceph_common.c       | 5 +++--
> >  4 files changed, 14 insertions(+), 2 deletions(-)
> > 
> > diff --git a/fs/ceph/super.c b/fs/ceph/super.c
> > index 0b324e43c9f4..03e5f4bb2b6f 100644
> > --- a/fs/ceph/super.c
> > +++ b/fs/ceph/super.c
> > @@ -268,6 +268,9 @@ static int ceph_parse_new_source(const char *dev_name, const char *dev_name_end,
> >  	if (!fs_name_start)
> >  		return invalfc(fc, "missing file system name");
> >  
> > +	if (ceph_parse_fsid(fsid_start, &fsopt->fsid))
> > +		return invalfc(fc, "invalid fsid format");
> > +
> >  	++fs_name_start; /* start of file system name */
> >  	fsopt->mds_namespace = kstrndup(fs_name_start,
> >  					dev_name_end - fs_name_start, GFP_KERNEL);
> > @@ -750,6 +753,12 @@ static struct ceph_fs_client *create_fs_client(struct ceph_mount_options *fsopt,
> >  	}
> >  	opt = NULL; /* fsc->client now owns this */
> >  
> > +	/* help learn fsid */
> > +	if (fsopt->new_dev_syntax) {
> > +		ceph_check_fsid(fsc->client, &fsopt->fsid);
> 
> This call to ceph_check_fsid() made me wonder what would happen if I use
> the wrong fsid with the new syntax.  And the result is:
> 
> [   41.882334] libceph: mon0 (1)192.168.155.1:40594 session established
> [   41.884537] libceph: bad fsid, had d52783e6-efc2-4dce-ad01-aa3272fa5f66 got 90bdb539-9d95-402e-8f23-b0e26cba8b1b
> [   41.885955] libceph: bad fsid, had d52783e6-efc2-4dce-ad01-aa3272fa5f66 got 90bdb539-9d95-402e-8f23-b0e26cba8b1b
> [   41.889313] libceph: bad fsid, had d52783e6-efc2-4dce-ad01-aa3272fa5f66 got 90bdb539-9d95-402e-8f23-b0e26cba8b1b
> [   41.892578] libceph: osdc handle_map corrupt msg
> 
> ... followed by a msg dump.
> 
> I guess this means that manually setting the fsid requires changes to the
> messenger (I've only tested with v1) so that it gracefully handles this
> scenario.

I forgot to mention that the above errors are, obviously, not due to this
call to ceph_check_fsid() but rather from calling it from mon_dispatch().

Cheers,
--
Luís

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

* Re: [PATCH v2 1/4] ceph: new device mount syntax
  2021-07-02 10:38   ` Luis Henriques
@ 2021-07-02 11:05     ` Venky Shankar
  2021-07-06 18:41       ` Jeff Layton
  0 siblings, 1 reply; 20+ messages in thread
From: Venky Shankar @ 2021-07-02 11:05 UTC (permalink / raw)
  To: Luis Henriques; +Cc: Jeff Layton, idryomov, Patrick Donnelly, ceph-devel

On Fri, Jul 2, 2021 at 4:08 PM Luis Henriques <lhenriques@suse.de> wrote:
>
> On Fri, Jul 02, 2021 at 12:18:18PM +0530, Venky Shankar wrote:
> > Old mount device syntax (source) has the following problems:
> >
> > - mounts to the same cluster but with different fsnames
> >   and/or creds have identical device string which can
> >   confuse xfstests.
> >
> > - Userspace mount helper tool resolves monitor addresses
> >   and fill in mon addrs automatically, but that means the
> >   device shown in /proc/mounts is different than what was
> >   used for mounting.
> >
> > New device syntax is as follows:
> >
> >   cephuser@fsid.mycephfs2=/path
> >
> > Note, there is no "monitor address" in the device string.
> > That gets passed in as mount option. This keeps the device
> > string same when monitor addresses change (on remounts).
> >
> > Also note that the userspace mount helper tool is backward
> > compatible. I.e., the mount helper will fallback to using
> > old syntax after trying to mount with the new syntax.
> >
> > Signed-off-by: Venky Shankar <vshankar@redhat.com>
> > ---
> >  fs/ceph/super.c | 122 ++++++++++++++++++++++++++++++++++++++++++++----
> >  fs/ceph/super.h |   3 ++
> >  2 files changed, 115 insertions(+), 10 deletions(-)
> >
> > diff --git a/fs/ceph/super.c b/fs/ceph/super.c
> > index 9b1b7f4cfdd4..0b324e43c9f4 100644
> > --- a/fs/ceph/super.c
> > +++ b/fs/ceph/super.c
> > @@ -145,6 +145,7 @@ enum {
> >       Opt_mds_namespace,
> >       Opt_recover_session,
> >       Opt_source,
> > +     Opt_mon_addr,
> >       /* string args above */
> >       Opt_dirstat,
> >       Opt_rbytes,
> > @@ -196,6 +197,7 @@ static const struct fs_parameter_spec ceph_mount_parameters[] = {
> >       fsparam_u32     ("rsize",                       Opt_rsize),
> >       fsparam_string  ("snapdirname",                 Opt_snapdirname),
> >       fsparam_string  ("source",                      Opt_source),
> > +     fsparam_string  ("mon_addr",                    Opt_mon_addr),
> >       fsparam_u32     ("wsize",                       Opt_wsize),
> >       fsparam_flag_no ("wsync",                       Opt_wsync),
> >       {}
> > @@ -226,10 +228,70 @@ static void canonicalize_path(char *path)
> >       path[j] = '\0';
> >  }
> >
> > +static int ceph_parse_old_source(const char *dev_name, const char *dev_name_end,
> > +                              struct fs_context *fc)
> > +{
> > +     int r;
> > +     struct ceph_parse_opts_ctx *pctx = fc->fs_private;
> > +     struct ceph_mount_options *fsopt = pctx->opts;
> > +
> > +     if (*dev_name_end != ':')
> > +             return invalfc(fc, "separator ':' missing in source");
> > +
> > +     r = ceph_parse_mon_ips(dev_name, dev_name_end - dev_name,
> > +                            pctx->copts, fc->log.log);
> > +     if (r)
> > +             return r;
> > +
> > +     fsopt->new_dev_syntax = false;
> > +     return 0;
> > +}
> > +
> > +static int ceph_parse_new_source(const char *dev_name, const char *dev_name_end,
> > +                              struct fs_context *fc)
> > +{
> > +     struct ceph_parse_opts_ctx *pctx = fc->fs_private;
> > +     struct ceph_mount_options *fsopt = pctx->opts;
> > +     char *fsid_start, *fs_name_start;
> > +
> > +     if (*dev_name_end != '=') {
> > +             dout("separator '=' missing in source");
> > +             return -EINVAL;
> > +     }
> > +
> > +     fsid_start = strchr(dev_name, '@');
> > +     if (!fsid_start)
> > +             return invalfc(fc, "missing cluster fsid");
> > +     ++fsid_start; /* start of cluster fsid */
> > +
> > +     fs_name_start = strchr(fsid_start, '.');
> > +     if (!fs_name_start)
> > +             return invalfc(fc, "missing file system name");
> > +
> > +     ++fs_name_start; /* start of file system name */
> > +     fsopt->mds_namespace = kstrndup(fs_name_start,
> > +                                     dev_name_end - fs_name_start, GFP_KERNEL);
> > +     if (!fsopt->mds_namespace)
> > +             return -ENOMEM;
> > +     dout("file system (mds namespace) '%s'\n", fsopt->mds_namespace);
> > +
> > +     fsopt->new_dev_syntax = true;
> > +     return 0;
> > +}
> > +
> >  /*
> > - * Parse the source parameter.  Distinguish the server list from the path.
> > + * Parse the source parameter for new device format. Distinguish the device
> > + * spec from the path. Try parsing new device format and fallback to old
> > + * format if needed.
> >   *
> > - * The source will look like:
> > + * New device syntax will looks like:
> > + *     <device_spec>=/<path>
> > + * where
> > + *     <device_spec> is name@fsid.fsname
> > + *     <path> is optional, but if present must begin with '/'
> > + * (monitor addresses are passed via mount option)
> > + *
> > + * Old device syntax is:
> >   *     <server_spec>[,<server_spec>...]:[<path>]
> >   * where
> >   *     <server_spec> is <ip>[:<port>]
> > @@ -262,22 +324,48 @@ static int ceph_parse_source(struct fs_parameter *param, struct fs_context *fc)
> >               dev_name_end = dev_name + strlen(dev_name);
> >       }
> >
> > -     dev_name_end--;         /* back up to ':' separator */
> > -     if (dev_name_end < dev_name || *dev_name_end != ':')
> > -             return invalfc(fc, "No path or : separator in source");
> > +     dev_name_end--;         /* back up to separator */
> > +     if (dev_name_end < dev_name)
> > +             return invalfc(fc, "path missing in source");
> >
> >       dout("device name '%.*s'\n", (int)(dev_name_end - dev_name), dev_name);
> >       if (fsopt->server_path)
> >               dout("server path '%s'\n", fsopt->server_path);
> >
> > -     ret = ceph_parse_mon_ips(param->string, dev_name_end - dev_name,
> > -                              pctx->copts, fc->log.log);
> > +     dout("trying new device syntax");
> > +     ret = ceph_parse_new_source(dev_name, dev_name_end, fc);
> > +     if (ret == 0)
> > +             goto done;
> > +
> > +     dout("trying old device syntax");
> > +     ret = ceph_parse_old_source(dev_name, dev_name_end, fc);
> >       if (ret)
> > -             return ret;
> > +             goto out;
>
> Do we really need this goto?  My (personal) preference would be to drop
> this one and simply return.   And maybe it's even possible to drop the
> previous 'goto done' too.

Sure. Just a preference I had.

>
> > + done:
> >       fc->source = param->string;
> >       param->string = NULL;
> > -     return 0;
> > + out:
> > +     return ret;
> > +}
> > +
> > +static int ceph_parse_mon_addr(struct fs_parameter *param,
> > +                            struct fs_context *fc)
> > +{
> > +     int r;
> > +     struct ceph_parse_opts_ctx *pctx = fc->fs_private;
> > +     struct ceph_mount_options *fsopt = pctx->opts;
> > +
> > +     kfree(fsopt->mon_addr);
> > +     fsopt->mon_addr = param->string;
> > +     param->string = NULL;
> > +
> > +     strreplace(fsopt->mon_addr, '/', ',');
> > +     r = ceph_parse_mon_ips(fsopt->mon_addr, strlen(fsopt->mon_addr),
> > +                            pctx->copts, fc->log.log);
> > +        // since its used in ceph_show_options()
>
> (nit: use c-style comments...? yeah, again personal preference :-)
>
> > +     strreplace(fsopt->mon_addr, ',', '/');
>
> This is ugly.  Have you considered modifying ceph_parse_mon_ips() (and
> ceph_parse_ips()) to receive a delimiter as a parameter?''

I did. However, for most cases (all possibly), "," is the addr
delimiter. So, I didn't take the approach to make these helpers really
generic for parsing addrs.

>
> > +     return r;
> >  }
> >
> >  static int ceph_parse_mount_param(struct fs_context *fc,
> > @@ -322,6 +410,8 @@ static int ceph_parse_mount_param(struct fs_context *fc,
> >               if (fc->source)
> >                       return invalfc(fc, "Multiple sources specified");
> >               return ceph_parse_source(param, fc);
> > +     case Opt_mon_addr:
> > +             return ceph_parse_mon_addr(param, fc);
> >       case Opt_wsize:
> >               if (result.uint_32 < PAGE_SIZE ||
> >                   result.uint_32 > CEPH_MAX_WRITE_SIZE)
> > @@ -473,6 +563,7 @@ static void destroy_mount_options(struct ceph_mount_options *args)
> >       kfree(args->mds_namespace);
> >       kfree(args->server_path);
> >       kfree(args->fscache_uniq);
> > +     kfree(args->mon_addr);
> >       kfree(args);
> >  }
> >
> > @@ -516,6 +607,10 @@ static int compare_mount_options(struct ceph_mount_options *new_fsopt,
> >       if (ret)
> >               return ret;
> >
> > +     ret = strcmp_null(fsopt1->mon_addr, fsopt2->mon_addr);
> > +     if (ret)
> > +             return ret;
> > +
> >       return ceph_compare_options(new_opt, fsc->client);
> >  }
> >
> > @@ -571,9 +666,13 @@ static int ceph_show_options(struct seq_file *m, struct dentry *root)
> >       if ((fsopt->flags & CEPH_MOUNT_OPT_NOCOPYFROM) == 0)
> >               seq_puts(m, ",copyfrom");
> >
> > -     if (fsopt->mds_namespace)
> > +     /* dump mds_namespace when old device syntax is in use */
> > +     if (fsopt->mds_namespace && !fsopt->new_dev_syntax)
> >               seq_show_option(m, "mds_namespace", fsopt->mds_namespace);
>
> I haven't really tested it, but... what happens if we set mds_namespace
> *and* we're using the new syntax?  Or, in another words, what should
> happen?

Depends on the order of token parsing in ceph_parse_mount_param()
which mds_namespace gets used.

(however, that means ceph_parse_new_source() should additionally
kfree(fsopt->mds_namespace)).

>
> Cheers,
> --
> Luís
>
> >
> > +     if (fsopt->mon_addr)
> > +             seq_printf(m, ",mon_addr=%s", fsopt->mon_addr);
> > +
> >       if (fsopt->flags & CEPH_MOUNT_OPT_CLEANRECOVER)
> >               seq_show_option(m, "recover_session", "clean");
> >
> > @@ -1048,6 +1147,7 @@ static int ceph_setup_bdi(struct super_block *sb, struct ceph_fs_client *fsc)
> >  static int ceph_get_tree(struct fs_context *fc)
> >  {
> >       struct ceph_parse_opts_ctx *pctx = fc->fs_private;
> > +     struct ceph_mount_options *fsopt = pctx->opts;
> >       struct super_block *sb;
> >       struct ceph_fs_client *fsc;
> >       struct dentry *res;
> > @@ -1059,6 +1159,8 @@ static int ceph_get_tree(struct fs_context *fc)
> >
> >       if (!fc->source)
> >               return invalfc(fc, "No source");
> > +     if (fsopt->new_dev_syntax && !fsopt->mon_addr)
> > +             return invalfc(fc, "No monitor address");
> >
> >       /* create client (which we may/may not use) */
> >       fsc = create_fs_client(pctx->opts, pctx->copts);
> > diff --git a/fs/ceph/super.h b/fs/ceph/super.h
> > index c48bb30c8d70..8f71184b7c85 100644
> > --- a/fs/ceph/super.h
> > +++ b/fs/ceph/super.h
> > @@ -87,6 +87,8 @@ struct ceph_mount_options {
> >       unsigned int max_readdir;       /* max readdir result (entries) */
> >       unsigned int max_readdir_bytes; /* max readdir result (bytes) */
> >
> > +     bool new_dev_syntax;
> > +
> >       /*
> >        * everything above this point can be memcmp'd; everything below
> >        * is handled in compare_mount_options()
> > @@ -96,6 +98,7 @@ struct ceph_mount_options {
> >       char *mds_namespace;  /* default NULL */
> >       char *server_path;    /* default NULL (means "/") */
> >       char *fscache_uniq;   /* default NULL */
> > +     char *mon_addr;
> >  };
> >
> >  struct ceph_fs_client {
> > --
> > 2.27.0
> >
>


-- 
Cheers,
Venky


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

* Re: [PATCH v2 2/4] ceph: validate cluster FSID for new device syntax
  2021-07-02 10:44   ` Luis Henriques
  2021-07-02 10:48     ` Luis Henriques
@ 2021-07-02 11:10     ` Venky Shankar
  2021-07-02 13:49       ` Luis Henriques
  1 sibling, 1 reply; 20+ messages in thread
From: Venky Shankar @ 2021-07-02 11:10 UTC (permalink / raw)
  To: Luis Henriques; +Cc: Jeff Layton, idryomov, Patrick Donnelly, ceph-devel

On Fri, Jul 2, 2021 at 4:14 PM Luis Henriques <lhenriques@suse.de> wrote:
>
> On Fri, Jul 02, 2021 at 12:18:19PM +0530, Venky Shankar wrote:
> > The new device syntax requires the cluster FSID as part
> > of the device string. Use this FSID to verify if it matches
> > the cluster FSID we get back from the monitor, failing the
> > mount on mismatch.
> >
> > Also, rename parse_fsid() to ceph_parse_fsid() as it is too
> > generic.
> >
> > Signed-off-by: Venky Shankar <vshankar@redhat.com>
> > ---
> >  fs/ceph/super.c              | 9 +++++++++
> >  fs/ceph/super.h              | 1 +
> >  include/linux/ceph/libceph.h | 1 +
> >  net/ceph/ceph_common.c       | 5 +++--
> >  4 files changed, 14 insertions(+), 2 deletions(-)
> >
> > diff --git a/fs/ceph/super.c b/fs/ceph/super.c
> > index 0b324e43c9f4..03e5f4bb2b6f 100644
> > --- a/fs/ceph/super.c
> > +++ b/fs/ceph/super.c
> > @@ -268,6 +268,9 @@ static int ceph_parse_new_source(const char *dev_name, const char *dev_name_end,
> >       if (!fs_name_start)
> >               return invalfc(fc, "missing file system name");
> >
> > +     if (ceph_parse_fsid(fsid_start, &fsopt->fsid))
> > +             return invalfc(fc, "invalid fsid format");
> > +
> >       ++fs_name_start; /* start of file system name */
> >       fsopt->mds_namespace = kstrndup(fs_name_start,
> >                                       dev_name_end - fs_name_start, GFP_KERNEL);
> > @@ -750,6 +753,12 @@ static struct ceph_fs_client *create_fs_client(struct ceph_mount_options *fsopt,
> >       }
> >       opt = NULL; /* fsc->client now owns this */
> >
> > +     /* help learn fsid */
> > +     if (fsopt->new_dev_syntax) {
> > +             ceph_check_fsid(fsc->client, &fsopt->fsid);
>
> This call to ceph_check_fsid() made me wonder what would happen if I use
> the wrong fsid with the new syntax.  And the result is:
>
> [   41.882334] libceph: mon0 (1)192.168.155.1:40594 session established
> [   41.884537] libceph: bad fsid, had d52783e6-efc2-4dce-ad01-aa3272fa5f66 got 90bdb539-9d95-402e-8f23-b0e26cba8b1b
> [   41.885955] libceph: bad fsid, had d52783e6-efc2-4dce-ad01-aa3272fa5f66 got 90bdb539-9d95-402e-8f23-b0e26cba8b1b
> [   41.889313] libceph: bad fsid, had d52783e6-efc2-4dce-ad01-aa3272fa5f66 got 90bdb539-9d95-402e-8f23-b0e26cba8b1b
> [   41.892578] libceph: osdc handle_map corrupt msg
>
> ... followed by a msg dump.
>
> I guess this means that manually setting the fsid requires changes to the
> messenger (I've only tested with v1) so that it gracefully handles this
> scenario.

Yes, this results in a big dump of messages. I haven't looked at
gracefully handling these.

I'm not sure if it needs to be done in these set of patches though.

>
> Cheers,
> --
> Luís
>
> > +             fsc->client->have_fsid = true;
> > +     }
> > +
> >       fsc->client->extra_mon_dispatch = extra_mon_dispatch;
> >       ceph_set_opt(fsc->client, ABORT_ON_FULL);
> >
> > diff --git a/fs/ceph/super.h b/fs/ceph/super.h
> > index 8f71184b7c85..ce5fb90a01a4 100644
> > --- a/fs/ceph/super.h
> > +++ b/fs/ceph/super.h
> > @@ -99,6 +99,7 @@ struct ceph_mount_options {
> >       char *server_path;    /* default NULL (means "/") */
> >       char *fscache_uniq;   /* default NULL */
> >       char *mon_addr;
> > +     struct ceph_fsid fsid;
> >  };
> >
> >  struct ceph_fs_client {
> > diff --git a/include/linux/ceph/libceph.h b/include/linux/ceph/libceph.h
> > index 409d8c29bc4f..75d059b79d90 100644
> > --- a/include/linux/ceph/libceph.h
> > +++ b/include/linux/ceph/libceph.h
> > @@ -296,6 +296,7 @@ extern bool libceph_compatible(void *data);
> >  extern const char *ceph_msg_type_name(int type);
> >  extern int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid);
> >  extern void *ceph_kvmalloc(size_t size, gfp_t flags);
> > +extern int ceph_parse_fsid(const char *str, struct ceph_fsid *fsid);
> >
> >  struct fs_parameter;
> >  struct fc_log;
> > diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c
> > index 97d6ea763e32..da480757fcca 100644
> > --- a/net/ceph/ceph_common.c
> > +++ b/net/ceph/ceph_common.c
> > @@ -217,7 +217,7 @@ void *ceph_kvmalloc(size_t size, gfp_t flags)
> >       return p;
> >  }
> >
> > -static int parse_fsid(const char *str, struct ceph_fsid *fsid)
> > +int ceph_parse_fsid(const char *str, struct ceph_fsid *fsid)
> >  {
> >       int i = 0;
> >       char tmp[3];
> > @@ -247,6 +247,7 @@ static int parse_fsid(const char *str, struct ceph_fsid *fsid)
> >       dout("parse_fsid ret %d got fsid %pU\n", err, fsid);
> >       return err;
> >  }
> > +EXPORT_SYMBOL(ceph_parse_fsid);
> >
> >  /*
> >   * ceph options
> > @@ -465,7 +466,7 @@ int ceph_parse_param(struct fs_parameter *param, struct ceph_options *opt,
> >               break;
> >
> >       case Opt_fsid:
> > -             err = parse_fsid(param->string, &opt->fsid);
> > +             err = ceph_parse_fsid(param->string, &opt->fsid);
> >               if (err) {
> >                       error_plog(&log, "Failed to parse fsid: %d", err);
> >                       return err;
> > --
> > 2.27.0
> >
>


-- 
Cheers,
Venky


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

* Re: [PATCH v2 2/4] ceph: validate cluster FSID for new device syntax
  2021-07-02 11:10     ` Venky Shankar
@ 2021-07-02 13:49       ` Luis Henriques
  2021-07-02 14:57         ` Venky Shankar
  0 siblings, 1 reply; 20+ messages in thread
From: Luis Henriques @ 2021-07-02 13:49 UTC (permalink / raw)
  To: Venky Shankar; +Cc: Jeff Layton, idryomov, Patrick Donnelly, ceph-devel

On Fri, Jul 02, 2021 at 04:40:18PM +0530, Venky Shankar wrote:
> On Fri, Jul 2, 2021 at 4:14 PM Luis Henriques <lhenriques@suse.de> wrote:
> >
> > On Fri, Jul 02, 2021 at 12:18:19PM +0530, Venky Shankar wrote:
> > > The new device syntax requires the cluster FSID as part
> > > of the device string. Use this FSID to verify if it matches
> > > the cluster FSID we get back from the monitor, failing the
> > > mount on mismatch.
> > >
> > > Also, rename parse_fsid() to ceph_parse_fsid() as it is too
> > > generic.
> > >
> > > Signed-off-by: Venky Shankar <vshankar@redhat.com>
> > > ---
> > >  fs/ceph/super.c              | 9 +++++++++
> > >  fs/ceph/super.h              | 1 +
> > >  include/linux/ceph/libceph.h | 1 +
> > >  net/ceph/ceph_common.c       | 5 +++--
> > >  4 files changed, 14 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/fs/ceph/super.c b/fs/ceph/super.c
> > > index 0b324e43c9f4..03e5f4bb2b6f 100644
> > > --- a/fs/ceph/super.c
> > > +++ b/fs/ceph/super.c
> > > @@ -268,6 +268,9 @@ static int ceph_parse_new_source(const char *dev_name, const char *dev_name_end,
> > >       if (!fs_name_start)
> > >               return invalfc(fc, "missing file system name");
> > >
> > > +     if (ceph_parse_fsid(fsid_start, &fsopt->fsid))
> > > +             return invalfc(fc, "invalid fsid format");
> > > +
> > >       ++fs_name_start; /* start of file system name */
> > >       fsopt->mds_namespace = kstrndup(fs_name_start,
> > >                                       dev_name_end - fs_name_start, GFP_KERNEL);
> > > @@ -750,6 +753,12 @@ static struct ceph_fs_client *create_fs_client(struct ceph_mount_options *fsopt,
> > >       }
> > >       opt = NULL; /* fsc->client now owns this */
> > >
> > > +     /* help learn fsid */
> > > +     if (fsopt->new_dev_syntax) {
> > > +             ceph_check_fsid(fsc->client, &fsopt->fsid);
> >
> > This call to ceph_check_fsid() made me wonder what would happen if I use
> > the wrong fsid with the new syntax.  And the result is:
> >
> > [   41.882334] libceph: mon0 (1)192.168.155.1:40594 session established
> > [   41.884537] libceph: bad fsid, had d52783e6-efc2-4dce-ad01-aa3272fa5f66 got 90bdb539-9d95-402e-8f23-b0e26cba8b1b
> > [   41.885955] libceph: bad fsid, had d52783e6-efc2-4dce-ad01-aa3272fa5f66 got 90bdb539-9d95-402e-8f23-b0e26cba8b1b
> > [   41.889313] libceph: bad fsid, had d52783e6-efc2-4dce-ad01-aa3272fa5f66 got 90bdb539-9d95-402e-8f23-b0e26cba8b1b
> > [   41.892578] libceph: osdc handle_map corrupt msg
> >
> > ... followed by a msg dump.
> >
> > I guess this means that manually setting the fsid requires changes to the
> > messenger (I've only tested with v1) so that it gracefully handles this
> > scenario.
> 
> Yes, this results in a big dump of messages. I haven't looked at
> gracefully handling these.
> 
> I'm not sure if it needs to be done in these set of patches though.

Ah, sure!  I didn't meant you'd need to change the messenger to handle it
(as I'm not even sure it's the messenger or the mons client that require
changes).  But I also don't think that this patchset can be merged without
making sure we can handle a bad fsid correctly and without all this noise.

Cheers,
--
Luís

> 
> >
> > Cheers,
> > --
> > Luís
> >
> > > +             fsc->client->have_fsid = true;
> > > +     }
> > > +
> > >       fsc->client->extra_mon_dispatch = extra_mon_dispatch;
> > >       ceph_set_opt(fsc->client, ABORT_ON_FULL);
> > >
> > > diff --git a/fs/ceph/super.h b/fs/ceph/super.h
> > > index 8f71184b7c85..ce5fb90a01a4 100644
> > > --- a/fs/ceph/super.h
> > > +++ b/fs/ceph/super.h
> > > @@ -99,6 +99,7 @@ struct ceph_mount_options {
> > >       char *server_path;    /* default NULL (means "/") */
> > >       char *fscache_uniq;   /* default NULL */
> > >       char *mon_addr;
> > > +     struct ceph_fsid fsid;
> > >  };
> > >
> > >  struct ceph_fs_client {
> > > diff --git a/include/linux/ceph/libceph.h b/include/linux/ceph/libceph.h
> > > index 409d8c29bc4f..75d059b79d90 100644
> > > --- a/include/linux/ceph/libceph.h
> > > +++ b/include/linux/ceph/libceph.h
> > > @@ -296,6 +296,7 @@ extern bool libceph_compatible(void *data);
> > >  extern const char *ceph_msg_type_name(int type);
> > >  extern int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid);
> > >  extern void *ceph_kvmalloc(size_t size, gfp_t flags);
> > > +extern int ceph_parse_fsid(const char *str, struct ceph_fsid *fsid);
> > >
> > >  struct fs_parameter;
> > >  struct fc_log;
> > > diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c
> > > index 97d6ea763e32..da480757fcca 100644
> > > --- a/net/ceph/ceph_common.c
> > > +++ b/net/ceph/ceph_common.c
> > > @@ -217,7 +217,7 @@ void *ceph_kvmalloc(size_t size, gfp_t flags)
> > >       return p;
> > >  }
> > >
> > > -static int parse_fsid(const char *str, struct ceph_fsid *fsid)
> > > +int ceph_parse_fsid(const char *str, struct ceph_fsid *fsid)
> > >  {
> > >       int i = 0;
> > >       char tmp[3];
> > > @@ -247,6 +247,7 @@ static int parse_fsid(const char *str, struct ceph_fsid *fsid)
> > >       dout("parse_fsid ret %d got fsid %pU\n", err, fsid);
> > >       return err;
> > >  }
> > > +EXPORT_SYMBOL(ceph_parse_fsid);
> > >
> > >  /*
> > >   * ceph options
> > > @@ -465,7 +466,7 @@ int ceph_parse_param(struct fs_parameter *param, struct ceph_options *opt,
> > >               break;
> > >
> > >       case Opt_fsid:
> > > -             err = parse_fsid(param->string, &opt->fsid);
> > > +             err = ceph_parse_fsid(param->string, &opt->fsid);
> > >               if (err) {
> > >                       error_plog(&log, "Failed to parse fsid: %d", err);
> > >                       return err;
> > > --
> > > 2.27.0
> > >
> >
> 
> 
> -- 
> Cheers,
> Venky
> 

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

* Re: [PATCH v2 2/4] ceph: validate cluster FSID for new device syntax
  2021-07-02 13:49       ` Luis Henriques
@ 2021-07-02 14:57         ` Venky Shankar
  2021-07-06 18:35           ` Jeff Layton
  0 siblings, 1 reply; 20+ messages in thread
From: Venky Shankar @ 2021-07-02 14:57 UTC (permalink / raw)
  To: Luis Henriques; +Cc: Jeff Layton, idryomov, Patrick Donnelly, ceph-devel

On Fri, Jul 2, 2021 at 7:20 PM Luis Henriques <lhenriques@suse.de> wrote:
>
> On Fri, Jul 02, 2021 at 04:40:18PM +0530, Venky Shankar wrote:
> > On Fri, Jul 2, 2021 at 4:14 PM Luis Henriques <lhenriques@suse.de> wrote:
> > >
> > > On Fri, Jul 02, 2021 at 12:18:19PM +0530, Venky Shankar wrote:
> > > > The new device syntax requires the cluster FSID as part
> > > > of the device string. Use this FSID to verify if it matches
> > > > the cluster FSID we get back from the monitor, failing the
> > > > mount on mismatch.
> > > >
> > > > Also, rename parse_fsid() to ceph_parse_fsid() as it is too
> > > > generic.
> > > >
> > > > Signed-off-by: Venky Shankar <vshankar@redhat.com>
> > > > ---
> > > >  fs/ceph/super.c              | 9 +++++++++
> > > >  fs/ceph/super.h              | 1 +
> > > >  include/linux/ceph/libceph.h | 1 +
> > > >  net/ceph/ceph_common.c       | 5 +++--
> > > >  4 files changed, 14 insertions(+), 2 deletions(-)
> > > >
> > > > diff --git a/fs/ceph/super.c b/fs/ceph/super.c
> > > > index 0b324e43c9f4..03e5f4bb2b6f 100644
> > > > --- a/fs/ceph/super.c
> > > > +++ b/fs/ceph/super.c
> > > > @@ -268,6 +268,9 @@ static int ceph_parse_new_source(const char *dev_name, const char *dev_name_end,
> > > >       if (!fs_name_start)
> > > >               return invalfc(fc, "missing file system name");
> > > >
> > > > +     if (ceph_parse_fsid(fsid_start, &fsopt->fsid))
> > > > +             return invalfc(fc, "invalid fsid format");
> > > > +
> > > >       ++fs_name_start; /* start of file system name */
> > > >       fsopt->mds_namespace = kstrndup(fs_name_start,
> > > >                                       dev_name_end - fs_name_start, GFP_KERNEL);
> > > > @@ -750,6 +753,12 @@ static struct ceph_fs_client *create_fs_client(struct ceph_mount_options *fsopt,
> > > >       }
> > > >       opt = NULL; /* fsc->client now owns this */
> > > >
> > > > +     /* help learn fsid */
> > > > +     if (fsopt->new_dev_syntax) {
> > > > +             ceph_check_fsid(fsc->client, &fsopt->fsid);
> > >
> > > This call to ceph_check_fsid() made me wonder what would happen if I use
> > > the wrong fsid with the new syntax.  And the result is:
> > >
> > > [   41.882334] libceph: mon0 (1)192.168.155.1:40594 session established
> > > [   41.884537] libceph: bad fsid, had d52783e6-efc2-4dce-ad01-aa3272fa5f66 got 90bdb539-9d95-402e-8f23-b0e26cba8b1b
> > > [   41.885955] libceph: bad fsid, had d52783e6-efc2-4dce-ad01-aa3272fa5f66 got 90bdb539-9d95-402e-8f23-b0e26cba8b1b
> > > [   41.889313] libceph: bad fsid, had d52783e6-efc2-4dce-ad01-aa3272fa5f66 got 90bdb539-9d95-402e-8f23-b0e26cba8b1b
> > > [   41.892578] libceph: osdc handle_map corrupt msg
> > >
> > > ... followed by a msg dump.
> > >
> > > I guess this means that manually setting the fsid requires changes to the
> > > messenger (I've only tested with v1) so that it gracefully handles this
> > > scenario.
> >
> > Yes, this results in a big dump of messages. I haven't looked at
> > gracefully handling these.
> >
> > I'm not sure if it needs to be done in these set of patches though.
>
> Ah, sure!  I didn't meant you'd need to change the messenger to handle it
> (as I'm not even sure it's the messenger or the mons client that require
> changes).  But I also don't think that this patchset can be merged without
> making sure we can handle a bad fsid correctly and without all this noise.

True. However, for most cases users really won't be filling in the
fsid and the mount helper would fill the "correct" one automatically.

>
> Cheers,
> --
> Luís
>
> >
> > >
> > > Cheers,
> > > --
> > > Luís
> > >
> > > > +             fsc->client->have_fsid = true;
> > > > +     }
> > > > +
> > > >       fsc->client->extra_mon_dispatch = extra_mon_dispatch;
> > > >       ceph_set_opt(fsc->client, ABORT_ON_FULL);
> > > >
> > > > diff --git a/fs/ceph/super.h b/fs/ceph/super.h
> > > > index 8f71184b7c85..ce5fb90a01a4 100644
> > > > --- a/fs/ceph/super.h
> > > > +++ b/fs/ceph/super.h
> > > > @@ -99,6 +99,7 @@ struct ceph_mount_options {
> > > >       char *server_path;    /* default NULL (means "/") */
> > > >       char *fscache_uniq;   /* default NULL */
> > > >       char *mon_addr;
> > > > +     struct ceph_fsid fsid;
> > > >  };
> > > >
> > > >  struct ceph_fs_client {
> > > > diff --git a/include/linux/ceph/libceph.h b/include/linux/ceph/libceph.h
> > > > index 409d8c29bc4f..75d059b79d90 100644
> > > > --- a/include/linux/ceph/libceph.h
> > > > +++ b/include/linux/ceph/libceph.h
> > > > @@ -296,6 +296,7 @@ extern bool libceph_compatible(void *data);
> > > >  extern const char *ceph_msg_type_name(int type);
> > > >  extern int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid);
> > > >  extern void *ceph_kvmalloc(size_t size, gfp_t flags);
> > > > +extern int ceph_parse_fsid(const char *str, struct ceph_fsid *fsid);
> > > >
> > > >  struct fs_parameter;
> > > >  struct fc_log;
> > > > diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c
> > > > index 97d6ea763e32..da480757fcca 100644
> > > > --- a/net/ceph/ceph_common.c
> > > > +++ b/net/ceph/ceph_common.c
> > > > @@ -217,7 +217,7 @@ void *ceph_kvmalloc(size_t size, gfp_t flags)
> > > >       return p;
> > > >  }
> > > >
> > > > -static int parse_fsid(const char *str, struct ceph_fsid *fsid)
> > > > +int ceph_parse_fsid(const char *str, struct ceph_fsid *fsid)
> > > >  {
> > > >       int i = 0;
> > > >       char tmp[3];
> > > > @@ -247,6 +247,7 @@ static int parse_fsid(const char *str, struct ceph_fsid *fsid)
> > > >       dout("parse_fsid ret %d got fsid %pU\n", err, fsid);
> > > >       return err;
> > > >  }
> > > > +EXPORT_SYMBOL(ceph_parse_fsid);
> > > >
> > > >  /*
> > > >   * ceph options
> > > > @@ -465,7 +466,7 @@ int ceph_parse_param(struct fs_parameter *param, struct ceph_options *opt,
> > > >               break;
> > > >
> > > >       case Opt_fsid:
> > > > -             err = parse_fsid(param->string, &opt->fsid);
> > > > +             err = ceph_parse_fsid(param->string, &opt->fsid);
> > > >               if (err) {
> > > >                       error_plog(&log, "Failed to parse fsid: %d", err);
> > > >                       return err;
> > > > --
> > > > 2.27.0
> > > >
> > >
> >
> >
> > --
> > Cheers,
> > Venky
> >
>


-- 
Cheers,
Venky


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

* Re: [PATCH v2 0/4] ceph: new mount device syntax
  2021-07-02  6:48 [PATCH v2 0/4] ceph: new mount device syntax Venky Shankar
                   ` (3 preceding siblings ...)
  2021-07-02  6:48 ` [PATCH v2 4/4] doc: document new CephFS mount device syntax Venky Shankar
@ 2021-07-02 18:05 ` Patrick Donnelly
  2021-07-05  4:36   ` Venky Shankar
  4 siblings, 1 reply; 20+ messages in thread
From: Patrick Donnelly @ 2021-07-02 18:05 UTC (permalink / raw)
  To: Venky Shankar; +Cc: Jeff Layton, Ilya Dryomov, lhenriques, Ceph Development

On Thu, Jul 1, 2021 at 11:48 PM Venky Shankar <vshankar@redhat.com> wrote:
> Also note that the userspace mount helper tool is backward
> compatible. I.e., the mount helper will fallback to using
> old syntax after trying to mount with the new syntax.

The kernel is also backwards compatible too, right?

-- 
Patrick Donnelly, Ph.D.
He / Him / His
Principal Software Engineer
Red Hat Sunnyvale, CA
GPG: 19F28A586F808C2402351B93C3301A3E258DD79D


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

* Re: [PATCH v2 4/4] doc: document new CephFS mount device syntax
  2021-07-02  6:48 ` [PATCH v2 4/4] doc: document new CephFS mount device syntax Venky Shankar
@ 2021-07-02 18:08   ` Patrick Donnelly
  2021-07-05  4:39     ` Venky Shankar
  0 siblings, 1 reply; 20+ messages in thread
From: Patrick Donnelly @ 2021-07-02 18:08 UTC (permalink / raw)
  To: Venky Shankar; +Cc: Jeff Layton, Ilya Dryomov, lhenriques, Ceph Development

On Thu, Jul 1, 2021 at 11:48 PM Venky Shankar <vshankar@redhat.com> wrote:
>
> Signed-off-by: Venky Shankar <vshankar@redhat.com>
> ---
>  Documentation/filesystems/ceph.rst | 25 ++++++++++++++++++++++---
>  1 file changed, 22 insertions(+), 3 deletions(-)
>
> diff --git a/Documentation/filesystems/ceph.rst b/Documentation/filesystems/ceph.rst
> index 7d2ef4e27273..830ea8969d9d 100644
> --- a/Documentation/filesystems/ceph.rst
> +++ b/Documentation/filesystems/ceph.rst
> @@ -82,7 +82,7 @@ Mount Syntax
>
>  The basic mount syntax is::
>
> - # mount -t ceph monip[:port][,monip2[:port]...]:/[subdir] mnt
> + # mount -t ceph user@fsid.fs_name=/[subdir] mnt -o mon_addr=monip1[:port][/monip2[:port]]

Somewhat unrelated question to this patchset: can you specify the mons
in the ceph.conf format? i.e. with v2/v1 syntax?

>  You only need to specify a single monitor, as the client will get the
>  full list when it connects.  (However, if the monitor you specify
> @@ -90,16 +90,35 @@ happens to be down, the mount won't succeed.)  The port can be left
>  off if the monitor is using the default.  So if the monitor is at
>  1.2.3.4::
>
> - # mount -t ceph 1.2.3.4:/ /mnt/ceph
> + # mount -t ceph cephuser@07fe3187-00d9-42a3-814b-72a4d5e7d5be.cephfs=/ /mnt/ceph -o mon_addr=1.2.3.4
>
>  is sufficient.  If /sbin/mount.ceph is installed, a hostname can be
> -used instead of an IP address.
> +used instead of an IP address and the cluster FSID can be left out
> +(as the mount helper will fill it in by reading the ceph configuration
> +file)::
>
> +  # mount -t ceph cephuser@cephfs=/ /mnt/ceph -o mon_addr=mon-addr
>
> +Multiple monitor addresses can be passed by separating each address with a slash (`/`)::
> +
> +  # mount -t ceph cephuser@cephfs=/ /mnt/ceph -o mon_addr=192.168.1.100/192.168.1.101
> +
> +When using the mount helper, monitor address can be read from ceph
> +configuration file if available. Note that, the cluster FSID (passed as part
> +of the device string) is validated by checking it with the FSID reported by
> +the monitor.
>
>  Mount Options
>  =============
>
> +  mon_addr=ip_address[:port][/ip_address[:port]]
> +       Monitor address to the cluster. This is used to bootstrap the
> +        connection to the cluster. Once connection is established, the
> +        monitor addresses in the monitor map are followed.
> +
> +  fsid=cluster-id
> +       FSID of the cluster

Let's note it's the output of `ceph fsid`.

>    ip=A.B.C.D[:N]
>         Specify the IP and/or port the client should bind to locally.
>         There is normally not much reason to do this.  If the IP is not
> --
> 2.27.0
>


-- 
Patrick Donnelly, Ph.D.
He / Him / His
Principal Software Engineer
Red Hat Sunnyvale, CA
GPG: 19F28A586F808C2402351B93C3301A3E258DD79D


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

* Re: [PATCH v2 0/4] ceph: new mount device syntax
  2021-07-02 18:05 ` [PATCH v2 0/4] ceph: new " Patrick Donnelly
@ 2021-07-05  4:36   ` Venky Shankar
  0 siblings, 0 replies; 20+ messages in thread
From: Venky Shankar @ 2021-07-05  4:36 UTC (permalink / raw)
  To: Patrick Donnelly
  Cc: Jeff Layton, Ilya Dryomov, Luis Henriques, Ceph Development

On Fri, Jul 2, 2021 at 11:36 PM Patrick Donnelly <pdonnell@redhat.com> wrote:
>
> On Thu, Jul 1, 2021 at 11:48 PM Venky Shankar <vshankar@redhat.com> wrote:
> > Also note that the userspace mount helper tool is backward
> > compatible. I.e., the mount helper will fallback to using
> > old syntax after trying to mount with the new syntax.
>
> The kernel is also backwards compatible too, right?

Yes.

>
> --
> Patrick Donnelly, Ph.D.
> He / Him / His
> Principal Software Engineer
> Red Hat Sunnyvale, CA
> GPG: 19F28A586F808C2402351B93C3301A3E258DD79D
>


-- 
Cheers,
Venky


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

* Re: [PATCH v2 4/4] doc: document new CephFS mount device syntax
  2021-07-02 18:08   ` Patrick Donnelly
@ 2021-07-05  4:39     ` Venky Shankar
  2021-07-06 18:25       ` Jeff Layton
  0 siblings, 1 reply; 20+ messages in thread
From: Venky Shankar @ 2021-07-05  4:39 UTC (permalink / raw)
  To: Patrick Donnelly
  Cc: Jeff Layton, Ilya Dryomov, Luis Henriques, Ceph Development

On Fri, Jul 2, 2021 at 11:38 PM Patrick Donnelly <pdonnell@redhat.com> wrote:
>
> On Thu, Jul 1, 2021 at 11:48 PM Venky Shankar <vshankar@redhat.com> wrote:
> >
> > Signed-off-by: Venky Shankar <vshankar@redhat.com>
> > ---
> >  Documentation/filesystems/ceph.rst | 25 ++++++++++++++++++++++---
> >  1 file changed, 22 insertions(+), 3 deletions(-)
> >
> > diff --git a/Documentation/filesystems/ceph.rst b/Documentation/filesystems/ceph.rst
> > index 7d2ef4e27273..830ea8969d9d 100644
> > --- a/Documentation/filesystems/ceph.rst
> > +++ b/Documentation/filesystems/ceph.rst
> > @@ -82,7 +82,7 @@ Mount Syntax
> >
> >  The basic mount syntax is::
> >
> > - # mount -t ceph monip[:port][,monip2[:port]...]:/[subdir] mnt
> > + # mount -t ceph user@fsid.fs_name=/[subdir] mnt -o mon_addr=monip1[:port][/monip2[:port]]
>
> Somewhat unrelated question to this patchset: can you specify the mons
> in the ceph.conf format? i.e. with v2/v1 syntax?

The problem with that is the delimiter used is comma (",") which
restricts passing it through the mount option.

>
> >  You only need to specify a single monitor, as the client will get the
> >  full list when it connects.  (However, if the monitor you specify
> > @@ -90,16 +90,35 @@ happens to be down, the mount won't succeed.)  The port can be left
> >  off if the monitor is using the default.  So if the monitor is at
> >  1.2.3.4::
> >
> > - # mount -t ceph 1.2.3.4:/ /mnt/ceph
> > + # mount -t ceph cephuser@07fe3187-00d9-42a3-814b-72a4d5e7d5be.cephfs=/ /mnt/ceph -o mon_addr=1.2.3.4
> >
> >  is sufficient.  If /sbin/mount.ceph is installed, a hostname can be
> > -used instead of an IP address.
> > +used instead of an IP address and the cluster FSID can be left out
> > +(as the mount helper will fill it in by reading the ceph configuration
> > +file)::
> >
> > +  # mount -t ceph cephuser@cephfs=/ /mnt/ceph -o mon_addr=mon-addr
> >
> > +Multiple monitor addresses can be passed by separating each address with a slash (`/`)::
> > +
> > +  # mount -t ceph cephuser@cephfs=/ /mnt/ceph -o mon_addr=192.168.1.100/192.168.1.101
> > +
> > +When using the mount helper, monitor address can be read from ceph
> > +configuration file if available. Note that, the cluster FSID (passed as part
> > +of the device string) is validated by checking it with the FSID reported by
> > +the monitor.
> >
> >  Mount Options
> >  =============
> >
> > +  mon_addr=ip_address[:port][/ip_address[:port]]
> > +       Monitor address to the cluster. This is used to bootstrap the
> > +        connection to the cluster. Once connection is established, the
> > +        monitor addresses in the monitor map are followed.
> > +
> > +  fsid=cluster-id
> > +       FSID of the cluster
>
> Let's note it's the output of `ceph fsid`.
>
> >    ip=A.B.C.D[:N]
> >         Specify the IP and/or port the client should bind to locally.
> >         There is normally not much reason to do this.  If the IP is not
> > --
> > 2.27.0
> >
>
>
> --
> Patrick Donnelly, Ph.D.
> He / Him / His
> Principal Software Engineer
> Red Hat Sunnyvale, CA
> GPG: 19F28A586F808C2402351B93C3301A3E258DD79D
>


-- 
Cheers,
Venky


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

* Re: [PATCH v2 4/4] doc: document new CephFS mount device syntax
  2021-07-05  4:39     ` Venky Shankar
@ 2021-07-06 18:25       ` Jeff Layton
  0 siblings, 0 replies; 20+ messages in thread
From: Jeff Layton @ 2021-07-06 18:25 UTC (permalink / raw)
  To: Venky Shankar, Patrick Donnelly
  Cc: Ilya Dryomov, Luis Henriques, Ceph Development

On Mon, 2021-07-05 at 10:09 +0530, Venky Shankar wrote:
> On Fri, Jul 2, 2021 at 11:38 PM Patrick Donnelly <pdonnell@redhat.com> wrote:
> > 
> > On Thu, Jul 1, 2021 at 11:48 PM Venky Shankar <vshankar@redhat.com> wrote:
> > > 
> > > Signed-off-by: Venky Shankar <vshankar@redhat.com>
> > > ---
> > >  Documentation/filesystems/ceph.rst | 25 ++++++++++++++++++++++---
> > >  1 file changed, 22 insertions(+), 3 deletions(-)
> > > 
> > > diff --git a/Documentation/filesystems/ceph.rst b/Documentation/filesystems/ceph.rst
> > > index 7d2ef4e27273..830ea8969d9d 100644
> > > --- a/Documentation/filesystems/ceph.rst
> > > +++ b/Documentation/filesystems/ceph.rst
> > > @@ -82,7 +82,7 @@ Mount Syntax
> > > 
> > >  The basic mount syntax is::
> > > 
> > > - # mount -t ceph monip[:port][,monip2[:port]...]:/[subdir] mnt
> > > + # mount -t ceph user@fsid.fs_name=/[subdir] mnt -o mon_addr=monip1[:port][/monip2[:port]]
> > 
> > Somewhat unrelated question to this patchset: can you specify the mons
> > in the ceph.conf format? i.e. with v2/v1 syntax?
> 
> The problem with that is the delimiter used is comma (",") which
> restricts passing it through the mount option.
> > 

Yeah. I don't see an alternative here. You'd have to escape the comma
somehow. You'd also have to build an in-kernel parser for that format.

Doing this would be a project in and of itself, and it doesn't seem
valuable. mount.ceph is mostly what's going to populate this anyway and
for that we don't really care.

> > >  You only need to specify a single monitor, as the client will get the
> > >  full list when it connects.  (However, if the monitor you specify
> > > @@ -90,16 +90,35 @@ happens to be down, the mount won't succeed.)  The port can be left
> > >  off if the monitor is using the default.  So if the monitor is at
> > >  1.2.3.4::
> > > 
> > > - # mount -t ceph 1.2.3.4:/ /mnt/ceph
> > > + # mount -t ceph cephuser@07fe3187-00d9-42a3-814b-72a4d5e7d5be.cephfs=/ /mnt/ceph -o mon_addr=1.2.3.4
> > > 
> > >  is sufficient.  If /sbin/mount.ceph is installed, a hostname can be
> > > -used instead of an IP address.
> > > +used instead of an IP address and the cluster FSID can be left out
> > > +(as the mount helper will fill it in by reading the ceph configuration
> > > +file)::
> > > 
> > > +  # mount -t ceph cephuser@cephfs=/ /mnt/ceph -o mon_addr=mon-addr
> > > 
> > > +Multiple monitor addresses can be passed by separating each address with a slash (`/`)::
> > > +
> > > +  # mount -t ceph cephuser@cephfs=/ /mnt/ceph -o mon_addr=192.168.1.100/192.168.1.101
> > > +
> > > +When using the mount helper, monitor address can be read from ceph
> > > +configuration file if available. Note that, the cluster FSID (passed as part
> > > +of the device string) is validated by checking it with the FSID reported by
> > > +the monitor.
> > > 
> > >  Mount Options
> > >  =============
> > > 
> > > +  mon_addr=ip_address[:port][/ip_address[:port]]
> > > +       Monitor address to the cluster. This is used to bootstrap the
> > > +        connection to the cluster. Once connection is established, the
> > > +        monitor addresses in the monitor map are followed.
> > > +
> > > +  fsid=cluster-id
> > > +       FSID of the cluster
> > 
> > Let's note it's the output of `ceph fsid`.
> > 
> > >    ip=A.B.C.D[:N]
> > >         Specify the IP and/or port the client should bind to locally.
> > >         There is normally not much reason to do this.  If the IP is not
> > > --
> > > 2.27.0
> > > 
> > 
> > 
> > --
> > Patrick Donnelly, Ph.D.
> > He / Him / His
> > Principal Software Engineer
> > Red Hat Sunnyvale, CA
> > GPG: 19F28A586F808C2402351B93C3301A3E258DD79D
> > 
> 
> 

-- 
Jeff Layton <jlayton@redhat.com>


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

* Re: [PATCH v2 2/4] ceph: validate cluster FSID for new device syntax
  2021-07-02 14:57         ` Venky Shankar
@ 2021-07-06 18:35           ` Jeff Layton
  2021-07-07  5:05             ` Venky Shankar
  0 siblings, 1 reply; 20+ messages in thread
From: Jeff Layton @ 2021-07-06 18:35 UTC (permalink / raw)
  To: Venky Shankar, Luis Henriques; +Cc: idryomov, Patrick Donnelly, ceph-devel

On Fri, 2021-07-02 at 20:27 +0530, Venky Shankar wrote:
> On Fri, Jul 2, 2021 at 7:20 PM Luis Henriques <lhenriques@suse.de> wrote:
> > 
> > On Fri, Jul 02, 2021 at 04:40:18PM +0530, Venky Shankar wrote:
> > > On Fri, Jul 2, 2021 at 4:14 PM Luis Henriques <lhenriques@suse.de> wrote:
> > > > 
> > > > On Fri, Jul 02, 2021 at 12:18:19PM +0530, Venky Shankar wrote:
> > > > > The new device syntax requires the cluster FSID as part
> > > > > of the device string. Use this FSID to verify if it matches
> > > > > the cluster FSID we get back from the monitor, failing the
> > > > > mount on mismatch.
> > > > > 
> > > > > Also, rename parse_fsid() to ceph_parse_fsid() as it is too
> > > > > generic.
> > > > > 
> > > > > Signed-off-by: Venky Shankar <vshankar@redhat.com>
> > > > > ---
> > > > >  fs/ceph/super.c              | 9 +++++++++
> > > > >  fs/ceph/super.h              | 1 +
> > > > >  include/linux/ceph/libceph.h | 1 +
> > > > >  net/ceph/ceph_common.c       | 5 +++--
> > > > >  4 files changed, 14 insertions(+), 2 deletions(-)
> > > > > 
> > > > > diff --git a/fs/ceph/super.c b/fs/ceph/super.c
> > > > > index 0b324e43c9f4..03e5f4bb2b6f 100644
> > > > > --- a/fs/ceph/super.c
> > > > > +++ b/fs/ceph/super.c
> > > > > @@ -268,6 +268,9 @@ static int ceph_parse_new_source(const char *dev_name, const char *dev_name_end,
> > > > >       if (!fs_name_start)
> > > > >               return invalfc(fc, "missing file system name");
> > > > > 
> > > > > +     if (ceph_parse_fsid(fsid_start, &fsopt->fsid))
> > > > > +             return invalfc(fc, "invalid fsid format");
> > > > > +
> > > > >       ++fs_name_start; /* start of file system name */
> > > > >       fsopt->mds_namespace = kstrndup(fs_name_start,
> > > > >                                       dev_name_end - fs_name_start, GFP_KERNEL);
> > > > > @@ -750,6 +753,12 @@ static struct ceph_fs_client *create_fs_client(struct ceph_mount_options *fsopt,
> > > > >       }
> > > > >       opt = NULL; /* fsc->client now owns this */
> > > > > 
> > > > > +     /* help learn fsid */
> > > > > +     if (fsopt->new_dev_syntax) {
> > > > > +             ceph_check_fsid(fsc->client, &fsopt->fsid);
> > > > 
> > > > This call to ceph_check_fsid() made me wonder what would happen if I use
> > > > the wrong fsid with the new syntax.  And the result is:
> > > > 
> > > > [   41.882334] libceph: mon0 (1)192.168.155.1:40594 session established
> > > > [   41.884537] libceph: bad fsid, had d52783e6-efc2-4dce-ad01-aa3272fa5f66 got 90bdb539-9d95-402e-8f23-b0e26cba8b1b
> > > > [   41.885955] libceph: bad fsid, had d52783e6-efc2-4dce-ad01-aa3272fa5f66 got 90bdb539-9d95-402e-8f23-b0e26cba8b1b
> > > > [   41.889313] libceph: bad fsid, had d52783e6-efc2-4dce-ad01-aa3272fa5f66 got 90bdb539-9d95-402e-8f23-b0e26cba8b1b
> > > > [   41.892578] libceph: osdc handle_map corrupt msg
> > > > 
> > > > ... followed by a msg dump.
> > > > 
> > > > I guess this means that manually setting the fsid requires changes to the
> > > > messenger (I've only tested with v1) so that it gracefully handles this
> > > > scenario.
> > > 
> > > Yes, this results in a big dump of messages. I haven't looked at
> > > gracefully handling these.
> > > 
> > > I'm not sure if it needs to be done in these set of patches though.
> > 
> > Ah, sure!  I didn't meant you'd need to change the messenger to handle it
> > (as I'm not even sure it's the messenger or the mons client that require
> > changes).  But I also don't think that this patchset can be merged without
> > making sure we can handle a bad fsid correctly and without all this noise.
> 
> True. However, for most cases users really won't be filling in the
> fsid and the mount helper would fill the "correct" one automatically.
> 

Yes, but some of them may and I think we do need to handle this
gracefully. Let's step back a moment and consider:

AIUI, the fsid is only here to disambiguate when you have multiple
clusters. The kernel doesn't really care about this value at all. All it
cares about is whether it's talking to the right mons (as evidenced by
the fact that we don't pass the fsid in at mount time today).

So probably the right thing to do is to just return an error (-EINVAL?)
to mount() when there is a mismatch between the fsid and the one in the
maps. Is that possible?

> > 
> > Cheers,
> > --
> > Luís
> > 
> > > 
> > > > 
> > > > Cheers,
> > > > --
> > > > Luís
> > > > 
> > > > > +             fsc->client->have_fsid = true;
> > > > > +     }
> > > > > +
> > > > >       fsc->client->extra_mon_dispatch = extra_mon_dispatch;
> > > > >       ceph_set_opt(fsc->client, ABORT_ON_FULL);
> > > > > 
> > > > > diff --git a/fs/ceph/super.h b/fs/ceph/super.h
> > > > > index 8f71184b7c85..ce5fb90a01a4 100644
> > > > > --- a/fs/ceph/super.h
> > > > > +++ b/fs/ceph/super.h
> > > > > @@ -99,6 +99,7 @@ struct ceph_mount_options {
> > > > >       char *server_path;    /* default NULL (means "/") */
> > > > >       char *fscache_uniq;   /* default NULL */
> > > > >       char *mon_addr;
> > > > > +     struct ceph_fsid fsid;
> > > > >  };
> > > > > 
> > > > >  struct ceph_fs_client {
> > > > > diff --git a/include/linux/ceph/libceph.h b/include/linux/ceph/libceph.h
> > > > > index 409d8c29bc4f..75d059b79d90 100644
> > > > > --- a/include/linux/ceph/libceph.h
> > > > > +++ b/include/linux/ceph/libceph.h
> > > > > @@ -296,6 +296,7 @@ extern bool libceph_compatible(void *data);
> > > > >  extern const char *ceph_msg_type_name(int type);
> > > > >  extern int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid);
> > > > >  extern void *ceph_kvmalloc(size_t size, gfp_t flags);
> > > > > +extern int ceph_parse_fsid(const char *str, struct ceph_fsid *fsid);
> > > > > 
> > > > >  struct fs_parameter;
> > > > >  struct fc_log;
> > > > > diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c
> > > > > index 97d6ea763e32..da480757fcca 100644
> > > > > --- a/net/ceph/ceph_common.c
> > > > > +++ b/net/ceph/ceph_common.c
> > > > > @@ -217,7 +217,7 @@ void *ceph_kvmalloc(size_t size, gfp_t flags)
> > > > >       return p;
> > > > >  }
> > > > > 
> > > > > -static int parse_fsid(const char *str, struct ceph_fsid *fsid)
> > > > > +int ceph_parse_fsid(const char *str, struct ceph_fsid *fsid)
> > > > >  {
> > > > >       int i = 0;
> > > > >       char tmp[3];
> > > > > @@ -247,6 +247,7 @@ static int parse_fsid(const char *str, struct ceph_fsid *fsid)
> > > > >       dout("parse_fsid ret %d got fsid %pU\n", err, fsid);
> > > > >       return err;
> > > > >  }
> > > > > +EXPORT_SYMBOL(ceph_parse_fsid);
> > > > > 
> > > > >  /*
> > > > >   * ceph options
> > > > > @@ -465,7 +466,7 @@ int ceph_parse_param(struct fs_parameter *param, struct ceph_options *opt,
> > > > >               break;
> > > > > 
> > > > >       case Opt_fsid:
> > > > > -             err = parse_fsid(param->string, &opt->fsid);
> > > > > +             err = ceph_parse_fsid(param->string, &opt->fsid);
> > > > >               if (err) {
> > > > >                       error_plog(&log, "Failed to parse fsid: %d", err);
> > > > >                       return err;
> > > > > --
> > > > > 2.27.0
> > > > > 
> > > > 
> > > 
> > > 
> > > --
> > > Cheers,
> > > Venky
> > > 
> > 
> 
> 

-- 
Jeff Layton <jlayton@redhat.com>


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

* Re: [PATCH v2 1/4] ceph: new device mount syntax
  2021-07-02 11:05     ` Venky Shankar
@ 2021-07-06 18:41       ` Jeff Layton
  0 siblings, 0 replies; 20+ messages in thread
From: Jeff Layton @ 2021-07-06 18:41 UTC (permalink / raw)
  To: Venky Shankar, Luis Henriques; +Cc: idryomov, Patrick Donnelly, ceph-devel

On Fri, 2021-07-02 at 16:35 +0530, Venky Shankar wrote:
> On Fri, Jul 2, 2021 at 4:08 PM Luis Henriques <lhenriques@suse.de> wrote:
> > 
> > On Fri, Jul 02, 2021 at 12:18:18PM +0530, Venky Shankar wrote:
> > > Old mount device syntax (source) has the following problems:
> > > 
> > > - mounts to the same cluster but with different fsnames
> > >   and/or creds have identical device string which can
> > >   confuse xfstests.
> > > 
> > > - Userspace mount helper tool resolves monitor addresses
> > >   and fill in mon addrs automatically, but that means the
> > >   device shown in /proc/mounts is different than what was
> > >   used for mounting.
> > > 
> > > New device syntax is as follows:
> > > 
> > >   cephuser@fsid.mycephfs2=/path
> > > 
> > > Note, there is no "monitor address" in the device string.
> > > That gets passed in as mount option. This keeps the device
> > > string same when monitor addresses change (on remounts).
> > > 
> > > Also note that the userspace mount helper tool is backward
> > > compatible. I.e., the mount helper will fallback to using
> > > old syntax after trying to mount with the new syntax.
> > > 
> > > Signed-off-by: Venky Shankar <vshankar@redhat.com>
> > > ---
> > >  fs/ceph/super.c | 122 ++++++++++++++++++++++++++++++++++++++++++++----
> > >  fs/ceph/super.h |   3 ++
> > >  2 files changed, 115 insertions(+), 10 deletions(-)
> > > 
> > > diff --git a/fs/ceph/super.c b/fs/ceph/super.c
> > > index 9b1b7f4cfdd4..0b324e43c9f4 100644
> > > --- a/fs/ceph/super.c
> > > +++ b/fs/ceph/super.c
> > > @@ -145,6 +145,7 @@ enum {
> > >       Opt_mds_namespace,
> > >       Opt_recover_session,
> > >       Opt_source,
> > > +     Opt_mon_addr,
> > >       /* string args above */
> > >       Opt_dirstat,
> > >       Opt_rbytes,
> > > @@ -196,6 +197,7 @@ static const struct fs_parameter_spec ceph_mount_parameters[] = {
> > >       fsparam_u32     ("rsize",                       Opt_rsize),
> > >       fsparam_string  ("snapdirname",                 Opt_snapdirname),
> > >       fsparam_string  ("source",                      Opt_source),
> > > +     fsparam_string  ("mon_addr",                    Opt_mon_addr),
> > >       fsparam_u32     ("wsize",                       Opt_wsize),
> > >       fsparam_flag_no ("wsync",                       Opt_wsync),
> > >       {}
> > > @@ -226,10 +228,70 @@ static void canonicalize_path(char *path)
> > >       path[j] = '\0';
> > >  }
> > > 
> > > +static int ceph_parse_old_source(const char *dev_name, const char *dev_name_end,
> > > +                              struct fs_context *fc)
> > > +{
> > > +     int r;
> > > +     struct ceph_parse_opts_ctx *pctx = fc->fs_private;
> > > +     struct ceph_mount_options *fsopt = pctx->opts;
> > > +
> > > +     if (*dev_name_end != ':')
> > > +             return invalfc(fc, "separator ':' missing in source");
> > > +
> > > +     r = ceph_parse_mon_ips(dev_name, dev_name_end - dev_name,
> > > +                            pctx->copts, fc->log.log);
> > > +     if (r)
> > > +             return r;
> > > +
> > > +     fsopt->new_dev_syntax = false;
> > > +     return 0;
> > > +}
> > > +
> > > +static int ceph_parse_new_source(const char *dev_name, const char *dev_name_end,
> > > +                              struct fs_context *fc)
> > > +{
> > > +     struct ceph_parse_opts_ctx *pctx = fc->fs_private;
> > > +     struct ceph_mount_options *fsopt = pctx->opts;
> > > +     char *fsid_start, *fs_name_start;
> > > +
> > > +     if (*dev_name_end != '=') {
> > > +             dout("separator '=' missing in source");
> > > +             return -EINVAL;
> > > +     }
> > > +
> > > +     fsid_start = strchr(dev_name, '@');
> > > +     if (!fsid_start)
> > > +             return invalfc(fc, "missing cluster fsid");
> > > +     ++fsid_start; /* start of cluster fsid */
> > > +
> > > +     fs_name_start = strchr(fsid_start, '.');
> > > +     if (!fs_name_start)
> > > +             return invalfc(fc, "missing file system name");
> > > +
> > > +     ++fs_name_start; /* start of file system name */
> > > +     fsopt->mds_namespace = kstrndup(fs_name_start,
> > > +                                     dev_name_end - fs_name_start, GFP_KERNEL);
> > > +     if (!fsopt->mds_namespace)
> > > +             return -ENOMEM;
> > > +     dout("file system (mds namespace) '%s'\n", fsopt->mds_namespace);
> > > +
> > > +     fsopt->new_dev_syntax = true;
> > > +     return 0;
> > > +}
> > > +
> > >  /*
> > > - * Parse the source parameter.  Distinguish the server list from the path.
> > > + * Parse the source parameter for new device format. Distinguish the device
> > > + * spec from the path. Try parsing new device format and fallback to old
> > > + * format if needed.
> > >   *
> > > - * The source will look like:
> > > + * New device syntax will looks like:
> > > + *     <device_spec>=/<path>
> > > + * where
> > > + *     <device_spec> is name@fsid.fsname
> > > + *     <path> is optional, but if present must begin with '/'
> > > + * (monitor addresses are passed via mount option)
> > > + *
> > > + * Old device syntax is:
> > >   *     <server_spec>[,<server_spec>...]:[<path>]
> > >   * where
> > >   *     <server_spec> is <ip>[:<port>]
> > > @@ -262,22 +324,48 @@ static int ceph_parse_source(struct fs_parameter *param, struct fs_context *fc)
> > >               dev_name_end = dev_name + strlen(dev_name);
> > >       }
> > > 
> > > -     dev_name_end--;         /* back up to ':' separator */
> > > -     if (dev_name_end < dev_name || *dev_name_end != ':')
> > > -             return invalfc(fc, "No path or : separator in source");
> > > +     dev_name_end--;         /* back up to separator */
> > > +     if (dev_name_end < dev_name)
> > > +             return invalfc(fc, "path missing in source");
> > > 
> > >       dout("device name '%.*s'\n", (int)(dev_name_end - dev_name), dev_name);
> > >       if (fsopt->server_path)
> > >               dout("server path '%s'\n", fsopt->server_path);
> > > 
> > > -     ret = ceph_parse_mon_ips(param->string, dev_name_end - dev_name,
> > > -                              pctx->copts, fc->log.log);
> > > +     dout("trying new device syntax");
> > > +     ret = ceph_parse_new_source(dev_name, dev_name_end, fc);
> > > +     if (ret == 0)
> > > +             goto done;
> > > +
> > > +     dout("trying old device syntax");
> > > +     ret = ceph_parse_old_source(dev_name, dev_name_end, fc);
> > >       if (ret)
> > > -             return ret;
> > > +             goto out;
> > 
> > Do we really need this goto?  My (personal) preference would be to drop
> > this one and simply return.   And maybe it's even possible to drop the
> > previous 'goto done' too.
> 
> Sure. Just a preference I had.
> 
> > 
> > > + done:
> > >       fc->source = param->string;
> > >       param->string = NULL;
> > > -     return 0;
> > > + out:
> > > +     return ret;
> > > +}
> > > +
> > > +static int ceph_parse_mon_addr(struct fs_parameter *param,
> > > +                            struct fs_context *fc)
> > > +{
> > > +     int r;
> > > +     struct ceph_parse_opts_ctx *pctx = fc->fs_private;
> > > +     struct ceph_mount_options *fsopt = pctx->opts;
> > > +
> > > +     kfree(fsopt->mon_addr);
> > > +     fsopt->mon_addr = param->string;
> > > +     param->string = NULL;
> > > +
> > > +     strreplace(fsopt->mon_addr, '/', ',');
> > > +     r = ceph_parse_mon_ips(fsopt->mon_addr, strlen(fsopt->mon_addr),
> > > +                            pctx->copts, fc->log.log);
> > > +        // since its used in ceph_show_options()
> > 
> > (nit: use c-style comments...? yeah, again personal preference :-)
> > 
> > > +     strreplace(fsopt->mon_addr, ',', '/');
> > 
> > This is ugly.  Have you considered modifying ceph_parse_mon_ips() (and
> > ceph_parse_ips()) to receive a delimiter as a parameter?''
> 
> I did. However, for most cases (all possibly), "," is the addr
> delimiter. So, I didn't take the approach to make these helpers really
> generic for parsing addrs.
> 

Yeah, I'm not a fan of this either. Why not just add an extra char
argument to to ceph_parse_mon_ips and use that to pass in a delimiter
char? Looks like you'll have to plumb it through a couple of functions
but that seems doable.

> > 
> > > +     return r;
> > >  }
> > > 
> > >  static int ceph_parse_mount_param(struct fs_context *fc,
> > > @@ -322,6 +410,8 @@ static int ceph_parse_mount_param(struct fs_context *fc,
> > >               if (fc->source)
> > >                       return invalfc(fc, "Multiple sources specified");
> > >               return ceph_parse_source(param, fc);
> > > +     case Opt_mon_addr:
> > > +             return ceph_parse_mon_addr(param, fc);
> > >       case Opt_wsize:
> > >               if (result.uint_32 < PAGE_SIZE ||
> > >                   result.uint_32 > CEPH_MAX_WRITE_SIZE)
> > > @@ -473,6 +563,7 @@ static void destroy_mount_options(struct ceph_mount_options *args)
> > >       kfree(args->mds_namespace);
> > >       kfree(args->server_path);
> > >       kfree(args->fscache_uniq);
> > > +     kfree(args->mon_addr);
> > >       kfree(args);
> > >  }
> > > 
> > > @@ -516,6 +607,10 @@ static int compare_mount_options(struct ceph_mount_options *new_fsopt,
> > >       if (ret)
> > >               return ret;
> > > 
> > > +     ret = strcmp_null(fsopt1->mon_addr, fsopt2->mon_addr);
> > > +     if (ret)
> > > +             return ret;
> > > +
> > >       return ceph_compare_options(new_opt, fsc->client);
> > >  }
> > > 
> > > @@ -571,9 +666,13 @@ static int ceph_show_options(struct seq_file *m, struct dentry *root)
> > >       if ((fsopt->flags & CEPH_MOUNT_OPT_NOCOPYFROM) == 0)
> > >               seq_puts(m, ",copyfrom");
> > > 
> > > -     if (fsopt->mds_namespace)
> > > +     /* dump mds_namespace when old device syntax is in use */
> > > +     if (fsopt->mds_namespace && !fsopt->new_dev_syntax)
> > >               seq_show_option(m, "mds_namespace", fsopt->mds_namespace);
> > 
> > I haven't really tested it, but... what happens if we set mds_namespace
> > *and* we're using the new syntax?  Or, in another words, what should
> > happen?

Probably best to just throw an error at mount time if they don't match.

> 
> Depends on the order of token parsing in ceph_parse_mount_param()
> which mds_namespace gets used.
> 
> (however, that means ceph_parse_new_source() should additionally
> kfree(fsopt->mds_namespace)).
> 
> 
> > Cheers,
> > --
> > Luís
> > 
> > > 
> > > +     if (fsopt->mon_addr)
> > > +             seq_printf(m, ",mon_addr=%s", fsopt->mon_addr);
> > > +
> > >       if (fsopt->flags & CEPH_MOUNT_OPT_CLEANRECOVER)
> > >               seq_show_option(m, "recover_session", "clean");
> > > 
> > > @@ -1048,6 +1147,7 @@ static int ceph_setup_bdi(struct super_block *sb, struct ceph_fs_client *fsc)
> > >  static int ceph_get_tree(struct fs_context *fc)
> > >  {
> > >       struct ceph_parse_opts_ctx *pctx = fc->fs_private;
> > > +     struct ceph_mount_options *fsopt = pctx->opts;
> > >       struct super_block *sb;
> > >       struct ceph_fs_client *fsc;
> > >       struct dentry *res;
> > > @@ -1059,6 +1159,8 @@ static int ceph_get_tree(struct fs_context *fc)
> > > 
> > >       if (!fc->source)
> > >               return invalfc(fc, "No source");
> > > +     if (fsopt->new_dev_syntax && !fsopt->mon_addr)
> > > +             return invalfc(fc, "No monitor address");
> > > 
> > >       /* create client (which we may/may not use) */
> > >       fsc = create_fs_client(pctx->opts, pctx->copts);
> > > diff --git a/fs/ceph/super.h b/fs/ceph/super.h
> > > index c48bb30c8d70..8f71184b7c85 100644
> > > --- a/fs/ceph/super.h
> > > +++ b/fs/ceph/super.h
> > > @@ -87,6 +87,8 @@ struct ceph_mount_options {
> > >       unsigned int max_readdir;       /* max readdir result (entries) */
> > >       unsigned int max_readdir_bytes; /* max readdir result (bytes) */
> > > 
> > > +     bool new_dev_syntax;
> > > +
> > >       /*
> > >        * everything above this point can be memcmp'd; everything below
> > >        * is handled in compare_mount_options()
> > > @@ -96,6 +98,7 @@ struct ceph_mount_options {
> > >       char *mds_namespace;  /* default NULL */
> > >       char *server_path;    /* default NULL (means "/") */
> > >       char *fscache_uniq;   /* default NULL */
> > > +     char *mon_addr;
> > >  };
> > > 
> > >  struct ceph_fs_client {
> > > --
> > > 2.27.0
> > > 
> > 
> 
> 

-- 
Jeff Layton <jlayton@redhat.com>


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

* Re: [PATCH v2 2/4] ceph: validate cluster FSID for new device syntax
  2021-07-06 18:35           ` Jeff Layton
@ 2021-07-07  5:05             ` Venky Shankar
  0 siblings, 0 replies; 20+ messages in thread
From: Venky Shankar @ 2021-07-07  5:05 UTC (permalink / raw)
  To: Jeff Layton; +Cc: Luis Henriques, Ilya Dryomov, Patrick Donnelly, ceph-devel

On Wed, Jul 7, 2021 at 12:05 AM Jeff Layton <jlayton@redhat.com> wrote:
>
> On Fri, 2021-07-02 at 20:27 +0530, Venky Shankar wrote:
> > On Fri, Jul 2, 2021 at 7:20 PM Luis Henriques <lhenriques@suse.de> wrote:
> > >
> > > On Fri, Jul 02, 2021 at 04:40:18PM +0530, Venky Shankar wrote:
> > > > On Fri, Jul 2, 2021 at 4:14 PM Luis Henriques <lhenriques@suse.de> wrote:
> > > > >
> > > > > On Fri, Jul 02, 2021 at 12:18:19PM +0530, Venky Shankar wrote:
> > > > > > The new device syntax requires the cluster FSID as part
> > > > > > of the device string. Use this FSID to verify if it matches
> > > > > > the cluster FSID we get back from the monitor, failing the
> > > > > > mount on mismatch.
> > > > > >
> > > > > > Also, rename parse_fsid() to ceph_parse_fsid() as it is too
> > > > > > generic.
> > > > > >
> > > > > > Signed-off-by: Venky Shankar <vshankar@redhat.com>
> > > > > > ---
> > > > > >  fs/ceph/super.c              | 9 +++++++++
> > > > > >  fs/ceph/super.h              | 1 +
> > > > > >  include/linux/ceph/libceph.h | 1 +
> > > > > >  net/ceph/ceph_common.c       | 5 +++--
> > > > > >  4 files changed, 14 insertions(+), 2 deletions(-)
> > > > > >
> > > > > > diff --git a/fs/ceph/super.c b/fs/ceph/super.c
> > > > > > index 0b324e43c9f4..03e5f4bb2b6f 100644
> > > > > > --- a/fs/ceph/super.c
> > > > > > +++ b/fs/ceph/super.c
> > > > > > @@ -268,6 +268,9 @@ static int ceph_parse_new_source(const char *dev_name, const char *dev_name_end,
> > > > > >       if (!fs_name_start)
> > > > > >               return invalfc(fc, "missing file system name");
> > > > > >
> > > > > > +     if (ceph_parse_fsid(fsid_start, &fsopt->fsid))
> > > > > > +             return invalfc(fc, "invalid fsid format");
> > > > > > +
> > > > > >       ++fs_name_start; /* start of file system name */
> > > > > >       fsopt->mds_namespace = kstrndup(fs_name_start,
> > > > > >                                       dev_name_end - fs_name_start, GFP_KERNEL);
> > > > > > @@ -750,6 +753,12 @@ static struct ceph_fs_client *create_fs_client(struct ceph_mount_options *fsopt,
> > > > > >       }
> > > > > >       opt = NULL; /* fsc->client now owns this */
> > > > > >
> > > > > > +     /* help learn fsid */
> > > > > > +     if (fsopt->new_dev_syntax) {
> > > > > > +             ceph_check_fsid(fsc->client, &fsopt->fsid);
> > > > >
> > > > > This call to ceph_check_fsid() made me wonder what would happen if I use
> > > > > the wrong fsid with the new syntax.  And the result is:
> > > > >
> > > > > [   41.882334] libceph: mon0 (1)192.168.155.1:40594 session established
> > > > > [   41.884537] libceph: bad fsid, had d52783e6-efc2-4dce-ad01-aa3272fa5f66 got 90bdb539-9d95-402e-8f23-b0e26cba8b1b
> > > > > [   41.885955] libceph: bad fsid, had d52783e6-efc2-4dce-ad01-aa3272fa5f66 got 90bdb539-9d95-402e-8f23-b0e26cba8b1b
> > > > > [   41.889313] libceph: bad fsid, had d52783e6-efc2-4dce-ad01-aa3272fa5f66 got 90bdb539-9d95-402e-8f23-b0e26cba8b1b
> > > > > [   41.892578] libceph: osdc handle_map corrupt msg
> > > > >
> > > > > ... followed by a msg dump.
> > > > >
> > > > > I guess this means that manually setting the fsid requires changes to the
> > > > > messenger (I've only tested with v1) so that it gracefully handles this
> > > > > scenario.
> > > >
> > > > Yes, this results in a big dump of messages. I haven't looked at
> > > > gracefully handling these.
> > > >
> > > > I'm not sure if it needs to be done in these set of patches though.
> > >
> > > Ah, sure!  I didn't meant you'd need to change the messenger to handle it
> > > (as I'm not even sure it's the messenger or the mons client that require
> > > changes).  But I also don't think that this patchset can be merged without
> > > making sure we can handle a bad fsid correctly and without all this noise.
> >
> > True. However, for most cases users really won't be filling in the
> > fsid and the mount helper would fill the "correct" one automatically.
> >
>
> Yes, but some of them may and I think we do need to handle this
> gracefully. Let's step back a moment and consider:
>
> AIUI, the fsid is only here to disambiguate when you have multiple
> clusters. The kernel doesn't really care about this value at all. All it
> cares about is whether it's talking to the right mons (as evidenced by
> the fact that we don't pass the fsid in at mount time today).
>
> So probably the right thing to do is to just return an error (-EINVAL?)
> to mount() when there is a mismatch between the fsid and the one in the
> maps. Is that possible?

Gracefully handling this is the correct way forward. With these
changes, a fsid mismatch results in a big splat of message dumps and
mount failure.

I haven't yet figured where (all) to plumb in the work to handle this,
but looks doable.

>
> > >
> > > Cheers,
> > > --
> > > Luís
> > >
> > > >
> > > > >
> > > > > Cheers,
> > > > > --
> > > > > Luís
> > > > >
> > > > > > +             fsc->client->have_fsid = true;
> > > > > > +     }
> > > > > > +
> > > > > >       fsc->client->extra_mon_dispatch = extra_mon_dispatch;
> > > > > >       ceph_set_opt(fsc->client, ABORT_ON_FULL);
> > > > > >
> > > > > > diff --git a/fs/ceph/super.h b/fs/ceph/super.h
> > > > > > index 8f71184b7c85..ce5fb90a01a4 100644
> > > > > > --- a/fs/ceph/super.h
> > > > > > +++ b/fs/ceph/super.h
> > > > > > @@ -99,6 +99,7 @@ struct ceph_mount_options {
> > > > > >       char *server_path;    /* default NULL (means "/") */
> > > > > >       char *fscache_uniq;   /* default NULL */
> > > > > >       char *mon_addr;
> > > > > > +     struct ceph_fsid fsid;
> > > > > >  };
> > > > > >
> > > > > >  struct ceph_fs_client {
> > > > > > diff --git a/include/linux/ceph/libceph.h b/include/linux/ceph/libceph.h
> > > > > > index 409d8c29bc4f..75d059b79d90 100644
> > > > > > --- a/include/linux/ceph/libceph.h
> > > > > > +++ b/include/linux/ceph/libceph.h
> > > > > > @@ -296,6 +296,7 @@ extern bool libceph_compatible(void *data);
> > > > > >  extern const char *ceph_msg_type_name(int type);
> > > > > >  extern int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid);
> > > > > >  extern void *ceph_kvmalloc(size_t size, gfp_t flags);
> > > > > > +extern int ceph_parse_fsid(const char *str, struct ceph_fsid *fsid);
> > > > > >
> > > > > >  struct fs_parameter;
> > > > > >  struct fc_log;
> > > > > > diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c
> > > > > > index 97d6ea763e32..da480757fcca 100644
> > > > > > --- a/net/ceph/ceph_common.c
> > > > > > +++ b/net/ceph/ceph_common.c
> > > > > > @@ -217,7 +217,7 @@ void *ceph_kvmalloc(size_t size, gfp_t flags)
> > > > > >       return p;
> > > > > >  }
> > > > > >
> > > > > > -static int parse_fsid(const char *str, struct ceph_fsid *fsid)
> > > > > > +int ceph_parse_fsid(const char *str, struct ceph_fsid *fsid)
> > > > > >  {
> > > > > >       int i = 0;
> > > > > >       char tmp[3];
> > > > > > @@ -247,6 +247,7 @@ static int parse_fsid(const char *str, struct ceph_fsid *fsid)
> > > > > >       dout("parse_fsid ret %d got fsid %pU\n", err, fsid);
> > > > > >       return err;
> > > > > >  }
> > > > > > +EXPORT_SYMBOL(ceph_parse_fsid);
> > > > > >
> > > > > >  /*
> > > > > >   * ceph options
> > > > > > @@ -465,7 +466,7 @@ int ceph_parse_param(struct fs_parameter *param, struct ceph_options *opt,
> > > > > >               break;
> > > > > >
> > > > > >       case Opt_fsid:
> > > > > > -             err = parse_fsid(param->string, &opt->fsid);
> > > > > > +             err = ceph_parse_fsid(param->string, &opt->fsid);
> > > > > >               if (err) {
> > > > > >                       error_plog(&log, "Failed to parse fsid: %d", err);
> > > > > >                       return err;
> > > > > > --
> > > > > > 2.27.0
> > > > > >
> > > > >
> > > >
> > > >
> > > > --
> > > > Cheers,
> > > > Venky
> > > >
> > >
> >
> >
>
> --
> Jeff Layton <jlayton@redhat.com>
>


-- 
Cheers,
Venky


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

end of thread, other threads:[~2021-07-07  5:05 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-02  6:48 [PATCH v2 0/4] ceph: new mount device syntax Venky Shankar
2021-07-02  6:48 ` [PATCH v2 1/4] ceph: new device mount syntax Venky Shankar
2021-07-02 10:38   ` Luis Henriques
2021-07-02 11:05     ` Venky Shankar
2021-07-06 18:41       ` Jeff Layton
2021-07-02  6:48 ` [PATCH v2 2/4] ceph: validate cluster FSID for new device syntax Venky Shankar
2021-07-02 10:44   ` Luis Henriques
2021-07-02 10:48     ` Luis Henriques
2021-07-02 11:10     ` Venky Shankar
2021-07-02 13:49       ` Luis Henriques
2021-07-02 14:57         ` Venky Shankar
2021-07-06 18:35           ` Jeff Layton
2021-07-07  5:05             ` Venky Shankar
2021-07-02  6:48 ` [PATCH v2 3/4] ceph: record updated mon_addr on remount Venky Shankar
2021-07-02  6:48 ` [PATCH v2 4/4] doc: document new CephFS mount device syntax Venky Shankar
2021-07-02 18:08   ` Patrick Donnelly
2021-07-05  4:39     ` Venky Shankar
2021-07-06 18:25       ` Jeff Layton
2021-07-02 18:05 ` [PATCH v2 0/4] ceph: new " Patrick Donnelly
2021-07-05  4:36   ` Venky Shankar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).