Browse Source
Emulated devices and other BlockBackend users wishing to take advantage of blk_register_buf() all have the same repetitive job: register RAMBlocks with the BlockBackend using RAMBlockNotifier. Add a BlockRAMRegistrar API to do this. A later commit will use this from hw/block/virtio-blk.c. Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> Reviewed-by: Stefano Garzarella <sgarzare@redhat.com> Message-id: 20221013185908.1297568-10-stefanha@redhat.com Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>pull/225/head
4 changed files with 97 additions and 0 deletions
@ -0,0 +1,58 @@ |
|||
/*
|
|||
* BlockBackend RAM Registrar |
|||
* |
|||
* SPDX-License-Identifier: GPL-2.0-or-later |
|||
*/ |
|||
|
|||
#include "qemu/osdep.h" |
|||
#include "sysemu/block-backend.h" |
|||
#include "sysemu/block-ram-registrar.h" |
|||
#include "qapi/error.h" |
|||
|
|||
static void ram_block_added(RAMBlockNotifier *n, void *host, size_t size, |
|||
size_t max_size) |
|||
{ |
|||
BlockRAMRegistrar *r = container_of(n, BlockRAMRegistrar, notifier); |
|||
Error *err = NULL; |
|||
|
|||
if (!r->ok) { |
|||
return; /* don't try again if we've already failed */ |
|||
} |
|||
|
|||
if (!blk_register_buf(r->blk, host, max_size, &err)) { |
|||
error_report_err(err); |
|||
ram_block_notifier_remove(&r->notifier); |
|||
r->ok = false; |
|||
} |
|||
} |
|||
|
|||
static void ram_block_removed(RAMBlockNotifier *n, void *host, size_t size, |
|||
size_t max_size) |
|||
{ |
|||
BlockRAMRegistrar *r = container_of(n, BlockRAMRegistrar, notifier); |
|||
blk_unregister_buf(r->blk, host, max_size); |
|||
} |
|||
|
|||
void blk_ram_registrar_init(BlockRAMRegistrar *r, BlockBackend *blk) |
|||
{ |
|||
r->blk = blk; |
|||
r->notifier = (RAMBlockNotifier){ |
|||
.ram_block_added = ram_block_added, |
|||
.ram_block_removed = ram_block_removed, |
|||
|
|||
/*
|
|||
* .ram_block_resized() is not necessary because we use the max_size |
|||
* value that does not change across resize. |
|||
*/ |
|||
}; |
|||
r->ok = true; |
|||
|
|||
ram_block_notifier_add(&r->notifier); |
|||
} |
|||
|
|||
void blk_ram_registrar_destroy(BlockRAMRegistrar *r) |
|||
{ |
|||
if (r->ok) { |
|||
ram_block_notifier_remove(&r->notifier); |
|||
} |
|||
} |
|||
@ -0,0 +1,37 @@ |
|||
/*
|
|||
* BlockBackend RAM Registrar |
|||
* |
|||
* SPDX-License-Identifier: GPL-2.0-or-later |
|||
*/ |
|||
|
|||
#ifndef BLOCK_RAM_REGISTRAR_H |
|||
#define BLOCK_RAM_REGISTRAR_H |
|||
|
|||
#include "exec/ramlist.h" |
|||
|
|||
/**
|
|||
* struct BlockRAMRegistrar: |
|||
* |
|||
* Keeps RAMBlock memory registered with a BlockBackend using |
|||
* blk_register_buf() including hotplugged memory. |
|||
* |
|||
* Emulated devices or other BlockBackend users initialize a BlockRAMRegistrar |
|||
* with blk_ram_registrar_init() before submitting I/O requests with the |
|||
* BDRV_REQ_REGISTERED_BUF flag set. |
|||
*/ |
|||
typedef struct { |
|||
BlockBackend *blk; |
|||
RAMBlockNotifier notifier; |
|||
bool ok; |
|||
} BlockRAMRegistrar; |
|||
|
|||
void blk_ram_registrar_init(BlockRAMRegistrar *r, BlockBackend *blk); |
|||
void blk_ram_registrar_destroy(BlockRAMRegistrar *r); |
|||
|
|||
/* Have all RAMBlocks been registered successfully? */ |
|||
static inline bool blk_ram_registrar_ok(BlockRAMRegistrar *r) |
|||
{ |
|||
return r->ok; |
|||
} |
|||
|
|||
#endif /* BLOCK_RAM_REGISTRAR_H */ |
|||
Loading…
Reference in new issue