Whamcloud - gitweb
EX-8927 csdc: server reject FIEMAP/SEEK_HOLE|DATA on compr obj
authorBobi Jam <bobijam@whamcloud.com>
Fri, 2 Feb 2024 07:15:30 +0000 (15:15 +0800)
committerAndreas Dilger <adilger@whamcloud.com>
Wed, 14 Feb 2024 19:19:31 +0000 (19:19 +0000)
Server return -EOPNOTSUPP if they get the FIEMAP and
SEEK_HOLE/SEEK_DATA requests upon compressed file objects.

Signed-off-by: Bobi Jam <bobijam@whamcloud.com>
Change-Id: I9f04fbb13a22cc83402d9989daab63a59367ff33
Reviewed-on: https://review.whamcloud.com/c/ex/lustre-release/+/53886
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Sebastien Buisson <sbuisson@ddn.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
lustre/include/obd_support.h
lustre/include/uapi/linux/lustre/lustre_user.h
lustre/lov/lov_io.c
lustre/lov/lov_object.c
lustre/ofd/ofd_dev.c
lustre/ofd/ofd_internal.h
lustre/osd-ldiskfs/osd_handler.c
lustre/osd-ldiskfs/osd_internal.h
lustre/osd-ldiskfs/osd_io.c
lustre/osd-zfs/osd_io.c
lustre/tests/sanity.sh

index 86ee3b6..3fa8521 100644 (file)
@@ -638,6 +638,7 @@ extern char obd_jobid_var[];
 #define OBD_FAIL_LOV_COMP_MAGIC                            0x1426
 #define OBD_FAIL_LOV_COMP_PATTERN                  0x1427
 #define OBD_FAIL_LOV_INVALID_OSTIDX                0x1428
+#define OBD_FAIL_LOV_SKIP_CHECK_COMPR              0x1429
 #define OBD_FAIL_LLITE_DELAY_TRUNCATE              0x1430
 #define OBD_FAIL_LLITE_READ_PAUSE                  0x1431
 
index 70e7edb..8f8f94e 100644 (file)
@@ -419,6 +419,13 @@ struct filter_fid {
        struct ost_layout_compr ff_layout_compr;
 } __attribute__((packed));
 
+/**
+ * for compatibility, filter_fid could occupy more space in newer version and
+ * downgraded Lustre would fail reading it with -ERANGE, so it can read it
+ * again with more space to hold it.
+ */
+#define FILTER_FID_EXTRA_SIZE  32
+
 /* Userspace should treat lu_fid as opaque, and only use the following methods
  * to print or parse them.  Other functions (e.g. compare, swab) could be moved
  * here from lustre_idl.h if needed. */
index 18dbb36..2a0d91f 100644 (file)
@@ -605,7 +605,8 @@ static int lov_io_slice_init(struct lov_io *lio,
        }
 
        case CIT_LSEEK: {
-               if (io->ci_compressed_file)
+               if (!OBD_FAIL_CHECK(OBD_FAIL_LOV_SKIP_CHECK_COMPR) &&
+                   io->ci_compressed_file)
                        GOTO(out, result = -EOPNOTSUPP);
                lio->lis_pos = io->u.ci_lseek.ls_start;
                lio->lis_endpos = OBD_OBJECT_EOF;
index 3d6952e..9188b40 100644 (file)
@@ -2077,7 +2077,8 @@ static int lov_object_fiemap(const struct lu_env *env, struct cl_object *obj,
 
        lsme = lsm->lsm_entries[0];
        /* No support for compressed yet. */
-       if (lsme->lsme_compr_type != LL_COMPR_TYPE_NONE)
+       if (!OBD_FAIL_CHECK(OBD_FAIL_LOV_SKIP_CHECK_COMPR) &&
+           lsme->lsme_compr_type != LL_COMPR_TYPE_NONE)
                GOTO(out_lsm, rc = -EOPNOTSUPP);
 
        if (!(fiemap->fm_flags & FIEMAP_FLAG_DEVICE_ORDER)) {
index 7081caa..801eac8 100644 (file)
@@ -961,10 +961,20 @@ int ofd_fiemap_get(const struct lu_env *env, struct ofd_device *ofd,
        }
 
        ofd_read_lock(env, fo);
-       if (ofd_object_exists(fo))
-               rc = dt_fiemap_get(env, ofd_object_child(fo), fiemap);
-       else
+       if (!ofd_object_exists(fo)) {
                rc = -ENOENT;
+               goto out;
+       }
+
+       rc = ofd_object_ff_load(env, fo);
+       if (rc == 0 &&
+           fo->ofo_ff.ff_layout_compr.ol_compr_type != LL_COMPR_TYPE_NONE) {
+               rc = -EOPNOTSUPP;
+               goto out;
+       }
+
+       rc = dt_fiemap_get(env, ofd_object_child(fo), fiemap);
+out:
        ofd_read_unlock(env, fo);
        ofd_object_put(env, fo);
        return rc;
index 53a47fb..075a0ce 100644 (file)
@@ -181,13 +181,6 @@ static inline char *ofd_name(struct ofd_device *ofd)
        return ofd->ofd_dt_dev.dd_lu_dev.ld_obd->obd_name;
 }
 
-/**
- * for compatibility, filter_fid could occupy more space in newer version and
- * downgraded Lustre would fail reading it with -ERANGE, so it can read it
- * again with more space to hold it.
- */
-#define FILTER_FID_EXTRA_SIZE  32
-
 struct ofd_object {
        struct lu_object_header ofo_header;
        struct dt_object        ofo_obj;
index 0902890..197baf1 100644 (file)
@@ -4681,8 +4681,8 @@ static int osd_ref_del(const struct lu_env *env, struct dt_object *dt,
 /*
  * Concurrency: @dt is read locked.
  */
-static int osd_xattr_get(const struct lu_env *env, struct dt_object *dt,
-                        struct lu_buf *buf, const char *name)
+int osd_xattr_get(const struct lu_env *env, struct dt_object *dt,
+                 struct lu_buf *buf, const char *name)
 {
        struct osd_object      *obj    = osd_dt_obj(dt);
        struct inode           *inode  = obj->oo_inode;
index ead0ecd..e7640a0 100644 (file)
@@ -812,6 +812,9 @@ extern int ldiskfs_pdo;
 #define DECLARE_BVEC_ITER_ALL(iter) int iter
 #endif
 
+int osd_xattr_get(const struct lu_env *env, struct dt_object *dt,
+                 struct lu_buf *buf, const char *name);
+
 static inline int __osd_xattr_get(struct inode *inode, struct dentry *dentry,
                                  const char *name, void *buf, int len)
 {
index bbcc2e0..837ab29 100644 (file)
@@ -2765,11 +2765,13 @@ static int osd_ladvise(const struct lu_env *env, struct dt_object *dt,
 static loff_t osd_lseek(const struct lu_env *env, struct dt_object *dt,
                        loff_t offset, int whence)
 {
+       struct osd_thread_info *oti = osd_oti_get(env);
        struct osd_object *obj = osd_dt_obj(dt);
        struct osd_device *dev = osd_obj2dev(obj);
        struct inode *inode = obj->oo_inode;
        struct file *file;
        loff_t result;
+       int rc;
 
        ENTRY;
        LASSERT(dt_object_exists(dt));
@@ -2777,6 +2779,31 @@ static loff_t osd_lseek(const struct lu_env *env, struct dt_object *dt,
        LASSERT(inode);
        LASSERT(offset >= 0);
 
+       /* check whether it's a compressed object */
+       oti->oti_buf.lb_buf = &oti->oti_ff;
+       oti->oti_buf.lb_len = sizeof(oti->oti_ff);
+       rc = osd_xattr_get(env, dt, &oti->oti_buf, XATTR_NAME_FID);
+       if (rc == -ERANGE) {
+               struct filter_fid *ff_new;
+
+               OBD_ALLOC(ff_new, sizeof(*ff_new) + FILTER_FID_EXTRA_SIZE);
+               if (!ff_new)
+                       RETURN(-ENOMEM);
+
+               oti->oti_buf.lb_buf = ff_new;
+               oti->oti_buf.lb_len = sizeof(*ff_new) + FILTER_FID_EXTRA_SIZE;
+               rc = osd_xattr_get(env, dt, &oti->oti_buf, XATTR_NAME_FID);
+               if (rc > 0)
+                       memcpy(&oti->oti_ff, ff_new, sizeof(oti->oti_ff));
+               OBD_FREE(ff_new, sizeof(*ff_new) + FILTER_FID_EXTRA_SIZE);
+       }
+       if (rc > 0) {
+               filter_fid_le_to_cpu(&oti->oti_ff, &oti->oti_ff, rc);
+               if (oti->oti_ff.ff_layout_compr.ol_compr_type !=
+                   LL_COMPR_TYPE_NONE)
+                       RETURN(-EOPNOTSUPP);
+       }
+
        file = alloc_file_pseudo(inode, dev->od_mnt, "/", O_NOATIME,
                                 inode->i_fop);
        if (IS_ERR(file))
index be48b92..bdf6a60 100644 (file)
@@ -1197,6 +1197,8 @@ static loff_t osd_lseek(const struct lu_env *env, struct dt_object *dt,
        struct osd_object *obj = osd_dt_obj(dt);
        uint64_t size = obj->oo_attr.la_size;
        uint64_t result = offset;
+       struct lu_buf buf;
+       struct filter_fid ff;
        int rc;
        boolean_t hole = whence == SEEK_HOLE;
 
@@ -1206,6 +1208,30 @@ static loff_t osd_lseek(const struct lu_env *env, struct dt_object *dt,
        LASSERT(osd_invariant(obj));
        LASSERT(offset >= 0);
 
+       /* check whether it's a compressed object */
+       buf.lb_buf = &ff;
+       buf.lb_len = sizeof(ff);
+       rc = osd_xattr_get(env, dt, &buf, XATTR_NAME_FID);
+       if (rc == -ERANGE) {
+               struct filter_fid *ff_new;
+
+               OBD_ALLOC(ff_new, sizeof(*ff_new) + FILTER_FID_EXTRA_SIZE);
+               if (!ff_new)
+                       RETURN(-ENOMEM);
+
+               buf.lb_buf = ff_new;
+               buf.lb_len = sizeof(*ff_new) + FILTER_FID_EXTRA_SIZE;
+               rc = osd_xattr_get(env, dt, &buf, XATTR_NAME_FID);
+               if (rc > 0)
+                       memcpy(&ff, ff_new, sizeof(ff));
+               OBD_FREE(ff_new, sizeof(*ff_new) + FILTER_FID_EXTRA_SIZE);
+       }
+       if (rc > 0) {
+               filter_fid_le_to_cpu(&ff, &ff, rc);
+               if (ff.ff_layout_compr.ol_compr_type != LL_COMPR_TYPE_NONE)
+                       RETURN(-EOPNOTSUPP);
+       }
+
        /* for SEEK_HOLE treat 'offset' beyond the end of file as in real
         * hole. LOV to decide after all if that real hole or not.
         */
index d0dc227..0879100 100644 (file)
@@ -28741,6 +28741,46 @@ test_460f() {
 }
 run_test 460f "verify hole/data lseek is disabled for compressed files"
 
+test_460g() {
+       (( MDS1_VERSION >= $(version_code 2.14.0.134) )) ||
+               skip "Need MDS version at least 2.14.0.134"
+
+       local tf=$DIR/$tfile
+
+       stack_trap "rm -f $tf; 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"
+
+       # skip the compression check from LOV, and prevent fiemap/lseek
+       # upon compressed file in OFD
+       #define OBD_FAIL_LOV_SKIP_CHECK_COMPR 0x1429
+       $LCTL set_param fail_loc=0x1429
+
+       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"
+
+       checkfiemap --test ||
+               skip "checkfiemap not runnable: $?"
+       checkfiemap $tf 131072 && error "fiemap should fail"
+
+       return 0
+}
+run_test 460g "verify hole/data lseek or fiemap is disabled for compressed files on server"
+
 prep_801() {
        [[ $MDS1_VERSION -lt $(version_code 2.9.55) ]] ||
        [[ $OST1_VERSION -lt $(version_code 2.9.55) ]] &&