Whamcloud - gitweb
LU-10509 mdd: don't set size attr for DOM file 08/33008/2
authorMikhail Pershin <mpershin@whamcloud.com>
Wed, 15 Aug 2018 21:15:03 +0000 (00:15 +0300)
committerOleg Drokin <green@whamcloud.com>
Sat, 1 Sep 2018 03:28:54 +0000 (03:28 +0000)
When client does truncate it calls ll_md_setattr() followed by
ll_setattr_ost() to set size on OSTs. With DOM file that causes
setattr on MDT first including size then PUNCH RPC on the same
object. That was considered as non-optimized situation and
LU-11033 is intended to improve it, but with ZFS there is
check in OSD which does no truncate if size is the same already.
Therefore real file blocks are not truncated actually so sparse
write beyond the end of file will get old data in hole instead of
zeroes.

Quick patch checks if mdd_attr_set() is going to set SIZE attr for
DOM file and clear LA_SIZE bit, assuming there will be truncate.

Complete solution for this will be implemented under LU-11033

Signed-off-by: Mikhail Pershin <mpershin@whamcloud.com>
Change-Id: I47873dccf4270e5f0338f7b6696aa5969cfb9444
Reviewed-on: https://review.whamcloud.com/33008
Tested-by: Jenkins
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: John L. Hammond <jhammond@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/mdd/mdd_object.c

index feb2720..3e48fcc 100644 (file)
@@ -1121,6 +1121,30 @@ static inline bool permission_needs_sync(const struct lu_attr *old,
        return false;
 }
 
+static inline __u64 mdd_lmm_dom_size(void *buf)
+{
+       struct lov_mds_md *lmm = buf;
+       struct lov_comp_md_v1 *comp_v1;
+       struct lov_mds_md *v1;
+       __u32 off;
+
+       if (lmm == NULL)
+               return 0;
+
+       if (le32_to_cpu(lmm->lmm_magic) != LOV_MAGIC_COMP_V1)
+               return 0;
+
+       comp_v1 = (struct lov_comp_md_v1 *)lmm;
+       off = le32_to_cpu(comp_v1->lcm_entries[0].lcme_offset);
+       v1 = (struct lov_mds_md *)((char *)comp_v1 + off);
+
+       /* DoM entry is the first entry always */
+       if (lov_pattern(le32_to_cpu(v1->lmm_pattern)) == LOV_PATTERN_MDT)
+               return le64_to_cpu(comp_v1->lcm_entries[0].lcme_extent.e_end);
+
+       return 0;
+}
+
 /* set attr and LOV EA at once, return updated attr */
 int mdd_attr_set(const struct lu_env *env, struct md_object *obj,
                 const struct md_attr *ma)
@@ -1198,6 +1222,25 @@ int mdd_attr_set(const struct lu_env *env, struct md_object *obj,
                       la->la_mtime, la->la_ctime);
 
        mdd_write_lock(env, mdd_obj, MOR_TGT_CHILD);
+
+       /* LU-10509: setattr of LA_SIZE should be skipped case of DOM,
+        * otherwise following truncate will do nothing and truncated
+        * data may be read again. This is a quick fix until LU-11033
+        * will be resolved.
+        */
+       if (la_copy->la_valid & LA_SIZE) {
+               struct lu_buf *lov_buf = mdd_buf_get(env, NULL, 0);
+
+               rc = mdd_get_lov_ea(env, mdd_obj, lov_buf);
+               if (rc) {
+                       rc = 0;
+               } else {
+                       if (mdd_lmm_dom_size(lov_buf->lb_buf) > 0)
+                               la_copy->la_valid &= ~LA_SIZE;
+                       lu_buf_free(lov_buf);
+               }
+       }
+
        if (la_copy->la_valid) {
                rc = mdd_attr_set_internal(env, mdd_obj, la_copy, handle, 1);
 
@@ -2151,30 +2194,6 @@ static inline int mdd_set_lmm_gen(struct lov_mds_md *lmm, __u32 *gen)
        return mdd_lmm_gen(lmm, gen, false);
 }
 
-static inline __u64 mdd_lmm_dom_size(void *buf)
-{
-       struct lov_mds_md *lmm = buf;
-       struct lov_comp_md_v1 *comp_v1;
-       struct lov_mds_md *v1;
-       __u32 off;
-
-       if (lmm == NULL)
-               return 0;
-
-       if (le32_to_cpu(lmm->lmm_magic) != LOV_MAGIC_COMP_V1)
-               return 0;
-
-       comp_v1 = (struct lov_comp_md_v1 *)lmm;
-       off = le32_to_cpu(comp_v1->lcm_entries[0].lcme_offset);
-       v1 = (struct lov_mds_md *)((char *)comp_v1 + off);
-
-       /* DoM entry is the first entry always */
-       if (lov_pattern(le32_to_cpu(v1->lmm_pattern)) == LOV_PATTERN_MDT)
-               return le64_to_cpu(comp_v1->lcm_entries[0].lcme_extent.e_end);
-
-       return 0;
-}
-
 /**
  * swap layouts between 2 lustre objects
  */