On Tue, Aug 27, 2013 at 11:51:29AM -0700, Ian Main wrote: > This patch changes virFileLoopDeviceOpen() to use the new loop-control > device to allocate a new loop device. If this behavior is unsupported > we fall back to the previous method of searching /dev for a free device. > > With this patch you can start as many image based LXC domains as you > like (well almost). > > Fixes bug https://bugzilla.redhat.com/show_bug.cgi?id=995543 > > V2: > - Modified to use a dedicated error return for loop-control allocation > function. > - Only do fallback if /dev/loop-control does not exist, otherwise return > error. > > Signed-off-by: Ian Main <imain@xxxxxxxxxx> > --- > configure.ac | 12 +++++++++ > src/util/virfile.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++- > 2 files changed, 84 insertions(+), 1 deletion(-) > > diff --git a/configure.ac b/configure.ac > index ac8cfa1..10cd872 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -913,6 +913,18 @@ if test "$with_lxc" = "yes" || test "$with_lxc" = "check"; then > AC_MSG_ERROR([Required kernel features for LXC were not found]) > fi > ]) > + AC_LINK_IFELSE([AC_LANG_PROGRAM( > + [[ > + #include <sched.h> > + #include <linux/loop.h> > + #include <sys/epoll.h> > + ]], [[ > + unshare(!(LOOP_CTL_GET_FREE)); > + ]])], [ > + AC_DEFINE([HAVE_DECL_LOOP_CTL_GET_FREE], [1], > + [Define to 1 if you have the declaration of `LOOP_CTL_GET_FREE', > + and to 0 if you don't.]) > + ]) > fi > if test "$with_lxc" = "yes" ; then > AC_DEFINE_UNQUOTED([WITH_LXC], 1, [whether LXC driver is enabled]) > diff --git a/src/util/virfile.c b/src/util/virfile.c > index 2b07ac9..22a0db5 100644 > --- a/src/util/virfile.c > +++ b/src/util/virfile.c > @@ -528,7 +528,56 @@ int virFileUpdatePerm(const char *path, > > > #if defined(__linux__) && HAVE_DECL_LO_FLAGS_AUTOCLEAR > -static int virFileLoopDeviceOpen(char **dev_name) > + > +#if HAVE_DECL_LOOP_CTL_GET_FREE > + > +/* virFileLoopDeviceOpenLoopCtl() returns -1 when a real failure has occured > + * while in the process of allocating or opening the loop device. On success > + * we return 0 and modify the fd to the appropriate file descriptor. > + * If /dev/loop-control does not exist, we return 0 and do not set fd. */ > + > +static int virFileLoopDeviceOpenLoopCtl(char **dev_name, int *fd) > +{ > + int devnr; > + int ctl_fd; > + char *looppath = NULL; > + > + VIR_DEBUG("Opening loop-control device"); > + if ((ctl_fd = open("/dev/loop-control", O_RDWR)) < 0) { > + virReportSystemError(errno, "%s", > + _("Unable to open /dev/loop-control")); > + if (errno == ENOENT) { > + return 0; > + } > + return -1; > + } > + > + if ((devnr = ioctl(ctl_fd, LOOP_CTL_GET_FREE)) < 0) { > + virReportSystemError(errno, "%s", > + _("Unable to get free loop device via ioctl")); > + close(ctl_fd); > + return -1; > + } > + close(ctl_fd); > + > + VIR_DEBUG("Found free loop device number %i", devnr); > + > + if (virAsprintf(&looppath, "/dev/loop%i", devnr) < 0) > + return -1; > + > + if ((*fd = open(looppath, O_RDWR)) < 0) { > + virReportSystemError(errno, > + _("Unable to open %s"), looppath); > + VIR_FREE(looppath); > + return -1; > + } > + > + *dev_name = looppath; > + return 0; > +} > +#endif /* HAVE_DECL_LOOP_CTL_GET_FREE */ > + > +static int virFileLoopDeviceOpenSearch(char **dev_name) > { > int fd = -1; > DIR *dh = NULL; > @@ -601,6 +650,28 @@ cleanup: > return fd; > } > > +static int virFileLoopDeviceOpen(char **dev_name) > +{ > + int loop_fd = -1; > + > +#ifdef HAVE_DECL_LOOP_CTL_GET_FREE > + if (virFileLoopDeviceOpenLoopCtl(dev_name, &loop_fd) < 0) > + return -1; > + > + VIR_DEBUG("Return from loop-control got fd %d\n", loop_fd); > + > + if (loop_fd < 0) { > + VIR_WARN("loop-control allocation failed, trying search technique."); > + } else { > + return loop_fd; > + } We don't really need to VIR_WARN here - it is an expected scenario on old kernels. We're already logging the loop_fd value above, so I'd change this if/else pair to be simply: if (loop_fd >= 0) return loop_fd; > +#endif /* HAVE_DECL_LOOP_CTL_GET_FREE */ > + > + /* Without the loop control device we just use the old technique. */ > + loop_fd = virFileLoopDeviceOpenSearch(dev_name); > + > + return loop_fd; > +} > > int virFileLoopDeviceAssociate(const char *file, > char **dev) Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list