linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* linux-next: manual merge of the vfs tree with the ceph tree
@ 2019-08-29  1:25 Stephen Rothwell
  0 siblings, 0 replies; 6+ messages in thread
From: Stephen Rothwell @ 2019-08-29  1:25 UTC (permalink / raw)
  To: Al Viro, Sage Weil
  Cc: Linux Next Mailing List, Linux Kernel Mailing List,
	David Howells, Yan, Zheng, Ilya Dryomov

[-- Attachment #1: Type: text/plain, Size: 15318 bytes --]

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:

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

from the vfs tree.

I fixed it up (Thanks to Al for the supplied merge resolution, see
below) 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,6be1e75e70c5..000000000000
--- a/fs/ceph/super.c
+++ b/fs/ceph/super.c
@@@ -138,266 -139,269 +139,279 @@@ enum 
  	Opt_readdir_max_entries,
  	Opt_readdir_max_bytes,
  	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_dcache,
- 	Opt_nodcache,
  	Opt_ino32,
- 	Opt_noino32,
  	Opt_fscache,
- 	Opt_nofscache,
  	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_source,
  };
  
- 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_string	("recover_session",		Opt_recover_session),
+ 	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_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 const struct fs_parameter_description ceph_fs_parameters = {
+         .name           = "ceph",
+         .specs          = ceph_param_specs,
  };
  
- static int parse_fsopt_token(char *c, void *private)
+ /*
+  * 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);
+ 	}
+ 
+ 	/* 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;
  	}
  
- 	switch (token) {
+ 	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 (!strcmp(param->string, "no"))
 +			fsopt->flags &= ~CEPH_MOUNT_OPT_CLEANRECOVER;
- 		} else if (!strncmp(argstr[0].from, "clean",
- 				    argstr[0].to - argstr[0].from)) {
++		else if (!strcmp(param->string, "clean"))
 +			fsopt->flags |= CEPH_MOUNT_OPT_CLEANRECOVER;
- 		} else {
- 			return -EINVAL;
- 		}
- 		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;
++		else
++			goto invalid_value;
 +		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)

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* linux-next: manual merge of the vfs tree with the ceph tree
@ 2019-08-27  1:06 Stephen Rothwell
  0 siblings, 0 replies; 6+ messages in thread
From: Stephen Rothwell @ 2019-08-27  1:06 UTC (permalink / raw)
  To: Al Viro, Sage Weil
  Cc: Linux Next Mailing List, Linux Kernel Mailing List,
	David Howells, Yan, Zheng, Ilya Dryomov

[-- Attachment #1: Type: text/plain, Size: 16305 bytes --]

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;
  }
  

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* linux-next: manual merge of the vfs tree with the ceph tree
@ 2018-10-29  1:16 Stephen Rothwell
  0 siblings, 0 replies; 6+ messages in thread
From: Stephen Rothwell @ 2018-10-29  1:16 UTC (permalink / raw)
  To: Al Viro, Sage Weil
  Cc: Linux-Next Mailing List, Linux Kernel Mailing List, Yan, Zheng,
	Ilya Dryomov, David Howells

[-- Attachment #1: Type: text/plain, Size: 4915 bytes --]

Hi Al,

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

  fs/ceph/file.c

between commit:

  fce7a9744bdf ("ceph: refactor ceph_sync_read()")

from the ceph tree and commit:

  00e23707442a ("iov_iter: Use accessor function")

from the vfs tree.

I fixed it up (see below) 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/file.c
index f788496fafcc,5dd433aa9b23..000000000000
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@@ -594,103 -658,48 +594,103 @@@ static ssize_t ceph_sync_read(struct ki
  	if (ret < 0)
  		return ret;
  
 -	if (unlikely(iov_iter_is_pipe(to))) {
 +	ret = 0;
 +	while ((len = iov_iter_count(to)) > 0) {
 +		struct ceph_osd_request *req;
 +		struct page **pages;
 +		int num_pages;
  		size_t page_off;
 -		ret = iov_iter_get_pages_alloc(to, &pages, len,
 -					       &page_off);
 -		if (ret <= 0)
 -			return -ENOMEM;
 -		num_pages = DIV_ROUND_UP(ret + page_off, PAGE_SIZE);
 +		u64 i_size;
 +		bool more;
 +
 +		req = ceph_osdc_new_request(osdc, &ci->i_layout,
 +					ci->i_vino, off, &len, 0, 1,
 +					CEPH_OSD_OP_READ, CEPH_OSD_FLAG_READ,
 +					NULL, ci->i_truncate_seq,
 +					ci->i_truncate_size, false);
 +		if (IS_ERR(req)) {
 +			ret = PTR_ERR(req);
 +			break;
 +		}
 +
 +		more = len < iov_iter_count(to);
  
- 		if (unlikely(to->type & ITER_PIPE)) {
 -		ret = striped_read(inode, off, ret, pages, num_pages,
 -				   page_off, checkeof);
 -		if (ret > 0) {
 -			iov_iter_advance(to, ret);
 -			off += ret;
++		if (unlikely(iov_iter_is_pipe(to))) {
 +			ret = iov_iter_get_pages_alloc(to, &pages, len,
 +						       &page_off);
 +			if (ret <= 0) {
 +				ceph_osdc_put_request(req);
 +				ret = -ENOMEM;
 +				break;
 +			}
 +			num_pages = DIV_ROUND_UP(ret + page_off, PAGE_SIZE);
 +			if (ret < len) {
 +				len = ret;
 +				osd_req_op_extent_update(req, 0, len);
 +				more = false;
 +			}
  		} else {
 -			iov_iter_advance(to, 0);
 +			num_pages = calc_pages_for(off, len);
 +			page_off = off & ~PAGE_MASK;
 +			pages = ceph_alloc_page_vector(num_pages, GFP_KERNEL);
 +			if (IS_ERR(pages)) {
 +				ceph_osdc_put_request(req);
 +				ret = PTR_ERR(pages);
 +				break;
 +			}
  		}
 -		ceph_put_page_vector(pages, num_pages, false);
 -	} else {
 -		num_pages = calc_pages_for(off, len);
 -		pages = ceph_alloc_page_vector(num_pages, GFP_KERNEL);
 -		if (IS_ERR(pages))
 -			return PTR_ERR(pages);
 -
 -		ret = striped_read(inode, off, len, pages, num_pages,
 -				   (off & ~PAGE_MASK), checkeof);
 -		if (ret > 0) {
 -			int l, k = 0;
 -			size_t left = ret;
 -
 -			while (left) {
 -				size_t page_off = off & ~PAGE_MASK;
 -				size_t copy = min_t(size_t, left,
 -						    PAGE_SIZE - page_off);
 -				l = copy_page_to_iter(pages[k++], page_off,
 -						      copy, to);
 -				off += l;
 -				left -= l;
 -				if (l < copy)
 +
 +		osd_req_op_extent_osd_data_pages(req, 0, pages, len, page_off,
 +						 false, false);
 +		ret = ceph_osdc_start_request(osdc, req, false);
 +		if (!ret)
 +			ret = ceph_osdc_wait_request(osdc, req);
 +		ceph_osdc_put_request(req);
 +
 +		i_size = i_size_read(inode);
 +		dout("sync_read %llu~%llu got %zd i_size %llu%s\n",
 +		     off, len, ret, i_size, (more ? " MORE" : ""));
 +
 +		if (ret == -ENOENT)
 +			ret = 0;
 +		if (ret >= 0 && ret < len && (off + ret < i_size)) {
 +			int zlen = min(len - ret, i_size - off - ret);
 +			int zoff = page_off + ret;
 +			dout("sync_read zero gap %llu~%llu\n",
 +                             off + ret, off + ret + zlen);
 +			ceph_zero_page_vector_range(zoff, zlen, pages);
 +			ret += zlen;
 +		}
 +
- 		if (unlikely(to->type & ITER_PIPE)) {
++		if (unlikely(iov_iter_is_pipe(to))) {
 +			if (ret > 0) {
 +				iov_iter_advance(to, ret);
 +				off += ret;
 +			} else {
 +				iov_iter_advance(to, 0);
 +			}
 +			ceph_put_page_vector(pages, num_pages, false);
 +		} else {
 +			int idx = 0;
 +			size_t left = ret > 0 ? ret : 0;
 +			while (left > 0) {
 +				size_t len, copied;
 +				page_off = off & ~PAGE_MASK;
 +				len = min_t(size_t, left, PAGE_SIZE - page_off);
 +				copied = copy_page_to_iter(pages[idx++],
 +							   page_off, len, to);
 +				off += copied;
 +				left -= copied;
 +				if (copied < len) {
 +					ret = -EFAULT;
  					break;
 +				}
  			}
 +			ceph_release_page_vector(pages, num_pages);
  		}
 -		ceph_release_page_vector(pages, num_pages);
 +
 +		if (ret <= 0 || off >= i_size || !more)
 +			break;
  	}
  
  	if (off > iocb->ki_pos) {

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: linux-next: manual merge of the vfs tree with the ceph tree
  2015-06-26  8:21 ` Ilya Dryomov
@ 2015-06-26  8:33   ` Stephen Rothwell
  0 siblings, 0 replies; 6+ messages in thread
From: Stephen Rothwell @ 2015-06-26  8:33 UTC (permalink / raw)
  To: Ilya Dryomov; +Cc: Al Viro, Sage Weil, linux-next, linux-kernel, Yan, Zheng

[-- Attachment #1: Type: text/plain, Size: 1487 bytes --]

Hi Ilya,

On Fri, 26 Jun 2015 11:21:52 +0300 Ilya Dryomov <idryomov@gmail.com> wrote:
>
> > Sage: that ceph tree commit has no Signed-off-by from its
> > committer :-(  The same is true for almost all the commits in the ceph
> > tree ... and the committer (Ilya) is not listed as a maintainer of that
> > tree ... and its on github :-(
> 
> Well, it has Signed-off-by from a person who is listed as a maintainer
> of fs/ceph (Zheng).  We share the same tree for three components: rbd
> (drivers/block/rbd.c), cephfs (fs/ceph) and libceph (net/ceph) which is
> used by both rbd and cephfs (we should probably split libceph into its
> own MAINTAINERS entry).  The volume of commits is not that high and
> we prefer to not clutter our 30-40 commits per cycle with a bunch of
> merges, so when one of us rebases the committer stamp gets wiped.

Then the person who rebases it must add a Signed-off-by line since they
are then on the handling path from the author to Linus.

> As for github, is that a bad thing?  ceph-client.git is certainly not
> the only github tree in linux-next.

Yeah, it just means that I am a bit more suspicious of things there.
You are *not* listed in my contacts for the ceph tree not are you
listed in the MAINTAINERS file for that tree.

Also the tree listed in MAINTAINERS is:

T:      git git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client.git

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: linux-next: manual merge of the vfs tree with the ceph tree
  2015-06-26  1:17 Stephen Rothwell
@ 2015-06-26  8:21 ` Ilya Dryomov
  2015-06-26  8:33   ` Stephen Rothwell
  0 siblings, 1 reply; 6+ messages in thread
From: Ilya Dryomov @ 2015-06-26  8:21 UTC (permalink / raw)
  To: Stephen Rothwell; +Cc: Al Viro, Sage Weil, linux-next, linux-kernel, Yan, Zheng

On Fri, Jun 26, 2015 at 4:17 AM, Stephen Rothwell <sfr@canb.auug.org.au> wrote:
> Hi Al,
>
> Today's linux-next merge of the vfs tree got a conflict in:
>
>   fs/ceph/dir.c
>
> between commit:
>
>   fdd4e15838e5 ("ceph: rework dcache readdir")
>
> from the ceph tree and commit:
>
>   dc3f4198eac1 ("make simple_positive() public")
>
> from the vfs tree.
>
> I fixed it up (I think - see below) and can carry the fix as necessary (no action
> is required).
>
> Sage: that ceph tree commit has no Signed-off-by from its
> committer :-(  The same is true for almost all the commits in the ceph
> tree ... and the committer (Ilya) is not listed as a maintainer of that
> tree ... and its on github :-(

Well, it has Signed-off-by from a person who is listed as a maintainer
of fs/ceph (Zheng).  We share the same tree for three components: rbd
(drivers/block/rbd.c), cephfs (fs/ceph) and libceph (net/ceph) which is
used by both rbd and cephfs (we should probably split libceph into its
own MAINTAINERS entry).  The volume of commits is not that high and
we prefer to not clutter our 30-40 commits per cycle with a bunch of
merges, so when one of us rebases the committer stamp gets wiped.

As for github, is that a bad thing?  ceph-client.git is certainly not
the only github tree in linux-next.

Thanks,

                Ilya

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

* linux-next: manual merge of the vfs tree with the ceph tree
@ 2015-06-26  1:17 Stephen Rothwell
  2015-06-26  8:21 ` Ilya Dryomov
  0 siblings, 1 reply; 6+ messages in thread
From: Stephen Rothwell @ 2015-06-26  1:17 UTC (permalink / raw)
  To: Al Viro, Sage Weil; +Cc: linux-next, linux-kernel, Yan, Zheng, Ilya Dryomov

[-- Attachment #1: Type: text/plain, Size: 6626 bytes --]

Hi Al,

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

  fs/ceph/dir.c

between commit:

  fdd4e15838e5 ("ceph: rework dcache readdir")

from the ceph tree and commit:

  dc3f4198eac1 ("make simple_positive() public")

from the vfs tree.

I fixed it up (I think - see below) and can carry the fix as necessary (no action
is required).

Sage: that ceph tree commit has no Signed-off-by from its
committer :-(  The same is true for almost all the commits in the ceph
tree ... and the committer (Ilya) is not listed as a maintainer of that
tree ... and its on github :-(
-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

diff --cc fs/ceph/dir.c
index 9314b4ea2375,edbb8da02a6a..000000000000
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@@ -144,110 -123,101 +144,110 @@@ static int __dcache_readdir(struct fil
  	struct ceph_file_info *fi = file->private_data;
  	struct dentry *parent = file->f_path.dentry;
  	struct inode *dir = d_inode(parent);
 -	struct list_head *p;
 -	struct dentry *dentry, *last;
 +	struct dentry *dentry, *last = NULL;
  	struct ceph_dentry_info *di;
 +	unsigned nsize = PAGE_CACHE_SIZE / sizeof(struct dentry *);
  	int err = 0;
 +	loff_t ptr_pos = 0;
 +	struct ceph_readdir_cache_control cache_ctl = {};
  
 -	/* claim ref on last dentry we returned */
 -	last = fi->dentry;
 -	fi->dentry = NULL;
 -
 -	dout("__dcache_readdir %p v%u at %llu (last %p)\n",
 -	     dir, shared_gen, ctx->pos, last);
 +	dout("__dcache_readdir %p v%u at %llu\n", dir, shared_gen, ctx->pos);
  
 -	spin_lock(&parent->d_lock);
 -
 -	/* start at beginning? */
 -	if (ctx->pos == 2 || last == NULL ||
 -	    fpos_cmp(ctx->pos, ceph_dentry(last)->offset) < 0) {
 -		if (list_empty(&parent->d_subdirs))
 -			goto out_unlock;
 -		p = parent->d_subdirs.prev;
 -		dout(" initial p %p/%p\n", p->prev, p->next);
 -	} else {
 -		p = last->d_child.prev;
 +	/* we can calculate cache index for the first dirfrag */
 +	if (ceph_frag_is_leftmost(fpos_frag(ctx->pos))) {
 +		cache_ctl.index = fpos_off(ctx->pos) - 2;
 +		BUG_ON(cache_ctl.index < 0);
 +		ptr_pos = cache_ctl.index * sizeof(struct dentry *);
  	}
  
 -more:
 -	dentry = list_entry(p, struct dentry, d_child);
 -	di = ceph_dentry(dentry);
 -	while (1) {
 -		dout(" p %p/%p %s d_subdirs %p/%p\n", p->prev, p->next,
 -		     d_unhashed(dentry) ? "!hashed" : "hashed",
 -		     parent->d_subdirs.prev, parent->d_subdirs.next);
 -		if (p == &parent->d_subdirs) {
 +	while (true) {
 +		pgoff_t pgoff;
 +		bool emit_dentry;
 +
 +		if (ptr_pos >= i_size_read(dir)) {
  			fi->flags |= CEPH_F_ATEND;
 -			goto out_unlock;
 +			err = 0;
 +			break;
 +		}
 +
 +		err = -EAGAIN;
 +		pgoff = ptr_pos >> PAGE_CACHE_SHIFT;
 +		if (!cache_ctl.page || pgoff != page_index(cache_ctl.page)) {
 +			ceph_readdir_cache_release(&cache_ctl);
 +			cache_ctl.page = find_lock_page(&dir->i_data, pgoff);
 +			if (!cache_ctl.page) {
 +				dout(" page %lu not found\n", pgoff);
 +				break;
 +			}
 +			/* reading/filling the cache are serialized by
 +			 * i_mutex, no need to use page lock */
 +			unlock_page(cache_ctl.page);
 +			cache_ctl.dentries = kmap(cache_ctl.page);
  		}
 -		spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
 +
 +		rcu_read_lock();
 +		spin_lock(&parent->d_lock);
 +		/* check i_size again here, because empty directory can be
 +		 * marked as complete while not holding the i_mutex. */
 +		if (ceph_dir_is_complete_ordered(dir) &&
 +		    ptr_pos < i_size_read(dir))
 +			dentry = cache_ctl.dentries[cache_ctl.index % nsize];
 +		else
 +			dentry = NULL;
 +		spin_unlock(&parent->d_lock);
 +		if (dentry && !lockref_get_not_dead(&dentry->d_lockref))
 +			dentry = NULL;
 +		rcu_read_unlock();
 +		if (!dentry)
 +			break;
 +
 +		emit_dentry = false;
 +		di = ceph_dentry(dentry);
 +		spin_lock(&dentry->d_lock);
  		if (di->lease_shared_gen == shared_gen &&
- 		    d_really_is_positive(dentry) &&
+ 		    simple_positive(dentry) &&
  		    ceph_snap(d_inode(dentry)) != CEPH_SNAPDIR &&
  		    ceph_ino(d_inode(dentry)) != CEPH_INO_CEPH &&
 -		    fpos_cmp(ctx->pos, di->offset) <= 0)
 -			break;
 -		dout(" skipping %p %pd at %llu (%llu)%s%s\n", dentry,
 -		     dentry, di->offset,
 -		     ctx->pos, d_unhashed(dentry) ? " unhashed" : "",
 -		     !d_inode(dentry) ? " null" : "");
 +		    fpos_cmp(ctx->pos, di->offset) <= 0) {
 +			emit_dentry = true;
 +		}
  		spin_unlock(&dentry->d_lock);
 -		p = p->prev;
 -		dentry = list_entry(p, struct dentry, d_child);
 -		di = ceph_dentry(dentry);
 -	}
 -
 -	dget_dlock(dentry);
 -	spin_unlock(&dentry->d_lock);
 -	spin_unlock(&parent->d_lock);
  
 -	/* make sure a dentry wasn't dropped while we didn't have parent lock */
 -	if (!ceph_dir_is_complete_ordered(dir)) {
 -		dout(" lost dir complete on %p; falling back to mds\n", dir);
 -		dput(dentry);
 -		err = -EAGAIN;
 -		goto out;
 -	}
 +		if (emit_dentry) {
 +			dout(" %llu (%llu) dentry %p %pd %p\n", di->offset, ctx->pos,
 +			     dentry, dentry, d_inode(dentry));
 +			ctx->pos = di->offset;
 +			if (!dir_emit(ctx, dentry->d_name.name,
 +				      dentry->d_name.len,
 +				      ceph_translate_ino(dentry->d_sb,
 +							 d_inode(dentry)->i_ino),
 +				      d_inode(dentry)->i_mode >> 12)) {
 +				dput(dentry);
 +				err = 0;
 +				break;
 +			}
 +			ctx->pos++;
  
 -	dout(" %llu (%llu) dentry %p %pd %p\n", di->offset, ctx->pos,
 -	     dentry, dentry, d_inode(dentry));
 -	if (!dir_emit(ctx, dentry->d_name.name,
 -		      dentry->d_name.len,
 -		      ceph_translate_ino(dentry->d_sb, d_inode(dentry)->i_ino),
 -		      d_inode(dentry)->i_mode >> 12)) {
 -		if (last) {
 -			/* remember our position */
 -			fi->dentry = last;
 -			fi->next_offset = fpos_off(di->offset);
 +			if (last)
 +				dput(last);
 +			last = dentry;
 +		} else {
 +			dput(dentry);
  		}
 -		dput(dentry);
 -		return 0;
 -	}
 -
 -	ctx->pos = di->offset + 1;
  
 -	if (last)
 -		dput(last);
 -	last = dentry;
 -
 -	spin_lock(&parent->d_lock);
 -	p = p->prev;	/* advance to next dentry */
 -	goto more;
 -
 -out_unlock:
 -	spin_unlock(&parent->d_lock);
 -out:
 -	if (last)
 +		cache_ctl.index++;
 +		ptr_pos += sizeof(struct dentry *);
 +	}
 +	ceph_readdir_cache_release(&cache_ctl);
 +	if (last) {
 +		int ret;
 +		di = ceph_dentry(last);
 +		ret = note_last_dentry(fi, last->d_name.name, last->d_name.len,
 +				       fpos_off(di->offset) + 1);
 +		if (ret < 0)
 +			err = ret;
  		dput(last);
 +	}
  	return err;
  }
  

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

end of thread, other threads:[~2019-08-29  1:25 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-29  1:25 linux-next: manual merge of the vfs tree with the ceph tree Stephen Rothwell
  -- strict thread matches above, loose matches on Subject: below --
2019-08-27  1:06 Stephen Rothwell
2018-10-29  1:16 Stephen Rothwell
2015-06-26  1:17 Stephen Rothwell
2015-06-26  8:21 ` Ilya Dryomov
2015-06-26  8:33   ` Stephen Rothwell

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).