From 92d799217aeac4e1e859264d157c62e0f02b83a8 Mon Sep 17 00:00:00 2001 From: Wang Shilong Date: Wed, 4 Mar 2020 15:41:58 +0800 Subject: [PATCH] LU-13227 ofd: update lvb before dropping server lock If this is a local lock on a server namespace and this was the last reference, lock will be canceled directly instead of staying at LRU, this might be problem that we will lose O_DIRECT write size expanding without LVB updating. This patch try to fix the problem by updating LVB just after writing but before lock is dropped. Fixes: 6bce536725 ("LU-4198 clio: turn on lockless for some kind of IO") Change-Id: I9d1fbac30c8599d677358e8720fe9b3ca81fe818 Signed-off-by: Wang Shilong Reviewed-on: https://review.whamcloud.com/37790 Reviewed-by: Bobi Jam Reviewed-by: Andreas Dilger Tested-by: jenkins Tested-by: Maloo Reviewed-by: Alex Zhuravlev Reviewed-by: Oleg Drokin --- lustre/ofd/ofd_io.c | 22 +++++++++++++++++++--- lustre/tests/sanityn.sh | 20 ++++++++++++++++++++ 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/lustre/ofd/ofd_io.c b/lustre/ofd/ofd_io.c index 5c78d0c..3049225 100644 --- a/lustre/ofd/ofd_io.c +++ b/lustre/ofd/ofd_io.c @@ -1298,6 +1298,8 @@ int ofd_commitrw(const struct lu_env *env, int cmd, struct obd_export *exp, struct ofd_thread_info *info = ofd_info(env); struct ofd_device *ofd = ofd_exp(exp); const struct lu_fid *fid = &oa->o_oi.oi_fid; + struct ldlm_namespace *ns = ofd->ofd_namespace; + struct ldlm_resource *rs = NULL; __u64 valid; int rc = 0; @@ -1349,6 +1351,23 @@ int ofd_commitrw(const struct lu_env *env, int cmd, struct obd_export *exp, oa->o_valid |= OBD_MD_FLALLQUOTA; } + /** + * Update LVB after writing finish for server lock, see + * comments in ldlm_lock_decref_internal(), If this is a + * local lock on a server namespace and this was the last + * reference, lock will be destroyed directly thus there + * is no chance for ldlm_request_cancel() to update lvb. + */ + if (rc == 0 && (rnb[0].rnb_flags & OBD_BRW_SRVLOCK)) { + ost_fid_build_resid(fid, &info->fti_resid); + rs = ldlm_resource_get(ns, NULL, &info->fti_resid, + LDLM_EXTENT, 0); + if (!IS_ERR(rs)) { + ldlm_res_lvbo_update(rs, NULL, 1); + ldlm_resource_putref(rs); + } + } + /* Convert back to client IDs. LU-9671. * nodemap_get_from_exp() may fail due to nodemap deactivated, * server ID will be returned back to client in that case. */ @@ -1363,14 +1382,11 @@ int ofd_commitrw(const struct lu_env *env, int cmd, struct obd_export *exp, nodemap_putref(nodemap); } } else if (cmd == OBD_BRW_READ) { - struct ldlm_namespace *ns = ofd->ofd_namespace; /* If oa != NULL then ofd_preprw_read updated the inode * atime and we should update the lvb so that other glimpses * will also get the updated value. bug 5972 */ if (oa && ns && ns->ns_lvbo && ns->ns_lvbo->lvbo_update) { - struct ldlm_resource *rs = NULL; - ost_fid_build_resid(fid, &info->fti_resid); rs = ldlm_resource_get(ns, NULL, &info->fti_resid, LDLM_EXTENT, 0); diff --git a/lustre/tests/sanityn.sh b/lustre/tests/sanityn.sh index 731c717..918dbac 100755 --- a/lustre/tests/sanityn.sh +++ b/lustre/tests/sanityn.sh @@ -503,6 +503,26 @@ test_16d() { } run_test 16d "Verify DIO and buffer IO with two clients" +test_16e() { # LU-13227 + local file1=$DIR1/$tfile + local file2=$DIR2/$tfile + + # client1 write 10M data + dd if=/dev/zero of=$file1 bs=1M count=10 + # drop locks + cancel_lru_locks osc > /dev/null + # use lockahead to generate one PW lock to keep LVB loaded. + $LFS ladvise -a lockahead --start 0 --length 1M \ + --mode WRITE $file1 + # direct write to extend file size on client2 + dd if=/dev/zero of=$file2 bs=1M seek=20 count=1 \ + oflag=direct conv=notrunc + local filesize=$(stat -c %s $file2) + [ "$filesize" -eq 22020096 ] || + error "expected filesize 22020096 got $filesize" + rm -f $file1 +} +run_test 16e "Verify size consistency for O_DIRECT write" test_17() { # bug 3513, 3667 remote_ost_nodsh && skip "remote OST with nodsh" && return -- 1.8.3.1