diff options
Diffstat (limited to 'drivers/block/nbd.c')
-rw-r--r-- | drivers/block/nbd.c | 50 |
1 files changed, 24 insertions, 26 deletions
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 39e5f7fae3ef..83a7ba4a3eec 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c | |||
@@ -230,29 +230,40 @@ static int nbd_send_req(struct nbd_device *nbd, struct request *req) | |||
230 | int result, flags; | 230 | int result, flags; |
231 | struct nbd_request request; | 231 | struct nbd_request request; |
232 | unsigned long size = blk_rq_bytes(req); | 232 | unsigned long size = blk_rq_bytes(req); |
233 | u32 type; | ||
234 | |||
235 | if (req->cmd_type == REQ_TYPE_DRV_PRIV) | ||
236 | type = NBD_CMD_DISC; | ||
237 | else if (req->cmd_flags & REQ_DISCARD) | ||
238 | type = NBD_CMD_TRIM; | ||
239 | else if (req->cmd_flags & REQ_FLUSH) | ||
240 | type = NBD_CMD_FLUSH; | ||
241 | else if (rq_data_dir(req) == WRITE) | ||
242 | type = NBD_CMD_WRITE; | ||
243 | else | ||
244 | type = NBD_CMD_READ; | ||
233 | 245 | ||
234 | memset(&request, 0, sizeof(request)); | 246 | memset(&request, 0, sizeof(request)); |
235 | request.magic = htonl(NBD_REQUEST_MAGIC); | 247 | request.magic = htonl(NBD_REQUEST_MAGIC); |
236 | request.type = htonl(nbd_cmd(req)); | 248 | request.type = htonl(type); |
237 | 249 | if (type != NBD_CMD_FLUSH && type != NBD_CMD_DISC) { | |
238 | if (nbd_cmd(req) != NBD_CMD_FLUSH && nbd_cmd(req) != NBD_CMD_DISC) { | ||
239 | request.from = cpu_to_be64((u64)blk_rq_pos(req) << 9); | 250 | request.from = cpu_to_be64((u64)blk_rq_pos(req) << 9); |
240 | request.len = htonl(size); | 251 | request.len = htonl(size); |
241 | } | 252 | } |
242 | memcpy(request.handle, &req, sizeof(req)); | 253 | memcpy(request.handle, &req, sizeof(req)); |
243 | 254 | ||
244 | dev_dbg(nbd_to_dev(nbd), "request %p: sending control (%s@%llu,%uB)\n", | 255 | dev_dbg(nbd_to_dev(nbd), "request %p: sending control (%s@%llu,%uB)\n", |
245 | req, nbdcmd_to_ascii(nbd_cmd(req)), | 256 | req, nbdcmd_to_ascii(type), |
246 | (unsigned long long)blk_rq_pos(req) << 9, blk_rq_bytes(req)); | 257 | (unsigned long long)blk_rq_pos(req) << 9, blk_rq_bytes(req)); |
247 | result = sock_xmit(nbd, 1, &request, sizeof(request), | 258 | result = sock_xmit(nbd, 1, &request, sizeof(request), |
248 | (nbd_cmd(req) == NBD_CMD_WRITE) ? MSG_MORE : 0); | 259 | (type == NBD_CMD_WRITE) ? MSG_MORE : 0); |
249 | if (result <= 0) { | 260 | if (result <= 0) { |
250 | dev_err(disk_to_dev(nbd->disk), | 261 | dev_err(disk_to_dev(nbd->disk), |
251 | "Send control failed (result %d)\n", result); | 262 | "Send control failed (result %d)\n", result); |
252 | return -EIO; | 263 | return -EIO; |
253 | } | 264 | } |
254 | 265 | ||
255 | if (nbd_cmd(req) == NBD_CMD_WRITE) { | 266 | if (type == NBD_CMD_WRITE) { |
256 | struct req_iterator iter; | 267 | struct req_iterator iter; |
257 | struct bio_vec bvec; | 268 | struct bio_vec bvec; |
258 | /* | 269 | /* |
@@ -352,7 +363,7 @@ static struct request *nbd_read_stat(struct nbd_device *nbd) | |||
352 | } | 363 | } |
353 | 364 | ||
354 | dev_dbg(nbd_to_dev(nbd), "request %p: got reply\n", req); | 365 | dev_dbg(nbd_to_dev(nbd), "request %p: got reply\n", req); |
355 | if (nbd_cmd(req) == NBD_CMD_READ) { | 366 | if (rq_data_dir(req) != WRITE) { |
356 | struct req_iterator iter; | 367 | struct req_iterator iter; |
357 | struct bio_vec bvec; | 368 | struct bio_vec bvec; |
358 | 369 | ||
@@ -452,23 +463,11 @@ static void nbd_handle_req(struct nbd_device *nbd, struct request *req) | |||
452 | if (req->cmd_type != REQ_TYPE_FS) | 463 | if (req->cmd_type != REQ_TYPE_FS) |
453 | goto error_out; | 464 | goto error_out; |
454 | 465 | ||
455 | nbd_cmd(req) = NBD_CMD_READ; | 466 | if (rq_data_dir(req) == WRITE && |
456 | if (rq_data_dir(req) == WRITE) { | 467 | (nbd->flags & NBD_FLAG_READ_ONLY)) { |
457 | if ((req->cmd_flags & REQ_DISCARD)) { | 468 | dev_err(disk_to_dev(nbd->disk), |
458 | WARN_ON(!(nbd->flags & NBD_FLAG_SEND_TRIM)); | 469 | "Write on read-only\n"); |
459 | nbd_cmd(req) = NBD_CMD_TRIM; | 470 | goto error_out; |
460 | } else | ||
461 | nbd_cmd(req) = NBD_CMD_WRITE; | ||
462 | if (nbd->flags & NBD_FLAG_READ_ONLY) { | ||
463 | dev_err(disk_to_dev(nbd->disk), | ||
464 | "Write on read-only\n"); | ||
465 | goto error_out; | ||
466 | } | ||
467 | } | ||
468 | |||
469 | if (req->cmd_flags & REQ_FLUSH) { | ||
470 | BUG_ON(unlikely(blk_rq_sectors(req))); | ||
471 | nbd_cmd(req) = NBD_CMD_FLUSH; | ||
472 | } | 471 | } |
473 | 472 | ||
474 | req->errors = 0; | 473 | req->errors = 0; |
@@ -592,8 +591,7 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, | |||
592 | fsync_bdev(bdev); | 591 | fsync_bdev(bdev); |
593 | mutex_lock(&nbd->tx_lock); | 592 | mutex_lock(&nbd->tx_lock); |
594 | blk_rq_init(NULL, &sreq); | 593 | blk_rq_init(NULL, &sreq); |
595 | sreq.cmd_type = REQ_TYPE_SPECIAL; | 594 | sreq.cmd_type = REQ_TYPE_DRV_PRIV; |
596 | nbd_cmd(&sreq) = NBD_CMD_DISC; | ||
597 | 595 | ||
598 | /* Check again after getting mutex back. */ | 596 | /* Check again after getting mutex back. */ |
599 | if (!nbd->sock) | 597 | if (!nbd->sock) |