mirror of
				https://github.com/qemu/qemu.git
				synced 2025-10-31 04:06:46 +00:00 
			
		
		
		
	nbd patches for 2019-06-13
- add 'qemu-nbd --pid-file' - NBD-related iotest improvements - NBD code refactoring in preparation for reconnect -----BEGIN PGP SIGNATURE----- iQEcBAABCAAGBQJdAm3WAAoJEKeha0olJ0NqEdMH/iXo+ps7bZNkO9JwEh15VUqQ tMDt+lZi3hi1p9u2V8uF6flWsnUWurIQ55r6WXRQj7r2LgZfRzeLCcgbsFA+6cXM ChA4HI9Q/3NdXhdNcyGcXfoZ3jPLJZYkUzaE5CbsRxsOm2Wi5xxDsXf4lcp4aJdm R2sfccPOFuwIQp09d/6NEA0TCxmfJLEw6KRbcAZ5UKSMnK0VXKF7ZMegM6meDQn8 mIjjkBAKhGN7q/8FOvluUmnkmGCp0uWfsAtmYCr8/qOSRoKaBFBlfzbAZu6jY9dZ yrEPs2RActPUHdYvFeLVOaEXlYTVOYG8NLdXM6Ilp0XDLuUAPkjZYP/VKPj/GzI= =JixR -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/ericb/tags/pull-nbd-2019-06-13' into staging nbd patches for 2019-06-13 - add 'qemu-nbd --pid-file' - NBD-related iotest improvements - NBD code refactoring in preparation for reconnect # gpg: Signature made Thu 13 Jun 2019 16:37:58 BST # gpg: using RSA key A7A16B4A2527436A # gpg: Good signature from "Eric Blake <eblake@redhat.com>" [full] # gpg: aka "Eric Blake (Free Software Programmer) <ebb9@byu.net>" [full] # gpg: aka "[jpeg image of size 6874]" [full] # Primary key fingerprint: 71C2 CC22 B1C4 6029 27D2 F3AA A7A1 6B4A 2527 436A * remotes/ericb/tags/pull-nbd-2019-06-13: block/nbd: merge NBDClientSession struct back to BDRVNBDState block/nbd: merge nbd-client.* to nbd.c block/nbd-client: drop stale logout nbd/server: Nicer spelling of max BLOCK_STATUS reply length iotests: Let 233 run concurrently iotests: Use qemu-nbd's --pid-file qemu-nbd: Do not close stderr iotests.py: Add qemu_nbd_early_pipe() qemu-nbd: Add --pid-file option Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
		
						commit
						d1bf88e56f
					
				| @ -22,7 +22,7 @@ block-obj-y += null.o mirror.o commit.o io.o create.o | ||||
| block-obj-y += throttle-groups.o | ||||
| block-obj-$(CONFIG_LINUX) += nvme.o | ||||
| 
 | ||||
| block-obj-y += nbd.o nbd-client.o | ||||
| block-obj-y += nbd.o | ||||
| block-obj-$(CONFIG_SHEEPDOG) += sheepdog.o | ||||
| block-obj-$(CONFIG_LIBISCSI) += iscsi.o | ||||
| block-obj-$(if $(CONFIG_LIBISCSI),y,n) += iscsi-opts.o | ||||
|  | ||||
							
								
								
									
										1226
									
								
								block/nbd-client.c
									
									
									
									
									
								
							
							
						
						
									
										1226
									
								
								block/nbd-client.c
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -1,71 +0,0 @@ | ||||
| #ifndef NBD_CLIENT_H | ||||
| #define NBD_CLIENT_H | ||||
| 
 | ||||
| #include "block/nbd.h" | ||||
| #include "block/block_int.h" | ||||
| #include "io/channel-socket.h" | ||||
| 
 | ||||
| /* #define DEBUG_NBD */ | ||||
| 
 | ||||
| #if defined(DEBUG_NBD) | ||||
| #define logout(fmt, ...) \ | ||||
|     fprintf(stderr, "nbd\t%-24s" fmt, __func__, ##__VA_ARGS__) | ||||
| #else | ||||
| #define logout(fmt, ...) ((void)0) | ||||
| #endif | ||||
| 
 | ||||
| #define MAX_NBD_REQUESTS    16 | ||||
| 
 | ||||
| typedef struct { | ||||
|     Coroutine *coroutine; | ||||
|     uint64_t offset;        /* original offset of the request */ | ||||
|     bool receiving;         /* waiting for connection_co? */ | ||||
| } NBDClientRequest; | ||||
| 
 | ||||
| typedef struct NBDClientSession { | ||||
|     QIOChannelSocket *sioc; /* The master data channel */ | ||||
|     QIOChannel *ioc; /* The current I/O channel which may differ (eg TLS) */ | ||||
|     NBDExportInfo info; | ||||
| 
 | ||||
|     CoMutex send_mutex; | ||||
|     CoQueue free_sema; | ||||
|     Coroutine *connection_co; | ||||
|     int in_flight; | ||||
| 
 | ||||
|     NBDClientRequest requests[MAX_NBD_REQUESTS]; | ||||
|     NBDReply reply; | ||||
|     BlockDriverState *bs; | ||||
|     bool quit; | ||||
| } NBDClientSession; | ||||
| 
 | ||||
| NBDClientSession *nbd_get_client_session(BlockDriverState *bs); | ||||
| 
 | ||||
| int nbd_client_init(BlockDriverState *bs, | ||||
|                     SocketAddress *saddr, | ||||
|                     const char *export_name, | ||||
|                     QCryptoTLSCreds *tlscreds, | ||||
|                     const char *hostname, | ||||
|                     const char *x_dirty_bitmap, | ||||
|                     Error **errp); | ||||
| void nbd_client_close(BlockDriverState *bs); | ||||
| 
 | ||||
| int nbd_client_co_pdiscard(BlockDriverState *bs, int64_t offset, int bytes); | ||||
| int nbd_client_co_flush(BlockDriverState *bs); | ||||
| int nbd_client_co_pwritev(BlockDriverState *bs, uint64_t offset, | ||||
|                           uint64_t bytes, QEMUIOVector *qiov, int flags); | ||||
| int nbd_client_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, | ||||
|                                 int bytes, BdrvRequestFlags flags); | ||||
| int nbd_client_co_preadv(BlockDriverState *bs, uint64_t offset, | ||||
|                          uint64_t bytes, QEMUIOVector *qiov, int flags); | ||||
| 
 | ||||
| void nbd_client_detach_aio_context(BlockDriverState *bs); | ||||
| void nbd_client_attach_aio_context(BlockDriverState *bs, | ||||
|                                    AioContext *new_context); | ||||
| 
 | ||||
| int coroutine_fn nbd_client_co_block_status(BlockDriverState *bs, | ||||
|                                             bool want_zero, | ||||
|                                             int64_t offset, int64_t bytes, | ||||
|                                             int64_t *pnum, int64_t *map, | ||||
|                                             BlockDriverState **file); | ||||
| 
 | ||||
| #endif /* NBD_CLIENT_H */ | ||||
							
								
								
									
										1284
									
								
								block/nbd.c
									
									
									
									
									
								
							
							
						
						
									
										1284
									
								
								block/nbd.c
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -160,11 +160,13 @@ nvme_cmd_map_qiov_iov(void *s, int i, void *page, int pages) "s %p iov[%d] %p pa | ||||
| # iscsi.c | ||||
| iscsi_xcopy(void *src_lun, uint64_t src_off, void *dst_lun, uint64_t dst_off, uint64_t bytes, int ret) "src_lun %p offset %"PRIu64" dst_lun %p offset %"PRIu64" bytes %"PRIu64" ret %d" | ||||
| 
 | ||||
| # nbd-client.c | ||||
| # nbd.c | ||||
| nbd_parse_blockstatus_compliance(const char *err) "ignoring extra data from non-compliant server: %s" | ||||
| nbd_structured_read_compliance(const char *type) "server sent non-compliant unaligned read %s chunk" | ||||
| nbd_read_reply_entry_fail(int ret, const char *err) "ret = %d, err: %s" | ||||
| nbd_co_request_fail(uint64_t from, uint32_t len, uint64_t handle, uint16_t flags, uint16_t type, const char *name, int ret, const char *err) "Request failed { .from = %" PRIu64", .len = %" PRIu32 ", .handle = %" PRIu64 ", .flags = 0x%" PRIx16 ", .type = %" PRIu16 " (%s) } ret = %d, err: %s" | ||||
| nbd_client_connect(const char *export_name) "export '%s'" | ||||
| nbd_client_connect_success(const char *export_name) "export '%s'" | ||||
| 
 | ||||
| # ssh.c | ||||
| ssh_restart_coroutine(void *co) "co=%p" | ||||
|  | ||||
							
								
								
									
										13
									
								
								nbd/server.c
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								nbd/server.c
									
									
									
									
									
								
							| @ -21,15 +21,18 @@ | ||||
| #include "qapi/error.h" | ||||
| #include "trace.h" | ||||
| #include "nbd-internal.h" | ||||
| #include "qemu/units.h" | ||||
| 
 | ||||
| #define NBD_META_ID_BASE_ALLOCATION 0 | ||||
| #define NBD_META_ID_DIRTY_BITMAP 1 | ||||
| 
 | ||||
| /* NBD_MAX_BITMAP_EXTENTS: 1 mb of extents data. An empirical
 | ||||
| /*
 | ||||
|  * NBD_MAX_BLOCK_STATUS_EXTENTS: 1 MiB of extents data. An empirical | ||||
|  * constant. If an increase is needed, note that the NBD protocol | ||||
|  * recommends no larger than 32 mb, so that the client won't consider | ||||
|  * the reply as a denial of service attack. */ | ||||
| #define NBD_MAX_BITMAP_EXTENTS (0x100000 / 8) | ||||
|  * the reply as a denial of service attack. | ||||
|  */ | ||||
| #define NBD_MAX_BLOCK_STATUS_EXTENTS (1 * MiB / 8) | ||||
| 
 | ||||
| static int system_errno_to_nbd_errno(int err) | ||||
| { | ||||
| @ -1960,7 +1963,7 @@ static int nbd_co_send_block_status(NBDClient *client, uint64_t handle, | ||||
|                                     Error **errp) | ||||
| { | ||||
|     int ret; | ||||
|     unsigned int nb_extents = dont_fragment ? 1 : NBD_MAX_BITMAP_EXTENTS; | ||||
|     unsigned int nb_extents = dont_fragment ? 1 : NBD_MAX_BLOCK_STATUS_EXTENTS; | ||||
|     NBDExtent *extents = g_new(NBDExtent, nb_extents); | ||||
|     uint64_t final_length = length; | ||||
| 
 | ||||
| @ -2045,7 +2048,7 @@ static int nbd_co_send_bitmap(NBDClient *client, uint64_t handle, | ||||
|                               uint32_t context_id, Error **errp) | ||||
| { | ||||
|     int ret; | ||||
|     unsigned int nb_extents = dont_fragment ? 1 : NBD_MAX_BITMAP_EXTENTS; | ||||
|     unsigned int nb_extents = dont_fragment ? 1 : NBD_MAX_BLOCK_STATUS_EXTENTS; | ||||
|     NBDExtent *extents = g_new(NBDExtent, nb_extents); | ||||
|     uint64_t final_length = length; | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										14
									
								
								qemu-nbd.c
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								qemu-nbd.c
									
									
									
									
									
								
							| @ -61,6 +61,7 @@ | ||||
| #define QEMU_NBD_OPT_IMAGE_OPTS    262 | ||||
| #define QEMU_NBD_OPT_FORK          263 | ||||
| #define QEMU_NBD_OPT_TLSAUTHZ      264 | ||||
| #define QEMU_NBD_OPT_PID_FILE      265 | ||||
| 
 | ||||
| #define MBR_SIZE 512 | ||||
| 
 | ||||
| @ -113,6 +114,7 @@ static void usage(const char *name) | ||||
| "                            specify tracing options\n" | ||||
| "  --fork                    fork off the server process and exit the parent\n" | ||||
| "                            once the server is running\n" | ||||
| "  --pid-file=PATH           store the server's process ID in the given file\n" | ||||
| #if HAVE_NBD_DEVICE | ||||
| "\n" | ||||
| "Kernel NBD client support:\n" | ||||
| @ -641,6 +643,7 @@ int main(int argc, char **argv) | ||||
|         { "image-opts", no_argument, NULL, QEMU_NBD_OPT_IMAGE_OPTS }, | ||||
|         { "trace", required_argument, NULL, 'T' }, | ||||
|         { "fork", no_argument, NULL, QEMU_NBD_OPT_FORK }, | ||||
|         { "pid-file", required_argument, NULL, QEMU_NBD_OPT_PID_FILE }, | ||||
|         { NULL, 0, NULL, 0 } | ||||
|     }; | ||||
|     int ch; | ||||
| @ -667,6 +670,7 @@ int main(int argc, char **argv) | ||||
|     bool list = false; | ||||
|     int old_stderr = -1; | ||||
|     unsigned socket_activation; | ||||
|     const char *pid_file_name = NULL; | ||||
| 
 | ||||
|     /* The client thread uses SIGTERM to interrupt the server.  A signal
 | ||||
|      * handler ensures that "qemu-nbd -v -c" exits with a nice status code. | ||||
| @ -866,6 +870,9 @@ int main(int argc, char **argv) | ||||
|         case 'L': | ||||
|             list = true; | ||||
|             break; | ||||
|         case QEMU_NBD_OPT_PID_FILE: | ||||
|             pid_file_name = optarg; | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -997,10 +1004,11 @@ int main(int argc, char **argv) | ||||
|             exit(EXIT_FAILURE); | ||||
|         } else if (pid == 0) { | ||||
|             close(stderr_fd[0]); | ||||
| 
 | ||||
|             old_stderr = dup(STDERR_FILENO); | ||||
|             ret = qemu_daemon(1, 0); | ||||
| 
 | ||||
|             /* Temporarily redirect stderr to the parent's pipe...  */ | ||||
|             old_stderr = dup(STDERR_FILENO); | ||||
|             dup2(stderr_fd[1], STDERR_FILENO); | ||||
|             if (ret < 0) { | ||||
|                 error_report("Failed to daemonize: %s", strerror(errno)); | ||||
| @ -1186,6 +1194,10 @@ int main(int argc, char **argv) | ||||
| 
 | ||||
|     nbd_update_server_watch(); | ||||
| 
 | ||||
|     if (pid_file_name) { | ||||
|         qemu_write_pidfile(pid_file_name, &error_fatal); | ||||
|     } | ||||
| 
 | ||||
|     /* now when the initialization is (almost) complete, chdir("/")
 | ||||
|      * to free any busy filesystems */ | ||||
|     if (chdir("/") < 0) { | ||||
|  | ||||
| @ -117,6 +117,8 @@ option; or provide the credentials needed for connecting as a client | ||||
| in list mode. | ||||
| @item --fork | ||||
| Fork off the server process and exit the parent once the server is running. | ||||
| @item --pid-file=PATH | ||||
| Store the server's process ID in the given file. | ||||
| @item --tls-authz=ID | ||||
| Specify the ID of a qauthz object previously created with the | ||||
| --object option. This will be used to authorize connecting users | ||||
|  | ||||
| @ -24,7 +24,7 @@ import socket | ||||
| import stat | ||||
| import time | ||||
| import iotests | ||||
| from iotests import cachemode, imgfmt, qemu_img, qemu_nbd, qemu_nbd_pipe | ||||
| from iotests import cachemode, imgfmt, qemu_img, qemu_nbd, qemu_nbd_early_pipe | ||||
| 
 | ||||
| NBD_PORT_START      = 32768 | ||||
| NBD_PORT_END        = NBD_PORT_START + 1024 | ||||
| @ -93,7 +93,7 @@ class QemuNBD(NBDBlockdevAddBase): | ||||
|             pass | ||||
| 
 | ||||
|     def _try_server_up(self, *args): | ||||
|         status, msg = qemu_nbd_pipe('-f', imgfmt, test_img, *args) | ||||
|         status, msg = qemu_nbd_early_pipe('-f', imgfmt, test_img, *args) | ||||
|         if status == 0: | ||||
|             return True | ||||
|         if 'Address already in use' in msg: | ||||
|  | ||||
| @ -49,7 +49,6 @@ _supported_proto file | ||||
| # If porting to non-Linux, consider using socat instead of ss in common.nbd | ||||
| _require_command QEMU_NBD | ||||
| 
 | ||||
| nbd_server_set_tcp_port | ||||
| tls_x509_init | ||||
| 
 | ||||
| echo | ||||
|  | ||||
| @ -22,6 +22,11 @@ | ||||
| nbd_unix_socket="${TEST_DIR}/qemu-nbd.sock" | ||||
| nbd_tcp_addr="127.0.0.1" | ||||
| nbd_pid_file="${TEST_DIR}/qemu-nbd.pid" | ||||
| nbd_stderr_fifo="${TEST_DIR}/qemu-nbd.fifo" | ||||
| 
 | ||||
| # If bash version is >= 4.1, this will be overwritten by a dynamically | ||||
| # assigned file descriptor value. | ||||
| nbd_fifo_fd=10 | ||||
| 
 | ||||
| nbd_server_stop() | ||||
| { | ||||
| @ -33,77 +38,62 @@ nbd_server_stop() | ||||
|             kill "$NBD_PID" | ||||
|         fi | ||||
|     fi | ||||
|     rm -f "$nbd_unix_socket" | ||||
| } | ||||
| 
 | ||||
| nbd_server_wait_for_unix_socket() | ||||
| { | ||||
|     pid=$1 | ||||
| 
 | ||||
|     for ((i = 0; i < 300; i++)) | ||||
|     do | ||||
|         if [ -r "$nbd_unix_socket" ]; then | ||||
|             return | ||||
|         fi | ||||
|         kill -s 0 $pid 2>/dev/null | ||||
|         if test $? != 0 | ||||
|         then | ||||
|             echo "qemu-nbd unexpectedly quit" | ||||
|             exit 1 | ||||
|         fi | ||||
|         sleep 0.1 | ||||
|     done | ||||
|     echo "Failed in check of unix socket created by qemu-nbd" | ||||
|     exit 1 | ||||
|     rm -f "$nbd_unix_socket" "$nbd_stderr_fifo" | ||||
| } | ||||
| 
 | ||||
| nbd_server_start_unix_socket() | ||||
| { | ||||
|     nbd_server_stop | ||||
|     $QEMU_NBD -v -t -k "$nbd_unix_socket" "$@" & | ||||
|     nbd_server_wait_for_unix_socket $! | ||||
| } | ||||
| 
 | ||||
| nbd_server_set_tcp_port() | ||||
| { | ||||
|     (ss --help) >/dev/null 2>&1 || _notrun "ss utility not found, skipping test" | ||||
| 
 | ||||
|     for ((port = 10809; port <= 10909; port++)) | ||||
|     do | ||||
|         if ! ss -tln | grep -sqE ":$port\b"; then | ||||
|             nbd_tcp_port=$port | ||||
|             return | ||||
|         fi | ||||
|     done | ||||
| 
 | ||||
|     echo "Cannot find free TCP port for nbd in range 10809-10909" | ||||
|     exit 1 | ||||
| } | ||||
| 
 | ||||
| nbd_server_wait_for_tcp_socket() | ||||
| { | ||||
|     pid=$1 | ||||
| 
 | ||||
|     for ((i = 0; i < 300; i++)) | ||||
|     do | ||||
|         if ss -tln | grep -sqE ":$nbd_tcp_port\b"; then | ||||
|             return | ||||
|         fi | ||||
|         kill -s 0 $pid 2>/dev/null | ||||
|         if test $? != 0 | ||||
|         then | ||||
|             echo "qemu-nbd unexpectedly quit" | ||||
|             exit 1 | ||||
|         fi | ||||
|         sleep 0.1 | ||||
|     done | ||||
|     echo "Failed in check of TCP socket created by qemu-nbd" | ||||
|     exit 1 | ||||
|     $QEMU_NBD -v -t -k "$nbd_unix_socket" --fork "$@" | ||||
| } | ||||
| 
 | ||||
| nbd_server_start_tcp_socket() | ||||
| { | ||||
|     nbd_server_stop | ||||
|     $QEMU_NBD -v -t -b $nbd_tcp_addr -p $nbd_tcp_port "$@" & | ||||
|     nbd_server_wait_for_tcp_socket $! | ||||
| 
 | ||||
|     mkfifo "$nbd_stderr_fifo" | ||||
|     for ((port = 10809; port <= 10909; port++)) | ||||
|     do | ||||
|         # Redirect stderr to FIFO, so we can later decide whether we | ||||
|         # want to read it or to redirect it to our stderr, depending | ||||
|         # on whether the command fails or not | ||||
|         $QEMU_NBD -v -t -b $nbd_tcp_addr -p $port --fork "$@" \ | ||||
|             2> "$nbd_stderr_fifo" & | ||||
| 
 | ||||
|         # Taken from common.qemu | ||||
|         if [[ "${BASH_VERSINFO[0]}" -ge "5" || | ||||
|             ("${BASH_VERSINFO[0]}" -ge "4" && "${BASH_VERSINFO[1]}" -ge "1") ]] | ||||
|         then | ||||
|             exec {nbd_fifo_fd}<"$nbd_stderr_fifo" | ||||
|         else | ||||
|             let _nbd_fifo_fd++ | ||||
|             eval "exec ${_nbd_fifo_fd}<'$nbd_stderr_fifo'" | ||||
|         fi | ||||
|         wait $! | ||||
| 
 | ||||
|         if test $? == 0 | ||||
|         then | ||||
|             # Success, redirect qemu-nbd's stderr to our stderr | ||||
|             nbd_tcp_port=$port | ||||
|             (cat <&$nbd_fifo_fd >&2) & | ||||
|             eval "exec $nbd_fifo_fd>&-" | ||||
|             return | ||||
|         fi | ||||
| 
 | ||||
|         # Failure, read the output | ||||
|         output=$(cat <&$nbd_fifo_fd) | ||||
|         eval "exec $nbd_fifo_fd>&-" | ||||
| 
 | ||||
|         if ! echo "$output" | grep -q "Address already in use" | ||||
|         then | ||||
|             # Unknown error, print it | ||||
|             echo "$output" >&2 | ||||
|             rm -f "$nbd_stderr_fifo" | ||||
|             exit 1 | ||||
|         fi | ||||
|     done | ||||
| 
 | ||||
|     echo "Cannot find free TCP port for nbd in range 10809-10909" | ||||
|     rm -f "$nbd_stderr_fifo" | ||||
|     exit 1 | ||||
| } | ||||
|  | ||||
| @ -105,10 +105,8 @@ _qemu_io_wrapper() | ||||
| 
 | ||||
| _qemu_nbd_wrapper() | ||||
| { | ||||
|     ( | ||||
|         echo $BASHPID > "${QEMU_TEST_DIR}/qemu-nbd.pid" | ||||
|         exec "$QEMU_NBD_PROG" $QEMU_NBD_OPTIONS "$@" | ||||
|     ) | ||||
|     "$QEMU_NBD_PROG" --pid-file="${QEMU_TEST_DIR}/qemu-nbd.pid" \ | ||||
|                      $QEMU_NBD_OPTIONS "$@" | ||||
| } | ||||
| 
 | ||||
| _qemu_vxhs_wrapper() | ||||
|  | ||||
| @ -209,9 +209,9 @@ def qemu_nbd(*args): | ||||
|     '''Run qemu-nbd in daemon mode and return the parent's exit code''' | ||||
|     return subprocess.call(qemu_nbd_args + ['--fork'] + list(args)) | ||||
| 
 | ||||
| def qemu_nbd_pipe(*args): | ||||
| def qemu_nbd_early_pipe(*args): | ||||
|     '''Run qemu-nbd in daemon mode and return both the parent's exit code | ||||
|        and its output''' | ||||
|        and its output in case of an error''' | ||||
|     subp = subprocess.Popen(qemu_nbd_args + ['--fork'] + list(args), | ||||
|                             stdout=subprocess.PIPE, | ||||
|                             stderr=subprocess.STDOUT, | ||||
| @ -221,7 +221,10 @@ def qemu_nbd_pipe(*args): | ||||
|         sys.stderr.write('qemu-nbd received signal %i: %s\n' % | ||||
|                          (-exitcode, | ||||
|                           ' '.join(qemu_nbd_args + ['--fork'] + list(args)))) | ||||
|     return exitcode, subp.communicate()[0] | ||||
|     if exitcode == 0: | ||||
|         return exitcode, '' | ||||
|     else: | ||||
|         return exitcode, subp.communicate()[0] | ||||
| 
 | ||||
| def compare_images(img1, img2, fmt1=imgfmt, fmt2=imgfmt): | ||||
|     '''Return True if two image files are identical''' | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Peter Maydell
						Peter Maydell