Rather than splitting this logic up (hoisting the CInv declaration above the code block, fetching the type inside the cs_main scope, and then putting the rest of the logic outside the cs_main scope), I recommend you keep all the logic together:
 0--- a/src/net_processing.cpp
 1+++ b/src/net_processing.cpp
 2@@ -2872,8 +2872,6 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
 3             return;
 4         }
 5 
 6-        CInv inv;
 7-
 8         {
 9             LOCK(cs_main);
10 
11@@ -2892,17 +2890,18 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
12                 return;
13             }
14 
15-            // If an older block is requested (should never happen in practice,
16-            // but can happen in tests) send a block response instead of a
17-            // blocktxn response. Sending a full block response instead of a
18-            // small blocktxn response is preferable in the case where a peer
19-            // might maliciously send lots of getblocktxn requests to trigger
20-            // expensive disk reads, because it will require the peer to
21-            // actually receive all the data read from disk over the network.
22-            inv.type = State(pfrom.GetId())->fWantsCmpctWitness ? MSG_WITNESS_BLOCK : MSG_BLOCK;
23         }
24 
25+        // If an older block is requested (should never happen in practice,
26+        // but can happen in tests) send a block response instead of a
27+        // blocktxn response. Sending a full block response instead of a
28+        // small blocktxn response is preferable in the case where a peer
29+        // might maliciously send lots of getblocktxn requests to trigger
30+        // expensive disk reads, because it will require the peer to
31+        // actually receive all the data read from disk over the network.
32         LogPrint(BCLog::NET, "Peer %d sent us a getblocktxn for a block > %i deep\n", pfrom.GetId(), MAX_BLOCKTXN_DEPTH);
33+        CInv inv;
34+        inv.type = WITH_LOCK(cs_main, return State(pfrom.GetId())->fWantsCmpctWitness ? MSG_WITNESS_BLOCK : MSG_BLOCK);
35         inv.hash = req.blockhash;
It’s slightly wasteful that cs_main is released and then taken again, but I think it’s ok because:
- As the comment says, we don’t expect this to happen except in tests
- fWantsCmpctWitnessshould move to the- Peerstruct eventually, removing the need to take cs_main