From 55cf1ddbffe17586bdb585647e53c44c92e900b1 Mon Sep 17 00:00:00 2001 From: Steffen Maier Date: Thu, 14 Sep 2006 16:58:24 +0200 Subject: [PATCH] [PATCH] block: fix negative bias of ios_in_flight (CONFIG_BLK_STATS) because of unbalanced I/O accounting Fix for unbalanced I/O accounting, that caused ios_in_flight (CONFIG_BLK_STATS) to become and stay negative, as suggested by Jens Axboe. An added boolean field "io_account" in struct request is assumed to be initialized to false on new requests. On starting I/O accounting, true is assigned to the field. On ending I/O accounting, accounting is only executed if the field has already been assigned true previously. Thus, this fixes unbalanced cases where requests such as non-data get enqueued without starting to account (ide_do_drive_cmd?) but the end of accounting gets executed on finishing the same requests (ide_end_drive_cmd, end_that_request_last, req_finished_io). The precondition of io_account being initialized to false is ensured by 1) ide_init_drive_taskfile / ide_init_drive_cmd memset'ing the whole request to zero, for requests that were potentially accounted unbalanced, and 2) get_request assigning zero to io_account on allocating a request from the free list cache (or slab cache initially), for the majority of requests such as those involving data. Jens preferred this to other discussed solutions and it should fix all those unbalanced cases at once without touching each of them individually. For more details, please see previous posts of this thread http://www.uwsg.iu.edu/hypermail/linux/kernel/0608.2/0776.html. I tested the patch with 2.4.24 and 2.4.33.3 successfully on an UP ia32 machine with one /dev/hda. Signed-off-by: Steffen Maier --- drivers/block/ll_rw_blk.c | 6 ++++++ include/linux/blkdev.h | 1 + 2 files changed, 7 insertions(+) diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index 3924b24f..c259ceee 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -575,6 +575,7 @@ static struct request *get_request(request_queue_t *q, int rw) rq->rq_status = RQ_ACTIVE; rq->cmd = rw; rq->special = NULL; + rq->io_account = 0; rq->q = q; } @@ -813,6 +814,7 @@ void req_new_io(struct request *req, int merge, int sectors) struct hd_struct *hd1, *hd2; locate_hd_struct(req, &hd1, &hd2); + req->io_account = 1; if (hd1) account_io_start(hd1, req, merge, sectors); if (hd2) @@ -823,6 +825,8 @@ void req_merged_io(struct request *req) { struct hd_struct *hd1, *hd2; + if (unlikely(req->io_account == 0)) + return; locate_hd_struct(req, &hd1, &hd2); if (hd1) down_ios(hd1); @@ -834,6 +838,8 @@ void req_finished_io(struct request *req) { struct hd_struct *hd1, *hd2; + if (unlikely(req->io_account == 0)) + return; locate_hd_struct(req, &hd1, &hd2); if (hd1) account_io_end(hd1, req); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index fd524f2a..57230bf2 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -46,6 +46,7 @@ struct request { struct buffer_head * bh; struct buffer_head * bhtail; request_queue_t *q; + char io_account; }; #include -- 2.11.0