Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / libafscp / afscp_volume.c
1 /* AUTORIGHTS
2 Copyright (C) 2003 - 2010 Chaskiel Grundman
3 All rights reserved
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8
9 1. Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 #include <afsconfig.h>
28 #include <afs/param.h>
29
30 #include <roken.h>
31
32 #include <search.h>
33
34 #include <afs/vlserver.h>
35 #include <afs/vldbint.h>
36 #include <afs/volint.h>
37 #include "afscp.h"
38 #include "afscp_internal.h"
39
40 static int
41 icompare(const void *pa, const void *pb)
42 {
43 const struct afscp_volume *va = pa, *vb = pb;
44
45 if (va->id > vb->id)
46 return 1;
47 if (va->id < vb->id)
48 return -1;
49 return 0;
50 }
51
52 static int
53 ncompare(const void *pa, const void *pb)
54 {
55 const struct afscp_volume *va = pa, *vb = pb;
56
57 if (va->voltype > vb->voltype)
58 return 1;
59 if (vb->voltype < va->voltype)
60 return -1;
61 return strcmp(va->name, vb->name);
62 }
63
64 union allvldbentry {
65 struct uvldbentry u;
66 struct nvldbentry n;
67 struct vldbentry o;
68 };
69
70 struct afscp_volume *
71 afscp_VolumeByName(struct afscp_cell *cell, const char *vname,
72 afs_int32 intype)
73 {
74 union allvldbentry u;
75 struct afscp_volume *ret, key;
76 struct afscp_server *server;
77 afs_int32 code, vtype, type, srv;
78 void *s;
79 #ifdef AFSCP_DEBUG
80 struct in_addr i;
81 #endif
82 if (intype == RWVOL)
83 vtype = VLSF_RWVOL;
84 else if (intype == ROVOL)
85 vtype = VLSF_ROVOL;
86 else if (intype == BACKVOL)
87 vtype = VLSF_BACKVOL;
88 else {
89 afscp_errno = EINVAL;
90 return NULL;
91 }
92
93 memset(&key, 0, sizeof(key));
94 strlcpy(key.name, vname, sizeof(key.name));
95 key.voltype = vtype;
96 s = tfind(&key, &cell->volsbyname, ncompare);
97 if (s) {
98 ret = *(struct afscp_volume **)s;
99 return ret;
100 }
101
102 type = 0;
103 code = ubik_VL_GetEntryByNameU(cell->vlservers, 0, (char *)vname, &u.u);
104 if (code == RXGEN_OPCODE) {
105 type = 1;
106 code =
107 ubik_VL_GetEntryByNameN(cell->vlservers, 0, (char *)vname, &u.n);
108 if (code == RXGEN_OPCODE) {
109 type = 2;
110 code = ubik_VL_GetEntryByNameO(cell->vlservers, 0, (char *)vname,
111 &u.o);
112 }
113 }
114 if (code != 0) {
115 afscp_errno = code;
116 return NULL;
117 }
118 ret = calloc(1, sizeof(struct afscp_volume));
119 if (ret == NULL) {
120 afscp_errno = ENOMEM;
121 return NULL;
122 }
123 strlcpy(ret->name, u.u.name, sizeof(ret->name));
124 ret->nservers = 0;
125 ret->cell = cell;
126 switch (type) {
127 case 0:
128 ret->id = u.u.volumeId[intype];
129 for (srv = 0; srv < u.u.nServers; srv++) {
130 if ((u.u.serverFlags[srv] & vtype) == 0)
131 continue;
132 afs_dprintf(("uvldbentry server %d flags: %x\n", srv,
133 u.u.serverFlags[srv]));
134
135 if ((u.u.serverFlags[srv] & VLSF_UUID) == 0)
136 server =
137 afscp_ServerByAddr(cell, u.u.serverNumber[srv].time_low);
138 else
139 server = afscp_ServerById(cell, &u.u.serverNumber[srv]);
140 if (!server)
141 continue;
142 ret->servers[ret->nservers++] = server->index;
143 }
144 break;
145 case 1:
146 ret->id = u.n.volumeId[intype];
147 for (srv = 0; srv < u.n.nServers; srv++) {
148 if ((u.n.serverFlags[srv] & vtype) == 0)
149 continue;
150 server = afscp_ServerByAddr(cell, u.n.serverNumber[srv]);
151 if (!server)
152 continue;
153 ret->servers[ret->nservers++] = server->index;
154 }
155 break;
156 case 2:
157 ret->id = u.o.volumeId[intype];
158 for (srv = 0; srv < u.o.nServers; srv++) {
159 if ((u.o.serverFlags[srv] & vtype) == 0)
160 continue;
161 server = afscp_ServerByAddr(cell, u.o.serverNumber[srv]);
162 if (!server)
163 continue;
164 ret->servers[ret->nservers++] = server->index;
165 }
166 break;
167 }
168 if (!ret->nservers || !ret->id) {
169 free(ret);
170 return NULL;
171 }
172
173 ret->voltype = intype;
174 #ifdef AFSCP_DEBUG
175 server = afscp_ServerByIndex(ret->servers[0]);
176 if (server != NULL)
177 i.s_addr = server->addrs[0];
178 else
179 i.s_addr = 0;
180 #endif
181 afs_dprintf(("New volume BYNAME %s (%lu) on %s (%d)\n", ret->name,
182 afs_printable_uint32_lu(ret->id),
183 inet_ntoa(i), ret->servers[0]));
184 s = tsearch(&key, &cell->volsbyname, ncompare);
185 if (s)
186 *(struct afscp_volume **)s = ret;
187 key.id = ret->id;
188 s = tsearch(&key, &cell->volsbyid, icompare);
189 if (s)
190 *(struct afscp_volume **)s = ret;
191 return ret;
192 }
193
194 struct afscp_volume *
195 afscp_VolumeById(struct afscp_cell *cell, afs_uint32 id)
196 {
197 union allvldbentry u;
198 struct afscp_volume *ret, key;
199 struct afscp_server *server;
200 afs_int32 code, vtype, type, srv;
201 int voltype = -1;
202 char idbuffer[16];
203 void *s;
204 #ifdef AFSCP_DEBUG
205 struct in_addr i;
206 #endif
207
208 memset(&key, 0, sizeof(key));
209 key.id = id;
210 s = tfind(&key, &cell->volsbyid, icompare);
211 if (s) {
212 ret = *(struct afscp_volume **)s;
213 return ret;
214 }
215
216 snprintf(idbuffer, sizeof(idbuffer), "%lu", afs_printable_uint32_lu(id));
217 type = 0;
218 code = ubik_VL_GetEntryByNameU(cell->vlservers, 0, idbuffer, &u.u);
219 if (code == RXGEN_OPCODE) {
220 type = 1;
221 code = ubik_VL_GetEntryByIDN(cell->vlservers, 0, id, -1, &u.n);
222 if (code == RXGEN_OPCODE) {
223 type = 2;
224 code = ubik_VL_GetEntryByID(cell->vlservers, 0, id, -1, &u.o);
225 }
226 }
227 if (code != 0) {
228 afscp_errno = code;
229 return NULL;
230 }
231 ret = calloc(1, sizeof(struct afscp_volume));
232 if (ret == NULL) {
233 afscp_errno = ENOMEM;
234 return NULL;
235 }
236 strlcpy(ret->name, u.u.name, sizeof(ret->name));
237 ret->nservers = 0;
238 ret->cell = cell;
239
240 switch (type) {
241 case 0:
242 if (id == u.u.volumeId[RWVOL]) {
243 vtype = VLSF_RWVOL;
244 voltype = RWVOL;
245 } else if (id == u.u.volumeId[ROVOL]) {
246 vtype = VLSF_ROVOL;
247 voltype = ROVOL;
248 } else if (id == u.u.volumeId[BACKVOL]) {
249 vtype = VLSF_BACKVOL;
250 voltype = BACKVOL;
251 } else {
252 vtype = 0;
253 voltype = -1;
254 }
255 for (srv = 0; srv < u.u.nServers; srv++) {
256 if ((u.u.serverFlags[srv] & vtype) == 0)
257 continue;
258 if ((u.u.serverFlags[srv] & VLSF_UUID) == 0)
259 server =
260 afscp_ServerByAddr(cell, u.u.serverNumber[srv].time_low);
261 else
262 server = afscp_ServerById(cell, &u.u.serverNumber[srv]);
263 if (!server)
264 continue;
265 ret->servers[ret->nservers++] = server->index;
266 }
267 break;
268 case 1:
269 if (id == u.n.volumeId[RWVOL]) {
270 vtype = VLSF_RWVOL;
271 voltype = RWVOL;
272 } else if (id == u.n.volumeId[ROVOL]) {
273 vtype = VLSF_ROVOL;
274 voltype = ROVOL;
275 } else if (id == u.n.volumeId[BACKVOL]) {
276 vtype = VLSF_BACKVOL;
277 voltype = BACKVOL;
278 } else {
279 vtype = 0;
280 voltype = -1;
281 }
282 for (srv = 0; srv < u.n.nServers; srv++) {
283 if ((u.n.serverFlags[srv] & vtype) == 0)
284 continue;
285 server = afscp_ServerByAddr(cell, u.n.serverNumber[srv]);
286 if (server == NULL)
287 continue;
288 ret->servers[ret->nservers++] = server->index;
289 }
290 break;
291 case 2:
292 if (id == u.o.volumeId[RWVOL]) {
293 vtype = VLSF_RWVOL;
294 voltype = RWVOL;
295 } else if (id == u.o.volumeId[ROVOL]) {
296 vtype = VLSF_ROVOL;
297 voltype = ROVOL;
298 } else if (id == u.o.volumeId[BACKVOL]) {
299 vtype = VLSF_BACKVOL;
300 voltype = BACKVOL;
301 } else {
302 vtype = 0;
303 voltype = -1;
304 }
305 for (srv = 0; srv < u.o.nServers; srv++) {
306 if ((u.o.serverFlags[srv] & vtype) == 0)
307 continue;
308 server = afscp_ServerByAddr(cell, u.o.serverNumber[srv]);
309 if (server == NULL)
310 continue;
311 ret->servers[ret->nservers++] = server->index;
312 }
313 break;
314 }
315 ret->voltype = voltype;
316 #ifdef AFSCP_DEBUG
317 server = afscp_ServerByIndex(ret->servers[0]);
318 if (server)
319 i.s_addr = server->addrs[0];
320 else
321 i.s_addr = 0;
322 #endif
323 afs_dprintf(("New volume BYID %s (%lu) on %s (%d)\n", ret->name,
324 afs_printable_uint32_lu(ret->id), inet_ntoa(i),
325 ret->servers[0]));
326 s = tsearch(&key, &cell->volsbyid, icompare);
327 if (s)
328 *(struct afscp_volume **)s = ret;
329 strlcpy(key.name, ret->name, sizeof(key.name));
330 s = tsearch(&key, &cell->volsbyname, ncompare);
331 if (s)
332 *(struct afscp_volume **)s = ret;
333 return ret;
334 }