diff --git a/fs/lustre/llite/file.c b/fs/lustre/llite/file.c
index 0186db4..05a75ae 100644
--- a/fs/lustre/llite/file.c
+++ b/fs/lustre/llite/file.c
@@ -1417,7 +1417,7 @@ static int ll_lease_file_resync(struct obd_client_handle *och,
 	return rc;
 }
 
-int ll_merge_attr(const struct lu_env *env, struct inode *inode)
+static int ll_merge_attr_nolock(const struct lu_env *env, struct inode *inode)
 {
 	struct ll_inode_info *lli = ll_i2info(inode);
 	struct cl_object *obj = lli->lli_clob;
@@ -1427,10 +1427,7 @@ int ll_merge_attr(const struct lu_env *env, struct inode *inode)
 	s64 ctime;
 	int rc = 0;
 
-	ll_inode_size_lock(inode);
-
-	/*
-	 * merge timestamps the most recently obtained from MDS with
+	/* merge timestamps the most recently obtained from MDS with
 	 * timestamps obtained from OSTSs.
 	 *
 	 * Do not overwrite atime of inode because it may be refreshed
@@ -1463,7 +1460,7 @@ int ll_merge_attr(const struct lu_env *env, struct inode *inode)
 	if (rc != 0) {
 		if (rc == -ENODATA)
 			rc = 0;
-		goto out_size_unlock;
+		goto out;
 	}
 
 	if (atime < attr->cat_atime)
@@ -1475,8 +1472,8 @@ int ll_merge_attr(const struct lu_env *env, struct inode *inode)
 	if (mtime < attr->cat_mtime)
 		mtime = attr->cat_mtime;
 
-	CDEBUG(D_VFSTRACE, DFID " updating i_size %llu\n",
-	       PFID(&lli->lli_fid), attr->cat_size);
+	CDEBUG(D_VFSTRACE, DFID" updating i_size %llu i_block %llu\n",
+	       PFID(&lli->lli_fid), attr->cat_size, attr->cat_blocks);
 
 	if (fscrypt_require_key(inode) == -ENOKEY) {
 		/* Without the key, round up encrypted file size to next
@@ -1495,13 +1492,34 @@ int ll_merge_attr(const struct lu_env *env, struct inode *inode)
 	inode->i_mtime.tv_sec = mtime;
 	inode->i_atime.tv_sec = atime;
 	inode->i_ctime.tv_sec = ctime;
+out:
+	return rc;
+}
 
-out_size_unlock:
+int ll_merge_attr(const struct lu_env *env, struct inode *inode)
+{
+	int rc;
+
+	ll_inode_size_lock(inode);
+	rc = ll_merge_attr_nolock(env, inode);
 	ll_inode_size_unlock(inode);
 
 	return rc;
 }
 
+/* Use to update size and blocks on inode for LSOM if there is no contention */
+int ll_merge_attr_try(const struct lu_env *env, struct inode *inode)
+{
+	int rc = 0;
+
+	if (ll_inode_size_trylock(inode)) {
+		rc = ll_merge_attr_nolock(env, inode);
+		ll_inode_size_unlock(inode);
+	}
+
+	return rc;
+}
+
 /**
  * Set designated mirror for I/O.
  *
diff --git a/fs/lustre/llite/llite_internal.h b/fs/lustre/llite/llite_internal.h
index 6088da08..88dbd6c 100644
--- a/fs/lustre/llite/llite_internal.h
+++ b/fs/lustre/llite/llite_internal.h
@@ -551,6 +551,7 @@ static inline void obd_connect_set_enc_fid2path(struct obd_connect_data *data)
 
 void ll_inode_size_lock(struct inode *inode);
 void ll_inode_size_unlock(struct inode *inode);
+int ll_inode_size_trylock(struct inode *inode);
 
 static inline struct ll_inode_info *ll_i2info(struct inode *inode)
 {
@@ -1248,6 +1249,7 @@ int ll_dir_getstripe(struct inode *inode, void **plmm, int *plmm_size,
 		     struct ptlrpc_request **request, u64 valid);
 int ll_fsync(struct file *file, loff_t start, loff_t end, int data);
 int ll_merge_attr(const struct lu_env *env, struct inode *inode);
+int ll_merge_attr_try(const struct lu_env *env, struct inode *inode);
 int ll_fid2path(struct inode *inode, void __user *arg);
 int __ll_fid2path(struct inode *inode, struct getinfo_fid2path *gfout,
 		  size_t outsize, u32 pathlen_orig);
diff --git a/fs/lustre/llite/llite_lib.c b/fs/lustre/llite/llite_lib.c
index b1bbeb3..2c286e8 100644
--- a/fs/lustre/llite/llite_lib.c
+++ b/fs/lustre/llite/llite_lib.c
@@ -2558,6 +2558,16 @@ void ll_inode_size_unlock(struct inode *inode)
 	mutex_unlock(&lli->lli_size_mutex);
 }
 
+int ll_inode_size_trylock(struct inode *inode)
+{
+	struct ll_inode_info *lli;
+
+	LASSERT(!S_ISDIR(inode->i_mode));
+
+	lli = ll_i2info(inode);
+	return mutex_trylock(&lli->lli_size_mutex);
+}
+
 void ll_update_inode_flags(struct inode *inode, unsigned int ext_flags)
 {
 	struct ll_inode_info *lli = ll_i2info(inode);
diff --git a/fs/lustre/llite/vvp_io.c b/fs/lustre/llite/vvp_io.c
index 50c2872..31a3992 100644
--- a/fs/lustre/llite/vvp_io.c
+++ b/fs/lustre/llite/vvp_io.c
@@ -763,6 +763,10 @@ static void vvp_io_setattr_end(const struct lu_env *env,
 		vvp_do_vmtruncate(inode, size);
 		mutex_unlock(&lli->lli_setattr_mutex);
 		trunc_sem_up_write(&lli->lli_trunc_sem);
+
+		/* Update size and blocks for LSOM */
+		if (!io->ci_ignore_layout)
+			ll_merge_attr(env, inode);
 	} else if (cl_io_is_fallocate(io)) {
 		int mode = io->u.ci_setattr.sa_falloc_mode;
 
@@ -1306,6 +1310,20 @@ static void vvp_io_rw_end(const struct lu_env *env,
 	trunc_sem_up_read(&lli->lli_trunc_sem);
 }
 
+static void vvp_io_write_end(const struct lu_env *env,
+			     const struct cl_io_slice *ios)
+{
+	struct inode *inode = vvp_object_inode(ios->cis_obj);
+	struct cl_io *io = ios->cis_io;
+
+	vvp_io_rw_end(env, ios);
+
+	/* Update size and blocks for LSOM (best effort) */
+	if (!io->ci_ignore_layout && cl_io_is_sync_write(io))
+		ll_merge_attr_try(env, inode);
+}
+
+
 static int vvp_io_kernel_fault(struct vvp_fault_io *cfio)
 {
 	struct vm_fault *vmf = cfio->ft_vmf;
@@ -1559,6 +1577,17 @@ static int vvp_io_fsync_start(const struct lu_env *env,
 	return 0;
 }
 
+static void vvp_io_fsync_end(const struct lu_env *env,
+			     const struct cl_io_slice *ios)
+{
+	struct inode *inode = vvp_object_inode(ios->cis_obj);
+	struct cl_io *io = ios->cis_io;
+
+	/* Update size and blocks for LSOM (best effort) */
+	if (!io->ci_ignore_layout)
+		ll_merge_attr_try(env, inode);
+}
+
 static int vvp_io_read_ahead(const struct lu_env *env,
 			     const struct cl_io_slice *ios,
 			     pgoff_t start, struct cl_read_ahead *ra)
@@ -1639,7 +1668,7 @@ static void vvp_io_lseek_end(const struct lu_env *env,
 			.cio_iter_fini	= vvp_io_write_iter_fini,
 			.cio_lock	= vvp_io_write_lock,
 			.cio_start	= vvp_io_write_start,
-			.cio_end	= vvp_io_rw_end,
+			.cio_end	= vvp_io_write_end,
 			.cio_advance	= vvp_io_advance,
 		},
 		[CIT_SETATTR] = {
@@ -1658,7 +1687,8 @@ static void vvp_io_lseek_end(const struct lu_env *env,
 		},
 		[CIT_FSYNC] = {
 			.cio_start	= vvp_io_fsync_start,
-			.cio_fini	= vvp_io_fini
+			.cio_fini	= vvp_io_fini,
+			.cio_end	= vvp_io_fsync_end,
 		},
 		[CIT_GLIMPSE] = {
 			.cio_fini	= vvp_io_fini
