xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Juergen Gross <jgross@suse.com>
To: xen-devel@lists.xen.org
Cc: Juergen Gross <jgross@suse.com>,
	wei.liu2@citrix.com, andrew.cooper3@citrix.com,
	ian.jackson@eu.citrix.com, david.vrabel@citrix.com,
	jbeulich@suse.com
Subject: [PATCH 1/2] xenstore: add support for reading directory with many children
Date: Tue, 25 Oct 2016 07:52:40 +0200	[thread overview]
Message-ID: <1477374761-25962-2-git-send-email-jgross@suse.com> (raw)
In-Reply-To: <1477374761-25962-1-git-send-email-jgross@suse.com>

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@suse.com>
---
 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@lists.xen.org
https://lists.xen.org/xen-devel

  reply	other threads:[~2016-10-25  5:52 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-10-25  5:52 [PATCH 0/2] xenstore: support reading directory with many children Juergen Gross
2016-10-25  5:52 ` Juergen Gross [this message]
2016-10-25  9:06   ` [PATCH 1/2] xenstore: add support for " Jan Beulich
     [not found]   ` <580F3CC902000078001195F3@suse.com>
2016-10-25 11:41     ` Juergen Gross
2016-10-25 13:20       ` Jan Beulich
     [not found]       ` <580F785502000078001197C7@suse.com>
2016-10-25 13:47         ` Juergen Gross
2016-10-25 14:02           ` Jan Beulich
     [not found]           ` <580F820E0200007800119823@suse.com>
2016-10-25 14:48             ` Juergen Gross
2016-10-25  5:52 ` [PATCH 2/2] xenstore: support XS_DIRECTORY_PART in libxenstore Juergen Gross

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1477374761-25962-2-git-send-email-jgross@suse.com \
    --to=jgross@suse.com \
    --cc=andrew.cooper3@citrix.com \
    --cc=david.vrabel@citrix.com \
    --cc=ian.jackson@eu.citrix.com \
    --cc=jbeulich@suse.com \
    --cc=wei.liu2@citrix.com \
    --cc=xen-devel@lists.xen.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).