Whamcloud - gitweb
LU-13227 ofd: update lvb before dropping server lock 90/37790/7
authorWang Shilong <wshilong@ddn.com>
Wed, 4 Mar 2020 07:41:58 +0000 (15:41 +0800)
committerOleg Drokin <green@whamcloud.com>
Wed, 11 Mar 2020 02:19:37 +0000 (02:19 +0000)
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 <wshilong@ddn.com>
Reviewed-on: https://review.whamcloud.com/37790
Reviewed-by: Bobi Jam <bobijam@hotmail.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Alex Zhuravlev <bzzz@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/ofd/ofd_io.c
lustre/tests/sanityn.sh

index 5c78d0c..3049225 100644 (file)
@@ -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 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;
 
        __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;
                }
 
                        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. */
                /* 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) {
                        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) {
 
                /* 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);
                        ost_fid_build_resid(fid, &info->fti_resid);
                        rs = ldlm_resource_get(ns, NULL, &info->fti_resid,
                                               LDLM_EXTENT, 0);
index 731c717..918dbac 100755 (executable)
@@ -503,6 +503,26 @@ test_16d() {
 }
 run_test 16d "Verify DIO and buffer IO with two clients"
 
 }
 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
 
 test_17() { # bug 3513, 3667
        remote_ost_nodsh && skip "remote OST with nodsh" && return