Whamcloud - gitweb
LU-14448 lod: verify LOV before set/inherit
[fs/lustre-release.git] / lustre / lod / lod_object.c
index f4829a3..95319e5 100644 (file)
@@ -1262,9 +1262,11 @@ static bool lod_obj_attr_set_comp_skip_cb(const struct lu_env *env,
                }
                break;
        }
+       case LCM_FL_RDONLY:
+       case LCM_FL_SYNC_PENDING:
+               break;
        default:
                LASSERTF(0, "impossible: %d\n", lo->ldo_flr_state);
-       case LCM_FL_SYNC_PENDING:
                break;
        }
 
@@ -2411,9 +2413,11 @@ static int lod_dir_layout_set(const struct lu_env *env,
                RETURN(-EINVAL);
 
        /* adjust hash for dir merge, which may not be set in user command */
-       if (lmv_is_merging(lmv) && !lmv->lmv_migrate_hash)
-               lmv->lmv_merge_hash =
-                       lod->lod_mdt_descs.ltd_lmv_desc.ld_pattern;
+       if (lmv_is_merging(lmv) &&
+           !(lmv->lmv_migrate_hash & LMV_HASH_TYPE_MASK))
+               lmv->lmv_merge_hash |=
+                       lod->lod_mdt_descs.ltd_lmv_desc.ld_pattern &
+                       LMV_HASH_TYPE_MASK;
 
        LMV_DEBUG(D_INFO, lmv, "set");
 
@@ -2654,7 +2658,9 @@ __u16 lod_comp_entry_stripe_count(struct lod_object *lo,
                return lod->lod_ost_count;
        else
                return lod_get_stripe_count(lod, lo, comp_idx,
-                                           entry->llc_stripe_count, false);
+                                           entry->llc_stripe_count,
+                                           entry->llc_pattern &
+                                           LOV_PATTERN_OVERSTRIPING);
 }
 
 static int lod_comp_md_size(struct lod_object *lo, bool is_dir)
@@ -3270,13 +3276,14 @@ static int lod_declare_layout_merge(const struct lu_env *env,
                struct dt_object *dt, const struct lu_buf *mbuf,
                struct thandle *th)
 {
-       struct lod_thread_info  *info = lod_env_info(env);
-       struct lu_buf           *buf = &info->lti_buf;
-       struct lod_object       *lo = lod_dt_obj(dt);
-       struct lov_comp_md_v1   *lcm;
-       struct lov_comp_md_v1   *cur_lcm;
-       struct lov_comp_md_v1   *merge_lcm;
-       struct lov_comp_md_entry_v1     *lcme;
+       struct lod_thread_info *info = lod_env_info(env);
+       struct lu_attr *layout_attr = &info->lti_layout_attr;
+       struct lu_buf *buf = &info->lti_buf;
+       struct lod_object *lo = lod_dt_obj(dt);
+       struct lov_comp_md_v1 *lcm;
+       struct lov_comp_md_v1 *cur_lcm;
+       struct lov_comp_md_v1 *merge_lcm;
+       struct lov_comp_md_entry_v1 *lcme;
        struct lov_mds_md_v1 *lmm;
        size_t size = 0;
        size_t offset;
@@ -3285,7 +3292,7 @@ static int lod_declare_layout_merge(const struct lu_env *env,
        __u32 id = 0;
        __u16 mirror_id = 0;
        __u32 mirror_count;
-       int     rc, i;
+       int rc, i;
        bool merge_has_dom;
 
        ENTRY;
@@ -3404,8 +3411,6 @@ static int lod_declare_layout_merge(const struct lu_env *env,
        }
 
        /* fixup layout information */
-       lod_obj_inc_layout_gen(lo);
-       lcm->lcm_layout_gen = cpu_to_le32(lo->ldo_layout_gen);
        lcm->lcm_size = cpu_to_le32(size);
        lcm->lcm_entry_count = cpu_to_le16(cur_entry_count + merge_entry_count);
        lcm->lcm_mirror_count = cpu_to_le16(mirror_count);
@@ -3416,6 +3421,23 @@ static int lod_declare_layout_merge(const struct lu_env *env,
        if (rc)
                GOTO(out, rc);
 
+       lod_obj_inc_layout_gen(lo);
+       lcm->lcm_layout_gen = cpu_to_le32(lo->ldo_layout_gen);
+
+       /* transfer layout version to OST objects. */
+       if (lo->ldo_mirror_count > 1) {
+               struct lod_obj_stripe_cb_data data = { {0} };
+
+               layout_attr->la_valid = LA_LAYOUT_VERSION;
+               layout_attr->la_layout_version = 0;
+               data.locd_attr = layout_attr;
+               data.locd_declare = true;
+               data.locd_stripe_cb = lod_obj_stripe_attr_set_cb;
+               rc = lod_obj_for_each_stripe(env, lo, th, &data);
+               if (rc)
+                       GOTO(out, rc);
+       }
+
        rc = lod_sub_declare_xattr_set(env, dt_object_child(dt), buf,
                                        XATTR_NAME_LOV, LU_XATTR_REPLACE, th);
 
@@ -3431,6 +3453,8 @@ static int lod_declare_layout_split(const struct lu_env *env,
                struct dt_object *dt, const struct lu_buf *mbuf,
                struct thandle *th)
 {
+       struct lod_thread_info *info = lod_env_info(env);
+       struct lu_attr *layout_attr = &info->lti_layout_attr;
        struct lod_object *lo = lod_dt_obj(dt);
        struct lov_comp_md_v1 *lcm = mbuf->lb_buf;
        int rc;
@@ -3444,6 +3468,21 @@ static int lod_declare_layout_split(const struct lu_env *env,
        /* fix on-disk layout gen */
        lcm->lcm_layout_gen = cpu_to_le32(lo->ldo_layout_gen);
 
+
+       /* transfer layout version to OST objects. */
+       if (lo->ldo_mirror_count > 1) {
+               struct lod_obj_stripe_cb_data data = { {0} };
+
+               layout_attr->la_valid = LA_LAYOUT_VERSION;
+               layout_attr->la_layout_version = 0;
+               data.locd_attr = layout_attr;
+               data.locd_declare = true;
+               data.locd_stripe_cb = lod_obj_stripe_attr_set_cb;
+               rc = lod_obj_for_each_stripe(env, lo, th, &data);
+               if (rc)
+                       RETURN(rc);
+       }
+
        rc = lod_sub_declare_xattr_set(env, dt_object_child(dt), mbuf,
                                       XATTR_NAME_LOV, LU_XATTR_REPLACE, th);
        RETURN(rc);
@@ -4252,6 +4291,8 @@ static int lod_dir_striping_create_internal(const struct lu_env *env,
 
        /* Transfer default LMV striping from the parent */
        if (lds != NULL && lds->lds_dir_def_striping_set &&
+           lds->lds_dir_def_max_inherit != LMV_INHERIT_END &&
+           lds->lds_dir_def_max_inherit != LMV_INHERIT_NONE &&
            !(LMVEA_DELETE_VALUES(lds->lds_dir_def_stripe_count,
                                 lds->lds_dir_def_stripe_offset) &&
              le32_to_cpu(lds->lds_dir_def_hash_type) !=
@@ -4273,6 +4314,10 @@ static int lod_dir_striping_create_internal(const struct lu_env *env,
                        cpu_to_le32(lds->lds_dir_def_stripe_offset);
                v1->lum_hash_type =
                        cpu_to_le32(lds->lds_dir_def_hash_type);
+               v1->lum_max_inherit =
+                       lmv_inherit_next(lds->lds_dir_def_max_inherit);
+               v1->lum_max_inherit_rr =
+                       lmv_inherit_rr_next(lds->lds_dir_def_max_inherit_rr);
 
                info->lti_buf.lb_buf = v1;
                info->lti_buf.lb_len = sizeof(*v1);
@@ -4732,7 +4777,10 @@ static int lod_xattr_set(const struct lu_env *env,
                         const char *name, int fl, struct thandle *th)
 {
        struct dt_object *next = dt_object_child(dt);
-       int rc;
+       struct lu_attr *layout_attr = &lod_env_info(env)->lti_layout_attr;
+       struct lod_object *lo = lod_dt_obj(dt);
+       struct lod_obj_stripe_cb_data data = { {0} };
+       int rc = 0;
 
        ENTRY;
 
@@ -4826,6 +4874,29 @@ static int lod_xattr_set(const struct lu_env *env,
                        lod_striping_free(env, lod_dt_obj(dt));
 
                        rc = lod_sub_xattr_set(env, next, buf, name, fl, th);
+               } else if (fl & LU_XATTR_SPLIT) {
+                       rc = lod_sub_xattr_set(env, next, buf, name, fl, th);
+                       if (rc)
+                               RETURN(rc);
+
+                       rc = lod_striping_reload(env, lo, buf);
+                       if (rc)
+                               RETURN(rc);
+
+                       if (lo->ldo_mirror_count > 1 &&
+                           layout_attr->la_valid & LA_LAYOUT_VERSION) {
+                               /* mirror split */
+                               layout_attr->la_layout_version =
+                                               lo->ldo_layout_gen;
+                               data.locd_attr = layout_attr;
+                               data.locd_declare = false;
+                               data.locd_stripe_cb =
+                                               lod_obj_stripe_attr_set_cb;
+                               rc = lod_obj_for_each_stripe(env, lo, th,
+                                                            &data);
+                               if (rc)
+                                       RETURN(rc);
+                       }
                } else if (fl & LU_XATTR_PURGE) {
                        rc = lod_layout_purge(env, dt, buf, th);
                } else if (dt_object_remote(dt)) {
@@ -4856,6 +4927,23 @@ static int lod_xattr_set(const struct lu_env *env,
                                !lod_dt_obj(dt)->ldo_comp_cached));
 
                        rc = lod_striped_create(env, dt, NULL, NULL, th);
+                       if (rc)
+                               RETURN(rc);
+
+                       if (fl & LU_XATTR_MERGE && lo->ldo_mirror_count > 1 &&
+                           layout_attr->la_valid & LA_LAYOUT_VERSION) {
+                               /* mirror merge exec phase */
+                               layout_attr->la_layout_version =
+                                               lo->ldo_layout_gen;
+                               data.locd_attr = layout_attr;
+                               data.locd_declare = false;
+                               data.locd_stripe_cb =
+                                               lod_obj_stripe_attr_set_cb;
+                               rc = lod_obj_for_each_stripe(env, lo, th,
+                                                            &data);
+                               if (rc)
+                                       RETURN(rc);
+                       }
                }
                RETURN(rc);
        } else if (strcmp(name, XATTR_NAME_FID) == 0) {
@@ -5037,6 +5125,8 @@ static int lod_get_default_lov_striping(const struct lu_env *env,
 
        ENTRY;
 
+       lds->lds_def_striping_set = 0;
+
        rc = lod_get_lov_ea(env, lo);
        if (rc < 0)
                RETURN(rc);
@@ -5195,6 +5285,8 @@ static int lod_get_default_lmv_striping(const struct lu_env *env,
                                le32_to_cpu(lmu->lum_stripe_offset);
                lds->lds_dir_def_hash_type =
                                le32_to_cpu(lmu->lum_hash_type);
+               lds->lds_dir_def_max_inherit = lmu->lum_max_inherit;
+               lds->lds_dir_def_max_inherit_rr = lmu->lum_max_inherit_rr;
                lds->lds_dir_def_striping_set = 1;
        }
 
@@ -5424,7 +5516,12 @@ static void lod_ah_init(const struct lu_env *env,
                 */
                if (likely(lp != NULL)) {
                        lod_get_default_striping(env, lp, lds);
-
+                       if (lds->lds_def_striping_set) {
+                               rc = lod_verify_striping(env, d, lp,
+                                                        &info->lti_buf, false);
+                               if (rc)
+                                       lds->lds_def_striping_set = 0;
+                       }
                        /* inherit default striping except ROOT */
                        if ((lds->lds_def_striping_set ||
                             lds->lds_dir_def_striping_set) &&
@@ -5493,8 +5590,12 @@ static void lod_ah_init(const struct lu_env *env,
         */
        if (likely(lp != NULL)) {
                rc = lod_get_default_lov_striping(env, lp, lds, ah);
-               if (rc == 0)
-                       lod_striping_from_default(lc, lds, child_mode);
+               if (rc == 0 && lds->lds_def_striping_set) {
+                       rc = lod_verify_striping(env, d, lp, &info->lti_buf,
+                                                false);
+                       if (rc == 0)
+                               lod_striping_from_default(lc, lds, child_mode);
+               }
        }
 
        /* Initialize lod_device::lod_md_root object reference */
@@ -5524,8 +5625,14 @@ static void lod_ah_init(const struct lu_env *env,
            lod_need_inherit_more(lc, true, ah->dah_append_pool)) {
                rc = lod_get_default_lov_striping(env, d->lod_md_root, lds,
                                                  ah);
+               if (rc || !lds->lds_def_striping_set)
+                       goto out;
+
+               rc = lod_verify_striping(env, d, d->lod_md_root, &info->lti_buf,
+                                        false);
                if (rc)
                        goto out;
+
                if (lc->ldo_comp_cnt == 0) {
                        lod_striping_from_default(lc, lds, child_mode);
                } else if (!lds->lds_def_striping_is_composite) {
@@ -5837,24 +5944,8 @@ static int lod_declare_create(const struct lu_env *env, struct dt_object *dt,
                        if (OBD_FAIL_CHECK(OBD_FAIL_MDS_STALE_DIR_LAYOUT))
                                GOTO(out, rc = -EREMOTE);
 
-                       if (lo->ldo_dir_stripe_offset == LMV_OFFSET_DEFAULT) {
-                               struct lod_default_striping *lds;
-
-                               lds = lo->ldo_def_striping;
-                               /*
-                                * child and parent should be on the same MDT,
-                                * but if parent has default LMV, and the start
-                                * MDT offset is -1, it's allowed. This check
-                                * is not necessary after 2.12.22 because client
-                                * follows this already, but old client may not.
-                                */
-                               if (hint->dah_parent &&
-                                   dt_object_remote(hint->dah_parent) && lds &&
-                                   lds->lds_dir_def_stripe_offset !=
-                                   LMV_OFFSET_DEFAULT)
-                                       GOTO(out, rc = -EREMOTE);
-                       } else if (lo->ldo_dir_stripe_offset !=
-                                  ss->ss_node_id) {
+                       if (lo->ldo_dir_stripe_offset != LMV_OFFSET_DEFAULT &&
+                           lo->ldo_dir_stripe_offset != ss->ss_node_id) {
                                struct lod_device *lod;
                                struct lu_tgt_desc *mdt = NULL;
                                bool found_mdt = false;
@@ -7376,6 +7467,11 @@ static int lod_primary_pick(const struct lu_env *env, struct lod_object *lo,
         * cluster.
         */
        lod_qos_statfs_update(env, lod, &lod->lod_ost_descs);
+
+       rc = lod_fill_mirrors(lo);
+       if (rc)
+               RETURN(rc);
+
        for (i = 0; i < lo->ldo_mirror_count; i++) {
                bool ost_avail = true;
                int index = (i + seq) % lo->ldo_mirror_count;
@@ -7824,6 +7920,7 @@ static int lod_declare_update_sync_pending(const struct lu_env *env,
                struct thandle *th)
 {
        struct lod_thread_info  *info = lod_env_info(env);
+       struct lu_attr *layout_attr = &info->lti_layout_attr;
        unsigned sync_components = 0;
        unsigned resync_components = 0;
        int i;
@@ -7896,6 +7993,12 @@ static int lod_declare_update_sync_pending(const struct lu_env *env,
        lo->ldo_flr_state = LCM_FL_RDONLY;
        lod_obj_inc_layout_gen(lo);
 
+       layout_attr->la_valid = LA_LAYOUT_VERSION;
+       layout_attr->la_layout_version = 0; /* set current version */
+       rc = lod_declare_attr_set(env, &lo->ldo_obj, layout_attr, th);
+       if (rc)
+               GOTO(out, rc);
+
        info->lti_buf.lb_len = lod_comp_md_size(lo, false);
        rc = lod_sub_declare_xattr_set(env, lod_object_child(lo),
                                       &info->lti_buf, XATTR_NAME_LOV, 0, th);
@@ -8173,9 +8276,9 @@ static int lod_dir_declare_layout_shrink(const struct lu_env *env,
        struct lod_object *lo = lod_dt_obj(dt);
        struct dt_object *next = dt_object_child(dt);
        struct lmv_user_md *lmu = mlc->mlc_buf.lb_buf;
-       __u32 final_stripe_count;
        char *stripe_name = info->lti_key;
        struct lu_buf *lmv_buf = &info->lti_buf;
+       __u32 final_stripe_count;
        struct dt_object *dto;
        int i;
        int rc;
@@ -8201,9 +8304,6 @@ static int lod_dir_declare_layout_shrink(const struct lu_env *env,
                        continue;
 
                if (i < final_stripe_count) {
-                       if (final_stripe_count == 1)
-                               continue;
-
                        rc = lod_sub_declare_xattr_set(env, dto, lmv_buf,
                                                       XATTR_NAME_LMV,
                                                       LU_XATTR_REPLACE, th);
@@ -8427,9 +8527,12 @@ static int lod_dir_layout_shrink(const struct lu_env *env,
        lmv->lmv_magic = cpu_to_le32(LMV_MAGIC_STRIPE);
        lmv->lmv_stripe_count = cpu_to_le32(final_stripe_count);
        lmv->lmv_hash_type = cpu_to_le32(lo->ldo_dir_hash_type) &
-                            cpu_to_le32(LMV_HASH_TYPE_MASK);
+                            cpu_to_le32(LMV_HASH_TYPE_MASK |
+                                        LMV_HASH_FLAG_FIXED);
        lmv->lmv_layout_version =
                        cpu_to_le32(lo->ldo_dir_layout_version + 1);
+       lmv->lmv_migrate_offset = 0;
+       lmv->lmv_migrate_hash = 0;
 
        for (i = 0; i < lo->ldo_dir_stripe_count; i++) {
                dto = lo->ldo_stripe[i];
@@ -8437,14 +8540,6 @@ static int lod_dir_layout_shrink(const struct lu_env *env,
                        continue;
 
                if (i < final_stripe_count) {
-                       /* if only one stripe left, no need to update
-                        * LMV because this stripe will replace master
-                        * object and act as a plain directory.
-                        */
-                       if (final_stripe_count == 1)
-                               continue;
-
-
                        rc = lod_fld_lookup(env, lod,
                                            lu_object_fid(&dto->do_lu),
                                            &mdtidx, &type);