933705ee06e9970551efe4705a745dcdeb9eaf8d
[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 <afs/param.h>
28 #include <afs/vlserver.h>
29 #include <afs/vldbint.h>
30 #include <afs/volint.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <errno.h>
34 #include <netinet/in.h>
35 #include <arpa/inet.h>
36 #include <inttypes.h>
37 #include "afscp.h"
38 #include "afscp_internal.h"
39
40 #include <search.h>
41 #include <time.h>
42
43 static int icompare(const void *pa, const void *pb) {
44   const struct afs_volume *va=pa,*vb=pb;
45
46   if (va->id > vb->id) return 1;
47   if (va->id < vb->id) return -1;
48   return 0;
49 }
50
51
52 static int ncompare(const void *pa, const void *pb) {
53   const struct afs_volume *va=pa,*vb=pb;
54
55   if (va->voltype > vb->voltype) return 1;
56   if (vb->voltype < va->voltype) return -1;
57   return strcmp(va->name, vb->name);
58 }
59
60
61 union allvldbentry
62 {
63      struct uvldbentry u;
64      struct nvldbentry n;
65      struct vldbentry o;
66 };
67
68 struct afs_volume *afs_volumebyname(struct afs_cell *cell, const char *vname, afs_int32 intype)
69 {
70      union allvldbentry u;
71      struct afs_volume *ret,key;
72      struct afs_server *server;
73      afs_int32 code,vtype,type,srv;
74      void *s;
75      struct in_addr i;
76
77      if (intype == VOLTYPE_RW)
78           vtype=VLSF_RWVOL;
79      else if (intype == VOLTYPE_RO)
80           vtype=VLSF_ROVOL;
81      else if (intype == VOLTYPE_BK)
82           vtype=VLSF_BACKVOL;
83      else {
84           afs_errno=EINVAL;
85           return NULL;
86      }
87
88      memset(&key,0, sizeof(key));
89      strcpy(key.name,vname);
90      key.voltype=vtype;
91      s=tfind(&key, &cell->volsbyname, ncompare);
92      if (s) {
93        ret=*(struct afs_volume **)s;
94        return ret;
95      }
96
97      type=0;
98      if ((code=ubik_VL_GetEntryByNameU(cell->vlservers, 0, (char *)vname, &u.u))
99          == RXGEN_OPCODE) {
100           type=1;
101           if ((code=ubik_VL_GetEntryByNameN(cell->vlservers, 0, (char *)vname, &u.n))
102               == RXGEN_OPCODE) {
103                type=2;
104                code=ubik_VL_GetEntryByNameO(cell->vlservers, 0, (char *)vname, &u.o);
105           }
106      }
107      if (code) {
108           afs_errno=code;
109           return NULL;
110      }
111      ret=malloc(sizeof(struct afs_volume));
112      if (!ret) {
113           afs_errno=ENOMEM;
114           return NULL;
115      }
116      memset(ret,0,sizeof(struct afs_volume));
117      strcpy(ret->name, u.u.name);
118      ret->nservers=0;
119      ret->cell=cell;
120      switch (type) {
121      case 0:
122        ret->id=u.u.volumeId[intype];
123           for (srv=0;srv < u.u.nServers;srv++) {
124                if ((u.u.serverFlags[srv] & vtype) == 0)
125                     continue;
126                //printf("uvldbentry server %d flags: %x\n",srv,  u.u.serverFlags[srv]);
127
128                if ((u.u.serverFlags[srv] & VLSERVER_FLAG_UUID) == 0)
129                     server=afs_serverbyaddr(cell, u.u.serverNumber[srv].time_low);
130                else
131                     server=afs_serverbyid(cell, &u.u.serverNumber[srv]);
132                if (!server)
133                     continue;
134                ret->servers[ret->nservers++]=server->index;
135           }
136           break;
137      case 1:
138        ret->id=u.n.volumeId[intype];
139           for (srv=0;srv < u.n.nServers;srv++) {
140                if ((u.n.serverFlags[srv] & vtype) == 0)
141                     continue;
142                server=afs_serverbyaddr(cell, u.n.serverNumber[srv]);
143                if (!server)
144                     continue;
145                ret->servers[ret->nservers++]=server->index;
146           }
147           break;
148      case 2:
149        ret->id=u.o.volumeId[intype];
150           for (srv=0;srv < u.o.nServers;srv++) {
151                if ((u.o.serverFlags[srv] & vtype) == 0)
152                     continue;
153                server=afs_serverbyaddr(cell, u.o.serverNumber[srv]);
154                if (!server)
155                     continue;
156                ret->servers[ret->nservers++]=server->index;
157           }
158           break;
159      }
160      if (!ret->nservers || !ret->id) {
161           free(ret);
162           return NULL;
163      }
164
165      ret->voltype=intype;
166      server=afs_serverbyindex(ret->servers[0]);
167      if (server)
168        i.s_addr=server->addrs[0];
169      else
170        i.s_addr=0;
171      afscp_dprintf(("New volume BYNAME %s (%lu) on %s (%d)\n", ret->name, ret->id, inet_ntoa(i),ret->servers[0]));
172      s=tsearch(&key, &cell->volsbyname, ncompare);
173      if (s)
174        *(struct afs_volume **)s=ret;
175      key.id=ret->id;
176      s=tsearch(&key, &cell->volsbyid, icompare);
177      if (s)
178        *(struct afs_volume **)s=ret;
179      return ret;
180 }
181
182 struct afs_volume *afs_volumebyid(struct afs_cell *cell, afs_uint32 id)
183 {
184      union allvldbentry u;
185      struct afs_volume *ret,key;
186      struct afs_server *server;
187      afs_int32 code,vtype,type,srv;
188      int voltype;
189      char idbuffer[16];
190      void *s;
191      struct in_addr i;
192
193      memset(&key,0, sizeof(key));
194      key.id=id;
195      s=tfind(&key, &cell->volsbyid, icompare);
196      if (s) {
197        ret=*(struct afs_volume **)s;
198        return ret;
199      }
200
201      sprintf(idbuffer,"%" PRIu32, id);
202      type=0;
203      if ((code=ubik_VL_GetEntryByNameU(cell->vlservers, 0, idbuffer, &u.u))
204          == RXGEN_OPCODE) {
205           type=1;
206           if ((code=ubik_VL_GetEntryByIDN(cell->vlservers, 0, id, -1, &u.n))
207               == RXGEN_OPCODE) {
208                type=2;
209                code=ubik_VL_GetEntryByID(cell->vlservers, 0, id, -1,  &u.o);
210           }
211      }
212      if (code) {
213           afs_errno=code;
214           return NULL;
215      }
216      ret=malloc(sizeof(struct afs_volume));
217      if (!ret) {
218           afs_errno=ENOMEM;
219           return NULL;
220      }
221
222      memset(ret,0,sizeof(struct afs_volume));
223      strcpy(ret->name, u.u.name);
224      ret->nservers=0;
225      ret->cell=cell;
226
227      switch (type) {
228      case 0:
229           if (id == u.u.volumeId[RWVOL]) {
230                vtype=VLSF_RWVOL;
231                voltype=VOLTYPE_RW;
232           } else if (id == u.u.volumeId[ROVOL]) {
233                vtype=VLSF_ROVOL;
234                voltype=VOLTYPE_RO;
235           } else if (id == u.u.volumeId[BACKVOL]) {
236                vtype=VLSF_BACKVOL;
237                voltype=VOLTYPE_BK;
238           } else {
239                vtype=0;
240                voltype=-1;
241           }
242           for (srv=0;srv < u.u.nServers;srv++) {
243                if ((u.u.serverFlags[srv] & vtype) == 0)
244                     continue;
245                if ((u.u.serverFlags[srv] & VLSERVER_FLAG_UUID) == 0)
246                     server=afs_serverbyaddr(cell, u.u.serverNumber[srv].time_low);
247                else
248                     server=afs_serverbyid(cell, &u.u.serverNumber[srv]);
249                if (!server)
250                     continue;
251                ret->servers[ret->nservers++]=server->index;
252           }
253           break;
254      case 1:
255           if (id == u.n.volumeId[RWVOL]) {
256                vtype=VLSF_RWVOL;
257                voltype=VOLTYPE_RW;
258           } else if (id == u.n.volumeId[ROVOL]) {
259                vtype=VLSF_ROVOL;
260                voltype=VOLTYPE_RO;
261           } else if (id == u.n.volumeId[BACKVOL]) {
262                vtype=VLSF_BACKVOL;
263                voltype=VOLTYPE_BK;
264           } else {
265                vtype=0;
266                voltype=-1;
267           }
268           for (srv=0;srv < u.n.nServers;srv++) {
269                if ((u.n.serverFlags[srv] & vtype) == 0)
270                     continue;
271                server=afs_serverbyaddr(cell, u.n.serverNumber[srv]);
272                if (!server)
273                     continue;
274                ret->servers[ret->nservers++]=server->index;
275           }
276           break;
277      case 2:
278           if (id == u.o.volumeId[RWVOL]) {
279                vtype=VLSF_RWVOL;
280                voltype=VOLTYPE_RW;
281           } else if (id == u.o.volumeId[ROVOL]) {
282                vtype=VLSF_ROVOL;
283                voltype=VOLTYPE_RO;
284           } else if (id == u.o.volumeId[BACKVOL]) {
285                vtype=VLSF_BACKVOL;
286                voltype=VOLTYPE_BK;
287           } else {
288                vtype=0;
289                voltype=-1;
290           }
291           for (srv=0;srv < u.o.nServers;srv++) {
292                if ((u.o.serverFlags[srv] & vtype) == 0)
293                     continue;
294                server=afs_serverbyaddr(cell, u.o.serverNumber[srv]);
295                if (!server)
296                     continue;
297                ret->servers[ret->nservers++]=server->index;
298           }
299           break;
300      }
301      ret->voltype=voltype;
302      server=afs_serverbyindex(ret->servers[0]);
303      if (server)
304        i.s_addr=server->addrs[0];
305      else
306        i.s_addr=0;
307      afscp_dprintf(("New volume BYID %s (%lu) on %s (%d)\n", ret->name, ret->id, inet_ntoa(i), ret->servers[0]));
308      s=tsearch(&key, &cell->volsbyid, icompare);
309      if (s)
310        *(struct afs_volume **)s=ret;
311      strcpy(key.name, ret->name);
312      s=tsearch(&key, &cell->volsbyname, ncompare);
313      if (s)
314        *(struct afs_volume **)s=ret;
315      return ret;
316 }
317