Merge 1.8.0~pre4 packaging into master
[pkg-k5-afs_openafs.git] / src / volser / vsutils.c
blob51b24651bcee3da30e23ef5a7d802665c28316d2
1 /*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
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 */
10 #include <afsconfig.h>
11 #include <afs/param.h>
12 #include <afs/stds.h>
14 #include <roken.h>
16 #include <ctype.h>
17 #ifdef AFS_AIX_ENV
18 #include <sys/statfs.h>
19 #endif
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>
34 #include "volser.h"
35 #include "volint.h"
36 #include "lockdata.h"
38 #include "vsutils_prototypes.h"
40 struct ubik_client *cstruct;
42 static void
43 ovlentry_to_nvlentry(struct vldbentry *oentryp,
44 struct nvldbentry *nentryp)
46 int i;
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];
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;
62 static int
63 nvlentry_to_ovlentry(struct nvldbentry *nentryp,
64 struct vldbentry *oentryp)
66 int i;
68 memset(oentryp, 0, sizeof(struct vldbentry));
69 strncpy(oentryp->name, nentryp->name, sizeof(oentryp->name));
70 if (nentryp->nServers > OMAXNSERVERS) {
72 * The alternative is to store OMAXSERVERS but it's always better
73 * to know what's going on...
75 return VL_BADSERVER;
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];
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;
90 enum _vlserver_type {
91 vltype_unknown = 0,
92 vltype_old = 1,
93 vltype_new = 2,
94 vltype_uuid = 3
97 static enum _vlserver_type newvlserver = vltype_unknown;
99 int
100 VLDB_CreateEntry(struct nvldbentry *entryp)
102 struct vldbentry oentry;
103 int code;
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;
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;
122 return code;
126 VLDB_GetEntryByID(afs_uint32 volid, afs_int32 voltype, struct nvldbentry *entryp)
128 struct vldbentry oentry;
129 int code;
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;
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;
148 return code;
152 VLDB_GetEntryByName(char *namep, struct nvldbentry *entryp)
154 struct vldbentry oentry;
155 int code;
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;
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;
173 return code;
177 VLDB_ReplaceEntry(afs_uint32 volid, afs_int32 voltype, struct nvldbentry *entryp, afs_int32 releasetype)
179 struct vldbentry oentry;
180 int code;
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;
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;
203 return code;
206 static void
207 convertBulkToNBulk(bulkentries *bulk, nbulkentries *nbulk) {
208 unsigned int i;
210 if (bulk->bulkentries_len == 0)
211 return;
213 nbulk->nbulkentries_len = bulk->bulkentries_len;
214 nbulk->nbulkentries_val =
215 xdr_alloc(bulk->bulkentries_len * sizeof(struct nvldbentry));
217 for (i = 0; i < bulk->bulkentries_len; i++) {
218 ovlentry_to_nvlentry(&bulk->bulkentries_val[i],
219 &nbulk->nbulkentries_val[i]);
224 VLDB_ListAttributes(VldbListByAttributes *attrp,
225 afs_int32 *entriesp,
226 nbulkentries *blkentriesp)
228 bulkentries arrayEntries;
229 int code;
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);
238 if (code)
239 return code;
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;
247 convertBulkToNBulk(&arrayEntries, blkentriesp);
249 xdr_free((xdrproc_t) xdr_bulkentries, &arrayEntries);
250 return code;
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;
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;
269 return code;
273 VLDB_ListAttributesN2(VldbListByAttributes *attrp,
274 char *name,
275 afs_int32 thisindex,
276 afs_int32 *nentriesp,
277 nbulkentries *blkentriesp,
278 afs_int32 *nextindexp)
280 afs_int32 code = RXGEN_OPCODE;
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;
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;
295 return code;
298 struct cacheips {
299 afs_uint32 server;
300 afs_uint32 count;
301 afs_uint32 addrs[16];
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.
308 #define GETADDRUCACHESIZE 64
309 struct cacheips cacheips[GETADDRUCACHESIZE];
310 int cacheip_index = 0;
313 VLDB_IsSameAddrs(afs_uint32 serv1, afs_uint32 serv2, afs_int32 *errorp)
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;
323 *errorp = 0;
325 if (serv1 == serv2)
326 return 1;
327 if (newvlserver == vltype_old || newvlserver == vltype_new) {
328 return 0;
330 if (!initcache) {
331 for (i = 0; i < GETADDRUCACHESIZE; i++) {
332 cacheips[i].server = cacheips[i].count = 0;
334 initcache = 1;
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;
346 if (f1 && f2)
347 return 1;
349 if (f1 || f2)
350 return 0;
351 if (cacheips[i].server == serv1)
352 return 0;
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;
370 if (code == VL_NOENT)
371 return 0;
372 if (code) {
373 *errorp = code;
374 return 0;
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;
391 return code;
395 Get the appropriate type of ubik client structure out from the system.
398 vsu_ClientInit(const char *confDir, char *cellName, int secFlags,
399 int (*secproc)(struct rx_securityClass *, afs_int32),
400 struct ubik_client **uclientp)
402 return ugen_ClientInitFlags(confDir, cellName, secFlags, uclientp,
403 secproc, VLDB_MAXSERVERS, AFSCONF_VLDBSERVICE,
404 90);
407 /*extract the name of volume <name> without readonly or backup suffixes
408 * and return the result as <rname>.
411 vsu_ExtractName(char rname[], char name[])
413 char sname[VOLSER_OLDMAXVOLNAME + 1];
414 size_t total;
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;
436 /* returns 0 if failed */
437 afs_uint32
438 vsu_GetVolumeID(char *astring, struct ubik_client *acstruct, afs_int32 *errp)
440 char volname[VOLSER_OLDMAXVOLNAME + 1];
441 struct nvldbentry entry;
442 afs_int32 vcode = 0;
443 size_t total;
445 *errp = 0;
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;
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]);
467 *errp = vcode;
468 return 0; /* can't find volume */