[v2] drbd: Store op in drbd_peer_request

Message ID 20221020085946.132253-1-christoph.boehmwalder@linbit.com
State New
Headers
Series [v2] drbd: Store op in drbd_peer_request |

Commit Message

Christoph Böhmwalder Oct. 20, 2022, 8:59 a.m. UTC
  (Sort of) cherry-picked from the out-of-tree drbd9 branch. Original
commit message by Joel Colledge:

    This simplifies drbd_submit_peer_request by removing most of the
    arguments. It also makes the treatment of the op better aligned with
    that in struct bio.

    Determine fault_type dynamically using information which is already
    available instead of passing it in as a parameter.

Note: The opf in receive_rs_deallocated was changed from
REQ_OP_WRITE_ZEROES to REQ_OP_DISCARD. This was required in the
out-of-tree module, and does not matter in-tree. The opf is ignored
anyway in drbd_submit_peer_request, since the discard/zero-out is
decided by the EE_TRIM flag.

Signed-off-by: Joel Colledge <joel.colledge@linbit.com>
Signed-off-by: Christoph Böhmwalder <christoph.boehmwalder@linbit.com>
---
Changes in v2:
    - Make opf the correct type
    - Fix compiler warnings
---
 drivers/block/drbd/drbd_int.h      |  8 ++-
 drivers/block/drbd/drbd_receiver.c | 81 +++++++++++++++++-------------
 drivers/block/drbd/drbd_worker.c   |  4 +-
 3 files changed, 53 insertions(+), 40 deletions(-)
  

Comments

kernel test robot Oct. 21, 2022, 12:39 a.m. UTC | #1
Hi Christoph,

I love your patch! Perhaps something to improve:

[auto build test WARNING on axboe-block/for-next]
[also build test WARNING on linus/master v6.1-rc1 next-20221020]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Christoph-B-hmwalder/drbd-Store-op-in-drbd_peer_request/20221020-170145
base:   https://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux-block.git for-next
patch link:    https://lore.kernel.org/r/20221020085946.132253-1-christoph.boehmwalder%40linbit.com
patch subject: [PATCH v2] drbd: Store op in drbd_peer_request
config: parisc-randconfig-s051-20221019
compiler: hppa-linux-gcc (GCC) 12.1.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # apt-get install sparse
        # sparse version: v0.6.4-39-gce1a6720-dirty
        # https://github.com/intel-lab-lkp/linux/commit/60b5915aa524152936deba45d2b2ca55e5f2ac5e
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Christoph-B-hmwalder/drbd-Store-op-in-drbd_peer_request/20221020-170145
        git checkout 60b5915aa524152936deba45d2b2ca55e5f2ac5e
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=parisc SHELL=/bin/bash drivers/block/drbd/

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>

sparse warnings: (new ones prefixed by >>)
   drivers/block/drbd/drbd_receiver.c:5308:27: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:5309:27: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:5318:54: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:5375:14: sparse: sparse: incompatible types in comparison expression (different address spaces):
   drivers/block/drbd/drbd_receiver.c:5375:14: sparse:    struct net_conf [noderef] __rcu *
   drivers/block/drbd/drbd_receiver.c:5375:14: sparse:    struct net_conf *
   drivers/block/drbd/drbd_receiver.c:273:14: sparse: sparse: incompatible types in comparison expression (different address spaces):
   drivers/block/drbd/drbd_receiver.c:273:14: sparse:    struct net_conf [noderef] __rcu *
   drivers/block/drbd/drbd_receiver.c:273:14: sparse:    struct net_conf *
   drivers/block/drbd/drbd_receiver.c:529:29: sparse: sparse: incompatible types in comparison expression (different address spaces):
   drivers/block/drbd/drbd_receiver.c:529:29: sparse:    struct net_conf [noderef] __rcu *
   drivers/block/drbd/drbd_receiver.c:529:29: sparse:    struct net_conf *
   drivers/block/drbd/drbd_receiver.c:601:14: sparse: sparse: incompatible types in comparison expression (different address spaces):
   drivers/block/drbd/drbd_receiver.c:601:14: sparse:    struct net_conf [noderef] __rcu *
   drivers/block/drbd/drbd_receiver.c:601:14: sparse:    struct net_conf *
   drivers/block/drbd/drbd_receiver.c:705:14: sparse: sparse: incompatible types in comparison expression (different address spaces):
   drivers/block/drbd/drbd_receiver.c:705:14: sparse:    struct net_conf [noderef] __rcu *
   drivers/block/drbd/drbd_receiver.c:705:14: sparse:    struct net_conf *
   drivers/block/drbd/drbd_receiver.c:774:14: sparse: sparse: incompatible types in comparison expression (different address spaces):
   drivers/block/drbd/drbd_receiver.c:774:14: sparse:    struct net_conf [noderef] __rcu *
   drivers/block/drbd/drbd_receiver.c:774:14: sparse:    struct net_conf *
   drivers/block/drbd/drbd_receiver.c:1167:27: sparse: sparse: cast to restricted __be16
   drivers/block/drbd/drbd_receiver.c:1168:27: sparse: sparse: cast to restricted __be16
   drivers/block/drbd/drbd_receiver.c:1169:28: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:1173:27: sparse: sparse: cast to restricted __be16
   drivers/block/drbd/drbd_receiver.c:1174:28: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:1179:27: sparse: sparse: cast to restricted __be16
   drivers/block/drbd/drbd_receiver.c:1180:28: sparse: sparse: cast to restricted __be16
   drivers/block/drbd/drbd_receiver.c:822:14: sparse: sparse: incompatible types in comparison expression (different address spaces):
   drivers/block/drbd/drbd_receiver.c:822:14: sparse:    struct net_conf [noderef] __rcu *
   drivers/block/drbd/drbd_receiver.c:822:14: sparse:    struct net_conf *
   drivers/block/drbd/drbd_receiver.c:877:14: sparse: sparse: incompatible types in comparison expression (different address spaces):
   drivers/block/drbd/drbd_receiver.c:877:14: sparse:    struct net_conf [noderef] __rcu *
   drivers/block/drbd/drbd_receiver.c:877:14: sparse:    struct net_conf *
   drivers/block/drbd/drbd_receiver.c:1042:14: sparse: sparse: incompatible types in comparison expression (different address spaces):
   drivers/block/drbd/drbd_receiver.c:1042:14: sparse:    struct net_conf [noderef] __rcu *
   drivers/block/drbd/drbd_receiver.c:1042:14: sparse:    struct net_conf *
   drivers/block/drbd/drbd_receiver.c:1432:14: sparse: sparse: incompatible types in comparison expression (different address spaces):
   drivers/block/drbd/drbd_receiver.c:1432:14: sparse:    struct disk_conf [noderef] __rcu *
   drivers/block/drbd/drbd_receiver.c:1432:14: sparse:    struct disk_conf *
   drivers/block/drbd/drbd_receiver.c:1585:14: sparse: sparse: incompatible types in comparison expression (different address spaces):
   drivers/block/drbd/drbd_receiver.c:1585:14: sparse:    struct disk_conf [noderef] __rcu *
   drivers/block/drbd/drbd_receiver.c:1585:14: sparse:    struct disk_conf *
   drivers/block/drbd/drbd_receiver.c:1878:22: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:1882:22: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:2128:18: sparse: sparse: cast to restricted __be64
   drivers/block/drbd/drbd_receiver.c:2159:18: sparse: sparse: cast to restricted __be64
   drivers/block/drbd/drbd_receiver.c:2373:22: sparse: sparse: incompatible types in comparison expression (different address spaces):
   drivers/block/drbd/drbd_receiver.c:2373:22: sparse:    struct net_conf [noderef] __rcu *
   drivers/block/drbd/drbd_receiver.c:2373:22: sparse:    struct net_conf *
   drivers/block/drbd/drbd_receiver.c:2383:27: sparse: sparse: incompatible types in comparison expression (different address spaces):
   drivers/block/drbd/drbd_receiver.c:2383:27: sparse:    struct net_conf [noderef] __rcu *
   drivers/block/drbd/drbd_receiver.c:2383:27: sparse:    struct net_conf *
>> drivers/block/drbd/drbd_receiver.c:2413:46: sparse: sparse: incorrect type in return expression (different base types) @@     expected unsigned long @@     got restricted blk_opf_t @@
   drivers/block/drbd/drbd_receiver.c:2413:46: sparse:     expected unsigned long
   drivers/block/drbd/drbd_receiver.c:2413:46: sparse:     got restricted blk_opf_t
   drivers/block/drbd/drbd_receiver.c:2559:24: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:2586:18: sparse: sparse: cast to restricted __be64
   drivers/block/drbd/drbd_receiver.c:2597:20: sparse: sparse: cast to restricted __be32
>> drivers/block/drbd/drbd_receiver.c:2598:23: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted blk_opf_t [usertype] opf @@     got unsigned long @@
   drivers/block/drbd/drbd_receiver.c:2598:23: sparse:     expected restricted blk_opf_t [usertype] opf
   drivers/block/drbd/drbd_receiver.c:2598:23: sparse:     got unsigned long
   drivers/block/drbd/drbd_receiver.c:2629:14: sparse: sparse: incompatible types in comparison expression (different address spaces):
   drivers/block/drbd/drbd_receiver.c:2629:14: sparse:    struct net_conf [noderef] __rcu *
   drivers/block/drbd/drbd_receiver.c:2629:14: sparse:    struct net_conf *
   drivers/block/drbd/drbd_receiver.c:2760:22: sparse: sparse: incompatible types in comparison expression (different address spaces):
   drivers/block/drbd/drbd_receiver.c:2760:22: sparse:    struct disk_conf [noderef] __rcu *
   drivers/block/drbd/drbd_receiver.c:2760:22: sparse:    struct disk_conf *
   drivers/block/drbd/drbd_receiver.c:2815:18: sparse: sparse: cast to restricted __be64
   drivers/block/drbd/drbd_receiver.c:2816:18: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:3023:23: sparse: sparse: incompatible types in comparison expression (different address spaces):
   drivers/block/drbd/drbd_receiver.c:3023:23: sparse:    struct net_conf [noderef] __rcu *
   drivers/block/drbd/drbd_receiver.c:3023:23: sparse:    struct net_conf *
   drivers/block/drbd/drbd_receiver.c:3099:23: sparse: sparse: incompatible types in comparison expression (different address spaces):
   drivers/block/drbd/drbd_receiver.c:3099:23: sparse:    struct net_conf [noderef] __rcu *
   drivers/block/drbd/drbd_receiver.c:3099:23: sparse:    struct net_conf *
   drivers/block/drbd/drbd_receiver.c:3156:23: sparse: sparse: incompatible types in comparison expression (different address spaces):
   drivers/block/drbd/drbd_receiver.c:3156:23: sparse:    struct net_conf [noderef] __rcu *
   drivers/block/drbd/drbd_receiver.c:3156:23: sparse:    struct net_conf *
   drivers/block/drbd/drbd_receiver.c:3502:14: sparse: sparse: incompatible types in comparison expression (different address spaces):
   drivers/block/drbd/drbd_receiver.c:3502:14: sparse:    struct net_conf [noderef] __rcu *
   drivers/block/drbd/drbd_receiver.c:3502:14: sparse:    struct net_conf *
   drivers/block/drbd/drbd_receiver.c:3634:27: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:3635:27: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:3636:27: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:3637:27: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:3638:27: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:3639:27: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:3660:22: sparse: sparse: incompatible types in comparison expression (different address spaces):
   drivers/block/drbd/drbd_receiver.c:3660:22: sparse:    struct net_conf [noderef] __rcu *
   drivers/block/drbd/drbd_receiver.c:3660:22: sparse:    struct net_conf *
   drivers/block/drbd/drbd_receiver.c:3744:9: sparse: sparse: incompatible types in comparison expression (different address spaces):
   drivers/block/drbd/drbd_receiver.c:3744:9: sparse:    struct net_conf [noderef] __rcu *
   drivers/block/drbd/drbd_receiver.c:3744:9: sparse:    struct net_conf *
   drivers/block/drbd/drbd_receiver.c:3901:46: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:3959:55: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:3960:57: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:3961:56: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:3962:53: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:3996:25: sparse: sparse: incompatible types in comparison expression (different address spaces):
   drivers/block/drbd/drbd_receiver.c:3996:25: sparse:    struct net_conf [noderef] __rcu *
   drivers/block/drbd/drbd_receiver.c:3996:25: sparse:    struct net_conf *
   drivers/block/drbd/drbd_receiver.c:4001:17: sparse: sparse: incompatible types in comparison expression (different address spaces):
   drivers/block/drbd/drbd_receiver.c:4001:17: sparse:    struct disk_conf [noderef] __rcu *
   drivers/block/drbd/drbd_receiver.c:4001:17: sparse:    struct disk_conf *
   drivers/block/drbd/drbd_receiver.c:4007:17: sparse: sparse: incompatible types in comparison expression (different address spaces):
   drivers/block/drbd/drbd_receiver.c:4007:17: sparse:    struct fifo_buffer [noderef] __rcu *
   drivers/block/drbd/drbd_receiver.c:4007:17: sparse:    struct fifo_buffer *
   drivers/block/drbd/drbd_receiver.c:4074:18: sparse: sparse: cast to restricted __be64
   drivers/block/drbd/drbd_receiver.c:4075:19: sparse: sparse: cast to restricted __be64
   drivers/block/drbd/drbd_receiver.c:4076:19: sparse: sparse: cast to restricted __be64
   drivers/block/drbd/drbd_receiver.c:4084:28: sparse: sparse: incompatible types in comparison expression (different address spaces):
   drivers/block/drbd/drbd_receiver.c:4084:28: sparse:    struct disk_conf [noderef] __rcu *
   drivers/block/drbd/drbd_receiver.c:4084:28: sparse:    struct disk_conf *
   drivers/block/drbd/drbd_receiver.c:4125:25: sparse: sparse: incompatible types in comparison expression (different address spaces):
   drivers/block/drbd/drbd_receiver.c:4125:25: sparse:    struct disk_conf [noderef] __rcu *
   drivers/block/drbd/drbd_receiver.c:4125:25: sparse:    struct disk_conf *
   drivers/block/drbd/drbd_receiver.c:4245:29: sparse: sparse: cast to restricted __be64
   drivers/block/drbd/drbd_receiver.c:4345:18: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:4346:17: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:4371:18: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:4372:17: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:4404:24: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:4608:52: sparse: sparse: cast to restricted __be64
   drivers/block/drbd/drbd_receiver.c:4935:9: sparse: sparse: cast to restricted __be64
   drivers/block/drbd/drbd_receiver.c:4935:9: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:4953:18: sparse: sparse: cast to restricted __be64
   drivers/block/drbd/drbd_receiver.c:4954:16: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:5262:25: sparse: sparse: incorrect type in assignment (different base types) @@     expected unsigned int [usertype] protocol_min @@     got restricted __be32 [usertype] @@
   drivers/block/drbd/drbd_receiver.c:5263:25: sparse: sparse: incorrect type in assignment (different base types) @@     expected unsigned int [usertype] protocol_max @@     got restricted __be32 [usertype] @@
   drivers/block/drbd/drbd_receiver.c:5264:26: sparse: sparse: incorrect type in assignment (different base types) @@     expected unsigned int [usertype] feature_flags @@     got restricted __be32 [usertype] @@
   drivers/block/drbd/drbd_receiver.c:5570:23: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:5589:23: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:5634:27: sparse: sparse: cast to restricted __be64
   drivers/block/drbd/drbd_receiver.c:5635:23: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:5644:38: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:5686:27: sparse: sparse: cast to restricted __be64
   drivers/block/drbd/drbd_receiver.c:5687:23: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:5695:38: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:5732:27: sparse: sparse: cast to restricted __be64
   drivers/block/drbd/drbd_receiver.c:5733:20: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:5741:38: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:5768:27: sparse: sparse: cast to restricted __be64
   drivers/block/drbd/drbd_receiver.c:5775:38: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:5777:9: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:5777:9: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:5777:9: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:5777:9: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:5798:18: sparse: sparse: cast to restricted __be64
   drivers/block/drbd/drbd_receiver.c:5799:16: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:5801:38: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:5828:44: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:5860:18: sparse: sparse: cast to restricted __be64
   drivers/block/drbd/drbd_receiver.c:5861:16: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:5863:38: sparse: sparse: cast to restricted __be32
   drivers/block/drbd/drbd_receiver.c:5865:13: sparse: sparse: cast to restricted __be64
   drivers/block/drbd/drbd_receiver.c:5914:14: sparse: sparse: incompatible types in comparison expression (different address spaces):
   drivers/block/drbd/drbd_receiver.c:5914:14: sparse:    struct net_conf [noderef] __rcu *
   drivers/block/drbd/drbd_receiver.c:5914:14: sparse:    struct net_conf *
   drivers/block/drbd/drbd_receiver.c:6004:37: sparse: sparse: incompatible types in comparison expression (different address spaces):

vim +2413 drivers/block/drbd/drbd_receiver.c

  2407	
  2408	/* see also bio_flags_to_wire() */
  2409	static unsigned long wire_flags_to_bio(struct drbd_connection *connection, u32 dpf)
  2410	{
  2411		return wire_flags_to_bio_op(dpf) |
  2412			(dpf & DP_RW_SYNC ? REQ_SYNC : 0) |
> 2413			(dpf & DP_FUA ? REQ_FUA : 0) |
  2414			(dpf & DP_FLUSH ? REQ_PREFLUSH : 0);
  2415	}
  2416	
  2417	static void fail_postponed_requests(struct drbd_device *device, sector_t sector,
  2418					    unsigned int size)
  2419	{
  2420		struct drbd_interval *i;
  2421	
  2422	    repeat:
  2423		drbd_for_each_overlap(i, &device->write_requests, sector, size) {
  2424			struct drbd_request *req;
  2425			struct bio_and_error m;
  2426	
  2427			if (!i->local)
  2428				continue;
  2429			req = container_of(i, struct drbd_request, i);
  2430			if (!(req->rq_state & RQ_POSTPONED))
  2431				continue;
  2432			req->rq_state &= ~RQ_POSTPONED;
  2433			__req_mod(req, NEG_ACKED, &m);
  2434			spin_unlock_irq(&device->resource->req_lock);
  2435			if (m.bio)
  2436				complete_master_bio(device, &m);
  2437			spin_lock_irq(&device->resource->req_lock);
  2438			goto repeat;
  2439		}
  2440	}
  2441	
  2442	static int handle_write_conflicts(struct drbd_device *device,
  2443					  struct drbd_peer_request *peer_req)
  2444	{
  2445		struct drbd_connection *connection = peer_req->peer_device->connection;
  2446		bool resolve_conflicts = test_bit(RESOLVE_CONFLICTS, &connection->flags);
  2447		sector_t sector = peer_req->i.sector;
  2448		const unsigned int size = peer_req->i.size;
  2449		struct drbd_interval *i;
  2450		bool equal;
  2451		int err;
  2452	
  2453		/*
  2454		 * Inserting the peer request into the write_requests tree will prevent
  2455		 * new conflicting local requests from being added.
  2456		 */
  2457		drbd_insert_interval(&device->write_requests, &peer_req->i);
  2458	
  2459	    repeat:
  2460		drbd_for_each_overlap(i, &device->write_requests, sector, size) {
  2461			if (i == &peer_req->i)
  2462				continue;
  2463			if (i->completed)
  2464				continue;
  2465	
  2466			if (!i->local) {
  2467				/*
  2468				 * Our peer has sent a conflicting remote request; this
  2469				 * should not happen in a two-node setup.  Wait for the
  2470				 * earlier peer request to complete.
  2471				 */
  2472				err = drbd_wait_misc(device, i);
  2473				if (err)
  2474					goto out;
  2475				goto repeat;
  2476			}
  2477	
  2478			equal = i->sector == sector && i->size == size;
  2479			if (resolve_conflicts) {
  2480				/*
  2481				 * If the peer request is fully contained within the
  2482				 * overlapping request, it can be considered overwritten
  2483				 * and thus superseded; otherwise, it will be retried
  2484				 * once all overlapping requests have completed.
  2485				 */
  2486				bool superseded = i->sector <= sector && i->sector +
  2487					       (i->size >> 9) >= sector + (size >> 9);
  2488	
  2489				if (!equal)
  2490					drbd_alert(device, "Concurrent writes detected: "
  2491						       "local=%llus +%u, remote=%llus +%u, "
  2492						       "assuming %s came first\n",
  2493						  (unsigned long long)i->sector, i->size,
  2494						  (unsigned long long)sector, size,
  2495						  superseded ? "local" : "remote");
  2496	
  2497				peer_req->w.cb = superseded ? e_send_superseded :
  2498							   e_send_retry_write;
  2499				list_add_tail(&peer_req->w.list, &device->done_ee);
  2500				queue_work(connection->ack_sender, &peer_req->peer_device->send_acks_work);
  2501	
  2502				err = -ENOENT;
  2503				goto out;
  2504			} else {
  2505				struct drbd_request *req =
  2506					container_of(i, struct drbd_request, i);
  2507	
  2508				if (!equal)
  2509					drbd_alert(device, "Concurrent writes detected: "
  2510						       "local=%llus +%u, remote=%llus +%u\n",
  2511						  (unsigned long long)i->sector, i->size,
  2512						  (unsigned long long)sector, size);
  2513	
  2514				if (req->rq_state & RQ_LOCAL_PENDING ||
  2515				    !(req->rq_state & RQ_POSTPONED)) {
  2516					/*
  2517					 * Wait for the node with the discard flag to
  2518					 * decide if this request has been superseded
  2519					 * or needs to be retried.
  2520					 * Requests that have been superseded will
  2521					 * disappear from the write_requests tree.
  2522					 *
  2523					 * In addition, wait for the conflicting
  2524					 * request to finish locally before submitting
  2525					 * the conflicting peer request.
  2526					 */
  2527					err = drbd_wait_misc(device, &req->i);
  2528					if (err) {
  2529						_conn_request_state(connection, NS(conn, C_TIMEOUT), CS_HARD);
  2530						fail_postponed_requests(device, sector, size);
  2531						goto out;
  2532					}
  2533					goto repeat;
  2534				}
  2535				/*
  2536				 * Remember to restart the conflicting requests after
  2537				 * the new peer request has completed.
  2538				 */
  2539				peer_req->flags |= EE_RESTART_REQUESTS;
  2540			}
  2541		}
  2542		err = 0;
  2543	
  2544	    out:
  2545		if (err)
  2546			drbd_remove_epoch_entry_interval(device, peer_req);
  2547		return err;
  2548	}
  2549	
  2550	/* mirrored write */
  2551	static int receive_Data(struct drbd_connection *connection, struct packet_info *pi)
  2552	{
  2553		struct drbd_peer_device *peer_device;
  2554		struct drbd_device *device;
  2555		struct net_conf *nc;
  2556		sector_t sector;
  2557		struct drbd_peer_request *peer_req;
  2558		struct p_data *p = pi->data;
  2559		u32 peer_seq = be32_to_cpu(p->seq_num);
  2560		u32 dp_flags;
  2561		int err, tp;
  2562	
  2563		peer_device = conn_peer_device(connection, pi->vnr);
  2564		if (!peer_device)
  2565			return -EIO;
  2566		device = peer_device->device;
  2567	
  2568		if (!get_ldev(device)) {
  2569			int err2;
  2570	
  2571			err = wait_for_and_update_peer_seq(peer_device, peer_seq);
  2572			drbd_send_ack_dp(peer_device, P_NEG_ACK, p, pi->size);
  2573			atomic_inc(&connection->current_epoch->epoch_size);
  2574			err2 = drbd_drain_block(peer_device, pi->size);
  2575			if (!err)
  2576				err = err2;
  2577			return err;
  2578		}
  2579	
  2580		/*
  2581		 * Corresponding put_ldev done either below (on various errors), or in
  2582		 * drbd_peer_request_endio, if we successfully submit the data at the
  2583		 * end of this function.
  2584		 */
  2585	
  2586		sector = be64_to_cpu(p->sector);
  2587		peer_req = read_in_block(peer_device, p->block_id, sector, pi);
  2588		if (!peer_req) {
  2589			put_ldev(device);
  2590			return -EIO;
  2591		}
  2592	
  2593		peer_req->w.cb = e_end_block;
  2594		peer_req->submit_jif = jiffies;
  2595		peer_req->flags |= EE_APPLICATION;
  2596	
  2597		dp_flags = be32_to_cpu(p->dp_flags);
> 2598		peer_req->opf = wire_flags_to_bio(connection, dp_flags);
  2599		if (pi->cmd == P_TRIM) {
  2600			D_ASSERT(peer_device, peer_req->i.size > 0);
  2601			D_ASSERT(peer_device, peer_req_op(peer_req) == REQ_OP_DISCARD);
  2602			D_ASSERT(peer_device, peer_req->pages == NULL);
  2603			/* need to play safe: an older DRBD sender
  2604			 * may mean zero-out while sending P_TRIM. */
  2605			if (0 == (connection->agreed_features & DRBD_FF_WZEROES))
  2606				peer_req->flags |= EE_ZEROOUT;
  2607		} else if (pi->cmd == P_ZEROES) {
  2608			D_ASSERT(peer_device, peer_req->i.size > 0);
  2609			D_ASSERT(peer_device, peer_req_op(peer_req) == REQ_OP_WRITE_ZEROES);
  2610			D_ASSERT(peer_device, peer_req->pages == NULL);
  2611			/* Do (not) pass down BLKDEV_ZERO_NOUNMAP? */
  2612			if (dp_flags & DP_DISCARD)
  2613				peer_req->flags |= EE_TRIM;
  2614		} else if (peer_req->pages == NULL) {
  2615			D_ASSERT(device, peer_req->i.size == 0);
  2616			D_ASSERT(device, dp_flags & DP_FLUSH);
  2617		}
  2618	
  2619		if (dp_flags & DP_MAY_SET_IN_SYNC)
  2620			peer_req->flags |= EE_MAY_SET_IN_SYNC;
  2621	
  2622		spin_lock(&connection->epoch_lock);
  2623		peer_req->epoch = connection->current_epoch;
  2624		atomic_inc(&peer_req->epoch->epoch_size);
  2625		atomic_inc(&peer_req->epoch->active);
  2626		spin_unlock(&connection->epoch_lock);
  2627	
  2628		rcu_read_lock();
  2629		nc = rcu_dereference(peer_device->connection->net_conf);
  2630		tp = nc->two_primaries;
  2631		if (peer_device->connection->agreed_pro_version < 100) {
  2632			switch (nc->wire_protocol) {
  2633			case DRBD_PROT_C:
  2634				dp_flags |= DP_SEND_WRITE_ACK;
  2635				break;
  2636			case DRBD_PROT_B:
  2637				dp_flags |= DP_SEND_RECEIVE_ACK;
  2638				break;
  2639			}
  2640		}
  2641		rcu_read_unlock();
  2642	
  2643		if (dp_flags & DP_SEND_WRITE_ACK) {
  2644			peer_req->flags |= EE_SEND_WRITE_ACK;
  2645			inc_unacked(device);
  2646			/* corresponding dec_unacked() in e_end_block()
  2647			 * respective _drbd_clear_done_ee */
  2648		}
  2649	
  2650		if (dp_flags & DP_SEND_RECEIVE_ACK) {
  2651			/* I really don't like it that the receiver thread
  2652			 * sends on the msock, but anyways */
  2653			drbd_send_ack(peer_device, P_RECV_ACK, peer_req);
  2654		}
  2655	
  2656		if (tp) {
  2657			/* two primaries implies protocol C */
  2658			D_ASSERT(device, dp_flags & DP_SEND_WRITE_ACK);
  2659			peer_req->flags |= EE_IN_INTERVAL_TREE;
  2660			err = wait_for_and_update_peer_seq(peer_device, peer_seq);
  2661			if (err)
  2662				goto out_interrupted;
  2663			spin_lock_irq(&device->resource->req_lock);
  2664			err = handle_write_conflicts(device, peer_req);
  2665			if (err) {
  2666				spin_unlock_irq(&device->resource->req_lock);
  2667				if (err == -ENOENT) {
  2668					put_ldev(device);
  2669					return 0;
  2670				}
  2671				goto out_interrupted;
  2672			}
  2673		} else {
  2674			update_peer_seq(peer_device, peer_seq);
  2675			spin_lock_irq(&device->resource->req_lock);
  2676		}
  2677		/* TRIM and is processed synchronously,
  2678		 * we wait for all pending requests, respectively wait for
  2679		 * active_ee to become empty in drbd_submit_peer_request();
  2680		 * better not add ourselves here. */
  2681		if ((peer_req->flags & (EE_TRIM | EE_ZEROOUT)) == 0)
  2682			list_add_tail(&peer_req->w.list, &device->active_ee);
  2683		spin_unlock_irq(&device->resource->req_lock);
  2684	
  2685		if (device->state.conn == C_SYNC_TARGET)
  2686			wait_event(device->ee_wait, !overlapping_resync_write(device, peer_req));
  2687	
  2688		if (device->state.pdsk < D_INCONSISTENT) {
  2689			/* In case we have the only disk of the cluster, */
  2690			drbd_set_out_of_sync(device, peer_req->i.sector, peer_req->i.size);
  2691			peer_req->flags &= ~EE_MAY_SET_IN_SYNC;
  2692			drbd_al_begin_io(device, &peer_req->i);
  2693			peer_req->flags |= EE_CALL_AL_COMPLETE_IO;
  2694		}
  2695	
  2696		err = drbd_submit_peer_request(peer_req);
  2697		if (!err)
  2698			return 0;
  2699	
  2700		/* don't care for the reason here */
  2701		drbd_err(device, "submit failed, triggering re-connect\n");
  2702		spin_lock_irq(&device->resource->req_lock);
  2703		list_del(&peer_req->w.list);
  2704		drbd_remove_epoch_entry_interval(device, peer_req);
  2705		spin_unlock_irq(&device->resource->req_lock);
  2706		if (peer_req->flags & EE_CALL_AL_COMPLETE_IO) {
  2707			peer_req->flags &= ~EE_CALL_AL_COMPLETE_IO;
  2708			drbd_al_complete_io(device, &peer_req->i);
  2709		}
  2710	
  2711	out_interrupted:
  2712		drbd_may_finish_epoch(connection, peer_req->epoch, EV_PUT | EV_CLEANUP);
  2713		put_ldev(device);
  2714		drbd_free_peer_req(device, peer_req);
  2715		return err;
  2716	}
  2717
  

Patch

diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index 4d661282ff41..6ab96fb2983f 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -395,6 +395,7 @@  struct drbd_peer_request {
 	struct drbd_peer_device *peer_device;
 	struct drbd_epoch *epoch; /* for writes */
 	struct page *pages;
+	blk_opf_t opf;
 	atomic_t pending_bios;
 	struct drbd_interval i;
 	/* see comments on ee flag bits below */
@@ -406,6 +407,10 @@  struct drbd_peer_request {
 	};
 };
 
+/* Equivalent to bio_op and req_op. */
+#define peer_req_op(peer_req) \
+       ((peer_req)->opf & REQ_OP_MASK)
+
 /* ee flag bits.
  * While corresponding bios are in flight, the only modification will be
  * set_bit WAS_ERROR, which has to be atomic.
@@ -1545,8 +1550,7 @@  extern void drbd_send_acks_wf(struct work_struct *ws);
 extern bool drbd_rs_c_min_rate_throttle(struct drbd_device *device);
 extern bool drbd_rs_should_slow_down(struct drbd_device *device, sector_t sector,
 		bool throttle_if_app_is_waiting);
-extern int drbd_submit_peer_request(struct drbd_device *,
-				    struct drbd_peer_request *, blk_opf_t, int);
+extern int drbd_submit_peer_request(struct drbd_peer_request *);
 extern int drbd_free_peer_reqs(struct drbd_device *, struct list_head *);
 extern struct drbd_peer_request *drbd_alloc_peer_req(struct drbd_peer_device *, u64,
 						     sector_t, unsigned int,
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index c897c4572036..af52a3ae37c1 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -1603,9 +1603,19 @@  static void drbd_issue_peer_discard_or_zero_out(struct drbd_device *device, stru
 	drbd_endio_write_sec_final(peer_req);
 }
 
+static int peer_request_fault_type(struct drbd_peer_request *peer_req)
+{
+	if (peer_req_op(peer_req) == REQ_OP_READ) {
+		return peer_req->flags & EE_APPLICATION ?
+			DRBD_FAULT_DT_RD : DRBD_FAULT_RS_RD;
+	} else {
+		return peer_req->flags & EE_APPLICATION ?
+			DRBD_FAULT_DT_WR : DRBD_FAULT_RS_WR;
+	}
+}
+
 /**
  * drbd_submit_peer_request()
- * @device:	DRBD device.
  * @peer_req:	peer request
  *
  * May spread the pages to multiple bios,
@@ -1619,10 +1629,9 @@  static void drbd_issue_peer_discard_or_zero_out(struct drbd_device *device, stru
  *  on certain Xen deployments.
  */
 /* TODO allocate from our own bio_set. */
-int drbd_submit_peer_request(struct drbd_device *device,
-			     struct drbd_peer_request *peer_req,
-			     const blk_opf_t opf, const int fault_type)
+int drbd_submit_peer_request(struct drbd_peer_request *peer_req)
 {
+	struct drbd_device *device = peer_req->peer_device->device;
 	struct bio *bios = NULL;
 	struct bio *bio;
 	struct page *page = peer_req->pages;
@@ -1667,7 +1676,18 @@  int drbd_submit_peer_request(struct drbd_device *device,
 	 * generated bio, but a bio allocated on behalf of the peer.
 	 */
 next_bio:
-	bio = bio_alloc(device->ldev->backing_bdev, nr_pages, opf, GFP_NOIO);
+	/* _DISCARD, _WRITE_ZEROES handled above.
+	 * REQ_OP_FLUSH (empty flush) not expected,
+	 * should have been mapped to a "drbd protocol barrier".
+	 * REQ_OP_SECURE_ERASE: I don't see how we could ever support that.
+	 */
+	if (!(peer_req_op(peer_req) == REQ_OP_WRITE ||
+				peer_req_op(peer_req) == REQ_OP_READ)) {
+		drbd_err(device, "Invalid bio op received: 0x%x\n", peer_req->opf);
+		return -EINVAL;
+	}
+
+	bio = bio_alloc(device->ldev->backing_bdev, nr_pages, peer_req->opf, GFP_NOIO);
 	/* > peer_req->i.sector, unless this is the first bio */
 	bio->bi_iter.bi_sector = sector;
 	bio->bi_private = peer_req;
@@ -1697,7 +1717,7 @@  int drbd_submit_peer_request(struct drbd_device *device,
 		bios = bios->bi_next;
 		bio->bi_next = NULL;
 
-		drbd_submit_bio_noacct(device, fault_type, bio);
+		drbd_submit_bio_noacct(device, peer_request_fault_type(peer_req), bio);
 	} while (bios);
 	return 0;
 }
@@ -2051,6 +2071,7 @@  static int recv_resync_read(struct drbd_peer_device *peer_device, sector_t secto
 	 * respective _drbd_clear_done_ee */
 
 	peer_req->w.cb = e_end_resync_block;
+	peer_req->opf = REQ_OP_WRITE;
 	peer_req->submit_jif = jiffies;
 
 	spin_lock_irq(&device->resource->req_lock);
@@ -2058,8 +2079,7 @@  static int recv_resync_read(struct drbd_peer_device *peer_device, sector_t secto
 	spin_unlock_irq(&device->resource->req_lock);
 
 	atomic_add(pi->size >> 9, &device->rs_sect_ev);
-	if (drbd_submit_peer_request(device, peer_req, REQ_OP_WRITE,
-				     DRBD_FAULT_RS_WR) == 0)
+	if (drbd_submit_peer_request(peer_req) == 0)
 		return 0;
 
 	/* don't care for the reason here */
@@ -2375,16 +2395,6 @@  static int wait_for_and_update_peer_seq(struct drbd_peer_device *peer_device, co
 	return ret;
 }
 
-/* see also bio_flags_to_wire()
- * DRBD_REQ_*, because we need to semantically map the flags to data packet
- * flags and back. We may replicate to other kernel versions. */
-static blk_opf_t wire_flags_to_bio_flags(u32 dpf)
-{
-	return  (dpf & DP_RW_SYNC ? REQ_SYNC : 0) |
-		(dpf & DP_FUA ? REQ_FUA : 0) |
-		(dpf & DP_FLUSH ? REQ_PREFLUSH : 0);
-}
-
 static enum req_op wire_flags_to_bio_op(u32 dpf)
 {
 	if (dpf & DP_ZEROES)
@@ -2395,6 +2405,15 @@  static enum req_op wire_flags_to_bio_op(u32 dpf)
 		return REQ_OP_WRITE;
 }
 
+/* see also bio_flags_to_wire() */
+static unsigned long wire_flags_to_bio(struct drbd_connection *connection, u32 dpf)
+{
+	return wire_flags_to_bio_op(dpf) |
+		(dpf & DP_RW_SYNC ? REQ_SYNC : 0) |
+		(dpf & DP_FUA ? REQ_FUA : 0) |
+		(dpf & DP_FLUSH ? REQ_PREFLUSH : 0);
+}
+
 static void fail_postponed_requests(struct drbd_device *device, sector_t sector,
 				    unsigned int size)
 {
@@ -2538,8 +2557,6 @@  static int receive_Data(struct drbd_connection *connection, struct packet_info *
 	struct drbd_peer_request *peer_req;
 	struct p_data *p = pi->data;
 	u32 peer_seq = be32_to_cpu(p->seq_num);
-	enum req_op op;
-	blk_opf_t op_flags;
 	u32 dp_flags;
 	int err, tp;
 
@@ -2578,11 +2595,10 @@  static int receive_Data(struct drbd_connection *connection, struct packet_info *
 	peer_req->flags |= EE_APPLICATION;
 
 	dp_flags = be32_to_cpu(p->dp_flags);
-	op = wire_flags_to_bio_op(dp_flags);
-	op_flags = wire_flags_to_bio_flags(dp_flags);
+	peer_req->opf = wire_flags_to_bio(connection, dp_flags);
 	if (pi->cmd == P_TRIM) {
 		D_ASSERT(peer_device, peer_req->i.size > 0);
-		D_ASSERT(peer_device, op == REQ_OP_DISCARD);
+		D_ASSERT(peer_device, peer_req_op(peer_req) == REQ_OP_DISCARD);
 		D_ASSERT(peer_device, peer_req->pages == NULL);
 		/* need to play safe: an older DRBD sender
 		 * may mean zero-out while sending P_TRIM. */
@@ -2590,7 +2606,7 @@  static int receive_Data(struct drbd_connection *connection, struct packet_info *
 			peer_req->flags |= EE_ZEROOUT;
 	} else if (pi->cmd == P_ZEROES) {
 		D_ASSERT(peer_device, peer_req->i.size > 0);
-		D_ASSERT(peer_device, op == REQ_OP_WRITE_ZEROES);
+		D_ASSERT(peer_device, peer_req_op(peer_req) == REQ_OP_WRITE_ZEROES);
 		D_ASSERT(peer_device, peer_req->pages == NULL);
 		/* Do (not) pass down BLKDEV_ZERO_NOUNMAP? */
 		if (dp_flags & DP_DISCARD)
@@ -2677,8 +2693,7 @@  static int receive_Data(struct drbd_connection *connection, struct packet_info *
 		peer_req->flags |= EE_CALL_AL_COMPLETE_IO;
 	}
 
-	err = drbd_submit_peer_request(device, peer_req, op | op_flags,
-				       DRBD_FAULT_DT_WR);
+	err = drbd_submit_peer_request(peer_req);
 	if (!err)
 		return 0;
 
@@ -2789,7 +2804,6 @@  static int receive_DataRequest(struct drbd_connection *connection, struct packet
 	struct drbd_peer_request *peer_req;
 	struct digest_info *di = NULL;
 	int size, verb;
-	unsigned int fault_type;
 	struct p_block_req *p =	pi->data;
 
 	peer_device = conn_peer_device(connection, pi->vnr);
@@ -2849,11 +2863,11 @@  static int receive_DataRequest(struct drbd_connection *connection, struct packet
 		put_ldev(device);
 		return -ENOMEM;
 	}
+	peer_req->opf = REQ_OP_READ;
 
 	switch (pi->cmd) {
 	case P_DATA_REQUEST:
 		peer_req->w.cb = w_e_end_data_req;
-		fault_type = DRBD_FAULT_DT_RD;
 		/* application IO, don't drbd_rs_begin_io */
 		peer_req->flags |= EE_APPLICATION;
 		goto submit;
@@ -2867,14 +2881,12 @@  static int receive_DataRequest(struct drbd_connection *connection, struct packet
 		fallthrough;
 	case P_RS_DATA_REQUEST:
 		peer_req->w.cb = w_e_end_rsdata_req;
-		fault_type = DRBD_FAULT_RS_RD;
 		/* used in the sector offset progress display */
 		device->bm_resync_fo = BM_SECT_TO_BIT(sector);
 		break;
 
 	case P_OV_REPLY:
 	case P_CSUM_RS_REQUEST:
-		fault_type = DRBD_FAULT_RS_RD;
 		di = kmalloc(sizeof(*di) + pi->size, GFP_NOIO);
 		if (!di)
 			goto out_free_e;
@@ -2923,7 +2935,6 @@  static int receive_DataRequest(struct drbd_connection *connection, struct packet
 					(unsigned long long)sector);
 		}
 		peer_req->w.cb = w_e_end_ov_req;
-		fault_type = DRBD_FAULT_RS_RD;
 		break;
 
 	default:
@@ -2975,8 +2986,7 @@  static int receive_DataRequest(struct drbd_connection *connection, struct packet
 submit:
 	update_receiver_timing_details(connection, drbd_submit_peer_request);
 	inc_unacked(device);
-	if (drbd_submit_peer_request(device, peer_req, REQ_OP_READ,
-				     fault_type) == 0)
+	if (drbd_submit_peer_request(peer_req) == 0)
 		return 0;
 
 	/* don't care for the reason here */
@@ -4947,7 +4957,6 @@  static int receive_rs_deallocated(struct drbd_connection *connection, struct pac
 
 	if (get_ldev(device)) {
 		struct drbd_peer_request *peer_req;
-		const enum req_op op = REQ_OP_WRITE_ZEROES;
 
 		peer_req = drbd_alloc_peer_req(peer_device, ID_SYNCER, sector,
 					       size, 0, GFP_NOIO);
@@ -4957,6 +4966,7 @@  static int receive_rs_deallocated(struct drbd_connection *connection, struct pac
 		}
 
 		peer_req->w.cb = e_end_resync_block;
+		peer_req->opf = REQ_OP_DISCARD;
 		peer_req->submit_jif = jiffies;
 		peer_req->flags |= EE_TRIM;
 
@@ -4965,8 +4975,7 @@  static int receive_rs_deallocated(struct drbd_connection *connection, struct pac
 		spin_unlock_irq(&device->resource->req_lock);
 
 		atomic_add(pi->size >> 9, &device->rs_sect_ev);
-		err = drbd_submit_peer_request(device, peer_req, op,
-					       DRBD_FAULT_RS_WR);
+		err = drbd_submit_peer_request(peer_req);
 
 		if (err) {
 			spin_lock_irq(&device->resource->req_lock);
diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c
index 0bb1a900c2d5..c69beefc9d5c 100644
--- a/drivers/block/drbd/drbd_worker.c
+++ b/drivers/block/drbd/drbd_worker.c
@@ -400,13 +400,13 @@  static int read_for_csum(struct drbd_peer_device *peer_device, sector_t sector,
 		goto defer;
 
 	peer_req->w.cb = w_e_send_csum;
+	peer_req->opf = REQ_OP_READ;
 	spin_lock_irq(&device->resource->req_lock);
 	list_add_tail(&peer_req->w.list, &device->read_ee);
 	spin_unlock_irq(&device->resource->req_lock);
 
 	atomic_add(size >> 9, &device->rs_sect_ev);
-	if (drbd_submit_peer_request(device, peer_req, REQ_OP_READ,
-				     DRBD_FAULT_RS_RD) == 0)
+	if (drbd_submit_peer_request(peer_req) == 0)
 		return 0;
 
 	/* If it failed because of ENOMEM, retry should help.  If it failed