(root)/xen_locking.patch - Rev 3
Rev 2 |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
--- /root/xen_lock_patch/XendDomainInfo.py 2011-03-14 11:03:21.000000000 +0100
+++ /usr/lib/xen-4.1/lib/python/xen/xend/XendDomainInfo.py 2011-03-14 15:50:52.000000000 +0100
@@ -365,6 +365,8 @@
@type state_updated: threading.Condition
@ivar refresh_shutdown_lock: lock for polling shutdown state
@type refresh_shutdown_lock: threading.Condition
+ @ivar running_lock: lock for running VM
+ @type running_lock: bool or None
@ivar _deviceControllers: device controller cache for this domain
@type _deviceControllers: dict 'string' to DevControllers
"""
@@ -444,6 +446,8 @@
self.refresh_shutdown_lock = threading.Condition()
self._stateSet(DOM_STATE_HALTED)
+ self.running_lock = None
+
self._deviceControllers = {}
for state in DOM_STATES_OLD:
@@ -470,6 +474,7 @@
if self._stateGet() in (XEN_API_VM_POWER_STATE_HALTED, XEN_API_VM_POWER_STATE_SUSPENDED, XEN_API_VM_POWER_STATE_CRASHED):
try:
+ self.acquire_running_lock();
XendTask.log_progress(0, 30, self._constructDomain)
XendTask.log_progress(31, 60, self._initDomain)
@@ -496,6 +501,7 @@
state = self._stateGet()
if state in (DOM_STATE_SUSPENDED, DOM_STATE_HALTED):
try:
+ self.acquire_running_lock();
self._constructDomain()
try:
@@ -2950,6 +2956,11 @@
self._stateSet(DOM_STATE_HALTED)
self.domid = None # Do not push into _stateSet()!
+
+ try:
+ self.release_running_lock()
+ except:
+ log.exception("Release running lock failed: %s" % status)
finally:
self.refresh_shutdown_lock.release()
@@ -4438,6 +4449,32 @@
def has_device(self, dev_class, dev_uuid):
return (dev_uuid in self.info['%s_refs' % dev_class.lower()])
+ def acquire_running_lock(self):
+ if not self.running_lock:
+ lock_path = xoptions.get_xend_domains_lock_path()
+ if lock_path:
+ doms_lock_path = xoptions.get_xend_domains_path()
+ if doms_lock_path:
+ status = os.system('%s --lock --name %s --uuid %s --path %s' % \
+ (lock_path, self.info['name_label'], self.info['uuid'], doms_lock_path))
+ if status == 0:
+ self.running_lock = True
+ else:
+ raise XendError('Acquire running lock failed: %s' % status)
+
+ def release_running_lock(self):
+ if self.running_lock:
+ lock_path = xoptions.get_xend_domains_lock_path()
+ if lock_path:
+ doms_lock_path = xoptions.get_xend_domains_path()
+ if doms_lock_path:
+ status = os.system('%s --unlock --name %s --uuid %s --path %s' % \
+ (lock_path, self.info['name_label'], self.info['uuid'], doms_lock_path))
+ if status == 0:
+ self.running_lock = False
+ else:
+ raise XendError('Release running lock failed: %s' % status)
+
def __str__(self):
return '<domain id=%s name=%s memory=%s state=%s>' % \
(str(self.domid), self.info['name_label'],
--- /root/xen_lock_patch/XendDomain.py 2011-03-14 11:04:13.000000000 +0100
+++ /usr/lib/xen-4.1/lib/python/xen/xend/XendDomain.py 2011-03-14 11:26:44.000000000 +0100
@@ -1368,6 +1368,7 @@
raise XendError("Domain is not a managed domain")
""" The following call may raise a XendError exception """
+ dominfo.release_running_lock();
dominfo.testMigrateDevices(True, dst)
if live:
--- /root/xen_lock_patch/XendOptions.py 2011-03-14 11:02:52.000000000 +0100
+++ /usr/lib/xen-4.1/lib/python/xen/xend/XendOptions.py 2011-03-14 11:27:33.000000000 +0100
@@ -321,6 +321,11 @@
"""
return self.get_config_string("xend-domains-path", self.xend_domains_path_default)
+ def get_xend_domains_lock_path(self):
+ """ Get the path of the lock utility for running domains.
+ """
+ return self.get_config_string("xend-domains-lock-path")
+
def get_xend_state_path(self):
""" Get the path for persistent domain configuration storage
"""
--- /root/xen_lock_patch/file-lock.c 2011-03-14 15:48:03.000000000 +0100
+++ /etc/xen/scripts/file-lock.c 1970-01-01 01:00:00.000000000 +0100
@@ -0,0 +1,190 @@
+/*
+ * file-lock.c
+ *
+ * Copyright (C) 2008 Oracle Inc.
+ * Copyright (C) 2008 Zhigang Wang <zhigang.x.wang@xxxxxxxxxx>
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <getopt.h>
+
+const char version[] = "0.0.1";
+static char short_opts[] = "lup:d:n:hvV";
+static struct option long_opts[] = {
+ { "lock", no_argument, NULL, 'l' },
+ { "unlock", no_argument, NULL, 'u' },
+ { "path", required_argument, NULL, 'p' },
+ { "name", required_argument, NULL, 'n' },
+ { "uuid", required_argument, NULL, 'd' },
+ { "help", no_argument, NULL, 'h' },
+ { "verbose", no_argument, NULL, 'v' },
+ { "version", no_argument, NULL, 'V' },
+ { NULL, 0, NULL, 0 }
+};
+
+static void usage(char *prog, FILE *fp, int n) {
+ fprintf(fp, "usage: %s [options]\n", prog);
+ fprintf(fp, "\n");
+ fprintf(fp, "options:\n");
+ fprintf(fp, " -l, --lock Acquire the lock.\n");
+ fprintf(fp, " -u, --unlock Release the lock.\n");
+ fprintf(fp, " -p, --path Set the path for the locks.\n");
+ fprintf(fp, " -n, --name Set the name of the VM.\n");
+ fprintf(fp, " -d, --uuid Set the uuid of the VM.\n");
+ fprintf(fp, " -v, --verbose Show more infomation.\n");
+ fprintf(fp, " -V, --version Show version number and exit.\n");
+ fprintf(fp, " -h, --help Show this help information.\n");
+ fprintf(fp, "\n");
+ exit(n);
+}
+
+static int do_lock(char *path, char *name, char *uuid)
+{
+ char *fn;
+ int fd;
+
+ if (asprintf(&fn, "%s/%s-%s.lock", path, name, uuid) == -1)
+ return -1;
+
+ fd = open(fn, O_CREAT|O_RDWR|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+ if (fd == -1) {
+ free(fn);
+ return errno;
+ }
+
+ free(fn);
+ close(fd);
+ return 0;
+}
+
+static int do_unlock(char *path, char *name, char *uuid)
+{
+ char *fn;
+
+ if (asprintf(&fn, "%s/%s-%s.lock", path, name, uuid) == -1)
+ return -1;
+
+ if (unlink(fn) == -1) {
+ free(fn);
+ return errno;
+ }
+
+ free(fn);
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ char *prog, *p;
+ char *name = NULL;
+ char *uuid = NULL;
+ char *path = "."; /* create lock file on current working
+directory by default*/
+ int verbose = 0; /* turn off verbose output by default */
+ int status = 0; /* returned value */
+ int lock = 0, unlock = 0;
+ int c;
+
+ prog = argv[0];
+ p = strrchr(prog, '/');
+ if (p)
+ prog = p+1;
+
+ while ((c = getopt_long(argc, argv, short_opts,
+ long_opts, NULL)) != -1) {
+ switch (c) {
+ case 'l': /* acquire the lock */
+ lock = 1;
+ break;
+ case 'u': /* release the lock */
+ unlock = 1;
+ break;
+ case 'p': /* path for lock file */
+ path = optarg;
+ break;
+ case 'n': /* name of vm */
+ name = optarg;
+ break;
+ case 'd': /* uuid of vm */
+ uuid = optarg;
+ break;
+ case 'h': /* help */
+ usage(prog, stdout, 0);
+ break;
+ case 'v': /* be chatty */
+ ++verbose;
+ break;
+ case 'V': /* version */
+ fprintf(stdout, "%s: %s\n", prog, version);
+ exit(0);
+ case 0:
+ break;
+ case '?':
+ default:
+ usage(prog, stderr, 1);
+ }
+ }
+
+ if (optind < argc)
+ usage(prog, stderr, 1);
+
+ if (name==NULL || uuid==NULL) {
+ fprintf(stderr, "you should specify the name and uuid of vm.\n\n");
+ usage(prog, stderr, 1);
+ }
+
+ if (lock && unlock) {
+ fprintf(stderr, "cannot execute lock and unlock at the same time.\n\n");
+ usage(prog, stderr, 1);
+ }
+
+ if (lock) {
+ if (verbose)
+ fprintf(stdout, "creating lock file %s/%s-%s.lock\n", path, name, uuid);
+
+ status = do_lock(path, name, uuid);
+
+ if (verbose)
+ if (status == 0)
+ fprintf(stdout, "lock sucess.\n");
+ else
+ fprintf(stdout, "lock failed.\n");
+ } else if (unlock) {
+ if (verbose)
+ fprintf(stdout, "removing lock file %s/%s-%s.lock\n", path, name, uuid);
+
+ status = do_unlock(path, name, uuid);
+
+ if (verbose)
+ if (status == 0)
+ fprintf(stdout, "unlock sucess.\n");
+ else
+ fprintf(stdout, "unlock failed.\n");
+ } else {
+ fprintf(stderr, "you should specify lock or unlock.\n\n");
+ usage(prog, stderr, 1);
+ }
+
+ return status;
+}
+
--- /root/xen_lock/xend-config.sxp 2011-03-14 15:28:51.000000000 +0100
+++ /etc/xen/xend-config.sxp 2011-03-14 15:51:54.000000000 +0100
@@ -279,3 +279,9 @@
# we have to realize this may incur security issue and we can't make sure the
# device assignment could really work properly even after we do this.
#(pci-passthrough-strict-check yes)
+
+# Locking patch taken from:
+# http://lists.xensource.com/archives/html/xen-devel/2008-08/msg00274.html
+#(xend-domains-path /mnt/xenfs/vm-locks/)
+#(xend-domains-lock-path /etc/xen/scripts/file-lock)
+