From 91cb04ef800a8ae9384777286ee1282a262ee89e Mon Sep 17 00:00:00 2001 From: Andreas Dilger Date: Mon, 6 Jun 2022 17:14:32 -0600 Subject: [PATCH] LU-15748 ofd: fix fallocate interop for older clients The logic for detecting older client fallocate was backward, and should be checking if the OBD_CONNECT_OLD_FALLOC patch was *not* present to detect old clients. Since the new server does not have OLD_FALLOC in the SUPPORTED flags, it will clear the flag from the export at connect time, so it needs to be saved in the export early on. Test-Parameters: testlist=sanityn env=ONLY=16,HONOR_EXCEPT=y Test-Parameters: serverversion=2.14 testlist=sanityn env=ONLY=16,HONOR_EXCEPT=y Fixes: 7905359296 ("LU-15748 osc: fallocate interop for 2.14 clients") Signed-off-by: Andreas Dilger Change-Id: I327183025a8de6fd814a7c2929365497153ebbe5 Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/47548 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Arshad Hussain Reviewed-by: Jian Yu Reviewed-by: Oleg Drokin --- lustre/include/lustre_export.h | 5 +++++ lustre/ldlm/ldlm_lib.c | 19 +++++++++++++++++++ lustre/mdt/mdt_io.c | 15 ++++++++++++++- lustre/ofd/ofd_dev.c | 21 +++++++++++++++++---- lustre/tests/sanityn.sh | 3 +++ 5 files changed, 58 insertions(+), 5 deletions(-) diff --git a/lustre/include/lustre_export.h b/lustre/include/lustre_export.h index 3137ccf..7a658d1 100644 --- a/lustre/include/lustre_export.h +++ b/lustre/include/lustre_export.h @@ -279,6 +279,11 @@ struct obd_export { exp_replay_done:1, /* local client with recovery disabled */ exp_no_recovery:1, + /* old client will set this to 1 (true). + * Newer clients 2.15 and beyond will have this + * set as 0 (false) + */ + exp_old_falloc:1, exp_hashed:1; /* also protected by exp_lock */ enum lustre_sec_part exp_sp_peer; diff --git a/lustre/ldlm/ldlm_lib.c b/lustre/ldlm/ldlm_lib.c index dadb8bd..9eea19a 100644 --- a/lustre/ldlm/ldlm_lib.c +++ b/lustre/ldlm/ldlm_lib.c @@ -1107,6 +1107,9 @@ int target_handle_connect(struct ptlrpc_request *req) struct obd_connect_data *data, *tmpdata; int size, tmpsize; lnet_nid_t client_nid; +#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 0, 53, 0) + int tmp_exp_old_falloc; +#endif struct ptlrpc_connection *pcon = NULL; ENTRY; @@ -1195,6 +1198,15 @@ int target_handle_connect(struct ptlrpc_request *req) if (!(data->ocd_connect_flags & OBD_CONNECT_FULL20)) GOTO(out, rc = -EPROTO); + /* Old clients will have 'tmp_exp_old_falloc' as 1. + * Newer clients (2.15) and beyond will have it set as 0 + */ + tmp_exp_old_falloc = + !!(data->ocd_connect_flags & OBD_CONNECT_OLD_FALLOC); + + CDEBUG(D_INFO, "%s: ocd_connect_flags: %#llx tmp_exp_old_falloc: %d\n", + target->obd_name, data->ocd_connect_flags, tmp_exp_old_falloc); + /* * Don't allow liblustre clients to connect. * - testing was disabled in v2_2_50_0-61-g6a75d65 @@ -1514,6 +1526,13 @@ dont_check_exports: LASSERT(lustre_msg_get_conn_cnt(req->rq_reqmsg) > 0); export->exp_conn_cnt = lustre_msg_get_conn_cnt(req->rq_reqmsg); +#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 0, 53, 0) + /* make 'tmp_exp_old_falloc' persistent by saving it into + * server side export object(obd_export) + */ + export->exp_old_falloc = tmp_exp_old_falloc; +#endif + /* Check to see if connection came from another NID. */ if (export->exp_connection != NULL && !nid_same(&export->exp_connection->c_peer.nid, diff --git a/lustre/mdt/mdt_io.c b/lustre/mdt/mdt_io.c index 3a9ec7e..f766315 100644 --- a/lustre/mdt/mdt_io.c +++ b/lustre/mdt/mdt_io.c @@ -971,13 +971,26 @@ int mdt_fallocate_hdl(struct tgt_session_info *tsi) if ((oa->o_valid & (OBD_MD_FLSIZE | OBD_MD_FLBLOCKS)) != (OBD_MD_FLSIZE | OBD_MD_FLBLOCKS) #if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 21, 53, 0) - && (tgt_conn_flags(tsi) & OBD_CONNECT_OLD_FALLOC) + && !tsi->tsi_exp->exp_old_falloc #endif ) RETURN(-EOPNOTSUPP); start = oa->o_size; end = oa->o_blocks; + CDEBUG(D_INFO, "%s: start: %llu end: %llu\n", + mdt->mdt_child_exp->exp_obd->obd_name, start, end); + +#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 21, 53, 0) + /* + * For inter-op case with older clients (where exp_old_falloc is true) + * fallocate() start and end are passed in as 0 (For interior case + * where end offset less than file size) This is fixed later. + * For such cases we return -EOPNOTSUPP + */ + if (tsi->tsi_exp->exp_old_falloc && start >= end) + RETURN(-EOPNOTSUPP); +#endif /* client should already limit len >= 0 */ if (start >= end) RETURN(-EINVAL); diff --git a/lustre/ofd/ofd_dev.c b/lustre/ofd/ofd_dev.c index 811a1e7..535196a 100644 --- a/lustre/ofd/ofd_dev.c +++ b/lustre/ofd/ofd_dev.c @@ -1991,9 +1991,10 @@ static int ofd_fallocate_hdl(struct tgt_session_info *tsi) * fallocate() start and end are passed in o_size and o_blocks * on the wire. Clients 2.15.0 and newer should always set * the OBD_MD_FLSIZE and OBD_MD_FLBLOCKS valid flags, but some - * older client versions did not. We permit older clients to - * not set these flags, checking their version by proxy using - * the lack of OBD_CONNECT_TRUNCLOCK to imply 2.14.0 and older. + * older client (exp_old_falloc is true) versions did not. + * We permit older clients to not set these flags, checking their + * version by proxy using the lack of OBD_CONNECT_TRUNCLOCK to + * imply 2.14.0 and older. * * Return -EOPNOTSUPP to also work with older clients not * supporting newer server modes. @@ -2001,13 +2002,25 @@ static int ofd_fallocate_hdl(struct tgt_session_info *tsi) if ((oa->o_valid & (OBD_MD_FLSIZE | OBD_MD_FLBLOCKS)) != (OBD_MD_FLSIZE | OBD_MD_FLBLOCKS) #if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 21, 53, 0) - && (tgt_conn_flags(tsi) & OBD_CONNECT_OLD_FALLOC) + && !tsi->tsi_exp->exp_old_falloc #endif ) RETURN(-EOPNOTSUPP); start = oa->o_size; end = oa->o_blocks; + CDEBUG(D_INFO, "%s: start: %llu end: %llu\n", tgt_name(tsi->tsi_tgt), + start, end); + +#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 21, 53, 0) + /* For inter-op case with older clients (where exp_old_falloc is true) + * fallocate() start and end are passed in as 0 (For interior case + * where end offset less than file size) This is fixed later. + * For such cases we return -EOPNOTSUPP + */ + if (tsi->tsi_exp->exp_old_falloc && start >= end) + RETURN(-EOPNOTSUPP); +#endif /* client should already limit len >= 0 */ if (start >= end) RETURN(-EINVAL); diff --git a/lustre/tests/sanityn.sh b/lustre/tests/sanityn.sh index 25158d0..ce4968e 100755 --- a/lustre/tests/sanityn.sh +++ b/lustre/tests/sanityn.sh @@ -563,6 +563,9 @@ test_16f() { # LU-14541 local duration=20 local status + (( $MDS1_VERSION > $(version_code 2.15.51) )) || + skip "Need MDS version at least 2.15.51" + timeout --preserve-status --signal=USR1 $duration \ rw_seq_cst_vs_drop_caches $file1 $file2 status=$? -- 1.8.3.1