struct niobuf_local *lnb,
struct obd_ioobj *obj, int npages,
enum ll_compr_type type, int lvl,
- int chunk_bits);
+ int chunk_bits, bool write);
int (*o_preprw)(const struct lu_env *env, int cmd,
struct obd_export *exp, struct obdo *oa, int objcount,
struct obd_ioobj *obj, struct niobuf_remote *remote,
int *nr_pages, struct niobuf_local *local,
- int chunk_bits);
+ enum ll_compr_type type, int lvl, int chunk_bits);
int (*o_commitrw)(const struct lu_env *env, int cmd,
struct obd_export *exp, struct obdo *oa,
int objcount, struct obd_ioobj *obj,
}
rc = OBP(exp->exp_obd, decompress_read)(env, exp, oa, rnb, lnb, obj,
- npages, type, lvl, chunk_bits);
+ npages, type, lvl, chunk_bits,
+ false);
RETURN(rc);
}
struct obd_export *exp, struct obdo *oa,
int objcount, struct obd_ioobj *obj,
struct niobuf_remote *remote, int *pages,
- struct niobuf_local *local, int chunk_bits)
+ struct niobuf_local *local,
+ enum ll_compr_type type, int lvl, int chunk_bits)
{
int rc;
}
rc = OBP(exp->exp_obd, preprw)(env, cmd, exp, oa, objcount, obj, remote,
- pages, local, chunk_bits);
+ pages, local, type, lvl, chunk_bits);
RETURN(rc);
}
int mdt_obd_preprw(const struct lu_env *env, int cmd, struct obd_export *exp,
struct obdo *oa, int objcount, struct obd_ioobj *obj,
struct niobuf_remote *rnb, int *nr_local,
- struct niobuf_local *lnb, int chunk_size);
+ struct niobuf_local *lnb, enum ll_compr_type type, int lvl,
+ int chunk_bits);
int mdt_obd_commitrw(const struct lu_env *env, int cmd, struct obd_export *exp,
struct obdo *oa, int objcount, struct obd_ioobj *obj,
int mdt_obd_preprw(const struct lu_env *env, int cmd, struct obd_export *exp,
struct obdo *oa, int objcount, struct obd_ioobj *obj,
struct niobuf_remote *rnb, int *nr_local,
- struct niobuf_local *lnb, int chunk_size)
+ struct niobuf_local *lnb, enum ll_compr_type type, int lvl,
+ int chunk_bits)
{
struct tgt_session_info *tsi = tgt_ses_info(env);
struct mdt_thread_info *info = tsi2mdt_info(tsi);
/* this should never be hit because setstripe does not allow DOM +
* compression, but it's here just in case
*/
- if (chunk_size != 0) {
+ if (chunk_bits != 0) {
rc = -EOPNOTSUPP;
CERROR("%s: Compression is not supported on dom, rc %d\n",
exp->exp_obd->obd_name, rc);
struct obd_export *export, struct obdo *oa,
int objcount, struct obd_ioobj *obj,
struct niobuf_remote *nb, int *pages,
- struct niobuf_local *res, int chunk_size)
+ struct niobuf_local *res, enum ll_compr_type type,
+ int lvl, int chunk_bits)
{
struct obd_device *obd;
int tot_bytes = 0;
lpages = npages;
ret = obd_preprw(env, rw, exp, oa, 1, &ioo, &rnb, &lpages, lnb,
- 0);
+ 0, 0, 0);
if (ret != 0)
GOTO(out, ret);
int decompress_rnb(const char *obd_name, struct niobuf_local *lnbs,
int lnb_npages, __u64 rnb_start, __u64 rnb_end,
int *lnb_start, void **bounce_src, void **bounce_dst,
- enum ll_compr_type type, int lvl, int chunk_size)
+ enum ll_compr_type type, int lvl, int chunk_size,
+ bool write)
{
struct niobuf_local *lnb = NULL;
int pages_per_chunk = chunk_size / PAGE_SIZE;
* a short chunk, so the read will return the complete
* chunk to the client and the client will decompress it
*/
- if (lnbs[j].lnb_rc == 0) {
+ if (lnbs[j].lnb_rc == 0 && !write) {
CDEBUG(D_SEC, "Hit EOF in lnb %d at %llu\n",
j, lnbs[j].lnb_file_offset);
if (prev &&
int decompress_rnb(const char *obd_name, struct niobuf_local *lnbs,
int lnb_npages, __u64 rnb_start, __u64 rnb_end,
int *lnb_offset, void **bounce_src, void **bounce_dst,
- enum ll_compr_type type, int lvl, int chunk_size);
+ enum ll_compr_type type, int lvl, int chunk_size,
+ bool write);
#endif /* _OFD_COMPRESS_H */
struct obdo *oa, struct niobuf_remote *rnb,
struct niobuf_local *lnb, struct obd_ioobj *obj,
int npages, enum ll_compr_type type, int lvl,
- int chunk_bits);
-int ofd_preprw(const struct lu_env *env,int cmd, struct obd_export *exp,
+ int chunk_bits, bool write);
+int ofd_preprw(const struct lu_env *env, int cmd, struct obd_export *exp,
struct obdo *oa, int objcount, struct obd_ioobj *obj,
struct niobuf_remote *rnb, int *nr_local,
- struct niobuf_local *lnb, int chunk_bits);
+ struct niobuf_local *lnb, enum ll_compr_type type, int lvl,
+ int chunk_bits);
int ofd_commitrw(const struct lu_env *env, int cmd, struct obd_export *exp,
struct obdo *oa, int objcount, struct obd_ioobj *obj,
struct niobuf_remote *rnb, int npages,
struct lu_attr *la, struct obdo *oa,
int objcount, struct obd_ioobj *obj,
struct niobuf_remote *rnb, int *nr_local,
- struct niobuf_local *lnb, int chunk_bits)
+ struct niobuf_local *lnb, enum ll_compr_type type,
+ int lvl, int chunk_bits)
{
struct range_lock *range = &ofd_info(env)->fti_write_range;
struct dt_object *dt_obj = NULL;
if (chunk_size && !(rnb[i].rnb_flags & OBD_BRW_COMPRESSED)) {
chunk_round(&buf_start, &buf_end, chunk_size);
- /* rounded rnbs can overlap at the chunk level, but it's
- * important we don't allocate multiple buffers for the
- * same page, so move the start of this buffer to the
- * end of the previous one
- */
if (buf_start < prev_buf_end) {
buf_start = prev_buf_end;
/* two rnbs may be entirely inside the same
continue;
}
- /* this write is unaligned */
+ /* this write is not aligned to chunk size */
if (buf_start != orig_start || buf_end != orig_end) {
/* get attr only once for each IO */
if (!dt_obj) {
}
if (compr_unaligned_write) {
- /* for now, read will not hold pages locked, since it's not
- * doing decompression. this will be changed shortly.
- */
rc = dt_read_prep(env, ofd_object_child(fo), lnb, *nr_local,
- false);
+ true);
+ if (unlikely(rc != 0))
+ GOTO(err, rc);
+ rc = ofd_decompress_read(env, exp, oa, rnb, lnb, obj, *nr_local,
+ type, lvl, chunk_bits, true);
if (unlikely(rc != 0))
GOTO(err, rc);
- /* read_prep sets rc if it read data, or on error, but the write
- * code expects rc to be zero, so we clear rc here except on
- * error
+ /* read_prep sets lnb_rc if it read data, or on error, but the
+ * write code expects rc to be zero, so we clear rc here except
+ * on error
*/
for (i = 0; i < *nr_local; i++) {
if (lnb[i].lnb_rc > 0)
struct obdo *oa, struct niobuf_remote *rnb,
struct niobuf_local *lnb, struct obd_ioobj *obj,
int npages, enum ll_compr_type type, int lvl,
- int chunk_bits)
+ int chunk_bits, bool write)
{
struct ofd_device *ofd = ofd_exp(exp);
struct lu_fid *fid = &oa->o_oi.oi_fid;
rnb_start, rnb_end);
chunk_round(&chunk_start, &chunk_end, chunk_size);
if (chunk_start != rnb_start || chunk_end != rnb_end) {
+ /* if the client provided this unaligned write already
+ * compressed, the client knows the write was at/past
+ * EOF, so we can skip it
+ */
+ if (write && rnb[i].rnb_flags & OBD_BRW_COMPRESSED) {
+ CDEBUG(D_SEC,
+ "skipping unaligned rnb %d, already compressed\n",
+ i);
+ continue;
+ }
/* rounded rnbs can overlap at the chunk level, but if
* they do, we've already decompressed that chunk, so
* start at the end of that chunk
rc = decompress_rnb(exp->exp_obd->obd_name, lnb, npages,
rnb_start, rnb_end, &lnb_start,
bounce_src, bounce_dst, type, lvl,
- chunk_size);
+ chunk_size, write);
if (rc)
GOTO(out, rc);
}
/* after decompression, we can now unlock the pages in the lnb so they
* can be read from other threads.
*
- * NB: We will skip this on decompress-for-rewrite, since the pages
- * must be locked for write.
+ * we skip this on decompress-for-rewrite, since the pages must be
+ * locked for write.
*/
- dt_unlock_pages(ofd_object_child(fo), lnb, npages);
+ if (!write)
+ dt_unlock_pages(ofd_object_child(fo), lnb, npages);
if (bounce_dst)
sptlrpc_pool_put_pages(&bounce_dst, buf_bits);
int ofd_preprw(const struct lu_env *env, int cmd, struct obd_export *exp,
struct obdo *oa, int objcount, struct obd_ioobj *obj,
struct niobuf_remote *rnb, int *nr_local,
- struct niobuf_local *lnb, int chunk_bits)
+ struct niobuf_local *lnb, enum ll_compr_type type, int lvl,
+ int chunk_bits)
{
struct tgt_session_info *tsi = tgt_ses_info(env);
struct ofd_device *ofd = ofd_exp(exp);
if (cmd == OBD_BRW_WRITE) {
la_from_obdo(&info->fti_attr, oa, OBD_MD_FLGETATTR);
rc = ofd_preprw_write(env, exp, ofd, fid, &info->fti_attr, oa,
- objcount, obj, rnb, nr_local, lnb,
- chunk_bits);
+ objcount, obj, rnb, nr_local, lnb, type,
+ lvl, chunk_bits);
} else if (cmd == OBD_BRW_READ) {
tgt_grant_prepare_read(env, exp, oa);
rc = ofd_preprw_read(env, exp, ofd, fid, &info->fti_attr, oa,
rc = obd_preprw(tsi->tsi_env, OBD_BRW_READ, exp, &repbody->oa, 1,
ioo, remote_nb, &npages_local, local_io_nb,
- chunk_bits);
+ compr_type, compr_lvl, chunk_bits);
if (rc != 0)
GOTO(out_lock, rc);
int chunk_bits = 0;
int npages_local;
ktime_t kstart;
+ int compr_lvl;
int objcount;
int niocount;
int nob = 0;
olc = &body->oa.o_layout_compr;
compr_type = olc->ol_compr_type;
+ compr_lvl = olc->ol_compr_lvl;
if (compr_type != LL_COMPR_TYPE_NONE) {
int nrbufs = ioo->ioo_bufcnt;
unsigned int chunk_log_bits;
kstart = ktime_get();
rc = obd_preprw(tsi->tsi_env, OBD_BRW_WRITE, exp, &repbody->oa,
objcount, ioo, remote_nb, &npages_local, local_io_nb,
- chunk_bits);
+ compr_type, compr_lvl, chunk_bits);
if (rc < 0)
GOTO(out_lock, rc);
# bug number for skipped test:
ALWAYS_EXCEPT="$SANITY_COMPR_EXCEPT "
-### TEMPORARY WILL BE REMOVED IN A FUTURE PATCH ###
-always_except EX-7601 1000
-always_except EX-7601 1001
-always_except EX-7601 1002
-always_except EX-7601 1003
build_test_filter
# until data compression on MDT works
always_except EX-7806 100k
-### TEMPORARY WILL BE REMOVED IN A FUTURE PATCH ###
-always_except EX-7601 100j
-always_except EX-7601 100l
build_test_filter
always_except LU-9054 312
always_except LU-8411 407
always_except EX-4334 428
-### TEMPORARY - REMOVED IN LATER PATCH ###
-always_except EX-7601 460
if $SHARED_KEY; then
always_except LU-14181 64e 64f
ALWAYS_EXCEPT="$SANITYN_EXCEPT "
# bug number for skipped test: LU-7105
-ALWAYS_EXCEPT+=" 28 "
+ALWAYS_EXCEPT+=" 28"
# UPDATE THE COMMENT ABOVE WITH BUG NUMBERS WHEN CHANGING ALWAYS_EXCEPT!
if [ $mds1_FSTYPE = "zfs" ]; then