Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / volser / vsutils.c
1 /*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
4 *
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
8 */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12 #include <afs/stds.h>
13
14 #include <roken.h>
15
16 #include <ctype.h>
17 #ifdef AFS_AIX_ENV
18 #include <sys/statfs.h>
19 #endif
20
21 #include <lock.h>
22 #include <rx/xdr.h>
23 #include <rx/rx.h>
24 #include <rx/rx_globals.h>
25 #include <afs/nfs.h>
26 #include <afs/vlserver.h>
27 #include <afs/cellconfig.h>
28 #include <afs/keys.h>
29 #include <ubik.h>
30 #include <afs/afsint.h>
31 #include <afs/cmd.h>
32 #include <rx/rxkad.h>
33
34 #include "volser.h"
35 #include "volint.h"
36 #include "lockdata.h"
37
38 #include "vsutils_prototypes.h"
39
40 struct ubik_client *cstruct;
41
42 static void
43 ovlentry_to_nvlentry(struct vldbentry *oentryp,
44 struct nvldbentry *nentryp)
45 {
46 int i;
47
48 memset(nentryp, 0, sizeof(struct nvldbentry));
49 strncpy(nentryp->name, oentryp->name, sizeof(nentryp->name));
50 for (i = 0; i < oentryp->nServers; i++) {
51 nentryp->serverNumber[i] = oentryp->serverNumber[i];
52 nentryp->serverPartition[i] = oentryp->serverPartition[i];
53 nentryp->serverFlags[i] = oentryp->serverFlags[i];
54 }
55 nentryp->nServers = oentryp->nServers;
56 for (i = 0; i < MAXTYPES; i++)
57 nentryp->volumeId[i] = oentryp->volumeId[i];
58 nentryp->cloneId = oentryp->cloneId;
59 nentryp->flags = oentryp->flags;
60 }
61
62 static int
63 nvlentry_to_ovlentry(struct nvldbentry *nentryp,
64 struct vldbentry *oentryp)
65 {
66 int i;
67
68 memset(oentryp, 0, sizeof(struct vldbentry));
69 strncpy(oentryp->name, nentryp->name, sizeof(oentryp->name));
70 if (nentryp->nServers > OMAXNSERVERS) {
71 /*
72 * The alternative is to store OMAXSERVERS but it's always better
73 * to know what's going on...
74 */
75 return VL_BADSERVER;
76 }
77 for (i = 0; i < nentryp->nServers; i++) {
78 oentryp->serverNumber[i] = nentryp->serverNumber[i];
79 oentryp->serverPartition[i] = nentryp->serverPartition[i];
80 oentryp->serverFlags[i] = nentryp->serverFlags[i];
81 }
82 oentryp->nServers = i;
83 for (i = 0; i < MAXTYPES; i++)
84 oentryp->volumeId[i] = nentryp->volumeId[i];
85 oentryp->cloneId = nentryp->cloneId;
86 oentryp->flags = nentryp->flags;
87 return 0;
88 }
89
90 enum _vlserver_type {
91 vltype_unknown = 0,
92 vltype_old = 1,
93 vltype_new = 2,
94 vltype_uuid = 3
95 };
96
97 static enum _vlserver_type newvlserver = vltype_unknown;
98
99 int
100 VLDB_CreateEntry(struct nvldbentry *entryp)
101 {
102 struct vldbentry oentry;
103 int code;
104
105 if (newvlserver == vltype_old) {
106 tryold:
107 code = nvlentry_to_ovlentry(entryp, &oentry);
108 if (code)
109 return code;
110 code = ubik_VL_CreateEntry(cstruct, 0, &oentry);
111 return code;
112 }
113 code = ubik_VL_CreateEntryN(cstruct, 0, entryp);
114 if (newvlserver == vltype_unknown) {
115 if (code == RXGEN_OPCODE) {
116 newvlserver = vltype_old; /* Doesn't support new interface */
117 goto tryold;
118 } else if (!code) {
119 newvlserver = vltype_new;
120 }
121 }
122 return code;
123 }
124
125 int
126 VLDB_GetEntryByID(afs_uint32 volid, afs_int32 voltype, struct nvldbentry *entryp)
127 {
128 struct vldbentry oentry;
129 int code;
130
131 if (newvlserver == vltype_old) {
132 tryold:
133 code =
134 ubik_VL_GetEntryByID(cstruct, 0, volid, voltype, &oentry);
135 if (!code)
136 ovlentry_to_nvlentry(&oentry, entryp);
137 return code;
138 }
139 code = ubik_VL_GetEntryByIDN(cstruct, 0, volid, voltype, entryp);
140 if (newvlserver == vltype_unknown) {
141 if (code == RXGEN_OPCODE) {
142 newvlserver = vltype_old; /* Doesn't support new interface */
143 goto tryold;
144 } else if (!code) {
145 newvlserver = vltype_new;
146 }
147 }
148 return code;
149 }
150
151 int
152 VLDB_GetEntryByName(char *namep, struct nvldbentry *entryp)
153 {
154 struct vldbentry oentry;
155 int code;
156
157 if (newvlserver == vltype_old) {
158 tryold:
159 code = ubik_VL_GetEntryByNameO(cstruct, 0, namep, &oentry);
160 if (!code)
161 ovlentry_to_nvlentry(&oentry, entryp);
162 return code;
163 }
164 code = ubik_VL_GetEntryByNameN(cstruct, 0, namep, entryp);
165 if (newvlserver == vltype_unknown) {
166 if (code == RXGEN_OPCODE) {
167 newvlserver = vltype_old; /* Doesn't support new interface */
168 goto tryold;
169 } else if (!code) {
170 newvlserver = vltype_new;
171 }
172 }
173 return code;
174 }
175
176 int
177 VLDB_ReplaceEntry(afs_uint32 volid, afs_int32 voltype, struct nvldbentry *entryp, afs_int32 releasetype)
178 {
179 struct vldbentry oentry;
180 int code;
181
182 if (newvlserver == vltype_old) {
183 tryold:
184 code = nvlentry_to_ovlentry(entryp, &oentry);
185 if (code)
186 return code;
187 code =
188 ubik_VL_ReplaceEntry(cstruct, 0, volid, voltype, &oentry,
189 releasetype);
190 return code;
191 }
192 code =
193 ubik_VL_ReplaceEntryN(cstruct, 0, volid, voltype, entryp,
194 releasetype);
195 if (newvlserver == vltype_unknown) {
196 if (code == RXGEN_OPCODE) {
197 newvlserver = vltype_old; /* Doesn't support new interface */
198 goto tryold;
199 } else if (!code) {
200 newvlserver = vltype_new;
201 }
202 }
203 return code;
204 }
205
206 static void
207 convertBulkToNBulk(bulkentries *bulk, nbulkentries *nbulk) {
208 unsigned int i;
209
210 if (bulk->bulkentries_len == 0)
211 return;
212
213 nbulk->nbulkentries_len = bulk->bulkentries_len;
214 nbulk->nbulkentries_val =
215 xdr_alloc(bulk->bulkentries_len * sizeof(struct nvldbentry));
216
217 for (i = 0; i < bulk->bulkentries_len; i++) {
218 ovlentry_to_nvlentry(&bulk->bulkentries_val[i],
219 &nbulk->nbulkentries_val[i]);
220 }
221 }
222
223 int
224 VLDB_ListAttributes(VldbListByAttributes *attrp,
225 afs_int32 *entriesp,
226 nbulkentries *blkentriesp)
227 {
228 bulkentries arrayEntries;
229 int code;
230
231 if (newvlserver == vltype_old) {
232 tryold:
233 memset(&arrayEntries, 0, sizeof(arrayEntries));
234 code =
235 ubik_VL_ListAttributes(cstruct, 0, attrp, entriesp,
236 &arrayEntries);
237
238 if (code)
239 return code;
240
241 /* Ensure the number of entries claimed matches the no. returned */
242 if (*entriesp < 0)
243 *entriesp = 0;
244 if (*entriesp > arrayEntries.bulkentries_len)
245 *entriesp = arrayEntries.bulkentries_len;
246
247 convertBulkToNBulk(&arrayEntries, blkentriesp);
248
249 xdr_free((xdrproc_t) xdr_bulkentries, &arrayEntries);
250 return code;
251 }
252 code =
253 ubik_VL_ListAttributesN(cstruct, 0, attrp, entriesp, blkentriesp);
254 if (newvlserver == vltype_unknown) {
255 if (code == RXGEN_OPCODE) {
256 newvlserver = vltype_old; /* Doesn't support new interface */
257 goto tryold;
258 } else if (!code) {
259 newvlserver = vltype_new;
260 }
261 }
262
263 /* Ensure the number of entries claimed matches the no. returned */
264 if (*entriesp < 0)
265 *entriesp = 0;
266 if (*entriesp > blkentriesp->nbulkentries_len)
267 *entriesp = blkentriesp->nbulkentries_len;
268
269 return code;
270 }
271
272 int
273 VLDB_ListAttributesN2(VldbListByAttributes *attrp,
274 char *name,
275 afs_int32 thisindex,
276 afs_int32 *nentriesp,
277 nbulkentries *blkentriesp,
278 afs_int32 *nextindexp)
279 {
280 afs_int32 code = RXGEN_OPCODE;
281
282 if (newvlserver != vltype_old) {
283 code =
284 ubik_VL_ListAttributesN2(cstruct, 0, attrp, (name ? name : ""),
285 thisindex, nentriesp, blkentriesp, nextindexp);
286 if (code)
287 return code;
288
289 /* Ensure the number of entries claimed matches the no. returned */
290 if (*nentriesp < 0)
291 *nentriesp = 0;
292 if (*nentriesp > blkentriesp->nbulkentries_len)
293 *nentriesp = blkentriesp->nbulkentries_len;
294 }
295 return code;
296 }
297
298 struct cacheips {
299 afs_uint32 server;
300 afs_uint32 count;
301 afs_uint32 addrs[16];
302 };
303 /*
304 * Increase cache size. This avoids high CPU usage by the vlserver
305 * in environments where there are more than 16 fileservers in the
306 * cell.
307 */
308 #define GETADDRUCACHESIZE 64
309 struct cacheips cacheips[GETADDRUCACHESIZE];
310 int cacheip_index = 0;
311
312 int
313 VLDB_IsSameAddrs(afs_uint32 serv1, afs_uint32 serv2, afs_int32 *errorp)
314 {
315 int code;
316 ListAddrByAttributes attrs;
317 bulkaddrs addrs;
318 afs_uint32 *addrp, j, f1, f2;
319 afs_int32 unique, nentries, i;
320 afsUUID uuid;
321 static int initcache = 0;
322
323 *errorp = 0;
324
325 if (serv1 == serv2)
326 return 1;
327 if (newvlserver == vltype_old || newvlserver == vltype_new) {
328 return 0;
329 }
330 if (!initcache) {
331 for (i = 0; i < GETADDRUCACHESIZE; i++) {
332 cacheips[i].server = cacheips[i].count = 0;
333 }
334 initcache = 1;
335 }
336
337 /* See if it's cached */
338 for (i = 0; i < GETADDRUCACHESIZE; i++) {
339 f1 = f2 = 0;
340 for (j = 0; j < cacheips[i].count; j++) {
341 if (serv1 == cacheips[i].addrs[j])
342 f1 = 1;
343 else if (serv2 == cacheips[i].addrs[j])
344 f2 = 1;
345
346 if (f1 && f2)
347 return 1;
348 }
349 if (f1 || f2)
350 return 0;
351 if (cacheips[i].server == serv1)
352 return 0;
353 }
354
355 memset(&attrs, 0, sizeof(attrs));
356 attrs.Mask = VLADDR_IPADDR;
357 attrs.ipaddr = serv1;
358 memset(&addrs, 0, sizeof(addrs));
359 memset(&uuid, 0, sizeof(uuid));
360 code =
361 ubik_VL_GetAddrsU(cstruct, 0, &attrs, &uuid, &unique, &nentries,
362 &addrs);
363 if (newvlserver == vltype_unknown) {
364 if (code == RXGEN_OPCODE) {
365 return 0;
366 } else if (!code) {
367 newvlserver = vltype_uuid;
368 }
369 }
370 if (code == VL_NOENT)
371 return 0;
372 if (code) {
373 *errorp = code;
374 return 0;
375 }
376
377 code = 0;
378 if (nentries > GETADDRUCACHESIZE)
379 nentries = GETADDRUCACHESIZE; /* safety check; should not happen */
380 if (++cacheip_index >= GETADDRUCACHESIZE)
381 cacheip_index = 0;
382 cacheips[cacheip_index].server = serv1;
383 cacheips[cacheip_index].count = nentries;
384 addrp = addrs.bulkaddrs_val;
385 for (i = 0; i < nentries; i++, addrp++) {
386 cacheips[cacheip_index].addrs[i] = *addrp;
387 if (serv2 == *addrp) {
388 code = 1;
389 }
390 }
391 return code;
392 }
393
394 /*
395 Get the appropriate type of ubik client structure out from the system.
396 */
397 int
398 vsu_ClientInit(const char *confDir, char *cellName, int secFlags,
399 int (*secproc)(struct rx_securityClass *, afs_int32),
400 struct ubik_client **uclientp)
401 {
402 return ugen_ClientInitFlags(confDir, cellName, secFlags, uclientp,
403 secproc, VLDB_MAXSERVERS, AFSCONF_VLDBSERVICE,
404 90);
405 }
406
407 /*extract the name of volume <name> without readonly or backup suffixes
408 * and return the result as <rname>.
409 */
410 int
411 vsu_ExtractName(char rname[], char name[])
412 {
413 char sname[VOLSER_OLDMAXVOLNAME + 1];
414 size_t total;
415
416 strncpy(sname, name, sizeof(sname));
417 sname[sizeof(sname) - 1] = '\0';
418 total = strlen(sname);
419 if (!strcmp(&sname[total - 9], ".readonly")) {
420 /*discard the last 8 chars */
421 sname[total - 9] = '\0';
422 strcpy(rname, sname);
423 return 0;
424 } else if (!strcmp(&sname[total - 7], ".backup")) {
425 /*discard last 6 chars */
426 sname[total - 7] = '\0';
427 strcpy(rname, sname);
428 return 0;
429 } else {
430 strncpy(rname, name, VOLSER_OLDMAXVOLNAME);
431 rname[VOLSER_OLDMAXVOLNAME] = '\0';
432 return -1;
433 }
434 }
435
436 /* returns 0 if failed */
437 afs_uint32
438 vsu_GetVolumeID(char *astring, struct ubik_client *acstruct, afs_int32 *errp)
439 {
440 char volname[VOLSER_OLDMAXVOLNAME + 1];
441 struct nvldbentry entry;
442 afs_int32 vcode = 0;
443 size_t total;
444
445 *errp = 0;
446
447 if (isdigit(astring[0])) {
448 char *end;
449 afs_uint32 result;
450 result = strtoul(astring, &end, 10);
451 if (result != UINT_MAX && *end == '\0')
452 return result;
453 }
454
455 /* It was not a volume number but something else */
456 total = strlen(astring);
457 vsu_ExtractName(volname, astring);
458 vcode = VLDB_GetEntryByName(volname, &entry);
459 if (!vcode) {
460 if ((total >= 9) && (!strcmp(&astring[total - 9], ".readonly")))
461 return entry.volumeId[ROVOL];
462 else if ((total >= 7) && (!strcmp(&astring[total - 7], ".backup")))
463 return entry.volumeId[BACKVOL];
464 else
465 return (entry.volumeId[RWVOL]);
466 }
467 *errp = vcode;
468 return 0; /* can't find volume */
469 }