From nobody Mon Mar 23 21:24:11 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=1774018935; cv=none; d=zohomail.com; s=zohoarc; b=jcrVyu2c13bwJlUc11JMyMFl5i1eXu52LdRQ4lLEILRmxgRcnfYBgGdPceGKoKWiTjoy93Smp51epvncvJ+4uEpuD6v+fLdJHmKE8ZQqYFdznGaQUUGc6kz+ISrINUXwYKNN56iW8arllH0R3vBIFIBS5LFSSLCiRhLlOKCzyts= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1774018935; 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=/PcS/7XQ557sIjqSKbSX5CF48BnA+Ztcs9ICymueV/w=; b=GUSSwg263sJqgOvU7Urfq0VmlHZxZ4IBOk/fzhVVLktC2C8+ZK3Ubd6yQqXfduTIhak55pp1s8vz/3COkYKM/sKehQHuGz702VqwHg9pH4H4vHvUg0yl6w5JzcBXwoiOWclr6jQhZb9QRZ7aSs+cU5fu/ejOOdEaubN8Lz5OCFs= 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 1774018935027456.6585447798318; Fri, 20 Mar 2026 08:02:15 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1258099.1552275 (Exim 4.92) (envelope-from ) id 1w3bME-0002LV-0l; Fri, 20 Mar 2026 15:01:50 +0000 Received: by outflank-mailman (output) from mailman id 1258099.1552275; Fri, 20 Mar 2026 15:01:49 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1w3bMD-0002LL-T7; Fri, 20 Mar 2026 15:01:49 +0000 Received: by outflank-mailman (input) for mailman id 1258099; Fri, 20 Mar 2026 15:01:48 +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 1w3bMC-0001Ve-Mg for xen-devel@lists.xenproject.org; Fri, 20 Mar 2026 15:01:48 +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 b7b941d6-246d-11f1-b164-2bf370ae4941; Fri, 20 Mar 2026 16:01:47 +0100 (CET) Received: from imap1.dmz-prg2.suse.org (imap1.dmz-prg2.suse.org [IPv6:2a07:de40:b281:104: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 6C9315BDF1; Fri, 20 Mar 2026 15:01:38 +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 4BD3842866; Fri, 20 Mar 2026 15:01:38 +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 Y4FYEVJhvWk/XAAAD6G6ig (envelope-from ); Fri, 20 Mar 2026 15:01:38 +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: b7b941d6-246d-11f1-b164-2bf370ae4941 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1774018903; 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=/PcS/7XQ557sIjqSKbSX5CF48BnA+Ztcs9ICymueV/w=; b=gy+MTAPWgRFjoGgXB1ttiyIPkAjxMVtyZdEUOgaB3d2DlHxd0WrsqKlHqnifDzVlzQSMDL 6sGO1hBya4UEn3XDGDbaUbmfK3HZYt+HZxO3S5Mt8610sRM4QxqlvB0u9ephMD4LqU+Izg YbLcgsyYyorCh0BE7I3phFBg8fO1Wyc= Authentication-Results: smtp-out2.suse.de; dkim=pass header.d=suse.com header.s=susede1 header.b=mo9MZ39Y DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1774018898; 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=/PcS/7XQ557sIjqSKbSX5CF48BnA+Ztcs9ICymueV/w=; b=mo9MZ39Y5662BNkZptfC09SxsSkiAc69252f8BV5wnxo7KdUdqaT7Rt06zYTdPb4uQhgR1 xNrFkjaSWYmqtnhcWG7ZEFbOYGqC6RnaVprSLd4TDAXDE6/bmVG0TXCJS8QdOsPAN4lY0R JjtXTzMIq0GNwetNUMU6Idh10eq9L3M= From: Juergen Gross To: xen-devel@lists.xenproject.org Cc: Juergen Gross , Julien Grall , Anthony PERARD Subject: [PATCH v2 03/12] tools/xenstored: add central quota check functions Date: Fri, 20 Mar 2026 16:01:11 +0100 Message-ID: <20260320150120.874878-4-jgross@suse.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260320150120.874878-1-jgross@suse.com> References: <20260320150120.874878-1-jgross@suse.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Spamd-Result: default: False [-3.01 / 50.00]; BAYES_HAM(-3.00)[100.00%]; NEURAL_HAM_LONG(-1.00)[-1.000]; MID_CONTAINS_FROM(1.00)[]; R_MISSING_CHARSET(0.50)[]; R_DKIM_ALLOW(-0.20)[suse.com:s=susede1]; NEURAL_HAM_SHORT(-0.20)[-1.000]; MIME_GOOD(-0.10)[text/plain]; MX_GOOD(-0.01)[]; ARC_NA(0.00)[]; RBL_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[2a07:de40:b281:104:10:150:64:97:from]; RCVD_COUNT_TWO(0.00)[2]; MIME_TRACE(0.00)[0:+]; RCVD_VIA_SMTP_AUTH(0.00)[]; SPAMHAUS_XBL(0.00)[2a07:de40:b281:104:10:150:64:97:from]; TO_DN_SOME(0.00)[]; FUZZY_RATELIMITED(0.00)[rspamd.com]; RECEIVED_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[2a07:de40:b281:106:10:150:64:167:received]; FROM_HAS_DN(0.00)[]; TO_MATCH_ENVRCPT_ALL(0.00)[]; DBL_BLOCKED_OPENRESOLVER(0.00)[suse.com:mid,suse.com:dkim,suse.com:email,imap1.dmz-prg2.suse.org:helo,imap1.dmz-prg2.suse.org:rdns]; RCVD_TLS_ALL(0.00)[]; FROM_EQ_ENVFROM(0.00)[]; RCPT_COUNT_THREE(0.00)[4]; DKIM_SIGNED(0.00)[suse.com:s=susede1]; DKIM_TRACE(0.00)[suse.com:+] X-Rspamd-Action: no action X-Spam-Flag: NO X-Spam-Score: -3.01 X-Spam-Level: X-Rspamd-Server: rspamd1.dmz-prg2.suse.org X-Rspamd-Queue-Id: 6C9315BDF1 X-ZohoMail-DKIM: pass (identity @suse.com) (identity @suse.com) X-ZM-MESSAGEID: 1774018937267154100 Content-Type: text/plain; charset="utf-8" Add central functions for checking a value (either an absolute one or the current domain value plus an offset) against a specific quota. This is in preparation of introducing per-domain quota. The required changes allow to drop the "update" parameter from domain_nbentry_fix(). While at it, make the returned error for exceeded quota consistent by changing one instance from "E2BIG" to "ENOSPC". Signed-off-by: Juergen Gross Reviewed-by: Anthony PERARD --- V2: - expand commit message (Anthony Perard) - rename domain_check_quota_*() to domain_quota_*_exceeds() (Jason Andryuk) --- tools/xenstored/core.c | 4 +- tools/xenstored/domain.c | 74 +++++++++++++++++------------------ tools/xenstored/domain.h | 6 +-- tools/xenstored/transaction.c | 2 +- tools/xenstored/watch.c | 4 +- 5 files changed, 42 insertions(+), 48 deletions(-) diff --git a/tools/xenstored/core.c b/tools/xenstored/core.c index e4d2fd4876..e86d947be4 100644 --- a/tools/xenstored/core.c +++ b/tools/xenstored/core.c @@ -1539,7 +1539,7 @@ static struct node *create_node(struct connection *co= nn, const void *ctx, for (i =3D node; i; i =3D i->parent) { /* i->parent is set for each new node, so check quota. */ if (i->parent && - domain_nbentry(conn) >=3D hard_quotas[ACC_NODES].val) { + domain_quota_add_exceeds(conn->domain, ACC_NODES, 1)) { ret =3D ENOSPC; goto err; } @@ -2321,7 +2321,7 @@ void setup_structure(bool live_update) manual_node("/tool/xenstored", NULL); manual_node("@releaseDomain", NULL); manual_node("@introduceDomain", NULL); - domain_nbentry_fix(priv_domid, 5, true); + domain_nbentry_fix(priv_domid, 5); } } =20 diff --git a/tools/xenstored/domain.c b/tools/xenstored/domain.c index a70acddf94..21f6f13f83 100644 --- a/tools/xenstored/domain.c +++ b/tools/xenstored/domain.c @@ -389,6 +389,25 @@ void wrl_apply_debit_trans_commit(struct connection *c= onn) wrl_apply_debit_actual(conn->domain); } =20 +static bool domain_quota_val_exceeds(struct domain *d, enum accitem what, + unsigned int val) +{ + unsigned int quota =3D hard_quotas[what].val; + + if (!quota || !domid_is_unprivileged(d->domid)) + return false; + + return val >=3D quota; +} + +bool domain_quota_add_exceeds(struct domain *d, enum accitem what, int add) +{ + if (add < 0 || !d) + return false; + + return domain_quota_val_exceeds(d, what, d->acc[what].val + add); +} + static bool check_indexes(XENSTORE_RING_IDX cons, XENSTORE_RING_IDX prod) { return ((prod - cons) <=3D XENSTORE_RING_SIZE); @@ -490,10 +509,9 @@ static bool domain_can_read(struct connection *conn) if (domain_is_unprivileged(conn)) { if (domain->wrl_credit < 0) return false; - if (domain->acc[ACC_OUTST].val >=3D hard_quotas[ACC_OUTST].val) + if (domain_quota_add_exceeds(domain, ACC_OUTST, 0)) return false; - if (domain->acc[ACC_MEM].val >=3D hard_quotas[ACC_MEM].val && - hard_quotas[ACC_MEM].val) + if (domain_quota_add_exceeds(domain, ACC_MEM, 0)) return false; } =20 @@ -916,16 +934,20 @@ do { \ =20 int acc_fix_domains(struct list_head *head, bool chk_quota, bool update) { + struct domain *d; struct changed_domain *cd; - int cnt; =20 list_for_each_entry(cd, head, list) { - cnt =3D domain_nbentry_fix(cd->domid, cd->acc[ACC_NODES], update); - if (!update) { - if (chk_quota && cnt >=3D hard_quotas[ACC_NODES].val) - return ENOSPC; - if (cnt < 0) + if (update) { + domain_nbentry_fix(cd->domid, cd->acc[ACC_NODES]); + } else if (chk_quota) { + d =3D find_or_alloc_existing_domain(cd->domid); + + if (!d) return ENOMEM; + if (domain_quota_add_exceeds(d, ACC_NODES, + cd->acc[ACC_NODES])) + return ENOSPC; } } =20 @@ -1763,7 +1785,7 @@ bool domain_max_chk(const struct connection *conn, en= um accitem what, if (!conn || !conn->domain) return false; =20 - if (domain_is_unprivileged(conn) && val > hard_quotas[what].val) + if (domain_quota_val_exceeds(conn->domain, what, val)) return true; =20 domain_acc_valid_max(conn->domain, what, val); @@ -1783,21 +1805,9 @@ int domain_nbentry_dec(struct connection *conn, unsi= gned int domid) ? errno : 0; } =20 -int domain_nbentry_fix(unsigned int domid, int num, bool update) -{ - int ret; - - ret =3D domain_acc_add(NULL, domid, ACC_NODES, update ? num : 0, update); - if (ret < 0 || update) - return ret; - - return domid_is_unprivileged(domid) ? ret + num : 0; -} - -unsigned int domain_nbentry(struct connection *conn) +int domain_nbentry_fix(unsigned int domid, int num) { - return domain_is_unprivileged(conn) - ? domain_acc_add(conn, conn->id, ACC_NODES, 0, true) : 0; + return domain_acc_add(NULL, domid, ACC_NODES, num, true); } =20 static bool domain_chk_quota(struct connection *conn, unsigned int mem) @@ -1812,7 +1822,7 @@ static bool domain_chk_quota(struct connection *conn,= unsigned int mem) domain =3D conn->domain; now =3D time(NULL); =20 - if (mem >=3D hard_quotas[ACC_MEM].val && hard_quotas[ACC_MEM].val) { + if (domain_quota_val_exceeds(domain, ACC_MEM, mem)) { if (domain->hard_quota_reported) return true; syslog(LOG_ERR, "Domain %u exceeds hard memory quota, Xenstore interface= to domain stalled\n", @@ -1888,13 +1898,6 @@ void domain_watch_dec(struct connection *conn) domain_acc_add(conn, conn->id, ACC_WATCH, -1, true); } =20 -int domain_watch(struct connection *conn) -{ - return (domain_is_unprivileged(conn)) - ? domain_acc_add(conn, conn->id, ACC_WATCH, 0, true) - : 0; -} - void domain_outstanding_inc(struct connection *conn) { domain_acc_add(conn, conn->id, ACC_OUTST, 1, true); @@ -1915,13 +1918,6 @@ void domain_transaction_dec(struct connection *conn) domain_acc_add(conn, conn->id, ACC_TRANS, -1, true); } =20 -unsigned int domain_transaction_get(struct connection *conn) -{ - return (domain_is_unprivileged(conn)) - ? domain_acc_add(conn, conn->id, ACC_TRANS, 0, true) - : 0; -} - const char *dump_state_connections(FILE *fp) { const char *ret =3D NULL; diff --git a/tools/xenstored/domain.h b/tools/xenstored/domain.h index 28186ccac0..29b91fc783 100644 --- a/tools/xenstored/domain.h +++ b/tools/xenstored/domain.h @@ -113,8 +113,7 @@ int domain_alloc_permrefs(struct node_perms *perms); /* Quota manipulation */ int domain_nbentry_inc(struct connection *conn, unsigned int domid); int domain_nbentry_dec(struct connection *conn, unsigned int domid); -int domain_nbentry_fix(unsigned int domid, int num, bool update); -unsigned int domain_nbentry(struct connection *conn); +int domain_nbentry_fix(unsigned int domid, int num); int domain_memory_add(struct connection *conn, unsigned int domid, int mem, bool no_quota_check); =20 @@ -141,12 +140,10 @@ static inline void domain_memory_add_nochk(struct con= nection *conn, } void domain_watch_inc(struct connection *conn); void domain_watch_dec(struct connection *conn); -int domain_watch(struct connection *conn); void domain_outstanding_inc(struct connection *conn); void domain_outstanding_dec(struct connection *conn, unsigned int domid); void domain_transaction_inc(struct connection *conn); void domain_transaction_dec(struct connection *conn); -unsigned int domain_transaction_get(struct connection *conn); int domain_get_quota(const void *ctx, struct connection *conn, unsigned int domid); =20 @@ -161,6 +158,7 @@ int domain_max_global_acc(const void *ctx, struct conne= ction *conn); void domain_reset_global_acc(void); bool domain_max_chk(const struct connection *conn, enum accitem what, unsigned int val); +bool domain_quota_add_exceeds(struct domain *d, enum accitem what, int add= ); =20 extern long wrl_ntransactions; =20 diff --git a/tools/xenstored/transaction.c b/tools/xenstored/transaction.c index 167cd597fd..47cd6ecd3c 100644 --- a/tools/xenstored/transaction.c +++ b/tools/xenstored/transaction.c @@ -470,7 +470,7 @@ int do_transaction_start(const void *ctx, struct connec= tion *conn, if (conn->transaction) return EBUSY; =20 - if (domain_transaction_get(conn) > hard_quotas[ACC_TRANS].val) + if (domain_quota_add_exceeds(conn->domain, ACC_TRANS, 1)) return ENOSPC; =20 /* Attach transaction to ctx for autofree until it's complete */ diff --git a/tools/xenstored/watch.c b/tools/xenstored/watch.c index b66a9f1a39..becb9c339d 100644 --- a/tools/xenstored/watch.c +++ b/tools/xenstored/watch.c @@ -220,8 +220,8 @@ int do_watch(const void *ctx, struct connection *conn, = struct buffered_data *in) return EEXIST; } =20 - if (domain_watch(conn) > hard_quotas[ACC_WATCH].val) - return E2BIG; + if (domain_quota_add_exceeds(conn->domain, ACC_WATCH, 1)) + return ENOSPC; =20 watch =3D add_watch(conn, vec[0], vec[1], relative, false); if (!watch) --=20 2.53.0