__u64 rq_xid;
/** bulk match bits */
__u64 rq_mbits;
+ /** reply match bits */
+ __u64 rq_rep_mbits;
/**
* List item to for replay list. Not yet committed requests get linked
* there.
#define OBD_FAIL_PTLRPC_CONNECT_RACE 0x531
#define OBD_FAIL_NET_ERROR_RPC 0x532
#define OBD_FAIL_PTLRPC_IDLE_RACE 0x533
+#define OBD_FAIL_PTLRPC_ENQ_RESEND 0x534
#define OBD_FAIL_OBD_PING_NET 0x600
/* OBD_FAIL_OBD_LOG_CANCEL_NET 0x601 obsolete since 1.5 */
#define OBD_CONNECT2_GETATTR_PFID 0x20000ULL /* pack parent FID in getattr */
#define OBD_CONNECT2_LSEEK 0x40000ULL /* SEEK_HOLE/DATA RPC */
#define OBD_CONNECT2_DOM_LVB 0x80000ULL /* pack DOM glimpse data in LVB */
+#define OBD_CONNECT2_REP_MBITS 0x100000ULL /* match reply by mbits, not xid */
/* XXX README XXX:
* Please DO NOT add flag values here before first ensuring that this same
* flag value is not in use on some other branch. Please clear any such
OBD_CONNECT2_CRUSH | \
OBD_CONNECT2_ENCRYPT | \
OBD_CONNECT2_GETATTR_PFID |\
- OBD_CONNECT2_LSEEK | OBD_CONNECT2_DOM_LVB)
+ OBD_CONNECT2_LSEEK | OBD_CONNECT2_DOM_LVB |\
+ OBD_CONNECT2_REP_MBITS)
#define OST_CONNECT_SUPPORTED (OBD_CONNECT_SRVLOCK | OBD_CONNECT_GRANT | \
OBD_CONNECT_REQPORTAL | OBD_CONNECT_VERSION | \
OBD_CONNECT_SHORTIO | OBD_CONNECT_FLAGS2)
#define OST_CONNECT_SUPPORTED2 (OBD_CONNECT2_LOCKAHEAD | OBD_CONNECT2_INC_XID |\
- OBD_CONNECT2_ENCRYPT | OBD_CONNECT2_LSEEK)
+ OBD_CONNECT2_ENCRYPT | OBD_CONNECT2_LSEEK |\
+ OBD_CONNECT2_REP_MBITS)
-#define ECHO_CONNECT_SUPPORTED (OBD_CONNECT_FID)
-#define ECHO_CONNECT_SUPPORTED2 0
+#define ECHO_CONNECT_SUPPORTED (OBD_CONNECT_FID | OBD_CONNECT_FLAGS2)
+#define ECHO_CONNECT_SUPPORTED2 OBD_CONNECT2_REP_MBITS
#define MGS_CONNECT_SUPPORTED (OBD_CONNECT_VERSION | OBD_CONNECT_AT | \
OBD_CONNECT_FULL20 | OBD_CONNECT_IMP_RECOV | \
OBD_CONNECT_PINGLESS |\
- OBD_CONNECT_BULK_MBITS | OBD_CONNECT_BARRIER)
+ OBD_CONNECT_BULK_MBITS | OBD_CONNECT_BARRIER | \
+ OBD_CONNECT_FLAGS2)
-#define MGS_CONNECT_SUPPORTED2 0
+#define MGS_CONNECT_SUPPORTED2 OBD_CONNECT2_REP_MBITS
/* Features required for this version of the client to work with server */
#define CLIENT_CONNECT_MDT_REQD (OBD_CONNECT_FID | \
revimp->imp_msghdr_flags |= MSGHDR_CKSUM_INCOMPAT18;
+ revimp->imp_connect_data = *data;
rc = sptlrpc_import_sec_adapt(revimp, req->rq_svc_ctx, &req->rq_flvr);
if (rc) {
CERROR("%s: cannot get reverse import %s security: rc = %d\n",
OBD_CONNECT2_PCC |
OBD_CONNECT2_CRUSH | OBD_CONNECT2_LSEEK |
OBD_CONNECT2_GETATTR_PFID |
- OBD_CONNECT2_DOM_LVB;
+ OBD_CONNECT2_DOM_LVB |
+ OBD_CONNECT2_REP_MBITS;
#ifdef HAVE_LRU_RESIZE_SUPPORT
if (sbi->ll_flags & LL_SBI_LRU_RESIZE)
OBD_CONNECT_BULK_MBITS | OBD_CONNECT_SHORTIO |
OBD_CONNECT_FLAGS2 | OBD_CONNECT_GRANT_SHRINK;
data->ocd_connect_flags2 = OBD_CONNECT2_LOCKAHEAD |
- OBD_CONNECT2_INC_XID | OBD_CONNECT2_LSEEK;
+ OBD_CONNECT2_INC_XID | OBD_CONNECT2_LSEEK |
+ OBD_CONNECT2_REP_MBITS;
if (!OBD_FAIL_CHECK(OBD_FAIL_OSC_CONNECT_GRANT_PARAM))
data->ocd_connect_flags |= OBD_CONNECT_GRANT_PARAM;
PLDLMRES(lock->l_resource),
PFID(mdt_object_fid(child)));
+ if (unlikely(OBD_FAIL_PRECHECK(OBD_FAIL_PTLRPC_ENQ_RESEND))) {
+ if (!(lustre_msg_get_flags(req->rq_reqmsg) & MSG_RESENT))
+ OBD_FAIL_TIMEOUT(OBD_FAIL_PTLRPC_ENQ_RESEND,
+ req->rq_deadline -
+ req->rq_arrival_time.tv_sec +
+ cfs_fail_val ?: 3);
+ /* Put the lock to the waiting list and force the cancel */
+ ldlm_set_ast_sent(lock);
+ }
+
if (S_ISREG(lu_object_attr(&child->mot_obj)) &&
!mdt_object_remote(child) && child != parent) {
mdt_object_put(info->mti_env, child);
if (OBD_FAIL_CHECK(OBD_FAIL_MDS_REINT_LINK))
RETURN(err_serious(-ENOENT));
- if (OBD_FAIL_PRECHECK(OBD_FAIL_PTLRPC_RESEND_RACE)) {
+ if (OBD_FAIL_PRECHECK(OBD_FAIL_PTLRPC_RESEND_RACE) ||
+ OBD_FAIL_PRECHECK(OBD_FAIL_PTLRPC_ENQ_RESEND)) {
req->rq_no_reply = 1;
RETURN(err_serious(-ENOENT));
}
"getattr_pfid", /* 0x20000 */
"lseek", /* 0x40000 */
"dom_lvb", /* 0x80000 */
+ "reply_mbits", /* 0x100000 */
NULL
};
data->ocd_connect_flags = OBD_CONNECT_VERSION | OBD_CONNECT_AT |
OBD_CONNECT_FULL20 | OBD_CONNECT_IMP_RECOV |
OBD_CONNECT_LVB_TYPE |
- OBD_CONNECT_BULK_MBITS | OBD_CONNECT_BARRIER;
+ OBD_CONNECT_BULK_MBITS | OBD_CONNECT_BARRIER |
+ OBD_CONNECT_FLAGS2;
+ data->ocd_connect_flags2 = OBD_CONNECT2_REP_MBITS;
if (lmd_is_client(lsi->lsi_lmd) &&
lsi->lsi_lmd->lmd_flags & LMD_FLG_NOIR)
OBD_CONNECT_BRW_SIZE |
OBD_CONNECT_GRANT | OBD_CONNECT_FULL20 |
OBD_CONNECT_64BITHASH | OBD_CONNECT_LVB_TYPE |
- OBD_CONNECT_FID;
+ OBD_CONNECT_FID | OBD_CONNECT_FLAGS2;
+ ocd->ocd_connect_flags2 = OBD_CONNECT2_REP_MBITS;
+
ocd->ocd_brw_size = DT_MAX_BRW_SIZE;
ocd->ocd_version = LUSTRE_VERSION_CODE;
ocd->ocd_group = FID_SEQ_ECHO;
* request to ensure previous bulk fails and avoid problems with lost replies
* and therefore several transfers landing into the same buffer from different
* sending attempts.
+ * Also, to avoid previous reply landing to a different sending attempt.
*/
-void ptlrpc_set_bulk_mbits(struct ptlrpc_request *req)
+void ptlrpc_set_mbits(struct ptlrpc_request *req)
{
- struct ptlrpc_bulk_desc *bd = req->rq_bulk;
-
- LASSERT(bd != NULL);
+ int md_count = req->rq_bulk ? req->rq_bulk->bd_md_count : 1;
/*
* Generate new matchbits for all resend requests, including
* 'resend for the -EINPROGRESS resend'. To make it simple,
* we opt to generate mbits for all resend cases.
*/
- if (OCD_HAS_FLAG(&bd->bd_import->imp_connect_data,
+ if (OCD_HAS_FLAG(&req->rq_import->imp_connect_data,
BULK_MBITS)) {
req->rq_mbits = ptlrpc_next_xid();
} else {
spin_unlock(&req->rq_import->imp_lock);
req->rq_mbits = req->rq_xid;
}
- CDEBUG(D_HA, "resend bulk old x%llu new x%llu\n",
+ CDEBUG(D_HA, "resend with new mbits old x%llu new x%llu\n",
old_mbits, req->rq_mbits);
} else if (!(lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY)) {
/* Request being sent first time, use xid as matchbits. */
- if (OCD_HAS_FLAG(&bd->bd_import->imp_connect_data, BULK_MBITS)
- || req->rq_mbits == 0) {
+ if (OCD_HAS_FLAG(&req->rq_import->imp_connect_data,
+ BULK_MBITS) || req->rq_mbits == 0)
+ {
req->rq_mbits = req->rq_xid;
} else {
- req->rq_mbits -= bd->bd_md_count - 1;
+ req->rq_mbits -= md_count - 1;
}
} else {
/*
* that server can infer the number of bulks that were prepared,
* see LU-1431
*/
- req->rq_mbits += bd->bd_md_count - 1;
+ req->rq_mbits += md_count - 1;
/*
* Set rq_xid as rq_mbits to indicate the final bulk for the old
* It's ok to directly set the rq_xid here, since this xid bump
* won't affect the request position in unreplied list.
*/
- if (!OCD_HAS_FLAG(&bd->bd_import->imp_connect_data, BULK_MBITS))
+ if (!OCD_HAS_FLAG(&req->rq_import->imp_connect_data, BULK_MBITS))
req->rq_xid = req->rq_mbits;
}
LNET_ACK_REQ : LNET_NOACK_REQ,
&rs->rs_cb_id, req->rq_self, req->rq_source,
ptlrpc_req2svc(req)->srv_rep_portal,
- req->rq_xid, req->rq_reply_off, NULL);
+ req->rq_rep_mbits ? req->rq_rep_mbits : req->rq_xid,
+ req->rq_reply_off, NULL);
out:
if (unlikely(rc != 0))
ptlrpc_req_drop_rs(req);
int ptl_send_rpc(struct ptlrpc_request *request, int noreply)
{
int rc;
+ __u32 opc;
int mpflag = 0;
+ bool rep_mbits = false;
struct lnet_handle_md bulk_cookie;
struct ptlrpc_connection *connection;
struct lnet_me *reply_me = NULL;
"Allocating new XID for resend on EINPROGRESS");
}
- if (request->rq_bulk != NULL) {
- ptlrpc_set_bulk_mbits(request);
+ opc = lustre_msg_get_opc(request->rq_reqmsg);
+ if (opc != OST_CONNECT && opc != MDS_CONNECT &&
+ opc != MGS_CONNECT && OCD_HAS_FLAG(&imp->imp_connect_data, FLAGS2))
+ rep_mbits = imp->imp_connect_data.ocd_connect_flags2 &
+ OBD_CONNECT2_REP_MBITS;
+
+ if ((request->rq_bulk != NULL) || rep_mbits) {
+ ptlrpc_set_mbits(request);
lustre_msg_set_mbits(request->rq_reqmsg, request->rq_mbits);
}
} else {
reply_me = LNetMEAttach(request->rq_reply_portal,
connection->c_peer,
- request->rq_xid, 0,
- LNET_UNLINK, LNET_INS_AFTER);
+ rep_mbits ? request->rq_mbits :
+ request->rq_xid,
+ 0, LNET_UNLINK, LNET_INS_AFTER);
}
if (IS_ERR(reply_me)) {
void ptlrpc_expired_set(struct ptlrpc_request_set *set);
time64_t ptlrpc_set_next_timeout(struct ptlrpc_request_set *);
void ptlrpc_resend_req(struct ptlrpc_request *request);
-void ptlrpc_set_bulk_mbits(struct ptlrpc_request *req);
+void ptlrpc_set_mbits(struct ptlrpc_request *req);
void ptlrpc_assign_next_xid_nolock(struct ptlrpc_request *req);
__u64 ptlrpc_known_replied_xid(struct obd_import *imp);
void ptlrpc_add_unreplied(struct ptlrpc_request *req);
ENTRY;
- if (CFS_FAIL_CHECK(OBD_FAIL_TGT_REPLAY_RECONNECT)) {
+ if (CFS_FAIL_CHECK(OBD_FAIL_TGT_REPLAY_RECONNECT) ||
+ CFS_FAIL_PRECHECK(OBD_FAIL_PTLRPC_ENQ_RESEND)) {
/* don't send early reply */
RETURN(1);
}
ptlrpc_at_remove_timed(orig);
spin_unlock(&orig->rq_rqbd->rqbd_svcpt->scp_at_lock);
orig->rq_deadline = req->rq_deadline;
+ orig->rq_rep_mbits = req->rq_rep_mbits;
if (likely(linked))
ptlrpc_at_add_timed(orig);
ptlrpc_server_drop_request(orig);
struct ptlrpc_service *svc = svcpt->scp_service;
struct ptlrpc_request *req;
__u32 deadline;
+ __u32 opc;
int rc;
ENTRY;
goto err_req;
}
+ opc = lustre_msg_get_opc(req->rq_reqmsg);
if (OBD_FAIL_CHECK(OBD_FAIL_PTLRPC_DROP_REQ_OPC) &&
- lustre_msg_get_opc(req->rq_reqmsg) == cfs_fail_val) {
+ opc == cfs_fail_val) {
CERROR("drop incoming rpc opc %u, x%llu\n",
cfs_fail_val, req->rq_xid);
goto err_req;
goto err_req;
}
- switch (lustre_msg_get_opc(req->rq_reqmsg)) {
+ switch (opc) {
case MDS_WRITEPAGE:
case OST_WRITE:
case OUT_UPDATE:
thread->t_env->le_ses = &req->rq_session;
}
+
+ if (unlikely(OBD_FAIL_PRECHECK(OBD_FAIL_PTLRPC_ENQ_RESEND) &&
+ (opc == LDLM_ENQUEUE) &&
+ (lustre_msg_get_flags(req->rq_reqmsg) & MSG_RESENT)))
+ OBD_FAIL_TIMEOUT(OBD_FAIL_PTLRPC_ENQ_RESEND, 6);
+
ptlrpc_at_add_timed(req);
+ if (opc != OST_CONNECT && opc != MDS_CONNECT &&
+ opc != MGS_CONNECT && req->rq_export != NULL) {
+ if (exp_connect_flags2(req->rq_export) & OBD_CONNECT2_REP_MBITS)
+ req->rq_rep_mbits = lustre_msg_get_mbits(req->rq_reqmsg);
+ }
+
/* Move it over to the request processing queue */
rc = ptlrpc_server_request_add(svcpt, req);
if (rc)
OBD_CONNECT2_LSEEK);
LASSERTF(OBD_CONNECT2_DOM_LVB == 0x80000ULL, "found 0x%.16llxULL\n",
OBD_CONNECT2_DOM_LVB);
+ LASSERTF(OBD_CONNECT2_REP_MBITS == 0x100000ULL, "found 0x%.16llxULL\n",
+ OBD_CONNECT2_REP_MBITS);
LASSERTF(OBD_CKSUM_CRC32 == 0x00000001UL, "found 0x%.8xUL\n",
(unsigned)OBD_CKSUM_CRC32);
LASSERTF(OBD_CKSUM_ADLER == 0x00000002UL, "found 0x%.8xUL\n",
run_test 109 "Race with several mount instances on 1 node"
+test_110() {
+ local before=$(date +%s)
+ local evict
+
+ mkdir -p $DIR/$tdir
+ touch $DIR/$tdir/f1
+ touch $DIR/$tfile
+
+ #define OBD_FAIL_PTLRPC_RESEND_RACE 0x525
+ do_facet mds1 lctl set_param fail_loc=0x525 fail_val=3
+
+ # disable last_xid logic by dropping link reply
+ ln $DIR/$tdir/f1 $DIR/$tdir/f2 &
+ sleep 1
+
+ #define OBD_FAIL_PTLRPC_ENQ_RESEND 0x534
+ do_facet mds1 lctl set_param fail_loc=0x534
+
+ # RPC will race with its Resend and the Resend will sleep to let
+ # the original lock to get granted & cancelled.
+ #
+ # AST_SENT is set artificially, so an explicit conflict is not needed
+ #
+ # The woken up Resend gets a new lock, but client does not wait for it
+ stat $DIR/$tfile
+ sleep $TIMEOUT
+ do_facet mds1 lctl set_param fail_loc=0 fail_val=0
+
+ # Take a conflict to wait long enough to see the eviction
+ touch $DIR2/$tfile
+
+ # let the client reconnect
+ client_reconnect
+ evict=$(do_facet client $LCTL get_param mdc.$FSNAME-MDT*.state |
+ awk -F"[ [,]" '/EVICTED ]$/ { if (mx<$5) {mx=$5;} } END { print mx }')
+
+ [ -z "$evict" ] || [[ $evict -le $before ]] ||
+ (do_facet client $LCTL get_param mdc.$FSNAME-MDT*.state;
+ error "eviction happened: $evict before:$before")
+}
+run_test 110 "do not grant another lock on resend"
+
log "cleanup: ======================================================"
# kill and wait in each test only guarentee script finish, but command in script
CHECK_DEFINE_64X(OBD_CONNECT2_GETATTR_PFID);
CHECK_DEFINE_64X(OBD_CONNECT2_LSEEK);
CHECK_DEFINE_64X(OBD_CONNECT2_DOM_LVB);
+ CHECK_DEFINE_64X(OBD_CONNECT2_REP_MBITS);
CHECK_VALUE_X(OBD_CKSUM_CRC32);
CHECK_VALUE_X(OBD_CKSUM_ADLER);
OBD_CONNECT2_LSEEK);
LASSERTF(OBD_CONNECT2_DOM_LVB == 0x80000ULL, "found 0x%.16llxULL\n",
OBD_CONNECT2_DOM_LVB);
+ LASSERTF(OBD_CONNECT2_REP_MBITS == 0x100000ULL, "found 0x%.16llxULL\n",
+ OBD_CONNECT2_REP_MBITS);
LASSERTF(OBD_CKSUM_CRC32 == 0x00000001UL, "found 0x%.8xUL\n",
(unsigned)OBD_CKSUM_CRC32);
LASSERTF(OBD_CKSUM_ADLER == 0x00000002UL, "found 0x%.8xUL\n",