mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
tools/xenstore: switch quota management to be table based
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 <jgross@suse.com> Acked-by: Julien Grall <jgrall@amazon.com>
This commit is contained in:
1 parent
561687f6bc
commit
685048441e
7 files changed
+153
-138
No files matched your search
@@ -221,35 +221,6 @@ static int do_control_log(const void *ctx, struct connection *conn,
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct quota {
|
||||
const char *name;
|
||||
int *quota;
|
||||
const char *descr;
|
||||
};
|
||||
|
||||
static const struct quota hard_quotas[] = {
|
||||
{ "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[] = {
|
||||
{ "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;
|
||||
|
||||
for (i = 0; quotas[i].quota; i++) {
|
||||
for (i = 0; i < ACC_N; i++) {
|
||||
if (!quotas[i].name)
|
||||
continue;
|
||||
resp = 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 connection *conn,
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
for (i = 0; quotas[i].quota; i++) {
|
||||
if (!strcmp(vec[0], quotas[i].name)) {
|
||||
*quotas[i].quota = val;
|
||||
for (i = 0; i < ACC_N; i++) {
|
||||
if (quotas[i].name && !strcmp(vec[0], quotas[i].name)) {
|
||||
quotas[i].val = val;
|
||||
send_ack(conn, XS_CONTROL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -89,17 +89,6 @@ unsigned int trace_flags = TRACE_OBJ | TRACE_IO;
|
||||
|
||||
static const char *sockmsg_string(enum xsd_sockmsg_type type);
|
||||
|
||||
int quota_nb_entry_per_domain = 1000;
|
||||
int quota_nb_watch_per_domain = 128;
|
||||
int quota_max_entry_size = 2048; /* 2K */
|
||||
int quota_max_transaction = 10;
|
||||
int quota_nb_perms_per_node = 5;
|
||||
int quota_trans_nodes = 1024;
|
||||
int quota_max_path_len = XENSTORE_REL_PATH_MAX;
|
||||
int quota_req_outstanding = 20;
|
||||
int quota_memory_per_domain_soft = 2 * 1024 * 1024; /* 2 MB */
|
||||
int quota_memory_per_domain_hard = 2 * 1024 * 1024 + 512 * 1024; /* 2.5 MB */
|
||||
|
||||
unsigned int timeout_watch_event_msec = 20000;
|
||||
|
||||
void trace(const char *fmt, ...)
|
||||
@@ -800,8 +789,7 @@ int write_node_raw(struct connection *conn, TDB_DATA *key, struct node *node,
|
||||
+ node->datalen + node->childlen;
|
||||
|
||||
/* Call domain_max_chk() in any case in order to record max values. */
|
||||
if (domain_max_chk(conn, ACC_NODESZ, data.dsize, quota_max_entry_size)
|
||||
&& !no_quota_check) {
|
||||
if (domain_max_chk(conn, ACC_NODESZ, data.dsize) && !no_quota_check) {
|
||||
errno = ENOSPC;
|
||||
return errno;
|
||||
}
|
||||
@@ -1191,8 +1179,7 @@ bool is_valid_nodename(const struct connection *conn, const char *node)
|
||||
if (sscanf(node, "/local/domain/%5u/%n", &domid, &local_off) != 1)
|
||||
local_off = 0;
|
||||
|
||||
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;
|
||||
|
||||
return valid_chars(node);
|
||||
@@ -1504,7 +1491,7 @@ static struct node *create_node(struct connection *conn, const void *ctx,
|
||||
for (i = node; i; i = i->parent) {
|
||||
/* i->parent is set for each new node, so check quota. */
|
||||
if (i->parent &&
|
||||
domain_nbentry(conn) >= quota_nb_entry_per_domain) {
|
||||
domain_nbentry(conn) >= hard_quotas[ACC_NODES].val) {
|
||||
ret = ENOSPC;
|
||||
goto err;
|
||||
}
|
||||
@@ -1786,7 +1773,7 @@ static int do_set_perms(const void *ctx, struct connection *conn,
|
||||
return EINVAL;
|
||||
|
||||
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;
|
||||
|
||||
permstr = in->buffer + strlen(in->buffer) + 1;
|
||||
@@ -2655,7 +2642,16 @@ static void usage(void)
|
||||
" memory: total used memory per domain for nodes,\n"
|
||||
" transactions, watches and requests, above\n"
|
||||
" which Xenstore will stop talking to domain\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 <what>=<nb> set a soft quota <what> to the value <nb>,\n"
|
||||
" causing a warning to be issued via syslog() if the\n"
|
||||
" limit is violated, allowed quotas are:\n"
|
||||
@@ -2720,7 +2716,12 @@ static unsigned int get_optval_uint(const char *arg)
|
||||
|
||||
static bool what_matches(const char *arg, const char *what)
|
||||
{
|
||||
unsigned int what_len = strlen(what);
|
||||
unsigned int what_len;
|
||||
|
||||
if (!what)
|
||||
return false;
|
||||
|
||||
what_len = strlen(what);
|
||||
|
||||
return !strncmp(arg, what, what_len) && arg[what_len] == '=';
|
||||
}
|
||||
@@ -2728,7 +2729,7 @@ static bool what_matches(const char *arg, const char *what)
|
||||
static void set_timeout(const char *arg)
|
||||
{
|
||||
const char *eq = strchr(arg, '=');
|
||||
int val;
|
||||
unsigned int val;
|
||||
|
||||
if (!eq)
|
||||
barf("quotas must be specified via <what>=<seconds>\n");
|
||||
@@ -2742,22 +2743,22 @@ static void set_timeout(const char *arg)
|
||||
static void set_quota(const char *arg, bool soft)
|
||||
{
|
||||
const char *eq = strchr(arg, '=');
|
||||
int val;
|
||||
struct quota *q = soft ? soft_quotas : hard_quotas;
|
||||
unsigned int val;
|
||||
unsigned int i;
|
||||
|
||||
if (!eq)
|
||||
barf("quotas must be specified via <what>=<nb>\n");
|
||||
val = get_optval_uint(eq + 1);
|
||||
if (what_matches(arg, "outstanding") && !soft)
|
||||
quota_req_outstanding = val;
|
||||
else if (what_matches(arg, "transaction-nodes") && !soft)
|
||||
quota_trans_nodes = val;
|
||||
else if (what_matches(arg, "memory")) {
|
||||
if (soft)
|
||||
quota_memory_per_domain_soft = val;
|
||||
else
|
||||
quota_memory_per_domain_hard = val;
|
||||
} else
|
||||
barf("unknown quota \"%s\"\n", arg);
|
||||
|
||||
for (i = 0; i < ACC_N; i++) {
|
||||
if (what_matches(arg, q[i].name)) {
|
||||
q[i].val = val;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
barf("unknown quota \"%s\"\n", arg);
|
||||
}
|
||||
|
||||
/* Sorted by bit values of TRACE_* flags. Flag is (1u << index). */
|
||||
@@ -2819,7 +2820,7 @@ int main(int argc, char *argv[])
|
||||
no_domain_init = true;
|
||||
break;
|
||||
case 'E':
|
||||
quota_nb_entry_per_domain = strtol(optarg, NULL, 10);
|
||||
hard_quotas[ACC_NODES].val = strtoul(optarg, NULL, 10);
|
||||
break;
|
||||
case 'F':
|
||||
pidfile = optarg;
|
||||
@@ -2837,10 +2838,10 @@ int main(int argc, char *argv[])
|
||||
recovery = false;
|
||||
break;
|
||||
case 'S':
|
||||
quota_max_entry_size = strtol(optarg, NULL, 10);
|
||||
hard_quotas[ACC_NODESZ].val = strtoul(optarg, NULL, 10);
|
||||
break;
|
||||
case 't':
|
||||
quota_max_transaction = strtol(optarg, NULL, 10);
|
||||
hard_quotas[ACC_TRANS].val = strtoul(optarg, NULL, 10);
|
||||
break;
|
||||
case 'T':
|
||||
tracefile = optarg;
|
||||
@@ -2860,15 +2861,17 @@ int main(int argc, char *argv[])
|
||||
verbose = true;
|
||||
break;
|
||||
case 'W':
|
||||
quota_nb_watch_per_domain = strtol(optarg, NULL, 10);
|
||||
hard_quotas[ACC_WATCH].val = strtoul(optarg, NULL, 10);
|
||||
break;
|
||||
case 'A':
|
||||
quota_nb_perms_per_node = strtol(optarg, NULL, 10);
|
||||
hard_quotas[ACC_NPERM].val = strtoul(optarg, NULL, 10);
|
||||
break;
|
||||
case 'M':
|
||||
quota_max_path_len = strtol(optarg, NULL, 10);
|
||||
quota_max_path_len = min(XENSTORE_REL_PATH_MAX,
|
||||
quota_max_path_len);
|
||||
hard_quotas[ACC_PATHLEN].val =
|
||||
strtoul(optarg, NULL, 10);
|
||||
hard_quotas[ACC_PATHLEN].val =
|
||||
min((unsigned int)XENSTORE_REL_PATH_MAX,
|
||||
hard_quotas[ACC_PATHLEN].val);
|
||||
break;
|
||||
case 'Q':
|
||||
set_quota(optarg, false);
|
||||
|
||||
@@ -316,16 +316,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;
|
||||
|
||||
extern unsigned int timeout_watch_event_msec;
|
||||
|
||||
@@ -43,7 +43,61 @@ static evtchn_port_t virq_port;
|
||||
|
||||
xenevtchn_handle *xce_handle = NULL;
|
||||
|
||||
static unsigned int acc_global_max[ACC_N];
|
||||
struct quota hard_quotas[ACC_N] = {
|
||||
[ACC_NODES] = {
|
||||
.name = "nodes",
|
||||
.descr = "Nodes per domain",
|
||||
.val = 1000,
|
||||
},
|
||||
[ACC_WATCH] = {
|
||||
.name = "watches",
|
||||
.descr = "Watches per domain",
|
||||
.val = 128,
|
||||
},
|
||||
[ACC_OUTST] = {
|
||||
.name = "outstanding",
|
||||
.descr = "Outstanding requests per domain",
|
||||
.val = 20,
|
||||
},
|
||||
[ACC_MEM] = {
|
||||
.name = "memory",
|
||||
.descr = "Total Xenstore memory per domain (error level)",
|
||||
.val = 2 * 1024 * 1024 + 512 * 1024, /* 2.5 MB */
|
||||
},
|
||||
[ACC_TRANS] = {
|
||||
.name = "transactions",
|
||||
.descr = "Active transactions per domain",
|
||||
.val = 10,
|
||||
},
|
||||
[ACC_TRANSNODES] = {
|
||||
.name = "transaction-nodes",
|
||||
.descr = "Max. number of accessed nodes per transaction",
|
||||
.val = 1024,
|
||||
},
|
||||
[ACC_NPERM] = {
|
||||
.name = "node-permissions",
|
||||
.descr = "Max. number of permissions per node",
|
||||
.val = 5,
|
||||
},
|
||||
[ACC_PATHLEN] = {
|
||||
.name = "path-max",
|
||||
.descr = "Max. length of a node path",
|
||||
.val = XENSTORE_REL_PATH_MAX,
|
||||
},
|
||||
[ACC_NODESZ] = {
|
||||
.name = "node-size",
|
||||
.descr = "Max. size of a node",
|
||||
.val = 2048,
|
||||
},
|
||||
};
|
||||
|
||||
struct quota soft_quotas[ACC_N] = {
|
||||
[ACC_MEM] = {
|
||||
.name = "memory",
|
||||
.descr = "Total Xenstore memory per domain (warning level)",
|
||||
.val = 2 * 1024 * 1024, /* 2.0 MB */
|
||||
},
|
||||
};
|
||||
|
||||
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 >= quota_req_outstanding)
|
||||
if (domain->acc[ACC_OUTST].val >= hard_quotas[ACC_OUTST].val)
|
||||
return false;
|
||||
if (domain->acc[ACC_MEM].val >= quota_memory_per_domain_hard &&
|
||||
quota_memory_per_domain_hard)
|
||||
if (domain->acc[ACC_MEM].val >= hard_quotas[ACC_MEM].val &&
|
||||
hard_quotas[ACC_MEM].val)
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -421,6 +475,7 @@ int domain_get_quota(const void *ctx, struct connection *conn,
|
||||
{
|
||||
struct domain *d = find_domain_struct(domid);
|
||||
char *resp;
|
||||
unsigned int i;
|
||||
|
||||
if (!d)
|
||||
return ENOENT;
|
||||
@@ -429,22 +484,15 @@ int domain_get_quota(const void *ctx, struct connection *conn,
|
||||
if (!resp)
|
||||
return ENOMEM;
|
||||
|
||||
#define ent(t, e) \
|
||||
resp = 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);
|
||||
ent(node-permissions, ACC_NPERM);
|
||||
ent(path-length, ACC_PATHLEN);
|
||||
ent(node-size, ACC_NODESZ);
|
||||
|
||||
#undef ent
|
||||
for (i = 0; i < ACC_N; i++) {
|
||||
if (!hard_quotas[i].name)
|
||||
continue;
|
||||
resp = 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;
|
||||
}
|
||||
|
||||
send_reply(conn, XS_CONTROL, resp, strlen(resp) + 1);
|
||||
|
||||
@@ -454,27 +502,21 @@ int domain_get_quota(const void *ctx, struct connection *conn,
|
||||
int domain_max_global_acc(const void *ctx, struct connection *conn)
|
||||
{
|
||||
char *resp;
|
||||
unsigned int i;
|
||||
|
||||
resp = talloc_asprintf(ctx, "Max. seen accounting values:\n");
|
||||
if (!resp)
|
||||
return ENOMEM;
|
||||
|
||||
#define ent(t, e) \
|
||||
resp = 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);
|
||||
ent(node-permissions, ACC_NPERM);
|
||||
ent(path-length, ACC_PATHLEN);
|
||||
ent(node-size, ACC_NODESZ);
|
||||
|
||||
#undef ent
|
||||
for (i = 0; i < ACC_N; i++) {
|
||||
if (!hard_quotas[i].name)
|
||||
continue;
|
||||
resp = talloc_asprintf_append(resp, "%-17s: %8u\n",
|
||||
hard_quotas[i].name,
|
||||
hard_quotas[i].max);
|
||||
if (!resp)
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
send_reply(conn, XS_CONTROL, resp, strlen(resp) + 1);
|
||||
|
||||
@@ -589,7 +631,7 @@ int acc_fix_domains(struct list_head *head, bool chk_quota, bool update)
|
||||
list_for_each_entry(cd, head, list) {
|
||||
cnt = domain_nbentry_fix(cd->domid, cd->acc[ACC_NODES], update);
|
||||
if (!update) {
|
||||
if (chk_quota && cnt >= quota_nb_entry_per_domain)
|
||||
if (chk_quota && cnt >= hard_quotas[ACC_NODES].val)
|
||||
return ENOSPC;
|
||||
if (cnt < 0)
|
||||
return ENOMEM;
|
||||
@@ -1090,12 +1132,12 @@ static void domain_acc_valid_max(struct domain *d, enum accitem what,
|
||||
unsigned int val)
|
||||
{
|
||||
assert(what < ARRAY_SIZE(d->acc));
|
||||
assert(what < ARRAY_SIZE(acc_global_max));
|
||||
assert(what < ARRAY_SIZE(hard_quotas));
|
||||
|
||||
if (val > d->acc[what].max)
|
||||
d->acc[what].max = val;
|
||||
if (val > acc_global_max[what] && domid_is_unprivileged(d->domid))
|
||||
acc_global_max[what] = val;
|
||||
if (val > hard_quotas[what].max && domid_is_unprivileged(d->domid))
|
||||
hard_quotas[what].max = val;
|
||||
}
|
||||
|
||||
static int domain_acc_add_valid(struct domain *d, enum accitem what, int add)
|
||||
@@ -1232,19 +1274,19 @@ void domain_reset_global_acc(void)
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ACC_N; i++)
|
||||
acc_global_max[i] = 0;
|
||||
hard_quotas[i].max = 0;
|
||||
|
||||
/* Set current max values seen. */
|
||||
hashtable_iterate(domhash, domain_reset_global_acc_sub, NULL);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (domain_is_unprivileged(conn) && val > quota)
|
||||
if (domain_is_unprivileged(conn) && val > hard_quotas[what].val)
|
||||
return true;
|
||||
|
||||
domain_acc_valid_max(conn->domain, what, val);
|
||||
@@ -1293,8 +1335,7 @@ static bool domain_chk_quota(struct connection *conn, unsigned int mem)
|
||||
domain = conn->domain;
|
||||
now = time(NULL);
|
||||
|
||||
if (mem >= quota_memory_per_domain_hard &&
|
||||
quota_memory_per_domain_hard) {
|
||||
if (mem >= 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",
|
||||
@@ -1311,15 +1352,14 @@ static bool domain_chk_quota(struct connection *conn, unsigned int mem)
|
||||
syslog(LOG_INFO, "Domain %u below hard memory quota again\n",
|
||||
domain->domid);
|
||||
}
|
||||
if (mem >= quota_memory_per_domain_soft &&
|
||||
quota_memory_per_domain_soft &&
|
||||
!domain->soft_quota_reported) {
|
||||
if (mem >= soft_quotas[ACC_MEM].val &&
|
||||
soft_quotas[ACC_MEM].val && !domain->soft_quota_reported) {
|
||||
domain->mem_last_msg = now;
|
||||
domain->soft_quota_reported = 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 = now;
|
||||
domain->soft_quota_reported = false;
|
||||
|
||||
@@ -40,6 +40,16 @@ enum accitem {
|
||||
ACC_N, /* Number of elements per domain. */
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
void check_domains(void);
|
||||
@@ -134,7 +144,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);
|
||||
|
||||
/* Write rate limiting */
|
||||
|
||||
|
||||
@@ -252,8 +252,7 @@ int access_node(struct connection *conn, struct node *node,
|
||||
|
||||
i = 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 = ENOSPC;
|
||||
goto err;
|
||||
}
|
||||
@@ -479,7 +478,7 @@ int do_transaction_start(const void *ctx, struct connection *conn,
|
||||
if (conn->transaction)
|
||||
return EBUSY;
|
||||
|
||||
if (domain_transaction_get(conn) > quota_max_transaction)
|
||||
if (domain_transaction_get(conn) > hard_quotas[ACC_TRANS].val)
|
||||
return ENOSPC;
|
||||
|
||||
/* Attach transaction to ctx for autofree until it's complete */
|
||||
|
||||
@@ -239,7 +239,7 @@ int do_watch(const void *ctx, struct connection *conn, struct buffered_data *in)
|
||||
return EEXIST;
|
||||
}
|
||||
|
||||
if (domain_watch(conn) > quota_nb_watch_per_domain)
|
||||
if (domain_watch(conn) > hard_quotas[ACC_WATCH].val)
|
||||
return E2BIG;
|
||||
|
||||
watch = add_watch(conn, vec[0], vec[1], relative, false);
|
||||
|
||||