+ RETURN(rc);
+}
+
+/**
+ * Declare component add. The xattr name is XATTR_LUSTRE_LOV.add, and
+ * the xattr value is binary lov_comp_md_v1 which contains component(s)
+ * to be added.
+ *
+ * \param[in] env execution environment
+ * \param[in] dt dt_object to add components on
+ * \param[in] buf buffer contains components to be added
+ * \parem[in] th thandle
+ *
+ * \retval 0 on success
+ * \retval negative errno on failure
+ */
+static int lod_declare_layout_add(const struct lu_env *env,
+ struct dt_object *dt,
+ const struct lu_buf *buf,
+ struct thandle *th)
+{
+ struct lod_layout_component *comp_array, *lod_comp;
+ struct lod_device *d = lu2lod_dev(dt->do_lu.lo_dev);
+ struct lov_desc *desc = &d->lod_desc;
+ struct lod_object *lo = lod_dt_obj(dt);
+ struct lov_user_md_v1 *v1;
+ struct lov_user_md_v3 *v3;
+ struct lov_comp_md_v1 *comp_v1 = buf->lb_buf;
+ struct lu_extent *ext;
+ __u32 magic;
+ __u64 prev_end;
+ int i, rc, array_cnt;
+ ENTRY;
+
+ LASSERT(lo->ldo_is_composite);
+
+ magic = comp_v1->lcm_magic;
+ /* Replay request, see comment for LOV_MAGIC_DEF */
+ if (unlikely(le32_to_cpu(magic) == LOV_MAGIC_COMP_V1_DEF)) {
+ struct dt_object *next = dt_object_child(dt);
+
+ lod_object_free_striping(env, lo);
+ rc = lod_use_defined_striping(env, lo, buf);
+ if (rc == 0) {
+ lo->ldo_comp_cached = 1;
+ rc = lod_sub_object_declare_xattr_set(env, next, buf,
+ XATTR_NAME_LOV,
+ 0, th);
+ }
+ RETURN(rc);
+ }
+
+ prev_end = lo->ldo_comp_entries[lo->ldo_comp_cnt - 1].llc_extent.e_end;
+ rc = lod_verify_striping(d, buf, false, prev_end);
+ if (rc != 0)
+ RETURN(rc);
+
+ if (magic == __swab32(LOV_USER_MAGIC_COMP_V1)) {
+ lustre_swab_lov_comp_md_v1(comp_v1);
+ magic = comp_v1->lcm_magic;
+ }
+
+ if (magic != LOV_USER_MAGIC_COMP_V1)
+ RETURN(-EINVAL);
+
+ array_cnt = lo->ldo_comp_cnt + comp_v1->lcm_entry_count;
+ OBD_ALLOC(comp_array, sizeof(*comp_array) * array_cnt);
+ if (comp_array == NULL)
+ RETURN(-ENOMEM);
+
+ memcpy(comp_array, lo->ldo_comp_entries,
+ sizeof(*comp_array) * lo->ldo_comp_cnt);
+
+ for (i = 0; i < comp_v1->lcm_entry_count; i++) {
+ v1 = (struct lov_user_md *)((char *)comp_v1 +
+ comp_v1->lcm_entries[i].lcme_offset);
+ ext = &comp_v1->lcm_entries[i].lcme_extent;
+
+ lod_comp = &comp_array[lo->ldo_comp_cnt + i];
+ lod_comp->llc_extent.e_start = ext->e_start;
+ lod_comp->llc_extent.e_end = ext->e_end;
+ lod_comp->llc_stripe_offset = v1->lmm_stripe_offset;
+
+ lod_comp->llc_stripenr = v1->lmm_stripe_count;
+ if (lod_comp->llc_stripenr <= 0)
+ lod_comp->llc_stripenr = desc->ld_default_stripe_count;
+ lod_comp->llc_stripe_size = v1->lmm_stripe_size;
+ if (lod_comp->llc_stripe_size <= 0)
+ lod_comp->llc_stripe_size =
+ desc->ld_default_stripe_size;
+
+ if (v1->lmm_magic == LOV_USER_MAGIC_V3) {
+ int len;
+ v3 = (struct lov_user_md_v3 *) v1;
+ if (v3->lmm_pool_name[0] != '\0') {
+ len = strlen(v3->lmm_pool_name);
+ OBD_ALLOC(lod_comp->llc_pool, len + 1);
+ if (lod_comp->llc_pool == NULL)
+ GOTO(error, rc = -ENOMEM);
+ strncpy(lod_comp->llc_pool, v3->lmm_pool_name,
+ len + 1);
+ }
+ }
+ }
+
+ OBD_FREE(lo->ldo_comp_entries, sizeof(*lod_comp) * lo->ldo_comp_cnt);
+ lo->ldo_comp_entries = comp_array;
+ lo->ldo_comp_cnt = array_cnt;
+ /* No need to increase layout generation here, it will be increased
+ * later when generating component ID for the new components */
+
+ rc = lod_declare_striped_object(env, dt, NULL, NULL, th);
+ RETURN(rc);
+
+error:
+ for (i = lo->ldo_comp_cnt; i < array_cnt; i++) {
+ lod_comp = &comp_array[i];
+ if (lod_comp->llc_pool != NULL) {
+ OBD_FREE(lod_comp->llc_pool,
+ strlen(lod_comp->llc_pool) + 1);
+ lod_comp->llc_pool = NULL;
+ }
+ }
+ OBD_FREE(comp_array, sizeof(*comp_array) * array_cnt);
+ RETURN(rc);
+}
+
+static int lod_comp_md_size(struct lod_object *lo, bool is_dir)
+{
+ int magic, size = 0, i;
+ struct lod_layout_component *comp_entries;
+ __u16 comp_cnt;
+ bool is_composite;
+
+ if (is_dir) {
+ comp_cnt = lo->ldo_def_striping->lds_def_comp_cnt;
+ comp_entries = lo->ldo_def_striping->lds_def_comp_entries;
+ is_composite =
+ lo->ldo_def_striping->lds_def_striping_is_composite;
+ } else {
+ comp_cnt = lo->ldo_comp_cnt;
+ comp_entries = lo->ldo_comp_entries;
+ is_composite = lo->ldo_is_composite;
+ }
+
+
+ LASSERT(comp_cnt != 0 && comp_entries != NULL);
+ if (is_composite) {
+ size = sizeof(struct lov_comp_md_v1) +
+ sizeof(struct lov_comp_md_entry_v1) * comp_cnt;
+ LASSERT(size % sizeof(__u64) == 0);
+ }
+
+ for (i = 0; i < comp_cnt; i++) {
+ magic = comp_entries[i].llc_pool ? LOV_MAGIC_V3 : LOV_MAGIC_V1;
+
+ size += lov_user_md_size(
+ is_dir ? 0 : comp_entries[i].llc_stripenr,
+ magic);
+ LASSERT(size % sizeof(__u64) == 0);
+ }
+ return size;
+}
+
+/**
+ * Declare component set. The xattr is name XATTR_LUSTRE_LOV.set.$field,
+ * the '$field' can only be 'flags' now. The xattr value is binary
+ * lov_comp_md_v1 which contains the component ID(s) and the value of
+ * the field to be modified.
+ *
+ * \param[in] env execution environment
+ * \param[in] dt dt_object to be modified
+ * \param[in] op operation string, like "set.flags"
+ * \param[in] buf buffer contains components to be set
+ * \parem[in] th thandle
+ *
+ * \retval 0 on success
+ * \retval negative errno on failure
+ */
+static int lod_declare_layout_set(const struct lu_env *env,
+ struct dt_object *dt,
+ char *op, const struct lu_buf *buf,
+ struct thandle *th)
+{
+ struct lod_layout_component *lod_comp;
+ struct lod_thread_info *info = lod_env_info(env);
+ struct lod_device *d = lu2lod_dev(dt->do_lu.lo_dev);
+ struct lod_object *lo = lod_dt_obj(dt);
+ struct lov_comp_md_v1 *comp_v1 = buf->lb_buf;
+ __u32 magic, id;
+ int i, j, rc;
+ bool changed = false;
+ ENTRY;
+
+ if (strcmp(op, "set.flags") != 0) {
+ CDEBUG(D_LAYOUT, "%s: operation (%s) not supported.\n",
+ lod2obd(d)->obd_name, op);
+ RETURN(-ENOTSUPP);
+ }
+
+ magic = comp_v1->lcm_magic;
+ if (magic == __swab32(LOV_USER_MAGIC_COMP_V1)) {
+ lustre_swab_lov_comp_md_v1(comp_v1);
+ magic = comp_v1->lcm_magic;
+ }
+
+ if (magic != LOV_USER_MAGIC_COMP_V1)
+ RETURN(-EINVAL);
+
+ if (comp_v1->lcm_entry_count == 0) {
+ CDEBUG(D_LAYOUT, "%s: entry count is zero.\n",
+ lod2obd(d)->obd_name);
+ RETURN(-EINVAL);
+ }
+
+ for (i = 0; i < comp_v1->lcm_entry_count; i++) {
+ id = comp_v1->lcm_entries[i].lcme_id;
+
+ for (j = 0; j < lo->ldo_comp_cnt; j++) {
+ lod_comp = &lo->ldo_comp_entries[j];
+ if (id == lod_comp->llc_id || id == LCME_ID_ALL) {
+ lod_comp->llc_flags =
+ comp_v1->lcm_entries[i].lcme_flags;
+ changed = true;
+ }
+ }
+ }
+
+ if (!changed) {
+ CDEBUG(D_LAYOUT, "%s: requested component(s) not found.\n",
+ lod2obd(d)->obd_name);
+ RETURN(-EINVAL);
+ }
+
+ lod_obj_inc_layout_gen(lo);
+
+ info->lti_buf.lb_len = lod_comp_md_size(lo, false);
+ rc = lod_sub_object_declare_xattr_set(env, dt, &info->lti_buf,
+ XATTR_NAME_LOV, 0, th);
+ RETURN(rc);
+}
+
+/**
+ * Declare component deletion. The xattr name is XATTR_LUSTRE_LOV.del,
+ * and the xattr value is a unique component ID or a special lcme_id.
+ *
+ * \param[in] env execution environment
+ * \param[in] dt dt_object to be operated on
+ * \param[in] buf buffer contains component ID or lcme_id
+ * \parem[in] th thandle
+ *
+ * \retval 0 on success
+ * \retval negative errno on failure
+ */
+static int lod_declare_layout_del(const struct lu_env *env,
+ struct dt_object *dt,
+ const struct lu_buf *buf,
+ struct thandle *th)
+{
+ struct lod_thread_info *info = lod_env_info(env);
+ struct dt_object *next = dt_object_child(dt);
+ struct lod_device *d = lu2lod_dev(dt->do_lu.lo_dev);
+ struct lod_object *lo = lod_dt_obj(dt);
+ struct lu_attr *attr = &lod_env_info(env)->lti_attr;
+ __u32 id;
+ int rc, i, j, left;
+ ENTRY;
+
+ LASSERT(lo->ldo_is_composite);
+
+ id = *(__u32 *)buf->lb_buf;
+ if (id == 0 || id == LCME_ID_NONE) {
+ CDEBUG(D_LAYOUT, "%s: invalid component id %#x\n",
+ lod2obd(d)->obd_name, id);
+ RETURN(-EINVAL);
+ }
+
+ left = lo->ldo_comp_cnt;
+ if (left <= 0)
+ RETURN(-EINVAL);
+
+ for (i = (lo->ldo_comp_cnt - 1); i >= 0; i--) {
+ struct lod_layout_component *lod_comp;
+
+ lod_comp = &lo->ldo_comp_entries[i];
+
+ if (id <= LCME_ID_MAX && id != lod_comp->llc_id)
+ continue;
+ else if (id > LCME_ID_MAX && id < LCME_ID_ALL &&
+ !(id & lod_comp->llc_flags))