@@ -4119,6 +4119,112 @@ static int lod_generate_and_set_lovea(const struct lu_env *env,
4119
4119
RETURN (rc );
4120
4120
}
4121
4121
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
+
4122
4228
static int lod_layout_data_init (struct lod_thread_info * info , __u32 comp_cnt )
4123
4229
{
4124
4230
ENTRY ;
@@ -6359,6 +6465,16 @@ static __u64 lod_extension_new_end(__u64 extension_size, __u64 extent_end,
6359
6465
return new_end ;
6360
6466
}
6361
6467
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
+
6362
6478
/**
6363
6479
* Process extent updates for a particular layout component
6364
6480
*
@@ -6381,8 +6497,15 @@ static __u64 lod_extension_new_end(__u64 extension_size, __u64 extent_end,
6381
6497
* extension space component, move the start of the next component down
6382
6498
* accordingly, then notify the caller to restart processing w/the new
6383
6499
* 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.
6386
6509
*
6387
6510
* Note further that uninited components followed by extension space can be zero
6388
6511
* 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,
6415
6538
struct lod_object * lo ,
6416
6539
struct lu_extent * extent ,
6417
6540
struct thandle * th , int * max_comp ,
6418
- int index , int write , int * force )
6541
+ int index , int write ,
6542
+ struct sel_data * sd )
6419
6543
{
6420
6544
struct lod_device * d = lu2lod_dev (lo -> ldo_obj .do_lu .lo_dev );
6421
6545
struct lod_thread_info * info = lod_env_info (env );
@@ -6424,6 +6548,7 @@ static int lod_sel_handler(const struct lu_env *env,
6424
6548
struct lod_layout_component * next = NULL ;
6425
6549
__u64 extension_size ;
6426
6550
__u64 new_end = 0 ;
6551
+ bool repeated ;
6427
6552
int change = 0 ;
6428
6553
int rc = 0 ;
6429
6554
ENTRY ;
@@ -6463,21 +6588,24 @@ static int lod_sel_handler(const struct lu_env *env,
6463
6588
info -> lti_count = 1 ;
6464
6589
info -> lti_comp_idx [0 ] = index - 1 ;
6465
6590
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 ) )
6471
6596
rc = 1 ;
6472
6597
if (rc < 0 )
6473
6598
RETURN (rc );
6474
6599
}
6475
6600
6476
- if (* force == 0 && rc == 0 )
6601
+ if (sd -> sd_force == 0 && rc == 0 )
6477
6602
rc = !lod_sel_osts_allowed (env , lo , index - 1 ,
6478
6603
extension_size , extent ,
6479
6604
& lod_comp -> llc_extent , write );
6480
- * force = 0 ;
6605
+
6606
+ repeated = !!(sd -> sd_repeat );
6607
+ sd -> sd_repeat = 0 ;
6608
+ sd -> sd_force = 0 ;
6481
6609
6482
6610
/* Extend previous component */
6483
6611
if (rc == 0 ) {
@@ -6509,8 +6637,29 @@ static int lod_sel_handler(const struct lu_env *env,
6509
6637
change -- ;
6510
6638
}
6511
6639
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 ;
6512
6651
} 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
+ }
6514
6663
}
6515
6664
}
6516
6665
@@ -6564,12 +6713,12 @@ static int lod_declare_update_extents(const struct lu_env *env,
6564
6713
struct lod_thread_info * info = lod_env_info (env );
6565
6714
struct lod_layout_component * lod_comp ;
6566
6715
bool layout_changed = false;
6716
+ struct sel_data sd = { 0 };
6567
6717
int start_index ;
6568
6718
int i = 0 ;
6569
6719
int max_comp = 0 ;
6570
6720
int rc = 0 , rc2 ;
6571
6721
int change = 0 ;
6572
- int force = 0 ;
6573
6722
ENTRY ;
6574
6723
6575
6724
/* 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,
6590
6739
if (lod_comp -> llc_flags & LCME_FL_EXTENSION ) {
6591
6740
layout_changed = true;
6592
6741
rc = lod_sel_handler (env , lo , extent , th , & max_comp ,
6593
- i , write , & force );
6742
+ i , write , & sd );
6594
6743
if (rc < 0 )
6595
6744
GOTO (out , rc );
6596
6745
@@ -6600,10 +6749,9 @@ static int lod_declare_update_extents(const struct lu_env *env,
6600
6749
}
6601
6750
}
6602
6751
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. */
6607
6755
change = max_comp - 1 - lo -> ldo_mirrors [pick ].lme_end ;
6608
6756
if (change ) {
6609
6757
lo -> ldo_mirrors [pick ].lme_end += change ;
0 commit comments