[adding NBD list]
On 03/21/2018 07:19 AM, Vladimir Sementsov-Ogievskiy wrote:
Signed-off-by: Vladimir Sementsov-Ogievskiy <address@hidden>
---
nbd/server.c | 60
+++++++++++++++++++++++++++++++++++++++++++-----------------
1 file changed, 43 insertions(+), 17 deletions(-)
+struct {
+ const char *ns;
+ int (*func)(NBDClient *, NBDExportMetaContexts *, uint32_t,
Error **);
+} meta_namespace_handlers[] = {
+ /* namespaces should go in non-decreasing order by name length */
+ {.ns = "base:", .func = nbd_meta_base_query},
+};
+
@@ -787,9 +793,12 @@ static int nbd_negotiate_meta_query(NBDClient
*client,
NBDExportMetaContexts *meta,
Error **errp)
{
int ret;
- char query[sizeof("base:") - 1];
- size_t baselen = strlen("base:");
+ int i;
uint32_t len;
+ int bytes_done = 0;
+ char *query;
+ int nb_ns = sizeof(meta_namespace_handlers) /
+ sizeof(meta_namespace_handlers[0]);
Use the ARRAY_SIZE() macro here.
+ query = g_malloc(strlen(meta_namespace_handlers[nb_ns - 1].ns));
So this sizes a buffer according to the largest namespace we expect to
handle,...
- len -= baselen;
- ret = nbd_opt_read(client, query, baselen, errp);
- if (ret <= 0) {
- return ret;
- }
- if (strncmp(query, "base:", baselen) != 0) {
- return nbd_opt_skip(client, len, errp);
+ for (i = 0; i < nb_ns; i++) {
+ const char *ns = meta_namespace_handlers[i].ns;
+ int ns_len = strlen(ns);
+ int diff_len = strlen(ns) - bytes_done;
+
+ assert(diff_len >= 0);
+
+ if (diff_len > 0) {
+ if (len < diff_len) {
+ ret = nbd_opt_skip(client, len, errp);
+ goto out;
+ }
+
+ len -= diff_len;
+ ret = nbd_opt_read(client, query + bytes_done, diff_len,
errp);
+ if (ret <= 0) {
+ goto out;
+ }
+ }
+
+ if (!strncmp(query, ns, ns_len)) {
+ ret = meta_namespace_handlers[i].func(client, meta, len,
errp);
+ goto out;
+ }
...then you do multiple iterative reads as you step through the list.
You know, if you encounter a ':' at any point in the iterative reads,
you don't have to continue through the rest of the handlers (the query
belongs to a short-named namespace we didn't recognize).
Is it any smarter to just blindly do a single read of MIN(querylen,
maxlen), then strchr() for ':' (if not found, it's not a namespace we
recognize), and then look up if the name matches, at which point we
then read the rest of the query and refactor the namespace handler to
be passed the already-parsed leafname, rather than having to parse the
leafname off the wire in the handler?