From dbb6b493ad9f989197401bdfec72b93bbb7a8faf Mon Sep 17 00:00:00 2001 From: Mikhail Pershin Date: Thu, 19 Nov 2020 16:24:18 +0300 Subject: [PATCH 1/1] LU-14143 lov: fix SEEK_HOLE calcs at component end If data ends exactly at component end then LOV assumed that is not yet hole in file and the next component will take care. Meanwhile there can be no next component initialized yet if file ends exactly at component boundary, so no hole offset is returned but error Patch fixes that issue. If component reports hole offset at component end then it is saved to be used as result when no other components report valid hole offset. Signed-off-by: Mikhail Pershin Change-Id: I8bffd8b76546b560a3d34034701eea4963f41593 Reviewed-on: https://review.whamcloud.com/40713 Reviewed-by: Andreas Dilger Tested-by: jenkins Tested-by: Maloo Reviewed-by: John L. Hammond --- lustre/lov/lov_io.c | 22 ++++++++++++++++++++-- lustre/tests/sanity.sh | 6 ++++-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/lustre/lov/lov_io.c b/lustre/lov/lov_io.c index d8aed58..0724043 100644 --- a/lustre/lov/lov_io.c +++ b/lustre/lov/lov_io.c @@ -1325,6 +1325,7 @@ static void lov_io_lseek_end(const struct lu_env *env, struct lov_stripe_md *lsm = lio->lis_object->lo_lsm; struct lov_io_sub *sub; loff_t offset = -ENXIO; + __u64 hole_off = 0; bool seek_hole = io->u.ci_lseek.ls_whence == SEEK_HOLE; ENTRY; @@ -1334,6 +1335,7 @@ static void lov_io_lseek_end(const struct lu_env *env, int index = lov_comp_entry(sub->sub_subio_index); int stripe = lov_comp_stripe(sub->sub_subio_index); loff_t sub_off, lov_off; + __u64 comp_end = lsm->lsm_entries[index]->lsme_extent.e_end; lov_io_end_wrapper(sub->sub_env, subio); @@ -1379,10 +1381,22 @@ static void lov_io_lseek_end(const struct lu_env *env, /* resulting offset can be out of component range if stripe * object is full and its file size was returned as virtual * hole start. Skip this result, the next component will give - * us correct lseek result. + * us correct lseek result but keep possible hole offset in + * case there is no more components ahead */ - if (lov_off >= lsm->lsm_entries[index]->lsme_extent.e_end) + if (lov_off >= comp_end) { + /* must be SEEK_HOLE case */ + if (likely(seek_hole)) { + /* save comp end as potential hole offset */ + hole_off = max_t(__u64, comp_end, hole_off); + } else { + io->ci_result = -EINVAL; + CDEBUG(D_INFO, + "off %lld >= comp_end %llu: rc = %d\n", + lov_off, comp_end, io->ci_result); + } continue; + } CDEBUG(D_INFO, "SEEK_%s: %lld->%lld/%lld: rc = %d\n", seek_hole ? "HOLE" : "DATA", @@ -1390,6 +1404,10 @@ static void lov_io_lseek_end(const struct lu_env *env, sub->sub_io.ci_result); offset = min_t(__u64, offset, lov_off); } + /* no result but some component returns hole as component end */ + if (seek_hole && offset == -ENXIO && hole_off > 0) + offset = hole_off; + io->u.ci_lseek.ls_result = offset; RETURN_EXIT; } diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index 5968b618..66c2903 100755 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -23945,7 +23945,10 @@ test_430b() { [[ $offset == 1000000 ]] || error "offset $offset != 1000000" printf "Seeking data from 1000000 ... " lseek_test -d 1000000 $file && error "lseek should fail" - # full first component, non-inited second one + rm $file + + # full component followed by non-inited one + $LFS setstripe -E 1M -c2 -E eof $file dd if=/dev/urandom of=$file bs=1M count=1 printf "Seeking hole from 1000000 ... " offset=$(lseek_test -l 1000000 $file) @@ -23956,7 +23959,6 @@ test_430b() { # init second component and truncate back echo "123" >> $file $TRUNCATE $file 1048576 - ls -lia $file printf "Seeking hole from 1000000 ... " offset=$(lseek_test -l 1000000 $file) echo $offset -- 1.8.3.1