[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [RFC 1/6] block: add request tracking
From: |
Stefan Hajnoczi |
Subject: |
Re: [Qemu-devel] [RFC 1/6] block: add request tracking |
Date: |
Thu, 3 Nov 2011 07:57:44 +0000 |
On Wed, Nov 2, 2011 at 4:30 PM, Kevin Wolf <address@hidden> wrote:
> Am 17.10.2011 17:47, schrieb Stefan Hajnoczi:
>> The block layer does not know about pending requests. This information
>> is necessary for copy-on-read since overlapping requests must be
>> serialized to prevent races that corrupt the image.
>>
>> Add a simple mechanism to enable/disable request tracking. By default
>> request tracking is disabled.
>>
>> The BlockDriverState gets a new tracked_request list field which
>> contains all pending requests. Each request is a BdrvTrackedRequest
>> record with sector_num, nb_sectors, and is_write fields.
>>
>> Signed-off-by: Stefan Hajnoczi <address@hidden>
>> ---
>> block.c | 83
>> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>> block_int.h | 8 +++++
>> 2 files changed, 90 insertions(+), 1 deletions(-)
>>
>> diff --git a/block.c b/block.c
>> index 9873b57..2d2c62a 100644
>> --- a/block.c
>> +++ b/block.c
>> @@ -978,6 +978,77 @@ void bdrv_commit_all(void)
>> }
>> }
>>
>> +struct BdrvTrackedRequest {
>> + BlockDriverState *bs;
>> + int64_t sector_num;
>> + int nb_sectors;
>> + bool is_write;
>> + QLIST_ENTRY(BdrvTrackedRequest) list;
>> +};
>> +
>> +/**
>> + * Remove an active request from the tracked requests list
>> + *
>> + * If req is NULL, no operation is performed.
>> + *
>> + * This function should be called when a tracked request is completing.
>> + */
>> +static void tracked_request_remove(BdrvTrackedRequest *req)
>> +{
>> + if (req) {
>> + QLIST_REMOVE(req, list);
>> + g_free(req);
>> + }
>> +}
>> +
>> +/**
>> + * Add an active request to the tracked requests list
>> + *
>> + * Return NULL if request tracking is disabled, non-NULL otherwise.
>> + */
>> +static BdrvTrackedRequest *tracked_request_add(BlockDriverState *bs,
>> + int64_t sector_num,
>> + int nb_sectors, bool
>> is_write)
>> +{
>> + BdrvTrackedRequest *req;
>> +
>> + if (!bs->request_tracking) {
>> + return NULL;
>> + }
>> +
>> + req = g_malloc(sizeof(*req));
>> + req->bs = bs;
>> + req->sector_num = sector_num;
>> + req->nb_sectors = nb_sectors;
>> + req->is_write = is_write;
>
> How about using g_malloc0 or a compound literal assignment for
> initialisation, so that we won't get surprises when the struct is extended?
Sure.
>> +
>> + QLIST_INSERT_HEAD(&bs->tracked_requests, req, list);
>> +
>> + return req;
>> +}
>> +
>> +/**
>> + * Enable tracking of incoming requests
>> + *
>> + * Request tracking can be safely used by multiple users at the same time,
>> + * there is an internal reference count to match start and stop calls.
>> + */
>> +void bdrv_start_request_tracking(BlockDriverState *bs)
>> +{
>> + bs->request_tracking++;
>> +}
>> +
>> +/**
>> + * Disable tracking of incoming requests
>> + *
>> + * Note that in-flight requests are still tracked, this function only stops
>> + * tracking incoming requests.
>> + */
>> +void bdrv_stop_request_tracking(BlockDriverState *bs)
>> +{
>> + bs->request_tracking--;
>> +}
>> +
>> /*
>> * Return values:
>> * 0 - success
>> @@ -1262,6 +1333,8 @@ static int coroutine_fn
>> bdrv_co_do_readv(BlockDriverState *bs,
>> int64_t sector_num, int nb_sectors, QEMUIOVector *qiov)
>> {
>> BlockDriver *drv = bs->drv;
>> + BdrvTrackedRequest *req;
>> + int ret;
>>
>> if (!drv) {
>> return -ENOMEDIUM;
>> @@ -1270,7 +1343,10 @@ static int coroutine_fn
>> bdrv_co_do_readv(BlockDriverState *bs,
>> return -EIO;
>> }
>>
>> - return drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov);
>> + req = tracked_request_add(bs, sector_num, nb_sectors, false);
>> + ret = drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov);
>> + tracked_request_remove(req);
>
> Hm... Do we actually need to malloc the BdrvTrackedRequest? If all users
> are like this (and at least those in this patch are), we can just keep
> it on the coroutine stack.
Okay.
Stefan