All of lore.kernel.org
 help / color / mirror / Atom feed
From: NeilBrown <neilb@suse.de>
To: lustre-devel@lists.lustre.org
Subject: [lustre-devel] [PATCH 043/151] lustre: lov: add MDT target to the LOV device
Date: Tue, 01 Oct 2019 10:33:52 +1000	[thread overview]
Message-ID: <87wodp718v.fsf@notabene.neil.brown.name> (raw)
In-Reply-To: <1569869810-23848-44-git-send-email-jsimmons@infradead.org>

On Mon, Sep 30 2019, James Simmons wrote:

> From: Mikhal Pershin <mpershin@whamcloud.com>
>
> MDC becomes LOV target like OSC for Data-on-MDT needs.
> Patch does the following:
> - new composite layout entry type is added - LLT_DOM to
> describe Data-on-MDT striping.
> - LOV process config log and checks for MDC targets organizing
> them separately from OSCs
> - LOV operations are changed where needed to understand new layout
> entry type
>
> WC-bug-id: https://jira.whamcloud.com/browse/LU-3285
> Lustre-commit: 8b352709a66f ("LU-3285 lov: add MDT target to the LOV device")
> Signed-off-by: Mikhal Pershin <mpershin@whamcloud.com>
> Reviewed-on: https://review.whamcloud.com/28010
> Reviewed-by: Jinshan Xiong <jinshan.xiong@gmail.com>
> Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
> Signed-off-by: James Simmons <jsimmons@infradead.org>

Hi James,
 you appear to have merged (most of) my
   lustre: use wait_event() in lov_subobject_kill()
 patch into this.  What that intentional?

NeilBrown

> ---
>  fs/lustre/include/obd.h                 |   8 +
>  fs/lustre/lmv/lmv_obd.c                 |   2 +-
>  fs/lustre/lov/lov_cl_internal.h         |  76 +++-
>  fs/lustre/lov/lov_dev.c                 | 276 +++++++++++--
>  fs/lustre/lov/lov_ea.c                  |  20 +-
>  fs/lustre/lov/lov_internal.h            |   7 +
>  fs/lustre/lov/lov_io.c                  |   6 +-
>  fs/lustre/lov/lov_obd.c                 |  39 +-
>  fs/lustre/lov/lov_object.c              | 696 +++++++++++++++++++++-----------
>  fs/lustre/lov/lov_offset.c              |   3 +
>  fs/lustre/mdc/mdc_request.c             |   7 +-
>  fs/lustre/obdclass/obd_config.c         |  36 +-
>  fs/lustre/ptlrpc/wiretest.c             |   4 +-
>  include/uapi/linux/lustre/lustre_user.h |   2 +-
>  14 files changed, 883 insertions(+), 299 deletions(-)
>
> diff --git a/fs/lustre/include/obd.h b/fs/lustre/include/obd.h
> index 9514260..baa97a9 100644
> --- a/fs/lustre/include/obd.h
> +++ b/fs/lustre/include/obd.h
> @@ -381,6 +381,11 @@ struct lov_tgt_desc {
>  				ltd_reap:1;  /* should this target be deleted */
>  };
>  
> +struct lov_md_tgt_desc {
> +	struct obd_device *lmtd_mdc;
> +	u32		   lmtd_index;
> +};
> +
>  struct lov_obd {
>  	struct lov_desc		desc;
>  	struct lov_tgt_desc   **lov_tgts;	/* sparse array */
> @@ -403,10 +408,13 @@ struct lov_obd {
>  	struct rw_semaphore     lov_notify_lock;
>  
>  	struct kobject	       *lov_tgts_kobj;
> +	/* Data-on-MDT: MDC array */
> +	struct lov_md_tgt_desc	*lov_mdc_tgts;
>  };
>  
>  struct lmv_tgt_desc {
>  	struct obd_uuid		ltd_uuid;
> +	struct obd_device	*ltd_obd;
>  	struct obd_export      *ltd_exp;
>  	u32			ltd_idx;
>  	struct mutex		ltd_fid_mutex;
> diff --git a/fs/lustre/lmv/lmv_obd.c b/fs/lustre/lmv/lmv_obd.c
> index bcbda30..aabd043 100644
> --- a/fs/lustre/lmv/lmv_obd.c
> +++ b/fs/lustre/lmv/lmv_obd.c
> @@ -389,7 +389,7 @@ static int lmv_add_target(struct obd_device *obd, struct obd_uuid *uuidp,
>  
>  	if ((index < lmv->tgts_size) && lmv->tgts[index]) {
>  		tgt = lmv->tgts[index];
> -		CERROR("%s: UUID %s already assigned at LOV target index %d: rc = %d\n",
> +		CERROR("%s: UUID %s already assigned at LMV target index %d: rc = %d\n",
>  		       obd->obd_name,
>  		       obd_uuid2str(&tgt->ltd_uuid), index, -EEXIST);
>  		mutex_unlock(&lmv->lmv_init_mutex);
> diff --git a/fs/lustre/lov/lov_cl_internal.h b/fs/lustre/lov/lov_cl_internal.h
> index 22ef7b2..069b30e 100644
> --- a/fs/lustre/lov/lov_cl_internal.h
> +++ b/fs/lustre/lov/lov_cl_internal.h
> @@ -91,6 +91,12 @@ enum lov_device_flags {
>   * Upper half.
>   */
>  
> +/* Data-on-MDT array item in lov_device::ld_md_tgts[] */
> +struct lovdom_device {
> +	struct cl_device	*ldm_mdc;
> +	int			 ldm_idx;
> +};
> +
>  struct lov_device {
>  	/*
>  	 * XXX Locking of lov-private data is missing.
> @@ -101,6 +107,13 @@ struct lov_device {
>  	u32			ld_target_nr;
>  	struct lovsub_device  **ld_target;
>  	u32			ld_flags;
> +
> +	/* Data-on-MDT devices */
> +	u32			  ld_md_tgts_nr;
> +	struct lovdom_device	 *ld_md_tgts;
> +	struct obd_device	 *ld_lmv;
> +	/* LU site for subdevices */
> +	struct lu_site		  ld_site;
>  };
>  
>  /**
> @@ -129,6 +142,34 @@ static inline char *llt2str(enum lov_layout_type llt)
>  	return "";
>  }
>  
> +/**
> + * Return lov_layout_entry_type associated with a given composite layout
> + * entry.
> + */
> +static inline u32 lov_entry_type(struct lov_stripe_md_entry *lsme)
> +{
> +	if ((lov_pattern(lsme->lsme_pattern) == LOV_PATTERN_RAID0) ||
> +	    (lov_pattern(lsme->lsme_pattern) == LOV_PATTERN_MDT))
> +		return lov_pattern(lsme->lsme_pattern);
> +	return 0;
> +}
> +
> +struct lov_layout_entry;
> +struct lov_object;
> +struct lov_lock_sub;
> +
> +struct lov_comp_layout_entry_ops {
> +	int (*lco_init)(const struct lu_env *env, struct lov_device *dev,
> +			struct lov_object *lov, unsigned int index,
> +			const struct cl_object_conf *conf,
> +			struct lov_layout_entry *lle);
> +	void (*lco_fini)(const struct lu_env *env,
> +			 struct lov_layout_entry *lle);
> +	int  (*lco_getattr)(const struct lu_env *env, struct lov_object *obj,
> +			    unsigned int index, struct lov_layout_entry *lle,
> +			    struct cl_attr **attr);
> +};
> +
>  struct lov_layout_raid0 {
>  	unsigned int		lo_nr;
>  	/**
> @@ -165,6 +206,25 @@ struct lov_layout_raid0 {
>  	struct cl_attr		lo_attr;
>  };
>  
> +struct lov_layout_dom {
> +	/* keep this always at first place so DOM layout entry
> +	 * can be addressed also as RAID0 after initialization.
> +	 */
> +	struct lov_layout_raid0 lo_dom_r0;
> +	struct lovsub_object	*lo_dom;
> +	struct lov_oinfo	*lo_loi;
> +};
> +
> +struct lov_layout_entry {
> +	u32					lle_type;
> +	struct lu_extent			lle_extent;
> +	struct lov_comp_layout_entry_ops	*lle_comp_ops;
> +	union {
> +		struct lov_layout_raid0		lle_raid0;
> +		struct lov_layout_dom		lle_dom;
> +	};
> +};
> +
>  /**
>   * lov-specific file state.
>   *
> @@ -220,13 +280,10 @@ struct lov_object {
>  		} released;
>  		struct lov_layout_composite {
>  			/**
> -			 * Current valid entry count of lo_entries.
> +			 * Current valid entry count of entries.
>  			 */
>  			unsigned int lo_entry_count;
> -			struct lov_layout_entry {
> -				struct lu_extent lle_extent;
> -				struct lov_layout_raid0 lle_raid0;
> -			} *lo_entries;
> +			struct lov_layout_entry *lo_entries;
>  		} composite;
>  	} u;
>  	/**
> @@ -633,6 +690,15 @@ static inline struct lov_thread_info *lov_env_info(const struct lu_env *env)
>  	return info;
>  }
>  
> +static inline struct lov_layout_entry *lov_entry(struct lov_object *lov, int i)
> +{
> +	LASSERT(lov->lo_type == LLT_COMP);
> +	LASSERTF(i < lov->u.composite.lo_entry_count,
> +		 "entry %d entry_count %d", i, lov->u.composite.lo_entry_count);
> +
> +	return &lov->u.composite.lo_entries[i];
> +}
> +
>  static inline struct lov_layout_raid0 *lov_r0(struct lov_object *lov, int i)
>  {
>  	LASSERT(lov->lo_type == LLT_COMP);
> diff --git a/fs/lustre/lov/lov_dev.c b/fs/lustre/lov/lov_dev.c
> index a55b3f9..5ddf49a 100644
> --- a/fs/lustre/lov/lov_dev.c
> +++ b/fs/lustre/lov/lov_dev.c
> @@ -146,23 +146,55 @@ struct lu_context_key lov_session_key = {
>  /* type constructor/destructor: lov_type_{init,fini,start,stop}() */
>  LU_TYPE_INIT_FINI(lov, &lov_key, &lov_session_key);
>  
> +
> +static int lov_mdc_dev_init(const struct lu_env *env, struct lov_device *ld,
> +			    struct lu_device *mdc_dev, u32 idx, u32 nr)
> +{
> +	struct cl_device *cl;
> +
> +	cl = cl_type_setup(env, &ld->ld_site, &lovsub_device_type,
> +			   mdc_dev);
> +	if (IS_ERR(cl))
> +		return PTR_ERR(cl);
> +
> +	ld->ld_md_tgts[nr].ldm_mdc = cl;
> +	ld->ld_md_tgts[nr].ldm_idx = idx;
> +	return 0;
> +}
> +
>  static struct lu_device *lov_device_fini(const struct lu_env *env,
>  					 struct lu_device *d)
>  {
> -	int i;
>  	struct lov_device *ld = lu2lov_dev(d);
> +	int i;
>  
>  	LASSERT(ld->ld_lov);
> -	if (!ld->ld_target)
> -		return NULL;
>  
> -	lov_foreach_target(ld, i) {
> -		struct lovsub_device *lsd;
> +	if (ld->ld_lmv) {
> +		class_decref(ld->ld_lmv, "lov", d);
> +		ld->ld_lmv = NULL;
> +	}
> +
> +	if (ld->ld_md_tgts) {
> +		for (i = 0; i < ld->ld_md_tgts_nr; i++) {
> +			if (!ld->ld_md_tgts[i].ldm_mdc)
> +				continue;
>  
> -		lsd = ld->ld_target[i];
> -		if (lsd) {
> -			cl_stack_fini(env, lovsub2cl_dev(lsd));
> -			ld->ld_target[i] = NULL;
> +			cl_stack_fini(env, ld->ld_md_tgts[i].ldm_mdc);
> +			ld->ld_md_tgts[i].ldm_mdc = NULL;
> +			ld->ld_lov->lov_mdc_tgts[i].lmtd_mdc = NULL;
> +		}
> +	}
> +
> +	if (ld->ld_target) {
> +		lov_foreach_target(ld, i) {
> +			struct lovsub_device *lsd;
> +
> +			lsd = ld->ld_target[i];
> +			if (lsd) {
> +				cl_stack_fini(env, lovsub2cl_dev(lsd));
> +				ld->ld_target[i] = NULL;
> +			}
>  		}
>  	}
>  	return NULL;
> @@ -175,9 +207,28 @@ static int lov_device_init(const struct lu_env *env, struct lu_device *d,
>  	int i;
>  	int rc = 0;
>  
> -	LASSERT(d->ld_site);
> +	/* check all added already MDC subdevices and initialize them */
> +	for (i = 0; i < ld->ld_md_tgts_nr; i++) {
> +		struct obd_device *mdc;
> +		u32 idx;
> +
> +		mdc = ld->ld_lov->lov_mdc_tgts[i].lmtd_mdc;
> +		idx = ld->ld_lov->lov_mdc_tgts[i].lmtd_index;
> +
> +		if (!mdc)
> +			continue;
> +
> +		rc = lov_mdc_dev_init(env, ld, mdc->obd_lu_dev, idx, i);
> +		if (rc) {
> +			CERROR("%s: failed to add MDC %s as target: rc = %d\n",
> +			       d->ld_obd->obd_name,
> +			       obd_uuid2str(&mdc->obd_uuid), rc);
> +			goto out_err;
> +		}
> +	}
> +
>  	if (!ld->ld_target)
> -		return rc;
> +		return 0;
>  
>  	lov_foreach_target(ld, i) {
>  		struct lovsub_device *lsd;
> @@ -188,21 +239,21 @@ static int lov_device_init(const struct lu_env *env, struct lu_device *d,
>  		if (!desc)
>  			continue;
>  
> -		cl = cl_type_setup(env, d->ld_site, &lovsub_device_type,
> +		cl = cl_type_setup(env, &ld->ld_site, &lovsub_device_type,
>  				   desc->ltd_obd->obd_lu_dev);
>  		if (IS_ERR(cl)) {
>  			rc = PTR_ERR(cl);
> -			break;
> +			goto out_err;
>  		}
> +
>  		lsd = cl2lovsub_dev(cl);
>  		ld->ld_target[i] = lsd;
>  	}
> +	ld->ld_flags |= LOV_DEV_INITIALIZED;
> +	return 0;
>  
> -	if (rc)
> -		lov_device_fini(env, d);
> -	else
> -		ld->ld_flags |= LOV_DEV_INITIALIZED;
> -
> +out_err:
> +	lu_device_fini(d);
>  	return rc;
>  }
>  
> @@ -211,8 +262,17 @@ static struct lu_device *lov_device_free(const struct lu_env *env,
>  {
>  	struct lov_device *ld = lu2lov_dev(d);
>  
> +	lu_site_fini(&ld->ld_site);
> +
>  	cl_device_fini(lu2cl_dev(d));
>  	kfree(ld->ld_target);
> +	ld->ld_target = NULL;
> +	kfree(ld->ld_md_tgts);
> +	ld->ld_md_tgts = NULL;
> +	/* free array of MDCs */
> +	kfree(ld->ld_lov->lov_mdc_tgts);
> +	ld->ld_lov->lov_mdc_tgts = NULL;
> +
>  	kfree(ld);
>  	return NULL;
>  }
> @@ -277,9 +337,7 @@ static int lov_cl_add_target(const struct lu_env *env, struct lu_device *dev,
>  
>  	rc = lov_expand_targets(env, ld);
>  	if (rc == 0 && ld->ld_flags & LOV_DEV_INITIALIZED) {
> -		LASSERT(dev->ld_site);
> -
> -		cl = cl_type_setup(env, dev->ld_site, &lovsub_device_type,
> +		cl = cl_type_setup(env, &ld->ld_site, &lovsub_device_type,
>  				   tgt->ltd_obd->obd_lu_dev);
>  		if (!IS_ERR(cl)) {
>  			lsd = cl2lovsub_dev(cl);
> @@ -297,6 +355,84 @@ static int lov_cl_add_target(const struct lu_env *env, struct lu_device *dev,
>  	return rc;
>  }
>  
> +/**
> + * Add new MDC target device in LOV.
> + *
> + * This function is part of the configuration log processing. It adds new MDC
> + * device to the MDC device array indexed by their indexes.
> + *
> + * @env		execution environment
> + * @d		LU device of LOV device
> + * @mdc		MDC device to add
> + * @idx		MDC device index
> + *
> + * Return:	0 if successful
> + *		negative value on error
> + */
> +static int lov_add_mdc_target(const struct lu_env *env, struct lu_device *d,
> +			      struct obd_device *mdc, u32 idx)
> +{
> +	struct lov_device *ld = lu2lov_dev(d);
> +	struct obd_device *lov_obd = d->ld_obd;
> +	struct obd_device *lmv_obd;
> +	int next;
> +	int rc = 0;
> +
> +	LASSERT(mdc);
> +	if (ld->ld_md_tgts_nr == LOV_MDC_TGT_MAX) {
> +		/* If the maximum value of LOV_MDC_TGT_MAX will become too
> +		 * small then all MD target handling must be rewritten in LOD
> +		 * manner, check lod_add_device() and related functionality.
> +		 */
> +		CERROR("%s: cannot serve more than %d MDC devices\n",
> +		       lov_obd->obd_name, LOV_MDC_TGT_MAX);
> +		return -ERANGE;
> +	}
> +
> +	/* grab FLD from lmv, do that here, when first MDC is added
> +	 * to be sure LMV is set up and can be found
> +	 */
> +	if (!ld->ld_lmv) {
> +		next = 0;
> +		while ((lmv_obd = class_devices_in_group(&lov_obd->obd_uuid,
> +							 &next)) != NULL) {
> +			if ((strncmp(lmv_obd->obd_type->typ_name,
> +				     LUSTRE_LMV_NAME,
> +				     strlen(LUSTRE_LMV_NAME)) == 0))
> +				break;
> +		}
> +		if (!lmv_obd) {
> +			CERROR("%s: cannot find LMV OBD by UUID (%s)\n",
> +			       lov_obd->obd_name,
> +			       obd_uuid2str(&lmv_obd->obd_uuid));
> +			return -ENODEV;
> +		}
> +		spin_lock(&lmv_obd->obd_dev_lock);
> +		class_incref(lmv_obd, "lov", ld);
> +		spin_unlock(&lmv_obd->obd_dev_lock);
> +		ld->ld_lmv = lmv_obd;
> +	}
> +
> +	LASSERT(!lov_obd->u.lov.lov_mdc_tgts[ld->ld_md_tgts_nr].lmtd_mdc);
> +
> +	if (ld->ld_flags & LOV_DEV_INITIALIZED) {
> +		rc = lov_mdc_dev_init(env, ld, mdc->obd_lu_dev, idx,
> +				      ld->ld_md_tgts_nr);
> +		if (rc) {
> +			CERROR("%s: failed to add MDC %s as target: rc = %d\n",
> +			       lov_obd->obd_name, obd_uuid2str(&mdc->obd_uuid),
> +			       rc);
> +			return rc;
> +		}
> +	}
> +
> +	lov_obd->u.lov.lov_mdc_tgts[ld->ld_md_tgts_nr].lmtd_mdc = mdc;
> +	lov_obd->u.lov.lov_mdc_tgts[ld->ld_md_tgts_nr].lmtd_index = idx;
> +	ld->ld_md_tgts_nr++;
> +
> +	return rc;
> +}
> +
>  static int lov_process_config(const struct lu_env *env,
>  			      struct lu_device *d, struct lustre_cfg *cfg)
>  {
> @@ -309,23 +445,52 @@ static int lov_process_config(const struct lu_env *env,
>  	lov_tgts_getref(obd);
>  
>  	cmd = cfg->lcfg_command;
> +
>  	rc = lov_process_config_base(d->ld_obd, cfg, &index, &gen);
> -	if (rc == 0) {
> -		switch (cmd) {
> -		case LCFG_LOV_ADD_OBD:
> -		case LCFG_LOV_ADD_INA:
> -			rc = lov_cl_add_target(env, d, index);
> -			if (rc != 0)
> -				lov_del_target(d->ld_obd, index, NULL, 0);
> -			break;
> -		case LCFG_LOV_DEL_OBD:
> -			lov_cl_del_target(env, d, index);
> -			break;
> +	if (rc < 0)
> +		goto out;
> +
> +	switch (cmd) {
> +	case LCFG_LOV_ADD_OBD:
> +	case LCFG_LOV_ADD_INA:
> +		rc = lov_cl_add_target(env, d, index);
> +		if (rc != 0)
> +			lov_del_target(d->ld_obd, index, NULL, 0);
> +		break;
> +	case LCFG_LOV_DEL_OBD:
> +		lov_cl_del_target(env, d, index);
> +		break;
> +	case LCFG_ADD_MDC:
> +	{
> +		struct obd_device *mdc;
> +		struct obd_uuid tgt_uuid;
> +
> +		/* modify_mdc_tgts add 0:lustre-clilmv  1:lustre-MDT0000_UUID
> +		 * 2:0  3:1  4:lustre-MDT0000-mdc_UUID
> +		 */
> +		if (LUSTRE_CFG_BUFLEN(cfg, 1) > sizeof(tgt_uuid.uuid)) {
> +			rc = -EINVAL;
> +			goto out;
>  		}
> -	}
>  
> -	lov_tgts_putref(obd);
> +		obd_str2uuid(&tgt_uuid, lustre_cfg_buf(cfg, 1));
>  
> +		if (sscanf(lustre_cfg_buf(cfg, 2), "%d", &index) != 1) {
> +			rc = -EINVAL;
> +			goto out;
> +		}
> +		mdc = class_find_client_obd(&tgt_uuid, LUSTRE_MDC_NAME,
> +					    &obd->obd_uuid);
> +		if (!mdc) {
> +			rc = -ENODEV;
> +			goto out;
> +		}
> +		rc = lov_add_mdc_target(env, d, mdc, index);
> +		break;
> +	}
> +	}
> +out:
> +	lov_tgts_putref(obd);
>  	return rc;
>  }
>  
> @@ -355,13 +520,50 @@ static struct lu_device *lov_device_alloc(const struct lu_env *env,
>  	obd = class_name2obd(lustre_cfg_string(cfg, 0));
>  	LASSERT(obd);
>  	rc = lov_setup(obd, cfg);
> -	if (rc) {
> -		lov_device_free(env, d);
> -		return ERR_PTR(rc);
> +	if (rc)
> +		goto out;
> +
> +	/* Alloc MDC devices array */
> +	/* XXX: need dynamic allocation at some moment */
> +	ld->ld_md_tgts = kcalloc(LOV_MDC_TGT_MAX, sizeof(*ld->ld_md_tgts),
> +				 GFP_NOFS);
> +	if (!ld->ld_md_tgts) {
> +		rc = -ENOMEM;
> +		goto out;
>  	}
> +	ld->ld_md_tgts_nr = 0;
>  
>  	ld->ld_lov = &obd->u.lov;
> +	ld->ld_lov->lov_mdc_tgts =
> +		kcalloc(LOV_MDC_TGT_MAX,
> +			sizeof(*ld->ld_lov->lov_mdc_tgts),
> +			GFP_NOFS);
> +	if (!ld->ld_lov->lov_mdc_tgts) {
> +		rc = -ENOMEM;
> +		goto out_md_tgts;
> +	}
> +
> +	rc = lu_site_init(&ld->ld_site, d);
> +	if (rc != 0)
> +		goto out_mdc_tgts;
> +
> +	rc = lu_site_init_finish(&ld->ld_site);
> +	if (rc != 0)
> +		goto out_site;
> +
>  	return d;
> +out_site:
> +	lu_site_fini(&ld->ld_site);
> +out_mdc_tgts:
> +	kfree(ld->ld_lov->lov_mdc_tgts);
> +	ld->ld_lov->lov_mdc_tgts = NULL;
> +out_md_tgts:
> +	kfree(ld->ld_md_tgts);
> +	ld->ld_md_tgts = NULL;
> +out:
> +	kfree(ld);
> +
> +	return ERR_PTR(rc);
>  }
>  
>  static const struct lu_device_type_operations lov_device_type_ops = {
> diff --git a/fs/lustre/lov/lov_ea.c b/fs/lustre/lov/lov_ea.c
> index 395ef77..e1630f6 100644
> --- a/fs/lustre/lov/lov_ea.c
> +++ b/fs/lustre/lov/lov_ea.c
> @@ -95,7 +95,8 @@ static int lsm_lmm_verify_v1v3(struct lov_mds_md *lmm, size_t lmm_size,
>  		return -EINVAL;
>  	}
>  
> -	if (lov_pattern(le32_to_cpu(lmm->lmm_pattern)) != LOV_PATTERN_RAID0) {
> +	if (lov_pattern(le32_to_cpu(lmm->lmm_pattern)) != LOV_PATTERN_MDT &&
> +	    lov_pattern(le32_to_cpu(lmm->lmm_pattern)) != LOV_PATTERN_RAID0) {
>  		CERROR("bad striping pattern\n");
>  		lov_dump_lmm_common(D_WARNING, lmm);
>  		return -EINVAL;
> @@ -206,6 +207,12 @@ void lsm_free(struct lov_stripe_md *lsm)
>  		}
>  	}
>  
> +	/* with Data-on-MDT set maxbytes to stripe size */
> +	if (lsme_is_dom(lsme)) {
> +		lov_bytes = lsme->lsme_stripe_size;
> +		goto out_dom;
> +	}
> +
>  	for (i = 0; i < stripe_count; i++) {
>  		struct lov_tgt_desc *ltd;
>  		struct lov_oinfo *loi;
> @@ -253,6 +260,7 @@ void lsm_free(struct lov_stripe_md *lsm)
>  
>  	lov_bytes = min_stripe_maxbytes * stripe_count;
>  
> +out_dom:
>  	if (maxbytes) {
>  		if (lov_bytes < min_stripe_maxbytes) /* handle overflow */
>  			*maxbytes = MAX_LFS_FILESIZE;
> @@ -385,7 +393,8 @@ static int lsm_verify_comp_md_v1(struct lov_comp_md_v1 *lcm,
>  	unsigned int magic;
>  
>  	stripe_count = le16_to_cpu(lmm->lmm_stripe_count);
> -	if (stripe_count == 0)
> +	if (stripe_count == 0 &&
> +	    lov_pattern(le32_to_cpu(lmm->lmm_pattern)) != LOV_PATTERN_MDT)
>  		return ERR_PTR(-EINVAL);
>  
>  	/* un-instantiated lmm contains no ost id info, i.e. lov_ost_data_v1 */
> @@ -474,9 +483,10 @@ static int lsm_verify_comp_md_v1(struct lov_comp_md_v1 *lcm,
>  			/* the last component hasn't been defined, or
>  			 * lsm_maxbytes overflowed.
>  			 */
> -			if (lsme->lsme_extent.e_end != LUSTRE_EOF ||
> -			    lsm->lsm_maxbytes <
> -			    (loff_t)lsme->lsme_extent.e_start)
> +			if (!lsme_is_dom(lsme) &&
> +			    (lsme->lsme_extent.e_end != LUSTRE_EOF ||
> +			     lsm->lsm_maxbytes <
> +			     (loff_t)lsme->lsme_extent.e_start))
>  				lsm->lsm_maxbytes = MAX_LFS_FILESIZE;
>  		}
>  	}
> diff --git a/fs/lustre/lov/lov_internal.h b/fs/lustre/lov/lov_internal.h
> index f69f2d6..e18ea8e 100644
> --- a/fs/lustre/lov/lov_internal.h
> +++ b/fs/lustre/lov/lov_internal.h
> @@ -57,6 +57,11 @@ struct lov_stripe_md_entry {
>  	struct lov_oinfo       *lsme_oinfo[];
>  };
>  
> +static inline bool lsme_is_dom(struct lov_stripe_md_entry *lsme)
> +{
> +	return (lov_pattern(lsme->lsme_pattern) == LOV_PATTERN_MDT);
> +}
> +
>  static inline void copy_lsm_entry(struct lov_stripe_md_entry *dst,
>  				  struct lov_stripe_md_entry *src)
>  {
> @@ -300,6 +305,8 @@ struct lov_stripe_md *lov_unpackmd(struct lov_obd *lov, void *buf,
>  /* lov_cl.c */
>  extern struct lu_device_type lov_device_type;
>  
> +#define LOV_MDC_TGT_MAX 256
> +
>  /* ost_pool methods */
>  int lov_ost_pool_init(struct ost_pool *op, unsigned int count);
>  int lov_ost_pool_extend(struct ost_pool *op, unsigned int min_count);
> diff --git a/fs/lustre/lov/lov_io.c b/fs/lustre/lov/lov_io.c
> index a72069f..c7fe4a2 100644
> --- a/fs/lustre/lov/lov_io.c
> +++ b/fs/lustre/lov/lov_io.c
> @@ -533,7 +533,11 @@ static int lov_io_setattr_iter_init(const struct lu_env *env,
>  
>  	if (cl_io_is_trunc(io) && lio->lis_pos > 0) {
>  		index = lov_lsm_entry(lsm, lio->lis_pos - 1);
> -		if (index > 0 && !lsm_entry_inited(lsm, index)) {
> +		/* no entry found for such offset */
> +		if (index < 0) {
> +			io->ci_result = -ENODATA;
> +			return io->ci_result;
> +		} else if (!lsm_entry_inited(lsm, index)) {
>  			io->ci_need_write_intent = 1;
>  			io->ci_result = -ENODATA;
>  			return io->ci_result;
> diff --git a/fs/lustre/lov/lov_obd.c b/fs/lustre/lov/lov_obd.c
> index 5dbc00e..4ced5f7 100644
> --- a/fs/lustre/lov/lov_obd.c
> +++ b/fs/lustre/lov/lov_obd.c
> @@ -852,6 +852,9 @@ int lov_process_config_base(struct obd_device *obd, struct lustre_cfg *lcfg,
>  	int rc = 0;
>  
>  	switch (cmd = lcfg->lcfg_command) {
> +	case LCFG_ADD_MDC:
> +	case LCFG_DEL_MDC:
> +		break;
>  	case LCFG_LOV_ADD_OBD:
>  	case LCFG_LOV_ADD_INA:
>  	case LCFG_LOV_DEL_OBD: {
> @@ -1179,31 +1182,32 @@ static int lov_set_info_async(const struct lu_env *env, struct obd_export *exp,
>  {
>  	struct obd_device *obddev = class_exp2obd(exp);
>  	struct lov_obd *lov = &obddev->u.lov;
> -	u32 count;
> -	int i, rc = 0, err;
>  	struct lov_tgt_desc *tgt;
> -	int do_inactive = 0, no_set = 0;
> +	bool do_inactive = false;
> +	bool no_set = false;
> +	int rc = 0;
> +	int err;
> +	u32 i;
>  
>  	if (!set) {
> -		no_set = 1;
> +		no_set = true;
>  		set = ptlrpc_prep_set();
>  		if (!set)
>  			return -ENOMEM;
>  	}
>  
>  	lov_tgts_getref(obddev);
> -	count = lov->desc.ld_tgt_count;
>  
>  	if (KEY_IS(KEY_CHECKSUM)) {
> -		do_inactive = 1;
> +		do_inactive = true;
>  	} else if (KEY_IS(KEY_CACHE_SET)) {
>  		LASSERT(!lov->lov_cache);
>  		lov->lov_cache = val;
> -		do_inactive = 1;
> +		do_inactive = true;
>  		cl_cache_incref(lov->lov_cache);
>  	}
>  
> -	for (i = 0; i < count; i++) {
> +	for (i = 0; i < lov->desc.ld_tgt_count; i++) {
>  		tgt = lov->lov_tgts[i];
>  
>  		/* OST was disconnected */
> @@ -1216,14 +1220,29 @@ static int lov_set_info_async(const struct lu_env *env, struct obd_export *exp,
>  
>  		err = obd_set_info_async(env, tgt->ltd_exp, keylen, key,
>  					 vallen, val, set);
> -		if (!rc)
> +
> +		if (rc == 0)
> +			rc = err;
> +	}
> +
> +	/* cycle through MDC target for Data-on-MDT */
> +	for (i = 0; i < LOV_MDC_TGT_MAX; i++) {
> +		struct obd_device *mdc;
> +
> +		mdc = lov->lov_mdc_tgts[i].lmtd_mdc;
> +		if (!mdc)
> +			continue;
> +
> +		err = obd_set_info_async(env, mdc->obd_self_export,
> +					 keylen, key, vallen, val, set);
> +		if (rc == 0)
>  			rc = err;
>  	}
>  
>  	lov_tgts_putref(obddev);
>  	if (no_set) {
>  		err = ptlrpc_set_wait(set);
> -		if (!rc)
> +		if (rc == 0)
>  			rc = err;
>  		ptlrpc_set_destroy(set);
>  	}
> diff --git a/fs/lustre/lov/lov_object.c b/fs/lustre/lov/lov_object.c
> index caeff89..186b875 100644
> --- a/fs/lustre/lov/lov_object.c
> +++ b/fs/lustre/lov/lov_object.c
> @@ -90,13 +90,6 @@ static void lov_lsm_put(struct lov_stripe_md *lsm)
>   * Lov object layout operations.
>   *
>   */
> -static int lov_init_empty(const struct lu_env *env, struct lov_device *dev,
> -			  struct lov_object *lov, struct lov_stripe_md *lsm,
> -			  const struct cl_object_conf *conf,
> -			  union lov_layout_state *state)
> -{
> -	return 0;
> -}
>  
>  static struct cl_object *lov_sub_find(const struct lu_env *env,
>  				      struct cl_device *dev,
> @@ -110,9 +103,25 @@ static struct cl_object *lov_sub_find(const struct lu_env *env,
>  	return lu2cl(o);
>  }
>  
> +static int lov_page_slice_fixup(struct lov_object *lov,
> +				struct cl_object *stripe)
> +{
> +	struct cl_object_header *hdr = cl_object_header(&lov->lo_cl);
> +	struct cl_object *o;
> +
> +	if (!stripe)
> +		return hdr->coh_page_bufsize - lov->lo_cl.co_slice_off -
> +		       cfs_size_round(sizeof(struct lov_page));
> +
> +	cl_object_for_each(o, stripe)
> +		o->co_slice_off += hdr->coh_page_bufsize;
> +
> +	return cl_object_header(stripe)->coh_page_bufsize;
> +}
> +
>  static int lov_init_sub(const struct lu_env *env, struct lov_object *lov,
> -			struct cl_object *subobj, struct lov_layout_raid0 *r0,
> -			struct lov_oinfo *oinfo, int idx)
> +			struct cl_object *subobj, struct lov_oinfo *oinfo,
> +			int idx)
>  {
>  	int stripe = lov_comp_stripe(idx);
>  	int entry = lov_comp_entry(idx);
> @@ -146,13 +155,14 @@ static int lov_init_sub(const struct lu_env *env, struct lov_object *lov,
>  	spin_lock(&subhdr->coh_attr_guard);
>  	parent = subhdr->coh_parent;
>  	if (!parent) {
> +		struct lovsub_object *lso = cl2lovsub(subobj);
> +
>  		subhdr->coh_parent = hdr;
>  		spin_unlock(&subhdr->coh_attr_guard);
>  		subhdr->coh_nesting = hdr->coh_nesting + 1;
>  		lu_object_ref_add(&subobj->co_lu, "lov-parent", lov);
> -		r0->lo_sub[stripe] = cl2lovsub(subobj);
> -		r0->lo_sub[stripe]->lso_super = lov;
> -		r0->lo_sub[stripe]->lso_index = idx;
> +		lso->lso_super = lov;
> +		lso->lso_index = idx;
>  		result = 0;
>  	} else {
>  		struct lu_object *old_obj;
> @@ -183,33 +193,19 @@ static int lov_init_sub(const struct lu_env *env, struct lov_object *lov,
>  	return result;
>  }
>  
> -static int lov_page_slice_fixup(struct lov_object *lov,
> -				struct cl_object *stripe)
> -{
> -	struct cl_object_header *hdr = cl_object_header(&lov->lo_cl);
> -	struct cl_object *o;
> -
> -	if (!stripe)
> -		return hdr->coh_page_bufsize - lov->lo_cl.co_slice_off -
> -		       cfs_size_round(sizeof(struct lov_page));
> -
> -	cl_object_for_each(o, stripe)
> -		o->co_slice_off += hdr->coh_page_bufsize;
> -
> -	return cl_object_header(stripe)->coh_page_bufsize;
> -}
> -
>  static int lov_init_raid0(const struct lu_env *env, struct lov_device *dev,
> -			  struct lov_object *lov, int index,
> -			  struct lov_layout_raid0 *r0)
> +			  struct lov_object *lov, unsigned int index,
> +			  const struct cl_object_conf *conf,
> +			  struct lov_layout_entry *lle)
>  {
>  	struct lov_stripe_md_entry *lse = lov_lse(lov, index);
> +	struct lov_layout_raid0 *r0 = &lle->lle_raid0;
>  	struct lov_thread_info *lti = lov_env_info(env);
>  	struct cl_object_conf *subconf = &lti->lti_stripe_conf;
>  	struct lu_fid *ofid = &lti->lti_fid;
>  	struct cl_object *stripe;
>  	int result;
> -	int psz;
> +	int psz, sz;
>  	int i;
>  
>  	spin_lock_init(&r0->lo_sub_lock);
> @@ -261,7 +257,7 @@ static int lov_init_raid0(const struct lu_env *env, struct lov_device *dev,
>  			goto out;
>  		}
>  
> -		result = lov_init_sub(env, lov, stripe, r0, oinfo,
> +		result = lov_init_sub(env, lov, stripe, oinfo,
>  				      lov_comp_index(index, i));
>  		if (result == -EAGAIN) { /* try again */
>  			--i;
> @@ -270,8 +266,9 @@ static int lov_init_raid0(const struct lu_env *env, struct lov_device *dev,
>  		}
>  
>  		if (result == 0) {
> -			int sz = lov_page_slice_fixup(lov, stripe);
> +			r0->lo_sub[i] = cl2lovsub(stripe);
>  
> +			sz = lov_page_slice_fixup(lov, stripe);
>  			LASSERT(ergo(psz > 0, psz == sz));
>  			psz = sz;
>  		}
> @@ -282,12 +279,333 @@ static int lov_init_raid0(const struct lu_env *env, struct lov_device *dev,
>  	return result;
>  }
>  
> +static void lov_subobject_kill(const struct lu_env *env, struct lov_object *lov,
> +			       struct lov_layout_raid0 *r0,
> +			       struct lovsub_object *los, int idx)
> +{
> +	struct cl_object *sub;
> +	struct lu_site *site;
> +	wait_queue_head_t *wq;
> +
> +	LASSERT(r0->lo_sub[idx] == los);
> +
> +	sub = lovsub2cl(los);
> +	site = sub->co_lu.lo_dev->ld_site;
> +	wq = lu_site_wq_from_fid(site, &sub->co_lu.lo_header->loh_fid);
> +
> +	cl_object_kill(env, sub);
> +	/* release a reference to the sub-object and ... */
> +	lu_object_ref_del(&sub->co_lu, "lov-parent", lov);
> +	cl_object_put(env, sub);
> +
> +	/* ... wait until it is actually destroyed---sub-object clears its
> +	 * ->lo_sub[] slot in lovsub_object_free()
> +	 */
> +	wait_event(*wq, r0->lo_sub[idx] != los);
> +	LASSERT(!r0->lo_sub[idx]);
> +}
> +
> +static void lov_delete_raid0(const struct lu_env *env, struct lov_object *lov,
> +			     struct lov_layout_entry *lle)
> +{
> +	struct lov_layout_raid0 *r0 = &lle->lle_raid0;
> +
> +	if (r0->lo_sub) {
> +		int i;
> +
> +		for (i = 0; i < r0->lo_nr; ++i) {
> +			struct lovsub_object *los = r0->lo_sub[i];
> +
> +			if (los) {
> +				cl_object_prune(env, &los->lso_cl);
> +				/*
> +				 * If top-level object is to be evicted from
> +				 * the cache, so are its sub-objects.
> +				 */
> +				lov_subobject_kill(env, lov, r0, los, i);
> +			}
> +		}
> +	}
> +}
> +
> +static void lov_fini_raid0(const struct lu_env *env,
> +			   struct lov_layout_entry *lle)
> +{
> +	struct lov_layout_raid0 *r0 = &lle->lle_raid0;
> +
> +	if (r0->lo_sub) {
> +		kvfree(r0->lo_sub);
> +		r0->lo_sub = NULL;
> +	}
> +}
> +
> +static int lov_print_raid0(const struct lu_env *env, void *cookie,
> +			   lu_printer_t p, const struct lov_layout_entry *lle)
> +{
> +	const struct lov_layout_raid0 *r0 = &lle->lle_raid0;
> +	int i;
> +
> +	for (i = 0; i < r0->lo_nr; ++i) {
> +		struct lu_object *sub;
> +
> +		if (r0->lo_sub[i]) {
> +			sub = lovsub2lu(r0->lo_sub[i]);
> +			lu_object_print(env, cookie, p, sub);
> +		} else {
> +			(*p)(env, cookie, "sub %d absent\n", i);
> +		}
> +	}
> +	return 0;
> +}
> +
> +static int lov_attr_get_raid0(const struct lu_env *env, struct lov_object *lov,
> +			      unsigned int index, struct lov_layout_entry *lle,
> +			      struct cl_attr **lov_attr)
> +{
> +	struct lov_layout_raid0 *r0 = &lle->lle_raid0;
> +	struct lov_stripe_md *lsm = lov->lo_lsm;
> +	struct ost_lvb *lvb = &lov_env_info(env)->lti_lvb;
> +	struct cl_attr *attr = &r0->lo_attr;
> +	u64 kms = 0;
> +	int result = 0;
> +
> +	if (r0->lo_attr_valid) {
> +		*lov_attr = attr;
> +		return 0;
> +	}
> +
> +	memset(lvb, 0, sizeof(*lvb));
> +
> +	/* XXX: timestamps can be negative by sanity:test_39m,
> +	 * how can it be?
> +	 */
> +	lvb->lvb_atime = LLONG_MIN;
> +	lvb->lvb_ctime = LLONG_MIN;
> +	lvb->lvb_mtime = LLONG_MIN;
> +
> +	/*
> +	 * XXX that should be replaced with a loop over sub-objects,
> +	 * doing cl_object_attr_get() on them. But for now, let's
> +	 * reuse old lov code.
> +	 */
> +
> +	/*
> +	 * XXX take lsm spin-lock to keep lov_merge_lvb_kms()
> +	 * happy. It's not needed, because new code uses
> +	 * ->coh_attr_guard spin-lock to protect consistency of
> +	 * sub-object attributes.
> +	 */
> +	lov_stripe_lock(lsm);
> +	result = lov_merge_lvb_kms(lsm, index, lvb, &kms);
> +	lov_stripe_unlock(lsm);
> +	if (result == 0) {
> +		cl_lvb2attr(attr, lvb);
> +		attr->cat_kms = kms;
> +		r0->lo_attr_valid = 1;
> +		*lov_attr = attr;
> +	}
> +
> +	return result;
> +}
> +
> +static struct lov_comp_layout_entry_ops raid0_ops = {
> +	.lco_init      = lov_init_raid0,
> +	.lco_fini      = lov_fini_raid0,
> +	.lco_getattr   = lov_attr_get_raid0,
> +};
> +
> +static int lov_attr_get_dom(const struct lu_env *env, struct lov_object *lov,
> +			    unsigned int index, struct lov_layout_entry *lle,
> +			    struct cl_attr **lov_attr)
> +{
> +	struct lov_layout_dom *dom = &lle->lle_dom;
> +	struct lov_oinfo *loi = dom->lo_loi;
> +	struct cl_attr *attr = &dom->lo_dom_r0.lo_attr;
> +
> +	if (dom->lo_dom_r0.lo_attr_valid) {
> +		*lov_attr = attr;
> +		return 0;
> +	}
> +
> +	if (OST_LVB_IS_ERR(loi->loi_lvb.lvb_blocks))
> +		return OST_LVB_GET_ERR(loi->loi_lvb.lvb_blocks);
> +
> +	cl_lvb2attr(attr, &loi->loi_lvb);
> +	attr->cat_kms = attr->cat_size > loi->loi_kms ? attr->cat_size :
> +							loi->loi_kms;
> +	dom->lo_dom_r0.lo_attr_valid = 1;
> +	*lov_attr = attr;
> +
> +	return 0;
> +}
> +
> +/**
> + * Lookup FLD to get MDS index of the given DOM object FID.
> + *
> + * @ld		LOV device
> + * @fid		FID to lookup
> + * @nr		index in MDC array to return back
> + *
> + * Return:	0 and @mds filled with MDS index if successful
> + *		negative value on error
> + */
> +static int lov_fld_lookup(struct lov_device *ld, const struct lu_fid *fid,
> +			  u32 *nr)
> +{
> +	u32 mds_idx;
> +	int i, rc;
> +
> +	rc = fld_client_lookup(&ld->ld_lmv->u.lmv.lmv_fld, fid_seq(fid),
> +			       &mds_idx, LU_SEQ_RANGE_MDT, NULL);
> +	if (rc) {
> +		CERROR("%s: error while looking for mds number. Seq %#llx, err = %d\n",
> +		       lu_dev_name(cl2lu_dev(&ld->ld_cl)), fid_seq(fid), rc);
> +		return rc;
> +	}
> +
> +	CDEBUG(D_INODE, "FLD lookup got mds #%x for fid=" DFID "\n",
> +	       mds_idx, PFID(fid));
> +
> +	/* find proper MDC device in the array */
> +	for (i = 0; i < ld->ld_md_tgts_nr; i++) {
> +		if (ld->ld_md_tgts[i].ldm_mdc &&
> +		    ld->ld_md_tgts[i].ldm_idx == mds_idx)
> +			break;
> +	}
> +
> +	if (i == ld->ld_md_tgts_nr) {
> +		CERROR("%s: cannot find corresponding MDC device for mds #%x for fid=" DFID "\n",
> +		       lu_dev_name(cl2lu_dev(&ld->ld_cl)), mds_idx, PFID(fid));
> +		rc = -EINVAL;
> +	} else {
> +		*nr = i;
> +	}
> +	return rc;
> +}
> +
> +/**
> + * Implementation of lov_comp_layout_entry_ops::lco_init for DOM object.
> + *
> + * Init the DOM object for the first time. It prepares also RAID0 entry
> + * for it to use in common methods with ordinary RAID0 layout entries.
> + *
> + * @env		execution environment
> + * @dev		LOV device
> + * @lov		LOV object
> + * @index	Composite layout entry index in LSM
> + * @lle		Composite LOV layout entry
> + */
> +static int lov_init_dom(const struct lu_env *env, struct lov_device *dev,
> +			struct lov_object *lov, unsigned int index,
> +			const struct cl_object_conf *conf,
> +			struct lov_layout_entry *lle)
> +{
> +	struct lov_thread_info *lti = lov_env_info(env);
> +	struct lov_stripe_md_entry *lsme = lov_lse(lov, index);
> +	struct cl_object *clo;
> +	struct lu_object *o = lov2lu(lov);
> +	const struct lu_fid *fid = lu_object_fid(o);
> +	struct cl_device *mdcdev;
> +	struct lov_oinfo *loi = NULL;
> +	struct cl_object_conf *sconf = &lti->lti_stripe_conf;
> +	struct inode *inode = conf->coc_inode;
> +	u32 idx = 0;
> +	int rc;
> +
> +	LASSERT(index == 0);
> +
> +	/* find proper MDS device */
> +	rc = lov_fld_lookup(dev, fid, &idx);
> +	if (rc)
> +		return rc;
> +
> +	LASSERTF(dev->ld_md_tgts[idx].ldm_mdc,
> +		 "LOV md target[%u] is NULL\n", idx);
> +
> +	/* check lsm is DOM, more checks are needed */
> +	LASSERT(lsme->lsme_stripe_count == 0);
> +
> +	/*
> +	 * Create lower cl_objects.
> +	 */
> +	mdcdev = dev->ld_md_tgts[idx].ldm_mdc;
> +
> +	LASSERTF(mdcdev, "non-initialized mdc subdev\n");
> +
> +	/* DoM object has no oinfo in LSM entry, create it exclusively */
> +	loi = kmem_cache_zalloc(lov_oinfo_slab, GFP_NOFS);
> +	if (!loi)
> +		return -ENOMEM;
> +
> +	fid_to_ostid(lu_object_fid(lov2lu(lov)), &loi->loi_oi);
> +	/* Initialize lvb structure */
> +	loi->loi_lvb.lvb_mtime = inode->i_mtime.tv_sec;
> +	loi->loi_lvb.lvb_atime = inode->i_atime.tv_sec;
> +	loi->loi_lvb.lvb_ctime = inode->i_ctime.tv_sec;
> +	loi->loi_lvb.lvb_blocks = inode->i_blocks;
> +	loi->loi_lvb.lvb_size = i_size_read(inode);
> +	if (loi->loi_lvb.lvb_size > lsme->lsme_stripe_size)
> +		loi->loi_lvb.lvb_size = lsme->lsme_stripe_size;
> +	loi_kms_set(loi, loi->loi_lvb.lvb_size);
> +
> +	sconf->u.coc_oinfo = loi;
> +again:
> +	clo = lov_sub_find(env, mdcdev, fid, sconf);
> +	if (IS_ERR(clo)) {
> +		rc = PTR_ERR(clo);
> +		goto out;
> +	}
> +
> +	rc = lov_init_sub(env, lov, clo, loi, lov_comp_index(index, 0));
> +	if (rc == -EAGAIN) /* try again */
> +		goto again;
> +	else if (rc != 0)
> +		goto out;
> +
> +	lle->lle_dom.lo_dom = cl2lovsub(clo);
> +	spin_lock_init(&lle->lle_dom.lo_dom_r0.lo_sub_lock);
> +	lle->lle_dom.lo_dom_r0.lo_nr = 1;
> +	lle->lle_dom.lo_dom_r0.lo_sub = &lle->lle_dom.lo_dom;
> +	lle->lle_dom.lo_loi = loi;
> +
> +	rc = lov_page_slice_fixup(lov, clo);
> +	return rc;
> +
> +out:
> +	kmem_cache_free(lov_oinfo_slab, loi);
> +	return rc;
> +}
> +
> +/**
> + * Implementation of lov_layout_operations::llo_fini for DOM object.
> + *
> + * Finish the DOM object and free related memory.
> + *
> + * @env		execution environment
> + * @lov		LOV object
> + * @state	LOV layout state
> + */
> +static void lov_fini_dom(const struct lu_env *env,
> +			 struct lov_layout_entry *lle)
> +{
> +	if (lle->lle_dom.lo_dom)
> +		lle->lle_dom.lo_dom = NULL;
> +	kmem_cache_free(lov_oinfo_slab, lle->lle_dom.lo_loi);
> +}
> +
> +static struct lov_comp_layout_entry_ops dom_ops = {
> +	.lco_init	= lov_init_dom,
> +	.lco_fini	= lov_fini_dom,
> +	.lco_getattr	= lov_attr_get_dom,
> +};
> +
>  static int lov_init_composite(const struct lu_env *env, struct lov_device *dev,
>  			      struct lov_object *lov, struct lov_stripe_md *lsm,
>  			      const struct cl_object_conf *conf,
>  			      union lov_layout_state *state)
>  {
>  	struct lov_layout_composite *comp = &state->composite;
> +	struct lov_layout_entry *lle;
>  	unsigned int entry_count;
>  	unsigned int psz = 0;
>  	int result = 0;
> @@ -306,24 +624,45 @@ static int lov_init_composite(const struct lu_env *env, struct lov_device *dev,
>  	if (!comp->lo_entries)
>  		return -ENOMEM;
>  
> +	/* Initiate all entry types and extents data at first */
>  	for (i = 0; i < entry_count; i++) {
> -		struct lov_layout_entry *le = &comp->lo_entries[i];
> +		lle = &comp->lo_entries[i];
>  
> -		le->lle_extent = lsm->lsm_entries[i]->lsme_extent;
> +		lle->lle_type = lov_entry_type(lsm->lsm_entries[i]);
> +		switch (lle->lle_type) {
> +		case LOV_PATTERN_RAID0:
> +			lle->lle_comp_ops = &raid0_ops;
> +			break;
> +		case LOV_PATTERN_MDT:
> +			lle->lle_comp_ops = &dom_ops;
> +			break;
> +		default:
> +			CERROR("%s: unknown composite layout entry type %i\n",
> +			       lov2obd(dev->ld_lov)->obd_name,
> +			       lsm->lsm_entries[i]->lsme_pattern);
> +			dump_lsm(D_ERROR, lsm);
> +			return -EIO;
> +		}
> +		lle->lle_extent = lsm->lsm_entries[i]->lsme_extent;
> +	}
> +
> +	i = 0;
> +	lov_foreach_layout_entry(lov, lle) {
>  		/**
>  		 * If the component has not been init-ed on MDS side, for
>  		 * PFL layout, we'd know that the components beyond this one
>  		 * will be dynamically init-ed later on file write/trunc ops.
>  		 */
> -		if (!lsm_entry_inited(lsm, i))
> -			continue;
> -
> -		result = lov_init_raid0(env, dev, lov, i, &le->lle_raid0);
> -		if (result < 0)
> -			break;
> +		if (lsm_entry_inited(lsm, i)) {
> +			result = lle->lle_comp_ops->lco_init(env, dev, lov, i,
> +							     conf, lle);
> +			if (result < 0)
> +				break;
>  
> -		LASSERT(ergo(psz > 0, psz == result));
> -		psz = result;
> +			LASSERT(ergo(psz > 0, psz == result));
> +			psz = result;
> +		}
> +		i++;
>  	}
>  	if (psz > 0)
>  		cl_object_header(&lov->lo_cl)->coh_page_bufsize += psz;
> @@ -331,10 +670,19 @@ static int lov_init_composite(const struct lu_env *env, struct lov_device *dev,
>  	return result > 0 ? 0 : result;
>  }
>  
> -static int lov_init_released(const struct lu_env *env, struct lov_device *dev,
> -			     struct lov_object *lov, struct lov_stripe_md *lsm,
> +static int lov_init_empty(const struct lu_env *env, struct lov_device *dev,
> +			  struct lov_object *lov, struct lov_stripe_md *lsm,
> +			  const struct cl_object_conf *conf,
> +			  union lov_layout_state *state)
> +{
> +	return 0;
> +}
> +
> +static int lov_init_released(const struct lu_env *env,
> +			     struct lov_device *dev, struct lov_object *lov,
> +			     struct lov_stripe_md *lsm,
>  			     const struct cl_object_conf *conf,
> -			     union  lov_layout_state *state)
> +			     union lov_layout_state *state)
>  {
>  	LASSERT(lsm);
>  	LASSERT(lsm->lsm_is_released);
> @@ -344,41 +692,6 @@ static int lov_init_released(const struct lu_env *env, struct lov_device *dev,
>  	return 0;
>  }
>  
> -static struct cl_object *lov_find_subobj(const struct lu_env *env,
> -					 struct lov_object *lov,
> -					 struct lov_stripe_md *lsm,
> -					 int index)
> -{
> -	struct lov_device *dev = lu2lov_dev(lov2lu(lov)->lo_dev);
> -	struct lov_thread_info *lti = lov_env_info(env);
> -	struct lu_fid *ofid = &lti->lti_fid;
> -	int stripe = lov_comp_stripe(index);
> -	int entry = lov_comp_entry(index);
> -	struct cl_object *result = NULL;
> -	struct cl_device *subdev;
> -	struct lov_oinfo *oinfo;
> -	int ost_idx;
> -	int rc;
> -
> -	if (lov->lo_type != LLT_COMP)
> -		goto out;
> -
> -	if (entry >= lsm->lsm_entry_count ||
> -	    stripe >= lsm->lsm_entries[entry]->lsme_stripe_count)
> -		goto out;
> -
> -	oinfo = lsm->lsm_entries[entry]->lsme_oinfo[stripe];
> -	ost_idx = oinfo->loi_ost_idx;
> -	rc = ostid_to_fid(ofid, &oinfo->loi_oi, ost_idx);
> -	if (rc)
> -		goto out;
> -
> -	subdev = lovsub2cl_dev(dev->ld_target[ost_idx]);
> -	result = lov_sub_find(env, subdev, ofid, NULL);
> -out:
> -	return result ? result : ERR_PTR(-EINVAL);
> -}
> -
>  static int lov_delete_empty(const struct lu_env *env, struct lov_object *lov,
>  			    union lov_layout_state *state)
>  {
> @@ -388,75 +701,6 @@ static int lov_delete_empty(const struct lu_env *env, struct lov_object *lov,
>  	return 0;
>  }
>  
> -static void lov_subobject_kill(const struct lu_env *env, struct lov_object *lov,
> -			       struct lov_layout_raid0 *r0,
> -			       struct lovsub_object *los, int idx)
> -{
> -	struct cl_object *sub;
> -	struct lu_site *site;
> -	wait_queue_head_t *wq;
> -	wait_queue_entry_t *waiter;
> -
> -	LASSERT(r0->lo_sub[idx] == los);
> -
> -	sub = lovsub2cl(los);
> -	site = sub->co_lu.lo_dev->ld_site;
> -	wq = lu_site_wq_from_fid(site, &sub->co_lu.lo_header->loh_fid);
> -
> -	cl_object_kill(env, sub);
> -	/* release a reference to the sub-object and ... */
> -	lu_object_ref_del(&sub->co_lu, "lov-parent", lov);
> -	cl_object_put(env, sub);
> -
> -	/* ... wait until it is actually destroyed---sub-object clears its
> -	 * ->lo_sub[] slot in lovsub_object_fini()
> -	 */
> -	if (r0->lo_sub[idx] == los) {
> -		waiter = &lov_env_info(env)->lti_waiter;
> -		init_waitqueue_entry(waiter, current);
> -		add_wait_queue(wq, waiter);
> -		set_current_state(TASK_UNINTERRUPTIBLE);
> -		while (1) {
> -			/* this wait-queue is signaled at the end of
> -			 * lu_object_free().
> -			 */
> -			set_current_state(TASK_UNINTERRUPTIBLE);
> -			spin_lock(&r0->lo_sub_lock);
> -			if (r0->lo_sub[idx] == los) {
> -				spin_unlock(&r0->lo_sub_lock);
> -				schedule();
> -			} else {
> -				spin_unlock(&r0->lo_sub_lock);
> -				set_current_state(TASK_RUNNING);
> -				break;
> -			}
> -		}
> -		remove_wait_queue(wq, waiter);
> -	}
> -	LASSERT(!r0->lo_sub[idx]);
> -}
> -
> -static void lov_delete_raid0(const struct lu_env *env, struct lov_object *lov,
> -			     struct lov_layout_raid0 *r0)
> -{
> -	if (r0->lo_sub) {
> -		int i;
> -
> -		for (i = 0; i < r0->lo_nr; ++i) {
> -			struct lovsub_object *los = r0->lo_sub[i];
> -
> -			if (los) {
> -				cl_object_prune(env, &los->lso_cl);
> -				/*
> -				 * If top-level object is to be evicted from
> -				 * the cache, so are its sub-objects.
> -				 */
> -				lov_subobject_kill(env, lov, r0, los, i);
> -			}
> -		}
> -	}
> -}
> -
>  static int lov_delete_composite(const struct lu_env *env,
>  				struct lov_object *lov,
>  				union lov_layout_state *state)
> @@ -469,7 +713,7 @@ static int lov_delete_composite(const struct lu_env *env,
>  	lov_layout_wait(env, lov);
>  	if (comp->lo_entries)
>  		lov_foreach_layout_entry(lov, entry)
> -			lov_delete_raid0(env, lov, &entry->lle_raid0);
> +			lov_delete_raid0(env, lov, entry);
>  
>  	return 0;
>  }
> @@ -480,15 +724,6 @@ static void lov_fini_empty(const struct lu_env *env, struct lov_object *lov,
>  	LASSERT(lov->lo_type == LLT_EMPTY || lov->lo_type == LLT_RELEASED);
>  }
>  
> -static void lov_fini_raid0(const struct lu_env *env,
> -			   struct lov_layout_raid0 *r0)
> -{
> -	if (r0->lo_sub) {
> -		kvfree(r0->lo_sub);
> -		r0->lo_sub = NULL;
> -	}
> -}
> -
>  static void lov_fini_composite(const struct lu_env *env,
>  			       struct lov_object *lov,
>  			       union lov_layout_state *state)
> @@ -499,7 +734,7 @@ static void lov_fini_composite(const struct lu_env *env,
>  		struct lov_layout_entry *entry;
>  
>  		lov_foreach_layout_entry(lov, entry)
> -			lov_fini_raid0(env, &entry->lle_raid0);
> +			entry->lle_comp_ops->lco_fini(env, entry);
>  
>  		kvfree(comp->lo_entries);
>  		comp->lo_entries = NULL;
> @@ -523,24 +758,6 @@ static int lov_print_empty(const struct lu_env *env, void *cookie,
>  	return 0;
>  }
>  
> -static int lov_print_raid0(const struct lu_env *env, void *cookie,
> -			   lu_printer_t p, struct lov_layout_raid0 *r0)
> -{
> -	int i;
> -
> -	for (i = 0; i < r0->lo_nr; ++i) {
> -		struct lu_object *sub;
> -
> -		if (r0->lo_sub[i]) {
> -			sub = lovsub2lu(r0->lo_sub[i]);
> -			lu_object_print(env, cookie, p, sub);
> -		} else {
> -			(*p)(env, cookie, "sub %d absent\n", i);
> -		}
> -	}
> -	return 0;
> -}
> -
>  static int lov_print_composite(const struct lu_env *env, void *cookie,
>  			       lu_printer_t p, const struct lu_object *o)
>  {
> @@ -556,12 +773,15 @@ static int lov_print_composite(const struct lu_env *env, void *cookie,
>  
>  	for (i = 0; i < lsm->lsm_entry_count; i++) {
>  		struct lov_stripe_md_entry *lse = lsm->lsm_entries[i];
> +		struct lov_layout_entry *lle = lov_entry(lov, i);
>  
> -		(*p)(env, cookie, DEXT ": { 0x%08X, %u, %u, %#x, %u, %u }\n",
> +		(*p)(env, cookie,
> +		     DEXT ": { 0x%08X, %u, %#x, %u, %#x, %u, %u }\n",
>  		     PEXT(&lse->lsme_extent), lse->lsme_magic,
> -		     lse->lsme_id, lse->lsme_layout_gen, lse->lsme_flags,
> -		     lse->lsme_stripe_count, lse->lsme_stripe_size);
> -		lov_print_raid0(env, cookie, p, lov_r0(lov, i));
> +		     lse->lsme_id, lse->lsme_pattern, lse->lsme_layout_gen,
> +		     lse->lsme_flags, lse->lsme_stripe_count,
> +		     lse->lsme_stripe_size);
> +		lov_print_raid0(env, cookie, p, lle);
>  	}
>  
>  	return 0;
> @@ -595,52 +815,6 @@ static int lov_attr_get_empty(const struct lu_env *env, struct cl_object *obj,
>  	return 0;
>  }
>  
> -static int lov_attr_get_raid0(const struct lu_env *env, struct lov_object *lov,
> -			      unsigned int index, struct lov_layout_raid0 *r0)
> -{
> -	struct lov_stripe_md *lsm = lov->lo_lsm;
> -	struct ost_lvb *lvb = &lov_env_info(env)->lti_lvb;
> -	struct cl_attr *attr = &r0->lo_attr;
> -	int result = 0;
> -	u64 kms = 0;
> -
> -	if (r0->lo_attr_valid)
> -		return 0;
> -
> -	memset(lvb, 0, sizeof(*lvb));
> -
> -	/* XXX: timestamps can be negative by sanity:test_39m,
> -	 * how can it be?
> -	 */
> -	lvb->lvb_atime = LLONG_MIN;
> -	lvb->lvb_ctime = LLONG_MIN;
> -	lvb->lvb_mtime = LLONG_MIN;
> -
> -	/*
> -	 * XXX that should be replaced with a loop over sub-objects,
> -	 * doing cl_object_attr_get() on them. But for now, let's
> -	 * reuse old lov code.
> -	 */
> -
> -	/*
> -	 * XXX take lsm spin-lock to keep lov_merge_lvb_kms()
> -	 * happy. It's not needed, because new code uses
> -	 * ->coh_attr_guard spin-lock to protect consistency of
> -	 * sub-object attributes.
> -	 */
> -	lov_stripe_lock(lsm);
> -	result = lov_merge_lvb_kms(lsm, index, lvb, &kms);
> -	lov_stripe_unlock(lsm);
> -	if (result)
> -		return result;
> -
> -	cl_lvb2attr(attr, lvb);
> -	attr->cat_kms = kms;
> -	r0->lo_attr_valid = 1;
> -
> -	return result;
> -}
> -
>  static int lov_attr_get_composite(const struct lu_env *env,
>  				  struct cl_object *obj,
>  				  struct cl_attr *attr)
> @@ -653,19 +827,22 @@ static int lov_attr_get_composite(const struct lu_env *env,
>  	attr->cat_size = 0;
>  	attr->cat_blocks = 0;
>  	lov_foreach_layout_entry(lov, entry) {
> -		struct lov_layout_raid0 *r0 = &entry->lle_raid0;
> -		struct cl_attr *lov_attr = &r0->lo_attr;
> +		struct cl_attr *lov_attr = NULL;
>  
>  		/* PFL: This component has not been init-ed. */
>  		if (!lsm_entry_inited(lov->lo_lsm, index))
>  			break;
>  
> -		result = lov_attr_get_raid0(env, lov, index, r0);
> -		if (result != 0)
> -			break;
> +		result = entry->lle_comp_ops->lco_getattr(env, lov, index,
> +							  entry, &lov_attr);
> +		if (result < 0)
> +			return result;
>  
>  		index++;
>  
> +		if (!lov_attr)
> +			continue;
> +
>  		/* merge results */
>  		attr->cat_blocks += lov_attr->cat_blocks;
>  		if (attr->cat_size < lov_attr->cat_size)
> @@ -679,7 +856,7 @@ static int lov_attr_get_composite(const struct lu_env *env,
>  		if (attr->cat_mtime < lov_attr->cat_mtime)
>  			attr->cat_mtime = lov_attr->cat_mtime;
>  	}
> -	return result;
> +	return 0;
>  }
>  
>  static const struct lov_layout_operations lov_dispatch[] = {
> @@ -1235,6 +1412,49 @@ struct fiemap_state {
>  	bool			fs_enough;
>  };
>  
> +static struct cl_object *lov_find_subobj(const struct lu_env *env,
> +					 struct lov_object *lov,
> +					 struct lov_stripe_md *lsm,
> +					 int index)
> +{
> +	struct lov_device *dev = lu2lov_dev(lov2lu(lov)->lo_dev);
> +	struct lov_thread_info *lti = lov_env_info(env);
> +	struct lu_fid *ofid = &lti->lti_fid;
> +	struct lov_oinfo *oinfo;
> +	struct cl_device *subdev;
> +	int entry = lov_comp_entry(index);
> +	int stripe = lov_comp_stripe(index);
> +	int ost_idx;
> +	int rc;
> +	struct cl_object *result;
> +
> +	if (lov->lo_type != LLT_COMP) {
> +		result = NULL;
> +		goto out;
> +	}
> +
> +	if (entry >= lsm->lsm_entry_count ||
> +	    stripe >= lsm->lsm_entries[entry]->lsme_stripe_count) {
> +		result = NULL;
> +		goto out;
> +	}
> +
> +	oinfo = lsm->lsm_entries[entry]->lsme_oinfo[stripe];
> +	ost_idx = oinfo->loi_ost_idx;
> +	rc = ostid_to_fid(ofid, &oinfo->loi_oi, ost_idx);
> +	if (rc != 0) {
> +		result = NULL;
> +		goto out;
> +	}
> +
> +	subdev = lovsub2cl_dev(dev->ld_target[ost_idx]);
> +	result = lov_sub_find(env, subdev, ofid, NULL);
> +out:
> +	if (!result)
> +		result = ERR_PTR(-EINVAL);
> +	return result;
> +}
> +
>  static int fiemap_for_stripe(const struct lu_env *env, struct cl_object *obj,
>  			     struct lov_stripe_md *lsm, struct fiemap *fiemap,
>  			     size_t *buflen, struct ll_fiemap_info_key *fmkey,
> @@ -1457,6 +1677,12 @@ static int lov_object_fiemap(const struct lu_env *env, struct cl_object *obj,
>  		}
>  	}
>  
> +	/* No support for DOM layout yet. */
> +	if (lsme_is_dom(lsm->lsm_entries[0])) {
> +		rc = -ENOTSUPP;
> +		goto out_lsm;
> +	}
> +
>  	if (lsm->lsm_is_released) {
>  		if (fiemap->fm_start < fmkey->lfik_oa.o_size) {
>  			/**
> diff --git a/fs/lustre/lov/lov_offset.c b/fs/lustre/lov/lov_offset.c
> index 26f5066..56a2d7b 100644
> --- a/fs/lustre/lov/lov_offset.c
> +++ b/fs/lustre/lov/lov_offset.c
> @@ -43,6 +43,9 @@ static u64 stripe_width(struct lov_stripe_md *lsm, unsigned int index)
>  
>  	LASSERT(index < lsm->lsm_entry_count);
>  
> +	if (lsme_is_dom(entry))
> +		return (loff_t)entry->lsme_stripe_size;
> +
>  	return entry->lsme_stripe_size * entry->lsme_stripe_count;
>  }
>  
> diff --git a/fs/lustre/mdc/mdc_request.c b/fs/lustre/mdc/mdc_request.c
> index 1103c15..eefaf44 100644
> --- a/fs/lustre/mdc/mdc_request.c
> +++ b/fs/lustre/mdc/mdc_request.c
> @@ -2265,7 +2265,12 @@ static int mdc_set_info_async(const struct lu_env *env,
>  		return 0;
>  	}
>  
> -	CERROR("Unknown key %s\n", (char *)key);
> +	/* TODO: these OSC-related keys are ignored for now */
> +	if (KEY_IS(KEY_CHECKSUM) || KEY_IS(KEY_CACHE_SET) ||
> +	    KEY_IS(KEY_CACHE_LRU_SHRINK) || KEY_IS(KEY_GRANT_SHRINK))
> +		return 0;
> +
> +	CERROR("%s: Unknown key %s\n", exp->exp_obd->obd_name, (char *)key);
>  	return -EINVAL;
>  }
>  
> diff --git a/fs/lustre/obdclass/obd_config.c b/fs/lustre/obdclass/obd_config.c
> index 73264fd..26b3e01 100644
> --- a/fs/lustre/obdclass/obd_config.c
> +++ b/fs/lustre/obdclass/obd_config.c
> @@ -972,7 +972,6 @@ int class_process_config(struct lustre_cfg *lcfg)
>  		err = -EINVAL;
>  		goto out;
>  	}
> -
>  	switch (lcfg->lcfg_command) {
>  	case LCFG_SETUP: {
>  		err = class_setup(obd, lcfg);
> @@ -1020,6 +1019,41 @@ int class_process_config(struct lustre_cfg *lcfg)
>  		err = 0;
>  		goto out;
>  	}
> +	/* Process config log ADD_MDC record twice to add MDC also to LOV
> +	 * for Data-on-MDT:
> +	 *
> +	 * add 0:lustre-clilmv 1:lustre-MDT0000_UUID 2:0 3:1
> +	 *     4:lustre-MDT0000-mdc_UUID
> +	 */
> +	case LCFG_ADD_MDC: {
> +		struct obd_device *lov_obd;
> +		char *clilmv;
> +
> +		err = obd_process_config(obd, sizeof(*lcfg), lcfg);
> +		if (err)
> +			goto out;
> +
> +		/* make sure this is client LMV log entry */
> +		clilmv = strstr(lustre_cfg_string(lcfg, 0), "clilmv");
> +		if (!clilmv)
> +			goto out;
> +
> +		/* replace 'lmv' with 'lov' name to address LOV device and
> +		 * process llog record to add MDC there.
> +		 */
> +		clilmv[4] = 'o';
> +		lov_obd = class_name2obd(lustre_cfg_string(lcfg, 0));
> +		if (!lov_obd) {
> +			err = -ENOENT;
> +			CERROR("%s: Cannot find LOV by %s name, rc = %d\n",
> +			       obd->obd_name, lustre_cfg_string(lcfg, 0), err);
> +		} else {
> +			err = obd_process_config(lov_obd, sizeof(*lcfg), lcfg);
> +		}
> +		/* restore 'lmv' name */
> +		clilmv[4] = 'm';
> +		goto out;
> +	}
>  	default: {
>  		err = obd_process_config(obd, sizeof(*lcfg), lcfg);
>  		goto out;
> diff --git a/fs/lustre/ptlrpc/wiretest.c b/fs/lustre/ptlrpc/wiretest.c
> index eb8bffe..2a38d1e 100644
> --- a/fs/lustre/ptlrpc/wiretest.c
> +++ b/fs/lustre/ptlrpc/wiretest.c
> @@ -1479,8 +1479,8 @@ void lustre_assert_wire_constants(void)
>  		 (unsigned int)LOV_PATTERN_RAID0);
>  	LASSERTF(LOV_PATTERN_RAID1 == 0x00000002UL, "found 0x%.8xUL\n",
>  		 (unsigned int)LOV_PATTERN_RAID1);
> -	LASSERTF(LOV_PATTERN_FIRST == 0x00000100UL, "found 0x%.8xUL\n",
> -		 (unsigned int)LOV_PATTERN_FIRST);
> +	LASSERTF(LOV_PATTERN_MDT == 0x00000100UL, "found 0x%.8xUL\n",
> +		 (unsigned int)LOV_PATTERN_MDT);
>  	LASSERTF(LOV_PATTERN_CMOBD == 0x00000200UL, "found 0x%.8xUL\n",
>  		 (unsigned int)LOV_PATTERN_CMOBD);
>  
> diff --git a/include/uapi/linux/lustre/lustre_user.h b/include/uapi/linux/lustre/lustre_user.h
> index 17bad49..4a6ed5e 100644
> --- a/include/uapi/linux/lustre/lustre_user.h
> +++ b/include/uapi/linux/lustre/lustre_user.h
> @@ -337,7 +337,7 @@ enum ll_lease_type {
>  
>  #define LOV_PATTERN_RAID0	0x001
>  #define LOV_PATTERN_RAID1	0x002
> -#define LOV_PATTERN_FIRST	0x100
> +#define LOV_PATTERN_MDT		0x100
>  #define LOV_PATTERN_CMOBD	0x200
>  
>  #define LOV_PATTERN_F_MASK	0xffff0000
> -- 
> 1.8.3.1
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 832 bytes
Desc: not available
URL: <http://lists.lustre.org/pipermail/lustre-devel-lustre.org/attachments/20191001/be422fc2/attachment-0001.sig>

  reply	other threads:[~2019-10-01  0:33 UTC|newest]

Thread overview: 165+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-09-30 18:54 [lustre-devel] [PATCH 000/151] lustre: update to 2.11 support James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 001/151] lnet: fix needed headers for lnet headers James Simmons
2019-10-01  7:24   ` NeilBrown
2019-10-01 17:52     ` James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 002/151] lustre: fix signal handling in abortable waits James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 003/151] lnet: ksocklnd: add secondary IP address handling James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 004/151] lnet: o2iblnd: " James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 005/151] lnet: consoldate " James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 006/151] lustre: support for gcc8 James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 007/151] lnet: Allocate MEs and small MDs in own kmem_caches James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 008/151] lustre: seq: make seq_proc_write_common() safer James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 009/151] lustre: ptlrpc: Fix an rq_no_reply assertion failure James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 010/151] lustre: fld: resend seq lookup RPC if it is on LWP James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 011/151] lustre: fld: retry fld rpc even for ESHUTDOWN James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 012/151] lustre: fld: retry fld rpc until the import is closed James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 013/151] lustre: fld: fld client lookup should retry James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 014/151] lustre: ldlm: testcases for multiple modify RPCs feature James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 015/151] lustre: ldlm: Don't check opcode with NULL rq_reqmsg James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 016/151] lustre: all: remove all Sun license and URL references James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 017/151] lustre: ldlm: Use interval tree to update kms James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 018/151] lustre: osc: prepare OSC code to be used from MDC James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 019/151] lustre: statahead: support striped directory James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 020/151] lustre: readdir: improve striped readdir James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 021/151] lustre: llog: consolidate common error checking James Simmons
2019-10-01  1:29   ` NeilBrown
2019-10-01 17:51     ` James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 022/151] lustre: llite: NULL pointer dereference in cl_object_top() James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 023/151] lustre: ptlrpc: remove incorrect pid printing James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 024/151] lnet: Fix lost lock James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 025/151] lustre: llite: Reduce overhead for ll_do_fast_read James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 026/151] lustre: ptlrpc: change cr_sent_tv from timespec to ktime James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 027/151] lustre: ptlrpc: Use C99 initializer in ptlrpc_register_rqbd() James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 028/151] lustre: lmv: stripe dir page may be released mistakenly James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 029/151] lnet: selftest: Use C99 struct initializer in framework.c James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 030/151] lnet: fix memory leak and lnet_interfaces_max James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 031/151] lnet: decref on peer after use James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 032/151] lnet: rediscover peer if it changed James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 033/151] lnet: resolve unsafe list access James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 034/151] lustre: llite: Implement ladvise lockahead James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 035/151] lustre: jobstats: move jobstats code into separate file James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 036/151] lustre: ldlm: don't use jiffies as sysfs parameter James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 037/151] lnet: Handle ping buffer with only loopback NID James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 038/151] lustre: llite: enable readahead for small read_ahead_per_file James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 039/151] lnet: don't discover loopback interface James Simmons
2019-09-30 18:54 ` [lustre-devel] [PATCH 040/151] lnet: reduce logging severity James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 041/151] lustre: ptlrpc: migrate pinger to 64 bit time James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 042/151] lustre: mdc: add cl_device to the MDC James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 043/151] lustre: lov: add MDT target to the LOV device James Simmons
2019-10-01  0:33   ` NeilBrown [this message]
2019-10-01 18:03     ` James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 044/151] lustre: mdt: IO request handling in MDT James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 045/151] lustre: osc: common client setup/cleanup James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 046/151] lustre: mdc: add IO methods to the MDC James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 047/151] lustre: lvbo: pass lock as parameter to lvbo_update() James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 048/151] lustre: mds: add IO locking to the MDC and MDT James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 049/151] lustre: mdc: add IO stats in mdc James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 050/151] lustre: lov: add Data-on-MDT tests and fixes James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 051/151] lustre: mdc: use generic grant code at MDT James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 052/151] lustre: mds: combine DoM bit with other IBITS James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 053/151] lustre: llite: increase whole-file readahead to RPC size James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 054/151] lustre: ldlm: remove liblustre remnants James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 055/151] lustre: misc: replace LASSERT() with BUILD_BUG_ON() James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 056/151] lustre: llite: check layout size after cl_object_layout_get James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 057/151] lustre: mdc: implement own mdc_io_fsync_start() James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 058/151] lustre: ldlm: migrate the rest of the code to 64 bit time James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 059/151] lustre: llite: sync bdi sysfs name with lustre sysfs tree James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 060/151] lustre: lov: allow lov.*.stripe{size, count}=-1 param James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 061/151] lustre: brw: add short io osc/ost transfer James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 062/151] lustre: lov: take lov layout lock for I/O with ignore_layout James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 063/151] lustre: lov: pack lsm_flags from layout James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 064/151] lustre: clio: introduce CIT_GLIMPSE for glimpse James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 065/151] lustre: flr: add infrastructure to create a new mirror James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 066/151] lustre: clio: no glimpse for data immutable file James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 067/151] lustre: flr: read support for flr James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 068/151] lustre: lov: rework write intent on componect instantiation James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 069/151] lustre: ptlrpc: use lu_extent in layout_intent James Simmons
2019-10-01  3:26   ` NeilBrown
2019-10-01 17:54     ` James Simmons
2019-10-01 23:19       ` NeilBrown
2019-10-04 20:39       ` Cory Spitz
2019-09-30 18:55 ` [lustre-devel] [PATCH 070/151] lustre: flr: Send write intent RPC to mdt James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 071/151] lustre: flr: extend DATA_VERSION API to read layout version James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 072/151] lustre: lov: skip empty pages in lov_io_submit() James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 073/151] lustre: mdc: don't assert on name pack James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 074/151] lustre: flr: mirror read and write James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 075/151] lustre: flr: resync support and test tool James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 076/151] lustre: flr: randomize mirror pick James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 077/151] lustre: flr: instantiate component for truncate James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 078/151] lustre: hsm: don't release with wrong size James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 079/151] lustre: mdc: Add an additional set of 64 changelog flags James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 080/151] lustre: ldlm: assume OBD_CONNECT_IBITS James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 081/151] lustre: llite: assume OBD_CONNECT_ATTRFID James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 082/151] lustre: llite: simplify ll_inode_revalidate() James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 083/151] lustre: obd: free obd_svc_stats when all users are gone James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 084/151] lustre: mdc: add uid/gid to Changelogs entries James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 085/151] lustre: scrub: general framework for OI scrub James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 086/151] lustre: idl: clean up and document ptlrpc structures James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 087/151] lustre: idl: remove obsolete RPC MSG flags James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 088/151] lnet: libcfs: call proper crypto algo when keys are passed in James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 089/151] lustre: clio: remove unused cl_lock layers James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 090/151] lustre: sec: migrate to 64 bit time James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 091/151] lustre: llite: avoid live-lock when concurrent mmap()s James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 092/151] lustre: llite: change lli_glimpse_time to ktime James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 093/151] lustre: hsm: filter kkuc write by client UUID James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 094/151] lustre: dne: allow mkdir with specific MDTs James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 095/151] lustre: misc: update Intel copyright messages for 2017 James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 096/151] lustre: fid: improve seq allocation error messages James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 097/151] lustre: mdc: interruptable during RPC retry for EINPROGRESS James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 098/151] lustre: osc: migrate to 64 bit time James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 099/151] lustre: vvp: Print discarded page warning on -EIO James Simmons
2019-09-30 18:55 ` [lustre-devel] [PATCH 100/151] lustre: clio: Use readahead for partial page write James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 101/151] lustre: flr: comp-flags support when creating mirrors James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 102/151] lustre: libcfs: remove cfs_time_XXX_64 wrappers James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 103/151] lustre: address issues raised by gcc7 James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 104/151] lustre: lov: fill no-extent fiemap on object with no stripe James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 105/151] lustre: ptlrpc: allow to limit number of service's rqbds James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 106/151] lnet: ensure peer put back on dc request queue James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 107/151] lustre: recovery: support setstripe replay James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 108/151] lustre: lustre: move LA_* flags to lustre_user.h James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 109/151] lustre: flr: revise lease API James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 110/151] lustre: idl: add PTLRPC definitions to enum James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 111/151] lustre: obd: remove s2dhms time function James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 112/151] lustre: mdc: add client NID to Changelogs entries James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 113/151] lustre: mdc: implement CL_OPEN for Changelogs James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 114/151] lustre: acl: prepare small buffer for ACL RPC reply James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 115/151] lnet: safe access in debug print James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 116/151] lnet: Remove LASSERT on userspace data James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 117/151] lustre: flr: split a mirror from mirrored file James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 118/151] lustre: llite: deny 2.10 clients to open mirrored files James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 119/151] lustre: uapi: rename LCM_FL_NOT_FLR to LCM_FL_NONE James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 120/151] lustre: flr: layout truncate compatibility James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 121/151] lustre: mdc: high-priority request handling for DOM James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 122/151] lustre: llite: Add tiny write support James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 123/151] lustre: mdc: add CL_GETXATTR for Changelogs James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 124/151] lustre: uapi: record denied OPEN in Changelogs James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 125/151] lustre: llite: have ll_write_end to sync for DIO James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 126/151] lustre: obd: add check to obd_statfs James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 127/151] lustre: obd: fix statfs handling James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 128/151] lustre: dom: support DATA_VERSION IO type James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 129/151] lnet: fix contiguous range support James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 130/151] lustre: osc: add a bit to indicate osc_page in cache tree James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 131/151] lustre: ldlm: fix export reference James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 132/151] lustre: llite: Add exit for filedata allocation failed James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 133/151] lustre: misc: Wrong checksum return value James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 134/151] lustre: llite: fix mount error handing James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 135/151] lustre: llite: Disable tiny writes for append James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 136/151] lustre: uapi: replace FMODE_{READ, WRITE} with MDS_* equivs James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 137/151] lnet: reduce discovery timeout James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 138/151] lustre: update version to 2.10.99 James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 139/151] lustre: ptlrpc: clarify 64 bit time usage James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 140/151] lustre: ptlrpc: add watchdog for ptlrpc service threads James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 141/151] lustre: handles: discard h_owner in favour of h_ops James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 142/151] lustre: ldlm: Remove use of SLAB_DESTROY_BY_RCU for ldlm lock slab James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 143/151] lustre: ldlm: simplify lock_mode_to_index() James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 144/151] lustre: ptlrpc: use list_move where appropriate James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 145/151] lustre: ptlrpc: simplify locking in ptlrpc_add_rqs_to_pool() James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 146/151] lustre: ptlrpc: incorporate BUILD_BUG_ON into ptlrpc_req_async_args() James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 147/151] lustre: introduce CONFIG_LUSTRE_FS_POSIX_ACL James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 148/151] lustre: ptlrpc: discard a server-only waitq James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 149/151] lustre: llite: remove // comments James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 150/151] lustre: remove outdated comments about ->ap_* functions James Simmons
2019-09-30 18:56 ` [lustre-devel] [PATCH 151/151] lustre: clean up some comment alignment James Simmons
2019-10-01  7:01 ` [lustre-devel] [PATCH 000/151] lustre: update to 2.11 support NeilBrown
2019-10-01 18:07   ` James Simmons
2019-10-02  0:52     ` NeilBrown

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87wodp718v.fsf@notabene.neil.brown.name \
    --to=neilb@suse.de \
    --cc=lustre-devel@lists.lustre.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.