#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
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. */
}
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;
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)) {
}
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;
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;
/*
* 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;
#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)
{
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));
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))
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;
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.
*/
}
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) ]] &&