Commit 45c21793 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Jens Axboe

drbd: implement REQ_OP_WRITE_ZEROES

It seems like DRBD assumes its on the wire TRIM request always zeroes data.
Use that fact to implement REQ_OP_WRITE_ZEROES.
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarHannes Reinecke <hare@suse.com>
Signed-off-by: default avatarJens Axboe <axboe@fb.com>
parent 0dbed96a
...@@ -1668,7 +1668,8 @@ static u32 bio_flags_to_wire(struct drbd_connection *connection, ...@@ -1668,7 +1668,8 @@ static u32 bio_flags_to_wire(struct drbd_connection *connection,
(bio->bi_opf & REQ_FUA ? DP_FUA : 0) | (bio->bi_opf & REQ_FUA ? DP_FUA : 0) |
(bio->bi_opf & REQ_PREFLUSH ? DP_FLUSH : 0) | (bio->bi_opf & REQ_PREFLUSH ? DP_FLUSH : 0) |
(bio_op(bio) == REQ_OP_WRITE_SAME ? DP_WSAME : 0) | (bio_op(bio) == REQ_OP_WRITE_SAME ? DP_WSAME : 0) |
(bio_op(bio) == REQ_OP_DISCARD ? DP_DISCARD : 0); (bio_op(bio) == REQ_OP_DISCARD ? DP_DISCARD : 0) |
(bio_op(bio) == REQ_OP_WRITE_ZEROES ? DP_DISCARD : 0);
else else
return bio->bi_opf & REQ_SYNC ? DP_RW_SYNC : 0; return bio->bi_opf & REQ_SYNC ? DP_RW_SYNC : 0;
} }
......
...@@ -1217,10 +1217,12 @@ static void decide_on_discard_support(struct drbd_device *device, ...@@ -1217,10 +1217,12 @@ static void decide_on_discard_support(struct drbd_device *device,
blk_queue_discard_granularity(q, 512); blk_queue_discard_granularity(q, 512);
q->limits.max_discard_sectors = drbd_max_discard_sectors(connection); q->limits.max_discard_sectors = drbd_max_discard_sectors(connection);
queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q); queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q);
q->limits.max_write_zeroes_sectors = drbd_max_discard_sectors(connection);
} else { } else {
queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, q); queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, q);
blk_queue_discard_granularity(q, 0); blk_queue_discard_granularity(q, 0);
q->limits.max_discard_sectors = 0; q->limits.max_discard_sectors = 0;
q->limits.max_write_zeroes_sectors = 0;
} }
} }
......
...@@ -2285,7 +2285,7 @@ static unsigned long wire_flags_to_bio_flags(u32 dpf) ...@@ -2285,7 +2285,7 @@ static unsigned long wire_flags_to_bio_flags(u32 dpf)
static unsigned long wire_flags_to_bio_op(u32 dpf) static unsigned long wire_flags_to_bio_op(u32 dpf)
{ {
if (dpf & DP_DISCARD) if (dpf & DP_DISCARD)
return REQ_OP_DISCARD; return REQ_OP_WRITE_ZEROES;
else else
return REQ_OP_WRITE; return REQ_OP_WRITE;
} }
...@@ -2476,7 +2476,7 @@ static int receive_Data(struct drbd_connection *connection, struct packet_info * ...@@ -2476,7 +2476,7 @@ static int receive_Data(struct drbd_connection *connection, struct packet_info *
op_flags = wire_flags_to_bio_flags(dp_flags); op_flags = wire_flags_to_bio_flags(dp_flags);
if (pi->cmd == P_TRIM) { if (pi->cmd == P_TRIM) {
D_ASSERT(peer_device, peer_req->i.size > 0); D_ASSERT(peer_device, peer_req->i.size > 0);
D_ASSERT(peer_device, op == REQ_OP_DISCARD); D_ASSERT(peer_device, op == REQ_OP_WRITE_ZEROES);
D_ASSERT(peer_device, peer_req->pages == NULL); D_ASSERT(peer_device, peer_req->pages == NULL);
} else if (peer_req->pages == NULL) { } else if (peer_req->pages == NULL) {
D_ASSERT(device, peer_req->i.size == 0); D_ASSERT(device, peer_req->i.size == 0);
...@@ -4789,7 +4789,7 @@ static int receive_rs_deallocated(struct drbd_connection *connection, struct pac ...@@ -4789,7 +4789,7 @@ static int receive_rs_deallocated(struct drbd_connection *connection, struct pac
if (get_ldev(device)) { if (get_ldev(device)) {
struct drbd_peer_request *peer_req; struct drbd_peer_request *peer_req;
const int op = REQ_OP_DISCARD; const int op = REQ_OP_WRITE_ZEROES;
peer_req = drbd_alloc_peer_req(peer_device, ID_SYNCER, sector, peer_req = drbd_alloc_peer_req(peer_device, ID_SYNCER, sector,
size, 0, GFP_NOIO); size, 0, GFP_NOIO);
......
...@@ -59,6 +59,7 @@ static struct drbd_request *drbd_req_new(struct drbd_device *device, struct bio ...@@ -59,6 +59,7 @@ static struct drbd_request *drbd_req_new(struct drbd_device *device, struct bio
drbd_req_make_private_bio(req, bio_src); drbd_req_make_private_bio(req, bio_src);
req->rq_state = (bio_data_dir(bio_src) == WRITE ? RQ_WRITE : 0) req->rq_state = (bio_data_dir(bio_src) == WRITE ? RQ_WRITE : 0)
| (bio_op(bio_src) == REQ_OP_WRITE_SAME ? RQ_WSAME : 0) | (bio_op(bio_src) == REQ_OP_WRITE_SAME ? RQ_WSAME : 0)
| (bio_op(bio_src) == REQ_OP_WRITE_ZEROES ? RQ_UNMAP : 0)
| (bio_op(bio_src) == REQ_OP_DISCARD ? RQ_UNMAP : 0); | (bio_op(bio_src) == REQ_OP_DISCARD ? RQ_UNMAP : 0);
req->device = device; req->device = device;
req->master_bio = bio_src; req->master_bio = bio_src;
...@@ -1180,7 +1181,8 @@ drbd_submit_req_private_bio(struct drbd_request *req) ...@@ -1180,7 +1181,8 @@ drbd_submit_req_private_bio(struct drbd_request *req)
if (get_ldev(device)) { if (get_ldev(device)) {
if (drbd_insert_fault(device, type)) if (drbd_insert_fault(device, type))
bio_io_error(bio); bio_io_error(bio);
else if (bio_op(bio) == REQ_OP_DISCARD) else if (bio_op(bio) == REQ_OP_WRITE_ZEROES ||
bio_op(bio) == REQ_OP_DISCARD)
drbd_process_discard_req(req); drbd_process_discard_req(req);
else else
generic_make_request(bio); generic_make_request(bio);
...@@ -1234,7 +1236,8 @@ drbd_request_prepare(struct drbd_device *device, struct bio *bio, unsigned long ...@@ -1234,7 +1236,8 @@ drbd_request_prepare(struct drbd_device *device, struct bio *bio, unsigned long
_drbd_start_io_acct(device, req); _drbd_start_io_acct(device, req);
/* process discards always from our submitter thread */ /* process discards always from our submitter thread */
if (bio_op(bio) & REQ_OP_DISCARD) if ((bio_op(bio) & REQ_OP_WRITE_ZEROES) ||
(bio_op(bio) & REQ_OP_DISCARD))
goto queue_for_submitter_thread; goto queue_for_submitter_thread;
if (rw == WRITE && req->private_bio && req->i.size if (rw == WRITE && req->private_bio && req->i.size
......
...@@ -174,7 +174,8 @@ void drbd_peer_request_endio(struct bio *bio) ...@@ -174,7 +174,8 @@ void drbd_peer_request_endio(struct bio *bio)
struct drbd_peer_request *peer_req = bio->bi_private; struct drbd_peer_request *peer_req = bio->bi_private;
struct drbd_device *device = peer_req->peer_device->device; struct drbd_device *device = peer_req->peer_device->device;
bool is_write = bio_data_dir(bio) == WRITE; bool is_write = bio_data_dir(bio) == WRITE;
bool is_discard = !!(bio_op(bio) == REQ_OP_DISCARD); bool is_discard = bio_op(bio) == REQ_OP_WRITE_ZEROES ||
bio_op(bio) == REQ_OP_DISCARD;
if (bio->bi_error && __ratelimit(&drbd_ratelimit_state)) if (bio->bi_error && __ratelimit(&drbd_ratelimit_state))
drbd_warn(device, "%s: error=%d s=%llus\n", drbd_warn(device, "%s: error=%d s=%llus\n",
...@@ -249,6 +250,7 @@ void drbd_request_endio(struct bio *bio) ...@@ -249,6 +250,7 @@ void drbd_request_endio(struct bio *bio)
/* to avoid recursion in __req_mod */ /* to avoid recursion in __req_mod */
if (unlikely(bio->bi_error)) { if (unlikely(bio->bi_error)) {
switch (bio_op(bio)) { switch (bio_op(bio)) {
case REQ_OP_WRITE_ZEROES:
case REQ_OP_DISCARD: case REQ_OP_DISCARD:
if (bio->bi_error == -EOPNOTSUPP) if (bio->bi_error == -EOPNOTSUPP)
what = DISCARD_COMPLETED_NOTSUPP; what = DISCARD_COMPLETED_NOTSUPP;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment