From d4f89c82b4f8668518635af8cd924ff25bbb5762 Mon Sep 17 00:00:00 2001 From: shadow <shadow> Date: Wed, 22 Aug 2007 10:13:32 +0000 Subject: [PATCH] Implement async OSC create to avoid the blocking unnecessarily. commit include all fixes from bugs 13143 and 13196. b=4900 i=nathan i=wangdi port to HEAD inspected yury. --- lustre/ChangeLog | 10 +++ lustre/include/obd.h | 1 + lustre/include/obd_class.h | 12 +++ lustre/include/obd_support.h | 1 + lustre/lov/lov_internal.h | 2 + lustre/lov/lov_qos.c | 131 +++++++++++++++++++++++-------- lustre/obdclass/lprocfs_status.c | 1 + lustre/obdfilter/filter.c | 2 + lustre/osc/osc_create.c | 45 +++++++++++ lustre/osc/osc_internal.h | 1 + lustre/osc/osc_request.c | 1 + lustre/tests/sanity.sh | 50 +++++++++++- 12 files changed, 222 insertions(+), 35 deletions(-) diff --git a/lustre/ChangeLog b/lustre/ChangeLog index 3b8bc382f8..cd254c5031 100644 --- a/lustre/ChangeLog +++ b/lustre/ChangeLog @@ -471,6 +471,15 @@ Details : decrease the amount of synchronous RPC between clients and servers by canceling conflicing lock before the operation on the client side and packing thier handles into the main operation RPC to server. +Severity : enhancement +Bugzilla : 4900 +Description: Async OSC create to avoid the blocking unnecessarily. +Details : If a OST has no remain object, system will block on the creating + when need to create a new object on this OST. Now, ways use + pre-created objects when available, instead of blocking on an + empty osc while others are not empty. If we must block, we block + for the shortest possible period of time. + -------------------------------------------------------------------------------- 2007-05-03 Cluster File Systems, Inc. <info@clusterfs.com> @@ -509,6 +518,7 @@ Details : The __iget() symbol export is missing. To avoid the need for * bug fixes + Severity : enhancement Bugzilla : 8007 Description: MountConf diff --git a/lustre/include/obd.h b/lustre/include/obd.h index 56d8918409..9446c160df 100644 --- a/lustre/include/obd.h +++ b/lustre/include/obd.h @@ -1066,6 +1066,7 @@ struct obd_ops { int (*o_preallocate)(struct lustre_handle *, obd_count *req, obd_id *ids); /* FIXME: add fid capability support for create & destroy! */ + int (*o_precreate)(struct obd_export *exp, int need_create); int (*o_create)(struct obd_export *exp, struct obdo *oa, struct lov_stripe_md **ea, struct obd_trans_info *oti); int (*o_destroy)(struct obd_export *exp, struct obdo *oa, diff --git a/lustre/include/obd_class.h b/lustre/include/obd_class.h index fb023077ae..90662fe805 100644 --- a/lustre/include/obd_class.h +++ b/lustre/include/obd_class.h @@ -632,6 +632,18 @@ static inline int obd_checkmd(struct obd_export *exp, RETURN(rc); } +static inline int obd_precreate(struct obd_export *exp, int need_create) +{ + int rc; + ENTRY; + + EXP_CHECK_DT_OP(exp, precreate); + OBD_COUNTER_INCREMENT(exp->exp_obd, precreate); + + rc = OBP(exp->exp_obd, precreate)(exp, need_create); + RETURN(rc); +} + static inline int obd_create(struct obd_export *exp, struct obdo *obdo, struct lov_stripe_md **ea, struct obd_trans_info *oti) diff --git a/lustre/include/obd_support.h b/lustre/include/obd_support.h index 0bc0904e2e..1bfe62d61f 100644 --- a/lustre/include/obd_support.h +++ b/lustre/include/obd_support.h @@ -111,6 +111,7 @@ extern int obd_race_state; #define OBD_FAIL_MDS_WRITEPAGE_NET 0x13a #define OBD_FAIL_MDS_WRITEPAGE_PACK 0x13b #define OBD_FAIL_MDS_LLOG_CREATE_FAILED 0x13c +#define OBD_FAIL_MDS_OSC_PRECREATE 0x13d #define OBD_FAIL_OST 0x200 #define OBD_FAIL_OST_CONNECT_NET 0x201 diff --git a/lustre/lov/lov_internal.h b/lustre/lov/lov_internal.h index 5ded7e18da..a8711e022a 100644 --- a/lustre/lov/lov_internal.h +++ b/lustre/lov/lov_internal.h @@ -147,6 +147,8 @@ int lov_stripe_intersects(struct lov_stripe_md *lsm, int stripeno, int lov_stripe_number(struct lov_stripe_md *lsm, obd_off lov_off); /* lov_qos.c */ +#define LOV_USES_ASSIGNED_STRIPE 0 +#define LOV_USES_DEFAULT_STRIPE 1 int qos_add_tgt(struct obd_device *obd, __u32 index); int qos_del_tgt(struct obd_device *obd, __u32 index); void qos_shrink_lsm(struct lov_request_set *set); diff --git a/lustre/lov/lov_qos.c b/lustre/lov/lov_qos.c index 9ab0f3b7be..866d2602d6 100644 --- a/lustre/lov/lov_qos.c +++ b/lustre/lov/lov_qos.c @@ -37,8 +37,7 @@ #include <obd_lov.h> #include "lov_internal.h" - -/* #define QOS_DEBUG 1 */ +/* #define QOS_DEBUG 1 */ #define D_QOS D_OTHER #define TGT_BAVAIL(i) (lov->lov_tgts[i]->ltd_exp->exp_obd->obd_osfs.os_bavail * \ @@ -55,7 +54,7 @@ int qos_add_tgt(struct obd_device *obd, __u32 index) ENTRY; /* We only need this QOS struct on MDT, not clients - but we may not - have registered the LOV's observer yet, so there's no way to know */ + have registered the LOV's observer yet, so there's no way to know */ if (!exp || !exp->exp_connection) { CERROR("Missing connection\n"); RETURN(-ENOTCONN); @@ -498,19 +497,29 @@ int qos_remedy_create(struct lov_request_set *set, struct lov_request *req) RETURN(rc); } +static int min_stripe_count(int stripe_cnt, int flags) +{ + return (flags & LOV_USES_DEFAULT_STRIPE ? + stripe_cnt - (stripe_cnt / 4) : stripe_cnt); +} + #define LOV_CREATE_RESEED_MULT 4 #define LOV_CREATE_RESEED_MIN 1000 /* Allocate objects on osts with round-robin algorithm */ -static int alloc_rr(struct lov_obd *lov, int *idx_arr, int *stripe_cnt) +static int alloc_rr(struct lov_obd *lov, int *idx_arr, int *stripe_cnt, + int flags) { unsigned array_idx, ost_count = lov->desc.ld_tgt_count; unsigned ost_active_count = lov->desc.ld_active_tgt_count; - int i, *idx_pos = idx_arr; + int i, *idx_pos; __u32 ost_idx; + int ost_start_idx_temp; + int speed = 0; + int stripe_cnt_min = min_stripe_count(*stripe_cnt, flags); ENTRY; i = qos_calc_rr(lov); - if (i) + if (i) RETURN(i); if (--lov->lov_start_count <= 0) { @@ -518,40 +527,61 @@ static int alloc_rr(struct lov_obd *lov, int *idx_arr, int *stripe_cnt) lov->lov_start_count = (LOV_CREATE_RESEED_MIN / max(ost_active_count, 1U) + LOV_CREATE_RESEED_MULT) * max(ost_active_count, 1U); - } else if (*stripe_cnt >= ost_active_count || + } else if (stripe_cnt_min >= ost_active_count || lov->lov_start_idx > ost_count) { /* If we have allocated from all of the OSTs, slowly precess the next start */ lov->lov_start_idx %= ost_count; ++lov->lov_offset_idx; } + down_read(&lov->lov_qos.lq_rw_sem); + ost_start_idx_temp = lov->lov_start_idx; + +repeat_find: array_idx = (lov->lov_start_idx + lov->lov_offset_idx) % ost_count; + idx_pos = idx_arr; #ifdef QOS_DEBUG CDEBUG(D_QOS, "want %d startidx %d startcnt %d offset %d arrayidx %d\n", - *stripe_cnt, lov->lov_start_idx, lov->lov_start_count, + stripe_cnt_min, lov->lov_start_idx, lov->lov_start_count, lov->lov_offset_idx, array_idx); #endif - down_read(&lov->lov_qos.lq_rw_sem); for (i = 0; i < ost_count; i++, array_idx=(array_idx + 1) % ost_count) { ++lov->lov_start_idx; ost_idx = lov->lov_qos.lq_rr_array[array_idx]; #ifdef QOS_DEBUG CDEBUG(D_QOS, "#%d strt %d act %d strp %d ary %d idx %d\n", - i, lov->lov_start_idx, + i, lov->lov_start_idx, ((ost_idx != LOV_QOS_EMPTY) && lov->lov_tgts[ost_idx]) ? lov->lov_tgts[ost_idx]->ltd_active : 0, idx_pos - idx_arr, array_idx, ost_idx); #endif - if ((ost_idx == LOV_QOS_EMPTY) || !lov->lov_tgts[ost_idx] || - !lov->lov_tgts[ost_idx]->ltd_active) + if ((ost_idx == LOV_QOS_EMPTY) || !lov->lov_tgts[ost_idx] || + !lov->lov_tgts[ost_idx]->ltd_active) + continue; + /* Fail Check before osc_precreate() is called + so we can only 'fail' single OSC. */ + if (OBD_FAIL_CHECK(OBD_FAIL_MDS_OSC_PRECREATE) && ost_idx == 0) + continue; + + /* Drop slow OSCs if we can */ + if (obd_precreate(lov->lov_tgts[ost_idx]->ltd_exp, speed == 0) > + speed) continue; + *idx_pos = ost_idx; idx_pos++; /* We have enough stripes */ - if (idx_pos - idx_arr == *stripe_cnt) + if (idx_pos - idx_arr == *stripe_cnt) break; } + if ((speed < 2) && (idx_pos - idx_arr < stripe_cnt_min)) { + /* Try again, allowing slower OSCs */ + speed++; + lov->lov_start_idx = ost_start_idx_temp; + goto repeat_find; + } + up_read(&lov->lov_qos.lq_rw_sem); *stripe_cnt = idx_pos - idx_arr; @@ -563,21 +593,41 @@ static int alloc_specific(struct lov_obd *lov, struct lov_stripe_md *lsm, int *idx_arr) { unsigned ost_idx, ost_count = lov->desc.ld_tgt_count; - int i, *idx_pos = idx_arr; + int i, *idx_pos; + int speed = 0; ENTRY; +repeat_find: + idx_pos = idx_arr; ost_idx = lsm->lsm_oinfo[0]->loi_ost_idx; for (i = 0; i < ost_count; i++, ost_idx = (ost_idx + 1) % ost_count) { if (!lov->lov_tgts[ost_idx] || !lov->lov_tgts[ost_idx]->ltd_active) { continue; } + + /* Fail Check before osc_precreate() is called + so we can only 'fail' single OSC. */ + if (OBD_FAIL_CHECK(OBD_FAIL_MDS_OSC_PRECREATE) && ost_idx == 0) + continue; + + /* Drop slow OSCs if we can */ + if (obd_precreate(lov->lov_tgts[ost_idx]->ltd_exp, speed == 0) > + speed) + continue; + *idx_pos = ost_idx; idx_pos++; - /* got enough ost */ + /* We have enough stripes */ if (idx_pos - idx_arr == lsm->lsm_stripe_count) RETURN(0); } + if (speed < 2) { + /* Try again, allowing slower OSCs */ + speed++; + goto repeat_find; + } + /* If we were passed specific striping params, then a failure to * meet those requirements is an error, since we can't reallocate * that memory (it might be part of a larger array or something). @@ -593,7 +643,8 @@ static int alloc_specific(struct lov_obd *lov, struct lov_stripe_md *lsm, - free space - network resources (shared OSS's) */ -static int alloc_qos(struct obd_export *exp, int *idx_arr, int *stripe_cnt) +static int alloc_qos(struct obd_export *exp, int *idx_arr, int *stripe_cnt, + int flags) { struct lov_obd *lov = &exp->exp_obd->u.lov; static time_t last_warn = 0; @@ -601,8 +652,12 @@ static int alloc_qos(struct obd_export *exp, int *idx_arr, int *stripe_cnt) __u64 total_bavail, total_weight = 0; __u32 ost_count; int nfound, good_osts, i, warn = 0, rc = 0; + int stripe_cnt_min = min_stripe_count(*stripe_cnt, flags); ENTRY; - + + if (stripe_cnt_min < 1) + GOTO(out, rc = -EINVAL); + lov_getref(exp->exp_obd); /* Detect -EAGAIN early, before expensive lock is taken. */ @@ -658,6 +713,14 @@ static int alloc_qos(struct obd_export *exp, int *idx_arr, int *stripe_cnt) continue; } + /* Fail Check before osc_precreate() is called + so we can only 'fail' single OSC. */ + if (OBD_FAIL_CHECK(OBD_FAIL_MDS_OSC_PRECREATE) && i == 0) + continue; + + if (obd_precreate(lov->lov_tgts[i]->ltd_exp, 1) >= 2) + continue; + lov->lov_tgts[i]->ltd_qos.ltq_usable = 1; qos_calc_weight(lov, i); total_bavail += bavail; @@ -665,17 +728,20 @@ static int alloc_qos(struct obd_export *exp, int *idx_arr, int *stripe_cnt) good_osts++; } - + if (!total_bavail) GOTO(out_up_write, rc = -ENOSPC); - - /* if we don't have enough good OSTs, we reduce the stripe count. */ + + if (good_osts < stripe_cnt_min) + GOTO(out_up_write, rc = -EAGAIN); + + /* We have enough osts */ if (good_osts < *stripe_cnt) *stripe_cnt = good_osts; - if (!*stripe_cnt) + if (!*stripe_cnt) GOTO(out_up_write, rc = -EAGAIN); - + /* Find enough OSTs with weighted random allocation. */ nfound = 0; while (nfound < *stripe_cnt) { @@ -713,6 +779,7 @@ static int alloc_qos(struct obd_export *exp, int *idx_arr, int *stripe_cnt) if (!lov->lov_tgts[i] || !lov->lov_tgts[i]->ltd_qos.ltq_usable) continue; + cur_weight += lov->lov_tgts[i]->ltd_qos.ltq_weight; if (cur_weight >= rand) { #ifdef QOS_DEBUG @@ -738,7 +805,7 @@ out_up_write: out: if (rc == -EAGAIN) - rc = alloc_rr(lov, idx_arr, stripe_cnt); + rc = alloc_rr(lov, idx_arr, stripe_cnt, flags); lov_putref(exp->exp_obd); RETURN(rc); @@ -746,7 +813,7 @@ out: /* return new alloced stripe count on success */ static int alloc_idx_array(struct obd_export *exp, struct lov_stripe_md *lsm, - int newea, int **idx_arr, int *arr_cnt) + int newea, int **idx_arr, int *arr_cnt, int flags) { struct lov_obd *lov = &exp->exp_obd->u.lov; int stripe_cnt = lsm->lsm_stripe_count; @@ -763,7 +830,7 @@ static int alloc_idx_array(struct obd_export *exp, struct lov_stripe_md *lsm, if (newea || lsm->lsm_oinfo[0]->loi_ost_idx >= lov->desc.ld_tgt_count) - rc = alloc_qos(exp, tmp_arr, &stripe_cnt); + rc = alloc_qos(exp, tmp_arr, &stripe_cnt, flags); else rc = alloc_specific(lov, lsm, tmp_arr); @@ -792,13 +859,14 @@ int qos_prep_create(struct obd_export *exp, struct lov_request_set *set) struct obd_trans_info *oti = set->set_oti; int i, stripes, rc = 0, newea = 0; int *idx_arr, idx_cnt = 0; + int flag = LOV_USES_ASSIGNED_STRIPE; ENTRY; LASSERT(src_oa->o_valid & OBD_MD_FLID); LASSERT(src_oa->o_valid & OBD_MD_FLGROUP); if (set->set_oi->oi_md == NULL) { - int stripe_cnt = lov_get_stripecnt(lov, 0); + int stripes_def = lov_get_stripecnt(lov, 0); /* If the MDS file was truncated up to some size, stripe over * enough OSTs to allow the file to be created at that size. @@ -821,10 +889,11 @@ int qos_prep_create(struct obd_export *exp, struct lov_request_set *set) } lov_putref(exp->exp_obd); - if (stripes < stripe_cnt) - stripes = stripe_cnt; + if (stripes < stripes_def) + stripes = stripes_def; } else { - stripes = stripe_cnt; + flag = LOV_USES_DEFAULT_STRIPE; + stripes = stripes_def; } rc = lov_alloc_memmd(&set->set_oi->oi_md, stripes, @@ -833,8 +902,8 @@ int qos_prep_create(struct obd_export *exp, struct lov_request_set *set) LOV_MAGIC); if (rc < 0) GOTO(out_err, rc); - rc = 0; newea = 1; + rc = 0; } lsm = set->set_oi->oi_md; @@ -848,7 +917,7 @@ int qos_prep_create(struct obd_export *exp, struct lov_request_set *set) lsm->lsm_pattern = lov->desc.ld_pattern; } - stripes = alloc_idx_array(exp, lsm, newea, &idx_arr, &idx_cnt); + stripes = alloc_idx_array(exp, lsm, newea, &idx_arr, &idx_cnt, flag); if (stripes <= 0) GOTO(out_err, rc = stripes ? stripes : -EIO); LASSERTF(stripes <= lsm->lsm_stripe_count,"requested %d allocated %d\n", diff --git a/lustre/obdclass/lprocfs_status.c b/lustre/obdclass/lprocfs_status.c index 6f9d903229..4a7fa3ea6c 100644 --- a/lustre/obdclass/lprocfs_status.c +++ b/lustre/obdclass/lprocfs_status.c @@ -854,6 +854,7 @@ void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats) LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd); LPROCFS_OBD_OP_INIT(num_private_stats, stats, checkmd); LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate); + LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate); LPROCFS_OBD_OP_INIT(num_private_stats, stats, create); LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy); LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr); diff --git a/lustre/obdfilter/filter.c b/lustre/obdfilter/filter.c index 42d9ffa0f7..81530b225b 100644 --- a/lustre/obdfilter/filter.c +++ b/lustre/obdfilter/filter.c @@ -3321,6 +3321,8 @@ static int filter_precreate(struct obd_device *obd, struct obdo *oa, LASSERT(down_trylock(&filter->fo_create_locks[group]) != 0); + OBD_FAIL_TIMEOUT(OBD_FAIL_TGT_DELAY_PRECREATE, obd_timeout / 2); + if ((oa->o_valid & OBD_MD_FLFLAGS) && (oa->o_flags & OBD_FL_RECREATE_OBJS)) { recreate_obj = 1; diff --git a/lustre/osc/osc_create.c b/lustre/osc/osc_create.c index cd0d3730ef..6962150951 100644 --- a/lustre/osc/osc_create.c +++ b/lustre/osc/osc_create.c @@ -234,6 +234,51 @@ int oscc_recovering(struct osc_creator *oscc) return recov; } +/* decide if the OST has remaining object, return value : + 0 : the OST has remaining object, and don't need to do precreate. + 1 : the OST has no remaining object, and will send a RPC for precreate. + 2 : the OST has no remaining object, and will not get any for + a potentially very long time + 1000 : unusable + */ +int osc_precreate(struct obd_export *exp, int need_create) +{ + struct osc_creator *oscc = &exp->exp_obd->u.cli.cl_oscc; + struct obd_import *imp = exp->exp_imp_reverse; + ENTRY; + + LASSERT(oscc != NULL); + if (imp != NULL && imp->imp_deactive) + RETURN(1000); + + if (oscc->oscc_last_id < oscc->oscc_next_id) { + spin_lock(&oscc->oscc_lock); + if (oscc->oscc_flags & OSCC_FLAG_NOSPC) { + spin_unlock(&oscc->oscc_lock); + RETURN(1000); + } + if (oscc->oscc_flags & OSCC_FLAG_SYNC_IN_PROGRESS) { + spin_unlock(&oscc->oscc_lock); + RETURN(1); + } + if (oscc->oscc_flags & OSCC_FLAG_RECOVERING) { + spin_unlock(&oscc->oscc_lock); + RETURN(2); + } + spin_unlock(&oscc->oscc_lock); + + if (oscc->oscc_flags & OSCC_FLAG_CREATING) + RETURN(1); + + if (!need_create) + RETURN(1); + + oscc_internal_create(oscc); + RETURN(1); + } + RETURN(0); +} + int osc_create(struct obd_export *exp, struct obdo *oa, struct lov_stripe_md **ea, struct obd_trans_info *oti) { diff --git a/lustre/osc/osc_internal.h b/lustre/osc/osc_internal.h index 18148c8053..e3e6013f13 100644 --- a/lustre/osc/osc_internal.h +++ b/lustre/osc/osc_internal.h @@ -54,6 +54,7 @@ struct osc_cache_waiter { #define OSCC_FLAG_LOW 0x10 #define OSCC_FLAG_EXITING 0x20 +int osc_precreate(struct obd_export *exp, int need_create); int osc_create(struct obd_export *exp, struct obdo *oa, struct lov_stripe_md **ea, struct obd_trans_info *oti); int osc_real_create(struct obd_export *exp, struct obdo *oa, diff --git a/lustre/osc/osc_request.c b/lustre/osc/osc_request.c index 16b78f9794..c2335740eb 100644 --- a/lustre/osc/osc_request.c +++ b/lustre/osc/osc_request.c @@ -3744,6 +3744,7 @@ struct obd_ops osc_obd_ops = { .o_statfs_async = osc_statfs_async, .o_packmd = osc_packmd, .o_unpackmd = osc_unpackmd, + .o_precreate = osc_precreate, .o_create = osc_create, .o_destroy = osc_destroy, .o_getattr = osc_getattr, diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index 260023012f..195319f6e0 100644 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -1187,6 +1187,48 @@ test_27x() { # bug 10997 } run_test 27x "check lfs setstripe -c -s -i options =============" +test_27u() { # bug 4900 + [ "$OSTCOUNT" -lt "2" -o -z "$MDS" ] && echo "skip $TESTNAME" && return + #define OBD_FAIL_MDS_OSC_PRECREATE 0x13d + + sysctl -w lustre.fail_loc=0x13d + mkdir -p $DIR/d27u + createmany -o $DIR/d27u/t- 1000 + sysctl -w lustre.fail_loc=0 + + $LFS getstripe $DIR/d27u > $TMP/files + OBJS=`cat $TMP/files | awk -vobjs=0 '($1 == 0) { objs += 1 } END { print objs;}'` + unlinkmany $DIR/d27u/t- 1000 + [ $OBJS -gt 0 ] && \ + error "Found $OBJS objects were created on OST-0" || pass +} +run_test 27u "skip object creation on OSC w/o objects ==========" + +test_27v() { # bug 4900 + [ "$OSTCOUNT" -lt "2" -o -z "$MDS" ] && echo "skip $TESTNAME" && return + exhaust_all_precreations + + mkdir -p $DIR/$tdir + lfs setstripe $DIR/$tdir 0 -1 1 # 1 stripe / file + + touch $DIR/$tdir/$tfile + #define OBD_FAIL_TGT_DELAY_PRECREATE 0x705 + sysctl -w lustre.fail_loc=0x705 + START=`date +%s` + for F in `seq 1 32`; do + touch $DIR/$tdir/$tfile.$F + done + sysctl -w lustre.fail_loc=0 + + FINISH=`date +%s` + TIMEOUT=`sysctl -n lustre.timeout` + [ $((FINISH - START)) -ge $((TIMEOUT / 2)) ] && \ + error "$FINISH - $START >= $TIMEOUT / 2" + + reset_enospc +} +run_test 27v "skip object creation on slow OST =================" + test_28() { mkdir $DIR/d28 $CREATETEST $DIR/d28/ct || error @@ -2796,7 +2838,7 @@ test_65j() { # bug6367 cleanup -f || error "failed to unmount" setup fi - $SETSTRIPE -d $MOUNT + $SETSTRIPE -d $MOUNT || error "setstripe failed" } run_test 65j "set default striping on root directory (bug 6367)=" @@ -2830,9 +2872,9 @@ test_65k() { # bug11679 run_test 65k "validate manual striping works properly with deactivated OSCs" test_65l() { # bug 12836 - mkdir -p $DIR/$tdir - $LFS setstripe $DIR/$tdir 65536 -1 -1 - $LFS find -mtime -1 $DIR + mkdir -p $DIR/$tdir/test_dir + $LFS setstripe $DIR/$tdir/test_dir 65536 -1 -1 + $LFS find -mtime -1 $DIR/$tdir } run_test 65l "lfs find on -1 stripe dir ========================" -- GitLab