[libvirt] [PATCH] LXC: support block devices for container

Daniel P. Berrange berrange at redhat.com
Fri Apr 6 10:38:47 UTC 2012


On Fri, Apr 06, 2012 at 02:31:54PM +0800, Gao feng wrote:
> This patch allows to config block device for container.
> the disk node is used to point out source device and target device
> source device is the device path in host,
> and target device is the device name in container.
> such as
> <disk type='block' device='disk'>
>     <driver name="lxc"/>
>     <source dev='/dev/sda2'/>
>     <target dev='sda1'/>

Here you have different source + target dev names - the way this is
implemented, they must match.

> </disk>
> 
> Unfortunately it's no use to config readonly in disk node now.

Can't you support readonly mode via cgroups. You set an ACL
of 'rwm' for the disk, which could just be set to 'r' for
<readonly/> mode.

> 
> Signed-off-by: Gao feng <gaofeng at cn.fujitsu.com>

While this patch works, and I've considered doing this myself
too, I was half wondering whether we should instead be doing
this using  <hostdev>, since the way we're implementing this
is really direct host device assignment to the container.

The vast majority of the data associated with the <disk>
element cannot be used in this scenario, since we can't
modify what the host device already uses.

> diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
> index 9bb6218..062cc8f 100644
> --- a/src/lxc/lxc_container.c
> +++ b/src/lxc/lxc_container.c
> @@ -581,6 +581,80 @@ static int lxcContainerMountFSDevPTS(virDomainFSDefPtr root)
>      return rc;
>  }
>  
> +static int lxcContainerAddDisk(virDomainDiskDefPtr disk,
> +                               const char *srcprefix)
> +{
> +    char *srcPath = NULL;
> +    char *dstPath = NULL;
> +    struct stat sb;
> +    dev_t dev;
> +    int ret = -1;
> +    switch (disk->device) {
> +    case VIR_DOMAIN_DISK_DEVICE_DISK:
> +    case VIR_DOMAIN_DISK_DEVICE_LUN:
> +        if (virAsprintf(&srcPath, "%s/%s", srcprefix, disk->src) < 0) {
> +            virReportOOMError();
> +            return ret;
> +        }
> +        if (virAsprintf(&dstPath, "/dev/%s", disk->dst) < 0) {
> +            virReportOOMError();
> +            goto cleanup;
> +        }
> +        if (stat(srcPath, &sb) < 0) {
> +            ret = -errno;
> +            goto cleanup;
> +        }
> +        dev = makedev(major(sb.st_rdev), minor(sb.st_rdev));
> +        if (mknod(dstPath, S_ISCHR(sb.st_mode) ? S_IFCHR : S_IFBLK, dev) < 0 ||
> +            chmod(dstPath, sb.st_mode)) {
> +            virReportSystemError(errno,
> +                                 _("Failed to make device %s"),
> +                                 dstPath);
> +            goto cleanup;
> +        }
> +        ret = 0;
> +        break;
> +    default:
> +        lxcError(VIR_ERR_CONFIG_UNSUPPORTED,
> +                 _("unsupported disk device type '%s'."),
> +                 virDomainDiskDeviceTypeToString(disk->device));
> +        break;
> +    }
> +
> +cleanup:
> +    VIR_FREE(srcPath);
> +    VIR_FREE(dstPath);
> +    return ret;
> +}
> +static int lxcContainerAddDevices(virDomainDefPtr vmDef,
> +                                 const char *srcprefix)
> +{
> +    int ret = -1;
> +    size_t i;
> +
> +    for (i=0 ; i<vmDef->ndisks ; i++) {
> +        virDomainDiskDefPtr disk = vmDef->disks[i];
> +
> +        if (disk->driverName !=NULL && !STREQ(disk->driverName, "lxc")) {
> +            lxcError(VIR_ERR_CONFIG_UNSUPPORTED,
> +		     _("unsupported driver name '%s' for disk '%s'"),
> +		     disk->driverName, disk->src);
> +            continue;
> +        }
> +        if (disk->type != VIR_DOMAIN_DISK_TYPE_BLOCK) {
> +            lxcError(VIR_ERR_CONFIG_UNSUPPORTED,
> +                     _("unsupported disk type '%s'"),
> +                     virDomainDiskTypeToString(disk->type));
> +            continue;
> +        }
> +        if (lxcContainerAddDisk(disk, srcprefix) < 0)
> +            goto cleanup;
> +    }
> +    ret = 0;
> +cleanup:
> +    return ret;
> +}
> +
>  static int lxcContainerPopulateDevices(char **ttyPaths, size_t nttyPaths)
>  {
>      size_t i;
> @@ -1144,6 +1218,10 @@ static int lxcContainerSetupPivotRoot(virDomainDefPtr vmDef,
>      if (lxcContainerMountFSDevPTS(root) < 0)
>          return -1;
>  
> +    /* Create devices */
> +    if (lxcContainerAddDevices(vmDef, "/.oldroot") <0)
> +        return -1;
> +
>      /* Populates device nodes in /dev/ */
>      if (lxcContainerPopulateDevices(ttyPaths, nttyPaths) < 0)
>          return -1;
> diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
> index bbc9d9c..5576f99 100644
> --- a/src/lxc/lxc_controller.c
> +++ b/src/lxc/lxc_controller.c
> @@ -545,6 +545,21 @@ static int lxcSetContainerDeviceACL(virCgroupPtr cgroup, virDomainDefPtr def)
>          }
>      }
>  
> +    for (i = 0 ; i < def->ndisks ; i++) {
> +        if (def->disks[i]->type != VIR_DOMAIN_DISK_TYPE_BLOCK)
> +            continue;
> +
> +        rc = virCgroupAllowDevicePath(cgroup,
> +                                      def->disks[i]->src,
> +                                      VIR_CGROUP_DEVICE_RWM);
> +        if (rc != 0) {
> +            virReportSystemError(-rc,
> +                                 _("Unable to allow device %s for domain %s"),
> +                                 def->disks[i]->src, def->name);
> +            goto cleanup;
> +        }
> +    }
> +
>      rc = virCgroupAllowDeviceMajor(cgroup, 'c', LXC_DEV_MAJ_PTY,
>                                     VIR_CGROUP_DEVICE_RWM);
>      if (rc != 0) {



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




More information about the libvir-list mailing list