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>
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>
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"