Commit 02d26103 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Jens Axboe

sd: implement REQ_OP_WRITE_ZEROES

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
Reviewed-by: default avatarHannes Reinecke <hare@suse.com>
Signed-off-by: default avatarJens Axboe <axboe@fb.com>
parent 885fa13f
...@@ -735,7 +735,7 @@ static int sd_setup_unmap_cmnd(struct scsi_cmnd *cmd) ...@@ -735,7 +735,7 @@ static int sd_setup_unmap_cmnd(struct scsi_cmnd *cmd)
return scsi_init_io(cmd); return scsi_init_io(cmd);
} }
static int sd_setup_write_same16_cmnd(struct scsi_cmnd *cmd) static int sd_setup_write_same16_cmnd(struct scsi_cmnd *cmd, bool unmap)
{ {
struct scsi_device *sdp = cmd->device; struct scsi_device *sdp = cmd->device;
struct request *rq = cmd->request; struct request *rq = cmd->request;
...@@ -752,13 +752,14 @@ static int sd_setup_write_same16_cmnd(struct scsi_cmnd *cmd) ...@@ -752,13 +752,14 @@ static int sd_setup_write_same16_cmnd(struct scsi_cmnd *cmd)
cmd->cmd_len = 16; cmd->cmd_len = 16;
cmd->cmnd[0] = WRITE_SAME_16; cmd->cmnd[0] = WRITE_SAME_16;
if (unmap)
cmd->cmnd[1] = 0x8; /* UNMAP */ cmd->cmnd[1] = 0x8; /* UNMAP */
put_unaligned_be64(sector, &cmd->cmnd[2]); put_unaligned_be64(sector, &cmd->cmnd[2]);
put_unaligned_be32(nr_sectors, &cmd->cmnd[10]); put_unaligned_be32(nr_sectors, &cmd->cmnd[10]);
cmd->allowed = SD_MAX_RETRIES; cmd->allowed = SD_MAX_RETRIES;
cmd->transfersize = data_len; cmd->transfersize = data_len;
rq->timeout = SD_TIMEOUT; rq->timeout = unmap ? SD_TIMEOUT : SD_WRITE_SAME_TIMEOUT;
scsi_req(rq)->resid_len = data_len; scsi_req(rq)->resid_len = data_len;
return scsi_init_io(cmd); return scsi_init_io(cmd);
...@@ -788,12 +789,27 @@ static int sd_setup_write_same10_cmnd(struct scsi_cmnd *cmd, bool unmap) ...@@ -788,12 +789,27 @@ static int sd_setup_write_same10_cmnd(struct scsi_cmnd *cmd, bool unmap)
cmd->allowed = SD_MAX_RETRIES; cmd->allowed = SD_MAX_RETRIES;
cmd->transfersize = data_len; cmd->transfersize = data_len;
rq->timeout = SD_TIMEOUT; rq->timeout = unmap ? SD_TIMEOUT : SD_WRITE_SAME_TIMEOUT;
scsi_req(rq)->resid_len = data_len; scsi_req(rq)->resid_len = data_len;
return scsi_init_io(cmd); return scsi_init_io(cmd);
} }
static int sd_setup_write_zeroes_cmnd(struct scsi_cmnd *cmd)
{
struct request *rq = cmd->request;
struct scsi_device *sdp = cmd->device;
struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
u64 sector = blk_rq_pos(rq) >> (ilog2(sdp->sector_size) - 9);
u32 nr_sectors = blk_rq_sectors(rq) >> (ilog2(sdp->sector_size) - 9);
if (sdp->no_write_same)
return BLKPREP_INVALID;
if (sdkp->ws16 || sector > 0xffffffff || nr_sectors > 0xffff)
return sd_setup_write_same16_cmnd(cmd, false);
return sd_setup_write_same10_cmnd(cmd, false);
}
static void sd_config_write_same(struct scsi_disk *sdkp) static void sd_config_write_same(struct scsi_disk *sdkp)
{ {
struct request_queue *q = sdkp->disk->queue; struct request_queue *q = sdkp->disk->queue;
...@@ -823,6 +839,8 @@ static void sd_config_write_same(struct scsi_disk *sdkp) ...@@ -823,6 +839,8 @@ static void sd_config_write_same(struct scsi_disk *sdkp)
out: out:
blk_queue_max_write_same_sectors(q, sdkp->max_ws_blocks * blk_queue_max_write_same_sectors(q, sdkp->max_ws_blocks *
(logical_block_size >> 9)); (logical_block_size >> 9));
blk_queue_max_write_zeroes_sectors(q, sdkp->max_ws_blocks *
(logical_block_size >> 9));
} }
/** /**
...@@ -1163,7 +1181,7 @@ static int sd_init_command(struct scsi_cmnd *cmd) ...@@ -1163,7 +1181,7 @@ static int sd_init_command(struct scsi_cmnd *cmd)
case SD_LBP_UNMAP: case SD_LBP_UNMAP:
return sd_setup_unmap_cmnd(cmd); return sd_setup_unmap_cmnd(cmd);
case SD_LBP_WS16: case SD_LBP_WS16:
return sd_setup_write_same16_cmnd(cmd); return sd_setup_write_same16_cmnd(cmd, true);
case SD_LBP_WS10: case SD_LBP_WS10:
return sd_setup_write_same10_cmnd(cmd, true); return sd_setup_write_same10_cmnd(cmd, true);
case SD_LBP_ZERO: case SD_LBP_ZERO:
...@@ -1171,6 +1189,8 @@ static int sd_init_command(struct scsi_cmnd *cmd) ...@@ -1171,6 +1189,8 @@ static int sd_init_command(struct scsi_cmnd *cmd)
default: default:
return BLKPREP_INVALID; return BLKPREP_INVALID;
} }
case REQ_OP_WRITE_ZEROES:
return sd_setup_write_zeroes_cmnd(cmd);
case REQ_OP_WRITE_SAME: case REQ_OP_WRITE_SAME:
return sd_setup_write_same_cmnd(cmd); return sd_setup_write_same_cmnd(cmd);
case REQ_OP_FLUSH: case REQ_OP_FLUSH:
...@@ -1810,6 +1830,7 @@ static int sd_done(struct scsi_cmnd *SCpnt) ...@@ -1810,6 +1830,7 @@ static int sd_done(struct scsi_cmnd *SCpnt)
switch (req_op(req)) { switch (req_op(req)) {
case REQ_OP_DISCARD: case REQ_OP_DISCARD:
case REQ_OP_WRITE_ZEROES:
case REQ_OP_WRITE_SAME: case REQ_OP_WRITE_SAME:
case REQ_OP_ZONE_RESET: case REQ_OP_ZONE_RESET:
if (!result) { if (!result) {
......
...@@ -329,6 +329,7 @@ void sd_zbc_complete(struct scsi_cmnd *cmd, ...@@ -329,6 +329,7 @@ void sd_zbc_complete(struct scsi_cmnd *cmd,
switch (req_op(rq)) { switch (req_op(rq)) {
case REQ_OP_WRITE: case REQ_OP_WRITE:
case REQ_OP_WRITE_ZEROES:
case REQ_OP_WRITE_SAME: case REQ_OP_WRITE_SAME:
case REQ_OP_ZONE_RESET: case REQ_OP_ZONE_RESET:
......
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