[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

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.