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 | ||
