#include <libudev.h>
#include "checkers.h"
-#include "memory.h"
#include "vector.h"
#include "util.h"
#include "structs.h"
#include "prio.h"
#include "prioritizers/alua_spc3.h"
#include "dm-generic.h"
+#include "devmapper.h"
struct adapter_group *
alloc_adaptergroup(void)
{
struct adapter_group *agp;
- agp = (struct adapter_group *)MALLOC(sizeof(struct adapter_group));
+ agp = (struct adapter_group *)calloc(1, sizeof(struct adapter_group));
if (!agp)
return NULL;
agp->host_groups = vector_alloc();
if (!agp->host_groups) {
- FREE(agp);
+ free(agp);
agp = NULL;
}
return agp;
vector_foreach_slot(adapters, agp, i) {
free_hostgroup(agp->host_groups);
- FREE(agp);
+ free(agp);
}
vector_free(adapters);
}
vector_foreach_slot(hostgroups, hgp, i) {
vector_free(hgp->paths);
- FREE(hgp);
+ free(hgp);
}
vector_free(hostgroups);
}
{
struct host_group *hgp;
- hgp = (struct host_group *)MALLOC(sizeof(struct host_group));
+ hgp = (struct host_group *)calloc(1, sizeof(struct host_group));
if (!hgp)
return NULL;
hgp->paths = vector_alloc();
if (!hgp->paths) {
- FREE(hgp);
+ free(hgp);
hgp = NULL;
}
return hgp;
{
struct path * pp;
- pp = (struct path *)MALLOC(sizeof(struct path));
+ pp = (struct path *)calloc(1, sizeof(struct path));
if (pp) {
+ pp->initialized = INIT_NEW;
pp->sg_id.host_no = -1;
pp->sg_id.channel = -1;
pp->sg_id.scsi_id = -1;
- pp->sg_id.lun = -1;
+ pp->sg_id.lun = SCSI_INVALID_LUN;
pp->sg_id.proto_id = SCSI_PROTOCOL_UNSPEC;
pp->fd = -1;
pp->tpgs = TPGS_UNDEF;
}
void
-free_path (struct path * pp)
+uninitialize_path(struct path *pp)
{
if (!pp)
return;
+ pp->dmstate = PSTATE_UNDEF;
+ pp->uid_attribute = NULL;
+ pp->getuid = NULL;
+
if (checker_selected(&pp->checker))
checker_put(&pp->checker);
if (prio_selected(&pp->prio))
prio_put(&pp->prio);
- if (pp->fd >= 0)
+ if (pp->fd >= 0) {
close(pp->fd);
+ pp->fd = -1;
+ }
+}
+
+void
+free_path (struct path * pp)
+{
+ if (!pp)
+ return;
+
+ uninitialize_path(pp);
if (pp->udev) {
udev_device_unref(pp->udev);
pp->udev = NULL;
}
+ if (pp->vpd_data)
+ free(pp->vpd_data);
+
vector_free(pp->hwe);
- FREE(pp);
+ free(pp);
}
void
{
struct pathgroup * pgp;
- pgp = (struct pathgroup *)MALLOC(sizeof(struct pathgroup));
+ pgp = (struct pathgroup *)calloc(1, sizeof(struct pathgroup));
if (!pgp)
return NULL;
pgp->paths = vector_alloc();
if (!pgp->paths) {
- FREE(pgp);
+ free(pgp);
return NULL;
}
return;
free_pathvec(pgp->paths, free_paths);
- FREE(pgp);
+ free(pgp);
}
void
{
struct multipath * mpp;
- mpp = (struct multipath *)MALLOC(sizeof(struct multipath));
+ mpp = (struct multipath *)calloc(1, sizeof(struct multipath));
if (mpp) {
mpp->bestpg = 1;
return mpp;
}
+void *set_mpp_hwe(struct multipath *mpp, const struct path *pp)
+{
+ if (!mpp || !pp || !pp->hwe)
+ return NULL;
+ if (mpp->hwe)
+ return mpp->hwe;
+ mpp->hwe = vector_convert(NULL, pp->hwe,
+ struct hwentry, identity);
+ return mpp->hwe;
+}
+
void free_multipath_attributes(struct multipath *mpp)
{
if (!mpp)
return;
if (mpp->selector) {
- FREE(mpp->selector);
+ free(mpp->selector);
mpp->selector = NULL;
}
if (mpp->features) {
- FREE(mpp->features);
+ free(mpp->features);
mpp->features = NULL;
}
if (mpp->hwhandler) {
- FREE(mpp->hwhandler);
+ free(mpp->hwhandler);
mpp->hwhandler = NULL;
}
}
free_multipath_attributes(mpp);
if (mpp->alias) {
- FREE(mpp->alias);
+ free(mpp->alias);
mpp->alias = NULL;
}
- if (mpp->dmi) {
- FREE(mpp->dmi);
- mpp->dmi = NULL;
+ if (!free_paths && mpp->pg) {
+ struct pathgroup *pgp;
+ struct path *pp;
+ int i, j;
+
+ /*
+ * Make sure paths carry no reference to this mpp any more
+ */
+ vector_foreach_slot(mpp->pg, pgp, i) {
+ vector_foreach_slot(pgp->paths, pp, j)
+ if (pp->mpp == mpp)
+ pp->mpp = NULL;
+ }
}
free_pathvec(mpp->paths, free_paths);
free_pgvec(mpp->pg, free_paths);
- FREE_PTR(mpp->mpcontext);
- FREE(mpp);
+ if (mpp->hwe) {
+ vector_free(mpp->hwe);
+ mpp->hwe = NULL;
+ }
+ free(mpp->mpcontext);
+ free(mpp);
}
void
err++;
}
if (!strlen(pp->dev)) {
- condlog(2, "%s: Empty device name", pp->dev_t);
+ condlog(3, "%s: Empty device name", pp->dev_t);
err++;
}
}
struct multipath *
-find_mp_by_minor (const struct _vector *mpvec, int minor)
+find_mp_by_minor (const struct _vector *mpvec, unsigned int minor)
{
int i;
struct multipath * mpp;
return NULL;
vector_foreach_slot (mpvec, mpp, i) {
- if (!mpp->dmi)
+ if (!has_dm_info(mpp))
continue;
- if (mpp->dmi->minor == minor)
+ if (mpp->dmi.minor == minor)
return mpp;
}
return NULL;
find_mp_by_alias (const struct _vector *mpvec, const char * alias)
{
int i;
- int len;
+ size_t len;
struct multipath * mpp;
if (!mpvec)
}
struct path *
-find_path_by_dev (const struct _vector *pathvec, const char * dev)
+find_path_by_dev (const struct _vector *pathvec, const char *dev)
{
int i;
struct path * pp;
- if (!pathvec)
+ if (!pathvec || !dev)
return NULL;
vector_foreach_slot (pathvec, pp, i)
return NULL;
}
-int pathcountgr(const struct pathgroup *pgp, int state)
+static int do_pathcount(const struct multipath *mpp, const int *states,
+ unsigned int nr_states)
{
+ struct pathgroup *pgp;
struct path *pp;
int count = 0;
- int i;
-
- vector_foreach_slot (pgp->paths, pp, i)
- if ((pp->state == state) || (state == PATH_WILD))
- count++;
-
+ unsigned int i, j, k;
+
+ if (!mpp->pg || !nr_states)
+ return count;
+
+ vector_foreach_slot (mpp->pg, pgp, i) {
+ vector_foreach_slot (pgp->paths, pp, j) {
+ for (k = 0; k < nr_states; k++) {
+ if (pp->state == states[k]) {
+ count++;
+ break;
+ }
+ }
+ }
+ }
return count;
}
int pathcount(const struct multipath *mpp, int state)
{
+ return do_pathcount(mpp, &state, 1);
+}
+
+int count_active_paths(const struct multipath *mpp)
+{
struct pathgroup *pgp;
+ struct path *pp;
int count = 0;
- int i;
+ int i, j;
- if (mpp->pg) {
- vector_foreach_slot (mpp->pg, pgp, i)
- count += pathcountgr(pgp, state);
+ if (!mpp->pg)
+ return 0;
+
+ vector_foreach_slot (mpp->pg, pgp, i) {
+ vector_foreach_slot (pgp->paths, pp, j) {
+ if (pp->state == PATH_UP || pp->state == PATH_GHOST)
+ count++;
+ }
}
return count;
}
+int count_active_pending_paths(const struct multipath *mpp)
+{
+ int states[] = {PATH_UP, PATH_GHOST, PATH_PENDING};
+
+ return do_pathcount(mpp, states, 3);
+}
+
int pathcmp(const struct pathgroup *pgp, const struct pathgroup *cpgp)
{
int i, j;
for (d = c; d >= 10; d /= 10)
l++;
- t = MALLOC(l + 1);
+ t = calloc(1, l + 1);
if (!t)
return 1;
snprintf(t, l + 1, "%0d%s %s", c, e, n);
- FREE(*f);
+ free(*f);
*f = t;
return 0;
/* Quick exit if all features have been removed */
if (c == 0) {
- n = MALLOC(2);
+ n = malloc(2);
if (!n)
return 1;
strcpy(n, "0");
/* Update feature count space */
l = strlen(*f) - d;
- n = MALLOC(l + 1);
+ n = malloc(l + 1);
if (!n)
return 1;
p = strchr(*f, ' ');
if (!p) {
/* Internal error, feature string inconsistent */
- FREE(n);
+ free(n);
return 1;
}
while (*p == ' ')
}
out:
- FREE(*f);
+ free(*f);
*f = n;
return 0;
}
+
+unsigned int bus_protocol_id(const struct path *pp) {
+ if (!pp || pp->bus < 0 || pp->bus > SYSFS_BUS_SCSI)
+ return SYSFS_BUS_UNDEF;
+ if (pp->bus != SYSFS_BUS_SCSI)
+ return pp->bus;
+ if ((int)pp->sg_id.proto_id < 0 || pp->sg_id.proto_id > SCSI_PROTOCOL_UNSPEC)
+ return SYSFS_BUS_UNDEF;
+ return SYSFS_BUS_SCSI + pp->sg_id.proto_id;
+}