direct-io.hg

changeset 7408:2b95dde72853

Fix transaction EAGAIN handling in xenstore client programs.
Redirect all output to a buffer and only print the buffer once the
transaction succeeds, discarding output from previous attempts.
In particular, fixes failures when the (block) backend driver would
not configure because reads from the hotplug script did get double
output when a transaction had to be redone.
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
author cl349@firebug.cl.cam.ac.uk
date Tue Oct 18 02:08:26 2005 +0100 (2005-10-18)
parents 1d88f303c39c
children cd2a4d6da0a1
files tools/xenstore/xenstore_client.c
line diff
     1.1 --- a/tools/xenstore/xenstore_client.c	Mon Oct 17 20:34:10 2005 +0100
     1.2 +++ b/tools/xenstore/xenstore_client.c	Tue Oct 18 02:08:26 2005 +0100
     1.3 @@ -9,13 +9,45 @@
     1.4   */
     1.5  
     1.6  #include <err.h>
     1.7 +#include <errno.h>
     1.8  #include <fcntl.h>
     1.9  #include <getopt.h>
    1.10 +#include <stdarg.h>
    1.11  #include <stdio.h>
    1.12  #include <stdlib.h>
    1.13  #include <string.h>
    1.14  #include <xs.h>
    1.15 -#include <errno.h>
    1.16 +
    1.17 +static char *output_buf = NULL;
    1.18 +static int output_pos = 0;
    1.19 +
    1.20 +#if defined(CLIENT_read) || defined(CLIENT_list)
    1.21 +static int output_size = 0;
    1.22 +
    1.23 +static void
    1.24 +output(const char *fmt, ...) {
    1.25 +    va_list ap;
    1.26 +    int len;
    1.27 +    char buf[1];
    1.28 +
    1.29 +    va_start(ap, fmt);
    1.30 +    len = vsnprintf(buf, 1, fmt, ap);
    1.31 +    if (len < 0)
    1.32 +	err(1, "output");
    1.33 +    va_end(ap);
    1.34 +    if (len + 1 + output_pos > output_size) {
    1.35 +	output_size += len + 1024;
    1.36 +	output_buf = realloc(output_buf, output_size);
    1.37 +	if (output_buf == NULL)
    1.38 +	    err(1, "malloc");
    1.39 +    }
    1.40 +    va_start(ap, fmt);
    1.41 +    if (vsnprintf(&output_buf[output_pos], len + 1, fmt, ap) != len)
    1.42 +	err(1, "output");
    1.43 +    va_end(ap);
    1.44 +    output_pos += len;
    1.45 +}
    1.46 +#endif
    1.47  
    1.48  static void
    1.49  usage(const char *progname)
    1.50 @@ -34,7 +66,7 @@ usage(const char *progname)
    1.51  
    1.52  #if defined(CLIENT_rm)
    1.53  static int
    1.54 -do_rm(char * path, struct xs_handle *xsh, struct xs_transaction_handle *xth)
    1.55 +do_rm(char *path, struct xs_handle *xsh, struct xs_transaction_handle *xth)
    1.56  {
    1.57      if (xs_rm(xsh, xth, path)) {
    1.58          return 0;
    1.59 @@ -59,8 +91,8 @@ perform(int optind, int argc, char **arg
    1.60  	    return 1;
    1.61  	}
    1.62  	if (prefix)
    1.63 -	    printf("%s: ", argv[optind]);
    1.64 -	printf("%s\n", val);
    1.65 +	    output("%s: ", argv[optind]);
    1.66 +	output("%s\n", val);
    1.67  	free(val);
    1.68  	optind++;
    1.69  #elif defined(CLIENT_write)
    1.70 @@ -131,8 +163,8 @@ perform(int optind, int argc, char **arg
    1.71  	}
    1.72  	for (i = 0; i < num; i++) {
    1.73  	    if (prefix)
    1.74 -		printf("%s/", argv[optind]);
    1.75 -	    printf("%s\n", list[i]);
    1.76 +		output("%s/", argv[optind]);
    1.77 +	    output("%s\n", list[i]);
    1.78  	}
    1.79  	free(list);
    1.80  	optind++;
    1.81 @@ -217,9 +249,15 @@ main(int argc, char **argv)
    1.82      ret = perform(optind, argc, argv, xsh, xth, prefix, tidy);
    1.83  
    1.84      if (!xs_transaction_end(xsh, xth, ret)) {
    1.85 -	if (ret == 0 && errno == EAGAIN)
    1.86 +	if (ret == 0 && errno == EAGAIN) {
    1.87 +	    output_pos = 0;
    1.88  	    goto again;
    1.89 +	}
    1.90  	errx(1, "couldn't end transaction");
    1.91      }
    1.92 +
    1.93 +    if (output_pos)
    1.94 +	printf("%s", output_buf);
    1.95 +
    1.96      return ret;
    1.97  }