[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 1/2] xenstore: add support for reading directory with many children
As the payload size for one xenstore wire command is limited to 4096 bytes it is impossible to read the children names of a node with a large number of children (e.g. /local/domain in case of a host with more than about 2000 domains). This effectively limits the maximum number of domains a host can support. In order to support such long directory outputs add a new wire command XS_DIRECTORY_PART which will return only some entries in each call and can be called in a loop to get all entries. For this to work reliably the loop using XS_DIRECTORY_PART until no further entries are returned must be in one transaction. Using XS_DIRECTORY_PART with a valid path will start the transmission by copying the list of children to a xenstored internal buffer linked to the transaction. Further calls of XS_DIRECTORY_PART with a path "@" will advance in the buffer. The end of the output is indicated by an empty child name. The internal buffer is released when: - the buffer is exhausted - XS_DIRECTORY or XS_DIRECTORY_PART with a valid path is called (this will allocate a new buffer, of course) - the transaction is terminated (explicit or implicit termination) The number of entries returned for each call is implementation specific. The only guarantee is that no call will exceed the limit of 4096 bytes returned. Signed-off-by: Juergen Gross <jgross@xxxxxxxx> --- tools/xenstore/xenstored_core.c | 4 +++ tools/xenstore/xenstored_transaction.c | 57 ++++++++++++++++++++++++++++++++++ tools/xenstore/xenstored_transaction.h | 1 + xen/include/public/io/xs_wire.h | 1 + 4 files changed, 63 insertions(+) diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_core.c index 3df977b..9667ce5 100644 --- a/tools/xenstore/xenstored_core.c +++ b/tools/xenstore/xenstored_core.c @@ -1327,6 +1327,10 @@ static void process_message(struct connection *conn, struct buffered_data *in) do_reset_watches(conn, in); break; + case XS_DIRECTORY_PART: + send_directory_part(conn, in); + break; + default: eprintf("Client unknown operation %i", in->hdr.msg.type); send_error(conn, ENOSYS); diff --git a/tools/xenstore/xenstored_transaction.c b/tools/xenstore/xenstored_transaction.c index 34720fa..22a51da 100644 --- a/tools/xenstore/xenstored_transaction.c +++ b/tools/xenstore/xenstored_transaction.c @@ -79,6 +79,11 @@ struct transaction /* List of changed domains - to record the changed domain entry number */ struct list_head changed_domains; + + /* Temporary buffer for XS_DIRECTORY_PART. */ + char *dirpart_buf; + unsigned buf_off; + unsigned buf_len; }; extern int quota_max_transaction; @@ -280,6 +285,58 @@ void conn_delete_all_transactions(struct connection *conn) conn->transaction_started = 0; } +void send_directory_part(struct connection *conn, struct buffered_data *in) +{ + struct transaction *trans = conn->transaction; + struct node *node; + const char *name = onearg(in); + unsigned len; + + if (name == NULL || trans == NULL) { + send_error(conn, EINVAL); + return; + } + + if (name[0] == '@' && name[1] == 0) { + if (trans->dirpart_buf == NULL) { + send_error(conn, EINVAL); + return; + } + } else { + if (trans->dirpart_buf) { + talloc_free(trans->dirpart_buf); + trans->dirpart_buf = NULL; + } + + name = canonicalize(conn, name); + node = get_node(conn, in, name, XS_PERM_READ); + if (!node) { + send_error(conn, errno); + return; + } + trans->dirpart_buf = talloc_array(trans, char, + node->childlen + 1); + memcpy(trans->dirpart_buf, node->children, node->childlen); + trans->dirpart_buf[node->childlen] = 0; + trans->buf_off = 0; + trans->buf_len = node->childlen + 1; + } + + if (trans->buf_len - trans->buf_off > 1024) + len = strlen(trans->dirpart_buf + trans->buf_off) + 1; + else + len = trans->buf_len - trans->buf_off; + + send_reply(conn, XS_DIRECTORY_PART, trans->dirpart_buf + trans->buf_off, + len); + + trans->buf_off += len; + if (trans->buf_off == trans->buf_len) { + talloc_free(trans->dirpart_buf); + trans->dirpart_buf = NULL; + } +} + /* * Local variables: * c-file-style: "linux" diff --git a/tools/xenstore/xenstored_transaction.h b/tools/xenstore/xenstored_transaction.h index 0c868ee..7e9e187 100644 --- a/tools/xenstore/xenstored_transaction.h +++ b/tools/xenstore/xenstored_transaction.h @@ -38,5 +38,6 @@ void add_change_node(struct transaction *trans, const char *node, TDB_CONTEXT *tdb_transaction_context(struct transaction *trans); void conn_delete_all_transactions(struct connection *conn); +void send_directory_part(struct connection *conn, struct buffered_data *in); #endif /* _XENSTORED_TRANSACTION_H */ diff --git a/xen/include/public/io/xs_wire.h b/xen/include/public/io/xs_wire.h index 0a0cdbc..545f916 100644 --- a/xen/include/public/io/xs_wire.h +++ b/xen/include/public/io/xs_wire.h @@ -50,6 +50,7 @@ enum xsd_sockmsg_type XS_SET_TARGET, XS_RESTRICT, XS_RESET_WATCHES, + XS_DIRECTORY_PART, XS_INVALID = 0xffff /* Guaranteed to remain an invalid type */ }; -- 2.6.6 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |