diff options
author | dmitry pervushin <dpervushin@nvidia.com> | 2021-08-24 06:59:51 -0400 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2021-08-27 15:26:13 -0400 |
commit | 665f24abc4bdffb8e153d3383f0cdc856c79cb5e (patch) | |
tree | 7f59d80c440a377d9e4708d35599e9c532f966ed | |
parent | 70896c585b95d84344d8c5ab9640b6abff015573 (diff) |
vblk: ignore invalid requests
The virtual block device driver knows about capabilities of the device
Based on this, we can early reject (complete with -ENOTSUPP) invalid
requests.
Bug 200511281
Change-Id: I54d457e7ccab293e48df7283e53236ec628a159b
Signed-off-by: dmitry pervushin <dpervushin@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2582114
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
Reviewed-by: Vikram Kanigiri <vkanigiri@nvidia.com>
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
Reviewed-by: Phoenix Jung <pjung@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
GVS: Gerrit_Virtual_Submit
-rw-r--r-- | drivers/block/tegra_virt_storage/tegra_hv_vblk.c | 69 |
1 files changed, 55 insertions, 14 deletions
diff --git a/drivers/block/tegra_virt_storage/tegra_hv_vblk.c b/drivers/block/tegra_virt_storage/tegra_hv_vblk.c index a429047ad..7a71b4f01 100644 --- a/drivers/block/tegra_virt_storage/tegra_hv_vblk.c +++ b/drivers/block/tegra_virt_storage/tegra_hv_vblk.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2015-2018, NVIDIA CORPORATION. All rights reserved. | 2 | * Copyright (c) 2015-2021, NVIDIA CORPORATION. All rights reserved. |
3 | * | 3 | * |
4 | * This software is licensed under the terms of the GNU General Public | 4 | * This software is licensed under the terms of the GNU General Public |
5 | * License version 2, as published by the Free Software Foundation, and | 5 | * License version 2, as published by the Free Software Foundation, and |
@@ -216,15 +216,17 @@ static int vblk_get_configinfo(struct vblk_dev *vblkdev) | |||
216 | return 0; | 216 | return 0; |
217 | } | 217 | } |
218 | 218 | ||
219 | static void req_error_handler(struct vblk_dev *vblkdev, struct request *breq) | 219 | static void req_error_handler(struct vblk_dev *vblkdev, |
220 | struct request *breq, int error) | ||
220 | { | 221 | { |
221 | dev_err(vblkdev->device, | 222 | if ((breq->cmd_flags & REQ_QUIET) == 0) |
222 | "Error for request pos %llx type %llx size %x\n", | 223 | dev_err(vblkdev->device, |
223 | (blk_rq_pos(breq) * (uint64_t)SECTOR_SIZE), | 224 | "Error for request pos %llx type %llx size %x\n", |
224 | (uint64_t)req_op(breq), | 225 | (blk_rq_pos(breq) * (uint64_t)SECTOR_SIZE), |
225 | blk_rq_bytes(breq)); | 226 | (uint64_t)req_op(breq), |
227 | blk_rq_bytes(breq)); | ||
226 | 228 | ||
227 | blk_end_request_all(breq, -EIO); | 229 | blk_end_request_all(breq, error); |
228 | } | 230 | } |
229 | 231 | ||
230 | /** | 232 | /** |
@@ -279,12 +281,12 @@ static bool complete_bio_req(struct vblk_dev *vblkdev) | |||
279 | if (req_resp->blkdev_resp.ioctl_resp.status != 0) { | 281 | if (req_resp->blkdev_resp.ioctl_resp.status != 0) { |
280 | dev_err(vblkdev->device, | 282 | dev_err(vblkdev->device, |
281 | "IOCTL request failed!\n"); | 283 | "IOCTL request failed!\n"); |
282 | req_error_handler(vblkdev, bio_req); | 284 | req_error_handler(vblkdev, bio_req, -EIO); |
283 | goto put_req; | 285 | goto put_req; |
284 | } | 286 | } |
285 | 287 | ||
286 | if (vblk_complete_ioctl_req(vblkdev, vsc_req)) { | 288 | if (vblk_complete_ioctl_req(vblkdev, vsc_req)) { |
287 | req_error_handler(vblkdev, bio_req); | 289 | req_error_handler(vblkdev, bio_req, -EIO); |
288 | } else { | 290 | } else { |
289 | if (blk_end_request(bio_req, 0, 0)) { | 291 | if (blk_end_request(bio_req, 0, 0)) { |
290 | dev_err(vblkdev->device, | 292 | dev_err(vblkdev->device, |
@@ -293,14 +295,15 @@ static bool complete_bio_req(struct vblk_dev *vblkdev) | |||
293 | } | 295 | } |
294 | } else { | 296 | } else { |
295 | if (req_resp->blkdev_resp.blk_resp.status != 0) { | 297 | if (req_resp->blkdev_resp.blk_resp.status != 0) { |
296 | req_error_handler(vblkdev, bio_req); | 298 | req_error_handler(vblkdev, bio_req, -EIO); |
297 | goto put_req; | 299 | goto put_req; |
298 | } | 300 | } |
299 | 301 | ||
300 | if (req_op(bio_req) != REQ_OP_FLUSH) { | 302 | if (req_op(bio_req) != REQ_OP_FLUSH) { |
301 | if (vs_req->blkdev_req.blk_req.num_blks != | 303 | if (vs_req->blkdev_req.blk_req.num_blks != |
302 | req_resp->blkdev_resp.blk_resp.num_blks) { | 304 | req_resp->blkdev_resp.blk_resp.num_blks) { |
303 | req_error_handler(vblkdev, bio_req); | 305 | req_error_handler(vblkdev, |
306 | bio_req, -EIO); | ||
304 | goto put_req; | 307 | goto put_req; |
305 | } | 308 | } |
306 | } | 309 | } |
@@ -342,7 +345,7 @@ static bool complete_bio_req(struct vblk_dev *vblkdev) | |||
342 | } | 345 | } |
343 | } | 346 | } |
344 | } else if ((bio_req != NULL) && (status != 0)) { | 347 | } else if ((bio_req != NULL) && (status != 0)) { |
345 | req_error_handler(vblkdev, bio_req); | 348 | req_error_handler(vblkdev, bio_req, -EIO); |
346 | } else { | 349 | } else { |
347 | dev_err(vblkdev->device, | 350 | dev_err(vblkdev->device, |
348 | "VSC request %d has null bio request!\n", | 351 | "VSC request %d has null bio request!\n", |
@@ -404,6 +407,39 @@ static bool bio_req_sanity_check(struct vblk_dev *vblkdev, | |||
404 | } | 407 | } |
405 | 408 | ||
406 | /** | 409 | /** |
410 | * is_valid_request - check if the request can be handled by the server | ||
411 | * | ||
412 | * we already know that virtual device supports - read/write capabilities | ||
413 | * so, we can reject invalid requests before sending down to the server | ||
414 | * | ||
415 | * return value: true if request is supported, false otherwise | ||
416 | */ | ||
417 | static bool is_valid_request(struct vblk_dev *vblkdev, | ||
418 | int rq_code, struct request *bio) | ||
419 | { | ||
420 | size_t i; | ||
421 | struct { | ||
422 | int rq_code; | ||
423 | uint32_t flag; | ||
424 | char *err_msg; | ||
425 | } checks[] = { | ||
426 | { REQ_OP_READ, VS_BLK_READ_OP_F, "unsupported read" }, | ||
427 | { REQ_OP_WRITE, VS_BLK_WRITE_OP_F, "unsupported write" }, | ||
428 | { REQ_OP_FLUSH, VS_BLK_FLUSH_OP_F, "unsupport flush" }, | ||
429 | }; | ||
430 | |||
431 | for (i = 0; i < ARRAY_SIZE(checks); i++) { | ||
432 | if (rq_code == checks[i].rq_code && | ||
433 | (vblkdev->config.blk_config.req_ops_supported & | ||
434 | checks[i].flag) == 0) { | ||
435 | bio->cmd_flags |= REQ_QUIET; | ||
436 | dev_dbg(vblkdev->device, "%s\n", checks[i].err_msg); | ||
437 | return false; | ||
438 | } | ||
439 | } | ||
440 | return true; | ||
441 | } | ||
442 | /** | ||
407 | * submit_bio_req: Fetch a bio request and submit it to | 443 | * submit_bio_req: Fetch a bio request and submit it to |
408 | * server for processing. | 444 | * server for processing. |
409 | */ | 445 | */ |
@@ -416,6 +452,7 @@ static bool submit_bio_req(struct vblk_dev *vblkdev) | |||
416 | size_t size; | 452 | size_t size; |
417 | size_t total_size = 0; | 453 | size_t total_size = 0; |
418 | void *buffer; | 454 | void *buffer; |
455 | int error = -EIO; | ||
419 | 456 | ||
420 | if (!tegra_hv_ivc_can_write(vblkdev->ivck)) | 457 | if (!tegra_hv_ivc_can_write(vblkdev->ivck)) |
421 | goto bio_exit; | 458 | goto bio_exit; |
@@ -443,6 +480,10 @@ static bool submit_bio_req(struct vblk_dev *vblkdev) | |||
443 | #else | 480 | #else |
444 | if (bio_req->cmd_type == REQ_TYPE_FS) { | 481 | if (bio_req->cmd_type == REQ_TYPE_FS) { |
445 | #endif | 482 | #endif |
483 | if (!is_valid_request(vblkdev, req_op(bio_req), bio_req)) { | ||
484 | error = -ENOTSUPP; | ||
485 | goto bio_exit; | ||
486 | } | ||
446 | if (req_op(bio_req) == REQ_OP_READ) { | 487 | if (req_op(bio_req) == REQ_OP_READ) { |
447 | vs_req->blkdev_req.req_op = VS_BLK_READ; | 488 | vs_req->blkdev_req.req_op = VS_BLK_READ; |
448 | } else if (req_op(bio_req) == REQ_OP_WRITE) { | 489 | } else if (req_op(bio_req) == REQ_OP_WRITE) { |
@@ -525,7 +566,7 @@ bio_exit: | |||
525 | } | 566 | } |
526 | 567 | ||
527 | if (bio_req != NULL) { | 568 | if (bio_req != NULL) { |
528 | req_error_handler(vblkdev, bio_req); | 569 | req_error_handler(vblkdev, bio_req, error); |
529 | return true; | 570 | return true; |
530 | } | 571 | } |
531 | 572 | ||