From patchwork Mon May 25 15:44:23 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lukas Straub X-Patchwork-Id: 1297412 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=web.de Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; secure) header.d=web.de header.i=@web.de header.a=rsa-sha256 header.s=dbaedf251592 header.b=iGNf9bwR; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49W1r71DkWz9sSd for ; Tue, 26 May 2020 01:54:46 +1000 (AEST) Received: from localhost ([::1]:45014 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jdFR4-0000uf-FX for incoming@patchwork.ozlabs.org; Mon, 25 May 2020 11:54:43 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:58904) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jdFHC-0004ya-KV; Mon, 25 May 2020 11:44:30 -0400 Received: from mout.web.de ([212.227.15.4]:43089) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jdFHB-0006cj-ET; Mon, 25 May 2020 11:44:30 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=web.de; s=dbaedf251592; t=1590421464; bh=MpS5nTcWOHXIi2EaTcyTwqG+3V2LQAXwFT5hRywBgQQ=; h=X-UI-Sender-Class:Date:From:To:Cc:Subject:In-Reply-To:References; b=iGNf9bwRQLIqEP1Mj5Il6TNmFkN7K2SrudELejOFb9rOubqNyjeZZjOaPC8cSRkLf 03+J5ZH7BwsR3RdegRXlj1GjFApqipt8ohS5z8WJhLXUCj8p5tFiS6NlUbi94mntFr mJK3U6PV5hPaHx1hnKGr27fPioGYN+c0lBBHKqJI= X-UI-Sender-Class: c548c8c5-30a9-4db5-a2e7-cb6cb037b8f9 Received: from luklap ([94.134.180.22]) by smtp.web.de (mrweb002 [213.165.67.108]) with ESMTPSA (Nemesis) id 0Lu5BO-1ivYBq1dcU-011QrO; Mon, 25 May 2020 17:44:24 +0200 Date: Mon, 25 May 2020 17:44:23 +0200 From: Lukas Straub To: qemu-devel Subject: [PATCH v4 1/4] Introduce yank feature Message-ID: In-Reply-To: References: MIME-Version: 1.0 X-Provags-ID: V03:K1:uO5EXCVTxC9hgMvxGWeRc3B9toqiS8jW+mdam3UStknHQyNmHAE ydPVyXeFCU1Ijho8B/Z1Y004SxezGBwnoq6CEKrn4b0SNNzwBXR7M7Ku/Xt0SeQ1lmoDTGG BjcQJy2djT//63EO7ww9bClnc0B8nq+3hhzAmY9Em7BjKZqbuDc35oECJgRTKncGLm6IyBb uha+AyzmQe66XIgIOdt1w== X-UI-Out-Filterresults: notjunk:1;V03:K0:Qc8KxK+S/JU=:6juDCBc3GNi9MIwJYGH8Ly SyzPFRf+rPgFSt/MDowJVR6VDQIV40reqPf8WAo6yC9goyPqKYBAjKlAmz+3t36ELqna+rihG dY8lJicPrgD02k2wSuiY9eqjBJLbi18ZxyfaB6tjU+Y5wGSOUrvcjRFAjKAlVnlIoJ8KlZmuW bstfAJHtQ3D2SfGBkT8SjlsLJ4J6aNmdAxEdvmd3j7iFGXazO3v39tg1ZSqV/y4oY4NSQ9n4t QWxwcb4FJLbRy9PjYEYuUyVSJLT/3QtbUsY8JiMRcPfbIhS2pitjuUmkFvRzyB3N87zwT7o8T Ncq87GL1detdHFuKepE/vSyrlA57WtRh4irtfGXL4bDAR0TogA1d8cXScm9UqwKzltRhe5hl3 lMmx95DudzsYP8gvulkhaycayVMAu6aIh3aDXL8VoqHWFzQ7k45KZ6T/Avu/H6E5EQrkm6YT0 MfYF876ep+LgpUkVBo8nUtKUGVOaKE4T5e4pDHWO7/m6vJ7mEipNqo2JrMydIn2gjIqcAkeEP LI3n1ZHHLexurwlj88EXBZ6XjOxNUCFP6LpLngcxaOjJRjzcll++qqB8NbX1f/G2Ih5r0GhZJ h/Z63B6aZcjM67YJAC7L4dOpoKT1/QzzWg43Rz3T23Ojm3fhWDIVCS3/c6veVH8oPoYV5BjKh n8oJAC427txAWEmcIvNViIhVSSRiMLJbK+RqbWNliBH7krHjn5wJnT0HbHiUCkZkmgbg+FzpR kNcWuD/MYSCakfg+w0bsngoGZDJQth7JK/JjFU0DVGGOdyPOW2P+504spOVq6o2kI4Htq2rby qotYpngfXPHqhvqPSsjeyF5yzjgdT7lO6idlsftGYRpXbRzGO4XQaac6kqNnDmXvkKu/hrOlB Sl/f7dtrcIMtpGfgG9liheRaHgY+ODu9BcV1KpCliYrLMbKmmsiLxl8YMvVzWuexylYtcQe2+ p7AtnEQf8+wFcHZFMsUHp7bnLDfswLdrmT72nMoNWAQi7h4dVCKtC4B8mkjPiEsnVrdBHpkgU WHrN/oi8Hlq6cYsw1F55IhvAR22XYO28GL6XSV/GLoPw1i4tqQvNmCcybB5lwyFFAyIsCuuPI 4FBHbuk4QyOlU3RKA1abq4j7bUPgIp5lEITkFDAAHu8HS50Bg0hNOn6/3ecB3Q/IscXXMQJWD xrfvn7fUha8+OJ/y7i+LQTsWNsmYwjZZEfA4v+zP98RfZmxOC312yBbRBZ5Im/CN0CQEhnbDO ebz2eAL44MSJMyNTj Received-SPF: pass client-ip=212.227.15.4; envelope-from=lukasstraub2@web.de; helo=mout.web.de X-detected-operating-system: by eggs.gnu.org: First seen = 2020/05/25 11:44:28 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] X-Spam_score_int: -24 X-Spam_score: -2.5 X-Spam_bar: -- X-Spam_report: (-2.5 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_PASS=-0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , "Daniel P. =?utf-8?b?QmVycmFuZ8Op?= " , qemu-block , Juan Quintela , "Dr. David Alan Gilbert" , Max Reitz , Paolo Bonzini , =?utf-8?q?Marc-Andr=C3=A9?= Lureau Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" The yank feature allows to recover from hanging qemu by "yanking" at various parts. Other qemu systems can register themselves and multiple yank functions. Then all yank functions for selected instances can be called by the 'yank' out-of-band qmp command. Available instances can be queried by a 'query-yank' oob command. Signed-off-by: Lukas Straub --- qapi/misc.json | 45 +++++++++++++ yank.c | 174 +++++++++++++++++++++++++++++++++++++++++++++++++ yank.h | 67 +++++++++++++++++++ 3 files changed, 286 insertions(+) create mode 100644 yank.c create mode 100644 yank.h -- 2.20.1 diff --git a/qapi/misc.json b/qapi/misc.json index 99b90ac80b..f5228b2502 100644 --- a/qapi/misc.json +++ b/qapi/misc.json @@ -1550,3 +1550,48 @@ ## { 'command': 'query-vm-generation-id', 'returns': 'GuidInfo' } +## +# @YankInstances: +# +# @instances: List of yank instances. +# +# Yank instances are named after the following schema: +# "blockdev:", "chardev:" and "migration" +# +# Since: 5.1 +## +{ 'struct': 'YankInstances', 'data': {'instances': ['str'] } } + +## +# @yank: +# +# Recover from hanging qemu by yanking the specified instances. +# +# Takes @YankInstances as argument. +# +# Returns: nothing. +# +# Example: +# +# -> { "execute": "yank", "arguments": { "instances": ["blockdev:nbd0"] } } +# <- { "return": {} } +# +# Since: 5.1 +## +{ 'command': 'yank', 'data': 'YankInstances', 'allow-oob': true } + +## +# @query-yank: +# +# Query yank instances. +# +# Returns: @YankInstances +# +# Example: +# +# -> { "execute": "query-yank" } +# <- { "return": { "instances": ["blockdev:nbd0"] } } +# +# Since: 5.1 +## +{ 'command': 'query-yank', 'returns': 'YankInstances', 'allow-oob': true } diff --git a/yank.c b/yank.c new file mode 100644 index 0000000000..36d8139d4d --- /dev/null +++ b/yank.c @@ -0,0 +1,174 @@ +/* + * QEMU yank feature + * + * Copyright (c) Lukas Straub + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qemu/thread.h" +#include "qemu/queue.h" +#include "qapi/qapi-commands-misc.h" +#include "io/channel.h" +#include "yank.h" + +struct YankFuncAndParam { + YankFn *func; + void *opaque; + QLIST_ENTRY(YankFuncAndParam) next; +}; + +struct YankInstance { + char *name; + QLIST_HEAD(, YankFuncAndParam) yankfns; + QLIST_ENTRY(YankInstance) next; +}; + +static QemuMutex lock; +static QLIST_HEAD(yankinst_list, YankInstance) head + = QLIST_HEAD_INITIALIZER(head); + +static struct YankInstance *yank_find_instance(char *name) +{ + struct YankInstance *tmp, *instance; + instance = NULL; + QLIST_FOREACH(tmp, &head, next) { + if (!strcmp(tmp->name, name)) { + instance = tmp; + } + } + return instance; +} + +void yank_register_instance(char *instance_name) +{ + struct YankInstance *instance; + + qemu_mutex_lock(&lock); + assert(!yank_find_instance(instance_name)); + + instance = g_slice_new(struct YankInstance); + instance->name = g_strdup(instance_name); + QLIST_INIT(&instance->yankfns); + QLIST_INSERT_HEAD(&head, instance, next); + + qemu_mutex_unlock(&lock); +} + +void yank_unregister_instance(char *instance_name) +{ + struct YankInstance *instance; + + qemu_mutex_lock(&lock); + instance = yank_find_instance(instance_name); + assert(instance); + + assert(QLIST_EMPTY(&instance->yankfns)); + QLIST_REMOVE(instance, next); + g_free(instance->name); + g_slice_free(struct YankInstance, instance); + + qemu_mutex_unlock(&lock); +} + +void yank_register_function(char *instance_name, YankFn *func, void *opaque) +{ + struct YankInstance *instance; + struct YankFuncAndParam *entry; + + qemu_mutex_lock(&lock); + instance = yank_find_instance(instance_name); + assert(instance); + + entry = g_slice_new(struct YankFuncAndParam); + entry->func = func; + entry->opaque = opaque; + + QLIST_INSERT_HEAD(&instance->yankfns, entry, next); + qemu_mutex_unlock(&lock); +} + +void yank_unregister_function(char *instance_name, YankFn *func, void *opaque) +{ + struct YankInstance *instance; + struct YankFuncAndParam *entry; + + qemu_mutex_lock(&lock); + instance = yank_find_instance(instance_name); + assert(instance); + + QLIST_FOREACH(entry, &instance->yankfns, next) { + if (entry->func == func && entry->opaque == opaque) { + QLIST_REMOVE(entry, next); + g_slice_free(struct YankFuncAndParam, entry); + qemu_mutex_unlock(&lock); + return; + } + } + + abort(); +} + +void yank_generic_iochannel(void *opaque) +{ + QIOChannel *ioc = QIO_CHANNEL(opaque); + + qio_channel_shutdown(ioc, QIO_CHANNEL_SHUTDOWN_BOTH, NULL); +} + +void qmp_yank(strList *instances, Error **errp) +{ + strList *tmp; + struct YankInstance *instance; + struct YankFuncAndParam *entry; + + qemu_mutex_lock(&lock); + tmp = instances; + for (; tmp; tmp = tmp->next) { + instance = yank_find_instance(tmp->value); + if (!instance) { + error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, + "Instance '%s' not found", tmp->value); + qemu_mutex_unlock(&lock); + return; + } + } + tmp = instances; + for (; tmp; tmp = tmp->next) { + instance = yank_find_instance(tmp->value); + assert(instance); + QLIST_FOREACH(entry, &instance->yankfns, next) { + entry->func(entry->opaque); + } + } + qemu_mutex_unlock(&lock); +} + +YankInstances *qmp_query_yank(Error **errp) +{ + struct YankInstance *instance; + YankInstances *ret; + + ret = g_new0(YankInstances, 1); + ret->instances = NULL; + + qemu_mutex_lock(&lock); + QLIST_FOREACH(instance, &head, next) { + strList *entry; + entry = g_new0(strList, 1); + entry->value = g_strdup(instance->name); + entry->next = ret->instances; + ret->instances = entry; + } + qemu_mutex_unlock(&lock); + + return ret; +} + +static void __attribute__((__constructor__)) yank_init(void) +{ + qemu_mutex_init(&lock); +} diff --git a/yank.h b/yank.h new file mode 100644 index 0000000000..f1c8743b72 --- /dev/null +++ b/yank.h @@ -0,0 +1,67 @@ + +#ifndef YANK_H +#define YANK_H + +typedef void (YankFn) (void *opaque); + +/** + * yank_register_instance: Register a new instance. + * + * This registers a new instance for yanking. Must be called before any yank + * function is registered for this instance. + * + * This function is thread-safe. + * + * @instance_name: The globally unique name of the instance. + */ +void yank_register_instance(char *instance_name); + +/** + * yank_unregister_instance: Unregister a instance. + * + * This unregisters a instance. Must be called only after every yank function + * of the instance has been unregistered. + * + * This function is thread-safe. + * + * @instance_name: The name of the instance. + */ +void yank_unregister_instance(char *instance_name); + +/** + * yank_register_function: Register a yank function + * + * This registers a yank function. All limitations of qmp oob commands apply + * to the yank function as well. + * + * This function is thread-safe. + * + * @instance_name: The name of the instance + * @func: The yank function + * @opaque: Will be passed to the yank function + */ +void yank_register_function(char *instance_name, YankFn *func, void *opaque); + +/** + * yank_unregister_function: Unregister a yank function + * + * This unregisters a yank function. + * + * This function is thread-safe. + * + * @instance_name: The name of the instance + * @func: func that was passed to yank_register_function + * @opaque: opaque that was passed to yank_register_function + */ +void yank_unregister_function(char *instance_name, YankFn *func, void *opaque); + +/** + * yank_unregister_function: Generic yank function for iochannel + * + * This is a generic yank function which will call qio_channel_shutdown on the + * provided QIOChannel. + * + * @opaque: QIOChannel to shutdown + */ +void yank_generic_iochannel(void *opaque); +#endif From patchwork Mon May 25 15:44:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Lukas Straub X-Patchwork-Id: 1297406 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=web.de Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; secure) header.d=web.de header.i=@web.de header.a=rsa-sha256 header.s=dbaedf251592 header.b=oGagybgk; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49W1gg18gFz9sSd for ; Tue, 26 May 2020 01:47:26 +1000 (AEST) Received: from localhost ([::1]:38124 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jdFJy-00065Q-2W for incoming@patchwork.ozlabs.org; Mon, 25 May 2020 11:47:22 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:58914) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jdFHI-000528-5B; Mon, 25 May 2020 11:44:36 -0400 Received: from mout.web.de ([217.72.192.78]:58053) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jdFHF-0006cz-G3; Mon, 25 May 2020 11:44:35 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=web.de; s=dbaedf251592; t=1590421468; bh=Spsqn3Js/ye6hJIlQ74t30HGMoZTUOMLYkK7TW3O+Ts=; h=X-UI-Sender-Class:Date:From:To:Cc:Subject:In-Reply-To:References; b=oGagybgkmWIrm6ZvEx3uNFB1+oBoVlMk6xQjLrhoaMNctKC4Sc9iF4V/cpQ6cDQOc 4SMvPqNaFFqAJrLyuIgg1uMG6ANDiSxw0cakVwHX4sRV1PIaYriaEUktcY4nPneEPE UXj372++1lvmI9OUPV1MAy2mUylm/682X+iGxP8k= X-UI-Sender-Class: c548c8c5-30a9-4db5-a2e7-cb6cb037b8f9 Received: from luklap ([94.134.180.22]) by smtp.web.de (mrweb101 [213.165.67.124]) with ESMTPSA (Nemesis) id 0Lh6UN-1jHMKK3Z9L-00oSok; Mon, 25 May 2020 17:44:27 +0200 Date: Mon, 25 May 2020 17:44:26 +0200 From: Lukas Straub To: qemu-devel Subject: [PATCH v4 2/4] block/nbd.c: Add yank feature Message-ID: <8e6a8e61b25813cdcdf385729709ef57f6255a3e.1590421341.git.lukasstraub2@web.de> In-Reply-To: References: MIME-Version: 1.0 X-Provags-ID: V03:K1:8ftyGAC81UCENtArw0+NmGCucdlXNKbSK0Ix6YQv0ruNDvkgJfi MzxPkpv2n0SFayTwwJKTJXgoOsRcd2Ge0fLgOtMozxPW1V1bJfuKhi/7qiYqXFlggZ2MZNG x16JgjZyvECxQH9WEVCoJK/xmvdaei4HbjdlTZMbTOFKW4jx4nm349fvHaZPZe5ZC+0xjXK uODzkTbYou6kBAhG677GA== X-UI-Out-Filterresults: notjunk:1;V03:K0:AQw4J5+grJg=:BwUBaR+uQF7Q/XGRuZK8NH wHAhDsFGfUSW/WPn212WtJ0f0JFNoh5hsxkkDbcjNBdiVuOALhHwXS79xw8u/3lpLitkZStRV Fpc9eZF19eEYgVOOted+jUYxuMgQKy027XYGL8GOzS9bOZnF9GJn4kC6sJVtKHfa+ujDpOkz8 bO3mhLBfLfvqai+ztU7vcpTtQPJS+Ob8c+vN0xvMyUV4SHLvUTi6OMyScSJQ+UgBFpZ7FjUnK aBFHxErG6EPrxxXQRzDpNztdQotOV+h+F7SSvYsaybuzQDuhSUaUbIvYbS5Iz8DlHPY8j6Aw5 vxZdkJc+7dsW/lOCoClmGZxIK6Jin7C+2O+OylrsvJznIp4EXDXhYeu4u1CpOSAu0LAJh2O/a /SN7uMpYd/jUeh7hoYOrUrfEP8rOHJtRfFKfTSC1+puTkIQ4sU0XGNp/qzUWQrSdb+g9jaZE0 0x3ilY9eIih3kvfMzM+W7IvE2HwOsG0w5b/Iakv9tXxY0zqOI1S58P6cJshuEPk9xECVQ0M+Q k+4xaVu3u8UKjL+sXMH51maGoHVZo8LtfI9MAMbefnCw59ux0v58jQYKsHzKhBqztfMV8Unbp 1uOc7KCicjqprxtc0XfgfRLMmKa8phxfQiykoE48jANx03XLDGiQiUk8hFJqSOzazfciAHV5s QxeaPHpsZUmNF3AAtgYomo6/lu5pDTpQPKYpzAW0/VjMeeYfBaAziIgEq6rbfgXdbN3AOrl0E Ji0aD+XtxZGKF1GC9VqqmxW0T8S7Ks7KohMqab/z8ful20bS8i7XrWODvMCUjngjiFayx4ut2 68BbkBeG+OoMnvRBzIfPDVeYpW8xpWa7bEx7Eb5pH75hB1oSyzYaMmPIapftj39sXbwLBu1Sp A5/bTVAo5SVfWKVxBynCUxI1xJ9/3K5M79Tqv+6yPM73LMfdAOcFrsV28hvEoqBvrcsXQVqaC i3eudIwuCsd+GBa+45u3z4AUgA7NZEtwpVllRzvYCEPhx7EjPcA5fAcB4St1D+dAHiFagMi7k MSWc4KIunZNLudmKutI28zNJn2ht4+IEaNuW7cN9T11kbbAS9X9AFa9kSNJ3sdThmQe4MHLpU L9wXk+jhM1sO7IJVIgCPS7MZ9Dtdl+JCGrxRfuSJbCa6++SK+npcU8wJfia9ieIZ5RuiZlIpy Oy94VtgCGQqchqEGT6LUXsopcsXyLvoGV2fnKhnIebMlIdGH6C8kOiHJnt0Q9bPd7z5BijqFf 35n8UPe4LahIcHNwi Received-SPF: pass client-ip=217.72.192.78; envelope-from=lukasstraub2@web.de; helo=mout.web.de X-detected-operating-system: by eggs.gnu.org: First seen = 2020/05/25 11:44:31 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] X-Spam_score_int: -24 X-Spam_score: -2.5 X-Spam_bar: -- X-Spam_report: (-2.5 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_PASS=-0.001, URIBL_BLOCKED=0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , "Daniel P. =?utf-8?b?QmVycmFuZ8Op?= " , qemu-block , Juan Quintela , "Dr. David Alan Gilbert" , Max Reitz , Paolo Bonzini , =?utf-8?q?Marc-Andr=C3=A9?= Lureau Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Register a yank function which shuts down the socket and sets s->state = NBD_CLIENT_QUIT. This is the same behaviour as if an error occured. Signed-off-by: Lukas Straub Reviewed-by: Daniel P. Berrangé --- Makefile.objs | 1 + block/nbd.c | 101 ++++++++++++++++++++++++++++++++------------------ 2 files changed, 65 insertions(+), 37 deletions(-) -- 2.20.1 diff --git a/Makefile.objs b/Makefile.objs index a7c967633a..8e403b81f3 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -18,6 +18,7 @@ block-obj-y += block.o blockjob.o job.o block-obj-y += block/ scsi/ block-obj-y += qemu-io-cmds.o block-obj-$(CONFIG_REPLICATION) += replication.o +block-obj-y += yank.o block-obj-m = block/ diff --git a/block/nbd.c b/block/nbd.c index 2160859f64..3a41749f1b 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -35,6 +35,7 @@ #include "qemu/option.h" #include "qemu/cutils.h" #include "qemu/main-loop.h" +#include "qemu/atomic.h" #include "qapi/qapi-visit-sockets.h" #include "qapi/qmp/qstring.h" @@ -43,6 +44,8 @@ #include "block/nbd.h" #include "block/block_int.h" +#include "yank.h" + #define EN_OPTSTR ":exportname=" #define MAX_NBD_REQUESTS 16 @@ -84,6 +87,8 @@ typedef struct BDRVNBDState { NBDReply reply; BlockDriverState *bs; + char *yank_name; + /* Connection parameters */ uint32_t reconnect_delay; SocketAddress *saddr; @@ -94,6 +99,7 @@ typedef struct BDRVNBDState { } BDRVNBDState; static int nbd_client_connect(BlockDriverState *bs, Error **errp); +static void nbd_yank(void *opaque); static void nbd_clear_bdrvstate(BDRVNBDState *s) { @@ -106,17 +112,19 @@ static void nbd_clear_bdrvstate(BDRVNBDState *s) s->tlscredsid = NULL; g_free(s->x_dirty_bitmap); s->x_dirty_bitmap = NULL; + g_free(s->yank_name); + s->yank_name = NULL; } static void nbd_channel_error(BDRVNBDState *s, int ret) { if (ret == -EIO) { - if (s->state == NBD_CLIENT_CONNECTED) { + if (atomic_read(&s->state) == NBD_CLIENT_CONNECTED) { s->state = s->reconnect_delay ? NBD_CLIENT_CONNECTING_WAIT : NBD_CLIENT_CONNECTING_NOWAIT; } } else { - if (s->state == NBD_CLIENT_CONNECTED) { + if (atomic_read(&s->state) == NBD_CLIENT_CONNECTED) { qio_channel_shutdown(s->ioc, QIO_CHANNEL_SHUTDOWN_BOTH, NULL); } s->state = NBD_CLIENT_QUIT; @@ -167,7 +175,7 @@ static void nbd_client_attach_aio_context(BlockDriverState *bs, * s->connection_co is either yielded from nbd_receive_reply or from * nbd_co_reconnect_loop() */ - if (s->state == NBD_CLIENT_CONNECTED) { + if (atomic_read(&s->state) == NBD_CLIENT_CONNECTED) { qio_channel_attach_aio_context(QIO_CHANNEL(s->ioc), new_context); } @@ -206,7 +214,7 @@ static void nbd_teardown_connection(BlockDriverState *bs) { BDRVNBDState *s = (BDRVNBDState *)bs->opaque; - if (s->state == NBD_CLIENT_CONNECTED) { + if (atomic_read(&s->state) == NBD_CLIENT_CONNECTED) { /* finish any pending coroutines */ assert(s->ioc); qio_channel_shutdown(s->ioc, QIO_CHANNEL_SHUTDOWN_BOTH, NULL); @@ -230,13 +238,14 @@ static void nbd_teardown_connection(BlockDriverState *bs) static bool nbd_client_connecting(BDRVNBDState *s) { - return s->state == NBD_CLIENT_CONNECTING_WAIT || - s->state == NBD_CLIENT_CONNECTING_NOWAIT; + NBDClientState state = atomic_read(&s->state); + return state == NBD_CLIENT_CONNECTING_WAIT || + state == NBD_CLIENT_CONNECTING_NOWAIT; } static bool nbd_client_connecting_wait(BDRVNBDState *s) { - return s->state == NBD_CLIENT_CONNECTING_WAIT; + return atomic_read(&s->state) == NBD_CLIENT_CONNECTING_WAIT; } static coroutine_fn void nbd_reconnect_attempt(BDRVNBDState *s) @@ -274,6 +283,7 @@ static coroutine_fn void nbd_reconnect_attempt(BDRVNBDState *s) /* Finalize previous connection if any */ if (s->ioc) { nbd_client_detach_aio_context(s->bs); + yank_unregister_function(s->yank_name, nbd_yank, s->bs); object_unref(OBJECT(s->sioc)); s->sioc = NULL; object_unref(OBJECT(s->ioc)); @@ -305,7 +315,7 @@ static coroutine_fn void nbd_co_reconnect_loop(BDRVNBDState *s) nbd_reconnect_attempt(s); while (nbd_client_connecting(s)) { - if (s->state == NBD_CLIENT_CONNECTING_WAIT && + if (atomic_read(&s->state) == NBD_CLIENT_CONNECTING_WAIT && qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - start_time_ns > delay_ns) { s->state = NBD_CLIENT_CONNECTING_NOWAIT; @@ -341,7 +351,7 @@ static coroutine_fn void nbd_connection_entry(void *opaque) int ret = 0; Error *local_err = NULL; - while (s->state != NBD_CLIENT_QUIT) { + while (atomic_read(&s->state) != NBD_CLIENT_QUIT) { /* * The NBD client can only really be considered idle when it has * yielded from qio_channel_readv_all_eof(), waiting for data. This is @@ -356,7 +366,7 @@ static coroutine_fn void nbd_connection_entry(void *opaque) nbd_co_reconnect_loop(s); } - if (s->state != NBD_CLIENT_CONNECTED) { + if (atomic_read(&s->state) != NBD_CLIENT_CONNECTED) { continue; } @@ -411,6 +421,7 @@ static coroutine_fn void nbd_connection_entry(void *opaque) s->connection_co = NULL; if (s->ioc) { nbd_client_detach_aio_context(s->bs); + yank_unregister_function(s->yank_name, nbd_yank, s->bs); object_unref(OBJECT(s->sioc)); s->sioc = NULL; object_unref(OBJECT(s->ioc)); @@ -435,7 +446,7 @@ static int nbd_co_send_request(BlockDriverState *bs, qemu_co_queue_wait(&s->free_sema, &s->send_mutex); } - if (s->state != NBD_CLIENT_CONNECTED) { + if (atomic_read(&s->state) != NBD_CLIENT_CONNECTED) { rc = -EIO; goto err; } @@ -462,7 +473,7 @@ static int nbd_co_send_request(BlockDriverState *bs, if (qiov) { qio_channel_set_cork(s->ioc, true); rc = nbd_send_request(s->ioc, request); - if (rc >= 0 && s->state == NBD_CLIENT_CONNECTED) { + if (rc >= 0 && atomic_read(&s->state) == NBD_CLIENT_CONNECTED) { if (qio_channel_writev_all(s->ioc, qiov->iov, qiov->niov, NULL) < 0) { rc = -EIO; @@ -777,7 +788,7 @@ static coroutine_fn int nbd_co_do_receive_one_chunk( s->requests[i].receiving = true; qemu_coroutine_yield(); s->requests[i].receiving = false; - if (s->state != NBD_CLIENT_CONNECTED) { + if (atomic_read(&s->state) != NBD_CLIENT_CONNECTED) { error_setg(errp, "Connection closed"); return -EIO; } @@ -936,7 +947,7 @@ static bool nbd_reply_chunk_iter_receive(BDRVNBDState *s, NBDReply local_reply; NBDStructuredReplyChunk *chunk; Error *local_err = NULL; - if (s->state != NBD_CLIENT_CONNECTED) { + if (atomic_read(&s->state) != NBD_CLIENT_CONNECTED) { error_setg(&local_err, "Connection closed"); nbd_iter_channel_error(iter, -EIO, &local_err); goto break_loop; @@ -961,7 +972,8 @@ static bool nbd_reply_chunk_iter_receive(BDRVNBDState *s, } /* Do not execute the body of NBD_FOREACH_REPLY_CHUNK for simple reply. */ - if (nbd_reply_is_simple(reply) || s->state != NBD_CLIENT_CONNECTED) { + if (nbd_reply_is_simple(reply) || + atomic_read(&s->state) != NBD_CLIENT_CONNECTED) { goto break_loop; } @@ -1395,6 +1407,15 @@ static int nbd_client_reopen_prepare(BDRVReopenState *state, return 0; } +static void nbd_yank(void *opaque) +{ + BlockDriverState *bs = opaque; + BDRVNBDState *s = (BDRVNBDState *)bs->opaque; + + qio_channel_shutdown(QIO_CHANNEL(s->sioc), QIO_CHANNEL_SHUTDOWN_BOTH, NULL); + atomic_set(&s->state, NBD_CLIENT_QUIT); +} + static void nbd_client_close(BlockDriverState *bs) { BDRVNBDState *s = (BDRVNBDState *)bs->opaque; @@ -1407,25 +1428,29 @@ static void nbd_client_close(BlockDriverState *bs) nbd_teardown_connection(bs); } -static QIOChannelSocket *nbd_establish_connection(SocketAddress *saddr, - Error **errp) +static int nbd_establish_connection(BlockDriverState *bs, + SocketAddress *saddr, + Error **errp) { - QIOChannelSocket *sioc; + BDRVNBDState *s = (BDRVNBDState *)bs->opaque; Error *local_err = NULL; - sioc = qio_channel_socket_new(); - qio_channel_set_name(QIO_CHANNEL(sioc), "nbd-client"); + s->sioc = qio_channel_socket_new(); + qio_channel_set_name(QIO_CHANNEL(s->sioc), "nbd-client"); + yank_register_function(s->yank_name, nbd_yank, bs); - qio_channel_socket_connect_sync(sioc, saddr, &local_err); + qio_channel_socket_connect_sync(s->sioc, saddr, &local_err); if (local_err) { - object_unref(OBJECT(sioc)); + yank_unregister_function(s->yank_name, nbd_yank, bs); + object_unref(OBJECT(s->sioc)); + s->sioc = NULL; error_propagate(errp, local_err); - return NULL; + return -1; } - qio_channel_set_delay(QIO_CHANNEL(sioc), false); + qio_channel_set_delay(QIO_CHANNEL(s->sioc), false); - return sioc; + return 0; } static int nbd_client_connect(BlockDriverState *bs, Error **errp) @@ -1438,28 +1463,27 @@ static int nbd_client_connect(BlockDriverState *bs, Error **errp) * establish TCP connection, return error if it fails * TODO: Configurable retry-until-timeout behaviour. */ - QIOChannelSocket *sioc = nbd_establish_connection(s->saddr, errp); - - if (!sioc) { + if (nbd_establish_connection(bs, s->saddr, errp) < 0) { return -ECONNREFUSED; } /* NBD handshake */ trace_nbd_client_connect(s->export); - qio_channel_set_blocking(QIO_CHANNEL(sioc), false, NULL); - qio_channel_attach_aio_context(QIO_CHANNEL(sioc), aio_context); + qio_channel_set_blocking(QIO_CHANNEL(s->sioc), false, NULL); + qio_channel_attach_aio_context(QIO_CHANNEL(s->sioc), aio_context); s->info.request_sizes = true; s->info.structured_reply = true; s->info.base_allocation = true; s->info.x_dirty_bitmap = g_strdup(s->x_dirty_bitmap); s->info.name = g_strdup(s->export ?: ""); - ret = nbd_receive_negotiate(aio_context, QIO_CHANNEL(sioc), s->tlscreds, + ret = nbd_receive_negotiate(aio_context, QIO_CHANNEL(s->sioc), s->tlscreds, s->hostname, &s->ioc, &s->info, errp); g_free(s->info.x_dirty_bitmap); g_free(s->info.name); if (ret < 0) { - object_unref(OBJECT(sioc)); + yank_unregister_function(s->yank_name, nbd_yank, bs); + object_unref(OBJECT(s->sioc)); return ret; } if (s->x_dirty_bitmap && !s->info.base_allocation) { @@ -1485,10 +1509,8 @@ static int nbd_client_connect(BlockDriverState *bs, Error **errp) } } - s->sioc = sioc; - if (!s->ioc) { - s->ioc = QIO_CHANNEL(sioc); + s->ioc = QIO_CHANNEL(s->sioc); object_ref(OBJECT(s->ioc)); } @@ -1504,9 +1526,10 @@ static int nbd_client_connect(BlockDriverState *bs, Error **errp) { NBDRequest request = { .type = NBD_CMD_DISC }; - nbd_send_request(s->ioc ?: QIO_CHANNEL(sioc), &request); + nbd_send_request(s->ioc ?: QIO_CHANNEL(s->sioc), &request); - object_unref(OBJECT(sioc)); + yank_unregister_function(s->yank_name, nbd_yank, bs); + object_unref(OBJECT(s->sioc)); return ret; } @@ -1913,6 +1936,9 @@ static int nbd_open(BlockDriverState *bs, QDict *options, int flags, qemu_co_mutex_init(&s->send_mutex); qemu_co_queue_init(&s->free_sema); + s->yank_name = g_strconcat("blockdev:", bs->node_name, NULL); + yank_register_instance(s->yank_name); + ret = nbd_client_connect(bs, errp); if (ret < 0) { nbd_clear_bdrvstate(s); @@ -1972,6 +1998,7 @@ static void nbd_close(BlockDriverState *bs) BDRVNBDState *s = bs->opaque; nbd_client_close(bs); + yank_unregister_instance(s->yank_name); nbd_clear_bdrvstate(s); } From patchwork Mon May 25 15:44:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Lukas Straub X-Patchwork-Id: 1297408 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=web.de Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; secure) header.d=web.de header.i=@web.de header.a=rsa-sha256 header.s=dbaedf251592 header.b=ViHs5jDQ; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49W1hL6bNpz9sSd for ; Tue, 26 May 2020 01:48:02 +1000 (AEST) Received: from localhost ([::1]:38792 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jdFKZ-0006N3-DK for incoming@patchwork.ozlabs.org; Mon, 25 May 2020 11:48:00 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:58918) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jdFHL-000536-2I; Mon, 25 May 2020 11:44:39 -0400 Received: from mout.web.de ([212.227.15.4]:53911) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jdFHI-0006d9-Jb; Mon, 25 May 2020 11:44:38 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=web.de; s=dbaedf251592; t=1590421471; bh=vjgc7wjc4cKdgQx7ocR5j9Ow5aCDgaGFl5sIJXEozlk=; h=X-UI-Sender-Class:Date:From:To:Cc:Subject:In-Reply-To:References; b=ViHs5jDQ4pfzj3Xp/nI5KN0SMsXGjZpKVnSmnLoiE5yesTB7r2qd7U1tjB+kXgPRJ 2L+7kPDrqPtRUrZ0eHUgLSLBal1RvIA61OZYLn7KQpItmLfEhqzkkZFPBZ2iKRr1P2 +YaAbUQJ+GHkeZuUSrQ2ps0pXcSmhOfT80NhHzx8= X-UI-Sender-Class: c548c8c5-30a9-4db5-a2e7-cb6cb037b8f9 Received: from luklap ([94.134.180.22]) by smtp.web.de (mrweb002 [213.165.67.108]) with ESMTPSA (Nemesis) id 0M7sga-1iqetT06a0-00vMTA; Mon, 25 May 2020 17:44:31 +0200 Date: Mon, 25 May 2020 17:44:29 +0200 From: Lukas Straub To: qemu-devel Subject: [PATCH v4 3/4] chardev/char-socket.c: Add yank feature Message-ID: In-Reply-To: References: MIME-Version: 1.0 X-Provags-ID: V03:K1:W4nAofsUgoJbkWOGQhUE8bIBSLOkYGcX3JNZs62PClHPOTB+190 3oBG62HGuMOdSh2kuL5+4sGly8vrlEkG5BodS+V5aYemxGwS/IvbfNAciqq8jkb33aA9/3w Zy5b7IP2UfLZzhdr8n8ozYJydMm5T2UVGI1zzI9aM0PDLU+d6hWPmsZebOI86wuOK8iHH8X bmKtFxzmZZI1ajTNKP52Q== X-UI-Out-Filterresults: notjunk:1;V03:K0:9Nrkf+Q33qo=:N14bzYhTwvlG1H02ndrZZW 2W9cdAXK0Wn8c18TBSqFLf0kg2zNjibASllb4/ssqYhfzot77MUw96UYz9jbv/2tcS/Ol2VRl xPaoYrx++7/m4yu/I8reyRrrMKvsc1qg9OAtQvzDQjmqKo6GzPYqJjbwG7ClZoEwShKurh4xT lKrXNcaX26By7YdPIZuZSwLt11KY+kpXWrMocmzbm2Z6uAsWmsn6BEZYNhaoiWxqG5ZuUrS27 miGCAFZJx0bx+6WSvY8UHFcLbG7K7lcGnIfAwdd0IO7HCSmDaUxt0Z5JFkW2trJENqXQ+tiVU O22yOUl/Lyqkvg7DjnVZ23Uzq0/tuvO0p627dZ8s7+zFvBqlr03fAG5N9JhvQ75LuItIp+/dp xbeSnN4CtwmcSUTMmEsh0POBYmALoSZ5y/+2yOTRtGn7B4gIipPGMp73Ll6FmgBdlKEdBmCrF yCDY0qr/tGLOdzkF5XD5Cntfm7hLB5IdaZr4KFv/+Qd/fhd/wks4WZ0QaQatWXDC6pCl21ME8 yYWxb8ZDr9xy1mTHhNFt8ppmMNKGk4ATJypkpC6kPjaI/igLZaXvAM6SOy9Gnwd1p+79xqobw jUkkIZ9j/mGU2zVzW8Pz7N8luovJeoa8YqitFt/+byE6m8suGC99hc0it16DgHVKM41+V8Jab b3Po8VHYtngd93xfVNbBLmlQuO5nK0yl9lZiTbI2TuYIOw66lqSy3drFrR7mwQm+0sxhJK4bQ rpUo9QGVNjyvxuv7id6cSqSUuR3gawQ9Dr0SAOFa1zjSfOtXyk3XKM3zzDFG7rQ1XThn8cxo3 mey+8nktSeRfP505kqNoJyV3GZqnSemlDGXHPAdW08G1jOzQnsdIcFYKmHCHFLrBvhYu4LZSR x2dvwDMRL8gP5Fq+u0eWZZxGQ4FDlmJhWek6OIcNn5Ov0C3DsW0Xo/7lGDQoVz1jioLgIAkRW z8Z67vb3lfdc0bOFLlMWWNWe+x9IsY5VzMs0zCQhN3zqIP6DdYKe3YIonPH9hRDlh+pIsWqgX 1WF14g+43As6Vk7Ztyjk0pSj7p73NDDsNBDol7/DONtR7SqUVqOZsnt5uP07oHCqGidj1S+NP BI4i01Y7aLdM1qLNOEWeAkKbkiZ2zxJyTMAMuQhcgJptF5dLx26PHyEa/t4dWC9KAA0KR0Uvp lcqXd5Y/oW5uLLPG9yzBgb8FrolFMZN3A8mNuCAUAD4YjTZEvnpjhM/YvDdKCxT1xDpOiACzX CrsY0xsT8DYl6ypk+ Received-SPF: pass client-ip=212.227.15.4; envelope-from=lukasstraub2@web.de; helo=mout.web.de X-detected-operating-system: by eggs.gnu.org: First seen = 2020/05/25 11:44:28 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] X-Spam_score_int: -24 X-Spam_score: -2.5 X-Spam_bar: -- X-Spam_report: (-2.5 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_PASS=-0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , "Daniel P. =?utf-8?b?QmVycmFuZ8Op?= " , qemu-block , Juan Quintela , "Dr. David Alan Gilbert" , Max Reitz , Paolo Bonzini , =?utf-8?q?Marc-Andr=C3=A9?= Lureau Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Register a yank function to shutdown the socket on yank. Signed-off-by: Lukas Straub Reviewed-by: Daniel P. Berrangé --- Makefile.objs | 1 + chardev/char-socket.c | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) -- 2.20.1 diff --git a/Makefile.objs b/Makefile.objs index 8e403b81f3..5582f4eda9 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -10,6 +10,7 @@ qom-obj-y = qom/ ifeq ($(call lor,$(CONFIG_SOFTMMU),$(CONFIG_TOOLS)),y) chardev-obj-y = chardev/ +chardev-obj-y += yank.o authz-obj-y = authz/ diff --git a/chardev/char-socket.c b/chardev/char-socket.c index 185fe38dda..d5c6cd2153 100644 --- a/chardev/char-socket.c +++ b/chardev/char-socket.c @@ -34,6 +34,7 @@ #include "qapi/error.h" #include "qapi/clone-visitor.h" #include "qapi/qapi-visit-sockets.h" +#include "yank.h" #include "chardev/char-io.h" @@ -69,6 +70,7 @@ typedef struct { size_t read_msgfds_num; int *write_msgfds; size_t write_msgfds_num; + char *yank_name; SocketAddress *addr; bool is_listen; @@ -409,6 +411,11 @@ static void tcp_chr_free_connection(Chardev *chr) tcp_set_msgfds(chr, NULL, 0); remove_fd_in_watch(chr); + if (s->state == TCP_CHARDEV_STATE_CONNECTING + || s->state == TCP_CHARDEV_STATE_CONNECTED) { + yank_unregister_function(s->yank_name, yank_generic_iochannel, + QIO_CHANNEL(s->sioc)); + } object_unref(OBJECT(s->sioc)); s->sioc = NULL; object_unref(OBJECT(s->ioc)); @@ -912,6 +919,8 @@ static int tcp_chr_add_client(Chardev *chr, int fd) } tcp_chr_change_state(s, TCP_CHARDEV_STATE_CONNECTING); tcp_chr_set_client_ioc_name(chr, sioc); + yank_register_function(s->yank_name, yank_generic_iochannel, + QIO_CHANNEL(sioc)); ret = tcp_chr_new_client(chr, sioc); object_unref(OBJECT(sioc)); return ret; @@ -926,6 +935,8 @@ static void tcp_chr_accept(QIONetListener *listener, tcp_chr_change_state(s, TCP_CHARDEV_STATE_CONNECTING); tcp_chr_set_client_ioc_name(chr, cioc); + yank_register_function(s->yank_name, yank_generic_iochannel, + QIO_CHANNEL(cioc)); tcp_chr_new_client(chr, cioc); } @@ -941,6 +952,8 @@ static int tcp_chr_connect_client_sync(Chardev *chr, Error **errp) object_unref(OBJECT(sioc)); return -1; } + yank_register_function(s->yank_name, yank_generic_iochannel, + QIO_CHANNEL(sioc)); tcp_chr_new_client(chr, sioc); object_unref(OBJECT(sioc)); return 0; @@ -956,6 +969,8 @@ static void tcp_chr_accept_server_sync(Chardev *chr) tcp_chr_change_state(s, TCP_CHARDEV_STATE_CONNECTING); sioc = qio_net_listener_wait_client(s->listener); tcp_chr_set_client_ioc_name(chr, sioc); + yank_register_function(s->yank_name, yank_generic_iochannel, + QIO_CHANNEL(sioc)); tcp_chr_new_client(chr, sioc); object_unref(OBJECT(sioc)); } @@ -1066,6 +1081,8 @@ static void char_socket_finalize(Object *obj) object_unref(OBJECT(s->tls_creds)); } g_free(s->tls_authz); + yank_unregister_instance(s->yank_name); + g_free(s->yank_name); qemu_chr_be_event(chr, CHR_EVENT_CLOSED); } @@ -1081,6 +1098,8 @@ static void qemu_chr_socket_connected(QIOTask *task, void *opaque) if (qio_task_propagate_error(task, &err)) { tcp_chr_change_state(s, TCP_CHARDEV_STATE_DISCONNECTED); + yank_unregister_function(s->yank_name, yank_generic_iochannel, + QIO_CHANNEL(sioc)); check_report_connect_error(chr, err); error_free(err); goto cleanup; @@ -1115,6 +1134,8 @@ static void tcp_chr_connect_client_async(Chardev *chr) tcp_chr_change_state(s, TCP_CHARDEV_STATE_CONNECTING); sioc = qio_channel_socket_new(); tcp_chr_set_client_ioc_name(chr, sioc); + yank_register_function(s->yank_name, yank_generic_iochannel, + QIO_CHANNEL(sioc)); /* * Normally code would use the qio_channel_socket_connect_async * method which uses a QIOTask + qio_task_set_error internally @@ -1356,6 +1377,9 @@ static void qmp_chardev_open_socket(Chardev *chr, qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_FD_PASS); } + s->yank_name = g_strconcat("chardev:", chr->label, NULL); + yank_register_instance(s->yank_name); + /* be isn't opened until we get a connection */ *be_opened = false; From patchwork Mon May 25 15:44:33 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Lukas Straub X-Patchwork-Id: 1297413 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=web.de Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; secure) header.d=web.de header.i=@web.de header.a=rsa-sha256 header.s=dbaedf251592 header.b=iR+q4NQK; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49W1rW6lwbz9sSd for ; Tue, 26 May 2020 01:55:07 +1000 (AEST) Received: from localhost ([::1]:45668 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jdFRR-0001Bg-E0 for incoming@patchwork.ozlabs.org; Mon, 25 May 2020 11:55:05 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:58924) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jdFHO-00057s-2N; Mon, 25 May 2020 11:44:42 -0400 Received: from mout.web.de ([212.227.17.12]:60207) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jdFHM-0006dL-RF; Mon, 25 May 2020 11:44:41 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=web.de; s=dbaedf251592; t=1590421475; bh=RjwTpyFKLImM2A/3YX/+JYWk6EWjPvnoBKIrskbhufs=; h=X-UI-Sender-Class:Date:From:To:Cc:Subject:In-Reply-To:References; b=iR+q4NQKh9O9PlFXg1pHuFN8GGB8mSIh0Nfak68FgikNGBFUb7Abl7XTx235O/RSB jKSMpjpPrCTb9a5DY+dghtOxngpWtUjrHY2qveP5Cx8wlC3yfQdrmLGXquA+8KvSs/ MX85RgNODMXlttQtAP3phxRhb5ZEn9w6lzf76b14= X-UI-Sender-Class: c548c8c5-30a9-4db5-a2e7-cb6cb037b8f9 Received: from luklap ([94.134.180.22]) by smtp.web.de (mrweb105 [213.165.67.124]) with ESMTPSA (Nemesis) id 1MKuON-1jKCpL3ETd-00LD4H; Mon, 25 May 2020 17:44:34 +0200 Date: Mon, 25 May 2020 17:44:33 +0200 From: Lukas Straub To: qemu-devel Subject: [PATCH v4 4/4] migration: Add yank feature Message-ID: <06c8eb78213a1cceaba4121d205dfc93b7ad9254.1590421341.git.lukasstraub2@web.de> In-Reply-To: References: MIME-Version: 1.0 X-Provags-ID: V03:K1:cFHglrK12IzXAfiYI9LscB6GUt9+tM6hWrecsoYVSk6ETlDUmB+ GNetg3YLGfJg9wRhMLzmWaeaSed9esVokNCMHHVSSxbYrm7qoVGMUN56dvLskJrRQXHKcqt mN1YMmRQNPqx6PTw1w72Y1YVCe3nlvtl1Gc9ujFfjuKuYBgyXs+Y6wlg8FturFXpLC/iCq3 F51rK0eUamd3NQwW0BO1w== X-UI-Out-Filterresults: notjunk:1;V03:K0:LhWVhNOis/o=:7IR+aQpmetpHAVFWvaK03X kHjMrgu6rURbvO0ySe39PIMhdE4q63NLElQFnfrPeW4YvTkh8QfvJ+6+L5vf3Cs2FnmlpNBTB /tV+/Eu7/ef4BZ9NQy0/Rg/tyaaAaebLJpKdVwZEc2IF87WgLcRM+uICRgJP6ouTe54e1egDp +X1O8p1uhhMB/H5fHN8WqEv5NgpmapM0K7efWzGMlRABHNVc9JTROAsa3/WqdoB4XfKgD62Pi 6GgeSN2kjVFLVUUpj5oxqedizIvWTVOKZHrIuInUXtTJ+Bi8Ow8T3UTZjBP3WJGL2vHwTbtzQ TxTPsq1EWsp52nhoLor36A6Fu7y/m1ewpO3vW16cmlhr8pwSI+d4hHbHTH4T2IwnWUDm2+G+w +m2m3nI8f87V9g9P6hZLsj6lLxagOAhcuSZYB5rDJEGJGx69lnW58RT6I6oh5A/qvqfRxRVuu gwn/HCy4n2ZVwlZyCtvNg0zEae1BTx/YdaY1gYnr4OFjrIgllaOGewIY6mLTPdtOMGDdHIFh/ rGkf42WwHVL8ZLBa08QhLkSmp7IvGGbCh+W7lutQPw/lT3aoDXQB4VjiyZrw9AGgFFADjcsE1 bmnfixesYlckSUXKTPfO8NJlePFG6GZuRkFSByXdi9qkRy2t9WZnCumPK8LY/wQGxrcKN29FZ ci/DRLglsL8ttOLQatpIG/z3IOhrkdyBc/x6etzzQbnG614FjuotBO6NJTZv3yuTV05VsUY4i 1pJHOqdKTt3+NPuKMmsr4CoUYyZod7Iv8UPHqvJCWavwIFvcMrgVKwJStJjg2de2diaoNoctc FXt5N1kmPQfXwFd2pJ3C46gm9/5oerF6UxQLFHEk0fLUzB30GNycr4uv5uIN/+cDrzKHjwjXg M4F9G1G8nCX6aUZmTsnKEQmL3nX5VSoWQIqnzcsmuoOUNvuHjJa9xeb2x+lDmIj4/aM4OGCIJ vuBIwmXkNGLu82Pm9csEb/QUTLlhelJpxEkqoQmqpjUehyIEKGJFsIlup+fWcsQY4XIUXrXe/ 1tUTpgoGlj+9qIJ0vpY7DUTwfA9aLsrtLNtmSGYZiU0/3gL6OVWQGjOJlBwRwEOjWem1+IckB grR+lCwobD2zGda+wxnYYLGSSyEn37fxRpNj70iYTh2sPmQW3B2fEmnotoBJgOnaeG2OVyoj3 zcyY5doBXINnUfUUY5fxbiXJvx92pGXQ3JWtmq9gHp7kw0VQVPiLLKxHft5ZP/Q12eTd7aUhd j3wMc027aBhz/kNwH Received-SPF: pass client-ip=212.227.17.12; envelope-from=lukasstraub2@web.de; helo=mout.web.de X-detected-operating-system: by eggs.gnu.org: First seen = 2020/05/25 11:44:39 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] X-Spam_score_int: -24 X-Spam_score: -2.5 X-Spam_bar: -- X-Spam_report: (-2.5 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_PASS=-0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , "Daniel P. =?utf-8?b?QmVycmFuZ8Op?= " , qemu-block , Juan Quintela , "Dr. David Alan Gilbert" , Max Reitz , Paolo Bonzini , =?utf-8?q?Marc-Andr=C3=A9?= Lureau Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Register yank functions on sockets to shut them down. Signed-off-by: Lukas Straub Reviewed-by: Daniel P. Berrangé --- Makefile.objs | 1 + migration/channel.c | 12 ++++++++++++ migration/migration.c | 18 +++++++++++++++++- migration/multifd.c | 10 ++++++++++ migration/qemu-file-channel.c | 6 ++++++ migration/savevm.c | 2 ++ tests/Makefile.include | 2 +- 7 files changed, 49 insertions(+), 2 deletions(-) -- 2.20.1 diff --git a/Makefile.objs b/Makefile.objs index 5582f4eda9..d2a49d3834 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -58,6 +58,7 @@ common-obj-$(CONFIG_LINUX) += fsdev/ common-obj-y += accel/ common-obj-y += migration/ +common-obj-y += yank.o common-obj-y += audio/ common-obj-m += audio/ diff --git a/migration/channel.c b/migration/channel.c index 20e4c8e2dc..5cb48d403a 100644 --- a/migration/channel.c +++ b/migration/channel.c @@ -18,6 +18,8 @@ #include "trace.h" #include "qapi/error.h" #include "io/channel-tls.h" +#include "io/channel-socket.h" +#include "yank.h" /** * @migration_channel_process_incoming - Create new incoming migration channel @@ -35,6 +37,11 @@ void migration_channel_process_incoming(QIOChannel *ioc) trace_migration_set_incoming_channel( ioc, object_get_typename(OBJECT(ioc))); + if (object_dynamic_cast(OBJECT(ioc), TYPE_QIO_CHANNEL_SOCKET)) { + yank_register_function((char *) "migration", yank_generic_iochannel, + QIO_CHANNEL(ioc)); + } + if (s->parameters.tls_creds && *s->parameters.tls_creds && !object_dynamic_cast(OBJECT(ioc), @@ -67,6 +74,11 @@ void migration_channel_connect(MigrationState *s, ioc, object_get_typename(OBJECT(ioc)), hostname, error); if (!error) { + if (object_dynamic_cast(OBJECT(ioc), TYPE_QIO_CHANNEL_SOCKET)) { + yank_register_function((char *) "migration", yank_generic_iochannel, + QIO_CHANNEL(ioc)); + } + if (s->parameters.tls_creds && *s->parameters.tls_creds && !object_dynamic_cast(OBJECT(ioc), diff --git a/migration/migration.c b/migration/migration.c index 187ac0410c..c6d7119c08 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -54,6 +54,7 @@ #include "net/announce.h" #include "qemu/queue.h" #include "multifd.h" +#include "yank.h" #define MAX_THROTTLE (32 << 20) /* Migration transfer speed throttling */ @@ -231,6 +232,8 @@ void migration_incoming_state_destroy(void) qapi_free_SocketAddressList(mis->socket_address_list); mis->socket_address_list = NULL; } + + yank_unregister_instance((char *) "migration"); } static void migrate_generate_event(int new_state) @@ -362,7 +365,9 @@ void qemu_start_incoming_migration(const char *uri, Error **errp) const char *p; qapi_event_send_migration(MIGRATION_STATUS_SETUP); + yank_register_instance((char *) "migration"); if (!strcmp(uri, "defer")) { + yank_unregister_instance((char *) "migration"); deferred_incoming_migration(errp); } else if (strstart(uri, "tcp:", &p)) { tcp_start_incoming_migration(p, errp); @@ -377,6 +382,7 @@ void qemu_start_incoming_migration(const char *uri, Error **errp) } else if (strstart(uri, "fd:", &p)) { fd_start_incoming_migration(p, errp); } else { + yank_unregister_instance((char *) "migration"); error_setg(errp, "unknown migration protocol: %s", uri); } } @@ -1632,6 +1638,7 @@ static void migrate_fd_cleanup(MigrationState *s) } notifier_list_notify(&migration_state_notifiers, s); block_cleanup_parameters(s); + yank_unregister_instance((char *) "migration"); } static void migrate_fd_cleanup_schedule(MigrationState *s) @@ -1899,6 +1906,7 @@ void qmp_migrate_recover(const char *uri, Error **errp) * only re-setup the migration stream and poke existing migration * to continue using that newly established channel. */ + yank_unregister_instance((char *) "migration"); qemu_start_incoming_migration(uri, errp); } @@ -2035,7 +2043,9 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk, /* Error detected, put into errp */ return; } - + if (!(has_resume && resume)) { + yank_register_instance((char *) "migration"); + } if (strstart(uri, "tcp:", &p)) { tcp_start_outgoing_migration(s, p, &local_err); #ifdef CONFIG_RDMA @@ -2049,6 +2059,9 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk, } else if (strstart(uri, "fd:", &p)) { fd_start_outgoing_migration(s, p, &local_err); } else { + if (!(has_resume && resume)) { + yank_unregister_instance((char *) "migration"); + } error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "uri", "a valid migration protocol"); migrate_set_state(&s->state, MIGRATION_STATUS_SETUP, @@ -2058,6 +2071,9 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk, } if (local_err) { + if (!(has_resume && resume)) { + yank_unregister_instance((char *) "migration"); + } migrate_fd_error(s, local_err); error_propagate(errp, local_err); return; diff --git a/migration/multifd.c b/migration/multifd.c index cb6a4a3ab8..97566262c1 100644 --- a/migration/multifd.c +++ b/migration/multifd.c @@ -24,6 +24,9 @@ #include "trace.h" #include "multifd.h" +#include "yank.h" +#include "io/channel-socket.h" + /* Multiple fd's */ #define MULTIFD_MAGIC 0x11223344U @@ -856,6 +859,13 @@ int multifd_load_cleanup(Error **errp) for (i = 0; i < migrate_multifd_channels(); i++) { MultiFDRecvParams *p = &multifd_recv_state->params[i]; + if (object_dynamic_cast(OBJECT(p->c), TYPE_QIO_CHANNEL_SOCKET) + && OBJECT(p->c)->ref == 1) { + yank_unregister_function((char *) "migration", + yank_generic_iochannel, + QIO_CHANNEL(p->c)); + } + object_unref(OBJECT(p->c)); p->c = NULL; qemu_mutex_destroy(&p->mutex); diff --git a/migration/qemu-file-channel.c b/migration/qemu-file-channel.c index d2ce32f4b9..b725ac8098 100644 --- a/migration/qemu-file-channel.c +++ b/migration/qemu-file-channel.c @@ -27,6 +27,7 @@ #include "qemu-file.h" #include "io/channel-socket.h" #include "qemu/iov.h" +#include "yank.h" static ssize_t channel_writev_buffer(void *opaque, @@ -104,6 +105,11 @@ static int channel_close(void *opaque, Error **errp) int ret; QIOChannel *ioc = QIO_CHANNEL(opaque); ret = qio_channel_close(ioc, errp); + if (object_dynamic_cast(OBJECT(ioc), TYPE_QIO_CHANNEL_SOCKET) + && OBJECT(ioc)->ref == 1) { + yank_unregister_function((char *) "migration", yank_generic_iochannel, + QIO_CHANNEL(ioc)); + } object_unref(OBJECT(ioc)); return ret; } diff --git a/migration/savevm.c b/migration/savevm.c index c00a6807d9..c5f957d4e4 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -63,6 +63,7 @@ #include "migration/colo.h" #include "qemu/bitmap.h" #include "net/announce.h" +#include "yank.h" const unsigned int postcopy_ram_discard_version = 0; @@ -2897,6 +2898,7 @@ int load_snapshot(const char *name, Error **errp) qemu_system_reset(SHUTDOWN_CAUSE_NONE); mis->from_src_file = f; + yank_register_instance((char *) "migration"); aio_context_acquire(aio_context); ret = qemu_loadvm_state(f); migration_incoming_state_destroy(); diff --git a/tests/Makefile.include b/tests/Makefile.include index 51de676298..e76a5458c3 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -442,7 +442,7 @@ tests/test-qdev-global-props$(EXESUF): tests/test-qdev-global-props.o \ $(test-qapi-obj-y) tests/test-vmstate$(EXESUF): tests/test-vmstate.o \ migration/vmstate.o migration/vmstate-types.o migration/qemu-file.o \ - migration/qemu-file-channel.o migration/qjson.o \ + migration/qemu-file-channel.o migration/qjson.o yank.o \ $(test-io-obj-y) tests/test-timed-average$(EXESUF): tests/test-timed-average.o $(test-util-obj-y) tests/test-base64$(EXESUF): tests/test-base64.o $(test-util-obj-y)