ia64/xen-unstable

changeset 9710:e7d769001b4b

add quota to xenstored.

Signed-off-by: Vincent Hanquez <vincent@xensource.com>
author vhanquez@kneesa.uk.xensource.com
date Thu Apr 13 16:21:13 2006 +0000 (2006-04-13)
parents 14f6d138c61d
children ec4f87e98fc1
files tools/xenstore/xenstored_core.c tools/xenstore/xenstored_domain.c tools/xenstore/xenstored_domain.h tools/xenstore/xenstored_watch.c
line diff
     1.1 --- a/tools/xenstore/xenstored_core.c	Thu Apr 13 15:15:56 2006 +0100
     1.2 +++ b/tools/xenstore/xenstored_core.c	Thu Apr 13 16:21:13 2006 +0000
     1.3 @@ -77,6 +77,10 @@ static void check_store(void);
     1.4  	} while (0)
     1.5  
     1.6  
     1.7 +int quota_nb_entry_per_domain = 1000;
     1.8 +int quota_nb_watch_per_domain = 128;
     1.9 +int quota_max_entry_size = 2048; /* 2K */
    1.10 +
    1.11  #ifdef TESTING
    1.12  static bool failtest = false;
    1.13  
    1.14 @@ -455,6 +459,10 @@ static bool write_node(struct connection
    1.15  	data.dsize = 3*sizeof(uint32_t)
    1.16  		+ node->num_perms*sizeof(node->perms[0])
    1.17  		+ node->datalen + node->childlen;
    1.18 +
    1.19 +	if (data.dsize >= quota_max_entry_size)
    1.20 +		goto error;
    1.21 +
    1.22  	data.dptr = talloc_size(node, data.dsize);
    1.23  	((uint32_t *)data.dptr)[0] = node->num_perms;
    1.24  	((uint32_t *)data.dptr)[1] = node->datalen;
    1.25 @@ -470,10 +478,12 @@ static bool write_node(struct connection
    1.26  	/* TDB should set errno, but doesn't even set ecode AFAICT. */
    1.27  	if (tdb_store(tdb_context(conn), key, data, TDB_REPLACE) != 0) {
    1.28  		corrupt(conn, "Write of %s = %s failed", key, data);
    1.29 -		errno = ENOSPC;
    1.30 -		return false;
    1.31 +		goto error;
    1.32  	}
    1.33  	return true;
    1.34 + error:
    1.35 +	errno = ENOSPC;
    1.36 +	return false;
    1.37  }
    1.38  
    1.39  static enum xs_perm_type perm_for_conn(struct connection *conn,
    1.40 @@ -765,8 +775,11 @@ static void delete_node_single(struct co
    1.41  	key.dptr = (void *)node->name;
    1.42  	key.dsize = strlen(node->name);
    1.43  
    1.44 -	if (tdb_delete(tdb_context(conn), key) != 0)
    1.45 +	if (tdb_delete(tdb_context(conn), key) != 0) {
    1.46  		corrupt(conn, "Could not delete '%s'", node->name);
    1.47 +		return;
    1.48 +	}
    1.49 +	domain_entry_dec(conn);
    1.50  }
    1.51  
    1.52  /* Must not be / */
    1.53 @@ -788,7 +801,10 @@ static struct node *construct_node(struc
    1.54  		parent = construct_node(conn, parentname);
    1.55  	if (!parent)
    1.56  		return NULL;
    1.57 -	
    1.58 +
    1.59 +	if (domain_entry(conn) >= quota_nb_entry_per_domain)
    1.60 +		return NULL;
    1.61 +
    1.62  	/* Add child to parent. */
    1.63  	base = basename(name);
    1.64  	baselen = strlen(base) + 1;
    1.65 @@ -814,6 +830,7 @@ static struct node *construct_node(struc
    1.66  	node->children = node->data = NULL;
    1.67  	node->childlen = node->datalen = 0;
    1.68  	node->parent = parent;
    1.69 +	domain_entry_inc(conn);
    1.70  	return node;
    1.71  }
    1.72  
    1.73 @@ -848,8 +865,10 @@ static struct node *create_node(struct c
    1.74  	/* We write out the nodes down, setting destructor in case
    1.75  	 * something goes wrong. */
    1.76  	for (i = node; i; i = i->parent) {
    1.77 -		if (!write_node(conn, i))
    1.78 +		if (!write_node(conn, i)) {
    1.79 +			domain_entry_dec(conn);
    1.80  			return NULL;
    1.81 +		}
    1.82  		talloc_set_destructor(i, destroy_node);
    1.83  	}
    1.84  
    1.85 @@ -1706,6 +1725,9 @@ static void usage(void)
    1.86  "  --no-fork           to request that the daemon does not fork,\n"
    1.87  "  --output-pid        to request that the pid of the daemon is output,\n"
    1.88  "  --trace-file <file> giving the file for logging, and\n"
    1.89 +"  --entry-nb <nb>     limit the number of entries per domain,\n"
    1.90 +"  --entry-size <size> limit the size of entry per domain, and\n"
    1.91 +"  --entry-watch <nb>  limit the number of watches per domain,\n"
    1.92  "  --no-recovery       to request that no recovery should be attempted when\n"
    1.93  "                      the store is corrupted (debug only),\n"
    1.94  "  --preserve-local    to request that /local is preserved on start-up,\n"
    1.95 @@ -1715,14 +1737,17 @@ static void usage(void)
    1.96  
    1.97  static struct option options[] = {
    1.98  	{ "no-domain-init", 0, NULL, 'D' },
    1.99 +	{ "entry-nb", 1, NULL, 'E' },
   1.100  	{ "pid-file", 1, NULL, 'F' },
   1.101  	{ "help", 0, NULL, 'H' },
   1.102  	{ "no-fork", 0, NULL, 'N' },
   1.103  	{ "output-pid", 0, NULL, 'P' },
   1.104 +	{ "entry-size", 1, NULL, 'S' },
   1.105  	{ "trace-file", 1, NULL, 'T' },
   1.106  	{ "no-recovery", 0, NULL, 'R' },
   1.107  	{ "preserve-local", 0, NULL, 'L' },
   1.108  	{ "verbose", 0, NULL, 'V' },
   1.109 +	{ "watch-nb", 1, NULL, 'W' },
   1.110  	{ NULL, 0, NULL, 0 } };
   1.111  
   1.112  extern void dump_conn(struct connection *conn); 
   1.113 @@ -1737,12 +1762,15 @@ int main(int argc, char *argv[])
   1.114  	bool no_domain_init = false;
   1.115  	const char *pidfile = NULL;
   1.116  
   1.117 -	while ((opt = getopt_long(argc, argv, "DF:HNPT:RLV", options,
   1.118 +	while ((opt = getopt_long(argc, argv, "DE:F:HNPS:T:RLVW:", options,
   1.119  				  NULL)) != -1) {
   1.120  		switch (opt) {
   1.121  		case 'D':
   1.122  			no_domain_init = true;
   1.123  			break;
   1.124 +		case 'E':
   1.125 +			quota_nb_entry_per_domain = strtol(optarg, NULL, 10);
   1.126 +			break;
   1.127  		case 'F':
   1.128  			pidfile = optarg;
   1.129  			break;
   1.130 @@ -1761,12 +1789,18 @@ int main(int argc, char *argv[])
   1.131  		case 'L':
   1.132  			remove_local = false;
   1.133  			break;
   1.134 +		case 'S':
   1.135 +			quota_max_entry_size = strtol(optarg, NULL, 10);
   1.136 +			break;
   1.137  		case 'T':
   1.138  			tracefile = optarg;
   1.139  			break;
   1.140  		case 'V':
   1.141  			verbose = true;
   1.142  			break;
   1.143 +		case 'W':
   1.144 +			quota_nb_watch_per_domain = strtol(optarg, NULL, 10);
   1.145 +			break;
   1.146  		}
   1.147  	}
   1.148  	if (optind != argc)
     2.1 --- a/tools/xenstore/xenstored_domain.c	Thu Apr 13 15:15:56 2006 +0100
     2.2 +++ b/tools/xenstore/xenstored_domain.c	Thu Apr 13 16:21:13 2006 +0000
     2.3 @@ -74,6 +74,12 @@ struct domain
     2.4  
     2.5  	/* Have we noticed that this domain is shutdown? */
     2.6  	int shutdown;
     2.7 +
     2.8 +	/* number of entry from this domain in the store */
     2.9 +	int nbentry;
    2.10 +
    2.11 +	/* number of watch for this domain */
    2.12 +	int nbwatch;
    2.13  };
    2.14  
    2.15  static LIST_HEAD(domains);
    2.16 @@ -285,6 +291,8 @@ static struct domain *new_domain(void *c
    2.17  	domain->conn->id = domid;
    2.18  
    2.19  	domain->remote_port = port;
    2.20 +	domain->nbentry = 0;
    2.21 +	domain->nbwatch = 0;
    2.22  
    2.23  	return domain;
    2.24  }
    2.25 @@ -562,6 +570,50 @@ int domain_init(void)
    2.26  	return eventchn_fd;
    2.27  }
    2.28  
    2.29 +void domain_entry_inc(struct connection *conn)
    2.30 +{
    2.31 +	if (!conn || !conn->domain)
    2.32 +		return;
    2.33 +	conn->domain->nbentry++;
    2.34 +}
    2.35 +
    2.36 +void domain_entry_dec(struct connection *conn)
    2.37 +{
    2.38 +	if (!conn || !conn->domain)
    2.39 +		return;
    2.40 +	if (conn->domain->nbentry)
    2.41 +		conn->domain->nbentry--;
    2.42 +}
    2.43 +
    2.44 +int domain_entry(struct connection *conn)
    2.45 +{
    2.46 +	return (conn && conn->domain && conn->domain->domid)
    2.47 +		? conn->domain->nbentry
    2.48 +		: 0;
    2.49 +}
    2.50 +
    2.51 +void domain_watch_inc(struct connection *conn)
    2.52 +{
    2.53 +	if (!conn || !conn->domain)
    2.54 +		return;
    2.55 +	conn->domain->nbwatch++;
    2.56 +}
    2.57 +
    2.58 +void domain_watch_dec(struct connection *conn)
    2.59 +{
    2.60 +	if (!conn || !conn->domain)
    2.61 +		return;
    2.62 +	if (conn->domain->nbwatch)
    2.63 +		conn->domain->nbwatch--;
    2.64 +}
    2.65 +
    2.66 +int domain_watch(struct connection *conn)
    2.67 +{
    2.68 +	return (conn && conn->domain && conn->domain->domid)
    2.69 +		? conn->domain->nbwatch
    2.70 +		: 0;
    2.71 +}
    2.72 +
    2.73  /*
    2.74   * Local variables:
    2.75   *  c-file-style: "linux"
     3.1 --- a/tools/xenstore/xenstored_domain.h	Thu Apr 13 15:15:56 2006 +0100
     3.2 +++ b/tools/xenstore/xenstored_domain.h	Thu Apr 13 16:21:13 2006 +0000
     3.3 @@ -47,4 +47,12 @@ void restore_existing_connections(void);
     3.4  bool domain_can_read(struct connection *conn);
     3.5  bool domain_can_write(struct connection *conn);
     3.6  
     3.7 +/* Quota manipulation */
     3.8 +void domain_entry_inc(struct connection *conn);
     3.9 +void domain_entry_dec(struct connection *conn);
    3.10 +int domain_entry(struct connection *conn);
    3.11 +void domain_watch_inc(struct connection *conn);
    3.12 +void domain_watch_dec(struct connection *conn);
    3.13 +int domain_watch(struct connection *conn);
    3.14 +
    3.15  #endif /* _XENSTORED_DOMAIN_H */
     4.1 --- a/tools/xenstore/xenstored_watch.c	Thu Apr 13 15:15:56 2006 +0100
     4.2 +++ b/tools/xenstore/xenstored_watch.c	Thu Apr 13 16:21:13 2006 +0000
     4.3 @@ -32,6 +32,8 @@
     4.4  #include "xenstored_test.h"
     4.5  #include "xenstored_domain.h"
     4.6  
     4.7 +extern int quota_nb_watch_per_domain;
     4.8 +
     4.9  struct watch
    4.10  {
    4.11  	/* Watches on this connection */
    4.12 @@ -135,6 +137,11 @@ void do_watch(struct connection *conn, s
    4.13  		}
    4.14  	}
    4.15  
    4.16 +	if (domain_watch(conn) > quota_nb_watch_per_domain) {
    4.17 +		send_error(conn, E2BIG);
    4.18 +		return;
    4.19 +	}
    4.20 +
    4.21  	watch = talloc(conn, struct watch);
    4.22  	watch->node = talloc_strdup(watch, vec[0]);
    4.23  	watch->token = talloc_strdup(watch, vec[1]);
    4.24 @@ -145,6 +152,7 @@ void do_watch(struct connection *conn, s
    4.25  
    4.26  	INIT_LIST_HEAD(&watch->events);
    4.27  
    4.28 +	domain_watch_inc(conn);
    4.29  	list_add_tail(&watch->list, &conn->watches);
    4.30  	trace_create(watch, "watch");
    4.31  	talloc_set_destructor(watch, destroy_watch);
    4.32 @@ -169,6 +177,7 @@ void do_unwatch(struct connection *conn,
    4.33  		if (streq(watch->node, node) && streq(watch->token, vec[1])) {
    4.34  			list_del(&watch->list);
    4.35  			talloc_free(watch);
    4.36 +			domain_watch_dec(conn);
    4.37  			send_ack(conn, XS_UNWATCH);
    4.38  			return;
    4.39  		}