From nobody Mon Mar 23 21:28:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=quarantine dis=none) header.from=suse.com ARC-Seal: i=1; a=rsa-sha256; t=1773388122; cv=none; d=zohomail.com; s=zohoarc; b=FSR6bd6hs4k9cmPOYigWXH6zOVv+YfmcZ0kVCJgyNQe/q+AiMcQwAeGHcZOv2IASjj6HzfE5ZRbqHZ6MZvZUMZuIzOYYmSsVugCIQo/gd4aKNUWO3AcrfVDkhRHX3H603uABBVdPAL+RfqkNFe73aKAjq0j1mhcn2rMxytp9Kb8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1773388122; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=pOMNch7LDMhlMuA7/SnfhE7VtklPTC8Mp2JthrXp6FM=; b=NJ3EPnToLV2ERv2giZW0hKqoqj0rP5+x2J+TcUfg5wYraV8rVIkc92QG8teTxEUXgIP1ESrFcztKMVFjrWGyob+1Eos12r+AFlYbPrFRY8fer0kD6oZ11u7afHgsEQLprVSSt/MLX5jLDTNs4MouwTHY48+VZh5H1k549lFRivI= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1773388122974384.62616378485427; Fri, 13 Mar 2026 00:48:42 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1253351.1549639 (Exim 4.92) (envelope-from ) id 1w0xFl-0004GZ-4P; Fri, 13 Mar 2026 07:48:13 +0000 Received: by outflank-mailman (output) from mailman id 1253351.1549639; Fri, 13 Mar 2026 07:48:13 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1w0xFl-0004GS-1k; Fri, 13 Mar 2026 07:48:13 +0000 Received: by outflank-mailman (input) for mailman id 1253351; Fri, 13 Mar 2026 07:48:11 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1w0xFj-0003TG-DM for xen-devel@lists.xenproject.org; Fri, 13 Mar 2026 07:48:11 +0000 Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.223.131]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id fb1de7e2-1eb0-11f1-b164-2bf370ae4941; Fri, 13 Mar 2026 08:48:10 +0100 (CET) Received: from imap1.dmz-prg2.suse.org (unknown [10.150.64.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id 0BB825CEF2; Fri, 13 Mar 2026 07:48:10 +0000 (UTC) Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id DEF51403F6; Fri, 13 Mar 2026 07:48:09 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id x6BCNTnBs2m1GAAAD6G6ig (envelope-from ); Fri, 13 Mar 2026 07:48:09 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: fb1de7e2-1eb0-11f1-b164-2bf370ae4941 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1773388090; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=pOMNch7LDMhlMuA7/SnfhE7VtklPTC8Mp2JthrXp6FM=; b=mv1paiadsjWVfW8yV3KF2x9/U5KPiDFrjBM2mhfK5Q4HkuKa1iyPzd/jP/OfeK3S7RTIHN ukbOc+khzCJbf4bjLfGAPF1RU+38nrQ/DEQ3OlxjLMScnnRH2BACo660X1Ro5qIhc+ShkW zF2PEdbxVZbnAqRp3rGbN2H1t71x97M= Authentication-Results: smtp-out2.suse.de; none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1773388090; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=pOMNch7LDMhlMuA7/SnfhE7VtklPTC8Mp2JthrXp6FM=; b=mv1paiadsjWVfW8yV3KF2x9/U5KPiDFrjBM2mhfK5Q4HkuKa1iyPzd/jP/OfeK3S7RTIHN ukbOc+khzCJbf4bjLfGAPF1RU+38nrQ/DEQ3OlxjLMScnnRH2BACo660X1Ro5qIhc+ShkW zF2PEdbxVZbnAqRp3rGbN2H1t71x97M= From: Juergen Gross To: xen-devel@lists.xenproject.org Cc: Juergen Gross , Anthony PERARD , Julien Grall Subject: [PATCH 3/8] tools/libs/store: add support to use watches with a depth parameter Date: Fri, 13 Mar 2026 08:47:46 +0100 Message-ID: <20260313074751.2904215-4-jgross@suse.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260313074751.2904215-1-jgross@suse.com> References: <20260313074751.2904215-1-jgross@suse.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Spamd-Result: default: False [-6.80 / 50.00]; REPLY(-4.00)[]; BAYES_HAM(-3.00)[100.00%]; NEURAL_HAM_LONG(-1.00)[-1.000]; MID_CONTAINS_FROM(1.00)[]; R_MISSING_CHARSET(0.50)[]; NEURAL_HAM_SHORT(-0.20)[-1.000]; MIME_GOOD(-0.10)[text/plain]; RCVD_COUNT_TWO(0.00)[2]; FROM_HAS_DN(0.00)[]; ARC_NA(0.00)[]; MIME_TRACE(0.00)[0:+]; TO_DN_SOME(0.00)[]; TO_MATCH_ENVRCPT_ALL(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[]; FROM_EQ_ENVFROM(0.00)[]; DKIM_SIGNED(0.00)[suse.com:s=susede1]; FUZZY_RATELIMITED(0.00)[rspamd.com]; RCPT_COUNT_THREE(0.00)[4]; DBL_BLOCKED_OPENRESOLVER(0.00)[imap1.dmz-prg2.suse.org:helo,suse.com:mid,suse.com:email]; RCVD_TLS_ALL(0.00)[] X-Spam-Flag: NO X-Spam-Score: -6.80 X-Spam-Level: X-ZohoMail-DKIM: pass (identity @suse.com) X-ZM-MESSAGEID: 1773388126944154100 Content-Type: text/plain; charset="utf-8" Add a new xs_watch_depth() function to libxenstore allowing to limit the scope of a Xenstore watch. It can be used only in case Xenstore is supporting the XENSTORE_SERVER_FEATURE_WATCHDEPTH feature. For convenience add a xs_watch_try_depth() wrapper, which will call xs_watch_depth() if supported and xs_watch() otherwise. Cache the supported features of Xenstore in order not having to get them from Xenstore for each call of one of the new functions. Signed-off-by: Juergen Gross --- docs/man/xl.cfg.5.pod.in | 6 ++ tools/include/xenstore.h | 16 +++++ tools/libs/store/libxenstore.map | 2 + tools/libs/store/xs.c | 116 ++++++++++++++++++++++++++----- xen/include/public/io/xs_wire.h | 2 + 5 files changed, 123 insertions(+), 19 deletions(-) diff --git a/docs/man/xl.cfg.5.pod.in b/docs/man/xl.cfg.5.pod.in index 3aac0bc4fb..2f77016ecf 100644 --- a/docs/man/xl.cfg.5.pod.in +++ b/docs/man/xl.cfg.5.pod.in @@ -740,6 +740,12 @@ Xenstore is capable to reconnect to a guest. Xenstore will present an error value in case it disconnects due to an error condition. =20 +=3Ditem B<0x00000004> + +Xenstore supports to set watches with a limited depth (depth 0 matches +only the watched node, depth 1 matches the node and its direct children, +etc.). + =3Dback =20 The features supported by the running Xenstore instance can be retrieved diff --git a/tools/include/xenstore.h b/tools/include/xenstore.h index 6b661e5895..8a6afd97f5 100644 --- a/tools/include/xenstore.h +++ b/tools/include/xenstore.h @@ -177,6 +177,22 @@ bool xs_set_permissions(struct xs_handle *h, xs_transa= ction_t t, */ bool xs_watch(struct xs_handle *h, const char *path, const char *token); =20 +/* Same as xs_watch(), but with limiting the matching for modified + * children to a specified depth (depth 0 only matches the node itself, + * depth 1 will additionally match direct children of the node, etc.). + * Only supported if the XENSTORE_SERVER_FEATURE_WATCHDEPTH (4) is set + * in the returned features of xs_get_features_supported(). + */ +bool xs_watch_depth(struct xs_handle *h, const char *path, const char *tok= en, + unsigned int depth); + +/* If supported, same as xs_watch_depth(), use xs_watch() otherwise. + * As a result watches might trigger for nodes below the watched path, too. + * Not to be used for special watches! + */ +bool xs_watch_try_depth(struct xs_handle *h, const char *path, + const char *token, unsigned int depth); + /* Return the FD to poll on to see if a watch has fired. */ int xs_fileno(struct xs_handle *h); =20 diff --git a/tools/libs/store/libxenstore.map b/tools/libs/store/libxenstor= e.map index a08ddd549f..7067068998 100644 --- a/tools/libs/store/libxenstore.map +++ b/tools/libs/store/libxenstore.map @@ -52,4 +52,6 @@ VERS_4.2 { xs_set_global_quota; xs_get_domain_quota; xs_set_domain_quota; + xs_watch_depth; + xs_watch_try_depth; } VERS_4.1; diff --git a/tools/libs/store/xs.c b/tools/libs/store/xs.c index dda37f7526..0bea464a33 100644 --- a/tools/libs/store/xs.c +++ b/tools/libs/store/xs.c @@ -984,37 +984,29 @@ bool xs_restrict(struct xs_handle *h, unsigned domid) return false; } =20 -/* Watch a node for changes (poll on fd to detect, or call read_watch()). - * When the node (or any child) changes, fd will become readable. - * Token is returned when watch is read, to allow matching. - * Returns false on failure. - */ -bool xs_watch(struct xs_handle *h, const char *path, const char *token) +static bool xs_watch_helper(struct xs_handle *h) { - struct xsd_sockmsg msg =3D { .type =3D XS_WATCH }; - struct iovec iov[3]; - #ifdef USE_PTHREAD + sigset_t set, old_set; + pthread_attr_t attr; + static size_t stack_size; +#ifdef USE_DLSYM + size_t (*getsz)(pthread_attr_t *attr); +#endif + #define DEFAULT_THREAD_STACKSIZE (16 * 1024) /* NetBSD doesn't have PTHREAD_STACK_MIN. */ #ifndef PTHREAD_STACK_MIN # define PTHREAD_STACK_MIN 0 #endif =20 -#define READ_THREAD_STACKSIZE \ - ((DEFAULT_THREAD_STACKSIZE < PTHREAD_STACK_MIN) ? \ +#define READ_THREAD_STACKSIZE \ + ((DEFAULT_THREAD_STACKSIZE < PTHREAD_STACK_MIN) ? \ PTHREAD_STACK_MIN : DEFAULT_THREAD_STACKSIZE) =20 /* We dynamically create a reader thread on demand. */ mutex_lock(&h->request_mutex); if (!h->read_thr_exists) { - sigset_t set, old_set; - pthread_attr_t attr; - static size_t stack_size; -#ifdef USE_DLSYM - size_t (*getsz)(pthread_attr_t *attr); -#endif - if (pthread_attr_init(&attr) !=3D 0) { mutex_unlock(&h->request_mutex); return false; @@ -1050,16 +1042,89 @@ bool xs_watch(struct xs_handle *h, const char *path= , const char *token) mutex_unlock(&h->request_mutex); #endif =20 + return true; +} + +/* Watch a node for changes (poll on fd to detect, or call read_watch()). + * When the node (or any child) changes, fd will become readable. + * Token is returned when watch is read, to allow matching. + * Returns false on failure. + */ +bool xs_watch(struct xs_handle *h, const char *path, const char *token) +{ + struct xsd_sockmsg msg =3D { .type =3D XS_WATCH }; + struct iovec iov[3]; + + if (!xs_watch_helper(h)) + return false; + + iov[0].iov_base =3D &msg; + iov[0].iov_len =3D sizeof(msg); + iov[1].iov_base =3D (void *)path; + iov[1].iov_len =3D strlen(path) + 1; + iov[2].iov_base =3D (void *)token; + iov[2].iov_len =3D strlen(token) + 1; + + return xs_bool(xs_talkv(h, iov, ARRAY_SIZE(iov), NULL)); +} + +/* Same as xs_watch(), but with limiting the matching for modified + * children to a specified depth (depth 0 only matches the node itself, + * depth 1 will additionally match direct children of the node, etc.). + * Only supported if the XENSTORE_SERVER_FEATURE_WATCHDEPTH (4) is set + * in the returned features of xs_get_features_supported(). + */ +bool xs_watch_depth(struct xs_handle *h, const char *path, const char *tok= en, + unsigned int depth) +{ + struct xsd_sockmsg msg =3D { .type =3D XS_WATCH }; + struct iovec iov[4]; + char depthstr[MAX_STRLEN(depth)]; + static bool depth_supported; + + if (!xs_watch_helper(h)) + return false; + + if (!depth_supported) { + unsigned int features; + + if (!xs_get_features_supported(h, &features)) + return false; + if (!(features & XENSTORE_SERVER_FEATURE_WATCHDEPTH)) + return false; + depth_supported =3D true; + } + + snprintf(depthstr, sizeof(depthstr), "%u", depth); + iov[0].iov_base =3D &msg; iov[0].iov_len =3D sizeof(msg); iov[1].iov_base =3D (void *)path; iov[1].iov_len =3D strlen(path) + 1; iov[2].iov_base =3D (void *)token; iov[2].iov_len =3D strlen(token) + 1; + iov[3].iov_base =3D depthstr; + iov[3].iov_len =3D strlen(depthstr) + 1; =20 return xs_bool(xs_talkv(h, iov, ARRAY_SIZE(iov), NULL)); } =20 +/* If supported, same as xs_watch_depth(), use xs_watch() otherwise. + * As a result watches might trigger for nodes below the watched path, too. + * Not to be used for special watches! + */ +bool xs_watch_try_depth(struct xs_handle *h, const char *path, + const char *token, unsigned int depth) +{ + unsigned int features; + + if (xs_get_features_supported(h, &features) && + (features & XENSTORE_SERVER_FEATURE_WATCHDEPTH) && + xs_watch_depth(h, path, token, depth)) + return true; + + return xs_watch(h, path, token); +} =20 /* Clear the pipe token if there are no more pending watchs. * We suppose the watch_mutex is already taken. @@ -1420,13 +1485,26 @@ static bool xs_uint(char *reply, unsigned int *uint= val) =20 bool xs_get_features_supported(struct xs_handle *h, unsigned int *features) { + static unsigned int own_features =3D 0; + static bool features_valid =3D false; struct xsd_sockmsg msg =3D { .type =3D XS_GET_FEATURE }; struct iovec iov[1]; =20 + if (features_valid) { + *features =3D own_features; + return true; + } + iov[0].iov_base =3D &msg; iov[0].iov_len =3D sizeof(msg); =20 - return xs_uint(xs_talkv(h, iov, ARRAY_SIZE(iov), NULL), features); + if (!xs_uint(xs_talkv(h, iov, ARRAY_SIZE(iov), NULL), &own_features)) + return false; + + features_valid =3D true; + *features =3D own_features; + + return true; } =20 bool xs_get_features_domain(struct xs_handle *h, unsigned int domid, diff --git a/xen/include/public/io/xs_wire.h b/xen/include/public/io/xs_wir= e.h index d2e2b8b9eb..2e763bc877 100644 --- a/xen/include/public/io/xs_wire.h +++ b/xen/include/public/io/xs_wire.h @@ -124,6 +124,8 @@ struct xenstore_domain_interface { #define XENSTORE_SERVER_FEATURE_RECONNECTION 1 /* The presence of the "error" field in the ring page */ #define XENSTORE_SERVER_FEATURE_ERROR 2 +/* The XS_WATCH command can be used with a parameter */ +#define XENSTORE_SERVER_FEATURE_WATCHDEPTH 4 =20 /* Valid values for the connection field */ #define XENSTORE_CONNECTED 0 /* the steady-state */ --=20 2.53.0