Whamcloud - gitweb
LU-14143 lov: fix SEEK_HOLE calcs at component end 13/40713/5
authorMikhail Pershin <mpershin@whamcloud.com>
Thu, 19 Nov 2020 13:24:18 +0000 (16:24 +0300)
committerOleg Drokin <green@whamcloud.com>
Sun, 13 Dec 2020 08:23:34 +0000 (08:23 +0000)
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 <mpershin@whamcloud.com>
Change-Id: I8bffd8b76546b560a3d34034701eea4963f41593
Reviewed-on: https://review.whamcloud.com/40713
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: John L. Hammond <jhammond@whamcloud.com>
lustre/lov/lov_io.c
lustre/tests/sanity.sh

index d8aed58..0724043 100644 (file)
@@ -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;
        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;
        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;
                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);
 
 
                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
                /* 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;
                        continue;
+               }
 
                CDEBUG(D_INFO, "SEEK_%s: %lld->%lld/%lld: rc = %d\n",
                       seek_hole ? "HOLE" : "DATA",
 
                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);
        }
                       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;
 }
        io->u.ci_lseek.ls_result = offset;
        RETURN_EXIT;
 }
index 5968b61..66c2903 100755 (executable)
@@ -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"
        [[ $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)
        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
        # 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
        printf "Seeking hole from 1000000 ... "
        offset=$(lseek_test -l 1000000 $file)
        echo $offset