Whamcloud - gitweb
EX-7680 llite: skip hole/data lseek() on compressed file
authorMikhail Pershin <mpershin@whamcloud.com>
Fri, 23 Jun 2023 22:21:28 +0000 (01:21 +0300)
committerAndreas Dilger <adilger@whamcloud.com>
Sat, 24 Jun 2023 18:12:56 +0000 (18:12 +0000)
Doesn't execute real lseek() on compressed file with
SEEK_HOLE/SEEK_DATA origin but consider file always
non-sparsed and do generic lseek() only

Signed-off-by: Mikhail Pershin <mpershin@whamcloud.com>
Change-Id: I2cd587cc0205e85758e06bbaafafe0e2959e0ade
Reviewed-on: https://review.whamcloud.com/c/ex/lustre-release/+/51429
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
lustre/llite/file.c
lustre/lov/lov_io.c
lustre/tests/sanity.sh

index 542bf7a..59a25ad 100644 (file)
@@ -4799,6 +4799,7 @@ static loff_t ll_file_seek(struct file *file, loff_t offset, int origin)
        struct inode *inode = file_inode(file);
        loff_t retval = offset, eof = 0;
        ktime_t kstart = ktime_get();
+       loff_t maxbytes = ll_file_maxbytes(inode);
 
        ENTRY;
 
@@ -4822,12 +4823,15 @@ static loff_t ll_file_seek(struct file *file, loff_t offset, int origin)
                                   CL_FSYNC_LOCAL, 0);
 
                retval = ll_lseek(file, offset, origin);
-               if (retval < 0)
-                       return retval;
-               retval = vfs_setpos(file, retval, ll_file_maxbytes(inode));
+               if (retval >= 0)
+                       retval = vfs_setpos(file, retval, maxbytes);
+               else if (retval == -EOPNOTSUPP)
+                       retval = generic_file_llseek_size(file, offset,
+                                                         origin, maxbytes,
+                                                         i_size_read(inode));
        } else {
                retval = generic_file_llseek_size(file, offset, origin,
-                                                 ll_file_maxbytes(inode), eof);
+                                                 maxbytes, eof);
        }
        if (retval >= 0)
                ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_LLSEEK,
index 0a2bed7..81ae127 100644 (file)
@@ -590,6 +590,8 @@ static int lov_io_slice_init(struct lov_io *lio,
        }
 
        case CIT_LSEEK: {
+               if (io->ci_compressed_io)
+                       GOTO(out, result = -EOPNOTSUPP);
                lio->lis_pos = io->u.ci_lseek.ls_start;
                lio->lis_endpos = OBD_OBJECT_EOF;
                break;
index 89e45cb..84dfeee 100755 (executable)
@@ -27718,8 +27718,8 @@ run_test 460b "Try to compress with wrong algo"
 # Non-chunk-aligned writes are only allowed if they are extending the file, ie,
 # if they are not overwriting existing data
 test_460c() {
-       (( MDS1_VERSION >= $(version_code 2.14.0.89) )) ||
-               skip "Need MDS version at least 2.14.0.89"
+       (( MDS1_VERSION >= $(version_code 2.14.0.90) )) ||
+               skip "Need MDS version at least 2.14.0.90"
 
        local stored=$DIR/$tdir/foofile
        local tmpfile=$TMP/$tdir/footmp
@@ -27762,8 +27762,8 @@ test_460c() {
 run_test 460c "simple verification of preview write restrictions"
 
 test_460d() {
-       (( MDS1_VERSION >= $(version_code 2.14.0.89) )) ||
-               skip "Need MDS version at least 2.14.0.89"
+       (( MDS1_VERSION >= $(version_code 2.14.0.90) )) ||
+               skip "Need MDS version at least 2.14.0.90"
 
        verify_yaml_available || skip_env "YAML verification not installed"
        $LCTL get_param -n sptlrpc.page_pools
@@ -27772,6 +27772,39 @@ test_460d() {
 }
 run_test 460d "Check encrypt pools output"
 
+test_460f() {
+       (( MDS1_VERSION >= $(version_code 2.14.0.90) )) ||
+               skip "Need MDS version at least 2.14.0.90"
+
+       local tf=$DIR/$tfile
+
+       stack_trap "rm -f $DIR/$tfile; disable_compression"
+       enable_compression
+
+       $LFS setstripe -E -1 -Z gzip:3 --compress-chunk=64 $tf ||
+               error "set a compress component in $tf failed"
+
+       dd if=/dev/zero of=$tf bs=32k count=2 ||
+               error "first dd failed"
+       dd if=/dev/urandom of=$tf bs=32k count=1 seek=3 ||
+               error "second dd failed"
+       sync; echo 3 > /proc/sys/vm/drop_caches
+
+       $LFS getstripe $tf | grep lcme_flags.*compress ||
+               error "no compressed component"
+
+       printf "Seeking hole from 0 ... "
+       offset=$(lseek_test -l 0 $tf) || error "hole lseek failed"
+       echo $offset
+       [[ $offset == 131072 ]] || error "offset $offset != 131072"
+       printf "Seeking data from $offset ... "
+       lseek_test -d $offset $tf && error "data lseek should fail"
+       rm -f $tf
+
+       return 0
+}
+run_test 460f "verify hole/data lseek is disabled for compressed files"
+
 prep_801() {
        [[ $MDS1_VERSION -lt $(version_code 2.9.55) ]] ||
        [[ $OST1_VERSION -lt $(version_code 2.9.55) ]] &&