aboutsummaryrefslogtreecommitdiffstats
path: root/tools/xenstore/xenstored_core.c
diff options
context:
space:
mode:
authorvhanquez@kneesa.uk.xensource.com <vhanquez@kneesa.uk.xensource.com>2006-04-13 16:21:13 +0000
committervhanquez@kneesa.uk.xensource.com <vhanquez@kneesa.uk.xensource.com>2006-04-13 16:21:13 +0000
commite43071c7b1a81fe80595bb6a42214d1029e8a88d (patch)
treeb9a1b215f0a8ced8902dfd5a214a2ba2cbd34a8f /tools/xenstore/xenstored_core.c
parent9f15c912a7ef65c4a6452ca9338fccc85a8f6170 (diff)
downloadxen-e43071c7b1a81fe80595bb6a42214d1029e8a88d.tar.gz
xen-e43071c7b1a81fe80595bb6a42214d1029e8a88d.tar.bz2
xen-e43071c7b1a81fe80595bb6a42214d1029e8a88d.zip
add quota to xenstored.
Signed-off-by: Vincent Hanquez <vincent@xensource.com>
Diffstat (limited to 'tools/xenstore/xenstored_core.c')
-rw-r--r--tools/xenstore/xenstored_core.c46
1 files changed, 40 insertions, 6 deletions
diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_core.c
index f4fa447d07..0fa08af504 100644
--- a/tools/xenstore/xenstored_core.c
+++ b/tools/xenstore/xenstored_core.c
@@ -77,6 +77,10 @@ static void check_store(void);
} while (0)
+int quota_nb_entry_per_domain = 1000;
+int quota_nb_watch_per_domain = 128;
+int quota_max_entry_size = 2048; /* 2K */
+
#ifdef TESTING
static bool failtest = false;
@@ -455,6 +459,10 @@ static bool write_node(struct connection *conn, const struct node *node)
data.dsize = 3*sizeof(uint32_t)
+ node->num_perms*sizeof(node->perms[0])
+ node->datalen + node->childlen;
+
+ if (data.dsize >= quota_max_entry_size)
+ goto error;
+
data.dptr = talloc_size(node, data.dsize);
((uint32_t *)data.dptr)[0] = node->num_perms;
((uint32_t *)data.dptr)[1] = node->datalen;
@@ -470,10 +478,12 @@ static bool write_node(struct connection *conn, const struct node *node)
/* TDB should set errno, but doesn't even set ecode AFAICT. */
if (tdb_store(tdb_context(conn), key, data, TDB_REPLACE) != 0) {
corrupt(conn, "Write of %s = %s failed", key, data);
- errno = ENOSPC;
- return false;
+ goto error;
}
return true;
+ error:
+ errno = ENOSPC;
+ return false;
}
static enum xs_perm_type perm_for_conn(struct connection *conn,
@@ -765,8 +775,11 @@ static void delete_node_single(struct connection *conn, struct node *node)
key.dptr = (void *)node->name;
key.dsize = strlen(node->name);
- if (tdb_delete(tdb_context(conn), key) != 0)
+ if (tdb_delete(tdb_context(conn), key) != 0) {
corrupt(conn, "Could not delete '%s'", node->name);
+ return;
+ }
+ domain_entry_dec(conn);
}
/* Must not be / */
@@ -788,7 +801,10 @@ static struct node *construct_node(struct connection *conn, const char *name)
parent = construct_node(conn, parentname);
if (!parent)
return NULL;
-
+
+ if (domain_entry(conn) >= quota_nb_entry_per_domain)
+ return NULL;
+
/* Add child to parent. */
base = basename(name);
baselen = strlen(base) + 1;
@@ -814,6 +830,7 @@ static struct node *construct_node(struct connection *conn, const char *name)
node->children = node->data = NULL;
node->childlen = node->datalen = 0;
node->parent = parent;
+ domain_entry_inc(conn);
return node;
}
@@ -848,8 +865,10 @@ static struct node *create_node(struct connection *conn,
/* We write out the nodes down, setting destructor in case
* something goes wrong. */
for (i = node; i; i = i->parent) {
- if (!write_node(conn, i))
+ if (!write_node(conn, i)) {
+ domain_entry_dec(conn);
return NULL;
+ }
talloc_set_destructor(i, destroy_node);
}
@@ -1706,6 +1725,9 @@ static void usage(void)
" --no-fork to request that the daemon does not fork,\n"
" --output-pid to request that the pid of the daemon is output,\n"
" --trace-file <file> giving the file for logging, and\n"
+" --entry-nb <nb> limit the number of entries per domain,\n"
+" --entry-size <size> limit the size of entry per domain, and\n"
+" --entry-watch <nb> limit the number of watches per domain,\n"
" --no-recovery to request that no recovery should be attempted when\n"
" the store is corrupted (debug only),\n"
" --preserve-local to request that /local is preserved on start-up,\n"
@@ -1715,14 +1737,17 @@ static void usage(void)
static struct option options[] = {
{ "no-domain-init", 0, NULL, 'D' },
+ { "entry-nb", 1, NULL, 'E' },
{ "pid-file", 1, NULL, 'F' },
{ "help", 0, NULL, 'H' },
{ "no-fork", 0, NULL, 'N' },
{ "output-pid", 0, NULL, 'P' },
+ { "entry-size", 1, NULL, 'S' },
{ "trace-file", 1, NULL, 'T' },
{ "no-recovery", 0, NULL, 'R' },
{ "preserve-local", 0, NULL, 'L' },
{ "verbose", 0, NULL, 'V' },
+ { "watch-nb", 1, NULL, 'W' },
{ NULL, 0, NULL, 0 } };
extern void dump_conn(struct connection *conn);
@@ -1737,12 +1762,15 @@ int main(int argc, char *argv[])
bool no_domain_init = false;
const char *pidfile = NULL;
- while ((opt = getopt_long(argc, argv, "DF:HNPT:RLV", options,
+ while ((opt = getopt_long(argc, argv, "DE:F:HNPS:T:RLVW:", options,
NULL)) != -1) {
switch (opt) {
case 'D':
no_domain_init = true;
break;
+ case 'E':
+ quota_nb_entry_per_domain = strtol(optarg, NULL, 10);
+ break;
case 'F':
pidfile = optarg;
break;
@@ -1761,12 +1789,18 @@ int main(int argc, char *argv[])
case 'L':
remove_local = false;
break;
+ case 'S':
+ quota_max_entry_size = strtol(optarg, NULL, 10);
+ break;
case 'T':
tracefile = optarg;
break;
case 'V':
verbose = true;
break;
+ case 'W':
+ quota_nb_watch_per_domain = strtol(optarg, NULL, 10);
+ break;
}
}
if (optind != argc)