if ((md->md_options & info->mi_opc) == 0)
return LNET_MATCHMD_NONE;
- /* mismatched ME nid/pid? */
- if (!LNET_NID_IS_ANY(&me->me_match_id.nid) &&
- !nid_same(&me->me_match_id.nid, &info->mi_id.nid))
- return LNET_MATCHMD_NONE;
-
- if (me->me_match_id.pid != LNET_PID_ANY &&
- me->me_match_id.pid != info->mi_id.pid)
- return LNET_MATCHMD_NONE;
-
/* mismatched ME matchbits? */
if (((me->me_match_bits ^ info->mi_mbits) & ~me->me_ignore_bits) != 0)
return LNET_MATCHMD_NONE;
+ /* mismatched ME nid/pid? */
+ if (me->me_match_bits & ~me->me_ignore_bits) {
+ /* try to accept match based on bits only */
+ if ((!LNET_NID_IS_ANY(&me->me_match_id.nid) &&
+ !nid_same(&me->me_match_id.nid, &info->mi_id.nid)) ||
+ CFS_FAIL_CHECK(CFS_FAIL_MATCH_MD_NID)) {
+ struct lnet_peer *lp_me, *lp_peer;
+
+ /* check if ME NID matches another NID of same peer */
+ lp_me = lnet_find_peer(&me->me_match_id.nid);
+ lp_peer = lnet_find_peer(&info->mi_id.nid);
+
+ if (lp_me && lp_peer && (lp_me == lp_peer)) {
+ /* Shouldn't happen, but better than dropping
+ * message entirely. Print warning so we know
+ * it happens, and something needs to be fixed.
+ */
+ CWARN("message from %s matched %llu with NID mismatch %s accepted (same peer %pK)\n",
+ libcfs_idstr(&info->mi_id),
+ info->mi_mbits,
+ libcfs_nidstr(&me->me_match_id.nid),
+ lp_me);
+ lnet_peer_decref_locked(lp_me);
+ lnet_peer_decref_locked(lp_peer);
+ } else {
+ CNETERR("message from %s matched %llu with NID mismatch %s rejected (different peer %pK != %pK)\n",
+ libcfs_idstr(&info->mi_id),
+ info->mi_mbits,
+ libcfs_nidstr(&me->me_match_id.nid),
+ lp_me, lp_peer);
+ if (lp_me)
+ lnet_peer_decref_locked(lp_me);
+ if (lp_peer)
+ lnet_peer_decref_locked(lp_peer);
+
+ return LNET_MATCHMD_NONE;
+ }
+ }
+
+ if (me->me_match_id.pid != LNET_PID_ANY &&
+ me->me_match_id.pid != info->mi_id.pid) {
+ CNETERR("message from %s matched %llu with PID mismatch %s rejected\n",
+ libcfs_idstr(&info->mi_id), info->mi_mbits,
+ libcfs_idstr(&me->me_match_id));
+ return LNET_MATCHMD_NONE;
+ }
+ } else {
+ /* there were no bits to match, reject on nid/pid mismatch */
+ if (!LNET_NID_IS_ANY(&me->me_match_id.nid) &&
+ !nid_same(&me->me_match_id.nid, &info->mi_id.nid))
+ return LNET_MATCHMD_NONE;
+
+ if (me->me_match_id.pid != LNET_PID_ANY &&
+ me->me_match_id.pid != info->mi_id.pid)
+ return LNET_MATCHMD_NONE;
+ }
+
/* Hurrah! This _is_ a match; check it out... */
if ((md->md_options & LNET_MD_MANAGE_REMOTE) == 0)
}
run_test 319 "lost lease lock on migrate error"
+test_350() {
+ local mdts=$(comma_list $(mdts_nodes))
+
+ mkdir $DIR/$tdir || error "mkdir $DIR/$tdir failed"
+ stack_trap "rm -r $DIR/$tdir"
+
+ #force 1/100 of replies to take "NID mismatch" codepath
+ #define CFS_FAIL_MATCH_MD_NID 0xe001 CFS_FAIL_SOME 0x10000000
+ do_nodes $mdts $LCTL set_param fail_loc=0x1000e001 fail_val=100
+
+ while ls -lR $DIR/$tdir > /dev/null; do :; done &
+ stack_trap "killall -9 ls || killall -9 ls"
+
+ cp -a /etc $DIR/$tdir || error "cp failed"
+}
+run_test 350 "force NID mismatch path to be exercised"
+
test_360() {
(( $OST1_VERSION >= $(version_code 2.15.58.96) )) ||
skip "Need OST version at least 2.15.58.96"