Skip to content

Commit 76ca884

Browse files
paf-49Oleg Drokin
authored andcommitted
LU-10070 lod: SEL: Repeated components
This changes behavior when there is no next component to spill over to. Currently, in that case, we just extend the current component regardless of available space. Now, if there is no following component, we try repeating the current component, creating a new component using the current one as a striping template. We try assigning striping for this component. If there is sufficient free space on the OSTs chosen for this component, it is instantiated and i/o continues there. If there is not sufficient space on the OSTs chosen for the new component, we remove it & extend the current component. This is a behavioral improvement, with no implications for layout sanity checking. Cray-bug-id: LUS-2528 Signed-off-by: Patrick Farrell <[email protected]> Change-Id: If9f364b4105a4bb892dfe673c724e04781c46336 Reviewed-on: https://review.whamcloud.com/33786 Tested-by: jenkins <[email protected]> Tested-by: Maloo <[email protected]> Reviewed-by: Alexey Lyashkov <[email protected]> Reviewed-by: Patrick Farrell <[email protected]> Reviewed-by: Oleg Drokin <[email protected]>
1 parent 3d7895b commit 76ca884

File tree

3 files changed

+721
-17
lines changed

3 files changed

+721
-17
lines changed

lustre/lod/lod_object.c

Lines changed: 165 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4119,6 +4119,112 @@ static int lod_generate_and_set_lovea(const struct lu_env *env,
41194119
RETURN(rc);
41204120
}
41214121

4122+
static __u32 lod_gen_component_id(struct lod_object *lo,
4123+
int mirror_id, int comp_idx);
4124+
4125+
/**
4126+
* Repeat an existing component
4127+
*
4128+
* Creates a new layout by replicating an existing component. Uses striping
4129+
* policy from previous component as a template for the striping for the new
4130+
* new component.
4131+
*
4132+
* New component starts with zero length, will be extended (or removed) before
4133+
* returning layout to client.
4134+
*
4135+
* NB: Reallocates layout components array (lo->ldo_comp_entries), invalidating
4136+
* any pre-existing pointers to components. Handle with care.
4137+
*
4138+
* \param[in] env execution environment for this thread
4139+
* \param[in,out] lo object to update the layout of
4140+
* \param[in] index index of component to copy
4141+
*
4142+
* \retval 0 on success
4143+
* \retval negative errno on error
4144+
*/
4145+
static int lod_layout_repeat_comp(const struct lu_env *env,
4146+
struct lod_object *lo, int index)
4147+
{
4148+
struct lod_layout_component *lod_comp;
4149+
struct lod_layout_component *new_comp = NULL;
4150+
struct lod_layout_component *comp_array;
4151+
int rc = 0, i, new_cnt = lo->ldo_comp_cnt + 1;
4152+
__u16 mirror_id;
4153+
int offset = 0;
4154+
ENTRY;
4155+
4156+
lod_comp = &lo->ldo_comp_entries[index];
4157+
LASSERT(lod_comp_inited(lod_comp) && lod_comp->llc_id != LCME_ID_INVAL);
4158+
4159+
CDEBUG(D_LAYOUT, "repeating component %d\n", index);
4160+
4161+
OBD_ALLOC(comp_array, sizeof(*comp_array) * new_cnt);
4162+
if (comp_array == NULL)
4163+
GOTO(out, rc = -ENOMEM);
4164+
4165+
for (i = 0; i < lo->ldo_comp_cnt; i++) {
4166+
memcpy(&comp_array[i + offset], &lo->ldo_comp_entries[i],
4167+
sizeof(*comp_array));
4168+
4169+
/* Duplicate this component in to the next slot */
4170+
if (i == index) {
4171+
new_comp = &comp_array[i + 1];
4172+
memcpy(&comp_array[i + 1], &lo->ldo_comp_entries[i],
4173+
sizeof(*comp_array));
4174+
/* We must now skip this new component when copying */
4175+
offset = 1;
4176+
}
4177+
}
4178+
4179+
/* Set up copied component */
4180+
new_comp->llc_flags &= ~LCME_FL_INIT;
4181+
new_comp->llc_stripe = NULL;
4182+
new_comp->llc_stripes_allocated = 0;
4183+
new_comp->llc_stripe_offset = LOV_OFFSET_DEFAULT;
4184+
/* for uninstantiated components, layout gen stores default stripe
4185+
* offset */
4186+
new_comp->llc_layout_gen = lod_comp->llc_stripe_offset;
4187+
/* This makes the repeated component zero-length, placed at the end of
4188+
* the preceding component */
4189+
new_comp->llc_extent.e_start = new_comp->llc_extent.e_end;
4190+
new_comp->llc_timestamp = lod_comp->llc_timestamp;
4191+
new_comp->llc_pool = NULL;
4192+
4193+
rc = lod_set_pool(&new_comp->llc_pool, lod_comp->llc_pool);
4194+
if (rc)
4195+
GOTO(out, rc);
4196+
4197+
if (new_comp->llc_ostlist.op_array) {
4198+
__u32 *op_array = NULL;
4199+
4200+
OBD_ALLOC(op_array, new_comp->llc_ostlist.op_size);
4201+
if (!op_array)
4202+
GOTO(out, rc = -ENOMEM);
4203+
memcpy(op_array, &new_comp->llc_ostlist.op_array,
4204+
new_comp->llc_ostlist.op_size);
4205+
new_comp->llc_ostlist.op_array = op_array;
4206+
}
4207+
4208+
OBD_FREE(lo->ldo_comp_entries,
4209+
sizeof(*comp_array) * lo->ldo_comp_cnt);
4210+
lo->ldo_comp_entries = comp_array;
4211+
lo->ldo_comp_cnt = new_cnt;
4212+
4213+
/* Generate an id for the new component */
4214+
mirror_id = mirror_id_of(new_comp->llc_id);
4215+
new_comp->llc_id = LCME_ID_INVAL;
4216+
new_comp->llc_id = lod_gen_component_id(lo, mirror_id, index + 1);
4217+
if (new_comp->llc_id == LCME_ID_INVAL)
4218+
GOTO(out, rc = -ERANGE);
4219+
4220+
EXIT;
4221+
out:
4222+
if (rc)
4223+
OBD_FREE(comp_array, sizeof(*comp_array) * new_cnt);
4224+
4225+
return rc;
4226+
}
4227+
41224228
static int lod_layout_data_init(struct lod_thread_info *info, __u32 comp_cnt)
41234229
{
41244230
ENTRY;
@@ -6359,6 +6465,16 @@ static __u64 lod_extension_new_end(__u64 extension_size, __u64 extent_end,
63596465
return new_end;
63606466
}
63616467

6468+
/* As lod_sel_handler() could be re-entered for the same component several
6469+
* times, this is the data for the next call. Fields could be changed to
6470+
* component indexes when needed, (e.g. if there is no need to instantiate
6471+
* all the previous components up to the current position) to tell the caller
6472+
* where to start over from. */
6473+
struct sel_data {
6474+
int sd_force;
6475+
int sd_repeat;
6476+
};
6477+
63626478
/**
63636479
* Process extent updates for a particular layout component
63646480
*
@@ -6381,8 +6497,15 @@ static __u64 lod_extension_new_end(__u64 extension_size, __u64 extent_end,
63816497
* extension space component, move the start of the next component down
63826498
* accordingly, then notify the caller to restart processing w/the new
63836499
* layout.
6384-
* b. If there is no following component, we extend the current component
6385-
* regardless.
6500+
* b. If there is no following component, we try repeating the current
6501+
* component, creating a new component using the current one as a
6502+
* template (keeping its stripe properties but not specific striping),
6503+
* and try assigning striping for this component. If there is sufficient
6504+
* free space on the OSTs chosen for this component, it is instantiated
6505+
* and i/o continues there.
6506+
*
6507+
* If there is not sufficient space on the new OSTs, we remove this new
6508+
* component & extend the current component.
63866509
*
63876510
* Note further that uninited components followed by extension space can be zero
63886511
* length meaning that we will try to extend them before initializing them, and
@@ -6415,7 +6538,8 @@ static int lod_sel_handler(const struct lu_env *env,
64156538
struct lod_object *lo,
64166539
struct lu_extent *extent,
64176540
struct thandle *th, int *max_comp,
6418-
int index, int write, int *force)
6541+
int index, int write,
6542+
struct sel_data *sd)
64196543
{
64206544
struct lod_device *d = lu2lod_dev(lo->ldo_obj.do_lu.lo_dev);
64216545
struct lod_thread_info *info = lod_env_info(env);
@@ -6424,6 +6548,7 @@ static int lod_sel_handler(const struct lu_env *env,
64246548
struct lod_layout_component *next = NULL;
64256549
__u64 extension_size;
64266550
__u64 new_end = 0;
6551+
bool repeated;
64276552
int change = 0;
64286553
int rc = 0;
64296554
ENTRY;
@@ -6463,21 +6588,24 @@ static int lod_sel_handler(const struct lu_env *env,
64636588
info->lti_count = 1;
64646589
info->lti_comp_idx[0] = index - 1;
64656590
rc = lod_declare_instantiate_components(env, lo, th);
6466-
/* ENOSPC tells us we can't use this component, so it's the
6467-
* same as if check_extension failed. But if there is no next,
6468-
* we have no fall back if we failed to stripe this, and we
6469-
* should return the error. */
6470-
if (rc == -ENOSPC && next)
6591+
/* ENOSPC tells us we can't use this component. If there is
6592+
* a next or we are repeating, we either spill over (next) or
6593+
* extend the original comp (repeat). Otherwise, return the
6594+
* error to the user. */
6595+
if (rc == -ENOSPC && (next || sd->sd_repeat))
64716596
rc = 1;
64726597
if (rc < 0)
64736598
RETURN(rc);
64746599
}
64756600

6476-
if (*force == 0 && rc == 0)
6601+
if (sd->sd_force == 0 && rc == 0)
64776602
rc = !lod_sel_osts_allowed(env, lo, index - 1,
64786603
extension_size, extent,
64796604
&lod_comp->llc_extent, write);
6480-
*force = 0;
6605+
6606+
repeated = !!(sd->sd_repeat);
6607+
sd->sd_repeat = 0;
6608+
sd->sd_force = 0;
64816609

64826610
/* Extend previous component */
64836611
if (rc == 0) {
@@ -6509,8 +6637,29 @@ static int lod_sel_handler(const struct lu_env *env,
65096637
change--;
65106638
}
65116639
lod_sel_adjust_extents(env, lo, *max_comp, index);
6640+
} else if (lod_comp_inited(prev)) {
6641+
/* If there is no next, and the previous component is
6642+
* INIT'ed, try repeating the previous component. */
6643+
LASSERT(repeated == 0);
6644+
rc = lod_layout_repeat_comp(env, lo, index - 1);
6645+
if (rc < 0)
6646+
RETURN(rc);
6647+
change++;
6648+
/* The previous component is a repeated component.
6649+
* Record this so we don't keep trying to repeat it. */
6650+
sd->sd_repeat = 1;
65126651
} else {
6513-
*force = 1;
6652+
/* If the previous component is not INIT'ed, this may
6653+
* be a component we have just instantiated but failed
6654+
* to extend. Or even a repeated component we failed
6655+
* to prepare a striping for. Do not repeat but instead
6656+
* remove the repeated component & force the extention
6657+
* of the original one */
6658+
sd->sd_force = 1;
6659+
if (repeated) {
6660+
prev->llc_id = LCME_ID_INVAL;
6661+
change--;
6662+
}
65146663
}
65156664
}
65166665

@@ -6564,12 +6713,12 @@ static int lod_declare_update_extents(const struct lu_env *env,
65646713
struct lod_thread_info *info = lod_env_info(env);
65656714
struct lod_layout_component *lod_comp;
65666715
bool layout_changed = false;
6716+
struct sel_data sd = { 0 };
65676717
int start_index;
65686718
int i = 0;
65696719
int max_comp = 0;
65706720
int rc = 0, rc2;
65716721
int change = 0;
6572-
int force = 0;
65736722
ENTRY;
65746723

65756724
/* This makes us work on the components of the chosen mirror */
@@ -6590,7 +6739,7 @@ static int lod_declare_update_extents(const struct lu_env *env,
65906739
if (lod_comp->llc_flags & LCME_FL_EXTENSION) {
65916740
layout_changed = true;
65926741
rc = lod_sel_handler(env, lo, extent, th, &max_comp,
6593-
i, write, &force);
6742+
i, write, &sd);
65946743
if (rc < 0)
65956744
GOTO(out, rc);
65966745

@@ -6600,10 +6749,9 @@ static int lod_declare_update_extents(const struct lu_env *env,
66006749
}
66016750
}
66026751

6603-
/* We may have removed components. If so, we must update the start &
6604-
* ends of all the mirrors after the current one, and the end of the
6605-
* current mirror.
6606-
*/
6752+
/* We may have added or removed components. If so, we must update the
6753+
* start & ends of all the mirrors after the current one, and the end
6754+
* of the current mirror. */
66076755
change = max_comp - 1 - lo->ldo_mirrors[pick].lme_end;
66086756
if (change) {
66096757
lo->ldo_mirrors[pick].lme_end += change;

0 commit comments

Comments
 (0)