Imported Upstream version 0.7.4
[platform/upstream/multipath-tools.git] / libdmmp / libdmmp_mp.c
1 /*
2  * Copyright (C) 2015 - 2016 Red Hat, Inc.
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  *
17  * Author: Gris Ge <fge@redhat.com>
18  *         Todd Gill <tgill@redhat.com>
19  */
20
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <inttypes.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <assert.h>
27 #include <json.h>
28
29 #include "libdmmp/libdmmp.h"
30 #include "libdmmp_private.h"
31
32 struct dmmp_mpath {
33         char *wwid;
34         char *alias;
35         uint32_t dmmp_pg_count;
36         struct dmmp_path_group **dmmp_pgs;
37         char *kdev_name;
38 };
39
40 _dmmp_getter_func_gen(dmmp_mpath_name_get, struct dmmp_mpath, dmmp_mp,
41                       alias, const char *);
42 _dmmp_getter_func_gen(dmmp_mpath_wwid_get, struct dmmp_mpath, dmmp_mp,
43                       wwid, const char *);
44 _dmmp_getter_func_gen(dmmp_mpath_kdev_name_get, struct dmmp_mpath, dmmp_mp,
45                       kdev_name, const char *);
46
47 struct dmmp_mpath *_dmmp_mpath_new(void)
48 {
49         struct dmmp_mpath *dmmp_mp = NULL;
50
51         dmmp_mp = (struct dmmp_mpath *) malloc(sizeof(struct dmmp_mpath));
52
53         if (dmmp_mp != NULL) {
54                 dmmp_mp->wwid = NULL;
55                 dmmp_mp->alias = NULL;
56                 dmmp_mp->dmmp_pg_count = 0;
57                 dmmp_mp->dmmp_pgs = NULL;
58         }
59         return dmmp_mp;
60 }
61
62 int _dmmp_mpath_update(struct dmmp_context *ctx, struct dmmp_mpath *dmmp_mp,
63                        json_object *j_obj_map)
64 {
65         int rc = DMMP_OK;
66         const char *wwid = NULL;
67         const char *alias = NULL;
68         struct array_list *ar_pgs = NULL;
69         int ar_pgs_len = -1;
70         uint32_t i = 0;
71         struct dmmp_path_group *dmmp_pg = NULL;
72         const char *kdev_name = NULL;
73
74         assert(ctx != NULL);
75         assert(dmmp_mp != NULL);
76         assert(j_obj_map != NULL);
77
78         _json_obj_get_value(ctx, j_obj_map, wwid, "uuid", json_type_string,
79                             json_object_get_string, rc, out);
80         _json_obj_get_value(ctx, j_obj_map, alias, "name", json_type_string,
81                             json_object_get_string, rc, out);
82         _json_obj_get_value(ctx, j_obj_map, kdev_name, "sysfs",
83                             json_type_string, json_object_get_string, rc, out);
84
85         _dmmp_null_or_empty_str_check(ctx, wwid, rc, out);
86         _dmmp_null_or_empty_str_check(ctx, alias, rc, out);
87
88         dmmp_mp->wwid = strdup(wwid);
89         _dmmp_alloc_null_check(ctx, dmmp_mp->wwid, rc, out);
90         dmmp_mp->alias = strdup(alias);
91         _dmmp_alloc_null_check(ctx, dmmp_mp->alias, rc, out);
92         dmmp_mp->kdev_name = strdup(kdev_name);
93         _dmmp_alloc_null_check(ctx, dmmp_mp->kdev_name, rc, out);
94
95         _json_obj_get_value(ctx, j_obj_map, ar_pgs, "path_groups",
96                             json_type_array, json_object_get_array, rc, out);
97         ar_pgs_len = array_list_length(ar_pgs);
98         if (ar_pgs_len < 0) {
99                 rc = DMMP_ERR_BUG;
100                 _error(ctx, "BUG: Got negative length for ar_pgs");
101                 goto out;
102         }
103         else if (ar_pgs_len == 0)
104                 goto out;
105         else
106                 dmmp_mp->dmmp_pg_count = ar_pgs_len & UINT32_MAX;
107
108         dmmp_mp->dmmp_pgs = (struct dmmp_path_group **)
109                 malloc(sizeof(struct dmmp_path_group *) *
110                        dmmp_mp->dmmp_pg_count);
111         _dmmp_alloc_null_check(ctx, dmmp_mp->dmmp_pgs, rc, out);
112         for (; i < dmmp_mp->dmmp_pg_count; ++i)
113                 dmmp_mp->dmmp_pgs[i] = NULL;
114
115         for (i = 0; i < dmmp_mp->dmmp_pg_count; ++i) {
116                 dmmp_pg = _dmmp_path_group_new();
117                 _dmmp_alloc_null_check(ctx, dmmp_pg, rc, out);
118                 dmmp_mp->dmmp_pgs[i] = dmmp_pg;
119                 _good(_dmmp_path_group_update(ctx, dmmp_pg,
120                                               array_list_get_idx(ar_pgs, i)),
121                       rc, out);
122         }
123
124         _debug(ctx, "Got mpath wwid: '%s', alias: '%s'", dmmp_mp->wwid,
125                dmmp_mp->alias);
126
127 out:
128         if (rc != DMMP_OK)
129                 _dmmp_mpath_free(dmmp_mp);
130         return rc;
131 }
132
133 void _dmmp_mpath_free(struct dmmp_mpath *dmmp_mp)
134 {
135         if (dmmp_mp == NULL)
136                 return ;
137
138         free((char *) dmmp_mp->alias);
139         free((char *) dmmp_mp->wwid);
140         free((char *) dmmp_mp->kdev_name);
141
142         if (dmmp_mp->dmmp_pgs != NULL)
143                 _dmmp_path_group_array_free(dmmp_mp->dmmp_pgs,
144                                             dmmp_mp->dmmp_pg_count);
145
146         free(dmmp_mp);
147 }
148
149 void dmmp_path_group_array_get(struct dmmp_mpath *dmmp_mp,
150                                struct dmmp_path_group ***dmmp_pgs,
151                                uint32_t *dmmp_pg_count)
152 {
153         assert(dmmp_mp != NULL);
154         assert(dmmp_pgs != NULL);
155         assert(dmmp_pg_count != NULL);
156
157         *dmmp_pgs = dmmp_mp->dmmp_pgs;
158         *dmmp_pg_count = dmmp_mp->dmmp_pg_count;
159 }