From patchwork Mon Nov 25 16:14:13 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Felipe Franciosi X-Patchwork-Id: 11260575 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9ADE9138C for ; Mon, 25 Nov 2019 16:14:59 +0000 (UTC) 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 mail.kernel.org (Postfix) with ESMTPS id 1B85C20740 for ; Mon, 25 Nov 2019 16:14:58 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=nutanix.com header.i=@nutanix.com header.b="1XAcq8Wb" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 1B85C20740 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=nutanix.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:46052 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iZH0r-0003uH-Ue for patchwork-qemu-devel@patchwork.kernel.org; Mon, 25 Nov 2019 11:14:57 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:38412) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iZH0G-0003US-RJ for qemu-devel@nongnu.org; Mon, 25 Nov 2019 11:14:22 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iZH0D-0001Vl-V2 for qemu-devel@nongnu.org; Mon, 25 Nov 2019 11:14:20 -0500 Received: from mx0a-002c1b01.pphosted.com ([148.163.151.68]:61934) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iZH0D-0001VM-LZ for qemu-devel@nongnu.org; Mon, 25 Nov 2019 11:14:17 -0500 Received: from pps.filterd (m0127838.ppops.net [127.0.0.1]) by mx0a-002c1b01.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id xAPG83ZR011984; Mon, 25 Nov 2019 08:14:15 -0800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nutanix.com; h=from : to : cc : subject : date : message-id : content-type : content-transfer-encoding : mime-version; s=proofpoint20171006; bh=4IQ+iqQsj7K9CPcqWBTN7lcON0pDu1M3slUJZ6Myn0E=; b=1XAcq8WbMXWdfj3JL1OmJsGcc9Aqi3TzqXTjqmFgjfFzEZJ6vF+PxTCYfAGZj4ofCTvF zHmDWVEyNurBm+62xYVjhRLtHS3I1v4/pyONr8enpOCvm2CiNCHn93ACJvRp+bQeM7n1 08kx407Nbicf/opdmsZUL8tHUbArE6pJzDx3bPJULUuSt+JiXGvaQ++BUkdRV+WOzC3c +5iT+S66mMWARcH7CLnNAGw2Is7Gj3n1PRnGYY7N0bhiSPNwjVJczfFhnCXE5JIFNmA/ SbMQR5GIwpb7ZQqh8lR2RUzm1edXboR5+gspRSj1W0rqhlpasM3U/9tPU5NsTPWbT8Em Xw== Received: from nam02-sn1-obe.outbound.protection.outlook.com (mail-sn1nam02lp2059.outbound.protection.outlook.com [104.47.36.59]) by mx0a-002c1b01.pphosted.com with ESMTP id 2wf574uypm-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 25 Nov 2019 08:14:15 -0800 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=WjFANh4jQS9Ux9H4+waqHJvpTXX2bIMslsAto/+jRQ+neTqe9Rf4NpRVOzLvPbdP5yGCXMf5JIzS0DUE7VSOkp2X/pr2CPhB0ZXGnxVy664nHMRRQ9a3PJTBFVfvU9S/ggprAigtqDZqUMt/dtP+aAtsXhoFf+i8TgvJFlGKVGVJe6whjMBt89caX4vnxU+CVDNBVvA5ltQopgpUc+TElVBv+YMO2VGTMcpGL/9208oDCKE+Tz5dXR4zc0GdwcQoRzoZ9lHnImrD91ibUDClAlvuIuqPladHJzK1Kb/kltMh8SFm5Lb0PlPYMPR/2VzuY8yxFutzzsjsxeqT6PHs1w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=4IQ+iqQsj7K9CPcqWBTN7lcON0pDu1M3slUJZ6Myn0E=; b=cP0ZPIJjNYO+gOa19NBso0jdD9Sz60oBey6ZY5LYpc/t9W9JB7UNu4dS+bu7pSS/CukrkH0Mh9fuzQb/dDYXpHLE4d08moXPvRRqtW8tpLVoQtXVTq5ShrFQE3PnJj5G53xLmflLyzSnxeujMujlAZA80fIf7ME8620fq9xoGQkgv+10PAA6+JgntZIe5Z6r3uu9X78gVLTjfmW0ZmiGMr6poDXE+IOgXf17bzxoPEy9lqb4YjsE3nEyhXGL9rE28dnvqJsHsYkSOM5FFbjnkQ3cWffNo6NYKJvnDc+5qq4QyJcedqviBQg15UFHWQBscAR9EVDtTA4R6PcR7KrCxw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nutanix.com; dmarc=pass action=none header.from=nutanix.com; dkim=pass header.d=nutanix.com; arc=none Received: from MWHPR02MB2656.namprd02.prod.outlook.com (10.168.206.142) by MWHPR02MB2239.namprd02.prod.outlook.com (10.168.244.11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2474.17; Mon, 25 Nov 2019 16:14:13 +0000 Received: from MWHPR02MB2656.namprd02.prod.outlook.com ([fe80::f801:763d:e7fc:6bf]) by MWHPR02MB2656.namprd02.prod.outlook.com ([fe80::f801:763d:e7fc:6bf%7]) with mapi id 15.20.2474.023; Mon, 25 Nov 2019 16:14:13 +0000 From: Felipe Franciosi To: Stefan Hajnoczi , Paolo Bonzini , Daniel Berrange , "Dr . David Alan Gilbert" Subject: [PATCH] fence: introduce a file-based self-fence mechanism Thread-Topic: [PATCH] fence: introduce a file-based self-fence mechanism Thread-Index: AQHVo6tgK6WTpsMO9UiL0xGIoXZMRg== Date: Mon, 25 Nov 2019 16:14:13 +0000 Message-ID: <20191125161356.108054-1-felipe@nutanix.com> Accept-Language: en-GB, en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-clientproxiedby: AM3PR03CA0068.eurprd03.prod.outlook.com (2603:10a6:207:5::26) To MWHPR02MB2656.namprd02.prod.outlook.com (2603:10b6:300:45::14) x-ms-exchange-messagesentrepresentingtype: 1 x-mailer: git-send-email 2.20.1 x-originating-ip: [62.254.189.133] x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: 52dd4b86-8b27-4c2b-9af3-08d771c28312 x-ms-traffictypediagnostic: MWHPR02MB2239: x-ms-exchange-purlcount: 1 x-ms-exchange-transport-forked: True x-microsoft-antispam-prvs: x-proofpoint-crosstenant: true x-ms-oob-tlc-oobclassifiers: OLM:626; x-forefront-prvs: 0232B30BBC x-forefront-antispam-report: SFV:NSPM; SFS:(10019020)(39860400002)(346002)(376002)(396003)(366004)(136003)(199004)(189003)(6116002)(2616005)(71190400001)(36756003)(6506007)(478600001)(256004)(6486002)(6306002)(14454004)(102836004)(6512007)(14444005)(30864003)(71200400001)(386003)(2906002)(66066001)(99286004)(107886003)(1076003)(110136005)(54906003)(7736002)(186003)(4326008)(81166006)(81156014)(26005)(305945005)(50226002)(5660300002)(3846002)(8936002)(66556008)(66476007)(316002)(52116002)(66946007)(25786009)(86362001)(8676002)(6436002)(64756008)(66446008)(64030200001)(2004002); DIR:OUT; SFP:1102; SCL:1; SRVR:MWHPR02MB2239; H:MWHPR02MB2656.namprd02.prod.outlook.com; FPR:; SPF:None; LANG:en; PTR:InfoNoRecords; A:1; MX:1; received-spf: None (protection.outlook.com: nutanix.com does not designate permitted sender hosts) x-ms-exchange-senderadcheck: 1 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: WFytVzBsM7qIa1bz60a7RDjWW+Qx1L4IE1BkxNK2WuBdxUVwu38ZBM78HVPNjrOW9i41AWDseixXHfYp//qDGsMjPC6yp1+BKytrH/3K7u6/7Ty+as24QHokp2jMp08erqGsBF1uzxGcEF6+dodw4N04Bli67sgaFeMKcpcIAb9sk/rz8Ymr33fjnq+rcV6YEJzWPfxvF31DjSNyE0P3UP6IrdfrXIdhm4G9v2oPu4fthNNf+rIJGJRiLpiWrMCvVcTy+a2vMcpYhqVAcrO2AOU2X72XUNTfZWFh5Qron7bJtNd23czYV5egLNgckmltryTCMWxeAfWFpYGgbeq3l305KMyZekPRpmbbkQirQ/UzaZO2MAkpU/T5OOM6dHWipR93e7PIuCQDmfVWuAxzSpCttqkbbUeKFS0vUAvuWAS9cVSuKQ6fqImQ1I/iMi7WKJzsIWxhYsRF9yO0hBzLT+llgaVGDxt0PDZW08dlNh8= MIME-Version: 1.0 X-OriginatorOrg: nutanix.com X-MS-Exchange-CrossTenant-Network-Message-Id: 52dd4b86-8b27-4c2b-9af3-08d771c28312 X-MS-Exchange-CrossTenant-originalarrivaltime: 25 Nov 2019 16:14:13.5941 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: bb047546-786f-4de1-bd75-24e5b6f79043 X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: RFqSiJyhqmSYA/tWvwkOarXIT5aiQnTy6QyBiVJFRvvtPtbD3ekiZxVYWmNhdSW/FzRts/LNUPwMoWVFT+ZfYlx76e+9POR9Y6vLtDLoON8= X-MS-Exchange-Transport-CrossTenantHeadersStamped: MWHPR02MB2239 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.95,18.0.572 definitions=2019-11-25_04:2019-11-21,2019-11-25 signatures=0 X-Proofpoint-Spam-Reason: safe X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [generic] [fuzzy] X-Received-From: 148.163.151.68 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: "qemu-devel@nongnu.org" , Felipe Franciosi Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" This introduces a self-fence mechanism to Qemu, causing it to die if a heartbeat condition is not met. Currently, a file-based heartbeat is available and can be configured as follows: -object file-fence,id=ff0,file=/foo,qtimeout=20,ktimeout=25,signal=kill Qemu will watch 'file' for attribute changes. Touching the file works as a heartbeat. This parameter is mandatory. Fencing happens after 'qtimeout' or 'ktimeout' seconds elapse without a heartbeat. At least one of these must be specified. Both may be used. When using 'qtimeout', an internal Qemu timer is used. Fencing with this method gives Qemu a chance to write a log message indicating which file caused the event. If Qemu's main loop is hung for whatever reason, this method won't successfully kill Qemu. When using 'ktimeout', a kernel timer is used. In this case, 'signal' can be 'kill' (for SIGKILL, default) or 'quit' (for SIGQUIT). Using SIGQUIT may be preferred for obtaining core dumps. If Qemu is hung (eg. uninterruptable sleep), this method won't successfully kill Qemu. It is worth noting that even successfully killing Qemu may not be sufficient to completely fence a VM as certain operations like network packets or block commands may be pending in the kernel. If that is a concern, systems should consider using further fencing mechanisms like hardware watchdogs either in addition or in conjunction with this for additional protection. Signed-off-by: Felipe Franciosi --- Based-on: <20191125153619.39893-2-felipe@nutanix.com> Makefile.objs | 1 + fence/Makefile.objs | 1 + fence/file_fence.c | 381 ++++++++++++++++++++++++++++++++++++++++++++ qemu-options.hx | 27 +++- 4 files changed, 409 insertions(+), 1 deletion(-) create mode 100644 fence/Makefile.objs create mode 100644 fence/file_fence.c diff --git a/Makefile.objs b/Makefile.objs index 11ba1a36bd..998eed4796 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -75,6 +75,7 @@ common-obj-$(CONFIG_TPM) += tpm.o common-obj-y += backends/ common-obj-y += chardev/ +common-obj-y += fence/ common-obj-$(CONFIG_SECCOMP) += qemu-seccomp.o qemu-seccomp.o-cflags := $(SECCOMP_CFLAGS) diff --git a/fence/Makefile.objs b/fence/Makefile.objs new file mode 100644 index 0000000000..2ed2092568 --- /dev/null +++ b/fence/Makefile.objs @@ -0,0 +1 @@ +common-obj-y += file_fence.o diff --git a/fence/file_fence.c b/fence/file_fence.c new file mode 100644 index 0000000000..5b743e69d2 --- /dev/null +++ b/fence/file_fence.c @@ -0,0 +1,381 @@ +/* + * QEMU file-based self-fence mechanism + * + * Copyright (c) 2019 Nutanix Inc. All rights reserved. + * + * Authors: + * Felipe Franciosi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + * + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qom/object_interfaces.h" +#include "qemu/filemonitor.h" +#include "qemu/timer.h" + +#include + +#define TYPE_FILE_FENCE "file-fence" + +typedef struct FileFence { + Object parent_obj; + + gchar *dir; + gchar *file; + uint32_t qtimeout; + uint32_t ktimeout; + int signal; + + timer_t ktimer; + QEMUTimer *qtimer; + + QFileMonitor *fm; + uint64_t id; +} FileFence; + +#define FILE_FENCE(obj) \ + OBJECT_CHECK(FileFence, (obj), TYPE_FILE_FENCE) + +static void +timer_update(FileFence *ff) +{ + struct itimerspec its = { + .it_value.tv_sec = ff->ktimeout, + }; + int err; + + if (ff->qtimeout) { + timer_mod(ff->qtimer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + + ff->qtimeout * 1000); + } + + if (ff->ktimeout) { + err = timer_settime(ff->ktimer, 0, &its, NULL); + g_assert(err == 0); + } +} + +static void +file_fence_abort_cb(void *opaque) +{ + FileFence *ff = opaque; + printf("Fencing after %u seconds on '%s'\n", + ff->qtimeout, g_strconcat(ff->dir, "/", ff->file, NULL)); + abort(); +} + +static void +file_fence_watch_cb(int64_t id, QFileMonitorEvent ev, const char *file, + void *opaque) +{ + FileFence *ff = opaque; + + if (ev != QFILE_MONITOR_EVENT_ATTRIBUTES) { + return; + } + + if (g_strcmp0(file, ff->file) != 0) { + return; + } + + timer_update(ff); +} + +static void +ktimer_tear(FileFence *ff) +{ + int err; + + if (ff->ktimer) { + err = timer_delete(ff->ktimer); + g_assert(err == 0); + ff->ktimer = NULL; + } +} + +static void +ktimer_setup(FileFence *ff, Error **errp) +{ + int err; + + struct sigevent sev = { + .sigev_notify = SIGEV_SIGNAL, + .sigev_signo = ff->signal ? ff->signal : SIGKILL, + }; + + if (ff->ktimeout == 0) { + return; + } + + err = timer_create(CLOCK_MONOTONIC, &sev, &ff->ktimer); + if (err == -1) { + error_setg(errp, "Error creating kernel timer: %m"); + return; + } +} + +static void +qtimer_tear(FileFence *ff) +{ + if (ff->qtimer) { + timer_del(ff->qtimer); + timer_free(ff->qtimer); + } + ff->qtimer = NULL; +} + +static void +qtimer_setup(FileFence *ff, Error **errp) +{ + QEMUTimer *qtimer; + + if (ff->qtimeout == 0) { + return; + } + + qtimer = timer_new_ms(QEMU_CLOCK_REALTIME, file_fence_abort_cb, ff); + if (qtimer == NULL) { + error_setg(errp, "Error creating Qemu timer"); + return; + } + + ff->qtimer = qtimer; +} + +static void +watch_tear(FileFence *ff) +{ + if (ff->fm) { + qemu_file_monitor_remove_watch(ff->fm, ff->dir, ff->id); + qemu_file_monitor_free(ff->fm); + ff->fm = NULL; + ff->id = 0; + } +} + +static void +watch_setup(FileFence *ff, Error **errp) +{ + QFileMonitor *fm; + int64_t id; + + fm = qemu_file_monitor_new(errp); + if (!fm) { + return; + } + + id = qemu_file_monitor_add_watch(fm, ff->dir, ff->file, + file_fence_watch_cb, ff, errp); + if (id < 0) { + qemu_file_monitor_free(fm); + return; + } + + ff->fm = fm; + ff->id = id; +} + +static void +file_fence_complete(UserCreatable *obj, Error **errp) +{ + FileFence *ff = FILE_FENCE(obj); + + if (ff->dir == NULL) { + error_setg(errp, "A 'file' must be set"); + return; + } + + if (ff->signal != 0 && ff->ktimeout == 0) { + error_setg(errp, "Using 'signal' requires 'ktimeout' to be set"); + return; + } + + if (ff->ktimeout == 0 && ff->qtimeout == 0) { + error_setg(errp, "One or both of 'ktimeout' or 'qtimeout' must be set"); + return; + } + + if (ff->qtimeout >= ff->ktimeout) { + error_setg(errp, "Using 'qtimeout' >= 'ktimeout' doesn't make sense"); + return; + } + + watch_setup(ff, errp); + if (*errp != NULL) { + return; + } + + qtimer_setup(ff, errp); + if (*errp != NULL) { + goto err_watch; + } + + ktimer_setup(ff, errp); + if (*errp != NULL) { + goto err_qtimer; + } + + timer_update(ff); + + return; + +err_qtimer: + qtimer_tear(ff); +err_watch: + watch_tear(ff); +} + +static void +file_fence_set_signal(Object *obj, const char *value, Error **errp) +{ + FileFence *ff = FILE_FENCE(obj); + gchar *gsig; + + if (ff->signal) { + error_setg(errp, "Signal property already set"); + return; + } + + gsig = g_ascii_strup(value, -1); + + if (g_strcmp0(gsig, "QUIT") == 0) { + ff->signal = SIGQUIT; + } else + if (g_strcmp0(gsig, "KILL") == 0) { + ff->signal = SIGKILL; + } else { + error_setg(errp, "Invalid signal. Must be 'quit' or 'kill'"); + } + + g_free(gsig); +} + +static char * +file_fence_get_signal(Object *obj, Error **errp) +{ + FileFence *ff = FILE_FENCE(obj); + + switch (ff->signal) { + case SIGKILL: + return g_strdup("kill"); + case SIGQUIT: + return g_strdup("quit"); + } + + /* Unreachable */ + abort(); +} + +static void +file_fence_set_file(Object *obj, const char *value, Error **errp) +{ + FileFence *ff = FILE_FENCE(obj); + gchar *dir, *file; + + if (ff->dir) { + error_setg(errp, "File property already set"); + return; + } + + dir = g_path_get_dirname(value); + if (g_str_equal(dir, ".")) { + error_setg(errp, "Path for file-fence must be absolute"); + return; + } + + file = g_path_get_basename(value); + if (g_str_equal(file, ".")) { + error_setg(errp, "Path for file-fence must be a file"); + g_free(dir); + return; + } + + ff->dir = dir; + ff->file = file; +} + +static char * +file_fence_get_file(Object *obj, Error **errp) +{ + FileFence *ff = FILE_FENCE(obj); + + if (ff->file) { + return g_strconcat(ff->dir, "/", ff->file, NULL); + } + + return NULL; +} + +static void +file_fence_instance_finalize(Object *obj) +{ + FileFence *ff = FILE_FENCE(obj); + + ktimer_tear(ff); + qtimer_tear(ff); + watch_tear(ff); + + g_free(ff->file); + g_free(ff->dir); +} + +static void +file_fence_instance_init(Object *obj) +{ + FileFence *ff = FILE_FENCE(obj); + + object_property_add_str(obj, "file", + file_fence_get_file, + file_fence_set_file, + &error_abort); + object_property_add_str(obj, "signal", + file_fence_get_signal, + file_fence_set_signal, + &error_abort); + object_property_add_uint32_ptr(obj, "qtimeout", &ff->qtimeout, + false, &error_abort); + object_property_add_uint32_ptr(obj, "ktimeout", &ff->ktimeout, + false, &error_abort); +} + +static void +file_fence_class_init(ObjectClass *klass, void *class_data) +{ + UserCreatableClass *ucc = USER_CREATABLE_CLASS(klass); + ucc->complete = file_fence_complete; +} + +static const TypeInfo file_fence_info = { + .name = TYPE_FILE_FENCE, + .parent = TYPE_OBJECT, + .class_init = file_fence_class_init, + .instance_size = sizeof(FileFence), + .instance_init = file_fence_instance_init, + .instance_finalize = file_fence_instance_finalize, + .interfaces = (InterfaceInfo[]) { + { TYPE_USER_CREATABLE }, + { } + } +}; + +static void +register_types(void) +{ + type_register_static(&file_fence_info); +} + +type_init(register_types); diff --git a/qemu-options.hx b/qemu-options.hx index 65c9473b73..995d3d6abf 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -4929,8 +4929,33 @@ CN=laptop.example.com,O=Example Home,L=London,ST=London,C=GB @end table -ETEXI +@item -object file-fence,id=@var{id},file=@var{file},qtimeout=@var{qtimeout},ktimeout=@var{ktimeout},signal=@{signal} + +Self-fence Qemu if @var{file} is not modified within a given timeout. + +Qemu will watch @var{file} for attribute changes. Touching the file works as a +heartbeat. This parameter is mandatory. + +Fencing happens after @var{qtimeout} or @var{ktimeout} seconds elapse +without a heartbeat. At least one of these must be specified. Both may be used. +When using @var{qtimeout}, an internal Qemu timer is used. Fencing with +this method gives Qemu a chance to write a log message indicating which file +caused the event. If Qemu's main loop is hung for whatever reason, this method +won't successfully kill Qemu. + +When using @var{ktimeout}, a kernel timer is used. In this case, @var{signal} +can be 'kill' (for SIGKILL, default) or 'quit' (for SIGQUIT). Using SIGQUIT may +be preferred for obtaining core dumps. If Qemu is hung (eg. uninterruptable +sleep), this method won't successfully kill Qemu. + +It is worth noting that even successfully killing Qemu may not be sufficient to +completely fence a VM as certain operations like network packets or block +commands may be pending in the kernel. If that is a concern, systems should +consider using further fencing mechanisms like hardware watchdogs either in +addition or in conjunction with this feature for additional protection. + +ETEXI HXCOMM This is the last statement. Insert new options before this line! STEXI