if ((md->md_options & info->mi_opc) == 0)
return LNET_MATCHMD_NONE;
- /* mismatched ME nid/pid? */
- if (me->me_match_id.nid != LNET_NID_ANY &&
- 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 ((me->me_match_id.nid != LNET_NID_ANY &&
+ 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_id2str(info->mi_id),
+ info->mi_mbits,
+ libcfs_nid2str(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 but NID mismatch %s rejected (different peer %pK != %pK)\n",
+ libcfs_id2str(info->mi_id),
+ info->mi_mbits,
+ libcfs_nid2str(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 but PID mismatch %s rejected\n",
+ libcfs_id2str(info->mi_id), info->mi_mbits,
+ libcfs_id2str(me->me_match_id));
+ return LNET_MATCHMD_NONE;
+ }
+ } else {
+ /* there were no bits to match, reject on NID/PID mismatch */
+ if (me->me_match_id.nid != LNET_NID_ANY &&
+ 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.14.0.114) )) ||
skip "Need OST version at least 2.14.0.114"