qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] How to introduce bs->node_name ?


From: Fam Zheng
Subject: Re: [Qemu-devel] How to introduce bs->node_name ?
Date: Tue, 29 Oct 2013 09:03:27 +0800
User-agent: Mutt/1.5.21 (2010-09-15)

On Mon, 10/28 16:40, Benoît Canet wrote:
> 
> Hi list,
> 
> After a discussion on irc we have two potential solution in order to introduce
> a new bs->node_name member in order to be able to manipulate the graph from 
> the
> monitors.
> 
> The first one is to make the QMP device parameter of the block commands 
> optional
> and add the node-name parameter as a second optional parameter.
> This is Markus prefered solution and Eric is ok with making mandatory 
> parameters
> optional in QMP.
> 
> The second one suggested by Kevin Would be to add some magic to the new
> node_name member by making it equal to device_name for backends and then 
> making
> the qmp commands operate only on node-names.
> My personnal suggestion would be that non specified node-name would be set to
> "undefined" meaning that no operation could occur on this bs.
> 
> For QMP access the device_name is accessed via bdrv_find() in a few place in
> blockdev.
> 
> Here are the occurences of it:
> 
> commit
> ------
> void do_commit(Monitor *mon, const QDict *qdict)
> {
>     const char *device = qdict_get_str(qdict, "device");
>     BlockDriverState *bs;
>     int ret;
> 
>     if (!strcmp(device, "all")) {
>         ret = bdrv_commit_all();
>     } else {
>         bs = bdrv_find(device);
>         if (!bs) {
>             monitor_printf(mon, "Device '%s' not found\n", device);
>             return;
>         }
>         ret = bdrv_commit(bs);
>     }
>     if (ret < 0) {
>         monitor_printf(mon, "'commit' error for '%s': %s\n", device,
>                        strerror(-ret));
>     }
> }
> 
> internal snapshot deletion
> --------------------------
> SnapshotInfo *qmp_blockdev_snapshot_delete_internal_sync(const char *device,
>                                                          bool has_id,
>                                                          const char *id,
>                                                          bool has_name,
>                                                          const char *name,
>                                                          Error **errp)
> {
>     BlockDriverState *bs = bdrv_find(device);
>     QEMUSnapshotInfo sn;
>     Error *local_err = NULL;
>     SnapshotInfo *info = NULL;
> 
> 
> Internal snapshot preparation
> -----------------------------
> static void internal_snapshot_prepare(BlkTransactionState *common,
>                                       Error **errp)
> {
>     const char *device;
>     const char *name;
> 
> BlockDriverState *bs;
>     QEMUSnapshotInfo old_sn, *sn;
>     bool ret;
>     qemu_timeval tv;
>     BlockdevSnapshotInternal *internal;
>     InternalSnapshotState *state;
>     int ret1;
> 
>     g_assert(common->action->kind ==
>              TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_INTERNAL_SYNC);
>     internal = common->action->blockdev_snapshot_internal_sync;
>     state = DO_UPCAST(InternalSnapshotState, common, common);
> 
>     /* 1. parse input */
>     device = internal->device;
>     name = internal->name;
> 
>     /* 2. check for validation */
>     bs = bdrv_find(device);
>     if (!bs) {
>         error_set(errp, QERR_DEVICE_NOT_FOUND, device);
>         return;
>     }
> 
> Drive backup
> ------------
> static void drive_backup_prepare(BlkTransactionState *common, Error **errp)
> {
>     DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common);
>     DriveBackup *backup;
>     Error *local_err = NULL;
> 
>     assert(common->action->kind == TRANSACTION_ACTION_KIND_DRIVE_BACKUP);
>     backup = common->action->drive_backup;
> 
>     qmp_drive_backup(backup->device, backup->target,
>                      backup->has_format, backup->format,
>                      backup->sync,
>                      backup->has_mode, backup->mode,
>                      backup->has_speed, backup->speed,
>                      backup->has_on_source_error, backup->on_source_error,
>                      backup->has_on_target_error, backup->on_target_error,
>                      &local_err);
>     if (error_is_set(&local_err)) {
>         error_propagate(errp, local_err);
>         state->bs = NULL;
>         state->job = NULL;
>         return;
>     }
> 
>     state->bs = bdrv_find(backup->device);
>     state->job = state->bs->job;
> }
> 
> Eject which should operate on backends
> --------------------------------------
> void qmp_eject(const char *device, bool has_force, bool force, Error **errp)
> {
>     BlockDriverState *bs;
> 
>     bs = bdrv_find(device);
>     if (!bs) {
>         error_set(errp, QERR_DEVICE_NOT_FOUND, device);
>         return;
>     }
> 
>     eject_device(bs, force, errp);
> }
> 
> QCow2 crypto
> ------------
> void qmp_block_passwd(const char *device, const char *password, Error **errp)
> {
>     BlockDriverState *bs;
>     int err;
> 
>     bs = bdrv_find(device);
>     if (!bs) {
>         error_set(errp, QERR_DEVICE_NOT_FOUND, device);
>         return;
>     }
> 
>     err = bdrv_set_key(bs, password);
>     if (err == -EINVAL) {
>         error_set(errp, QERR_DEVICE_NOT_ENCRYPTED, bdrv_get_device_name(bs));
>         return;
>     } else if (err < 0) {
>         error_set(errp, QERR_INVALID_PASSWORD);
>         return;
>     }
> }
> 
> Change blockdev (I don't know what it is used for)
> --------------------------------------------------
> void qmp_change_blockdev(const char *device, const char *filename,
>                          bool has_format, const char *format, Error **errp)
> {
>     BlockDriverState *bs;
>     BlockDriver *drv = NULL;
>     int bdrv_flags;
>     Error *err = NULL;
> 
>     bs = bdrv_find(device);
>     if (!bs) {
>         error_set(errp, QERR_DEVICE_NOT_FOUND, device);
>         return;
>     }
> 
>     if (format) {
>         drv = bdrv_find_whitelisted_format(format, bs->read_only);
>         if (!drv) {
>             error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);
>             return;
>         }
>     }
> 
>     eject_device(bs, 0, &err);
>     if (error_is_set(&err)) {
>         error_propagate(errp, err);
>         return;
>     }
> 
>     bdrv_flags = bdrv_is_read_only(bs) ? 0 : BDRV_O_RDWR;
>     bdrv_flags |= bdrv_is_snapshot(bs) ? BDRV_O_SNAPSHOT : 0;
> 
>     qmp_bdrv_open_encrypted(bs, filename, bdrv_flags, drv, NULL, errp);
> }
> 
> Throttling
> ----------
> void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t 
> bps_rd,
>                                int64_t bps_wr,
>                                int64_t iops,
>                                int64_t iops_rd,
>                                int64_t iops_wr,
>                                bool has_bps_max,
>                                int64_t bps_max,
>                                bool has_bps_rd_max,
>                                int64_t bps_rd_max,
>                                bool has_bps_wr_max,
>                                int64_t bps_wr_max,
>                                bool has_iops_max,
>                                int64_t iops_max,
>                                bool has_iops_rd_max,
>                                int64_t iops_rd_max,
>                                bool has_iops_wr_max,
>                                int64_t iops_wr_max,
>                                bool has_iops_size,
>                                int64_t iops_size, Error **errp)
> {
>     ThrottleConfig cfg;
>     BlockDriverState *bs;
> 
>     bs = bdrv_find(device);
>     if (!bs) {
>         error_set(errp, QERR_DEVICE_NOT_FOUND, device);
>         return;
>     }
> 
> Drive deletion
> --------------
> int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
> {
>     const char *id = qdict_get_str(qdict, "id");
>     BlockDriverState *bs;
> 
>     bs = bdrv_find(id);
>     if (!bs) {
>         qerror_report(QERR_DEVICE_NOT_FOUND, id);
>         return -1;
>     }
> 
> block resize
> ------------
> void qmp_block_resize(const char *device, int64_t size, Error **errp)
> {
>     BlockDriverState *bs;
>     int ret;
> 
>     bs = bdrv_find(device);
>     if (!bs) {
>         error_set(errp, QERR_DEVICE_NOT_FOUND, device);
>         return;
>     }
> 
> streaming
> ---------
> void qmp_block_stream(const char *device, bool has_base,
>                       const char *base, bool has_speed, int64_t speed,
>                       bool has_on_error, BlockdevOnError on_error,
>                       Error **errp)
> {
>     BlockDriverState *bs;
>     BlockDriverState *base_bs = NULL;
>     Error *local_err = NULL;
> 
>     if (!has_on_error) {
>         on_error = BLOCKDEV_ON_ERROR_REPORT;
>     }
> 
>     bs = bdrv_find(device);
>     if (!bs) {
>         error_set(errp, QERR_DEVICE_NOT_FOUND, device);
>         return;
>     }
> 
> commit
> ------
> void qmp_block_commit(const char *device,
>                       bool has_base, const char *base, const char *top,
>                       bool has_speed, int64_t speed,
>                       Error **errp)
> {
>     BlockDriverState *bs;
>     BlockDriverState *base_bs, *top_bs;
>     Error *local_err = NULL;
>     /* This will be part of the QMP command, if/when the
>      * BlockdevOnError change for blkmirror makes it in
>      */
>     BlockdevOnError on_error = BLOCKDEV_ON_ERROR_REPORT;
> 
>     /* drain all i/o before commits */
>     bdrv_drain_all();
> 
>     bs = bdrv_find(device);
>     if (!bs) {
>         error_set(errp, QERR_DEVICE_NOT_FOUND, device);
>         return;
>     }
> 
> 
> backup:
> -------
> void qmp_drive_backup(const char *device, const char *target,
>                       bool has_format, const char *format,
>                       enum MirrorSyncMode sync,
>                       bool has_mode, enum NewImageMode mode,
>                       bool has_speed, int64_t speed,
>                       bool has_on_source_error, BlockdevOnError 
> on_source_error,
>                       bool has_on_target_error, BlockdevOnError 
> on_target_error,
>                       Error **errp)
> {
>     BlockDriverState *bs;
>     BlockDriverState *target_bs;
>     BlockDriverState *source = NULL;
>     BlockDriver *drv = NULL;
>     Error *local_err = NULL;
>     int flags;
>     int64_t size;
>     int ret;
> 
>     if (!has_speed) {
>         speed = 0;
>     }
>     if (!has_on_source_error) {
>         on_source_error = BLOCKDEV_ON_ERROR_REPORT;
>     }
>     if (!has_on_target_error) {
>         on_target_error = BLOCKDEV_ON_ERROR_REPORT;
>     }
>     if (!has_mode) {
>         mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
>     }
> 
>     bs = bdrv_find(device);
>     if (!bs) {
>         error_set(errp, QERR_DEVICE_NOT_FOUND, device);
>         return;
>     }
> 
> 
> mirror
> ------
> void qmp_drive_mirror(const char *device, const char *target,
>                       bool has_format, const char *format,
>                       enum MirrorSyncMode sync,
>                       bool has_mode, enum NewImageMode mode,
>                       bool has_speed, int64_t speed,
>                       bool has_granularity, uint32_t granularity,
>                       bool has_buf_size, int64_t buf_size,
>                       bool has_on_source_error, BlockdevOnError 
> on_source_error,
>                       bool has_on_target_error, BlockdevOnError 
> on_target_error,
>                       Error **errp)
> {
>     BlockDriverState *bs;
>     BlockDriverState *source, *target_bs;
>     BlockDriver *drv = NULL;
>     Error *local_err = NULL;
>     int flags;
>     int64_t size;
>     int ret;
> 
>     if (!has_speed) {
>         speed = 0;
>     }
>     if (!has_on_source_error) {
>         on_source_error = BLOCKDEV_ON_ERROR_REPORT;
>     }
>     if (!has_on_target_error) {
>         on_target_error = BLOCKDEV_ON_ERROR_REPORT;
>     }
>     if (!has_mode) {
>         mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
>     }
>     if (!has_granularity) {
>         granularity = 0;
>     }
>     if (!has_buf_size) {
>         buf_size = DEFAULT_MIRROR_BUF_SIZE;
>     }
> 
>     if (granularity != 0 && (granularity < 512 || granularity > 1048576 * 
> 64)) {
>         error_set(errp, QERR_INVALID_PARAMETER, device);
>         return;
>     }
>     if (granularity & (granularity - 1)) {
>         error_set(errp, QERR_INVALID_PARAMETER, device);
>         return;
>     }
> 
>     bs = bdrv_find(device);
>     if (!bs) {
>         error_set(errp, QERR_DEVICE_NOT_FOUND, device);
>         return;
>     }
> 
> find block job
> --------------
> static BlockJob *find_block_job(const char *device)
> {
>     BlockDriverState *bs;
> 
>     bs = bdrv_find(device);
>     if (!bs || !bs->job) {
>         return NULL;
>     }
>     return bs->job;
> }
> 

And nbd-server-add.

> Very few of them operate on what is destined to become block backend and most 
> of
> them should be able to operate on nodes of the graph;
> 
> What solution do you prefer ?

My feeling is not to distinguish node-name and device-name, with the same
reason as above: most of them should be able to operate on nodes of the graph.
So I prefer we don't touch the qmp interface. We can always introduce optional
parameter and make mandatory ones optional, if necessary. But for now, just
equalize node-name and device-name should be neater from a users view.  If a
command is only for backend, we can check internally and report error if the
provided node is not.

Thanks,

Fam



reply via email to

[Prev in Thread] Current Thread [Next in Thread]