@@ -3801,6 +3801,42 @@ BlockDriverState *bdrv_find_node(const char *node_name)
return NULL;
}
+void bdrv_find_shared(BlockDriverState *bs)
+{
+ BlockDriverState *tmp_bs;
+ int max_shared_no = 0;
+ unsigned long shared_bits = 0;
+
+ if (!bs->filename)
+ return;
+ QTAILQ_FOREACH(tmp_bs, &graph_bdrv_states, node_list) {
+ if (tmp_bs == bs)
+ continue;
+ if (!strcmp(bs->filename, tmp_bs->filename)) {
+ if (tmp_bs->shared_no > 0) {
+ set_bit(tmp_bs->shared_no - 1, &shared_bits);
+ }
+ max_shared_no++;
+ }
+ }
+ if (max_shared_no > 0) {
+ int bit;
+
+ QTAILQ_FOREACH(tmp_bs, &graph_bdrv_states, node_list) {
+ if (!strcmp(bs->filename, tmp_bs->filename) && !tmp_bs->shared_no) {
+ bit = find_first_zero_bit(&shared_bits, sizeof(unsigned long));
+ tmp_bs->shared_no = bit + 1;
+ set_bit(bit, &shared_bits);
+ }
+ }
+ }
+}
+
+int bdrv_get_shared(BlockDriverState *bs)
+{
+ return bs->shared_no;
+}
+
/* Put this QMP function here so it can access the static graph_bdrv_states. */
BlockDeviceInfoList *bdrv_named_nodes_list(Error **errp)
{
@@ -2333,6 +2333,7 @@ static void scsi_realize(SCSIDevice *dev, Error **errp)
{
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
Error *err = NULL;
+ int port_no;
if (!s->qdev.conf.blk) {
error_setg(errp, "drive property not set");
@@ -2396,6 +2397,11 @@ static void scsi_realize(SCSIDevice *dev, Error **errp)
blk_set_guest_block_size(s->qdev.conf.blk, s->qdev.blocksize);
blk_iostatus_enable(s->qdev.conf.blk);
+ bdrv_find_shared(blk_bs(s->qdev.conf.blk));
+ port_no = bdrv_get_shared(blk_bs(s->qdev.conf.blk));
+ if (port_no && !s->port_index) {
+ s->port_index = port_no;
+ }
}
static void scsi_hd_realize(SCSIDevice *dev, Error **errp)
@@ -443,6 +443,8 @@ void bdrv_lock_medium(BlockDriverState *bs, bool locked);
void bdrv_eject(BlockDriverState *bs, bool eject_flag);
const char *bdrv_get_format_name(BlockDriverState *bs);
BlockDriverState *bdrv_find_node(const char *node_name);
+void bdrv_find_shared(BlockDriverState *bs);
+int bdrv_get_shared(BlockDriverState *bs);
BlockDeviceInfoList *bdrv_named_nodes_list(Error **errp);
BlockDriverState *bdrv_lookup_bs(const char *device,
const char *node_name,
@@ -634,6 +634,8 @@ struct BlockDriverState {
/* Flags honored during pwrite_zeroes (so far: BDRV_REQ_FUA,
* BDRV_REQ_MAY_UNMAP) */
unsigned int supported_zero_flags;
+ /* Shared instance count */
+ unsigned int shared_no;
/* the following member gives a name to every node on the bs graph. */
char node_name[32];
By setting 'locking=off' when creating a 'file' format drive one can simulate a multipath setup. This patch adds infrastructure for tracking shared block devices. Signed-off-by: Hannes Reinecke <hare@suse.com> --- block.c | 36 ++++++++++++++++++++++++++++++++++++ hw/scsi/scsi-disk.c | 6 ++++++ include/block/block.h | 2 ++ include/block/block_int.h | 2 ++ 4 files changed, 46 insertions(+)