libmultipath/checkers: cleanup class/instance model
[multipath-tools/.git] / libmultipath / print.c
index b1844c9..fc40b0f 100644 (file)
@@ -275,8 +275,6 @@ snprint_multipath_vpr (char * buff, size_t len, const struct multipath * mpp)
        int i, j;
 
        vector_foreach_slot(mpp->pg, pgp, i) {
-               if (!pgp)
-                       continue;
                vector_foreach_slot(pgp->paths, pp, j) {
                        if (strlen(pp->vendor_id) && strlen(pp->product_id))
                                return snprintf(buff, len, "%s,%s",
@@ -295,8 +293,6 @@ snprint_multipath_vend (char * buff, size_t len, const struct multipath * mpp)
        int i, j;
 
        vector_foreach_slot(mpp->pg, pgp, i) {
-               if (!pgp)
-                       continue;
                vector_foreach_slot(pgp->paths, pp, j) {
                        if (strlen(pp->vendor_id))
                                return snprintf(buff, len, "%s", pp->vendor_id);
@@ -313,8 +309,6 @@ snprint_multipath_prod (char * buff, size_t len, const struct multipath * mpp)
        int i, j;
 
        vector_foreach_slot(mpp->pg, pgp, i) {
-               if (!pgp)
-                       continue;
                vector_foreach_slot(pgp->paths, pp, j) {
                        if (strlen(pp->product_id))
                                return snprintf(buff, len, "%s", pp->product_id);
@@ -331,8 +325,6 @@ snprint_multipath_rev (char * buff, size_t len, const struct multipath * mpp)
        int i, j;
 
        vector_foreach_slot(mpp->pg, pgp, i) {
-               if (!pgp)
-                       continue;
                vector_foreach_slot(pgp->paths, pp, j) {
                        if (strlen(pp->rev))
                                return snprintf(buff, len, "%s", pp->rev);
@@ -623,7 +615,7 @@ static int
 snprint_path_checker (char * buff, size_t len, const struct path * pp)
 {
        const struct checker * c = &pp->checker;
-       return snprint_str(buff, len, c->name);
+       return snprint_str(buff, len, checker_name(c));
 }
 
 static int
@@ -638,6 +630,48 @@ snprint_path_failures(char * buff, size_t len, const struct path * pp)
        return snprint_int(buff, len, pp->failcount);
 }
 
+/* if you add a protocol string bigger than "scsi:unspec" you must
+ * also change PROTOCOL_BUF_SIZE */
+int
+snprint_path_protocol(char * buff, size_t len, const struct path * pp)
+{
+       switch (pp->bus) {
+       case SYSFS_BUS_SCSI:
+               switch (pp->sg_id.proto_id) {
+               case SCSI_PROTOCOL_FCP:
+                       return snprintf(buff, len, "scsi:fcp");
+               case SCSI_PROTOCOL_SPI:
+                       return snprintf(buff, len, "scsi:spi");
+               case SCSI_PROTOCOL_SSA:
+                       return snprintf(buff, len, "scsi:ssa");
+               case SCSI_PROTOCOL_SBP:
+                       return snprintf(buff, len, "scsi:sbp");
+               case SCSI_PROTOCOL_SRP:
+                       return snprintf(buff, len, "scsi:srp");
+               case SCSI_PROTOCOL_ISCSI:
+                       return snprintf(buff, len, "scsi:iscsi");
+               case SCSI_PROTOCOL_SAS:
+                       return snprintf(buff, len, "scsi:sas");
+               case SCSI_PROTOCOL_ADT:
+                       return snprintf(buff, len, "scsi:adt");
+               case SCSI_PROTOCOL_ATA:
+                       return snprintf(buff, len, "scsi:ata");
+               case SCSI_PROTOCOL_UNSPEC:
+               default:
+                       return snprintf(buff, len, "scsi:unspec");
+               }
+       case SYSFS_BUS_CCW:
+               return snprintf(buff, len, "ccw");
+       case SYSFS_BUS_CCISS:
+               return snprintf(buff, len, "cciss");
+       case SYSFS_BUS_NVME:
+               return snprintf(buff, len, "nvme");
+       case SYSFS_BUS_UNDEF:
+       default:
+               return snprintf(buff, len, "undef");
+       }
+}
+
 struct multipath_data mpd[] = {
        {'n', "name",          0, snprint_name},
        {'w', "uuid",          0, snprint_multipath_uuid},
@@ -687,6 +721,7 @@ struct path_data pd[] = {
        {'a', "host adapter",  0, snprint_host_adapter},
        {'G', "foreign",       0, snprint_path_foreign},
        {'0', "failures",      0, snprint_path_failures},
+       {'P', "protocol",      0, snprint_path_protocol},
        {0, NULL, 0 , NULL}
 };
 
@@ -1342,7 +1377,8 @@ snprint_multipath_topology_json (char * buff, int len, const struct vectors * ve
 }
 
 static int
-snprint_hwentry (struct config *conf, char * buff, int len, const struct hwentry * hwe)
+snprint_hwentry (const struct config *conf,
+                char * buff, int len, const struct hwentry * hwe)
 {
        int i;
        int fwd = 0;
@@ -1374,7 +1410,9 @@ snprint_hwentry (struct config *conf, char * buff, int len, const struct hwentry
        return fwd;
 }
 
-int snprint_hwtable(struct config *conf, char *buff, int len, vector hwtable)
+static int snprint_hwtable(const struct config *conf,
+                          char *buff, int len,
+                          const struct _vector *hwtable)
 {
        int fwd = 0;
        int i;
@@ -1400,12 +1438,17 @@ int snprint_hwtable(struct config *conf, char *buff, int len, vector hwtable)
 }
 
 static int
-snprint_mpentry (struct config *conf, char * buff, int len, const struct mpentry * mpe)
+snprint_mpentry (const struct config *conf, char * buff, int len,
+                const struct mpentry * mpe, const struct _vector *mpvec)
 {
        int i;
        int fwd = 0;
        struct keyword * kw;
        struct keyword * rootkw;
+       struct multipath *mpp = NULL;
+
+       if (mpvec != NULL && (mpp = find_mp_by_wwid(mpvec, mpe->wwid)) == NULL)
+               return 0;
 
        rootkw = find_keyword(conf->keywords, NULL, "multipath");
        if (!rootkw)
@@ -1420,13 +1463,23 @@ snprint_mpentry (struct config *conf, char * buff, int len, const struct mpentry
                if (fwd >= len)
                        return len;
        }
+       /*
+        * This mpp doesn't have alias defined. Add the alias in a comment.
+        */
+       if (mpp != NULL && strcmp(mpp->alias, mpp->wwid)) {
+               fwd += snprintf(buff + fwd, len - fwd, "\t\t# alias \"%s\"\n",
+                               mpp->alias);
+               if (fwd >= len)
+                       return len;
+       }
        fwd += snprintf(buff + fwd, len - fwd, "\t}\n");
        if (fwd >= len)
                return len;
        return fwd;
 }
 
-int snprint_mptable(struct config *conf, char *buff, int len, vector mptable)
+static int snprint_mptable(const struct config *conf,
+                          char *buff, int len, const struct _vector *mpvec)
 {
        int fwd = 0;
        int i;
@@ -1440,19 +1493,51 @@ int snprint_mptable(struct config *conf, char *buff, int len, vector mptable)
        fwd += snprintf(buff + fwd, len - fwd, "multipaths {\n");
        if (fwd >= len)
                return len;
-       vector_foreach_slot (mptable, mpe, i) {
-               fwd += snprint_mpentry(conf, buff + fwd, len - fwd, mpe);
+       vector_foreach_slot (conf->mptable, mpe, i) {
+               fwd += snprint_mpentry(conf, buff + fwd, len - fwd, mpe, mpvec);
                if (fwd >= len)
                        return len;
        }
+       if (mpvec != NULL) {
+               struct multipath *mpp;
+
+               vector_foreach_slot(mpvec, mpp, i) {
+                       if (find_mpe(conf->mptable, mpp->wwid) != NULL)
+                               continue;
+
+                       fwd += snprintf(buff + fwd, len - fwd,
+                                       "\tmultipath {\n");
+                       if (fwd >= len)
+                               return len;
+                       fwd += snprintf(buff + fwd, len - fwd,
+                                       "\t\twwid \"%s\"\n", mpp->wwid);
+                       if (fwd >= len)
+                               return len;
+                       /*
+                        * This mpp doesn't have alias defined in
+                        * multipath.conf - otherwise find_mpe would have
+                        * found it. Add the alias in a comment.
+                        */
+                       if (strcmp(mpp->alias, mpp->wwid)) {
+                               fwd += snprintf(buff + fwd, len - fwd,
+                                               "\t\t# alias \"%s\"\n",
+                                               mpp->alias);
+                               if (fwd >= len)
+                                       return len;
+                       }
+                       fwd += snprintf(buff + fwd, len - fwd, "\t}\n");
+                       if (fwd >= len)
+                               return len;
+               }
+       }
        fwd += snprintf(buff + fwd, len - fwd, "}\n");
        if (fwd >= len)
                return len;
        return fwd;
 }
 
-int snprint_overrides(struct config *conf, char * buff, int len,
-                     const struct hwentry *overrides)
+static int snprint_overrides(const struct config *conf, char * buff, int len,
+                            const struct hwentry *overrides)
 {
        int fwd = 0;
        int i;
@@ -1481,7 +1566,7 @@ out:
        return fwd;
 }
 
-int snprint_defaults(struct config *conf, char *buff, int len)
+static int snprint_defaults(const struct config *conf, char *buff, int len)
 {
        int fwd = 0;
        int i;
@@ -1593,6 +1678,19 @@ int snprint_blacklist_report(struct config *conf, char *buff, int len)
        if (snprint_blacklist_group(buff, len, &fwd, &conf->elist_property) == 0)
                return len;
 
+       if ((len - fwd - threshold) <= 0)
+               return len;
+       fwd += snprintf(buff + fwd, len - fwd, "protocol rules:\n"
+                                              "- blacklist:\n");
+       if (!snprint_blacklist_group(buff, len, &fwd, &conf->blist_protocol))
+               return len;
+
+       if ((len - fwd - threshold) <= 0)
+               return len;
+       fwd += snprintf(buff + fwd, len - fwd, "- exceptions:\n");
+       if (snprint_blacklist_group(buff, len, &fwd, &conf->elist_protocol) == 0)
+               return len;
+
        if ((len - fwd - threshold) <= 0)
                return len;
        fwd += snprintf(buff + fwd, len - fwd, "wwid rules:\n"
@@ -1624,7 +1722,7 @@ int snprint_blacklist_report(struct config *conf, char *buff, int len)
        return fwd;
 }
 
-int snprint_blacklist(struct config *conf, char *buff, int len)
+static int snprint_blacklist(const struct config *conf, char *buff, int len)
 {
        int i;
        struct blentry * ble;
@@ -1668,6 +1766,15 @@ int snprint_blacklist(struct config *conf, char *buff, int len)
                if (fwd >= len)
                        return len;
        }
+       vector_foreach_slot (conf->blist_protocol, ble, i) {
+               kw = find_keyword(conf->keywords, rootkw->sub, "protocol");
+               if (!kw)
+                       return 0;
+               fwd += snprint_keyword(buff + fwd, len - fwd, "\t%k %v\n",
+                                      kw, ble);
+               if (fwd >= len)
+                       return len;
+       }
        rootkw = find_keyword(conf->keywords, rootkw->sub, "device");
        if (!rootkw)
                return 0;
@@ -1700,7 +1807,8 @@ int snprint_blacklist(struct config *conf, char *buff, int len)
        return fwd;
 }
 
-int snprint_blacklist_except(struct config *conf, char *buff, int len)
+static int snprint_blacklist_except(const struct config *conf,
+                                   char *buff, int len)
 {
        int i;
        struct blentry * ele;
@@ -1744,6 +1852,15 @@ int snprint_blacklist_except(struct config *conf, char *buff, int len)
                if (fwd >= len)
                        return len;
        }
+       vector_foreach_slot (conf->elist_protocol, ele, i) {
+               kw = find_keyword(conf->keywords, rootkw->sub, "protocol");
+               if (!kw)
+                       return 0;
+               fwd += snprint_keyword(buff + fwd, len - fwd, "\t%k %v\n",
+                                      kw, ele);
+               if (fwd >= len)
+                       return len;
+       }
        rootkw = find_keyword(conf->keywords, rootkw->sub, "device");
        if (!rootkw)
                return 0;
@@ -1776,6 +1893,61 @@ int snprint_blacklist_except(struct config *conf, char *buff, int len)
        return fwd;
 }
 
+char *snprint_config(const struct config *conf, int *len,
+                    const struct _vector *hwtable, const struct _vector *mpvec)
+{
+       char *reply;
+       /* built-in config is >20kB already */
+       unsigned int maxlen = 32768;
+
+       for (reply = NULL; maxlen <= UINT_MAX/2; maxlen *= 2) {
+               char *c, *tmp = reply;
+
+               reply = REALLOC(reply, maxlen);
+               if (!reply) {
+                       if (tmp)
+                               free(tmp);
+                       return NULL;
+               }
+
+               c = reply + snprint_defaults(conf, reply, maxlen);
+               if ((c - reply) == maxlen)
+                       continue;
+
+               c += snprint_blacklist(conf, c, reply + maxlen - c);
+               if ((c - reply) == maxlen)
+                       continue;
+
+               c += snprint_blacklist_except(conf, c, reply + maxlen - c);
+               if ((c - reply) == maxlen)
+                       continue;
+
+               c += snprint_hwtable(conf, c, reply + maxlen - c,
+                                    hwtable ? hwtable : conf->hwtable);
+               if ((c - reply) == maxlen)
+                       continue;
+
+               c += snprint_overrides(conf, c, reply + maxlen - c,
+                                      conf->overrides);
+               if ((c - reply) == maxlen)
+                       continue;
+
+               if (VECTOR_SIZE(conf->mptable) > 0 ||
+                   (mpvec != NULL && VECTOR_SIZE(mpvec) > 0))
+                       c += snprint_mptable(conf, c, reply + maxlen - c,
+                                            mpvec);
+
+               if ((c - reply) < maxlen) {
+                       if (len)
+                               *len = c - reply;
+                       return reply;
+               }
+       }
+
+       free(reply);
+       return NULL;
+}
+
 int snprint_status(char *buff, int len, const struct vectors *vecs)
 {
        int fwd = 0;