2 * Copyright 2000, International Business Machines Corporation and others.
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
10 #include <afsconfig.h>
11 #include <afs/param.h>
16 #include <sys/types.h>
19 #include <afs/afsutil.h>
26 #include <netinet/in.h>
37 #include "afs/audit.h"
41 #ifdef HAVE_POSIX_REGEX /* use POSIX regexp library */
47 extern struct afsconf_dir *vldb_confdir;
48 extern struct ubik_dbase *VL_dbase;
49 struct vlheader cheader; /* kept in network byte order */
50 extern afs_uint32 HostAddress[]; /* host addresses kept in host byte order */
52 struct extentaddr *ex_addr[VL_MAX_ADDREXTBLKS] = { 0, 0, 0, 0 };
53 static char rxinfo_str[128]; /* Need rxinfo string to be non-local */
54 #define ABORT(c) { errorcode = (c); goto abort; }
56 #define END(c) { errorcode = (c); goto end; }
58 #define VLDBALLOCLIMIT 10000
59 #define VLDBALLOCINCR 2048
61 static int put_attributeentry();
62 static int put_nattributeentry();
63 static int RemoveEntry();
64 static ReleaseEntry();
65 static int check_vldbentry();
66 static int check_nvldbentry();
67 static int vldbentry_to_vlentry();
68 static int nvldbentry_to_vlentry();
69 static get_vldbupdateentry();
70 static int repsite_exists();
71 static repsite_compress();
72 static vlentry_to_vldbentry();
73 static vlentry_to_nvldbentry();
74 static vlentry_to_uvldbentry();
75 static int InvalidVolname();
76 static int InvalidVoltype();
77 static int InvalidOperation();
78 static int InvalidReleasetype();
79 static int IpAddrToRelAddr();
80 static int ChangeIPAddr();
84 struct rx_call *rxcall;
87 register struct rx_connection *tconn;
92 struct in_addr hostAddr;
94 tconn = rx_ConnectionOf(rxcall);
95 hostAddr.s_addr = rx_HostOf(rx_PeerOf(tconn));
97 rxkad_GetServerInfo(rxcall->conn, NULL, &exp, tname, tinst, tcell,
100 sprintf(rxinfo_str, "%s %s", inet_ntoa(hostAddr), tname);
102 sprintf(rxinfo_str, "%s noauth", inet_ntoa(hostAddr));
106 /* This is called to initialize the database, set the appropriate locks and make sure that the vldb header is valid */
108 Init_VLdbase(trans, locktype, this_op)
109 struct ubik_trans **trans;
110 int locktype; /* indicate read or write transaction */
113 int errorcode = 0, pass, wl;
115 for (pass = 1; pass <= 3; pass++) {
116 if (pass == 2) { /* take write lock to rebuild the db */
117 errorcode = ubik_BeginTrans(VL_dbase, UBIK_WRITETRANS, trans);
119 } else if (locktype == LOCKREAD) {
121 ubik_BeginTransReadAny(VL_dbase, UBIK_READTRANS, trans);
124 errorcode = ubik_BeginTrans(VL_dbase, UBIK_WRITETRANS, trans);
130 errorcode = ubik_SetLock(*trans, 1, 1, locktype);
133 ubik_AbortTrans(*trans);
137 /* check that dbase is initialized and setup cheader */
138 /* 2nd pass we try to rebuild the header */
139 errorcode = CheckInit(*trans, ((pass == 2) ? 1 : 0));
140 if (!errorcode && wl && extent_mod)
141 errorcode = readExtents(*trans); /* Fix the mh extent blocks */
144 ubik_AbortTrans(*trans);
145 /* Only rebuld if the database is empty */
146 /* Exit if can't rebuild */
147 if ((pass == 1) && (errorcode != VL_EMPTY))
151 } else { /* No errorcode */
153 ubik_EndTrans(*trans); /* Rebuilt db. End trans, then retake original lock */
155 break; /* didn't rebuild and successful - exit */
163 /* Create a new vldb entry; both new volume id and name must be unique (non-existant in vldb). */
166 SVL_CreateEntry(rxcall, newentry)
167 struct rx_call *rxcall;
168 struct vldbentry *newentry;
170 struct ubik_trans *trans;
171 afs_int32 errorcode, blockindex;
172 struct nvlentry tentry;
174 COUNT_REQ(VLCREATEENTRY);
175 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) {
180 /* Do some validity tests on new entry */
181 if ((errorcode = check_vldbentry(newentry))
182 || (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
186 ("OCreate Volume %d %s\n", newentry->volumeId[RWVOL],
188 /* XXX shouldn't we check to see if the r/o volume is duplicated? */
189 if (newentry->volumeId[RWVOL]
190 && FindByID(trans, newentry->volumeId[RWVOL], RWVOL, &tentry, &errorcode)) { /* entry already exists, we fail */
191 errorcode = VL_IDEXIST;
193 } else if (errorcode) {
197 /* Is this following check (by volume name) necessary?? */
198 /* If entry already exists, we fail */
199 if (FindByName(trans, newentry->name, &tentry, &errorcode)) {
200 errorcode = VL_NAMEEXIST;
202 } else if (errorcode) {
206 blockindex = AllocBlock(trans, &tentry);
207 if (blockindex == 0) {
208 errorcode = VL_CREATEFAIL;
212 memset(&tentry, 0, sizeof(struct nvlentry));
213 /* Convert to its internal representation; both in host byte order */
214 if (errorcode = vldbentry_to_vlentry(trans, newentry, &tentry)) {
215 FreeBlock(trans, blockindex);
219 /* Actually insert the entry in vldb */
220 errorcode = ThreadVLentry(trans, blockindex, &tentry);
222 FreeBlock(trans, blockindex);
225 errorcode = ubik_EndTrans(trans);
231 ubik_AbortTrans(trans);
234 osi_auditU(rxcall, VLCreateEntryEvent, errorcode, AUD_STR,
235 (newentry ? newentry->name : NULL), AUD_END);
241 SVL_CreateEntryN(rxcall, newentry)
242 struct rx_call *rxcall;
243 struct nvldbentry *newentry;
245 struct ubik_trans *trans;
246 afs_int32 errorcode, blockindex;
247 struct nvlentry tentry;
249 COUNT_REQ(VLCREATEENTRYN);
250 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) {
255 /* Do some validity tests on new entry */
256 if ((errorcode = check_nvldbentry(newentry))
257 || (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
261 ("Create Volume %d %s\n", newentry->volumeId[RWVOL],
263 /* XXX shouldn't we check to see if the r/o volume is duplicated? */
264 if (newentry->volumeId[RWVOL]
265 && FindByID(trans, newentry->volumeId[RWVOL], RWVOL, &tentry, &errorcode)) { /* entry already exists, we fail */
266 errorcode = VL_IDEXIST;
268 } else if (errorcode) {
272 /* Is this following check (by volume name) necessary?? */
273 /* If entry already exists, we fail */
274 if (FindByName(trans, newentry->name, &tentry, &errorcode)) {
275 errorcode = VL_NAMEEXIST;
277 } else if (errorcode) {
281 blockindex = AllocBlock(trans, &tentry);
282 if (blockindex == 0) {
283 errorcode = VL_CREATEFAIL;
287 memset(&tentry, 0, sizeof(struct nvlentry));
288 /* Convert to its internal representation; both in host byte order */
289 if (errorcode = nvldbentry_to_vlentry(trans, newentry, &tentry)) {
290 FreeBlock(trans, blockindex);
294 /* Actually insert the entry in vldb */
295 errorcode = ThreadVLentry(trans, blockindex, &tentry);
297 FreeBlock(trans, blockindex);
300 errorcode = ubik_EndTrans(trans);
306 ubik_AbortTrans(trans);
309 osi_auditU(rxcall, VLCreateEntryEvent, errorcode, AUD_STR,
310 (newentry ? newentry->name : NULL), AUD_END);
316 SVL_ChangeAddr(rxcall, ip1, ip2)
317 struct rx_call *rxcall;
320 struct ubik_trans *trans;
323 COUNT_REQ(VLCHANGEADDR);
324 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) {
329 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
332 VLog(1, ("Change Addr %d -> %d %s\n", ip1, ip2, rxinfo(rxcall)));
333 if (errorcode = ChangeIPAddr(ip1, ip2, trans))
336 errorcode = ubik_EndTrans(trans);
342 ubik_AbortTrans(trans);
345 osi_auditU(rxcall, VLChangeAddrEvent, errorcode, AUD_LONG, ip1, AUD_LONG,
350 /* Delete a vldb entry given the volume id. */
352 SVL_DeleteEntry(rxcall, volid, voltype)
353 struct rx_call *rxcall;
357 struct ubik_trans *trans;
358 afs_int32 blockindex, errorcode;
359 struct nvlentry tentry;
361 COUNT_REQ(VLDELETEENTRY);
362 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
365 if ((voltype != -1) && (InvalidVoltype(voltype)))
368 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
371 VLog(1, ("Delete Volume %d %s\n", volid, rxinfo(rxcall)));
372 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
373 if (blockindex == 0) { /* volid not found */
375 errorcode = VL_NOENT;
379 if (tentry.flags & VLDELETED) { /* Already deleted; return */
380 ABORT(VL_ENTDELETED);
382 if (errorcode = RemoveEntry(trans, blockindex, &tentry)) {
385 errorcode = (ubik_EndTrans(trans));
390 ubik_AbortTrans(trans);
393 osi_auditU(rxcall, VLDeleteEntryEvent, errorcode, AUD_LONG, volid,
399 /* Get a vldb entry given its volume id; make sure it's not a deleted entry. */
400 GetEntryByID(rxcall, volid, voltype, aentry, new, this_op)
401 struct rx_call *rxcall;
403 afs_int32 voltype, new, this_op;
404 char *aentry; /* entry data copied here */
406 struct ubik_trans *trans;
407 afs_int32 blockindex, errorcode;
408 struct nvlentry tentry;
410 if ((voltype != -1) && (InvalidVoltype(voltype)))
411 return VL_BADVOLTYPE;
412 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
415 VLog(5, ("GetVolumeByID %d (%d) %s\n", volid, new, rxinfo(rxcall)));
416 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
417 if (blockindex == 0) { /* entry not found */
419 errorcode = VL_NOENT;
421 ubik_AbortTrans(trans);
424 if (tentry.flags & VLDELETED) { /* Entry is deleted! */
426 ubik_AbortTrans(trans);
427 return VL_ENTDELETED;
429 /* Convert from the internal to external form */
431 vlentry_to_nvldbentry(&tentry, (struct nvldbentry *)aentry);
433 vlentry_to_uvldbentry(&tentry, (struct uvldbentry *)aentry);
435 vlentry_to_vldbentry(&tentry, (struct vldbentry *)aentry);
436 return (ubik_EndTrans(trans));
440 SVL_GetEntryByID(rxcall, volid, voltype, aentry)
441 struct rx_call *rxcall;
442 afs_int32 volid, voltype;
443 vldbentry *aentry; /* entry data copied here */
445 COUNT_REQ(VLGETENTRYBYID);
446 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 0, this_op));
450 SVL_GetEntryByIDN(rxcall, volid, voltype, aentry)
451 struct rx_call *rxcall;
452 afs_int32 volid, voltype;
453 nvldbentry *aentry; /* entry data copied here */
455 COUNT_REQ(VLGETENTRYBYIDN);
456 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 1, this_op));
460 SVL_GetEntryByIDU(rxcall, volid, voltype, aentry)
461 struct rx_call *rxcall;
462 afs_int32 volid, voltype;
463 uvldbentry *aentry; /* entry data copied here */
465 COUNT_REQ(VLGETENTRYBYIDU);
466 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 2, this_op));
471 /* returns true if the id is a decimal integer, in which case we interpret it
472 as an id. make the cache manager much simpler */
475 register char *aname;
478 while (tc = *aname++) {
479 if (tc > '9' || tc < '0')
485 /* Get a vldb entry given the volume's name; of course, very similar to VLGetEntryByID() above. */
486 GetEntryByName(rxcall, volname, aentry, new, this_op)
487 struct rx_call *rxcall;
489 char *aentry; /* entry data copied here */
492 struct ubik_trans *trans;
493 afs_int32 blockindex, errorcode;
494 struct nvlentry tentry;
496 if (NameIsId(volname)) {
497 return GetEntryByID(rxcall, atoi(volname), -1, aentry, new, this_op);
499 if (InvalidVolname(volname))
501 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
503 VLog(5, ("GetVolumeByName %s (%d) %s\n", volname, new, rxinfo(rxcall)));
504 blockindex = FindByName(trans, volname, &tentry, &errorcode);
505 if (blockindex == 0) { /* entry not found */
507 errorcode = VL_NOENT;
509 ubik_AbortTrans(trans);
512 if (tentry.flags & VLDELETED) { /* Entry is deleted */
514 ubik_AbortTrans(trans);
515 return VL_ENTDELETED;
517 /* Convert to external entry representation */
519 vlentry_to_nvldbentry(&tentry, (struct nvldbentry *)aentry);
521 vlentry_to_uvldbentry(&tentry, (struct uvldbentry *)aentry);
523 vlentry_to_vldbentry(&tentry, (struct vldbentry *)aentry);
524 return (ubik_EndTrans(trans));
528 SVL_GetEntryByNameO(rxcall, volname, aentry)
529 struct rx_call *rxcall;
531 struct vldbentry *aentry; /* entry data copied here */
533 COUNT_REQ(VLGETENTRYBYNAME);
534 return (GetEntryByName(rxcall, volname, (char *)aentry, 0, this_op));
539 SVL_GetEntryByNameN(rxcall, volname, aentry)
540 struct rx_call *rxcall;
542 struct nvldbentry *aentry; /* entry data copied here */
544 COUNT_REQ(VLGETENTRYBYNAMEN);
545 return (GetEntryByName(rxcall, volname, (char *)aentry, 1, this_op));
549 SVL_GetEntryByNameU(rxcall, volname, aentry)
550 struct rx_call *rxcall;
552 struct uvldbentry *aentry; /* entry data copied here */
554 COUNT_REQ(VLGETENTRYBYNAMEU);
555 return (GetEntryByName(rxcall, volname, (char *)aentry, 2, this_op));
560 /* Get the current value of the maximum volume id and bump the volume id counter by Maxvolidbump. */
562 SVL_GetNewVolumeId(rxcall, Maxvolidbump, newvolumeid)
563 struct rx_call *rxcall;
564 afs_int32 Maxvolidbump;
565 afs_int32 *newvolumeid;
567 register afs_int32 errorcode, maxvolumeid;
568 struct ubik_trans *trans;
570 COUNT_REQ(VLGETNEWVOLUMEID);
571 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
574 if (Maxvolidbump < 0 || Maxvolidbump > MAXBUMPCOUNT)
575 END(VL_BADVOLIDBUMP);
577 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
580 *newvolumeid = maxvolumeid = ntohl(cheader.vital_header.MaxVolumeId);
581 maxvolumeid += Maxvolidbump;
582 VLog(1, ("GetNewVolid newmax=%d %s\n", maxvolumeid, rxinfo(rxcall)));
583 cheader.vital_header.MaxVolumeId = htonl(maxvolumeid);
584 if (write_vital_vlheader(trans)) {
587 errorcode = (ubik_EndTrans(trans));
592 ubik_AbortTrans(trans);
595 osi_auditU(rxcall, VLGetNewVolumeIdEvent, errorcode, AUD_END);
600 /* Simple replace the contents of the vldb entry, volid, with
601 * newentry. No individual checking/updating per field (alike
602 * VLUpdateEntry) is done. */
605 SVL_ReplaceEntry(rxcall, volid, voltype, newentry, releasetype)
606 struct rx_call *rxcall;
609 struct vldbentry *newentry;
610 afs_int32 releasetype;
612 struct ubik_trans *trans;
613 afs_int32 blockindex, errorcode, typeindex;
615 int hashVol[MAXTYPES];
616 struct nvlentry tentry;
618 COUNT_REQ(VLREPLACEENTRY);
619 for (typeindex = 0; typeindex < MAXTYPES; typeindex++)
620 hashVol[typeindex] = 0;
622 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
625 if (errorcode = check_vldbentry(newentry))
628 if (voltype != -1 && InvalidVoltype(voltype))
631 if (releasetype && InvalidReleasetype(releasetype))
632 END(VL_BADRELLOCKTYPE);
633 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
636 VLog(1, ("OReplace Volume %d %s\n", volid, rxinfo(rxcall)));
637 /* find vlentry we're changing */
638 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
639 if (blockindex == 0) { /* entry not found */
641 errorcode = VL_NOENT;
645 /* check that we're not trying to change the RW vol ID */
646 if (newentry->volumeId[RWVOL] != tentry.volumeId[RWVOL]) {
650 /* unhash volid entries if they're disappearing or changing.
651 * Remember if we need to hash in the new value (we don't have to
652 * rehash if volid stays same */
653 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
654 if (tentry.volumeId[typeindex] != newentry->volumeId[typeindex]) {
655 if (tentry.volumeId[typeindex])
657 UnhashVolid(trans, typeindex, blockindex, &tentry)) {
660 /* we must rehash new id if the id is different and the ID is nonzero */
661 hashVol[typeindex] = 1; /* must rehash this guy if he exists */
665 /* Rehash volname if it changes */
666 if (strcmp(newentry->name, tentry.name)) { /* Name changes; redo hashing */
667 if (errorcode = UnhashVolname(trans, blockindex, &tentry)) {
673 /* after this, tentry is new entry, not old one. vldbentry_to_vlentry
674 * doesn't touch hash chains */
675 if (errorcode = vldbentry_to_vlentry(trans, newentry, &tentry)) {
679 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
680 if (hashVol[typeindex] && tentry.volumeId[typeindex]) {
681 if (errorcode = HashVolid(trans, typeindex, blockindex, &tentry)) {
688 HashVolname(trans, blockindex, &tentry);
691 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
692 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
696 END(ubik_EndTrans(trans));
700 ubik_AbortTrans(trans);
703 osi_auditU(rxcall, VLReplaceVLEntryEvent, errorcode, AUD_LONG, volid,
709 SVL_ReplaceEntryN(rxcall, volid, voltype, newentry, releasetype)
710 struct rx_call *rxcall;
713 struct nvldbentry *newentry;
714 afs_int32 releasetype;
716 struct ubik_trans *trans;
717 afs_int32 blockindex, errorcode, typeindex;
719 int hashVol[MAXTYPES];
720 struct nvlentry tentry;
722 COUNT_REQ(VLREPLACEENTRYN);
723 for (typeindex = 0; typeindex < MAXTYPES; typeindex++)
724 hashVol[typeindex] = 0;
726 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
729 if (errorcode = check_nvldbentry(newentry))
732 if (voltype != -1 && InvalidVoltype(voltype))
735 if (releasetype && InvalidReleasetype(releasetype))
736 END(VL_BADRELLOCKTYPE);
737 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
740 VLog(1, ("Replace Volume %d %s\n", volid, rxinfo(rxcall)));
741 /* find vlentry we're changing */
742 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
743 if (blockindex == 0) { /* entry not found */
745 errorcode = VL_NOENT;
749 /* check that we're not trying to change the RW vol ID */
750 if (newentry->volumeId[RWVOL] != tentry.volumeId[RWVOL]) {
754 /* unhash volid entries if they're disappearing or changing.
755 * Remember if we need to hash in the new value (we don't have to
756 * rehash if volid stays same */
757 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
758 if (tentry.volumeId[typeindex] != newentry->volumeId[typeindex]) {
759 if (tentry.volumeId[typeindex])
761 UnhashVolid(trans, typeindex, blockindex, &tentry)) {
764 /* we must rehash new id if the id is different and the ID is nonzero */
765 hashVol[typeindex] = 1; /* must rehash this guy if he exists */
769 /* Rehash volname if it changes */
770 if (strcmp(newentry->name, tentry.name)) { /* Name changes; redo hashing */
771 if (errorcode = UnhashVolname(trans, blockindex, &tentry)) {
777 /* after this, tentry is new entry, not old one. vldbentry_to_vlentry
778 * doesn't touch hash chains */
779 if (errorcode = nvldbentry_to_vlentry(trans, newentry, &tentry)) {
783 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
784 if (hashVol[typeindex] && tentry.volumeId[typeindex]) {
785 if (errorcode = HashVolid(trans, typeindex, blockindex, &tentry)) {
792 HashVolname(trans, blockindex, &tentry);
795 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
796 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
800 END(ubik_EndTrans(trans));
804 ubik_AbortTrans(trans);
807 osi_auditU(rxcall, VLReplaceVLEntryEvent, errorcode, AUD_LONG, volid,
813 /* Update a vldb entry (accessed thru its volume id). Almost all of the entry's fields can be modified in a single call by setting the appropriate bits in the Mask field in VldbUpdateentry. */
814 /* this routine may never have been tested; use replace entry instead unless you're brave */
816 SVL_UpdateEntry(rxcall, volid, voltype, updateentry, releasetype)
817 struct rx_call *rxcall;
820 afs_int32 releasetype;
821 struct VldbUpdateEntry *updateentry; /* Update entry copied here */
823 struct ubik_trans *trans;
824 afs_int32 blockindex, errorcode;
825 struct nvlentry tentry;
827 COUNT_REQ(VLUPDATEENTRY);
828 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
830 if ((voltype != -1) && (InvalidVoltype(voltype)))
832 if (releasetype && InvalidReleasetype(releasetype))
833 END(VL_BADRELLOCKTYPE);
834 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
837 VLog(1, ("Update Volume %d %s\n", volid, rxinfo(rxcall)));
838 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
839 if (blockindex == 0) { /* entry not found */
841 errorcode = VL_NOENT;
845 /* Do the actual updating of the entry, tentry. */
847 get_vldbupdateentry(trans, blockindex, updateentry, &tentry)) {
851 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
852 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
855 END(ubik_EndTrans(trans));
859 ubik_AbortTrans(trans);
862 osi_auditU(rxcall, VLUpdateEntryEvent, errorcode, AUD_LONG, volid,
869 SVL_UpdateEntryByName(rxcall, volname, updateentry, releasetype)
870 struct rx_call *rxcall;
872 afs_int32 releasetype;
873 struct VldbUpdateEntry *updateentry; /* Update entry copied here */
875 struct ubik_trans *trans;
876 afs_int32 blockindex, errorcode;
877 struct nvlentry tentry;
879 COUNT_REQ(VLUPDATEENTRYBYNAME);
880 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
882 if (releasetype && InvalidReleasetype(releasetype))
883 END(VL_BADRELLOCKTYPE);
884 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
887 blockindex = FindByName(trans, volname, &tentry, &errorcode);
888 if (blockindex == 0) { /* entry not found */
890 errorcode = VL_NOENT;
894 /* Do the actual updating of the entry, tentry. */
896 get_vldbupdateentry(trans, blockindex, updateentry, &tentry)) {
900 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
901 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
904 END(ubik_EndTrans(trans));
908 ubik_AbortTrans(trans);
911 osi_auditU(rxcall, VLUpdateEntryEvent, errorcode, AUD_LONG, -1, AUD_END);
916 /* Set a lock to the vldb entry for volid (of type voltype if not -1). */
918 SVL_SetLock(rxcall, volid, voltype, voloper)
919 struct rx_call *rxcall;
924 afs_int32 timestamp, blockindex, errorcode;
925 struct ubik_trans *trans;
926 struct nvlentry tentry;
928 COUNT_REQ(VLSETLOCK);
929 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
931 if ((voltype != -1) && (InvalidVoltype(voltype)))
933 if (InvalidOperation(voloper))
935 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
938 VLog(1, ("SetLock Volume %d %s\n", volid, rxinfo(rxcall)));
939 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
940 if (blockindex == NULLO) {
942 errorcode = VL_NOENT;
945 if (tentry.flags & VLDELETED) {
946 ABORT(VL_ENTDELETED);
948 timestamp = FT_ApproxTime();
950 /* Check if entry is already locked; note that we unlock any entry
951 * locked more than MAXLOCKTIME seconds */
952 if ((tentry.LockTimestamp)
953 && ((timestamp - tentry.LockTimestamp) < MAXLOCKTIME)) {
954 ABORT(VL_ENTRYLOCKED);
957 /* Consider it an unlocked entry: set current timestamp, caller
958 * and active vol operation */
959 tentry.LockTimestamp = timestamp;
960 tentry.LockAfsId = 0; /* Not implemented yet */
961 if (tentry.flags & VLOP_RELEASE) {
964 tentry.flags &= ~VLOP_ALLOPERS; /* Clear any possible older operation bit */
965 tentry.flags |= voloper;
967 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
970 END(ubik_EndTrans(trans));
974 ubik_AbortTrans(trans);
977 osi_auditU(rxcall, VLSetLockEvent, errorcode, AUD_LONG, volid, AUD_END);
982 /* Release an already locked vldb entry. Releasetype determines what
983 * fields (afsid and/or volume operation) will be cleared along with
984 * the lock time stamp. */
987 SVL_ReleaseLock(rxcall, volid, voltype, releasetype)
988 struct rx_call *rxcall;
991 afs_int32 releasetype;
993 afs_int32 blockindex, errorcode;
994 struct ubik_trans *trans;
995 struct nvlentry tentry;
997 COUNT_REQ(VLRELEASELOCK);
998 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
1000 if ((voltype != -1) && (InvalidVoltype(voltype)))
1002 if (releasetype && InvalidReleasetype(releasetype))
1003 END(VL_BADRELLOCKTYPE);
1004 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
1007 VLog(1, ("ReleaseLock Volume %d %s\n", volid, rxinfo(rxcall)));
1008 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
1009 if (blockindex == NULLO) {
1011 errorcode = VL_NOENT;
1014 if (tentry.flags & VLDELETED) {
1015 ABORT(VL_ENTDELETED);
1018 ReleaseEntry(&tentry, releasetype); /* Unlock the appropriate fields */
1019 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
1022 END(ubik_EndTrans(trans));
1026 ubik_AbortTrans(trans);
1029 osi_auditU(rxcall, VLReleaseLockEvent, errorcode, AUD_LONG, volid,
1035 /* ListEntry returns a single vldb entry, aentry, with offset previous_index; the remaining parameters (i.e. next_index) are used so that sequential calls to this routine will get the next (all) vldb entries. */
1037 SVL_ListEntry(rxcall, previous_index, count, next_index, aentry)
1038 struct rx_call *rxcall;
1039 afs_int32 previous_index;
1041 afs_int32 *next_index;
1042 struct vldbentry *aentry;
1045 struct ubik_trans *trans;
1046 struct nvlentry tentry;
1048 COUNT_REQ(VLLISTENTRY);
1049 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1051 VLog(25, ("OListEntry index=%d %s\n", previous_index, rxinfo(rxcall)));
1052 *next_index = NextEntry(trans, previous_index, &tentry, count);
1054 vlentry_to_vldbentry(&tentry, aentry);
1055 return (ubik_EndTrans(trans));
1058 /* ListEntry returns a single vldb entry, aentry, with offset previous_index; the remaining parameters (i.e. next_index) are used so that sequential calls to this routine will get the next (all) vldb entries. */
1060 SVL_ListEntryN(rxcall, previous_index, count, next_index, aentry)
1061 struct rx_call *rxcall;
1062 afs_int32 previous_index;
1064 afs_int32 *next_index;
1065 struct nvldbentry *aentry;
1068 struct ubik_trans *trans;
1069 struct nvlentry tentry;
1071 COUNT_REQ(VLLISTENTRYN);
1072 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1074 VLog(25, ("ListEntry index=%d %s\n", previous_index, rxinfo(rxcall)));
1075 *next_index = NextEntry(trans, previous_index, &tentry, count);
1077 vlentry_to_nvldbentry(&tentry, aentry);
1078 return (ubik_EndTrans(trans));
1082 /* Retrieves in vldbentries all vldb entries that match the specified attributes (by server number, partition, volume type, and flag); if volume id is specified then the associated list for that entry is returned. CAUTION: This could be a very expensive call since in most cases sequential search of all vldb entries is performed. */
1084 SVL_ListAttributes(rxcall, attributes, nentries, vldbentries)
1085 struct rx_call *rxcall;
1086 struct VldbListByAttributes *attributes;
1087 afs_int32 *nentries;
1088 bulkentries *vldbentries;
1090 int errorcode, allocCount = 0;
1091 struct ubik_trans *trans;
1092 struct nvlentry tentry;
1093 struct vldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1096 COUNT_REQ(VLLISTATTRIBUTES);
1097 vldbentries->bulkentries_val = 0;
1098 vldbentries->bulkentries_len = *nentries = 0;
1099 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1101 allocCount = VLDBALLOCCOUNT;
1102 Vldbentry = VldbentryFirst = vldbentries->bulkentries_val =
1103 (vldbentry *) malloc(allocCount * sizeof(vldbentry));
1104 if (Vldbentry == NULL) {
1106 ubik_AbortTrans(trans);
1109 VldbentryLast = VldbentryFirst + allocCount;
1110 /* Handle the attribute by volume id totally separate of the rest (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!) */
1111 if (attributes->Mask & VLLIST_VOLUMEID) {
1112 afs_int32 blockindex;
1115 FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1116 if (blockindex == 0) {
1118 errorcode = VL_NOENT;
1120 ubik_AbortTrans(trans);
1121 if (vldbentries->bulkentries_val)
1122 free((char *)vldbentries->bulkentries_val);
1123 vldbentries->bulkentries_val = 0;
1124 vldbentries->bulkentries_len = 0;
1128 put_attributeentry(&Vldbentry, &VldbentryFirst, &VldbentryLast,
1129 vldbentries, &tentry, nentries, &allocCount)) {
1131 ubik_AbortTrans(trans);
1132 if (vldbentries->bulkentries_val)
1133 free((char *)vldbentries->bulkentries_val);
1134 vldbentries->bulkentries_val = 0;
1135 vldbentries->bulkentries_len = 0;
1136 return VL_SIZEEXCEEDED;
1139 afs_int32 nextblockindex = 0, count = 0, k, match = 0;
1140 while (nextblockindex =
1141 NextEntry(trans, nextblockindex, &tentry, &count)) {
1142 if (++pollcount > 50) {
1147 if (attributes->Mask & VLLIST_SERVER) {
1150 IpAddrToRelAddr(attributes->server,
1151 (struct ubik_trans *)0)) == -1)
1153 for (k = 0; k < OMAXNSERVERS; k++) {
1154 if (tentry.serverNumber[k] == BADSERVERID)
1156 if (tentry.serverNumber[k] == serverindex) {
1164 if (attributes->Mask & VLLIST_PARTITION) {
1166 if (tentry.serverPartition[k] != attributes->partition)
1169 for (k = 0; k < OMAXNSERVERS; k++) {
1170 if (tentry.serverNumber[k] == BADSERVERID)
1172 if (tentry.serverPartition[k] ==
1173 attributes->partition) {
1183 if (attributes->Mask & VLLIST_FLAG) {
1184 if (!(tentry.flags & attributes->flag))
1188 put_attributeentry(&Vldbentry, &VldbentryFirst,
1189 &VldbentryLast, vldbentries, &tentry,
1190 nentries, &allocCount)) {
1192 ubik_AbortTrans(trans);
1193 if (vldbentries->bulkentries_val)
1194 free((char *)vldbentries->bulkentries_val);
1195 vldbentries->bulkentries_val = 0;
1196 vldbentries->bulkentries_len = 0;
1201 if (vldbentries->bulkentries_len
1202 && (allocCount > vldbentries->bulkentries_len)) {
1204 vldbentries->bulkentries_val =
1205 (vldbentry *) realloc(vldbentries->bulkentries_val,
1206 vldbentries->bulkentries_len *
1208 if (vldbentries->bulkentries_val == NULL) {
1210 ubik_AbortTrans(trans);
1215 ("ListAttrs nentries=%d %s\n", vldbentries->bulkentries_len,
1217 return (ubik_EndTrans(trans));
1221 SVL_ListAttributesN(rxcall, attributes, nentries, vldbentries)
1222 struct rx_call *rxcall;
1223 struct VldbListByAttributes *attributes;
1224 afs_int32 *nentries;
1225 nbulkentries *vldbentries;
1227 int errorcode, allocCount = 0;
1228 struct ubik_trans *trans;
1229 struct nvlentry tentry;
1230 struct nvldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1233 COUNT_REQ(VLLISTATTRIBUTESN);
1234 vldbentries->nbulkentries_val = 0;
1235 vldbentries->nbulkentries_len = *nentries = 0;
1236 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1238 allocCount = VLDBALLOCCOUNT;
1239 Vldbentry = VldbentryFirst = vldbentries->nbulkentries_val =
1240 (nvldbentry *) malloc(allocCount * sizeof(nvldbentry));
1241 if (Vldbentry == NULL) {
1243 ubik_AbortTrans(trans);
1246 VldbentryLast = VldbentryFirst + allocCount;
1247 /* Handle the attribute by volume id totally separate of the rest (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!) */
1248 if (attributes->Mask & VLLIST_VOLUMEID) {
1249 afs_int32 blockindex;
1252 FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1253 if (blockindex == 0) {
1255 errorcode = VL_NOENT;
1257 ubik_AbortTrans(trans);
1258 if (vldbentries->nbulkentries_val)
1259 free((char *)vldbentries->nbulkentries_val);
1260 vldbentries->nbulkentries_val = 0;
1261 vldbentries->nbulkentries_len = 0;
1265 put_nattributeentry(&Vldbentry, &VldbentryFirst, &VldbentryLast,
1266 vldbentries, &tentry, 0, 0, nentries,
1269 ubik_AbortTrans(trans);
1270 if (vldbentries->nbulkentries_val)
1271 free((char *)vldbentries->nbulkentries_val);
1272 vldbentries->nbulkentries_val = 0;
1273 vldbentries->nbulkentries_len = 0;
1274 return VL_SIZEEXCEEDED;
1277 afs_int32 nextblockindex = 0, count = 0, k, match = 0;
1278 while (nextblockindex =
1279 NextEntry(trans, nextblockindex, &tentry, &count)) {
1280 if (++pollcount > 50) {
1286 if (attributes->Mask & VLLIST_SERVER) {
1289 IpAddrToRelAddr(attributes->server,
1290 (struct ubik_trans *)0)) == -1)
1292 for (k = 0; k < NMAXNSERVERS; k++) {
1293 if (tentry.serverNumber[k] == BADSERVERID)
1295 if (tentry.serverNumber[k] == serverindex) {
1303 if (attributes->Mask & VLLIST_PARTITION) {
1305 if (tentry.serverPartition[k] != attributes->partition)
1308 for (k = 0; k < NMAXNSERVERS; k++) {
1309 if (tentry.serverNumber[k] == BADSERVERID)
1311 if (tentry.serverPartition[k] ==
1312 attributes->partition) {
1322 if (attributes->Mask & VLLIST_FLAG) {
1323 if (!(tentry.flags & attributes->flag))
1327 put_nattributeentry(&Vldbentry, &VldbentryFirst,
1328 &VldbentryLast, vldbentries, &tentry, 0,
1329 0, nentries, &allocCount)) {
1331 ubik_AbortTrans(trans);
1332 if (vldbentries->nbulkentries_val)
1333 free((char *)vldbentries->nbulkentries_val);
1334 vldbentries->nbulkentries_val = 0;
1335 vldbentries->nbulkentries_len = 0;
1340 if (vldbentries->nbulkentries_len
1341 && (allocCount > vldbentries->nbulkentries_len)) {
1343 vldbentries->nbulkentries_val =
1344 (nvldbentry *) realloc(vldbentries->nbulkentries_val,
1345 vldbentries->nbulkentries_len *
1346 sizeof(nvldbentry));
1347 if (vldbentries->nbulkentries_val == NULL) {
1349 ubik_AbortTrans(trans);
1354 ("NListAttrs nentries=%d %s\n", vldbentries->nbulkentries_len,
1356 return (ubik_EndTrans(trans));
1361 SVL_ListAttributesN2(rxcall, attributes, name, startindex, nentries,
1362 vldbentries, nextstartindex)
1363 struct rx_call *rxcall;
1364 struct VldbListByAttributes *attributes;
1365 char *name; /* Wildcarded volume name */
1366 afs_int32 startindex;
1367 afs_int32 *nentries;
1368 nbulkentries *vldbentries;
1369 afs_int32 *nextstartindex;
1371 int errorcode = 0, maxCount = VLDBALLOCCOUNT;
1372 struct ubik_trans *trans;
1373 struct nvlentry tentry;
1374 struct nvldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1375 afs_int32 blockindex = 0, count = 0, k, match, matchindex;
1376 int serverindex = -1; /* no server found */
1377 int findserver = 0, findpartition = 0, findflag = 0, findname = 0;
1380 int namematchRWBK, namematchRO, thismatch, matchtype;
1381 char volumename[VL_MAXNAMELEN];
1382 #ifdef HAVE_POSIX_REGEX
1384 int need_regfree = 0;
1387 COUNT_REQ(VLLISTATTRIBUTESN2);
1388 vldbentries->nbulkentries_val = 0;
1389 vldbentries->nbulkentries_len = 0;
1391 *nextstartindex = -1;
1393 errorcode = Init_VLdbase(&trans, LOCKREAD, this_op);
1397 Vldbentry = VldbentryFirst = vldbentries->nbulkentries_val =
1398 (nvldbentry *) malloc(maxCount * sizeof(nvldbentry));
1399 if (Vldbentry == NULL) {
1401 ubik_AbortTrans(trans);
1405 VldbentryLast = VldbentryFirst + maxCount;
1407 /* Handle the attribute by volume id totally separate of the rest
1408 * (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!)
1410 if (attributes->Mask & VLLIST_VOLUMEID) {
1412 FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1413 if (blockindex == 0) {
1415 errorcode = VL_NOENT;
1418 put_nattributeentry(&Vldbentry, &VldbentryFirst,
1419 &VldbentryLast, vldbentries, &tentry, 0,
1420 0, nentries, &maxCount);
1426 /* Search each entry in the database and return all entries
1427 * that match the request. It checks volumename (with
1428 * wildcarding), entry flags, server, and partition.
1431 /* Get the server index for matching server address */
1432 if (attributes->Mask & VLLIST_SERVER) {
1434 IpAddrToRelAddr(attributes->server, (struct ubik_trans *)0);
1435 if (serverindex == -1)
1439 findpartition = ((attributes->Mask & VLLIST_PARTITION) ? 1 : 0);
1440 findflag = ((attributes->Mask & VLLIST_FLAG) ? 1 : 0);
1441 if (name && (strcmp(name, ".*") != 0) && (strcmp(name, "") != 0)) {
1442 sprintf(volumename, "^%s$", name);
1443 #ifdef HAVE_POSIX_REGEX
1444 if (regcomp(&re, volumename, REG_NOSUB) != 0) {
1445 errorcode = VL_BADNAME;
1450 t = (char *)re_comp(volumename);
1452 errorcode = VL_BADNAME;
1459 /* Read each entry and see if it is the one we want */
1460 blockindex = startindex;
1461 while (blockindex = NextEntry(trans, blockindex, &tentry, &count)) {
1462 if (++pollcount > 50) {
1467 /* Step through each server index searching for a match.
1468 * Match to an existing RW, BK, or RO volume name (preference
1469 * is in this order). Remember which index we matched against.
1471 namematchRWBK = namematchRO = 0; /* 0->notTried; 1->match; 2->noMatch */
1475 && (tentry.serverNumber[k] != BADSERVERID)); k++) {
1476 thismatch = 0; /* does this index match */
1478 /* Match against the RW or BK volume name. Remember
1479 * results in namematchRWBK. Prefer RW over BK.
1481 if (tentry.serverFlags[k] & VLSF_RWVOL) {
1482 /* Does the name match the RW name */
1483 if (tentry.flags & VLF_RWEXISTS) {
1485 sprintf(volumename, "%s", tentry.name);
1486 #ifdef HAVE_POSIX_REGEX
1487 if (regexec(&re, volumename, 0, NULL, 0) == 0) {
1488 thismatch = VLSF_RWVOL;
1491 if (re_exec(volumename)) {
1492 thismatch = VLSF_RWVOL;
1496 thismatch = VLSF_RWVOL;
1500 /* Does the name match the BK name */
1501 if (!thismatch && (tentry.flags & VLF_BACKEXISTS)) {
1503 sprintf(volumename, "%s.backup", tentry.name);
1504 #ifdef HAVE_POSIX_REGEX
1505 if (regexec(&re, volumename, 0, NULL, 0) == 0) {
1506 thismatch = VLSF_BACKVOL;
1509 if (re_exec(volumename)) {
1510 thismatch = VLSF_BACKVOL;
1514 thismatch = VLSF_BACKVOL;
1518 namematchRWBK = (thismatch ? 1 : 2);
1521 /* Match with the RO volume name. Compare once and
1522 * remember results in namematchRO. Note that this will
1523 * pick up entries marked NEWREPSITEs and DONTUSE.
1526 if (tentry.flags & VLF_ROEXISTS) {
1530 ((namematchRO == 1) ? VLSF_ROVOL : 0);
1532 sprintf(volumename, "%s.readonly",
1534 #ifdef HAVE_POSIX_REGEX
1535 if (regexec(&re, volumename, 0, NULL, 0) == 0) {
1536 thismatch = VLSF_ROVOL;
1539 if (re_exec(volumename))
1540 thismatch = VLSF_ROVOL;
1544 thismatch = VLSF_ROVOL;
1547 namematchRO = (thismatch ? 1 : 2);
1550 /* Is there a server match */
1551 if (thismatch && findserver
1552 && (tentry.serverNumber[k] != serverindex))
1555 /* Is there a partition match */
1556 if (thismatch && findpartition
1557 && (tentry.serverPartition[k] != attributes->partition))
1560 /* Is there a flag match */
1561 if (thismatch && findflag
1562 && !(tentry.flags & attributes->flag))
1565 /* We found a match. Remember the index, and type */
1569 matchtype = thismatch;
1572 /* Since we prefer RW and BK volume matches over RO matches,
1573 * if we have already checked the RWBK name, then we already
1574 * found the best match and so end the search.
1576 * If we tried matching against the RW, BK, and RO volume names
1577 * and both failed, then we end the search (none will match).
1579 if ((match && namematchRWBK)
1580 || ((namematchRWBK == 2) && (namematchRO == 2)))
1584 /* Passed all the tests. Take it */
1587 put_nattributeentry(&Vldbentry, &VldbentryFirst,
1588 &VldbentryLast, vldbentries, &tentry,
1589 matchtype, matchindex, nentries,
1594 if (*nentries >= maxCount)
1595 break; /* collected the max */
1598 *nextstartindex = (blockindex ? blockindex : -1);
1602 #ifdef HAVE_POSIX_REGEX
1609 ubik_AbortTrans(trans);
1610 if (vldbentries->nbulkentries_val)
1611 free((char *)vldbentries->nbulkentries_val);
1612 vldbentries->nbulkentries_val = 0;
1613 vldbentries->nbulkentries_len = 0;
1614 *nextstartindex = -1;
1618 ("N2ListAttrs nentries=%d %s\n", vldbentries->nbulkentries_len,
1620 return (ubik_EndTrans(trans));
1625 /* Retrieves in vldbentries all vldb entries that match the specified
1626 * attributes (by server number, partition, volume type, and flag); if
1627 * volume id is specified then the associated list for that entry is
1628 * returned. CAUTION: This could be a very expensive call since in most
1629 * cases sequential search of all vldb entries is performed.
1632 SVL_LinkedList(rxcall, attributes, nentries, vldbentries)
1633 struct rx_call *rxcall;
1634 struct VldbListByAttributes *attributes;
1635 afs_int32 *nentries;
1636 vldb_list *vldbentries;
1639 struct ubik_trans *trans;
1640 struct nvlentry tentry;
1641 vldblist vllist, *vllistptr;
1642 afs_int32 blockindex, count, k, match;
1646 COUNT_REQ(VLLINKEDLIST);
1647 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1651 vldbentries->node = NULL;
1652 vllistptr = &vldbentries->node;
1654 /* List by volumeid */
1655 if (attributes->Mask & VLLIST_VOLUMEID) {
1657 FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1660 ubik_AbortTrans(trans);
1661 return (errorcode ? errorcode : VL_NOENT);
1664 vllist = (single_vldbentry *) malloc(sizeof(single_vldbentry));
1665 if (vllist == NULL) {
1667 ubik_AbortTrans(trans);
1670 vlentry_to_vldbentry(&tentry, &vllist->VldbEntry);
1671 vllist->next_vldb = NULL;
1673 *vllistptr = vllist; /* Thread onto list */
1674 vllistptr = &vllist->next_vldb;
1678 /* Search by server, partition, and flags */
1680 for (blockindex = NextEntry(trans, 0, &tentry, &count); blockindex;
1681 blockindex = NextEntry(trans, blockindex, &tentry, &count)) {
1684 if (++pollcount > 50) {
1689 /* Does this volume exist on the desired server */
1690 if (attributes->Mask & VLLIST_SERVER) {
1692 IpAddrToRelAddr(attributes->server,
1693 (struct ubik_trans *)0);
1694 if (serverindex == -1)
1696 for (k = 0; k < OMAXNSERVERS; k++) {
1697 if (tentry.serverNumber[k] == BADSERVERID)
1699 if (tentry.serverNumber[k] == serverindex) {
1708 /* Does this volume exist on the desired partition */
1709 if (attributes->Mask & VLLIST_PARTITION) {
1711 if (tentry.serverPartition[k] != attributes->partition)
1714 for (k = 0; k < OMAXNSERVERS; k++) {
1715 if (tentry.serverNumber[k] == BADSERVERID)
1717 if (tentry.serverPartition[k] ==
1718 attributes->partition) {
1728 /* Does this volume have the desired flags */
1729 if (attributes->Mask & VLLIST_FLAG) {
1730 if (!(tentry.flags & attributes->flag))
1734 vllist = (single_vldbentry *) malloc(sizeof(single_vldbentry));
1735 if (vllist == NULL) {
1737 ubik_AbortTrans(trans);
1740 vlentry_to_vldbentry(&tentry, &vllist->VldbEntry);
1741 vllist->next_vldb = NULL;
1743 *vllistptr = vllist; /* Thread onto list */
1744 vllistptr = &vllist->next_vldb;
1746 if (smallMem && (*nentries >= VLDBALLOCCOUNT)) {
1748 ubik_AbortTrans(trans);
1749 return VL_SIZEEXCEEDED;
1754 return (ubik_EndTrans(trans));
1758 SVL_LinkedListN(rxcall, attributes, nentries, vldbentries)
1759 struct rx_call *rxcall;
1760 struct VldbListByAttributes *attributes;
1761 afs_int32 *nentries;
1762 nvldb_list *vldbentries;
1765 struct ubik_trans *trans;
1766 struct nvlentry tentry;
1767 nvldblist vllist, *vllistptr;
1768 afs_int32 blockindex, count, k, match;
1772 COUNT_REQ(VLLINKEDLISTN);
1773 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1777 vldbentries->node = NULL;
1778 vllistptr = &vldbentries->node;
1780 /* List by volumeid */
1781 if (attributes->Mask & VLLIST_VOLUMEID) {
1783 FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1786 ubik_AbortTrans(trans);
1787 return (errorcode ? errorcode : VL_NOENT);
1790 vllist = (single_nvldbentry *) malloc(sizeof(single_nvldbentry));
1791 if (vllist == NULL) {
1793 ubik_AbortTrans(trans);
1796 vlentry_to_nvldbentry(&tentry, &vllist->VldbEntry);
1797 vllist->next_vldb = NULL;
1799 *vllistptr = vllist; /* Thread onto list */
1800 vllistptr = &vllist->next_vldb;
1804 /* Search by server, partition, and flags */
1806 for (blockindex = NextEntry(trans, 0, &tentry, &count); blockindex;
1807 blockindex = NextEntry(trans, blockindex, &tentry, &count)) {
1810 if (++pollcount > 50) {
1815 /* Does this volume exist on the desired server */
1816 if (attributes->Mask & VLLIST_SERVER) {
1818 IpAddrToRelAddr(attributes->server,
1819 (struct ubik_trans *)0);
1820 if (serverindex == -1)
1822 for (k = 0; k < NMAXNSERVERS; k++) {
1823 if (tentry.serverNumber[k] == BADSERVERID)
1825 if (tentry.serverNumber[k] == serverindex) {
1834 /* Does this volume exist on the desired partition */
1835 if (attributes->Mask & VLLIST_PARTITION) {
1837 if (tentry.serverPartition[k] != attributes->partition)
1840 for (k = 0; k < NMAXNSERVERS; k++) {
1841 if (tentry.serverNumber[k] == BADSERVERID)
1843 if (tentry.serverPartition[k] ==
1844 attributes->partition) {
1854 /* Does this volume have the desired flags */
1855 if (attributes->Mask & VLLIST_FLAG) {
1856 if (!(tentry.flags & attributes->flag))
1860 vllist = (single_nvldbentry *) malloc(sizeof(single_nvldbentry));
1861 if (vllist == NULL) {
1863 ubik_AbortTrans(trans);
1866 vlentry_to_nvldbentry(&tentry, &vllist->VldbEntry);
1867 vllist->next_vldb = NULL;
1869 *vllistptr = vllist; /* Thread onto list */
1870 vllistptr = &vllist->next_vldb;
1872 if (smallMem && (*nentries >= VLDBALLOCCOUNT)) {
1874 ubik_AbortTrans(trans);
1875 return VL_SIZEEXCEEDED;
1880 return (ubik_EndTrans(trans));
1883 /* Get back vldb header statistics (allocs, frees, maxvolumeid, totalentries, etc) and dynamic statistics (number of requests and/or aborts per remote procedure call, etc) */
1885 SVL_GetStats(rxcall, stats, vital_header)
1886 struct rx_call *rxcall;
1888 vital_vlheader *vital_header;
1890 register afs_int32 errorcode;
1891 struct ubik_trans *trans;
1893 COUNT_REQ(VLGETSTATS);
1895 /* Allow users to get statistics freely */
1896 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) /* Must be in 'UserList' to use */
1899 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1901 VLog(5, ("GetStats %s\n", rxinfo(rxcall)));
1902 memcpy((char *)vital_header, (char *)&cheader.vital_header,
1903 sizeof(vital_vlheader));
1904 memcpy((char *)stats, (char *)&dynamic_statistics, sizeof(vldstats));
1905 return (ubik_EndTrans(trans));
1908 /* Get the list of file server addresses from the VLDB. Currently it's pretty
1909 * easy to do. In the future, it might require a little bit of grunging
1910 * through the VLDB, but that's life.
1913 SVL_GetAddrs(rxcall, Handle, spare2, spare3, nentries, addrsp)
1914 struct rx_call *rxcall;
1915 afs_int32 Handle, spare2;
1916 struct VLCallBack *spare3;
1917 afs_int32 *nentries;
1920 register afs_int32 errorcode;
1921 struct ubik_trans *trans;
1925 COUNT_REQ(VLGETADDRS);
1926 addrsp->bulkaddrs_len = *nentries = 0;
1927 addrsp->bulkaddrs_val = 0;
1928 memset(spare3, 0, sizeof(struct VLCallBack));
1930 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1933 VLog(5, ("GetAddrs\n"));
1934 addrsp->bulkaddrs_val = taddrp =
1935 (afs_uint32 *) malloc(sizeof(afs_int32) * (MAXSERVERID + 1));
1936 nservers = *nentries = addrsp->bulkaddrs_len = 0;
1940 ubik_AbortTrans(trans);
1944 for (i = 0; i <= MAXSERVERID; i++) {
1945 if (*taddrp = ntohl(cheader.IpMappedAddr[i])) {
1951 addrsp->bulkaddrs_len = *nentries = nservers;
1952 return (ubik_EndTrans(trans));
1955 #define PADDR(addr) printf("%d.%d.%d.%d", (addr>>24)&0xff, (addr>>16)&0xff, (addr>>8) &0xff, addr&0xff);
1958 SVL_RegisterAddrs(rxcall, uuidp, spare1, addrsp)
1959 struct rx_call *rxcall;
1965 struct ubik_trans *trans;
1966 int cnt, h, i, j, k, m, base, index;
1967 struct extentaddr *exp = 0, *tex;
1969 afs_uint32 addrs[VL_MAXIPADDRS_PERMH];
1971 int count, willChangeEntry, foundUuidEntry, willReplaceCnt;
1972 int WillReplaceEntry, WillChange[MAXSERVERID + 1], FoundUuid,
1976 COUNT_REQ(VLREGADDR);
1977 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
1979 if (code = Init_VLdbase(&trans, LOCKWRITE, this_op))
1982 /* Eliminate duplicates from IP address list */
1983 for (k = 0, cnt = 0; k < addrsp->bulkaddrs_len; k++) {
1984 if (addrsp->bulkaddrs_val[k] == 0)
1986 for (m = 0; m < cnt; m++) {
1987 if (addrs[m] == addrsp->bulkaddrs_val[k])
1991 if (m == VL_MAXIPADDRS_PERMH) {
1993 ("Number of addresses exceeds %d. Cannot register IP addr 0x%x in VLDB\n",
1994 VL_MAXIPADDRS_PERMH, addrsp->bulkaddrs_val[k]));
1996 addrs[m] = addrsp->bulkaddrs_val[k];
2002 ubik_AbortTrans(trans);
2003 return VL_INDEXERANGE;
2009 /* For each server registered within the VLDB */
2010 for (srvidx = 0; srvidx <= MAXSERVERID; srvidx++) {
2011 willChangeEntry = 0;
2012 WillReplaceEntry = 1;
2013 if ((HostAddress[srvidx] & 0xff000000) == 0xff000000) {
2014 /* The server is registered as a multihomed */
2015 base = (HostAddress[srvidx] >> 16) & 0xff;
2016 index = HostAddress[srvidx] & 0x0000ffff;
2017 if (base >= VL_MAX_ADDREXTBLKS) {
2019 ("Internal error: Multihome extent base is too large. Base %d index %d\n",
2023 if (index >= VL_MHSRV_PERBLK) {
2025 ("Internal error: Multihome extent index is too large. Base %d index %d\n",
2029 if (!ex_addr[base]) {
2031 ("Internal error: Multihome extent does not exist. Base %d\n",
2036 /* See if the addresses to register will change this server entry */
2037 exp = &ex_addr[base][index];
2038 tuuid = exp->ex_hostuuid;
2039 afs_ntohuuid(&tuuid);
2040 if (afs_uuid_equal(uuidp, &tuuid)) {
2044 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2045 if (!exp->ex_addrs[mhidx])
2047 for (k = 0; k < cnt; k++) {
2048 if (ntohl(exp->ex_addrs[mhidx]) == addrs[k]) {
2049 willChangeEntry = 1;
2050 WillChange[count] = srvidx;
2055 WillReplaceEntry = 0;
2059 /* The server is not registered as a multihomed.
2060 * See if the addresses to register will replace this server entry.
2062 for (k = 0; k < cnt; k++) {
2063 if (HostAddress[srvidx] == addrs[k]) {
2064 willChangeEntry = 1;
2065 WillChange[count] = srvidx;
2066 WillReplaceEntry = 1;
2071 if (willChangeEntry) {
2072 if (WillReplaceEntry) {
2074 ReplaceEntry = srvidx;
2080 /* If we found the uuid in the VLDB and if we are replacing another
2081 * entire entry, then complain and fail. Also, if we did not find
2082 * the uuid in the VLDB and the IP addresses being registered was
2083 * found in more than one other entry, then we don't know which one
2084 * to replace and will complain and fail.
2086 if ((foundUuidEntry && (willReplaceCnt > 0))
2087 || (!foundUuidEntry && (count > 1))) {
2089 ("The following fileserver is being registered in the VLDB:\n"));
2091 for (k = 0; k < cnt; k++) {
2098 if (foundUuidEntry) {
2100 (" It would have replaced the existing VLDB server entry:\n");
2101 printf(" entry %d: [", FoundUuid);
2102 base = (HostAddress[FoundUuid] >> 16) & 0xff;
2103 index = HostAddress[FoundUuid] & 0x0000ffff;
2104 exp = &ex_addr[base][index];
2105 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2106 if (!exp->ex_addrs[mhidx])
2110 PADDR(ntohl(exp->ex_addrs[mhidx]));
2116 printf(" Yet another VLDB server entry exists:\n");
2118 printf(" Yet other VLDB server entries exist:\n");
2119 for (j = 0; j < count; j++) {
2120 srvidx = WillChange[j];
2121 printf(" entry %d: ", srvidx);
2122 if ((HostAddress[srvidx] & 0xff000000) == 0xff000000) {
2124 base = (HostAddress[srvidx] >> 16) & 0xff;
2125 index = HostAddress[srvidx] & 0x0000ffff;
2126 exp = &ex_addr[base][index];
2127 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2128 if (!exp->ex_addrs[mhidx])
2132 PADDR(ntohl(exp->ex_addrs[mhidx]));
2136 PADDR(HostAddress[srvidx]);
2142 printf(" You must 'vos changeaddr' this other server entry\n");
2145 (" You must 'vos changeaddr' these other server entries\n");
2148 (" and/or remove the sysid file from the registering fileserver\n");
2149 printf(" before the fileserver can be registered in the VLDB.\n");
2151 ubik_AbortTrans(trans);
2152 return VL_MULTIPADDR;
2155 /* Passed the checks. Now find and update the existing mh entry, or create
2158 if (foundUuidEntry) {
2159 /* Found the entry with same uuid. See if we need to change it */
2162 fbase = (HostAddress[FoundUuid] >> 16) & 0xff;
2163 index = HostAddress[FoundUuid] & 0x0000ffff;
2164 exp = &ex_addr[fbase][index];
2166 /* Determine if the entry has changed */
2167 for (k = 0; ((k < cnt) && !change); k++) {
2168 if (ntohl(exp->ex_addrs[k]) != addrs[k])
2171 for (; ((k < VL_MAXIPADDRS_PERMH) && !change); k++) {
2172 if (exp->ex_addrs[k] != 0)
2176 return (ubik_EndTrans(trans));
2180 VLog(0, ("The following fileserver is being registered in the VLDB:\n"));
2182 for (k = 0; k < cnt; k++) {
2189 if (foundUuidEntry) {
2191 (" It will replace the following existing entry in the VLDB (same uuid):\n");
2192 printf(" entry %d: [", FoundUuid);
2193 for (k = 0; k < VL_MAXIPADDRS_PERMH; k++) {
2194 if (exp->ex_addrs[k] == 0)
2198 PADDR(ntohl(exp->ex_addrs[k]));
2201 } else if (willReplaceCnt || (count == 1)) {
2202 /* If we are not replacing an entry and there is only one entry to change,
2203 * then we will replace that entry.
2205 if (!willReplaceCnt) {
2206 ReplaceEntry = WillChange[0];
2210 /* Have an entry that needs to be replaced */
2211 if ((HostAddress[ReplaceEntry] & 0xff000000) == 0xff000000) {
2212 fbase = (HostAddress[ReplaceEntry] >> 16) & 0xff;
2213 index = HostAddress[ReplaceEntry] & 0x0000ffff;
2214 exp = &ex_addr[fbase][index];
2217 (" It will replace the following existing entry in the VLDB (new uuid):\n");
2218 printf(" entry %d: [", ReplaceEntry);
2219 for (k = 0; k < VL_MAXIPADDRS_PERMH; k++) {
2220 if (exp->ex_addrs[k] == 0)
2224 PADDR(ntohl(exp->ex_addrs[k]));
2228 /* Not a mh entry. So we have to create a new mh entry and
2229 * put it on the ReplaceEntry slot of the HostAddress array.
2231 printf(" It will replace existing entry %d, ", ReplaceEntry);
2232 PADDR(HostAddress[ReplaceEntry]);
2233 printf(", in the VLDB (new uuid):\n");
2236 FindExtentBlock(trans, uuidp, 1, ReplaceEntry, &exp, &fbase);
2238 ubik_AbortTrans(trans);
2239 return (code ? code : VL_IO);
2243 /* There is no entry for this server, must create a new mh entry as
2244 * well as use a new slot of the HostAddress array.
2246 printf(" It will create a new entry in the VLDB.\n");
2247 code = FindExtentBlock(trans, uuidp, 1, -1, &exp, &fbase);
2249 ubik_AbortTrans(trans);
2250 return (code ? code : VL_IO);
2254 /* Now we have a mh entry to fill in. Update the uuid, bump the
2255 * uniquifier, and fill in its IP addresses.
2258 afs_htonuuid(&tuuid);
2259 exp->ex_hostuuid = tuuid;
2260 exp->ex_uniquifier = htonl(ntohl(exp->ex_uniquifier) + 1);
2261 for (k = 0; k < cnt; k++) {
2262 exp->ex_addrs[k] = htonl(addrs[k]);
2264 for (; k < VL_MAXIPADDRS_PERMH; k++) {
2265 exp->ex_addrs[k] = 0;
2268 /* Write the new mh entry out */
2271 DOFFSET(ntohl(ex_addr[0]->ex_contaddrs[fbase]),
2272 (char *)ex_addr[fbase], (char *)exp), (char *)exp,
2274 ubik_AbortTrans(trans);
2278 /* Remove any common addresses from other mh entres. We know these entries
2279 * are being changed and not replaced so they are mh entries.
2282 for (i = 0; i < count; i++) {
2285 /* Skip the entry we replaced */
2286 if (willReplaceCnt && (WillChange[i] == ReplaceEntry))
2289 base = (HostAddress[WillChange[i]] >> 16) & 0xff;
2290 index = HostAddress[WillChange[i]] & 0x0000ffff;
2291 tex = &ex_addr[fbase][index];
2295 (" The following existing entries in the VLDB will be updated:\n");
2297 printf(" entry %d: [", WillChange[i]);
2298 for (h = j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2299 if (tex->ex_addrs[j]) {
2302 PADDR(ntohl(tex->ex_addrs[j]));
2305 for (k = 0; k < cnt; k++) {
2306 if (ntohl(tex->ex_addrs[j]) == addrs[k])
2310 /* Not found, so we keep it */
2311 tex->ex_addrs[h] = tex->ex_addrs[j];
2315 for (j = h; j < VL_MAXIPADDRS_PERMH; j++) {
2316 tex->ex_addrs[j] = 0; /* zero rest of mh entry */
2320 /* Write out the modified mh entry */
2321 tex->ex_uniquifier = htonl(ntohl(tex->ex_uniquifier) + 1);
2323 DOFFSET(ntohl(ex_addr[0]->ex_contaddrs[base]),
2324 (char *)ex_addr[base], (char *)tex);
2325 if (vlwrite(trans, doff, (char *)tex, sizeof(*tex))) {
2326 ubik_AbortTrans(trans);
2331 return (ubik_EndTrans(trans));
2335 SVL_GetAddrsU(rxcall, attributes, uuidpo, uniquifier, nentries, addrsp)
2336 struct rx_call *rxcall;
2337 struct ListAddrByAttributes *attributes;
2339 afs_int32 *uniquifier, *nentries;
2342 register afs_int32 errorcode, index = -1, offset;
2343 struct ubik_trans *trans;
2344 int nservers, i, j, base = 0;
2345 struct extentaddr *exp = 0;
2347 afs_uint32 *taddrp, taddr;
2349 COUNT_REQ(VLGETADDRSU);
2350 addrsp->bulkaddrs_len = *nentries = 0;
2351 addrsp->bulkaddrs_val = 0;
2352 VLog(5, ("GetAddrsU %s\n", rxinfo(rxcall)));
2353 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
2356 if (attributes->Mask & VLADDR_IPADDR) {
2357 if (attributes->Mask & (VLADDR_INDEX | VLADDR_UUID)) {
2358 ubik_AbortTrans(trans);
2361 for (base = 0; base < VL_MAX_ADDREXTBLKS; base++) {
2364 for (i = 1; i < VL_MHSRV_PERBLK; i++) {
2365 exp = &ex_addr[base][i];
2366 tuuid = exp->ex_hostuuid;
2367 afs_ntohuuid(&tuuid);
2368 if (afs_uuid_is_nil(&tuuid))
2370 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2371 if (exp->ex_addrs[j]
2372 && (ntohl(exp->ex_addrs[j]) == attributes->ipaddr)) {
2376 if (j < VL_MAXIPADDRS_PERMH)
2379 if (i < VL_MHSRV_PERBLK)
2382 if (base >= VL_MAX_ADDREXTBLKS) {
2383 ubik_AbortTrans(trans);
2386 } else if (attributes->Mask & VLADDR_INDEX) {
2387 if (attributes->Mask & (VLADDR_IPADDR | VLADDR_UUID)) {
2388 ubik_AbortTrans(trans);
2391 index = attributes->index;
2392 if (index < 1 || index >= (VL_MAX_ADDREXTBLKS * VL_MHSRV_PERBLK)) {
2393 ubik_AbortTrans(trans);
2394 return VL_INDEXERANGE;
2396 base = index / VL_MHSRV_PERBLK;
2397 offset = index % VL_MHSRV_PERBLK;
2399 ubik_AbortTrans(trans);
2402 if (!ex_addr[base]) {
2403 ubik_AbortTrans(trans);
2404 return VL_INDEXERANGE;
2406 exp = &ex_addr[base][offset];
2407 } else if (attributes->Mask & VLADDR_UUID) {
2408 if (attributes->Mask & (VLADDR_IPADDR | VLADDR_INDEX)) {
2409 ubik_AbortTrans(trans);
2412 if (!ex_addr[0]) { /* mh servers probably aren't setup on this vldb */
2413 ubik_AbortTrans(trans);
2417 FindExtentBlock(trans, &attributes->uuid, 0, -1, &exp, &base)) {
2418 ubik_AbortTrans(trans);
2422 ubik_AbortTrans(trans);
2427 ubik_AbortTrans(trans);
2430 addrsp->bulkaddrs_val = taddrp =
2431 (afs_uint32 *) malloc(sizeof(afs_int32) * (MAXSERVERID + 1));
2432 nservers = *nentries = addrsp->bulkaddrs_len = 0;
2435 ubik_AbortTrans(trans);
2438 tuuid = exp->ex_hostuuid;
2439 afs_ntohuuid(&tuuid);
2440 if (afs_uuid_is_nil(&tuuid)) {
2441 ubik_AbortTrans(trans);
2447 *uniquifier = ntohl(exp->ex_uniquifier);
2448 for (i = 0; i < VL_MAXIPADDRS_PERMH; i++) {
2449 if (exp->ex_addrs[i]) {
2450 taddr = ntohl(exp->ex_addrs[i]);
2451 /* Weed out duplicates */
2452 for (j = 0; j < nservers; j++) {
2453 if (taddrp[j] == taddr)
2456 if ((j == nservers) && (j <= MAXSERVERID)) {
2457 taddrp[nservers] = taddr;
2462 addrsp->bulkaddrs_len = *nentries = nservers;
2463 return (ubik_EndTrans(trans));
2466 /* ============> End of Exported vldb RPC functions <============= */
2469 /* Routine that copies the given vldb entry to the output buffer, vldbentries. */
2471 put_attributeentry(Vldbentry, VldbentryFirst, VldbentryLast, vldbentries,
2472 entry, nentries, alloccnt)
2473 struct vldbentry **Vldbentry, **VldbentryFirst, **VldbentryLast;
2474 bulkentries *vldbentries;
2475 struct nvlentry *entry;
2476 afs_int32 *nentries, *alloccnt;
2481 if (*Vldbentry == *VldbentryLast) {
2483 return VL_SIZEEXCEEDED; /* no growing if smallMem defined */
2485 /* Allocate another set of memory; each time allocate twice as
2486 * many blocks as the last time. When we reach VLDBALLOCLIMIT,
2487 * then grow in increments of VLDBALLOCINCR.
2489 allo = (*alloccnt > VLDBALLOCLIMIT) ? VLDBALLOCINCR : *alloccnt;
2491 (vldbentry *) realloc(*VldbentryFirst,
2492 (*alloccnt + allo) * sizeof(vldbentry));
2496 *VldbentryFirst = vldbentries->bulkentries_val = reall;
2497 *Vldbentry = *VldbentryFirst + *alloccnt;
2498 *VldbentryLast = *Vldbentry + allo;
2501 vlentry_to_vldbentry(entry, *Vldbentry);
2504 vldbentries->bulkentries_len++;
2509 put_nattributeentry(Vldbentry, VldbentryFirst, VldbentryLast, vldbentries,
2510 entry, matchtype, matchindex, nentries, alloccnt)
2511 struct nvldbentry **Vldbentry, **VldbentryFirst, **VldbentryLast;
2512 nbulkentries *vldbentries;
2513 struct nvlentry *entry;
2514 afs_int32 matchtype, matchindex, *nentries, *alloccnt;
2519 if (*Vldbentry == *VldbentryLast) {
2521 return VL_SIZEEXCEEDED; /* no growing if smallMem defined */
2523 /* Allocate another set of memory; each time allocate twice as
2524 * many blocks as the last time. When we reach VLDBALLOCLIMIT,
2525 * then grow in increments of VLDBALLOCINCR.
2527 allo = (*alloccnt > VLDBALLOCLIMIT) ? VLDBALLOCINCR : *alloccnt;
2529 (nvldbentry *) realloc(*VldbentryFirst,
2530 (*alloccnt + allo) * sizeof(nvldbentry));
2534 *VldbentryFirst = vldbentries->nbulkentries_val = reall;
2535 *Vldbentry = *VldbentryFirst + *alloccnt;
2536 *VldbentryLast = *Vldbentry + allo;
2539 vlentry_to_nvldbentry(entry, *Vldbentry);
2540 (*Vldbentry)->matchindex = (matchtype << 16) + matchindex;
2543 vldbentries->nbulkentries_len++;
2548 /* Common code to actually remove a vldb entry from the database. */
2550 RemoveEntry(trans, entryptr, tentry)
2551 struct ubik_trans *trans;
2553 struct nvlentry *tentry;
2555 register int errorcode;
2557 if (errorcode = UnthreadVLentry(trans, entryptr, tentry))
2559 if (errorcode = FreeBlock(trans, entryptr))
2565 ReleaseEntry(tentry, releasetype)
2566 struct nvlentry *tentry;
2567 afs_int32 releasetype;
2569 if (releasetype & LOCKREL_TIMESTAMP)
2570 tentry->LockTimestamp = 0;
2571 if (releasetype & LOCKREL_OPCODE)
2572 tentry->flags &= ~VLOP_ALLOPERS;
2573 if (releasetype & LOCKREL_AFSID)
2574 tentry->LockAfsId = 0;
2578 /* Verify that the incoming vldb entry is valid; multi type of error codes are returned. */
2580 check_vldbentry(aentry)
2581 struct vldbentry *aentry;
2585 if (InvalidVolname(aentry->name))
2587 if (aentry->nServers <= 0 || aentry->nServers > OMAXNSERVERS)
2588 return VL_BADSERVER;
2589 for (i = 0; i < aentry->nServers; i++) {
2590 /* if (aentry->serverNumber[i] < 0 || aentry->serverNumber[i] > MAXSERVERID)
2591 return VL_BADSERVER; */
2592 if (aentry->serverPartition[i] < 0
2593 || aentry->serverPartition[i] > MAXPARTITIONID)
2594 return VL_BADPARTITION;
2595 if (aentry->serverFlags[i] < 0
2596 || aentry->serverFlags[i] > MAXSERVERFLAG)
2597 return VL_BADSERVERFLAG;
2603 check_nvldbentry(aentry)
2604 struct nvldbentry *aentry;
2608 if (InvalidVolname(aentry->name))
2610 if (aentry->nServers <= 0 || aentry->nServers > NMAXNSERVERS)
2611 return VL_BADSERVER;
2612 for (i = 0; i < aentry->nServers; i++) {
2613 /* if (aentry->serverNumber[i] < 0 || aentry->serverNumber[i] > MAXSERVERID)
2614 return VL_BADSERVER; */
2615 if (aentry->serverPartition[i] < 0
2616 || aentry->serverPartition[i] > MAXPARTITIONID)
2617 return VL_BADPARTITION;
2618 if (aentry->serverFlags[i] < 0
2619 || aentry->serverFlags[i] > MAXSERVERFLAG)
2620 return VL_BADSERVERFLAG;
2626 /* Convert from the external vldb entry representation to its internal
2627 (more compact) form. This call should not change the hash chains! */
2629 vldbentry_to_vlentry(atrans, VldbEntry, VlEntry)
2630 struct ubik_trans *atrans;
2631 struct vldbentry *VldbEntry;
2632 struct nvlentry *VlEntry;
2636 if (strcmp(VlEntry->name, VldbEntry->name))
2637 strncpy(VlEntry->name, VldbEntry->name, sizeof(VlEntry->name));
2638 for (i = 0; i < VldbEntry->nServers; i++) {
2639 serverindex = IpAddrToRelAddr(VldbEntry->serverNumber[i], atrans);
2640 if (serverindex == -1)
2641 return VL_BADSERVER;
2642 VlEntry->serverNumber[i] = serverindex;
2643 VlEntry->serverPartition[i] = VldbEntry->serverPartition[i];
2644 VlEntry->serverFlags[i] = VldbEntry->serverFlags[i];
2646 for (; i < OMAXNSERVERS; i++)
2647 VlEntry->serverNumber[i] = VlEntry->serverPartition[i] =
2648 VlEntry->serverFlags[i] = BADSERVERID;
2649 for (i = 0; i < MAXTYPES; i++)
2650 VlEntry->volumeId[i] = VldbEntry->volumeId[i];
2651 VlEntry->cloneId = VldbEntry->cloneId;
2652 VlEntry->flags = VldbEntry->flags;
2657 nvldbentry_to_vlentry(atrans, VldbEntry, VlEntry)
2658 struct ubik_trans *atrans;
2659 struct nvldbentry *VldbEntry;
2660 struct nvlentry *VlEntry;
2664 if (strcmp(VlEntry->name, VldbEntry->name))
2665 strncpy(VlEntry->name, VldbEntry->name, sizeof(VlEntry->name));
2666 for (i = 0; i < VldbEntry->nServers; i++) {
2667 serverindex = IpAddrToRelAddr(VldbEntry->serverNumber[i], atrans);
2668 if (serverindex == -1)
2669 return VL_BADSERVER;
2670 VlEntry->serverNumber[i] = serverindex;
2671 VlEntry->serverPartition[i] = VldbEntry->serverPartition[i];
2672 VlEntry->serverFlags[i] = VldbEntry->serverFlags[i];
2674 for (; i < NMAXNSERVERS; i++)
2675 VlEntry->serverNumber[i] = VlEntry->serverPartition[i] =
2676 VlEntry->serverFlags[i] = BADSERVERID;
2677 for (i = 0; i < MAXTYPES; i++)
2678 VlEntry->volumeId[i] = VldbEntry->volumeId[i];
2679 VlEntry->cloneId = VldbEntry->cloneId;
2680 VlEntry->flags = VldbEntry->flags;
2685 /* Update the vldb entry with the new fields as indicated by the value of the Mask entry in the updateentry structure. All necessary validation checks are performed. */
2687 get_vldbupdateentry(trans, blockindex, updateentry, VlEntry)
2688 struct ubik_trans *trans;
2689 afs_int32 blockindex;
2690 struct VldbUpdateEntry *updateentry;
2691 struct nvlentry *VlEntry;
2693 int i, j, errorcode, serverindex;
2695 if (updateentry->Mask & VLUPDATE_VOLUMENAME) {
2696 if (InvalidVolname(updateentry->name))
2698 if (errorcode = UnhashVolname(trans, blockindex, VlEntry))
2700 strncpy(VlEntry->name, updateentry->name, sizeof(VlEntry->name));
2701 HashVolname(trans, blockindex, VlEntry);
2704 if (updateentry->Mask & VLUPDATE_VOLNAMEHASH) {
2705 if (errorcode = UnhashVolname(trans, blockindex, VlEntry)) {
2706 if (errorcode != VL_NOENT)
2709 HashVolname(trans, blockindex, VlEntry);
2712 if (updateentry->Mask & VLUPDATE_FLAGS) {
2713 VlEntry->flags = updateentry->flags;
2715 if (updateentry->Mask & VLUPDATE_CLONEID) {
2716 VlEntry->cloneId = updateentry->cloneId;
2718 if (updateentry->Mask & VLUPDATE_RWID) {
2719 if (errorcode = UnhashVolid(trans, RWVOL, blockindex, VlEntry)) {
2720 if (errorcode != VL_NOENT)
2723 VlEntry->volumeId[RWVOL] = updateentry->spares3; /* rw id */
2724 if (errorcode = HashVolid(trans, RWVOL, blockindex, VlEntry))
2727 if (updateentry->Mask & VLUPDATE_READONLYID) {
2728 if (errorcode = UnhashVolid(trans, ROVOL, blockindex, VlEntry)) {
2729 if (errorcode != VL_NOENT)
2732 VlEntry->volumeId[ROVOL] = updateentry->ReadOnlyId;
2733 if (errorcode = HashVolid(trans, ROVOL, blockindex, VlEntry))
2736 if (updateentry->Mask & VLUPDATE_BACKUPID) {
2737 if (errorcode = UnhashVolid(trans, BACKVOL, blockindex, VlEntry)) {
2738 if (errorcode != VL_NOENT)
2741 VlEntry->volumeId[BACKVOL] = updateentry->BackupId;
2742 if (errorcode = HashVolid(trans, BACKVOL, blockindex, VlEntry))
2745 if (updateentry->Mask & VLUPDATE_REPSITES) {
2746 if (updateentry->nModifiedRepsites <= 0
2747 || updateentry->nModifiedRepsites > OMAXNSERVERS)
2748 return VL_BADSERVER;
2749 for (i = 0; i < updateentry->nModifiedRepsites; i++) {
2750 /* if (updateentry->RepsitesTargetServer[i] < 0 || updateentry->RepsitesTargetServer[i] > MAXSERVERID)
2751 return VL_BADSERVER; */
2752 if (updateentry->RepsitesTargetPart[i] < 0
2753 || updateentry->RepsitesTargetPart[i] > MAXPARTITIONID)
2754 return VL_BADPARTITION;
2755 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_DELETE) {
2757 repsite_exists(VlEntry,
2758 IpAddrToRelAddr(updateentry->
2759 RepsitesTargetServer[i],
2761 updateentry->RepsitesTargetPart[i])) !=
2763 repsite_compress(VlEntry, j);
2765 return VL_NOREPSERVER;
2767 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_ADD) {
2768 /* if (updateentry->RepsitesNewServer[i] < 0 || updateentry->RepsitesNewServer[i] > MAXSERVERID)
2769 return VL_BADSERVER; */
2770 if (updateentry->RepsitesNewPart[i] < 0
2771 || updateentry->RepsitesNewPart[i] > MAXPARTITIONID)
2772 return VL_BADPARTITION;
2775 IpAddrToRelAddr(updateentry->RepsitesNewServer[i],
2777 updateentry->RepsitesNewPart[i]) != -1)
2778 return VL_DUPREPSERVER;
2780 VlEntry->serverNumber[j] != BADSERVERID
2781 && j < OMAXNSERVERS; j++);
2782 if (j >= OMAXNSERVERS)
2785 IpAddrToRelAddr(updateentry->RepsitesNewServer[i],
2787 return VL_BADSERVER;
2788 VlEntry->serverNumber[j] = serverindex;
2789 VlEntry->serverPartition[j] = updateentry->RepsitesNewPart[i];
2790 if (updateentry->RepsitesNewFlags[i] < 0
2791 || updateentry->RepsitesNewFlags[i] > MAXSERVERFLAG)
2792 return VL_BADSERVERFLAG;
2793 VlEntry->serverFlags[j] = updateentry->RepsitesNewFlags[i];
2795 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODSERV) {
2796 /*n if (updateentry->RepsitesNewServer[i] < 0 || updateentry->RepsitesNewServer[i] > MAXSERVERID)
2797 return VL_BADSERVER; */
2799 repsite_exists(VlEntry,
2800 IpAddrToRelAddr(updateentry->
2801 RepsitesTargetServer[i],
2803 updateentry->RepsitesTargetPart[i])) !=
2805 VlEntry->serverNumber[j] =
2806 IpAddrToRelAddr(updateentry->RepsitesNewServer[i],
2809 return VL_NOREPSERVER;
2811 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODPART) {
2812 if (updateentry->RepsitesNewPart[i] < 0
2813 || updateentry->RepsitesNewPart[i] > MAXPARTITIONID)
2814 return VL_BADPARTITION;
2816 repsite_exists(VlEntry,
2817 IpAddrToRelAddr(updateentry->
2818 RepsitesTargetServer[i],
2820 updateentry->RepsitesTargetPart[i])) !=
2822 VlEntry->serverPartition[j] =
2823 updateentry->RepsitesNewPart[i];
2825 return VL_NOREPSERVER;
2827 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODFLAG) {
2829 repsite_exists(VlEntry,
2830 IpAddrToRelAddr(updateentry->
2831 RepsitesTargetServer[i],
2833 updateentry->RepsitesTargetPart[i])) !=
2835 if (updateentry->RepsitesNewFlags[i] < 0
2836 || updateentry->RepsitesNewFlags[i] > MAXSERVERFLAG)
2837 return VL_BADSERVERFLAG;
2838 VlEntry->serverFlags[j] =
2839 updateentry->RepsitesNewFlags[i];
2841 return VL_NOREPSERVER;
2849 /* Check if the specified [server,partition] entry is found in the vldb entry's repsite table; it's offset in the table is returned, if it's present there. */
2851 repsite_exists(VlEntry, server, partition)
2852 struct nvlentry *VlEntry;
2853 int server, partition;
2857 for (i = 0; VlEntry->serverNumber[i] != BADSERVERID && i < OMAXNSERVERS;
2859 if ((VlEntry->serverNumber[i] == server)
2860 && (VlEntry->serverPartition[i] == partition))
2868 /* Repsite table compression: used when deleting a repsite entry so that all active repsite entries are on the top of the table. */
2870 repsite_compress(VlEntry, offset)
2871 struct nvlentry *VlEntry;
2874 int repsite_offset = offset;
2876 VlEntry->serverNumber[repsite_offset] != BADSERVERID
2877 && repsite_offset < OMAXNSERVERS - 1; repsite_offset++) {
2878 VlEntry->serverNumber[repsite_offset] =
2879 VlEntry->serverNumber[repsite_offset + 1];
2880 VlEntry->serverPartition[repsite_offset] =
2881 VlEntry->serverPartition[repsite_offset + 1];
2882 VlEntry->serverFlags[repsite_offset] =
2883 VlEntry->serverFlags[repsite_offset + 1];
2885 VlEntry->serverNumber[repsite_offset] = BADSERVERID;
2889 /* Convert from the internal (compacted) vldb entry to the external representation used by the interface. */
2891 vlentry_to_vldbentry(VlEntry, VldbEntry)
2892 struct nvlentry *VlEntry;
2893 struct vldbentry *VldbEntry;
2897 memset(VldbEntry, 0, sizeof(struct vldbentry));
2898 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
2899 for (i = 0; i < OMAXNSERVERS; i++) {
2900 if (VlEntry->serverNumber[i] == BADSERVERID)
2902 if ((HostAddress[j = VlEntry->serverNumber[i]] & 0xff000000) ==
2904 struct extentaddr *exp;
2907 base = (HostAddress[j] >> 16) & 0xff;
2908 index = HostAddress[j] & 0x0000ffff;
2909 exp = &ex_addr[base][index];
2910 /* For now return the first ip address back */
2911 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2912 if (exp->ex_addrs[j]) {
2913 VldbEntry->serverNumber[i] = ntohl(exp->ex_addrs[j]);
2918 VldbEntry->serverNumber[i] =
2919 HostAddress[VlEntry->serverNumber[i]];
2920 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
2921 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
2923 VldbEntry->nServers = i;
2924 for (i = 0; i < MAXTYPES; i++)
2925 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
2926 VldbEntry->cloneId = VlEntry->cloneId;
2927 VldbEntry->flags = VlEntry->flags;
2931 /* Convert from the internal (compacted) vldb entry to the external representation used by the interface. */
2933 vlentry_to_nvldbentry(VlEntry, VldbEntry)
2934 struct nvlentry *VlEntry;
2935 struct nvldbentry *VldbEntry;
2939 memset(VldbEntry, 0, sizeof(struct vldbentry));
2940 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
2941 for (i = 0; i < NMAXNSERVERS; i++) {
2942 if (VlEntry->serverNumber[i] == BADSERVERID)
2944 if ((HostAddress[j = VlEntry->serverNumber[i]] & 0xff000000) ==
2946 struct extentaddr *exp;
2949 base = (HostAddress[j] >> 16) & 0xff;
2950 index = HostAddress[j] & 0x0000ffff;
2951 exp = &ex_addr[base][index];
2952 /* For now return the first ip address back */
2953 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2954 if (exp->ex_addrs[j]) {
2955 VldbEntry->serverNumber[i] = ntohl(exp->ex_addrs[j]);
2960 VldbEntry->serverNumber[i] =
2961 HostAddress[VlEntry->serverNumber[i]];
2962 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
2963 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
2965 VldbEntry->nServers = i;
2966 for (i = 0; i < MAXTYPES; i++)
2967 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
2968 VldbEntry->cloneId = VlEntry->cloneId;
2969 VldbEntry->flags = VlEntry->flags;
2973 vlentry_to_uvldbentry(VlEntry, VldbEntry)
2974 struct nvlentry *VlEntry;
2975 struct uvldbentry *VldbEntry;
2979 memset(VldbEntry, 0, sizeof(struct vldbentry));
2980 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
2981 for (i = 0; i < NMAXNSERVERS; i++) {
2982 if (VlEntry->serverNumber[i] == BADSERVERID)
2984 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
2985 VldbEntry->serverUnique[i] = 0;
2986 if ((HostAddress[j = VlEntry->serverNumber[i]] & 0xff000000) ==
2988 struct extentaddr *exp;
2992 base = (HostAddress[j] >> 16) & 0xff;
2993 index = HostAddress[j] & 0x0000ffff;
2994 exp = &ex_addr[base][index];
2995 tuuid = exp->ex_hostuuid;
2996 afs_ntohuuid(&tuuid);
2997 VldbEntry->serverFlags[i] |= VLSERVER_FLAG_UUID;
2998 VldbEntry->serverNumber[i] = tuuid;
2999 VldbEntry->serverUnique[i] = ntohl(exp->ex_uniquifier);
3001 VldbEntry->serverNumber[i].time_low =
3002 HostAddress[VlEntry->serverNumber[i]];
3004 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
3007 VldbEntry->nServers = i;
3008 for (i = 0; i < MAXTYPES; i++)
3009 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
3010 VldbEntry->cloneId = VlEntry->cloneId;
3011 VldbEntry->flags = VlEntry->flags;
3014 #define LEGALCHARS ".ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
3017 /* Verify that the volname is a valid volume name. */
3019 InvalidVolname(volname)
3026 slen = strlen(volname);
3027 if (slen >= VL_MAXNAMELEN)
3029 return (slen != strspn(volname, map));
3033 /* Verify that the given volume type is valid. */
3035 InvalidVoltype(voltype)
3038 if (voltype != RWVOL && voltype != ROVOL && voltype != BACKVOL)
3045 InvalidOperation(voloper)
3048 if (voloper != VLOP_MOVE && voloper != VLOP_RELEASE
3049 && voloper != VLOP_BACKUP && voloper != VLOP_DELETE
3050 && voloper != VLOP_DUMP)
3056 InvalidReleasetype(releasetype)
3057 afs_int32 releasetype;
3059 if ((releasetype & LOCKREL_TIMESTAMP) || (releasetype & LOCKREL_OPCODE)
3060 || (releasetype & LOCKREL_AFSID))
3066 IpAddrToRelAddr(ipaddr, atrans)
3067 struct ubik_trans *atrans;
3068 register afs_uint32 ipaddr;
3071 register afs_int32 code, base, index;
3072 struct extentaddr *exp;
3074 for (i = 0; i <= MAXSERVERID; i++) {
3075 if (HostAddress[i] == ipaddr)
3077 if ((HostAddress[i] & 0xff000000) == 0xff000000) {
3078 base = (HostAddress[i] >> 16) & 0xff;
3079 index = HostAddress[i] & 0x0000ffff;
3080 if (base >= VL_MAX_ADDREXTBLKS) {
3082 ("Internal error: Multihome extent base is too large. Base %d index %d\n",
3084 return -1; /* EINVAL */
3086 if (index >= VL_MHSRV_PERBLK) {
3088 ("Internal error: Multihome extent index is too large. Base %d index %d\n",
3090 return -1; /* EINVAL */
3092 if (!ex_addr[base]) {
3094 ("Internal error: Multihome extent does not exist. Base %d\n",
3096 return -1; /* EINVAL */
3098 exp = &ex_addr[base][index];
3099 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
3100 if (exp->ex_addrs[j] && (ntohl(exp->ex_addrs[j]) == ipaddr)) {
3107 /* allocate the new server a server id pronto */
3109 for (i = 0; i <= MAXSERVERID; i++) {
3110 if (cheader.IpMappedAddr[i] == 0) {
3111 cheader.IpMappedAddr[i] = htonl(ipaddr);
3114 DOFFSET(0, &cheader, &cheader.IpMappedAddr[i]),
3115 (char *)&cheader.IpMappedAddr[i],
3117 HostAddress[i] = ipaddr;
3128 ChangeIPAddr(ipaddr1, ipaddr2, atrans)
3129 struct ubik_trans *atrans;
3130 register afs_uint32 ipaddr1, ipaddr2;
3134 struct extentaddr *exp;
3135 int base, index, mhidx;
3137 afs_int32 blockindex, count;
3139 struct nvlentry tentry;
3142 return VL_CREATEFAIL;
3144 /* Don't let addr change to 256.*.*.* : Causes internal error below */
3145 if ((ipaddr2 & 0xff000000) == 0xff000000)
3146 return (VL_BADSERVER);
3148 /* If we are removing an address, ip1 will be -1 and ip2 will be
3149 * the original address. This prevents an older revision vlserver
3150 * from removing the IP address (won't find server 0xfffffff in
3151 * the VLDB). An older revision vlserver does not have the check
3152 * to see if any volumes exist on the server being removed.
3154 if (ipaddr1 == 0xffffffff) {
3159 for (i = 0; i <= MAXSERVERID; i++) {
3160 if ((HostAddress[i] & 0xff000000) == 0xff000000) {
3161 base = (HostAddress[i] >> 16) & 0xff;
3162 index = HostAddress[i] & 0x0000ffff;
3163 if ((base >= VL_MAX_ADDREXTBLKS) || (index >= VL_MHSRV_PERBLK)) {
3165 ("Internal error: Multihome extent addr is too large. Base %d index %d\n",
3167 return -1; /* EINVAL */
3170 exp = &ex_addr[base][index];
3171 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
3172 if (!exp->ex_addrs[mhidx])
3174 if (ntohl(exp->ex_addrs[mhidx]) == ipaddr1)
3177 if (mhidx < VL_MAXIPADDRS_PERMH) {
3180 } else if (HostAddress[i] == ipaddr1) {
3186 if (i >= MAXSERVERID) {
3187 return VL_NOENT; /* not found */
3190 /* If we are removing a server entry, a volume cannot
3191 * exist on the server. If one does, don't remove the
3192 * server entry: return error "volume entry exists".
3195 for (blockindex = NextEntry(atrans, 0, &tentry, &count); blockindex;
3196 blockindex = NextEntry(atrans, blockindex, &tentry, &count)) {
3197 if (++pollcount > 50) {
3201 for (j = 0; j < NMAXNSERVERS; j++) {
3202 if (tentry.serverNumber[j] == BADSERVERID)
3204 if (tentry.serverNumber[j] == i) {
3211 /* Log a message saying we are changing/removing an IP address */
3213 ("The following IP address is being %s:\n",
3214 (ipaddr2 ? "changed" : "removed")));
3215 printf(" entry %d: ", i);
3218 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
3219 if (!exp->ex_addrs[mhidx])
3223 PADDR(ntohl(exp->ex_addrs[mhidx]));
3235 /* Change the registered uuuid addresses */
3237 memset(&tuuid, 0, sizeof(afsUUID));
3238 afs_htonuuid(&tuuid);
3239 exp->ex_hostuuid = tuuid;
3242 DOFFSET(ntohl(ex_addr[0]->ex_contaddrs[base]),
3243 (char *)ex_addr[base], (char *)exp),
3244 (char *)&tuuid, sizeof(tuuid));
3249 /* Now change the host address entry */
3250 cheader.IpMappedAddr[i] = htonl(ipaddr2);
3252 vlwrite(atrans, DOFFSET(0, &cheader, &cheader.IpMappedAddr[i]),
3254 &cheader.IpMappedAddr[i], sizeof(afs_int32));
3255 HostAddress[i] = ipaddr2;
3262 /* see if the vlserver is back yet */
3264 SVL_ProbeServer(rxcall)
3265 struct rx_call *rxcall;