summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordmitry pervushin <dpervushin@nvidia.com>2021-08-24 06:59:51 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2021-08-27 15:26:13 -0400
commit665f24abc4bdffb8e153d3383f0cdc856c79cb5e (patch)
tree7f59d80c440a377d9e4708d35599e9c532f966ed
parent70896c585b95d84344d8c5ab9640b6abff015573 (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.c69
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
219static void req_error_handler(struct vblk_dev *vblkdev, struct request *breq) 219static 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 */
417static 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