Whamcloud - gitweb
EX-6265 llite: allow mmap reads of compressed files
authorPatrick Farrell <pfarrell@whamcloud.com>
Thu, 29 Jun 2023 17:52:01 +0000 (13:52 -0400)
committerAndreas Dilger <adilger@whamcloud.com>
Sat, 1 Jul 2023 10:05:17 +0000 (10:05 +0000)
mmap reads of compressed files work, so we should only
block writes.

We cannot block the actual fault operations because that
will cause the application to get a SIGBUS, so we check
the file open mode when we go to create the memory mapping.

Signed-off-by: Patrick Farrell <pfarrell@whamcloud.com>
Change-Id: I636f398fd247ddcd153f94bf8116440540e8469c
Reviewed-on: https://review.whamcloud.com/c/ex/lustre-release/+/51506
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Qian Yingjin <qian@ddn.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
lustre/llite/llite_mmap.c
lustre/tests/multiop.c
lustre/tests/sanity.sh

index 11d0570..096c589 100644 (file)
@@ -603,7 +603,7 @@ static const struct vm_operations_struct ll_file_vm_ops = {
        .close                  = ll_vm_close,
 };
 
-int ll_mmap_check_compression(struct file *file, unsigned long off)
+int ll_mmap_check_compression(struct file *file, loff_t off)
 {
        struct inode *inode = file_inode(file);
        struct ll_inode_info *lli = ll_i2info(inode);
@@ -615,9 +615,14 @@ int ll_mmap_check_compression(struct file *file, unsigned long off)
        int rc = 0;
        __u32 gen;
 
+       /* mmap reads of compressed files are supported */
+       if ((file->f_flags & O_ACCMODE) == O_RDONLY)
+               RETURN(0);
+
        rc = ll_layout_refresh(inode, &gen);
        if (rc) {
-               CERROR("can't refresh layout: rc=%d\n", rc);
+               CERROR("%s: "DFID" cannot refresh layout: rc = %d\n",
+                      ll_i2sbi(inode)->ll_fsname, PFID(&lli->lli_fid), rc);
                RETURN(rc);
        }
        if (ll_layout_version_get(lli) == CL_LAYOUT_GEN_EMPTY)
@@ -655,8 +660,10 @@ int ll_mmap_check_compression(struct file *file, unsigned long off)
                        rc = -EOPNOTSUPP;
        } else if (rc == 1 || rc == -ENODATA) {
                rc = 0;
-       } else
-               CDEBUG(D_ERROR, "rc=%d\n", rc);
+       } else {
+               CERROR("%s: "DFID" cl_io_rw_init() failed: rc = %d\n",
+                      ll_i2sbi(inode)->ll_fsname, PFID(&lli->lli_fid), rc);
+       }
 
        cl_io_fini(env, io);
 
@@ -681,7 +688,7 @@ int ll_file_mmap(struct file *file, struct vm_area_struct * vma)
        if (ll_file_nolock(file))
                RETURN(-EOPNOTSUPP);
 
-       rc = ll_mmap_check_compression(file, vma->vm_pgoff << PAGE_SHIFT);
+       rc = ll_mmap_check_compression(file, (loff_t)vma->vm_pgoff<<PAGE_SHIFT);
        if (rc)
                RETURN(rc);
 
index 70b61d8..09ff6e1 100644 (file)
@@ -516,20 +516,39 @@ int main(int argc, char **argv)
                        }
                        break;
                case 'M':
+               {
+                       int mmap_mode = 0;
+                       int fd_flags;
+
                        if (st.st_size == 0) {
                                fprintf(stderr,
                                        "mmap without preceeding stat, or on zero length file.\n");
                                exit(-1);
                        }
+
+                       /* match mmap mode to file open mode */
+                       fd_flags = fcntl(fd, F_GETFL);
+                       if (fd_flags < 0) {
+                               fprintf(stderr,
+                                       "unable to get file flags for mmap\n");
+                               exit (-1);
+                       }
+                       if (fd_flags & O_RDONLY || fd_flags & O_RDWR)
+                               mmap_mode |= PROT_READ;
+
+                       if (fd_flags & O_WRONLY || fd_flags & O_RDWR)
+                               mmap_mode |= PROT_WRITE;
+
                        mmap_len = st.st_size;
-                       mmap_ptr = mmap(NULL, mmap_len, PROT_WRITE | PROT_READ,
-                                       MAP_SHARED, fd, 0);
+                       mmap_ptr = mmap(NULL, mmap_len, mmap_mode, MAP_SHARED,
+                                       fd, 0);
                        if (mmap_ptr == MAP_FAILED) {
                                save_errno = errno;
                                perror("mmap");
                                exit(save_errno);
                        }
                        break;
+               }
                case 'n':
                        oldpath = POP_ARG();
                        if (!oldpath)
index 321a4ca..5814088 100755 (executable)
@@ -27778,44 +27778,46 @@ test_460d() {
 run_test 460d "Check encrypt pools output"
 
 test_460e() {
-       (( MDS1_VERSION >= $(version_code 2.14.0.85) )) ||
-               skip "Need MDS version at least 2.14.0.85"
+       (( MDS1_VERSION >= $(version_code 2.14.0.91) )) ||
+               skip "Need MDS version at least 2.14.0.91"
 
        local tf=$DIR/$tfile
 
-       stack_trap "rm -Rf $DIR/$tfile; disable_compression"
+       stack_trap "rm -f $tf; disable_compression"
        enable_compression
 
        $LFS setstripe -E -1 -Z lz4:5 --compress-chunk=64 $tf ||
                error "set a compress component in $tf failed"
 
-       dd if=/dev/zero of=$tf bs=32k count=5 ||
-               error "dd to $stored failed"
+       dd if=/dev/zero of=$tf bs=32k count=5 || error "dd to $stored failed"
 
        sync; echo 3 > /proc/sys/vm/drop_caches
 
        $LFS getstripe $tf
-       $LFS getstripe $tf | grep lcme_flags.*compress ||
+       $LFS getstripe $tf | grep -q lcme_flags.*compress ||
                error "no compressed component"
 
-       $MULTIOP $tf OSMc && error "mmap must be disabled"
+       $MULTIOP $tf OSMc &&
+               error "(0) writeable mmap of compressed files should not work"
+       $MULTIOP $tf oSMc ||
+               error "(1) readonly mmap of compressed files should work"
 
        rm -f $tf
-       dd if=/dev/zero of=$tf bs=32k count=5 ||
-               error "dd to $stored failed"
-       $MULTIOP $tf OSMc || error "mmap must be disabled"
-
-       return 0
+       dd if=/dev/zero of=$tf bs=32k count=5 || error "dd(2) to $stored failed"
+       $MULTIOP $tf OSMc ||
+               error "(2) writeable mmap of uncompressed files should work"
+       $MULTIOP $tf oSMc ||
+               error "(3) readonly mmap of uncompressed files should work"
 }
 run_test 460e "verify mmap is disabled with compressed files"
 
 test_460f() {
-       (( MDS1_VERSION >= $(version_code 2.14.0.90) )) ||
-               skip "Need MDS version at least 2.14.0.90"
+       (( MDS1_VERSION >= $(version_code 2.14.0.91) )) ||
+               skip "Need MDS version at least 2.14.0.91"
 
        local tf=$DIR/$tfile
 
-       stack_trap "rm -f $DIR/$tfile; disable_compression"
+       stack_trap "rm -f $tf; disable_compression"
        enable_compression
 
        $LFS setstripe -E -1 -Z gzip:3 --compress-chunk=64 $tf ||
@@ -27836,7 +27838,6 @@ test_460f() {
        [[ $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
 }