ia64/xen-unstable

changeset 7040:10d6bda59ea4

Add check for speed (takes 33 minutes on my laptop, OUCH!)

Make xenstored use tdb, transactions can soft-fail (EAGAIN)
Transactions no longer take root dir, no longer lock & block: commit can fail spuriously with EAGAIN, not ETIMEDOUT.
Speeds up transactions by over 1000 times, should be NFS safe.
New program: xs_tdb_dump to dump raw TDB contents.
Don't do failure testing: we are no longer robust against all ENOMEM 8(
Introduce "struct node" which contains perms, children and data.
Make struct xs_permissions unpadded, so we can write to tdb w/o valgrind complaints.
Gently modify TDB to use talloc, not do alloc on tdb_delete.

Fix up transaction users for new semantics.
Don't need a transaction around a single read in xen/i386/kernel/smpboot.c.
Python: transaction_start() returns True/False rather than raising exception on EAGAIN.
Fix usage comment on xs_transaction_end().
Include stdarg to xs_tdb_dump so it compiles.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
author emellor@ewan
date Fri Sep 23 14:28:16 2005 +0100 (2005-09-23)
parents 76af1a1df67c
children 352151393395 64e3cab7ab9e
files linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c linux-2.6-xen-sparse/arch/xen/kernel/reboot.c linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c linux-2.6-xen-sparse/include/asm-xen/xenbus.h tools/python/xen/lowlevel/xs/xs.c tools/python/xen/xend/XendDomainInfo.py tools/python/xen/xend/server/DevController.py tools/python/xen/xend/xenstore/xsnode.py tools/python/xen/xend/xenstore/xstransact.py tools/xenstore/xenstore_client.c tools/xenstore/xs.h tools/xenstore/xs_tdb_dump.c
line diff
     1.1 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c	Fri Sep 23 14:25:01 2005 +0100
     1.2 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c	Fri Sep 23 14:28:16 2005 +0100
     1.3 @@ -1394,9 +1394,7 @@ static void handle_vcpu_hotplug_event(st
     1.4  			return;
     1.5  
     1.6  		/* get the state value */
     1.7 -		xenbus_transaction_start("cpu");
     1.8  		err = xenbus_scanf(dir, "availability", "%s", state);
     1.9 -		xenbus_transaction_end(0);
    1.10  
    1.11  		if (err != 1) {
    1.12  			printk(KERN_ERR
     2.1 --- a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c	Fri Sep 23 14:25:01 2005 +0100
     2.2 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c	Fri Sep 23 14:28:16 2005 +0100
     2.3 @@ -324,7 +324,7 @@ static void shutdown_handler(struct xenb
     2.4      int err;
     2.5  
     2.6   again:
     2.7 -    err = xenbus_transaction_start("control");
     2.8 +    err = xenbus_transaction_start();
     2.9      if (err)
    2.10  	return;
    2.11      str = (char *)xenbus_read("control", "shutdown", NULL);
    2.12 @@ -337,7 +337,7 @@ static void shutdown_handler(struct xenb
    2.13      xenbus_write("control", "shutdown", "");
    2.14  
    2.15      err = xenbus_transaction_end(0);
    2.16 -    if (err == -ETIMEDOUT) {
    2.17 +    if (err == -EAGAIN) {
    2.18  	kfree(str);
    2.19  	goto again;
    2.20      }
    2.21 @@ -366,7 +366,7 @@ static void sysrq_handler(struct xenbus_
    2.22      int err;
    2.23  
    2.24   again:
    2.25 -    err = xenbus_transaction_start("control");
    2.26 +    err = xenbus_transaction_start();
    2.27      if (err)
    2.28  	return;
    2.29      if (!xenbus_scanf("control", "sysrq", "%c", &sysrq_key)) {
    2.30 @@ -379,7 +379,7 @@ static void sysrq_handler(struct xenbus_
    2.31  	xenbus_printf("control", "sysrq", "%c", '\0');
    2.32  
    2.33      err = xenbus_transaction_end(0);
    2.34 -    if (err == -ETIMEDOUT)
    2.35 +    if (err == -EAGAIN)
    2.36  	goto again;
    2.37  
    2.38      if (sysrq_key != '\0') {
     3.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c	Fri Sep 23 14:25:01 2005 +0100
     3.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c	Fri Sep 23 14:28:16 2005 +0100
     3.3 @@ -80,8 +80,9 @@ static void frontend_changed(struct xenb
     3.4  		return;
     3.5  	}
     3.6  
     3.7 +again:
     3.8  	/* Supply the information about the device the frontend needs */
     3.9 -	err = xenbus_transaction_start(be->dev->nodename);
    3.10 +	err = xenbus_transaction_start();
    3.11  	if (err) {
    3.12  		xenbus_dev_error(be->dev, err, "starting transaction");
    3.13  		return;
    3.14 @@ -119,7 +120,15 @@ static void frontend_changed(struct xenb
    3.15  		goto abort;
    3.16  	}
    3.17  
    3.18 -	xenbus_transaction_end(0);
    3.19 +	err = xenbus_transaction_end(0);
    3.20 +	if (err == EAGAIN)
    3.21 +		goto again;
    3.22 +	if (err) {
    3.23 +		xenbus_dev_error(be->dev, err, "ending transaction",
    3.24 +				 ring_ref, evtchn);
    3.25 +		goto abort;
    3.26 +	}
    3.27 +
    3.28  	xenbus_dev_ok(be->dev);
    3.29  
    3.30  	return;
     4.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c	Fri Sep 23 14:25:01 2005 +0100
     4.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c	Fri Sep 23 14:28:16 2005 +0100
     4.3 @@ -572,7 +572,8 @@ static int talk_to_backend(struct xenbus
     4.4  		goto out;
     4.5  	}
     4.6  
     4.7 -	err = xenbus_transaction_start(dev->nodename);
     4.8 +again:
     4.9 +	err = xenbus_transaction_start();
    4.10  	if (err) {
    4.11  		xenbus_dev_error(dev, err, "starting transaction");
    4.12  		goto destroy_blkring;
    4.13 @@ -603,6 +604,8 @@ static int talk_to_backend(struct xenbus
    4.14  
    4.15  	err = xenbus_transaction_end(0);
    4.16  	if (err) {
    4.17 +		if (err == EAGAIN)
    4.18 +			goto again;
    4.19  		xenbus_dev_error(dev, err, "completing transaction");
    4.20  		goto destroy_blkring;
    4.21  	}
     5.1 --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c	Fri Sep 23 14:25:01 2005 +0100
     5.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c	Fri Sep 23 14:28:16 2005 +0100
     5.3 @@ -1122,7 +1122,8 @@ static int talk_to_backend(struct xenbus
     5.4  		goto out;
     5.5  	}
     5.6  
     5.7 -	err = xenbus_transaction_start(dev->nodename);
     5.8 +again:
     5.9 +	err = xenbus_transaction_start();
    5.10  	if (err) {
    5.11  		xenbus_dev_error(dev, err, "starting transaction");
    5.12  		goto destroy_ring;
    5.13 @@ -1160,6 +1161,8 @@ static int talk_to_backend(struct xenbus
    5.14  
    5.15  	err = xenbus_transaction_end(0);
    5.16  	if (err) {
    5.17 +		if (err == EAGAIN)
    5.18 +			goto again;
    5.19  		xenbus_dev_error(dev, err, "completing transaction");
    5.20  		goto destroy_ring;
    5.21  	}
     6.1 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c	Fri Sep 23 14:25:01 2005 +0100
     6.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c	Fri Sep 23 14:28:16 2005 +0100
     6.3 @@ -287,12 +287,11 @@ EXPORT_SYMBOL(xenbus_rm);
     6.4  
     6.5  /* Start a transaction: changes by others will not be seen during this
     6.6   * transaction, and changes will not be visible to others until end.
     6.7 - * Transaction only applies to the given subtree.
     6.8   * You can only have one transaction at any time.
     6.9   */
    6.10 -int xenbus_transaction_start(const char *subtree)
    6.11 +int xenbus_transaction_start(void)
    6.12  {
    6.13 -	return xs_error(xs_single(XS_TRANSACTION_START, subtree, NULL));
    6.14 +	return xs_error(xs_single(XS_TRANSACTION_START, "", NULL));
    6.15  }
    6.16  EXPORT_SYMBOL(xenbus_transaction_start);
    6.17  
     7.1 --- a/linux-2.6-xen-sparse/include/asm-xen/xenbus.h	Fri Sep 23 14:25:01 2005 +0100
     7.2 +++ b/linux-2.6-xen-sparse/include/asm-xen/xenbus.h	Fri Sep 23 14:28:16 2005 +0100
     7.3 @@ -87,7 +87,7 @@ int xenbus_write(const char *dir, const 
     7.4  int xenbus_mkdir(const char *dir, const char *node);
     7.5  int xenbus_exists(const char *dir, const char *node);
     7.6  int xenbus_rm(const char *dir, const char *node);
     7.7 -int xenbus_transaction_start(const char *subtree);
     7.8 +int xenbus_transaction_start(void);
     7.9  int xenbus_transaction_end(int abort);
    7.10  
    7.11  /* Single read and scanf: returns -errno or num scanned if > 0. */
     8.1 --- a/tools/python/xen/lowlevel/xs/xs.c	Fri Sep 23 14:25:01 2005 +0100
     8.2 +++ b/tools/python/xen/lowlevel/xs/xs.c	Fri Sep 23 14:28:16 2005 +0100
     8.3 @@ -582,9 +582,8 @@ static PyObject *xspy_unwatch(PyObject *
     8.4  }
     8.5  
     8.6  #define xspy_transaction_start_doc "\n"				\
     8.7 -	"Start a transaction on a path.\n"			\
     8.8 +	"Start a transaction.\n"				\
     8.9  	"Only one transaction can be active at a time.\n"	\
    8.10 -	" path [string]: xenstore path.\n"			\
    8.11  	"\n"							\
    8.12  	"Returns None on success.\n"				\
    8.13  	"Raises RuntimeError on error.\n"			\
    8.14 @@ -593,8 +592,8 @@ static PyObject *xspy_unwatch(PyObject *
    8.15  static PyObject *xspy_transaction_start(PyObject *self, PyObject *args,
    8.16                                          PyObject *kwds)
    8.17  {
    8.18 -    static char *kwd_spec[] = { "path", NULL };
    8.19 -    static char *arg_spec = "s|";
    8.20 +    static char *kwd_spec[] = { NULL };
    8.21 +    static char *arg_spec = "";
    8.22      char *path = NULL;
    8.23  
    8.24      struct xs_handle *xh = xshandle(self);
    8.25 @@ -606,7 +605,7 @@ static PyObject *xspy_transaction_start(
    8.26      if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
    8.27          goto exit;
    8.28      Py_BEGIN_ALLOW_THREADS
    8.29 -    xsval = xs_transaction_start(xh, path);
    8.30 +    xsval = xs_transaction_start(xh);
    8.31      Py_END_ALLOW_THREADS
    8.32      if (!xsval) {
    8.33          PyErr_SetFromErrno(PyExc_RuntimeError);
    8.34 @@ -623,7 +622,7 @@ static PyObject *xspy_transaction_start(
    8.35  	"Attempts to commit the transaction unless abort is true.\n"	\
    8.36  	" abort [int]: abort flag (default 0).\n"			\
    8.37  	"\n"								\
    8.38 -	"Returns None on success.\n"					\
    8.39 +	"Returns True on success, False if you need to try again.\n"	\
    8.40  	"Raises RuntimeError on error.\n"				\
    8.41  	"\n"
    8.42  
    8.43 @@ -646,11 +645,16 @@ static PyObject *xspy_transaction_end(Py
    8.44      xsval = xs_transaction_end(xh, abort);
    8.45      Py_END_ALLOW_THREADS
    8.46      if (!xsval) {
    8.47 +	if (errno == EAGAIN) {
    8.48 +	    Py_INCREF(Py_False);
    8.49 +	    val = Py_False;
    8.50 +	    goto exit;
    8.51 +	}
    8.52          PyErr_SetFromErrno(PyExc_RuntimeError);
    8.53          goto exit;
    8.54      }
    8.55 -    Py_INCREF(Py_None);
    8.56 -    val = Py_None;
    8.57 +    Py_INCREF(Py_True);
    8.58 +    val = Py_True;
    8.59   exit:
    8.60      return val;
    8.61  }
     9.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Fri Sep 23 14:25:01 2005 +0100
     9.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Fri Sep 23 14:28:16 2005 +0100
     9.3 @@ -839,20 +839,20 @@ class XendDomainInfo:
     9.4          """Release all vm devices.
     9.5          """
     9.6  
     9.7 -        t = xstransact("%s/device" % self.path)
     9.8 -
     9.9 -        for n in controllerClasses.keys():
    9.10 -            for d in t.list(n):
    9.11 -                try:
    9.12 -                    t.remove(d)
    9.13 -                except ex:
    9.14 -                    # Log and swallow any exceptions in removal -- there's
    9.15 -                    # nothing more we can do.
    9.16 -                    log.exception(
    9.17 -                        "Device release failed: %s; %s; %s; %s" %
    9.18 -                        (self.info['name'], n, d, str(ex)))
    9.19 -        t.commit()
    9.20 -
    9.21 +        while True:
    9.22 +            t = xstransact("%s/device" % self.path)
    9.23 +            for n in controllerClasses.keys():
    9.24 +                for d in t.list(n):
    9.25 +                    try:
    9.26 +                        t.remove(d)
    9.27 +                    except ex:
    9.28 +                        # Log and swallow any exceptions in removal --
    9.29 +                        # there's nothing more we can do.
    9.30 +                        log.exception(
    9.31 +                           "Device release failed: %s; %s; %s; %s" %
    9.32 +                            (self.info['name'], n, d, str(ex)))
    9.33 +            if t.commit():
    9.34 +                break
    9.35  
    9.36      def eventChannel(self, path=None):
    9.37          """Create an event channel to the domain.
    10.1 --- a/tools/python/xen/xend/server/DevController.py	Fri Sep 23 14:25:01 2005 +0100
    10.2 +++ b/tools/python/xen/xend/server/DevController.py	Fri Sep 23 14:28:16 2005 +0100
    10.3 @@ -126,20 +126,21 @@ class DevController:
    10.4          compulsory to use it; subclasses may prefer to allocate IDs based upon
    10.5          the device configuration instead.
    10.6          """
    10.7 -        path = self.frontendMiscPath()
    10.8 -        t = xstransact(path)
    10.9 -        try:
   10.10 -            result = t.read("nextDeviceID")
   10.11 -            if result:
   10.12 -                result = int(result)
   10.13 -            else:
   10.14 -                result = 1
   10.15 -            t.write("nextDeviceID", str(result + 1))
   10.16 -            t.commit()
   10.17 -            return result
   10.18 -        except:
   10.19 -            t.abort()
   10.20 -            raise
   10.21 +        while True:
   10.22 +            path = self.frontendMiscPath()
   10.23 +            t = xstransact(path)
   10.24 +            try:
   10.25 +                result = t.read("nextDeviceID")
   10.26 +                if result:
   10.27 +                    result = int(result)
   10.28 +                else:
   10.29 +                    result = 1
   10.30 +                t.write("nextDeviceID", str(result + 1))
   10.31 +                if t.commit():
   10.32 +                    return result
   10.33 +            except:
   10.34 +                t.abort()
   10.35 +                raise
   10.36  
   10.37  
   10.38      ## private:
    11.1 --- a/tools/python/xen/xend/xenstore/xsnode.py	Fri Sep 23 14:25:01 2005 +0100
    11.2 +++ b/tools/python/xen/xend/xenstore/xsnode.py	Fri Sep 23 14:28:16 2005 +0100
    11.3 @@ -280,8 +280,8 @@ class XenStore:
    11.4                                 (', while writing %s : %s' % (str(path),
    11.5                                                               str(data))))
    11.6  
    11.7 -    def begin(self, path):
    11.8 -        self.getxs().transaction_start(path)
    11.9 +    def begin(self):
   11.10 +        self.getxs().transaction_start()
   11.11  
   11.12      def commit(self, abandon=False):
   11.13          self.getxs().transaction_end(abort=abandon)
    12.1 --- a/tools/python/xen/xend/xenstore/xstransact.py	Fri Sep 23 14:25:01 2005 +0100
    12.2 +++ b/tools/python/xen/xend/xenstore/xstransact.py	Fri Sep 23 14:28:16 2005 +0100
    12.3 @@ -14,16 +14,8 @@ class xstransact:
    12.4      def __init__(self, path):
    12.5          self.in_transaction = False
    12.6          self.path = path.rstrip("/")
    12.7 -        while True:
    12.8 -            try:
    12.9 -                xshandle().transaction_start(path)
   12.10 -                self.in_transaction = True
   12.11 -                return
   12.12 -            except RuntimeError, ex:
   12.13 -                if ex.args[0] == errno.ENOENT and path != "/":
   12.14 -                    path = "/".join(path.split("/")[0:-1]) or "/"
   12.15 -                else:
   12.16 -                    raise
   12.17 +        xshandle().transaction_start()
   12.18 +        self.in_transaction = True
   12.19  
   12.20      def __del__(self):
   12.21          if self.in_transaction:
   12.22 @@ -175,14 +167,8 @@ class xstransact:
   12.23              t = cls(path)
   12.24              try:
   12.25                  v = t.read(*args)
   12.26 -                t.commit()
   12.27 +                t.abort()
   12.28                  return v
   12.29 -            except RuntimeError, ex:
   12.30 -                t.abort()
   12.31 -                if ex.args[0] == errno.ETIMEDOUT:
   12.32 -                    pass
   12.33 -                else:
   12.34 -                    raise
   12.35              except:
   12.36                  t.abort()
   12.37                  raise
   12.38 @@ -194,14 +180,8 @@ class xstransact:
   12.39              t = cls(path)
   12.40              try:
   12.41                  t.write(*args, **opts)
   12.42 -                t.commit()
   12.43 -                return
   12.44 -            except RuntimeError, ex:
   12.45 -                t.abort()
   12.46 -                if ex.args[0] == errno.ETIMEDOUT:
   12.47 -                    pass
   12.48 -                else:
   12.49 -                    raise
   12.50 +                if t.commit():
   12.51 +                    return
   12.52              except:
   12.53                  t.abort()
   12.54                  raise
   12.55 @@ -217,14 +197,8 @@ class xstransact:
   12.56              t = cls(path)
   12.57              try:
   12.58                  t.remove(*args)
   12.59 -                t.commit()
   12.60 -                return
   12.61 -            except RuntimeError, ex:
   12.62 -                t.abort()
   12.63 -                if ex.args[0] == errno.ETIMEDOUT:
   12.64 -                    pass
   12.65 -                else:
   12.66 -                    raise
   12.67 +                if t.commit():
   12.68 +                    return
   12.69              except:
   12.70                  t.abort()
   12.71                  raise
   12.72 @@ -236,14 +210,8 @@ class xstransact:
   12.73              t = cls(path)
   12.74              try:
   12.75                  v = t.list(*args)
   12.76 -                t.commit()
   12.77 -                return v
   12.78 -            except RuntimeError, ex:
   12.79 -                t.abort()
   12.80 -                if ex.args[0] == errno.ETIMEDOUT:
   12.81 -                    pass
   12.82 -                else:
   12.83 -                    raise
   12.84 +                if t.commit():
   12.85 +                    return v
   12.86              except:
   12.87                  t.abort()
   12.88                  raise
   12.89 @@ -255,14 +223,8 @@ class xstransact:
   12.90              t = cls(path)
   12.91              try:
   12.92                  v = t.gather(*args)
   12.93 -                t.commit()
   12.94 -                return v
   12.95 -            except RuntimeError, ex:
   12.96 -                t.abort()
   12.97 -                if ex.args[0] == errno.ETIMEDOUT:
   12.98 -                    pass
   12.99 -                else:
  12.100 -                    raise
  12.101 +                if t.commit():
  12.102 +                    return v
  12.103              except:
  12.104                  t.abort()
  12.105                  raise
  12.106 @@ -274,14 +236,8 @@ class xstransact:
  12.107              t = cls(path)
  12.108              try:
  12.109                  v = t.store(*args)
  12.110 -                t.commit()
  12.111 -                return v
  12.112 -            except RuntimeError, ex:
  12.113 -                t.abort()
  12.114 -                if ex.args[0] == errno.ETIMEDOUT:
  12.115 -                    pass
  12.116 -                else:
  12.117 -                    raise
  12.118 +                if t.commit():
  12.119 +                    return v
  12.120              except:
  12.121                  t.abort()
  12.122                  raise
    13.1 --- a/tools/xenstore/xenstore_client.c	Fri Sep 23 14:25:01 2005 +0100
    13.2 +++ b/tools/xenstore/xenstore_client.c	Fri Sep 23 14:28:16 2005 +0100
    13.3 @@ -14,6 +14,7 @@
    13.4  #include <stdlib.h>
    13.5  #include <string.h>
    13.6  #include <xs.h>
    13.7 +#include <errno.h>
    13.8  
    13.9  static void
   13.10  usage(const char *progname)
   13.11 @@ -82,8 +83,8 @@ main(int argc, char **argv)
   13.12      }
   13.13  #endif
   13.14  
   13.15 -    /* XXX maybe find longest common prefix */
   13.16 -    success = xs_transaction_start(xsh, "/");
   13.17 +  again:
   13.18 +    success = xs_transaction_start(xsh);
   13.19      if (!success)
   13.20  	errx(1, "couldn't start transaction");
   13.21  
   13.22 @@ -145,8 +146,10 @@ main(int argc, char **argv)
   13.23  
   13.24   out:
   13.25      success = xs_transaction_end(xsh, ret ? true : false);
   13.26 -    if (!success)
   13.27 +    if (!success) {
   13.28 +	if (ret == 0 && errno == EAGAIN)
   13.29 +	    goto again;
   13.30  	errx(1, "couldn't end transaction");
   13.31 -
   13.32 +    }
   13.33      return ret;
   13.34  }
    14.1 --- a/tools/xenstore/xs.h	Fri Sep 23 14:25:01 2005 +0100
    14.2 +++ b/tools/xenstore/xs.h	Fri Sep 23 14:28:16 2005 +0100
    14.3 @@ -116,8 +116,8 @@ bool xs_transaction_start(struct xs_hand
    14.4  
    14.5  /* End a transaction.
    14.6   * If abandon is true, transaction is discarded instead of committed.
    14.7 - * Returns false on failure, which indicates an error: transactions will
    14.8 - * not fail spuriously.
    14.9 + * Returns false on failure: if errno == EAGAIN, you have to restart
   14.10 + * transaction.
   14.11   */
   14.12  bool xs_transaction_end(struct xs_handle *h, bool abort);
   14.13  
    15.1 --- a/tools/xenstore/xs_tdb_dump.c	Fri Sep 23 14:25:01 2005 +0100
    15.2 +++ b/tools/xenstore/xs_tdb_dump.c	Fri Sep 23 14:28:16 2005 +0100
    15.3 @@ -3,6 +3,7 @@
    15.4  #include <stdlib.h>
    15.5  #include <fcntl.h>
    15.6  #include <stdio.h>
    15.7 +#include <stdarg.h>
    15.8  
    15.9  #include "xs_lib.h"
   15.10  #include "tdb.h"