diff -Nru libvirt-0.9.2/debian/changelog libvirt-0.9.2/debian/changelog --- libvirt-0.9.2/debian/changelog 2011-10-03 20:39:16.000000000 -0500 +++ libvirt-0.9.2/debian/changelog 2011-10-12 16:43:03.000000000 -0500 @@ -1,3 +1,11 @@ +libvirt (0.9.2-4ubuntu16) oneiric; urgency=low + + * Lxc: call virFileOpenTtyAt() from a task with the container's /dev/pts + bind mounted to /dev/pts. Otherwise container creation will fail if + /dev/pts/0 is unavailable. (LP: #863629) + + -- Serge Hallyn Wed, 12 Oct 2011 16:42:12 -0500 + libvirt (0.9.2-4ubuntu15) oneiric; urgency=low * Pull patches from upstream which prevent a race between lxc driver and diff -Nru libvirt-0.9.2/debian/patches/lxc-fix-granpt.patch libvirt-0.9.2/debian/patches/lxc-fix-granpt.patch --- libvirt-0.9.2/debian/patches/lxc-fix-granpt.patch 1969-12-31 18:00:00.000000000 -0600 +++ libvirt-0.9.2/debian/patches/lxc-fix-granpt.patch 2011-10-12 16:42:08.000000000 -0500 @@ -0,0 +1,150 @@ +Description: Fix occasional container creation failure due to misuse of grantpt + glibc's grantpt and ptsname cannot be used on a fd for a pty not in + /dev/pts. The lxc controller tries to do just that. So if you try to + start a container on a system where /dev/pts/0 is not available, it + will fail. You can make this happen by opening a terminal on + /dev/pts/0, and doing 'sleep 2h & disown; exit'. To fix this, I call + the virFileOpenTtyAt() from a forked task in a new mount ns, and first + mount the container's /dev/pts onto /dev/pts. (Then the opened fd must + be passed back to the lxc driver). Another solution would be to just + do it all by hand without grantpt and ptsname. +Author: Serge Hallyn +Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/libvirt/+bug/863629 +Forwarded: yes + +Index: libvirt-0.9.2/src/lxc/lxc_controller.c +=================================================================== +--- libvirt-0.9.2.orig/src/lxc/lxc_controller.c 2011-10-12 16:30:10.850906668 -0500 ++++ libvirt-0.9.2/src/lxc/lxc_controller.c 2011-10-12 16:33:00.659748704 -0500 +@@ -606,6 +606,113 @@ + # define MS_SLAVE (1<<19) + #endif + ++static int send_pty(int sock, int *pty) ++{ ++ struct iovec vector; ++ struct msghdr msg; ++ struct cmsghdr * cmsg; ++ int ret; ++ ++ vector.iov_base = "PTY"; ++ vector.iov_len = 3; ++ ++ msg.msg_name = NULL; ++ msg.msg_namelen = 0; ++ msg.msg_iov = &vector; ++ msg.msg_iovlen = 1; ++ ++ cmsg = alloca(sizeof(struct cmsghdr) + sizeof(*pty)); ++ cmsg->cmsg_len = sizeof(struct cmsghdr) + sizeof(*pty); ++ cmsg->cmsg_level = SOL_SOCKET; ++ cmsg->cmsg_type = SCM_RIGHTS; ++ ++ memcpy(CMSG_DATA(cmsg), pty, sizeof(*pty)); ++ ++ msg.msg_control = cmsg; ++ msg.msg_controllen = cmsg->cmsg_len; ++ ++ ret = sendmsg(sock, &msg, 0); ++ if (ret < 0) ++ return -1; ++ return 0; ++} ++ ++static int recv_pty(int sock, int *pty, char **path, char *devpts) ++{ ++ char buf[50]; ++ struct iovec vector; ++ struct msghdr msg; ++ struct cmsghdr * cmsg; ++ int ret; ++ ++ vector.iov_base = buf; ++ vector.iov_len = 50; ++ ++ msg.msg_name = NULL; ++ msg.msg_namelen = 0; ++ msg.msg_iov = &vector; ++ msg.msg_iovlen = 1; ++ ++ cmsg = alloca(sizeof(struct cmsghdr) + sizeof(*pty)); ++ cmsg->cmsg_len = sizeof(struct cmsghdr) + sizeof(*pty); ++ msg.msg_control = cmsg; ++ msg.msg_controllen = cmsg->cmsg_len; ++ ++ ret = recvmsg(sock, &msg, 0); ++ if (ret < 0) ++ return ret; ++ ++ memcpy(pty, CMSG_DATA(cmsg), sizeof(*pty)); ++ ++ if (VIR_ALLOC_N(*path, PATH_MAX) < 0) { ++ virReportSystemError(errno, "%s", ++ _("Failed to allocate space for ptyname")); ++ return -ENOMEM; ++ } ++ //snprintf(*path, PATH_MAX, "%s/0", devpts); ++ snprintf(*path, PATH_MAX, "/dev/pts/0"); ++ return 0; ++} ++ ++static int private_open_tty_at(char *devpts, char *devptmx, ++ int *containerPty, ++ char **containerPtyPath, int rawmode) ++{ ++ int pid; ++ int ret; ++ int status; ++ int s[2]; ++ ++ ret = socketpair(PF_UNIX, SOCK_DGRAM, 0, s); ++ if (ret < 0) ++ return ret; ++ ++ pid = fork(); ++ if (pid < 0) ++ exit(pid); ++ if (pid == 0) { ++ close(s[1]); ++ ret = unshare(CLONE_NEWNS); ++ if (ret < 0) ++ exit(ret); ++ ret = mount(devpts, "/dev/pts", "none", MS_BIND, NULL); ++ if (ret < 0) ++ exit(ret); ++ ret = virFileOpenTtyAt(devptmx, containerPty, containerPtyPath, rawmode); ++ if (ret < 0) ++ exit(ret); ++ send_pty(s[0], containerPty); ++ exit(ret); ++ } ++ close(s[0]); ++ ret = recv_pty(s[1], containerPty, containerPtyPath, devpts); ++ close(s[1]); ++ if (ret) ++ return ret; ++ waitpid(pid, &status, 0); ++ return WEXITSTATUS(status); ++} ++ + static int + lxcControllerRun(virDomainDefPtr def, + unsigned int nveths, +@@ -706,12 +813,12 @@ + + if (devptmx) { + VIR_DEBUG("Opening tty on private %s", devptmx); +- if (virFileOpenTtyAt(devptmx, +- &containerPty, +- &containerPtyPath, +- 0) < 0) { ++ if (private_open_tty_at(devpts, devptmx, ++ &containerPty, ++ &containerPtyPath, ++ 0) < 0) { + virReportSystemError(errno, "%s", +- _("Failed to allocate tty")); ++ _("Failed to allocate tty")); + goto cleanup; + } + } else { diff -Nru libvirt-0.9.2/debian/patches/series libvirt-0.9.2/debian/patches/series --- libvirt-0.9.2/debian/patches/series 2011-10-03 20:39:03.000000000 -0500 +++ libvirt-0.9.2/debian/patches/series 2011-10-12 16:38:06.000000000 -0500 @@ -39,3 +39,4 @@ lxc-refactor-controller-command-building.patch lxc-improve-guest-startup-error-reporting.patch lxc-controller-improve-container-error-reporting.patch +lxc-fix-granpt.patch