From nobody Mon Feb 9 16:19:51 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=1674209143; cv=none; d=zohomail.com; s=zohoarc; b=jpntqWVjETt7M4pEh4AvjpQh8Dol1mX3gj2FjBuAhM5OnNzbiNmB7AiBO1HjK38G6alOyyqzvR3Sx2XpZ6gq/gkYjO6C8J6TcxlEGtDjCPCDUuXqEg6m+LrJgnoJxtNfU5gEGymAf8KFwh5TSEYt4dVDakJuv2mJwGxpu/fz+WE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1674209143; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=JJSfuNILKcRkQDqI4XTWSKAohkvwxo/7nLNUOQBwvSI=; b=aUX0+j5TDRNaE/4+ydZvo05GKOfe5nuAVLfpRcDnRLdXN7UmoS02oXTl5/2MqdLhg8SomZavsXhhKJRs2yBm3JuaKYSfHiybuSPHuRAxVexFv/XBT7cRwdyWZsXpi1nByZyxpBXV102j7hqJPAKGkDtkMZJKvwhcEfOMvONFSDQ= 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 1674209143138300.0728158433001; Fri, 20 Jan 2023 02:05:43 -0800 (PST) Received: from list by lists.xenproject.org with outflank-mailman.481598.746627 (Exim 4.92) (envelope-from ) id 1pIoGq-0006BM-HN; Fri, 20 Jan 2023 10:05:16 +0000 Received: by outflank-mailman (output) from mailman id 481598.746627; Fri, 20 Jan 2023 10:05:16 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1pIoGq-0006BD-EO; Fri, 20 Jan 2023 10:05:16 +0000 Received: by outflank-mailman (input) for mailman id 481598; Fri, 20 Jan 2023 10:05:14 +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 1pIoDV-0001Kj-Dc for xen-devel@lists.xenproject.org; Fri, 20 Jan 2023 10:01:49 +0000 Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.220.28]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id 734a4554-98a9-11ed-91b6-6bf2151ebd3b; Fri, 20 Jan 2023 11:01:47 +0100 (CET) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id DA4FE22A09; Fri, 20 Jan 2023 10:01:46 +0000 (UTC) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id AD1571390C; Fri, 20 Jan 2023 10:01:46 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id /cDhKIpmymOqRQAAMHmgww (envelope-from ); Fri, 20 Jan 2023 10:01:46 +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: 734a4554-98a9-11ed-91b6-6bf2151ebd3b DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1674208906; 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=JJSfuNILKcRkQDqI4XTWSKAohkvwxo/7nLNUOQBwvSI=; b=cJCwuxjlNNqoOJ2gBa6O0851P8a5V531LqvLKnZ5P8pjVt9mKlCe1ww4Sxihl4cf5p8Jy2 jwI2AdBbvfnPrTyiZwTNGk3WSGBy4TQ7yQrVY0FsNx5LS1zR2+xmbdw4fJSDXK4ORhugCb 5isdLZD95h+szi9cykVkdVu2o3XMroU= From: Juergen Gross To: xen-devel@lists.xenproject.org Cc: Juergen Gross , Wei Liu , Julien Grall , Anthony PERARD Subject: [PATCH v2 13/13] tools/xenstore: switch quota management to be table based Date: Fri, 20 Jan 2023 11:00:28 +0100 Message-Id: <20230120100028.11142-14-jgross@suse.com> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20230120100028.11142-1-jgross@suse.com> References: <20230120100028.11142-1-jgross@suse.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @suse.com) X-ZM-MESSAGEID: 1674209145276100003 Content-Type: text/plain; charset="utf-8" Instead of having individual quota variables switch to a table based approach like the generic accounting. Include all the related data in the same table and add accessor functions. This enables to use the command line --quota parameter for setting all possible quota values, keeping the previous parameters for compatibility. Signed-off-by: Juergen Gross --- V2: - new patch One further remark: it would be rather easy to add soft-quota for all the other quotas (similar to the memory one). This could be used as an early warning for the need to raise global quota. --- tools/xenstore/xenstored_control.c | 43 ++------ tools/xenstore/xenstored_core.c | 85 ++++++++-------- tools/xenstore/xenstored_core.h | 10 -- tools/xenstore/xenstored_domain.c | 132 +++++++++++++++++-------- tools/xenstore/xenstored_domain.h | 12 ++- tools/xenstore/xenstored_transaction.c | 5 +- tools/xenstore/xenstored_watch.c | 2 +- 7 files changed, 155 insertions(+), 134 deletions(-) diff --git a/tools/xenstore/xenstored_control.c b/tools/xenstore/xenstored_= control.c index a2ba64a15c..75f51a80db 100644 --- a/tools/xenstore/xenstored_control.c +++ b/tools/xenstore/xenstored_control.c @@ -221,35 +221,6 @@ static int do_control_log(const void *ctx, struct conn= ection *conn, return 0; } =20 -struct quota { - const char *name; - int *quota; - const char *descr; -}; - -static const struct quota hard_quotas[] =3D { - { "nodes", "a_nb_entry_per_domain, "Nodes per domain" }, - { "watches", "a_nb_watch_per_domain, "Watches per domain" }, - { "transactions", "a_max_transaction, "Transactions per domain" }, - { "outstanding", "a_req_outstanding, - "Outstanding requests per domain" }, - { "transaction-nodes", "a_trans_nodes, - "Max. number of accessed nodes per transaction" }, - { "memory", "a_memory_per_domain_hard, - "Total Xenstore memory per domain (error level)" }, - { "node-size", "a_max_entry_size, "Max. size of a node" }, - { "path-max", "a_max_path_len, "Max. length of a node path" }, - { "permissions", "a_nb_perms_per_node, - "Max. number of permissions per node" }, - { NULL, NULL, NULL } -}; - -static const struct quota soft_quotas[] =3D { - { "memory", "a_memory_per_domain_soft, - "Total Xenstore memory per domain (warning level)" }, - { NULL, NULL, NULL } -}; - static int quota_show_current(const void *ctx, struct connection *conn, const struct quota *quotas) { @@ -260,9 +231,11 @@ static int quota_show_current(const void *ctx, struct = connection *conn, if (!resp) return ENOMEM; =20 - for (i =3D 0; quotas[i].quota; i++) { + for (i =3D 0; i < ACC_N; i++) { + if (!quotas[i].name) + continue; resp =3D talloc_asprintf_append(resp, "%-17s: %8d %s\n", - quotas[i].name, *quotas[i].quota, + quotas[i].name, quotas[i].val, quotas[i].descr); if (!resp) return ENOMEM; @@ -274,7 +247,7 @@ static int quota_show_current(const void *ctx, struct c= onnection *conn, } =20 static int quota_set(const void *ctx, struct connection *conn, - char **vec, int num, const struct quota *quotas) + char **vec, int num, struct quota *quotas) { unsigned int i; int val; @@ -286,9 +259,9 @@ static int quota_set(const void *ctx, struct connection= *conn, if (val < 1) return EINVAL; =20 - for (i =3D 0; quotas[i].quota; i++) { - if (!strcmp(vec[0], quotas[i].name)) { - *quotas[i].quota =3D val; + for (i =3D 0; i < ACC_N; i++) { + if (quotas[i].name && !strcmp(vec[0], quotas[i].name)) { + quotas[i].val =3D val; send_ack(conn, XS_CONTROL); return 0; } diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_cor= e.c index c34de5ca3a..6d71cb5a2c 100644 --- a/tools/xenstore/xenstored_core.c +++ b/tools/xenstore/xenstored_core.c @@ -89,17 +89,6 @@ unsigned int trace_flags =3D TRACE_OBJ | TRACE_IO; =20 static const char *sockmsg_string(enum xsd_sockmsg_type type); =20 -int quota_nb_entry_per_domain =3D 1000; -int quota_nb_watch_per_domain =3D 128; -int quota_max_entry_size =3D 2048; /* 2K */ -int quota_max_transaction =3D 10; -int quota_nb_perms_per_node =3D 5; -int quota_trans_nodes =3D 1024; -int quota_max_path_len =3D XENSTORE_REL_PATH_MAX; -int quota_req_outstanding =3D 20; -int quota_memory_per_domain_soft =3D 2 * 1024 * 1024; /* 2 MB */ -int quota_memory_per_domain_hard =3D 2 * 1024 * 1024 + 512 * 1024; /* 2.5 = MB */ - unsigned int timeout_watch_event_msec =3D 20000; =20 void trace(const char *fmt, ...) @@ -799,7 +788,7 @@ int write_node_raw(struct connection *conn, TDB_DATA *k= ey, struct node *node, + node->perms.num * sizeof(node->perms.p[0]) + node->datalen + node->childlen; =20 - if (domain_max_chk(conn, ACC_NODESZ, data.dsize, quota_max_entry_size) + if (domain_max_chk(conn, ACC_NODESZ, data.dsize) && !no_quota_check) { errno =3D ENOSPC; return errno; @@ -1188,8 +1177,7 @@ bool is_valid_nodename(const struct connection *conn,= const char *node) if (sscanf(node, "/local/domain/%5u/%n", &domid, &local_off) !=3D 1) local_off =3D 0; =20 - if (domain_max_chk(conn, ACC_PATHLEN, strlen(node) - local_off, - quota_max_path_len)) + if (domain_max_chk(conn, ACC_PATHLEN, strlen(node) - local_off)) return false; =20 return valid_chars(node); @@ -1501,7 +1489,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 quota_nb_entry_per_domain) { + domain_nbentry(conn) >=3D hard_quotas[ACC_NODES].val) { ret =3D ENOSPC; goto err; } @@ -1776,7 +1764,7 @@ static int do_set_perms(const void *ctx, struct conne= ction *conn, return EINVAL; =20 perms.num--; - if (domain_max_chk(conn, ACC_NPERM, perms.num, quota_nb_perms_per_node)) + if (domain_max_chk(conn, ACC_NPERM, perms.num)) return ENOSPC; =20 permstr =3D in->buffer + strlen(in->buffer) + 1; @@ -2644,7 +2632,16 @@ static void usage(void) " memory: total used memory per domain for nodes,= \n" " transactions, watches and requests, abo= ve\n" " which Xenstore will stop talking to dom= ain\n" +" nodes: number nodes owned by a domain\n" +" node-permissions: number of access permissions = per\n" +" node\n" +" node-size: total size of a node (permissions +\= n" +" children names + content)\n" " outstanding: number of outstanding requests\n" +" path-length: length of a node path\n" +" transactions: number of concurrent transactions= \n" +" per domain\n" +" watches: number of watches per domain" " -q, --quota-soft =3D set a soft quota to the value ,\n" " causing a warning to be issued via syslog() if = the\n" " limit is violated, allowed quotas are:\n" @@ -2695,12 +2692,12 @@ int dom0_domid =3D 0; int dom0_event =3D 0; int priv_domid =3D 0; =20 -static int get_optval_int(const char *arg) +static unsigned int get_optval_int(const char *arg) { char *end; - long val; + unsigned long val; =20 - val =3D strtol(arg, &end, 10); + val =3D strtoul(arg, &end, 10); if (!*arg || *end || val < 0 || val > INT_MAX) barf("invalid parameter value \"%s\"\n", arg); =20 @@ -2709,15 +2706,19 @@ static int get_optval_int(const char *arg) =20 static bool what_matches(const char *arg, const char *what) { - unsigned int what_len =3D strlen(what); + unsigned int what_len; + + if (!what) + false; =20 + what_len =3D strlen(what); return !strncmp(arg, what, what_len) && arg[what_len] =3D=3D '=3D'; } =20 static void set_timeout(const char *arg) { const char *eq =3D strchr(arg, '=3D'); - int val; + unsigned int val; =20 if (!eq) barf("quotas must be specified via =3D\n"); @@ -2731,22 +2732,22 @@ static void set_timeout(const char *arg) static void set_quota(const char *arg, bool soft) { const char *eq =3D strchr(arg, '=3D'); - int val; + struct quota *q =3D soft ? soft_quotas : hard_quotas; + unsigned int val; + unsigned int i; =20 if (!eq) barf("quotas must be specified via =3D\n"); val =3D get_optval_int(eq + 1); - if (what_matches(arg, "outstanding") && !soft) - quota_req_outstanding =3D val; - else if (what_matches(arg, "transaction-nodes") && !soft) - quota_trans_nodes =3D val; - else if (what_matches(arg, "memory")) { - if (soft) - quota_memory_per_domain_soft =3D val; - else - quota_memory_per_domain_hard =3D val; - } else - barf("unknown quota \"%s\"\n", arg); + + for (i =3D 0; i < ACC_N; i++) { + if (what_matches(arg, q[i].name)) { + q[i].val =3D val; + return; + } + } + + barf("unknown quota \"%s\"\n", arg); } =20 /* Sorted by bit values of TRACE_* flags. Flag is (1u << index). */ @@ -2808,7 +2809,7 @@ int main(int argc, char *argv[]) no_domain_init =3D true; break; case 'E': - quota_nb_entry_per_domain =3D strtol(optarg, NULL, 10); + hard_quotas[ACC_NODES].val =3D strtoul(optarg, NULL, 10); break; case 'F': pidfile =3D optarg; @@ -2826,10 +2827,10 @@ int main(int argc, char *argv[]) recovery =3D false; break; case 'S': - quota_max_entry_size =3D strtol(optarg, NULL, 10); + hard_quotas[ACC_NODESZ].val =3D strtoul(optarg, NULL, 10); break; case 't': - quota_max_transaction =3D strtol(optarg, NULL, 10); + hard_quotas[ACC_TRANS].val =3D strtoul(optarg, NULL, 10); break; case 'T': tracefile =3D optarg; @@ -2849,15 +2850,17 @@ int main(int argc, char *argv[]) verbose =3D true; break; case 'W': - quota_nb_watch_per_domain =3D strtol(optarg, NULL, 10); + hard_quotas[ACC_WATCH].val =3D strtoul(optarg, NULL, 10); break; case 'A': - quota_nb_perms_per_node =3D strtol(optarg, NULL, 10); + hard_quotas[ACC_NPERM].val =3D strtoul(optarg, NULL, 10); break; case 'M': - quota_max_path_len =3D strtol(optarg, NULL, 10); - quota_max_path_len =3D min(XENSTORE_REL_PATH_MAX, - quota_max_path_len); + hard_quotas[ACC_PATHLEN].val =3D + strtoul(optarg, NULL, 10); + hard_quotas[ACC_PATHLEN].val =3D + min((unsigned int)XENSTORE_REL_PATH_MAX, + hard_quotas[ACC_PATHLEN].val); break; case 'Q': set_quota(optarg, false); diff --git a/tools/xenstore/xenstored_core.h b/tools/xenstore/xenstored_cor= e.h index 0140c25880..693622ec68 100644 --- a/tools/xenstore/xenstored_core.h +++ b/tools/xenstore/xenstored_core.h @@ -315,16 +315,6 @@ extern TDB_CONTEXT *tdb_ctx; extern int dom0_domid; extern int dom0_event; extern int priv_domid; -extern int quota_nb_watch_per_domain; -extern int quota_max_transaction; -extern int quota_max_entry_size; -extern int quota_nb_perms_per_node; -extern int quota_max_path_len; -extern int quota_nb_entry_per_domain; -extern int quota_req_outstanding; -extern int quota_trans_nodes; -extern int quota_memory_per_domain_soft; -extern int quota_memory_per_domain_hard; extern bool keep_orphans; =20 extern unsigned int timeout_watch_event_msec; diff --git a/tools/xenstore/xenstored_domain.c b/tools/xenstore/xenstored_d= omain.c index f431076505..3906047e6b 100644 --- a/tools/xenstore/xenstored_domain.c +++ b/tools/xenstore/xenstored_domain.c @@ -43,7 +43,61 @@ static evtchn_port_t virq_port; =20 xenevtchn_handle *xce_handle =3D NULL; =20 -static unsigned int acc_global_max[ACC_N]; +struct quota hard_quotas[ACC_N] =3D { + [ACC_NODES] =3D { + .name =3D "nodes", + .descr =3D "Nodes per domain", + .val =3D 1000, + }, + [ACC_WATCH] =3D { + .name =3D "watches", + .descr =3D "Watches per domain", + .val =3D 128, + }, + [ACC_OUTST] =3D { + .name =3D "outstanding", + .descr =3D "Outstanding requests per domain", + .val =3D 20, + }, + [ACC_MEM] =3D { + .name =3D "memory", + .descr =3D "Total Xenstore memory per domain (error level)", + .val =3D 2 * 1024 * 1024 + 512 * 1024, /* 2.5 MB */ + }, + [ACC_TRANS] =3D { + .name =3D "transactions", + .descr =3D "Active transactions per domain", + .val =3D 10, + }, + [ACC_TRANSNODES] =3D { + .name =3D "transaction-nodes", + .descr =3D "Max. number of accessed nodes per transaction", + .val =3D 1024, + }, + [ACC_NPERM] =3D { + .name =3D "node-permissions", + .descr =3D "Max. number of permissions per node", + .val =3D 5, + }, + [ACC_PATHLEN] =3D { + .name =3D "path-max", + .descr =3D "Max. length of a node path", + .val =3D XENSTORE_REL_PATH_MAX, + }, + [ACC_NODESZ] =3D { + .name =3D "node-size", + .descr =3D "Max. size of a node", + .val =3D 2048, + }, +}; + +struct quota soft_quotas[ACC_N] =3D { + [ACC_MEM] =3D { + .name =3D "memory", + .descr =3D "Total Xenstore memory per domain (warning level)", + .val =3D 2 * 1024 * 1024, /* 2.0 MB */ + }, +}; =20 struct domain { @@ -204,10 +258,10 @@ 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 quota_req_outstanding) + if (domain->acc[ACC_OUTST].val >=3D hard_quotas[ACC_OUTST].val) return false; - if (domain->acc[ACC_MEM].val >=3D quota_memory_per_domain_hard && - quota_memory_per_domain_hard) + if (domain->acc[ACC_MEM].val >=3D hard_quotas[ACC_MEM].val && + hard_quotas[ACC_MEM].val) return false; } =20 @@ -422,6 +476,7 @@ int domain_get_quota(const void *ctx, struct connection= *conn, { struct domain *d =3D find_domain_struct(domid); char *resp; + unsigned int i; =20 if (!d) return ENOENT; @@ -430,19 +485,15 @@ int domain_get_quota(const void *ctx, struct connecti= on *conn, if (!resp) return ENOMEM; =20 -#define ent(t, e) \ - resp =3D talloc_asprintf_append(resp, "%-17s: %8u (max: %8u\n", #t, \ - d->acc[e].val, d->acc[e].max); \ - if (!resp) return ENOMEM - - ent(nodes, ACC_NODES); - ent(watches, ACC_WATCH); - ent(transactions, ACC_TRANS); - ent(outstanding, ACC_OUTST); - ent(memory, ACC_MEM); - ent(transaction-nodes, ACC_TRANSNODES); - -#undef ent + for (i =3D 0; i < ACC_N; i++) { + if (!hard_quotas[i].name) + continue; + resp =3D talloc_asprintf_append(resp, "%-17s: %8u (max %8u)\n", + hard_quotas[i].name, + d->acc[i].val, d->acc[i].max); + if (!resp) + return ENOMEM; + } =20 send_reply(conn, XS_CONTROL, resp, strlen(resp) + 1); =20 @@ -452,24 +503,21 @@ int domain_get_quota(const void *ctx, struct connecti= on *conn, int domain_max_global_acc(const void *ctx, struct connection *conn) { char *resp; + unsigned int i; =20 resp =3D talloc_asprintf(ctx, "Max. seen accounting values:\n"); if (!resp) return ENOMEM; =20 -#define ent(t, e) \ - resp =3D talloc_asprintf_append(resp, "%-17s: %8u\n", #t, \ - acc_global_max[e]); \ - if (!resp) return ENOMEM - - ent(nodes, ACC_NODES); - ent(watches, ACC_WATCH); - ent(transactions, ACC_TRANS); - ent(outstanding, ACC_OUTST); - ent(memory, ACC_MEM); - ent(transaction-nodes, ACC_TRANSNODES); - -#undef ent + for (i =3D 0; i < ACC_N; i++) { + if (!hard_quotas[i].name) + continue; + resp =3D talloc_asprintf_append(resp, "%-17s: %8u\n", + hard_quotas[i].name, + hard_quotas[i].max); + if (!resp) + return ENOMEM; + } =20 send_reply(conn, XS_CONTROL, resp, strlen(resp) + 1); =20 @@ -584,7 +632,7 @@ int acc_fix_domains(struct list_head *head, bool update) list_for_each_entry(cd, head, list) { cnt =3D domain_nbentry_fix(cd->domid, cd->acc[ACC_NODES], update); if (!update) { - if (cnt >=3D quota_nb_entry_per_domain) + if (cnt >=3D hard_quotas[ACC_NODES].val) return ENOSPC; if (cnt < 0) return ENOMEM; @@ -1086,12 +1134,12 @@ static void domain_acc_chk_max(struct domain *d, en= um accitem what, unsigned int val, unsigned int domid) { assert(what < ARRAY_SIZE(d->acc)); - assert(what < ARRAY_SIZE(acc_global_max)); + assert(what < ARRAY_SIZE(hard_quotas)); =20 if (val > d->acc[what].max) d->acc[what].max =3D val; - if (val > acc_global_max[what] && domid_is_unprivileged(domid)) - acc_global_max[what] =3D val; + if (val > hard_quotas[what].max && domid_is_unprivileged(domid)) + hard_quotas[what].max =3D val; } =20 static int domain_acc_add_chk(struct domain *d, enum accitem what, int add, @@ -1222,19 +1270,19 @@ void domain_reset_global_acc(void) unsigned int i; =20 for (i =3D 0; i < ACC_N; i++) - acc_global_max[i] =3D 0; + hard_quotas[i].max =3D 0; =20 /* Set current max values seen. */ hashtable_iterate(domhash, domain_reset_global_acc_sub, NULL); } =20 bool domain_max_chk(const struct connection *conn, enum accitem what, - unsigned int val, unsigned int quota) + unsigned int val) { if (!conn || !conn->domain) return false; =20 - if (domain_is_unprivileged(conn) && val > quota) + if (domain_is_unprivileged(conn) && val > hard_quotas[what].val) return true; =20 domain_acc_chk_max(conn->domain, what, val, conn->id); @@ -1283,8 +1331,7 @@ static bool domain_chk_quota(struct connection *conn,= unsigned int mem) domain =3D conn->domain; now =3D time(NULL); =20 - if (mem >=3D quota_memory_per_domain_hard && - quota_memory_per_domain_hard) { + if (mem >=3D hard_quotas[ACC_MEM].val && hard_quotas[ACC_MEM].val) { if (domain->hard_quota_reported) return true; syslog(LOG_ERR, "Domain %u exceeds hard memory quota, Xenstore interface= to domain stalled\n", @@ -1301,15 +1348,14 @@ static bool domain_chk_quota(struct connection *con= n, unsigned int mem) syslog(LOG_INFO, "Domain %u below hard memory quota again\n", domain->domid); } - if (mem >=3D quota_memory_per_domain_soft && - quota_memory_per_domain_soft && - !domain->soft_quota_reported) { + if (mem >=3D soft_quotas[ACC_MEM].val && + soft_quotas[ACC_MEM].val && !domain->soft_quota_reported) { domain->mem_last_msg =3D now; domain->soft_quota_reported =3D true; syslog(LOG_WARNING, "Domain %u exceeds soft memory quota\n", domain->domid); } - if (mem < quota_memory_per_domain_soft && + if (mem < soft_quotas[ACC_MEM].val && domain->soft_quota_reported) { domain->mem_last_msg =3D now; domain->soft_quota_reported =3D false; diff --git a/tools/xenstore/xenstored_domain.h b/tools/xenstore/xenstored_d= omain.h index ff341dd8bf..3989d4a038 100644 --- a/tools/xenstore/xenstored_domain.h +++ b/tools/xenstore/xenstored_domain.h @@ -34,6 +34,16 @@ enum accitem { ACC_N /* Number of elements per domain. */ }; =20 +struct quota { + const char *name; + const char *descr; + unsigned int val; + unsigned int max; +}; + +extern struct quota hard_quotas[ACC_N]; +extern struct quota soft_quotas[ACC_N]; + void handle_event(void); =20 void check_domains(void); @@ -123,7 +133,7 @@ void acc_commit(struct connection *conn); int domain_max_global_acc(const void *ctx, struct connection *conn); void domain_reset_global_acc(void); bool domain_max_chk(const struct connection *conn, unsigned int what, - unsigned int val, unsigned int quota); + unsigned int val); =20 /* Write rate limiting */ =20 diff --git a/tools/xenstore/xenstored_transaction.c b/tools/xenstore/xensto= red_transaction.c index 7967770ca2..13fabe030d 100644 --- a/tools/xenstore/xenstored_transaction.c +++ b/tools/xenstore/xenstored_transaction.c @@ -244,8 +244,7 @@ int access_node(struct connection *conn, struct node *n= ode, =20 i =3D find_accessed_node(trans, node->name); if (!i) { - if (domain_max_chk(conn, ACC_TRANSNODES, trans->nodes + 1, - quota_trans_nodes)) { + if (domain_max_chk(conn, ACC_TRANSNODES, trans->nodes + 1)) { ret =3D ENOSPC; goto err; } @@ -471,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) > quota_max_transaction) + if (domain_transaction_get(conn) > hard_quotas[ACC_TRANS].val) return ENOSPC; =20 /* Attach transaction to ctx for autofree until it's complete */ diff --git a/tools/xenstore/xenstored_watch.c b/tools/xenstore/xenstored_wa= tch.c index 61b1e3421e..e8eb35de02 100644 --- a/tools/xenstore/xenstored_watch.c +++ b/tools/xenstore/xenstored_watch.c @@ -239,7 +239,7 @@ int do_watch(const void *ctx, struct connection *conn, = struct buffered_data *in) return EEXIST; } =20 - if (domain_watch(conn) > quota_nb_watch_per_domain) + if (domain_watch(conn) > hard_quotas[ACC_WATCH].val) return E2BIG; =20 watch =3D add_watch(conn, vec[0], vec[1], relative, false); --=20 2.35.3