Subject: linux-next: manual merge of the vfs tree with the ceph tree

From: Stephen Rothwell <[email-masked]>
Date: Tue, 27 Aug 2019 11:06:47 +1000

Hi all,

Today's linux-next merge of the vfs tree got a conflict in:

  fs/ceph/super.c

between commit:

  8e4133936f30 ("ceph: auto reconnect after blacklisted")

from the ceph tree and commit:

  108f95bfaa56 ("vfs: Convert ceph to use the new mount API")

from the vfs tree.

I fixed it up (see below, but clearly needs more ..) and can carry the
fix as necessary. This is now fixed as far as linux-next is concerned,
but any non trivial conflicts should be mentioned to your upstream
maintainer when your tree is submitted for merging.  You may also want
to consider cooperating with the maintainer of the conflicting tree to
minimise any particularly complex conflicts.

-- 
Cheers,
Stephen Rothwell

diff --cc fs/ceph/super.c
index 03b63b1cd32c,04c67bd20956..000000000000
--- a/fs/ceph/super.c
+++ b/fs/ceph/super.c
@@@ -129,275 -129,278 +130,287 @@@ static int ceph_sync_fs(struct super_bl
   * mount options
   */
  enum {
- 	Opt_wsize,
- 	Opt_rsize,
- 	Opt_rasize,
- 	Opt_caps_wanted_delay_min,
- 	Opt_caps_wanted_delay_max,
+ 	Opt_acl,
+ 	Opt_asyncreaddir,
  	Opt_caps_max,
- 	Opt_readdir_max_entries,
- 	Opt_readdir_max_bytes,
+ 	Opt_caps_wanted_delay_max,
+ 	Opt_caps_wanted_delay_min,
  	Opt_congestion_kb,
- 	Opt_last_int,
- 	/* int args above */
- 	Opt_snapdirname,
- 	Opt_mds_namespace,
- 	Opt_fscache_uniq,
- 	Opt_recover_session,
- 	Opt_last_string,
- 	/* string args above */
- 	Opt_dirstat,
- 	Opt_nodirstat,
- 	Opt_rbytes,
- 	Opt_norbytes,
- 	Opt_asyncreaddir,
- 	Opt_noasyncreaddir,
+ 	Opt_copyfrom,
  	Opt_dcache,
- 	Opt_nodcache,
- 	Opt_ino32,
- 	Opt_noino32,
+ 	Opt_dirstat,
  	Opt_fscache,
- 	Opt_nofscache,
+ 	Opt_ino32,
+ 	Opt_mds_namespace,
  	Opt_poolperm,
- 	Opt_nopoolperm,
- 	Opt_require_active_mds,
- 	Opt_norequire_active_mds,
- #ifdef CONFIG_CEPH_FS_POSIX_ACL
- 	Opt_acl,
- #endif
- 	Opt_noacl,
  	Opt_quotadf,
- 	Opt_noquotadf,
- 	Opt_copyfrom,
- 	Opt_nocopyfrom,
+ 	Opt_rasize,
+ 	Opt_rbytes,
+ 	Opt_readdir_max_bytes,
+ 	Opt_readdir_max_entries,
++	Opt_recover_session,
+ 	Opt_require_active_mds,
+ 	Opt_rsize,
+ 	Opt_snapdirname,
+ 	Opt_source,
+ 	Opt_wsize,
  };
  
- static match_table_t fsopt_tokens = {
- 	{Opt_wsize, "wsize=%d"},
- 	{Opt_rsize, "rsize=%d"},
- 	{Opt_rasize, "rasize=%d"},
- 	{Opt_caps_wanted_delay_min, "caps_wanted_delay_min=%d"},
- 	{Opt_caps_wanted_delay_max, "caps_wanted_delay_max=%d"},
- 	{Opt_caps_max, "caps_max=%d"},
- 	{Opt_readdir_max_entries, "readdir_max_entries=%d"},
- 	{Opt_readdir_max_bytes, "readdir_max_bytes=%d"},
- 	{Opt_congestion_kb, "write_congestion_kb=%d"},
- 	/* int args above */
- 	{Opt_snapdirname, "snapdirname=%s"},
- 	{Opt_mds_namespace, "mds_namespace=%s"},
- 	{Opt_recover_session, "recover_session=%s"},
- 	{Opt_fscache_uniq, "fsc=%s"},
- 	/* string args above */
- 	{Opt_dirstat, "dirstat"},
- 	{Opt_nodirstat, "nodirstat"},
- 	{Opt_rbytes, "rbytes"},
- 	{Opt_norbytes, "norbytes"},
- 	{Opt_asyncreaddir, "asyncreaddir"},
- 	{Opt_noasyncreaddir, "noasyncreaddir"},
- 	{Opt_dcache, "dcache"},
- 	{Opt_nodcache, "nodcache"},
- 	{Opt_ino32, "ino32"},
- 	{Opt_noino32, "noino32"},
- 	{Opt_fscache, "fsc"},
- 	{Opt_nofscache, "nofsc"},
- 	{Opt_poolperm, "poolperm"},
- 	{Opt_nopoolperm, "nopoolperm"},
- 	{Opt_require_active_mds, "require_active_mds"},
- 	{Opt_norequire_active_mds, "norequire_active_mds"},
- #ifdef CONFIG_CEPH_FS_POSIX_ACL
- 	{Opt_acl, "acl"},
- #endif
- 	{Opt_noacl, "noacl"},
- 	{Opt_quotadf, "quotadf"},
- 	{Opt_noquotadf, "noquotadf"},
- 	{Opt_copyfrom, "copyfrom"},
- 	{Opt_nocopyfrom, "nocopyfrom"},
- 	{-1, NULL}
+ static const struct fs_parameter_spec ceph_param_specs[] = {
+ 	fsparam_flag_no ("acl",				Opt_acl),
+ 	fsparam_flag_no ("asyncreaddir",		Opt_asyncreaddir),
+ 	fsparam_u32	("caps_max",			Opt_caps_max),
+ 	fsparam_u32	("caps_wanted_delay_max",	Opt_caps_wanted_delay_max),
+ 	fsparam_u32	("caps_wanted_delay_min",	Opt_caps_wanted_delay_min),
+ 	fsparam_s32	("write_congestion_kb",		Opt_congestion_kb),
+ 	fsparam_flag_no ("copyfrom",			Opt_copyfrom),
+ 	fsparam_flag_no ("dcache",			Opt_dcache),
+ 	fsparam_flag_no ("dirstat",			Opt_dirstat),
+ 	__fsparam	(fs_param_is_string, "fsc",	Opt_fscache,
+ 			 fs_param_neg_with_no | fs_param_v_optional),
+ 	fsparam_flag_no ("ino32",			Opt_ino32),
+ 	fsparam_string	("mds_namespace",		Opt_mds_namespace),
+ 	fsparam_flag_no ("poolperm",			Opt_poolperm),
+ 	fsparam_flag_no ("quotadf",			Opt_quotadf),
+ 	fsparam_u32	("rasize",			Opt_rasize),
+ 	fsparam_flag_no ("rbytes",			Opt_rbytes),
+ 	fsparam_s32	("readdir_max_bytes",		Opt_readdir_max_bytes),
+ 	fsparam_s32	("readdir_max_entries",		Opt_readdir_max_entries),
++	fsparam_string	("recover_session",		Opt_recover_session),
+ 	fsparam_flag_no ("require_active_mds",		Opt_require_active_mds),
+ 	fsparam_u32	("rsize",			Opt_rsize),
+ 	fsparam_string	("snapdirname",			Opt_snapdirname),
+ 	fsparam_string	("source",			Opt_source),
+ 	fsparam_u32	("wsize",			Opt_wsize),
+ 	{}
  };
  
- static int parse_fsopt_token(char *c, void *private)
+ static const struct fs_parameter_description ceph_fs_parameters = {
+         .name           = "ceph",
+         .specs          = ceph_param_specs,
+ };
+ 
+ /*
+  * Parse the source parameter.  Distinguish the server list from the path.
+  * Internally we do not include the leading '/' in the path.
+  *
+  * The source will look like:
+  *     <server_spec>[,<server_spec>...]:[<path>]
+  * where
+  *     <server_spec> is <ip>[:<port>]
+  *     <path> is optional, but if present must begin with '/'
+  */
+ static int ceph_parse_source(struct fs_context *fc, struct fs_parameter *param)
  {
- 	struct ceph_mount_options *fsopt = private;
- 	substring_t argstr[MAX_OPT_ARGS];
- 	int token, intval, ret;
- 
- 	token = match_token((char *)c, fsopt_tokens, argstr);
- 	if (token < 0)
- 		return -EINVAL;
- 
- 	if (token < Opt_last_int) {
- 		ret = match_int(&argstr[0], &intval);
- 		if (ret < 0) {
- 			pr_err("bad option arg (not int) at '%s'\n", c);
- 			return ret;
+ 	struct ceph_config_context *ctx = fc->fs_private;
+ 	struct ceph_mount_options *fsopt = ctx->mount_options;
+ 	char *dev_name = param->string, *dev_name_end;
+ 	int ret;
+ 
+ 	dout("parse_mount_options %p, dev_name '%s'\n", fsopt, dev_name);
+ 
+ 	if (fc->source)
+ 		return invalf(fc, "Multiple sources specified");
+ 	if (!dev_name || !*dev_name)
+ 		return invalf(fc, "Empty source");
+ 	if (dev_name[0] == '/')
+ 		return invalf(fc, "Missing colon");
+ 
+ 	dev_name_end = strchr(dev_name + 1, '/');
+ 	if (dev_name_end) {
+ 		if (strlen(dev_name_end) > 1) {
+ 			kfree(fsopt->server_path);
+ 			fsopt->server_path = kstrdup(dev_name_end, GFP_KERNEL);
+ 			if (!fsopt->server_path)
+ 				return -ENOMEM;
  		}
- 		dout("got int token %d val %d\n", token, intval);
- 	} else if (token > Opt_last_int && token < Opt_last_string) {
- 		dout("got string token %d val %s\n", token,
- 		     argstr[0].from);
  	} else {
- 		dout("got token %d\n", token);
+ 		dev_name_end = dev_name + strlen(dev_name);
  	}
  
- 	switch (token) {
+ 	/* Trim off the path and the colon separator */
+ 	dev_name_end--;
+ 	if (*dev_name_end != ':')
+ 		return invalf(fc, "device name is missing path (no : separator in %s)\n",
+ 			      dev_name);
+ 	*dev_name_end = 0;
+ 
+ 	dout("device name '%s'\n", dev_name);
+ 	if (fsopt->server_path)
+ 		dout("server path '%s'\n", fsopt->server_path);
+ 
+ 	param->size = dev_name_end - dev_name;
+ 	ret = ceph_parse_server_specs(ctx->opt, fc,
+ 				      param->string, dev_name_end - dev_name);
+ 	if (ret == 0) {
+ 		fc->source = param->string;
+ 		param->string = NULL;
+ 	}
+ 
+ 	return 0;
+ }
+ 
+ static int ceph_parse_param(struct fs_context *fc, struct fs_parameter *param)
+ {
+ 	struct ceph_config_context *ctx = fc->fs_private;
+ 	struct ceph_mount_options *fsopt = ctx->mount_options;
+ 	struct fs_parse_result result;
+ 	int ret, opt;
+ 
+ 	ret = ceph_parse_option(ctx->opt, fc, param);
+ 	if (ret != -ENOPARAM)
+ 		return ret;
+ 
+ 	opt = fs_parse(fc, &ceph_fs_parameters, param, &result);
+ 	if (opt < 0)
+ 		return opt;
+ 
+ 	switch (opt) {
+ 	case Opt_source:
+ 		return ceph_parse_source(fc, param);
  	case Opt_snapdirname:
  		kfree(fsopt->snapdir_name);
- 		fsopt->snapdir_name = kstrndup(argstr[0].from,
- 					       argstr[0].to-argstr[0].from,
- 					       GFP_KERNEL);
- 		if (!fsopt->snapdir_name)
- 			return -ENOMEM;
+ 		fsopt->snapdir_name = param->string;
+ 		param->string = NULL;
  		break;
  	case Opt_mds_namespace:
  		kfree(fsopt->mds_namespace);
- 		fsopt->mds_namespace = kstrndup(argstr[0].from,
- 						argstr[0].to-argstr[0].from,
- 						GFP_KERNEL);
- 		if (!fsopt->mds_namespace)
- 			return -ENOMEM;
+ 		fsopt->mds_namespace = param->string;
+ 		param->string = NULL;
  		break;
 +	case Opt_recover_session:
- 		if (!strncmp(argstr[0].from, "no",
- 			     argstr[0].to - argstr[0].from)) {
++		if (result.negated) {
 +			fsopt->flags &= ~CEPH_MOUNT_OPT_CLEANRECOVER;
- 		} else if (!strncmp(argstr[0].from, "clean",
- 				    argstr[0].to - argstr[0].from)) {
- 			fsopt->flags |= CEPH_MOUNT_OPT_CLEANRECOVER;
 +		} else {
- 			return -EINVAL;
++			fsopt->flags |= CEPH_MOUNT_OPT_CLEANRECOVER;
 +		}
 +		break;
- 	case Opt_fscache_uniq:
- 		kfree(fsopt->fscache_uniq);
- 		fsopt->fscache_uniq = kstrndup(argstr[0].from,
- 					       argstr[0].to-argstr[0].from,
- 					       GFP_KERNEL);
- 		if (!fsopt->fscache_uniq)
- 			return -ENOMEM;
- 		fsopt->flags |= CEPH_MOUNT_OPT_FSCACHE;
- 		break;
- 		/* misc */
  	case Opt_wsize:
- 		if (intval < (int)PAGE_SIZE || intval > CEPH_MAX_WRITE_SIZE)
- 			return -EINVAL;
- 		fsopt->wsize = ALIGN(intval, PAGE_SIZE);
+ 		if (result.uint_32 < (int)PAGE_SIZE || result.uint_32 > CEPH_MAX_WRITE_SIZE)
+ 			goto invalid_value;
+ 		fsopt->wsize = ALIGN(result.uint_32, PAGE_SIZE);
  		break;
  	case Opt_rsize:
- 		if (intval < (int)PAGE_SIZE || intval > CEPH_MAX_READ_SIZE)
- 			return -EINVAL;
- 		fsopt->rsize = ALIGN(intval, PAGE_SIZE);
+ 		if (result.uint_32 < (int)PAGE_SIZE || result.uint_32 > CEPH_MAX_READ_SIZE)
+ 			goto invalid_value;
+ 		fsopt->rsize = ALIGN(result.uint_32, PAGE_SIZE);
  		break;
  	case Opt_rasize:
- 		if (intval < 0)
- 			return -EINVAL;
- 		fsopt->rasize = ALIGN(intval, PAGE_SIZE);
+ 		fsopt->rasize = ALIGN(result.uint_32, PAGE_SIZE);
  		break;
  	case Opt_caps_wanted_delay_min:
- 		if (intval < 1)
- 			return -EINVAL;
- 		fsopt->caps_wanted_delay_min = intval;
+ 		if (result.uint_32 < 1)
+ 			goto invalid_value;
+ 		fsopt->caps_wanted_delay_min = result.uint_32;
  		break;
  	case Opt_caps_wanted_delay_max:
- 		if (intval < 1)
- 			return -EINVAL;
- 		fsopt->caps_wanted_delay_max = intval;
+ 		if (result.uint_32 < 1)
+ 			goto invalid_value;
+ 		fsopt->caps_wanted_delay_max = result.uint_32;
  		break;
  	case Opt_caps_max:
- 		if (intval < 0)
- 			return -EINVAL;
- 		fsopt->caps_max = intval;
+ 		fsopt->caps_max = result.uint_32;
  		break;
  	case Opt_readdir_max_entries:
- 		if (intval < 1)
- 			return -EINVAL;
- 		fsopt->max_readdir = intval;
+ 		if (result.uint_32 < 1)
+ 			goto invalid_value;
+ 		fsopt->max_readdir = result.uint_32;
  		break;
  	case Opt_readdir_max_bytes:
- 		if (intval < (int)PAGE_SIZE && intval != 0)
- 			return -EINVAL;
- 		fsopt->max_readdir_bytes = intval;
+ 		if (result.uint_32 < (int)PAGE_SIZE && result.uint_32 != 0)
+ 			goto invalid_value;
+ 		fsopt->max_readdir_bytes = result.uint_32;
  		break;
  	case Opt_congestion_kb:
- 		if (intval < 1024) /* at least 1M */
- 			return -EINVAL;
- 		fsopt->congestion_kb = intval;
+ 		if (result.uint_32 < 1024) /* at least 1M */
+ 			goto invalid_value;
+ 		fsopt->congestion_kb = result.uint_32;
  		break;
  	case Opt_dirstat:
- 		fsopt->flags |= CEPH_MOUNT_OPT_DIRSTAT;
- 		break;
- 	case Opt_nodirstat:
- 		fsopt->flags &= ~CEPH_MOUNT_OPT_DIRSTAT;
+ 		if (!result.negated)
+ 			fsopt->flags |= CEPH_MOUNT_OPT_DIRSTAT;
+ 		else
+ 			fsopt->flags &= ~CEPH_MOUNT_OPT_DIRSTAT;
  		break;
  	case Opt_rbytes:
- 		fsopt->flags |= CEPH_MOUNT_OPT_RBYTES;
- 		break;
- 	case Opt_norbytes:
- 		fsopt->flags &= ~CEPH_MOUNT_OPT_RBYTES;
+ 		if (!result.negated)
+ 			fsopt->flags |= CEPH_MOUNT_OPT_RBYTES;
+ 		else
+ 			fsopt->flags &= ~CEPH_MOUNT_OPT_RBYTES;
  		break;
  	case Opt_asyncreaddir:
- 		fsopt->flags &= ~CEPH_MOUNT_OPT_NOASYNCREADDIR;
- 		break;
- 	case Opt_noasyncreaddir:
- 		fsopt->flags |= CEPH_MOUNT_OPT_NOASYNCREADDIR;
+ 		if (!result.negated)
+ 			fsopt->flags &= ~CEPH_MOUNT_OPT_NOASYNCREADDIR;
+ 		else
+ 			fsopt->flags |= CEPH_MOUNT_OPT_NOASYNCREADDIR;
  		break;
  	case Opt_dcache:
- 		fsopt->flags |= CEPH_MOUNT_OPT_DCACHE;
- 		break;
- 	case Opt_nodcache:
- 		fsopt->flags &= ~CEPH_MOUNT_OPT_DCACHE;
+ 		if (!result.negated)
+ 			fsopt->flags |= CEPH_MOUNT_OPT_DCACHE;
+ 		else
+ 			fsopt->flags &= ~CEPH_MOUNT_OPT_DCACHE;
  		break;
  	case Opt_ino32:
- 		fsopt->flags |= CEPH_MOUNT_OPT_INO32;
- 		break;
- 	case Opt_noino32:
- 		fsopt->flags &= ~CEPH_MOUNT_OPT_INO32;
+ 		if (!result.negated)
+ 			fsopt->flags |= CEPH_MOUNT_OPT_INO32;
+ 		else
+ 			fsopt->flags &= ~CEPH_MOUNT_OPT_INO32;
  		break;
+ 
  	case Opt_fscache:
- 		fsopt->flags |= CEPH_MOUNT_OPT_FSCACHE;
- 		kfree(fsopt->fscache_uniq);
- 		fsopt->fscache_uniq = NULL;
- 		break;
- 	case Opt_nofscache:
- 		fsopt->flags &= ~CEPH_MOUNT_OPT_FSCACHE;
  		kfree(fsopt->fscache_uniq);
  		fsopt->fscache_uniq = NULL;
+ 		if (result.negated) {
+ 			fsopt->flags &= ~CEPH_MOUNT_OPT_FSCACHE;
+ 		} else {
+ 			fsopt->flags |= CEPH_MOUNT_OPT_FSCACHE;
+ 			fsopt->fscache_uniq = param->string;
+ 			param->string = NULL;
+ 		}
  		break;
+ 
  	case Opt_poolperm:
- 		fsopt->flags &= ~CEPH_MOUNT_OPT_NOPOOLPERM;
- 		break;
- 	case Opt_nopoolperm:
- 		fsopt->flags |= CEPH_MOUNT_OPT_NOPOOLPERM;
+ 		if (!result.negated)
+ 			fsopt->flags &= ~CEPH_MOUNT_OPT_NOPOOLPERM;
+ 		else
+ 			fsopt->flags |= CEPH_MOUNT_OPT_NOPOOLPERM;
  		break;
  	case Opt_require_active_mds:
- 		fsopt->flags &= ~CEPH_MOUNT_OPT_MOUNTWAIT;
- 		break;
- 	case Opt_norequire_active_mds:
- 		fsopt->flags |= CEPH_MOUNT_OPT_MOUNTWAIT;
+ 		if (!result.negated)
+ 			fsopt->flags &= ~CEPH_MOUNT_OPT_MOUNTWAIT;
+ 		else
+ 			fsopt->flags |= CEPH_MOUNT_OPT_MOUNTWAIT;
  		break;
  	case Opt_quotadf:
- 		fsopt->flags &= ~CEPH_MOUNT_OPT_NOQUOTADF;
- 		break;
- 	case Opt_noquotadf:
- 		fsopt->flags |= CEPH_MOUNT_OPT_NOQUOTADF;
+ 		if (!result.negated)
+ 			fsopt->flags &= ~CEPH_MOUNT_OPT_NOQUOTADF;
+ 		else
+ 			fsopt->flags |= CEPH_MOUNT_OPT_NOQUOTADF;
  		break;
  	case Opt_copyfrom:
- 		fsopt->flags &= ~CEPH_MOUNT_OPT_NOCOPYFROM;
- 		break;
- 	case Opt_nocopyfrom:
- 		fsopt->flags |= CEPH_MOUNT_OPT_NOCOPYFROM;
+ 		if (!result.negated)
+ 			fsopt->flags &= ~CEPH_MOUNT_OPT_NOCOPYFROM;
+ 		else
+ 			fsopt->flags |= CEPH_MOUNT_OPT_NOCOPYFROM;
  		break;
- #ifdef CONFIG_CEPH_FS_POSIX_ACL
  	case Opt_acl:
- 		fsopt->sb_flags |= SB_POSIXACL;
- 		break;
+ 		if (!result.negated) {
+ #ifdef CONFIG_CEPH_FS_POSIX_ACL
+ 			fc->sb_flags |= SB_POSIXACL;
+ #else
+ 			return invalf(fc, "POSIX ACL support is disabled");
  #endif
- 	case Opt_noacl:
- 		fsopt->sb_flags &= ~SB_POSIXACL;
+ 		} else {
+ 			fc->sb_flags &= ~SB_POSIXACL;
+ 		}
  		break;
  	default:
- 		BUG_ON(token);
+ 		BUG();
  	}
  	return 0;
+ 
+ invalid_value:
+ 	return invalf(fc, "ceph: Invalid value for %s", param->key);
  }
  
  static void destroy_mount_options(struct ceph_mount_options *args)
@@@ -996,17 -924,11 +925,11 @@@ static int ceph_set_super(struct super_
  	s->s_d_op = &ceph_dentry_ops;
  	s->s_export_op = &ceph_export_ops;
  
 -	s->s_time_gran = 1000;  /* 1000 ns == 1 us */
 +	s->s_time_gran = 1;
  
- 	ret = set_anon_super(s, NULL);  /* what is that second arg for? */
+ 	ret = set_anon_super_fc(s, fc);
  	if (ret != 0)
- 		goto fail;
- 
- 	return ret;
- 
- fail:
- 	s->s_fs_info = NULL;
- 	fsc->sb = NULL;
+ 		fsc->sb = NULL;
  	return ret;
  }