From f0de53755f628efe64cd60d4511a9667485eba62 Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Tue, 17 Mar 2015 11:33:50 +0100 Subject: [PATCH] Introduce libxl_vscsi_pdev Signed-off-by: Olaf Hering --- tools/libxl/libxl.c | 15 +++++-- tools/libxl/libxl_types.idl | 18 ++++++--- tools/libxl/libxl_vscsi.c | 78 +++++++++++++++++++++++++++++++++---- tools/libxl/libxlu_vscsi.c | 62 +++++++++++++++-------------- tools/libxl/libxlutil.h | 2 +- tools/libxl/xl_cmdimpl.c | 10 ++--- 6 files changed, 132 insertions(+), 53 deletions(-) diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c index 58cd6830dbd3..0c2826be53ea 100644 --- a/tools/libxl/libxl.c +++ b/tools/libxl/libxl.c @@ -1989,6 +1989,7 @@ void libxl__device_vscsi_add(libxl__egc *egc, uint32_t domid, flexarray_t *front; flexarray_t *back; libxl__device *device; + libxl_vscsi_hctl *hctl; char *be_path; unsigned int be_dirs = 0, rc, i; @@ -2034,18 +2035,24 @@ void libxl__device_vscsi_add(libxl__egc *egc, uint32_t domid, continue; } } - flexarray_append_pair(back, GCSPRINTF("vscsi-devs/dev-%u/p-devname", v->vscsi_dev_id), v->p_devname); - switch (v->pdev_type) { + flexarray_append_pair(back, GCSPRINTF("vscsi-devs/dev-%u/p-devname", v->vscsi_dev_id), v->pdev.p_devname); + switch (v->pdev.type) { case LIBXL_VSCSI_PDEV_TYPE_WWN: flexarray_append_pair(back, GCSPRINTF("vscsi-devs/dev-%u/p-dev", v->vscsi_dev_id), - v->p_devname); + v->pdev.u.wwn); break; case LIBXL_VSCSI_PDEV_TYPE_DEV: + hctl = &v->pdev.u.dev; + flexarray_append_pair(back, + GCSPRINTF("vscsi-devs/dev-%u/p-dev", v->vscsi_dev_id), + GCSPRINTF("%u:%u:%u:%u", hctl->hst, hctl->chn, hctl->tgt, hctl->lun)); + break; case LIBXL_VSCSI_PDEV_TYPE_HCTL: + hctl = &v->pdev.u.hctl; flexarray_append_pair(back, GCSPRINTF("vscsi-devs/dev-%u/p-dev", v->vscsi_dev_id), - GCSPRINTF("%u:%u:%u:%u", v->pdev.hst, v->pdev.chn, v->pdev.tgt, v->pdev.lun)); + GCSPRINTF("%u:%u:%u:%u", hctl->hst, hctl->chn, hctl->tgt, hctl->lun)); break; case LIBXL_VSCSI_PDEV_TYPE_INVALID: default: diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl index 48cd9afc6904..2bd050d8cf5e 100644 --- a/tools/libxl/libxl_types.idl +++ b/tools/libxl/libxl_types.idl @@ -556,12 +556,21 @@ libxl_vscsi_hctl = Struct("vscsi_hctl", [ ("lun", uint32), ]) +libxl_vscsi_pdev = Struct("vscsi_pdev", [ + ("p_devname", string), + ("u", KeyedUnion(None, libxl_vscsi_pdev_type, "type", + [ + ("invalid", None), + ("dev", libxl_vscsi_hctl), + ("wwn", string), + ("hctl", libxl_vscsi_hctl), + ])), + ]) + libxl_vscsi_dev = Struct("vscsi_dev", [ ("vscsi_dev_id", libxl_devid), ("remove", bool), - ("p_devname", string), - ("pdev_type", libxl_vscsi_pdev_type), - ("pdev", libxl_vscsi_hctl), + ("pdev", libxl_vscsi_pdev), ("vdev", libxl_vscsi_hctl), ]) @@ -624,8 +633,7 @@ libxl_vscsiinfo = Struct("vscsiinfo", [ ("frontend", string), ("frontend_id", uint32), ("devid", libxl_devid), - ("p_devname", string), - ("pdev", libxl_vscsi_hctl), + ("pdev", libxl_vscsi_pdev), ("vdev", libxl_vscsi_hctl), ("vscsi_dev_id", libxl_devid), ("feature_host", bool), diff --git a/tools/libxl/libxl_vscsi.c b/tools/libxl/libxl_vscsi.c index 8b1df3b3017e..bec2e4604c60 100644 --- a/tools/libxl/libxl_vscsi.c +++ b/tools/libxl/libxl_vscsi.c @@ -1,7 +1,7 @@ #include "libxl_osdeps.h" /* must come before any other headers */ #include "libxl_internal.h" -static int vscsi_parse_hctl(libxl__gc *gc, char *str, libxl_vscsi_hctl *hctl) +static int vscsi_parse_hctl(char *str, libxl_vscsi_hctl *hctl) { unsigned int hst, chn, tgt, lun; @@ -15,6 +15,69 @@ static int vscsi_parse_hctl(libxl__gc *gc, char *str, libxl_vscsi_hctl *hctl) return 0; } +static bool vscsi_wwn_valid(const char *p) +{ + bool ret = true; + int i = 0; + + for (i = 0; i < 16; i++, p++) { + if (*p >= '0' && *p <= '9') + continue; + if (*p >= 'a' && *p <= 'f') + continue; + if (*p >= 'A' && *p <= 'F') + continue; + ret = false; + break; + } + return ret; +} + +static bool vscsi_parse_pdev(libxl_ctx *ctx, libxl_vscsi_dev *v_dev, + char *c, char *p, char *v) +{ + GC_INIT(ctx); + libxl_vscsi_hctl hctl; + unsigned int lun; + char wwn[16 + 1]; + bool parsed_ok = false; + + libxl_vscsi_hctl_init(&hctl); + + v_dev->pdev.p_devname = libxl__strdup(NOGC, c); + + /* Translate p-dev back into pdev.type, expect a valid p-devname */ + if (strncmp(c, "/dev/", 5) == 0) { + /* Either xenlinux, or pvops with properly configured alias in sysfs */ + if (vscsi_parse_hctl(p, &hctl) == 0) { + libxl_vscsi_pdev_init_type(&v_dev->pdev, LIBXL_VSCSI_PDEV_TYPE_DEV); + libxl_vscsi_hctl_copy(ctx, &v_dev->pdev.u.dev, &hctl); + parsed_ok = true; + } + } else if (strncmp(c, "naa.", 4) == 0) { + /* WWN as understood by pvops */ + memset(wwn, 0, sizeof(wwn)); + if (sscanf(p, "naa.%16c:%u", wwn, &lun) == 2 && vscsi_wwn_valid(wwn)) { + libxl_vscsi_pdev_init_type(&v_dev->pdev, LIBXL_VSCSI_PDEV_TYPE_WWN); + v_dev->pdev.u.wwn = libxl__strdup(NOGC, c); + parsed_ok = true; + } + } else if (vscsi_parse_hctl(p, &hctl) == 0) { + /* Either xenlinux, or pvops with properly configured alias in sysfs */ + libxl_vscsi_pdev_init_type(&v_dev->pdev, LIBXL_VSCSI_PDEV_TYPE_HCTL); + libxl_vscsi_hctl_copy(ctx, &v_dev->pdev.u.hctl, &hctl); + parsed_ok = true; + } + + if (parsed_ok && vscsi_parse_hctl(v, &v_dev->vdev) != 0) + parsed_ok = false; + + libxl_vscsi_hctl_dispose(&hctl); + + GC_FREE; + return parsed_ok; +} + libxl_device_vscsi *libxl_device_vscsi_list(libxl_ctx *ctx, uint32_t domid, int *num) { GC_INIT(ctx); @@ -78,12 +141,11 @@ libxl_device_vscsi *libxl_device_vscsi_list(libxl_ctx *ctx, uint32_t domid, int v = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/vscsi-devs/dev-%u/v-dev", be_path, vscsi_dev_id)); - if (c && p && v) { - v_dev->p_devname = libxl__strdup(NOGC, c); - /* FIXME pdev not always in hctl format with pvops */ - if (vscsi_parse_hctl(gc, p, &v_dev->pdev) == 0 && - vscsi_parse_hctl(gc, v, &v_dev->vdev) == 0) - parsed_ok = true; + if (c && p && v) + parsed_ok = vscsi_parse_pdev(ctx, v_dev, c, p, v); + + /* Indication for caller that this v_dev is usable */ + if (parsed_ok) { v_dev->vscsi_dev_id = vscsi_dev_id; if (vscsi_dev_id > v_hst->next_vscsi_dev_id) v_hst->next_vscsi_dev_id = vscsi_dev_id + 1; @@ -120,7 +182,7 @@ int libxl_device_vscsi_getinfo(libxl_ctx *ctx, uint32_t domid, libxl_vscsiinfo_init(vscsiinfo); dompath = libxl__xs_get_dompath(gc, domid); vscsiinfo->devid = vscsi_host->devid; - libxl_vscsi_hctl_copy(ctx, &vscsiinfo->pdev, &vscsi_dev->pdev); + libxl_vscsi_pdev_copy(ctx, &vscsiinfo->pdev, &vscsi_dev->pdev); libxl_vscsi_hctl_copy(ctx, &vscsiinfo->vdev, &vscsi_dev->vdev); vscsipath = GCSPRINTF("%s/device/vscsi/%d", dompath, vscsiinfo->devid); diff --git a/tools/libxl/libxlu_vscsi.c b/tools/libxl/libxlu_vscsi.c index d7d49f8bd281..0c6909b294cc 100644 --- a/tools/libxl/libxlu_vscsi.c +++ b/tools/libxl/libxlu_vscsi.c @@ -117,33 +117,48 @@ static bool xlu__vscsi_wwn_valid(const char *p) return ret; } -static int xlu__vscsi_parse_pdev(XLU_Config *cfg, char *pdev, libxl_vscsi_dev *new_dev) +static int xlu__vscsi_parse_pdev(XLU_Config *cfg, libxl_ctx *ctx, char *str, + libxl_vscsi_pdev *pdev) { int rc = 0; unsigned int lun; char wwn[16 + 1]; + libxl_vscsi_hctl hctl; - if (strncmp(pdev, "/dev/", 5) == 0) { + libxl_vscsi_hctl_init(&hctl); + if (strncmp(str, "/dev/", 5) == 0) { /* Either xenlinux, or pvops with properly configured alias in sysfs */ - if (xlu__vscsi_parse_dev(cfg, pdev, &new_dev->pdev) == 0) - new_dev->pdev_type = LIBXL_VSCSI_PDEV_TYPE_DEV; - } else if (strncmp(pdev, "naa.", 4) == 0) { + if (xlu__vscsi_parse_dev(cfg, str, &hctl) == 0) { + libxl_vscsi_pdev_init_type(pdev, LIBXL_VSCSI_PDEV_TYPE_DEV); + libxl_vscsi_hctl_copy(ctx, &pdev->u.dev, &hctl); + } + } else if (strncmp(str, "naa.", 4) == 0) { /* WWN as understood by pvops */ memset(wwn, 0, sizeof(wwn)); - if (sscanf(pdev, "naa.%16c:%u", wwn, &lun) == 2 && xlu__vscsi_wwn_valid(wwn)) { - new_dev->pdev_type = LIBXL_VSCSI_PDEV_TYPE_WWN; - new_dev->pdev.lun = lun; + if (sscanf(str, "naa.%16c:%u", wwn, &lun) == 2 && xlu__vscsi_wwn_valid(wwn)) { + libxl_vscsi_pdev_init_type(pdev, LIBXL_VSCSI_PDEV_TYPE_WWN); + pdev->u.wwn = strdup(str); + if (!pdev->u.wwn) + rc = ERROR_NOMEM; } - } else if (xlu__vscsi_parse_hctl(pdev, &new_dev->pdev) == 0) { + } else if (xlu__vscsi_parse_hctl(str, &hctl) == 0) { /* Either xenlinux, or pvops with properly configured alias in sysfs */ - new_dev->pdev_type = LIBXL_VSCSI_PDEV_TYPE_HCTL; + libxl_vscsi_pdev_init_type(pdev, LIBXL_VSCSI_PDEV_TYPE_HCTL); + libxl_vscsi_hctl_copy(ctx, &pdev->u.dev, &hctl); } else rc = ERROR_INVAL; + if (rc == 0) { + pdev->p_devname = strdup(str); + if (!pdev->p_devname) + rc = ERROR_NOMEM; + } + + libxl_vscsi_hctl_dispose(&hctl); return rc; } -int xlu_vscsi_parse(XLU_Config *cfg, const char *str, +int xlu_vscsi_parse(XLU_Config *cfg, libxl_ctx *ctx, const char *str, libxl_device_vscsi *new_host, libxl_vscsi_dev *new_dev) { @@ -168,26 +183,16 @@ int xlu_vscsi_parse(XLU_Config *cfg, const char *str, pdev = xlu__vscsi_trim_string(pdev); vdev = xlu__vscsi_trim_string(vdev); - new_dev->pdev_type = LIBXL_VSCSI_PDEV_TYPE_INVALID; - rc = xlu__vscsi_parse_pdev(cfg, pdev, new_dev); - switch (rc) { - case ERROR_NOPARAVIRT: - LOG(cfg, "vscsi: not supported"); - goto out; - default: - LOG(cfg, "vscsi: failed to parse %s", pdev); - goto out; + rc = xlu__vscsi_parse_pdev(cfg, ctx, pdev, &new_dev->pdev); + if (rc) { + LOG(cfg, "vscsi: failed to parse %s, rc == %d", pdev, rc); + goto out; } - switch (new_dev->pdev_type) { + switch (new_dev->pdev.type) { case LIBXL_VSCSI_PDEV_TYPE_WWN: case LIBXL_VSCSI_PDEV_TYPE_DEV: case LIBXL_VSCSI_PDEV_TYPE_HCTL: - new_dev->p_devname = strdup(pdev); - if (!new_dev->p_devname) { - rc = ERROR_NOMEM; - goto out; - } break; case LIBXL_VSCSI_PDEV_TYPE_INVALID: LOG(cfg, "vscsi: invalid pdev '%s'", pdev); @@ -260,10 +265,9 @@ int xlu_vscsi_get_host(XLU_Config *cfg, libxl_ctx *ctx, uint32_t domid, const ch libxl_device_vscsi_init(new_host); libxl_vscsi_dev_init(new_dev); - if (xlu_vscsi_parse(cfg, str, new_host, new_dev)) { - rc = ERROR_INVAL; + rc = xlu_vscsi_parse(cfg, ctx, str, new_host, new_dev); + if (rc) goto out; - } /* Look for existing vscsi_host for given domain */ vscsi_hosts = libxl_device_vscsi_list(ctx, domid, &num_hosts); diff --git a/tools/libxl/libxlutil.h b/tools/libxl/libxlutil.h index cdfdccef5eb4..3f0b298c9a48 100644 --- a/tools/libxl/libxlutil.h +++ b/tools/libxl/libxlutil.h @@ -108,7 +108,7 @@ int xlu_vscsi_get_host(XLU_Config *config, uint32_t domid, const char *str, libxl_device_vscsi *vscsi_host); -int xlu_vscsi_parse(XLU_Config *cfg, const char *str, +int xlu_vscsi_parse(XLU_Config *cfg, libxl_ctx *ctx, const char *str, libxl_device_vscsi *new_host, libxl_vscsi_dev *new_dev); #endif /* LIBXLUTIL_H */ diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c index 79d1ce92500a..ca12aa673721 100644 --- a/tools/libxl/xl_cmdimpl.c +++ b/tools/libxl/xl_cmdimpl.c @@ -1508,7 +1508,7 @@ static void parse_config_data(const char *config_source, libxl_device_vscsi_init(&v_hst); libxl_vscsi_dev_init(&v_dev); - if (xlu_vscsi_parse(config, buf, &v_hst, &v_dev)) + if (xlu_vscsi_parse(config, ctx, buf, &v_hst, &v_dev)) exit (-1); if (d_config->num_vscsis) { @@ -6608,9 +6608,7 @@ int main_vscsilist(int argc, char **argv) for (h = 0; h < num_hosts; ++h) { for (d = 0; d < vscsi_hosts[h].num_vscsi_devs; d++) { if (!libxl_device_vscsi_getinfo(ctx, domid, &vscsi_hosts[h], &vscsi_hosts[h].vscsi_devs[d], &vscsiinfo)) { - char pdev[64], vdev[64]; - snprintf(pdev, sizeof(pdev), "%u:%u:%u:%u", - vscsiinfo.pdev.hst, vscsiinfo.pdev.chn, vscsiinfo.pdev.tgt, vscsiinfo.pdev.lun); + char vdev[64]; snprintf(vdev, sizeof(vdev), "%u:%u:%u:%u", vscsiinfo.vdev.hst, vscsiinfo.vdev.chn, vscsiinfo.vdev.tgt, vscsiinfo.vdev.lun); /* Idx BE state Sta */ @@ -6619,7 +6617,7 @@ int main_vscsilist(int argc, char **argv) vscsiinfo.backend_id, vscsiinfo.vscsi_host_state, vscsiinfo.backend_id, - pdev, vdev, + vscsiinfo.pdev.p_devname, vdev, vscsiinfo.vscsi_dev_state); libxl_vscsiinfo_dispose(&vscsiinfo); @@ -6657,7 +6655,7 @@ static int vscsidetach(libxl_device_vscsi *hosts, int num, uint32_t domid, libxl_vscsi_dev_init(&v_dev); libxl_device_vscsi_init(&v_hst); - if (xlu_vscsi_parse(config, tmp, &v_hst, &v_dev)) + if (xlu_vscsi_parse(config, ctx, tmp, &v_hst, &v_dev)) goto out; for (h = 0; h < num; ++h) {