1 /* Copyright (C) 1995 Transarc Corporation - All rights reserved */
3 * (C) COPYRIGHT IBM CORPORATION 1987, 1988
4 * LICENSED MATERIALS - PROPERTY OF IBM
11 #include <afs/afsutil.h>
18 #include <netinet/in.h>
22 #include "afs/audit.h"
29 extern struct afsconf_dir *vldb_confdir;
30 extern struct ubik_dbase *VL_dbase;
31 struct vlheader cheader; /* kept in network byte order */
32 extern afs_uint32 HostAddress[]; /* host addresses kept in host byte order */
34 struct extentaddr *ex_addr[VL_MAX_ADDREXTBLKS] = { 0, 0, 0, 0};
35 static char rxinfo_str[128]; /* Need rxinfo string to be non-local */
36 #define ABORT(c) { errorcode = (c); goto abort; }
38 #define END(c) { errorcode = (c); goto end; }
40 #define VLDBALLOCLIMIT 10000
41 #define VLDBALLOCINCR 2048
43 static int put_attributeentry();
44 static int put_nattributeentry();
45 static int RemoveEntry();
46 static ReleaseEntry();
47 static int check_vldbentry();
48 static int check_nvldbentry();
49 static int vldbentry_to_vlentry();
50 static int nvldbentry_to_vlentry();
51 static get_vldbupdateentry();
52 static int repsite_exists();
53 static repsite_compress();
54 static vlentry_to_vldbentry();
55 static vlentry_to_nvldbentry();
56 static vlentry_to_uvldbentry();
57 static int InvalidVolname();
58 static int InvalidVoltype();
59 static int InvalidOperation();
60 static int InvalidReleasetype();
61 static int IpAddrToRelAddr();
62 static int ChangeIPAddr();
65 struct rx_call *rxcall;
68 register struct rx_connection *tconn;
73 struct in_addr hostAddr;
75 tconn = rx_ConnectionOf(rxcall);
76 hostAddr.s_addr = rx_HostOf(rx_PeerOf(tconn));
77 code = rxkad_GetServerInfo(rxcall->conn, (afs_int32 *) 0, &exp, tname, tinst, tcell, (afs_int32 *) 0);
79 sprintf(rxinfo_str,"%s %s", inet_ntoa(hostAddr), tname);
81 sprintf(rxinfo_str,"%s noauth",inet_ntoa(hostAddr));
85 /* This is called to initialize the database, set the appropriate locks and make sure that the vldb header is valid */
86 int Init_VLdbase (trans, locktype, this_op)
87 struct ubik_trans **trans;
88 int locktype; /* indicate read or write transaction */
91 int errorcode=0, pass, wl;
93 for (pass=1; pass<=3; pass++) {
94 if (pass == 2) { /* take write lock to rebuild the db */
95 errorcode = ubik_BeginTrans (VL_dbase, UBIK_WRITETRANS, trans);
98 else if (locktype == LOCKREAD) {
99 errorcode = ubik_BeginTransReadAny (VL_dbase, UBIK_READTRANS, trans);
103 errorcode = ubik_BeginTrans (VL_dbase, UBIK_WRITETRANS, trans);
109 errorcode = ubik_SetLock (*trans, 1, 1, locktype);
112 ubik_AbortTrans (*trans);
116 /* check that dbase is initialized and setup cheader */
117 /* 2nd pass we try to rebuild the header */
118 errorcode = CheckInit(*trans, ((pass==2)?1:0));
119 if (!errorcode && wl && extent_mod)
120 errorcode = readExtents(*trans); /* Fix the mh extent blocks */
123 ubik_AbortTrans(*trans);
124 /* Only rebuld if the database is empty */
125 /* Exit if can't rebuild */
126 if ((pass == 1) && (errorcode != VL_EMPTY)) return errorcode;
127 if (pass == 2) return errorcode;
129 else { /* No errorcode */
131 ubik_EndTrans(*trans); /* Rebuilt db. End trans, then retake original lock */
134 break; /* didn't rebuild and successful - exit */
142 /* Create a new vldb entry; both new volume id and name must be unique (non-existant in vldb). */
144 VL_CreateEntry(rxcall, newentry)
145 struct rx_call *rxcall;
146 struct vldbentry *newentry;
147 { struct ubik_trans *trans;
148 afs_int32 errorcode, blockindex;
149 struct nvlentry tentry;
151 COUNT_REQ (VLCREATEENTRY);
152 if (!afsconf_SuperUser(vldb_confdir, rxcall, (char *)0)) {
157 /* Do some validity tests on new entry */
158 if ( (errorcode = check_vldbentry(newentry))
159 || (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
162 VLog(1, ("OCreate Volume %d %s\n", newentry->volumeId[RWVOL], rxinfo(rxcall)));
163 /* XXX shouldn't we check to see if the r/o volume is duplicated? */
164 if (newentry->volumeId[RWVOL]
165 && FindByID(trans, newentry->volumeId[RWVOL], RWVOL, &tentry,
166 &errorcode)) { /* entry already exists, we fail */
167 errorcode = VL_IDEXIST;
169 } else if (errorcode) {
173 /* Is this following check (by volume name) necessary?? */
174 /* If entry already exists, we fail */
175 if (FindByName(trans, newentry->name, &tentry, &errorcode)) {
176 errorcode = VL_NAMEEXIST;
178 } else if (errorcode) {
182 blockindex = AllocBlock(trans, &tentry);
183 if (blockindex == 0) {
184 errorcode = VL_CREATEFAIL;
188 bzero(&tentry, sizeof(struct nvlentry));
189 /* Convert to its internal representation; both in host byte order */
190 if (errorcode = vldbentry_to_vlentry(trans, newentry, &tentry)) {
191 FreeBlock(trans, blockindex);
195 /* Actually insert the entry in vldb */
196 errorcode = ThreadVLentry(trans, blockindex, &tentry);
198 FreeBlock(trans, blockindex);
202 errorcode = ubik_EndTrans(trans);
208 ubik_AbortTrans(trans);
211 osi_auditU (rxcall, VLCreateEntryEvent, errorcode,
212 AUD_STR, (newentry ? newentry->name : (char *)0), AUD_END);
217 VL_CreateEntryN(rxcall, newentry)
218 struct rx_call *rxcall;
219 struct nvldbentry *newentry;
220 { struct ubik_trans *trans;
221 afs_int32 errorcode, blockindex;
222 struct nvlentry tentry;
224 COUNT_REQ (VLCREATEENTRYN);
225 if (!afsconf_SuperUser(vldb_confdir, rxcall, (char *)0)) {
230 /* Do some validity tests on new entry */
231 if ( (errorcode = check_nvldbentry(newentry))
232 || (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
235 VLog(1, ("Create Volume %d %s\n", newentry->volumeId[RWVOL], rxinfo(rxcall)));
236 /* XXX shouldn't we check to see if the r/o volume is duplicated? */
237 if (newentry->volumeId[RWVOL]
238 && FindByID(trans, newentry->volumeId[RWVOL], RWVOL, &tentry,
239 &errorcode)) { /* entry already exists, we fail */
240 errorcode = VL_IDEXIST;
242 } else if (errorcode) {
246 /* Is this following check (by volume name) necessary?? */
247 /* If entry already exists, we fail */
248 if (FindByName(trans, newentry->name, &tentry, &errorcode)) {
249 errorcode = VL_NAMEEXIST;
251 } else if (errorcode) {
255 blockindex = AllocBlock(trans, &tentry);
256 if (blockindex == 0) {
257 errorcode = VL_CREATEFAIL;
261 bzero(&tentry, sizeof(struct nvlentry));
262 /* Convert to its internal representation; both in host byte order */
263 if (errorcode = nvldbentry_to_vlentry(trans, newentry, &tentry)) {
264 FreeBlock(trans, blockindex);
268 /* Actually insert the entry in vldb */
269 errorcode = ThreadVLentry(trans, blockindex, &tentry);
271 FreeBlock(trans, blockindex);
275 errorcode = ubik_EndTrans(trans);
281 ubik_AbortTrans(trans);
284 osi_auditU (rxcall, VLCreateEntryEvent, errorcode,
285 AUD_STR, (newentry ? newentry->name : (char *)0), AUD_END);
290 VL_ChangeAddr(rxcall, ip1, ip2)
291 struct rx_call *rxcall;
293 { struct ubik_trans *trans;
294 afs_int32 errorcode, blockindex;
295 struct nvlentry tentry;
297 COUNT_REQ (VLCHANGEADDR);
298 if (!afsconf_SuperUser(vldb_confdir, rxcall, (char *)0)) {
303 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
306 VLog(1, ("Change Addr %d -> %d %s\n", ip1, ip2, rxinfo(rxcall)));
307 if (errorcode = ChangeIPAddr(ip1, ip2, trans))
310 errorcode = ubik_EndTrans(trans);
316 ubik_AbortTrans(trans);
319 osi_auditU (rxcall, VLChangeAddrEvent, errorcode, AUD_LONG, ip1,
320 AUD_LONG, ip2, AUD_END);
324 /* Delete a vldb entry given the volume id. */
325 VL_DeleteEntry(rxcall, volid, voltype)
326 struct rx_call *rxcall;
329 { struct ubik_trans *trans;
330 afs_int32 blockindex, errorcode;
331 struct nvlentry tentry;
333 COUNT_REQ (VLDELETEENTRY);
334 if (!afsconf_SuperUser(vldb_confdir, rxcall, (char *)0))
337 if ((voltype != -1 ) && (InvalidVoltype(voltype)))
338 END( VL_BADVOLTYPE );
340 if (errorcode = Init_VLdbase (&trans, LOCKWRITE, this_op))
343 VLog(1, ("Delete Volume %d %s\n", volid, rxinfo(rxcall)));
344 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
345 if (blockindex == 0) { /* volid not found */
346 if (!errorcode) errorcode = VL_NOENT;
350 if (tentry.flags & VLDELETED) { /* Already deleted; return */
351 ABORT( VL_ENTDELETED );
353 if (errorcode = RemoveEntry(trans, blockindex, &tentry)) {
356 errorcode = (ubik_EndTrans(trans));
361 ubik_AbortTrans(trans);
364 osi_auditU (rxcall, VLDeleteEntryEvent, errorcode, AUD_LONG, volid, AUD_END);
369 /* Get a vldb entry given its volume id; make sure it's not a deleted entry. */
370 GetEntryByID (rxcall, volid, voltype, aentry, new, this_op)
371 struct rx_call *rxcall;
373 afs_int32 voltype, new, this_op;
374 char *aentry; /* entry data copied here */
375 { struct ubik_trans *trans;
376 afs_int32 blockindex, errorcode;
377 struct nvlentry tentry;
379 if ((voltype != -1 ) && (InvalidVoltype(voltype)))
380 return VL_BADVOLTYPE;
381 if (errorcode = Init_VLdbase (&trans, LOCKREAD, this_op))
384 VLog(5, ("GetVolumeByID %d (%d) %s\n", volid, new, rxinfo(rxcall)));
385 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
386 if (blockindex == 0) { /* entry not found */
387 if (!errorcode) errorcode = VL_NOENT;
389 ubik_AbortTrans (trans);
392 if (tentry.flags & VLDELETED) { /* Entry is deleted! */
394 ubik_AbortTrans (trans);
395 return VL_ENTDELETED;
397 /* Convert from the internal to external form */
399 vlentry_to_nvldbentry(&tentry, (struct nvldbentry *)aentry);
401 vlentry_to_uvldbentry(&tentry, (struct uvldbentry *)aentry);
403 vlentry_to_vldbentry(&tentry, (struct vldbentry *)aentry);
404 return(ubik_EndTrans(trans));
407 VL_GetEntryByID (rxcall, volid, voltype, aentry)
408 struct rx_call *rxcall;
409 afs_int32 volid, voltype;
410 vldbentry *aentry; /* entry data copied here */
412 COUNT_REQ (VLGETENTRYBYID);
413 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 0, this_op));
416 VL_GetEntryByIDN (rxcall, volid, voltype, aentry)
417 struct rx_call *rxcall;
418 afs_int32 volid, voltype;
419 nvldbentry *aentry; /* entry data copied here */
421 COUNT_REQ (VLGETENTRYBYIDN);
422 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 1, this_op));
425 VL_GetEntryByIDU (rxcall, volid, voltype, aentry)
426 struct rx_call *rxcall;
427 afs_int32 volid, voltype;
428 uvldbentry *aentry; /* entry data copied here */
430 COUNT_REQ (VLGETENTRYBYIDU);
431 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 2, this_op));
436 /* returns true if the id is a decimal integer, in which case we interpret it
437 as an id. make the cache manager much simpler */
438 static int NameIsId(aname)
439 register char *aname; {
441 while (tc = *aname++) {
442 if (tc > '9' || tc < '0') return 0;
447 /* Get a vldb entry given the volume's name; of course, very similar to VLGetEntryByID() above. */
448 GetEntryByName (rxcall, volname, aentry, new, this_op)
449 struct rx_call *rxcall;
451 char *aentry; /* entry data copied here */
453 { struct ubik_trans *trans;
454 afs_int32 blockindex, errorcode;
455 struct nvlentry tentry;
457 if (NameIsId(volname)) {
458 return GetEntryByID(rxcall, atoi(volname), -1, aentry, new, this_op);
460 if (InvalidVolname(volname))
462 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
464 VLog(5, ("GetVolumeByName %s (%d) %s\n", volname, new, rxinfo(rxcall)));
465 blockindex = FindByName(trans, volname, &tentry, &errorcode);
466 if (blockindex == 0) { /* entry not found */
467 if (!errorcode) errorcode = VL_NOENT;
469 ubik_AbortTrans(trans);
472 if (tentry.flags & VLDELETED) { /* Entry is deleted */
474 ubik_AbortTrans(trans);
475 return VL_ENTDELETED;
477 /* Convert to external entry representation */
479 vlentry_to_nvldbentry(&tentry, (struct nvldbentry *)aentry);
481 vlentry_to_uvldbentry(&tentry, (struct uvldbentry *)aentry);
483 vlentry_to_vldbentry(&tentry, (struct vldbentry *)aentry);
484 return(ubik_EndTrans(trans));
487 VL_GetEntryByNameO (rxcall, volname, aentry)
488 struct rx_call *rxcall;
490 struct vldbentry *aentry; /* entry data copied here */
492 COUNT_REQ (VLGETENTRYBYNAME);
493 return (GetEntryByName(rxcall, volname, (char *)aentry, 0, this_op));
497 VL_GetEntryByNameN (rxcall, volname, aentry)
498 struct rx_call *rxcall;
500 struct nvldbentry *aentry; /* entry data copied here */
502 COUNT_REQ (VLGETENTRYBYNAMEN);
503 return (GetEntryByName(rxcall, volname, (char *)aentry, 1, this_op));
506 VL_GetEntryByNameU (rxcall, volname, aentry)
507 struct rx_call *rxcall;
509 struct uvldbentry *aentry; /* entry data copied here */
511 COUNT_REQ (VLGETENTRYBYNAMEU);
512 return (GetEntryByName(rxcall, volname, (char *)aentry, 2, this_op));
517 /* Get the current value of the maximum volume id and bump the volume id counter by Maxvolidbump. */
518 VL_GetNewVolumeId (rxcall, Maxvolidbump, newvolumeid)
519 struct rx_call *rxcall;
520 afs_int32 Maxvolidbump;
521 afs_int32 *newvolumeid;
522 { register afs_int32 errorcode, maxvolumeid;
523 struct ubik_trans *trans;
525 COUNT_REQ (VLGETNEWVOLUMEID);
526 if (!afsconf_SuperUser(vldb_confdir, rxcall, (char *)0))
529 if (Maxvolidbump < 0 || Maxvolidbump > MAXBUMPCOUNT)
530 END ( VL_BADVOLIDBUMP );
532 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
535 *newvolumeid = maxvolumeid = ntohl(cheader.vital_header.MaxVolumeId);
536 maxvolumeid += Maxvolidbump;
537 VLog(1, ("GetNewVolid newmax=%d %s\n", maxvolumeid, rxinfo(rxcall)));
538 cheader.vital_header.MaxVolumeId = htonl(maxvolumeid);
539 if (write_vital_vlheader(trans)) {
542 errorcode = (ubik_EndTrans(trans));
547 ubik_AbortTrans(trans);
550 osi_auditU (rxcall, VLGetNewVolumeIdEvent, errorcode, AUD_END);
555 /* Simple replace the contents of the vldb entry, volid, with
556 * newentry. No individual checking/updating per field (alike
557 * VLUpdateEntry) is done. */
559 VL_ReplaceEntry (rxcall, volid, voltype, newentry, releasetype)
560 struct rx_call *rxcall;
563 struct vldbentry *newentry;
564 afs_int32 releasetype;
565 { struct ubik_trans *trans;
566 afs_int32 blockindex, errorcode, typeindex;
568 int hashVol[MAXTYPES];
569 struct nvlentry tentry;
571 COUNT_REQ (VLREPLACEENTRY);
572 for(typeindex = 0; typeindex < MAXTYPES; typeindex++)
573 hashVol[typeindex] = 0;
575 if (!afsconf_SuperUser(vldb_confdir, rxcall, (char *)0))
578 if (errorcode = check_vldbentry(newentry))
581 if (voltype != -1 && InvalidVoltype(voltype))
582 END ( VL_BADVOLTYPE );
584 if (releasetype && InvalidReleasetype(releasetype))
585 END( VL_BADRELLOCKTYPE );
586 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
589 VLog(1, ("OReplace Volume %d %s\n", volid, rxinfo(rxcall)));
590 /* find vlentry we're changing */
591 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
592 if (blockindex == 0) { /* entry not found */
593 if (!errorcode) errorcode = VL_NOENT;
597 /* check that we're not trying to change the RW vol ID */
598 if (newentry->volumeId[RWVOL] != tentry.volumeId[RWVOL]) {
599 ABORT( VL_BADENTRY );
602 /* unhash volid entries if they're disappearing or changing.
603 * Remember if we need to hash in the new value (we don't have to
604 * rehash if volid stays same */
605 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
606 if (tentry.volumeId[typeindex] != newentry->volumeId[typeindex]) {
607 if (tentry.volumeId[typeindex])
608 if (errorcode = UnhashVolid(trans, typeindex, blockindex,
612 /* we must rehash new id if the id is different and the ID is nonzero */
613 hashVol[typeindex] = 1; /* must rehash this guy if he exists */
617 /* Rehash volname if it changes */
618 if (strcmp(newentry->name, tentry.name)) { /* Name changes; redo hashing */
619 if (errorcode = UnhashVolname(trans, blockindex, &tentry)) {
625 /* after this, tentry is new entry, not old one. vldbentry_to_vlentry
626 doesn't touch hash chains */
627 if (errorcode = vldbentry_to_vlentry(trans, newentry, &tentry)) {
631 for(typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
632 if (hashVol[typeindex] && tentry.volumeId[typeindex]) {
633 if (errorcode = HashVolid(trans, typeindex, blockindex, &tentry)) {
640 HashVolname(trans, blockindex, &tentry);
643 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
644 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
648 END (ubik_EndTrans(trans));
652 ubik_AbortTrans(trans);
655 osi_auditU (rxcall, VLReplaceVLEntryEvent, errorcode, AUD_LONG, volid, AUD_END);
659 VL_ReplaceEntryN (rxcall, volid, voltype, newentry, releasetype)
660 struct rx_call *rxcall;
663 struct nvldbentry *newentry;
664 afs_int32 releasetype;
665 { struct ubik_trans *trans;
666 afs_int32 blockindex, errorcode, typeindex;
668 int hashVol[MAXTYPES];
669 struct nvlentry tentry;
671 COUNT_REQ (VLREPLACEENTRYN);
672 for(typeindex = 0; typeindex < MAXTYPES; typeindex++)
673 hashVol[typeindex] = 0;
675 if (!afsconf_SuperUser(vldb_confdir, rxcall, (char *)0))
678 if (errorcode = check_nvldbentry(newentry))
681 if (voltype != -1 && InvalidVoltype(voltype))
682 END ( VL_BADVOLTYPE );
684 if (releasetype && InvalidReleasetype(releasetype))
685 END( VL_BADRELLOCKTYPE );
686 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
689 VLog(1, ("Replace Volume %d %s\n", volid, rxinfo(rxcall)));
690 /* find vlentry we're changing */
691 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
692 if (blockindex == 0) { /* entry not found */
693 if (!errorcode) errorcode = VL_NOENT;
697 /* check that we're not trying to change the RW vol ID */
698 if (newentry->volumeId[RWVOL] != tentry.volumeId[RWVOL]) {
699 ABORT( VL_BADENTRY );
702 /* unhash volid entries if they're disappearing or changing.
703 * Remember if we need to hash in the new value (we don't have to
704 * rehash if volid stays same */
705 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
706 if (tentry.volumeId[typeindex] != newentry->volumeId[typeindex]) {
707 if (tentry.volumeId[typeindex])
708 if (errorcode = UnhashVolid(trans, typeindex, blockindex,
712 /* we must rehash new id if the id is different and the ID is nonzero */
713 hashVol[typeindex] = 1; /* must rehash this guy if he exists */
717 /* Rehash volname if it changes */
718 if (strcmp(newentry->name, tentry.name)) { /* Name changes; redo hashing */
719 if (errorcode = UnhashVolname(trans, blockindex, &tentry)) {
725 /* after this, tentry is new entry, not old one. vldbentry_to_vlentry
726 doesn't touch hash chains */
727 if (errorcode = nvldbentry_to_vlentry(trans, newentry, &tentry)) {
731 for(typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
732 if (hashVol[typeindex] && tentry.volumeId[typeindex]) {
733 if (errorcode = HashVolid(trans, typeindex, blockindex, &tentry)) {
740 HashVolname(trans, blockindex, &tentry);
743 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
744 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
748 END (ubik_EndTrans(trans));
752 ubik_AbortTrans(trans);
755 osi_auditU (rxcall, VLReplaceVLEntryEvent, errorcode, AUD_LONG, volid, AUD_END);
760 /* 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. */
761 /* this routine may never have been tested; use replace entry instead unless you're brave */
762 VL_UpdateEntry (rxcall, volid, voltype, updateentry, releasetype)
763 struct rx_call *rxcall;
766 afs_int32 releasetype;
767 struct VldbUpdateEntry *updateentry; /* Update entry copied here */
768 { struct ubik_trans *trans;
769 afs_int32 blockindex, errorcode;
770 struct nvlentry tentry;
772 COUNT_REQ (VLUPDATEENTRY);
773 if (!afsconf_SuperUser(vldb_confdir, rxcall, (char *)0))
775 if ((voltype != -1 ) && (InvalidVoltype(voltype)))
776 END( VL_BADVOLTYPE );
777 if (releasetype && InvalidReleasetype(releasetype))
778 END( VL_BADRELLOCKTYPE );
779 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
782 VLog(1, ("Update Volume %d %s\n", volid, rxinfo(rxcall)));
783 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
784 if (blockindex == 0) { /* entry not found */
785 if (!errorcode) errorcode = VL_NOENT;
789 /* Do the actual updating of the entry, tentry. */
790 if (errorcode = get_vldbupdateentry(trans, blockindex, updateentry, &tentry)) {
794 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
795 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
798 END(ubik_EndTrans(trans));
802 ubik_AbortTrans(trans);
805 osi_auditU (rxcall, VLUpdateEntryEvent, errorcode, AUD_LONG, volid, AUD_END);
810 VL_UpdateEntryByName (rxcall, volname, updateentry, releasetype)
811 struct rx_call *rxcall;
813 afs_int32 releasetype;
814 struct VldbUpdateEntry *updateentry; /* Update entry copied here */
815 { struct ubik_trans *trans;
816 afs_int32 blockindex, errorcode;
817 struct nvlentry tentry;
819 COUNT_REQ (VLUPDATEENTRYBYNAME);
820 if (!afsconf_SuperUser(vldb_confdir, rxcall, (char *)0))
822 if (releasetype && InvalidReleasetype(releasetype))
823 END( VL_BADRELLOCKTYPE );
824 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
827 blockindex = FindByName(trans, volname, &tentry, &errorcode);
828 if (blockindex == 0) { /* entry not found */
829 if (!errorcode) errorcode = VL_NOENT;
833 /* Do the actual updating of the entry, tentry. */
834 if (errorcode = get_vldbupdateentry(trans, blockindex, updateentry, &tentry)) {
838 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
839 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
842 END(ubik_EndTrans(trans));
846 ubik_AbortTrans(trans);
849 osi_auditU (rxcall, VLUpdateEntryEvent, errorcode, AUD_LONG, -1, AUD_END);
854 /* Set a lock to the vldb entry for volid (of type voltype if not -1). */
855 VL_SetLock (rxcall, volid, voltype, voloper)
856 struct rx_call *rxcall;
860 { afs_int32 timestamp, blockindex, errorcode;
861 struct ubik_trans *trans;
862 struct nvlentry tentry;
864 COUNT_REQ(VLSETLOCK);
865 if (!afsconf_SuperUser(vldb_confdir, rxcall, (char *)0))
867 if ((voltype != -1 ) && (InvalidVoltype(voltype)))
868 END( VL_BADVOLTYPE );
869 if (InvalidOperation(voloper))
870 END( VL_BADVOLOPER );
871 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
874 VLog(1, ("SetLock Volume %d %s\n", volid, rxinfo(rxcall)));
875 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
876 if (blockindex == NULLO) {
877 if (!errorcode) errorcode = VL_NOENT;
880 if (tentry.flags & VLDELETED) {
881 ABORT( VL_ENTDELETED );
883 timestamp = FT_ApproxTime();
885 /* Check if entry is already locked; note that we unlock any entry
886 * locked more than MAXLOCKTIME seconds */
887 if ((tentry.LockTimestamp)
888 && ((timestamp - tentry.LockTimestamp) < MAXLOCKTIME)) {
889 ABORT( VL_ENTRYLOCKED );
892 /* Consider it an unlocked entry: set current timestamp, caller
893 * and active vol operation */
894 tentry.LockTimestamp = timestamp;
895 tentry.LockAfsId = 0; /* Not implemented yet */
896 if (tentry.flags & VLOP_RELEASE) {
897 ABORT( VL_RERELEASE );
899 tentry.flags &= ~VLOP_ALLOPERS; /* Clear any possible older operation bit */
900 tentry.flags |= voloper;
902 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
905 END(ubik_EndTrans(trans));
909 ubik_AbortTrans(trans);
912 osi_auditU (rxcall, VLSetLockEvent, errorcode, AUD_LONG, volid, AUD_END);
917 /* Release an already locked vldb entry. Releasetype determines what
918 * fields (afsid and/or volume operation) will be cleared along with
919 * the lock time stamp. */
921 VL_ReleaseLock (rxcall, volid, voltype, releasetype)
922 struct rx_call *rxcall;
925 afs_int32 releasetype;
926 { afs_int32 blockindex, errorcode;
927 struct ubik_trans *trans;
928 struct nvlentry tentry;
930 COUNT_REQ(VLRELEASELOCK);
931 if (!afsconf_SuperUser(vldb_confdir, rxcall, (char *)0))
933 if ((voltype != -1 ) && (InvalidVoltype(voltype)))
934 END( VL_BADVOLTYPE );
935 if (releasetype && InvalidReleasetype(releasetype))
936 END( VL_BADRELLOCKTYPE );
937 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
940 VLog(1, ("ReleaseLock Volume %d %s\n", volid, rxinfo(rxcall)));
941 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
942 if (blockindex == NULLO) {
943 if (!errorcode) errorcode = VL_NOENT;
946 if (tentry.flags & VLDELETED) {
947 ABORT( VL_ENTDELETED );
950 ReleaseEntry(&tentry, releasetype); /* Unlock the appropriate fields */
951 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
954 END(ubik_EndTrans(trans));
958 ubik_AbortTrans(trans);
961 osi_auditU (rxcall, VLReleaseLockEvent, errorcode, AUD_LONG, volid, AUD_END);
966 /* 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. */
967 VL_ListEntry (rxcall, previous_index, count, next_index, aentry)
968 struct rx_call *rxcall;
969 afs_int32 previous_index;
971 afs_int32 *next_index;
972 struct vldbentry *aentry;
974 struct ubik_trans *trans;
975 struct nvlentry tentry;
977 COUNT_REQ(VLLISTENTRY);
978 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
980 VLog(25, ("OListEntry index=%d %s\n", previous_index, rxinfo(rxcall)));
981 *next_index = NextEntry(trans, previous_index, &tentry, count);
983 vlentry_to_vldbentry(&tentry, aentry);
984 return(ubik_EndTrans(trans));
987 /* 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. */
988 VL_ListEntryN (rxcall, previous_index, count, next_index, aentry)
989 struct rx_call *rxcall;
990 afs_int32 previous_index;
992 afs_int32 *next_index;
993 struct nvldbentry *aentry;
995 struct ubik_trans *trans;
996 struct nvlentry tentry;
998 COUNT_REQ(VLLISTENTRYN);
999 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1001 VLog(25, ("ListEntry index=%d %s\n", previous_index, rxinfo(rxcall)));
1002 *next_index = NextEntry(trans, previous_index, &tentry, count);
1004 vlentry_to_nvldbentry(&tentry, aentry);
1005 return(ubik_EndTrans(trans));
1009 /* 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. */
1010 VL_ListAttributes(rxcall, attributes, nentries, vldbentries)
1011 struct rx_call *rxcall;
1012 struct VldbListByAttributes *attributes;
1013 afs_int32 *nentries;
1014 bulkentries *vldbentries;
1015 { int errorcode, allocCount = 0;
1016 struct ubik_trans *trans;
1017 struct nvlentry tentry;
1018 struct vldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1021 COUNT_REQ (VLLISTATTRIBUTES);
1022 vldbentries->bulkentries_val = 0;
1023 vldbentries->bulkentries_len = *nentries = 0;
1024 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1026 allocCount = VLDBALLOCCOUNT;
1027 Vldbentry = VldbentryFirst = vldbentries->bulkentries_val = (vldbentry *)malloc(allocCount * sizeof(vldbentry));
1028 if (Vldbentry == NULL) {
1030 ubik_AbortTrans(trans);
1033 VldbentryLast = VldbentryFirst + allocCount;
1034 /* Handle the attribute by volume id totally separate of the rest (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!) */
1035 if (attributes->Mask & VLLIST_VOLUMEID) {
1036 afs_int32 blockindex, chain;
1037 struct nvlentry tempentry;
1039 blockindex = FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1040 if (blockindex == 0) {
1041 if (!errorcode) errorcode = VL_NOENT;
1043 ubik_AbortTrans(trans);
1044 if(vldbentries->bulkentries_val)free((char *)vldbentries->bulkentries_val);
1045 vldbentries->bulkentries_val = 0;
1046 vldbentries->bulkentries_len = 0;
1049 if (errorcode = put_attributeentry(&Vldbentry, &VldbentryFirst, &VldbentryLast, vldbentries, &tentry, nentries, &allocCount)) {
1051 ubik_AbortTrans(trans);
1052 if(vldbentries->bulkentries_val)free((char *)vldbentries->bulkentries_val);
1053 vldbentries->bulkentries_val = 0;
1054 vldbentries->bulkentries_len = 0;
1055 return VL_SIZEEXCEEDED;
1058 afs_int32 nextblockindex=0, count=0, k, match=0;
1059 while (nextblockindex = NextEntry(trans, nextblockindex, &tentry, &count)) {
1060 if (++pollcount > 50) {
1065 if (attributes->Mask & VLLIST_SERVER) {
1067 if ((serverindex = IpAddrToRelAddr(attributes->server, (struct ubik_trans *) 0)) == -1) continue;
1068 for (k=0; k<OMAXNSERVERS;k++) {
1069 if (tentry.serverNumber[k] == BADSERVERID) break;
1070 if (tentry.serverNumber[k] == serverindex) {
1075 if (!match) continue;
1077 if (attributes->Mask & VLLIST_PARTITION) {
1079 if (tentry.serverPartition[k] != attributes->partition) continue;
1081 for (k=0; k<OMAXNSERVERS;k++) {
1082 if (tentry.serverNumber[k] == BADSERVERID) break;
1083 if (tentry.serverPartition[k] == attributes->partition) {
1088 if (!match) continue;
1092 if (attributes->Mask & VLLIST_FLAG) {
1093 if (!(tentry.flags & attributes->flag)) continue;
1095 if (errorcode = put_attributeentry(&Vldbentry, &VldbentryFirst, &VldbentryLast, vldbentries, &tentry, nentries, &allocCount)) {
1097 ubik_AbortTrans(trans);
1098 if(vldbentries->bulkentries_val)free((char *)vldbentries->bulkentries_val);
1099 vldbentries->bulkentries_val = 0;
1100 vldbentries->bulkentries_len = 0;
1105 if (vldbentries->bulkentries_len && (allocCount > vldbentries->bulkentries_len)) {
1107 vldbentries->bulkentries_val = (vldbentry *) realloc(vldbentries->bulkentries_val, vldbentries->bulkentries_len * sizeof(vldbentry));
1108 if (vldbentries->bulkentries_val == NULL) {
1110 ubik_AbortTrans(trans);
1114 VLog(5, ("ListAttrs nentries=%d %s\n", vldbentries->bulkentries_len, rxinfo(rxcall)));
1115 return(ubik_EndTrans(trans));
1118 VL_ListAttributesN(rxcall, attributes, nentries, vldbentries)
1119 struct rx_call *rxcall;
1120 struct VldbListByAttributes *attributes;
1121 afs_int32 *nentries;
1122 nbulkentries *vldbentries;
1123 { int errorcode, allocCount = 0;
1124 struct ubik_trans *trans;
1125 struct nvlentry tentry;
1126 struct nvldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1129 COUNT_REQ (VLLISTATTRIBUTESN);
1130 vldbentries->nbulkentries_val = 0;
1131 vldbentries->nbulkentries_len = *nentries = 0;
1132 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1134 allocCount = VLDBALLOCCOUNT;
1135 Vldbentry = VldbentryFirst = vldbentries->nbulkentries_val = (nvldbentry *)malloc(allocCount * sizeof(nvldbentry));
1136 if (Vldbentry == NULL) {
1138 ubik_AbortTrans(trans);
1141 VldbentryLast = VldbentryFirst + allocCount;
1142 /* Handle the attribute by volume id totally separate of the rest (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!) */
1143 if (attributes->Mask & VLLIST_VOLUMEID) {
1144 afs_int32 blockindex, chain;
1145 struct nvlentry tempentry;
1147 blockindex = FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1148 if (blockindex == 0) {
1149 if (!errorcode) errorcode = VL_NOENT;
1151 ubik_AbortTrans(trans);
1152 if(vldbentries->nbulkentries_val)free((char *)vldbentries->nbulkentries_val);
1153 vldbentries->nbulkentries_val = 0;
1154 vldbentries->nbulkentries_len = 0;
1157 if (errorcode = put_nattributeentry(&Vldbentry, &VldbentryFirst, &VldbentryLast, vldbentries,
1158 &tentry, 0, 0, nentries, &allocCount)) {
1160 ubik_AbortTrans(trans);
1161 if(vldbentries->nbulkentries_val)free((char *)vldbentries->nbulkentries_val);
1162 vldbentries->nbulkentries_val = 0;
1163 vldbentries->nbulkentries_len = 0;
1164 return VL_SIZEEXCEEDED;
1167 afs_int32 nextblockindex=0, count=0, k, match=0;
1168 while (nextblockindex = NextEntry(trans, nextblockindex, &tentry, &count)) {
1169 if (++pollcount > 50) {
1175 if (attributes->Mask & VLLIST_SERVER) {
1177 if ((serverindex = IpAddrToRelAddr(attributes->server, (struct ubik_trans *) 0)) == -1) continue;
1178 for (k=0; k<NMAXNSERVERS;k++) {
1179 if (tentry.serverNumber[k] == BADSERVERID) break;
1180 if (tentry.serverNumber[k] == serverindex) {
1185 if (!match) continue;
1187 if (attributes->Mask & VLLIST_PARTITION) {
1189 if (tentry.serverPartition[k] != attributes->partition) continue;
1191 for (k=0; k<NMAXNSERVERS;k++) {
1192 if (tentry.serverNumber[k] == BADSERVERID) break;
1193 if (tentry.serverPartition[k] == attributes->partition) {
1198 if (!match) continue;
1202 if (attributes->Mask & VLLIST_FLAG) {
1203 if (!(tentry.flags & attributes->flag)) continue;
1205 if (errorcode = put_nattributeentry(&Vldbentry, &VldbentryFirst, &VldbentryLast,
1206 vldbentries, &tentry, 0, 0, nentries, &allocCount)) {
1208 ubik_AbortTrans(trans);
1209 if(vldbentries->nbulkentries_val)free((char *)vldbentries->nbulkentries_val);
1210 vldbentries->nbulkentries_val = 0;
1211 vldbentries->nbulkentries_len = 0;
1216 if (vldbentries->nbulkentries_len && (allocCount > vldbentries->nbulkentries_len)) {
1218 vldbentries->nbulkentries_val = (nvldbentry *) realloc(vldbentries->nbulkentries_val,
1219 vldbentries->nbulkentries_len * sizeof(nvldbentry));
1220 if (vldbentries->nbulkentries_val == NULL) {
1222 ubik_AbortTrans(trans);
1226 VLog(5, ("NListAttrs nentries=%d %s\n", vldbentries->nbulkentries_len, rxinfo(rxcall)));
1227 return(ubik_EndTrans(trans));
1231 VL_ListAttributesN2(rxcall, attributes, name, startindex, nentries, vldbentries, nextstartindex)
1232 struct rx_call *rxcall;
1233 struct VldbListByAttributes *attributes;
1234 char * name; /* Wildcarded volume name */
1235 afs_int32 startindex;
1236 afs_int32 *nentries;
1237 nbulkentries *vldbentries;
1238 afs_int32 *nextstartindex;
1240 int errorcode=0, maxCount=VLDBALLOCCOUNT;
1241 struct ubik_trans *trans;
1242 struct nvlentry tentry;
1243 struct nvldbentry *Vldbentry=0, *VldbentryFirst=0, *VldbentryLast=0, tVldbentry;
1244 afs_int32 blockindex=0, count=0, k, match, matchindex;
1245 int serverindex=-1; /* no server found */
1246 int findserver=0, findpartition=0, findflag=0, findname=0;
1249 int namematchRWBK, namematchRO, thismatch, matchtype;
1250 char volumename[VL_MAXNAMELEN];
1252 COUNT_REQ (VLLISTATTRIBUTESN2);
1253 vldbentries->nbulkentries_val = 0;
1254 vldbentries->nbulkentries_len = 0;
1256 *nextstartindex = -1;
1258 errorcode = Init_VLdbase(&trans, LOCKREAD, this_op);
1259 if (errorcode) return errorcode;
1261 Vldbentry = VldbentryFirst = vldbentries->nbulkentries_val = (nvldbentry *)malloc(maxCount * sizeof(nvldbentry));
1262 if (Vldbentry == NULL) {
1264 ubik_AbortTrans(trans);
1268 VldbentryLast = VldbentryFirst + maxCount;
1270 /* Handle the attribute by volume id totally separate of the rest
1271 * (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!)
1273 if (attributes->Mask & VLLIST_VOLUMEID) {
1274 blockindex = FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1275 if (blockindex == 0) {
1276 if (!errorcode) errorcode = VL_NOENT;
1278 errorcode = put_nattributeentry(&Vldbentry, &VldbentryFirst, &VldbentryLast,
1279 vldbentries, &tentry, 0, 0, nentries, &maxCount);
1280 if (errorcode) goto done;
1284 /* Search each entry in the database and return all entries
1285 * that match the request. It checks volumename (with
1286 * wildcarding), entry flags, server, and partition.
1289 /* Get the server index for matching server address */
1290 if (attributes->Mask & VLLIST_SERVER) {
1291 serverindex = IpAddrToRelAddr(attributes->server, (struct ubik_trans *)0);
1292 if (serverindex == -1) goto done;
1295 findpartition = ((attributes->Mask & VLLIST_PARTITION) ? 1 : 0);
1296 findflag = ((attributes->Mask & VLLIST_FLAG) ? 1 : 0);
1297 if (name && (strcmp(name,".*") != 0) && (strcmp(name,"") != 0)) {
1298 sprintf(volumename, "^%s$", name);
1299 t = (char *)re_comp(volumename);
1301 errorcode = VL_BADNAME;
1307 /* Read each entry and see if it is the one we want */
1308 blockindex = startindex;
1309 while (blockindex = NextEntry(trans, blockindex, &tentry, &count)) {
1310 if (++pollcount > 50) {
1315 /* Step through each server index searching for a match.
1316 * Match to an existing RW, BK, or RO volume name (preference
1317 * is in this order). Remember which index we matched against.
1319 namematchRWBK = namematchRO = 0; /* 0->notTried; 1->match; 2->noMatch */
1321 for (k=0; (k<NMAXNSERVERS && (tentry.serverNumber[k]!=BADSERVERID)); k++) {
1322 thismatch = 0; /* does this index match */
1324 /* Match against the RW or BK volume name. Remember
1325 * results in namematchRWBK. Prefer RW over BK.
1327 if (tentry.serverFlags[k] & VLSF_RWVOL) {
1328 /* Does the name match the RW name */
1329 if (tentry.flags & VLF_RWEXISTS) {
1331 sprintf(volumename, "%s", tentry.name);
1332 if (re_exec(volumename)) {
1333 thismatch = VLSF_RWVOL;
1336 thismatch = VLSF_RWVOL;
1340 /* Does the name match the BK name */
1341 if (!thismatch && (tentry.flags & VLF_BACKEXISTS)) {
1343 sprintf(volumename, "%s.backup", tentry.name);
1344 if (re_exec(volumename)) {
1345 thismatch = VLSF_BACKVOL;
1348 thismatch = VLSF_BACKVOL;
1352 namematchRWBK = (thismatch?1:2);
1355 /* Match with the RO volume name. Compare once and
1356 * remember results in namematchRO. Note that this will
1357 * pick up entries marked NEWREPSITEs and DONTUSE.
1360 if (tentry.flags & VLF_ROEXISTS) {
1363 thismatch = ((namematchRO == 1)?VLSF_ROVOL:0);
1365 sprintf(volumename, "%s.readonly", tentry.name);
1366 if (re_exec(volumename))
1367 thismatch = VLSF_ROVOL;
1370 thismatch = VLSF_ROVOL;
1373 namematchRO = (thismatch?1:2);
1376 /* Is there a server match */
1377 if (thismatch && findserver &&
1378 (tentry.serverNumber[k] != serverindex))
1381 /* Is there a partition match */
1382 if (thismatch && findpartition &&
1383 (tentry.serverPartition[k] != attributes->partition))
1386 /* Is there a flag match */
1387 if (thismatch && findflag && !(tentry.flags & attributes->flag))
1390 /* We found a match. Remember the index, and type */
1394 matchtype = thismatch;
1397 /* Since we prefer RW and BK volume matches over RO matches,
1398 * if we have already checked the RWBK name, then we already
1399 * found the best match and so end the search.
1401 * If we tried matching against the RW, BK, and RO volume names
1402 * and both failed, then we end the search (none will match).
1404 if ( (match && namematchRWBK) ||
1405 ((namematchRWBK==2) && (namematchRO==2)) )
1409 /* Passed all the tests. Take it */
1411 errorcode = put_nattributeentry(&Vldbentry,
1412 &VldbentryFirst, &VldbentryLast,
1413 vldbentries, &tentry, matchtype, matchindex,
1414 nentries, &maxCount);
1415 if (errorcode) goto done;
1417 if (*nentries >= maxCount) break; /* collected the max */
1420 *nextstartindex = (blockindex ? blockindex : -1);
1426 ubik_AbortTrans(trans);
1427 if (vldbentries->nbulkentries_val)
1428 free((char *)vldbentries->nbulkentries_val);
1429 vldbentries->nbulkentries_val = 0;
1430 vldbentries->nbulkentries_len = 0;
1431 *nextstartindex = -1;
1434 VLog(5, ("N2ListAttrs nentries=%d %s\n", vldbentries->nbulkentries_len, rxinfo(rxcall)));
1435 return(ubik_EndTrans(trans));
1440 /* Retrieves in vldbentries all vldb entries that match the specified
1441 * attributes (by server number, partition, volume type, and flag); if
1442 * volume id is specified then the associated list for that entry is
1443 * returned. CAUTION: This could be a very expensive call since in most
1444 * cases sequential search of all vldb entries is performed.
1446 VL_LinkedList(rxcall, attributes, nentries, vldbentries)
1447 struct rx_call *rxcall;
1448 struct VldbListByAttributes *attributes;
1449 afs_int32 *nentries;
1450 vldb_list *vldbentries;
1453 struct ubik_trans *trans;
1454 struct nvlentry tentry;
1455 vldblist vllist, *vllistptr;
1456 afs_int32 blockindex, count, k, match;
1460 COUNT_REQ (VLLINKEDLIST);
1461 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1465 vldbentries->node = NULL;
1466 vllistptr = &vldbentries->node;
1468 /* List by volumeid */
1469 if (attributes->Mask & VLLIST_VOLUMEID) {
1470 blockindex = FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1473 ubik_AbortTrans(trans);
1474 return (errorcode ? errorcode : VL_NOENT);
1477 vllist = (single_vldbentry *) malloc(sizeof(single_vldbentry));
1478 if (vllist == NULL) {
1480 ubik_AbortTrans(trans);
1483 vlentry_to_vldbentry(&tentry, &vllist->VldbEntry);
1484 vllist->next_vldb = NULL;
1486 *vllistptr = vllist; /* Thread onto list */
1487 vllistptr = &vllist->next_vldb;
1491 /* Search by server, partition, and flags */
1493 for (blockindex = NextEntry(trans, 0, &tentry, &count);
1495 blockindex = NextEntry(trans, blockindex, &tentry, &count)) {
1498 if (++pollcount > 50) {
1503 /* Does this volume exist on the desired server */
1504 if (attributes->Mask & VLLIST_SERVER) {
1505 serverindex = IpAddrToRelAddr(attributes->server, (struct ubik_trans *)0);
1506 if (serverindex == -1) continue;
1507 for (k=0; k < OMAXNSERVERS; k++) {
1508 if (tentry.serverNumber[k] == BADSERVERID) break;
1509 if (tentry.serverNumber[k] == serverindex) {
1514 if (!match) continue;
1517 /* Does this volume exist on the desired partition */
1518 if (attributes->Mask & VLLIST_PARTITION) {
1520 if (tentry.serverPartition[k] != attributes->partition)
1523 for (k=0; k < OMAXNSERVERS; k++) {
1524 if (tentry.serverNumber[k] == BADSERVERID) break;
1525 if (tentry.serverPartition[k] == attributes->partition) {
1531 if (!match) continue;
1534 /* Does this volume have the desired flags */
1535 if (attributes->Mask & VLLIST_FLAG) {
1536 if (!(tentry.flags & attributes->flag))
1540 vllist = (single_vldbentry *) malloc(sizeof(single_vldbentry));
1541 if (vllist == NULL) {
1543 ubik_AbortTrans(trans);
1546 vlentry_to_vldbentry(&tentry, &vllist->VldbEntry);
1547 vllist->next_vldb = NULL;
1549 *vllistptr = vllist; /* Thread onto list */
1550 vllistptr = &vllist->next_vldb;
1552 if (smallMem && (*nentries >= VLDBALLOCCOUNT)) {
1554 ubik_AbortTrans(trans);
1555 return VL_SIZEEXCEEDED;
1560 return(ubik_EndTrans(trans));
1563 VL_LinkedListN(rxcall, attributes, nentries, vldbentries)
1564 struct rx_call *rxcall;
1565 struct VldbListByAttributes *attributes;
1566 afs_int32 *nentries;
1567 nvldb_list *vldbentries;
1570 struct ubik_trans *trans;
1571 struct nvlentry tentry;
1572 nvldblist vllist, *vllistptr;
1573 afs_int32 blockindex, count, k, match;
1577 COUNT_REQ (VLLINKEDLISTN);
1578 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1582 vldbentries->node = NULL;
1583 vllistptr = &vldbentries->node;
1585 /* List by volumeid */
1586 if (attributes->Mask & VLLIST_VOLUMEID) {
1587 blockindex = FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1590 ubik_AbortTrans(trans);
1591 return (errorcode ? errorcode : VL_NOENT);
1594 vllist = (single_nvldbentry *) malloc(sizeof(single_nvldbentry));
1595 if (vllist == NULL) {
1597 ubik_AbortTrans(trans);
1600 vlentry_to_nvldbentry(&tentry, &vllist->VldbEntry);
1601 vllist->next_vldb = NULL;
1603 *vllistptr = vllist; /* Thread onto list */
1604 vllistptr = &vllist->next_vldb;
1608 /* Search by server, partition, and flags */
1610 for (blockindex = NextEntry(trans, 0, &tentry, &count);
1612 blockindex = NextEntry(trans, blockindex, &tentry, &count)) {
1615 if (++pollcount > 50) {
1620 /* Does this volume exist on the desired server */
1621 if (attributes->Mask & VLLIST_SERVER) {
1622 serverindex = IpAddrToRelAddr(attributes->server, (struct ubik_trans *)0);
1623 if (serverindex == -1) continue;
1624 for (k=0; k < NMAXNSERVERS; k++) {
1625 if (tentry.serverNumber[k] == BADSERVERID) break;
1626 if (tentry.serverNumber[k] == serverindex) {
1631 if (!match) continue;
1634 /* Does this volume exist on the desired partition */
1635 if (attributes->Mask & VLLIST_PARTITION) {
1637 if (tentry.serverPartition[k] != attributes->partition)
1640 for (k=0; k < NMAXNSERVERS; k++) {
1641 if (tentry.serverNumber[k] == BADSERVERID) break;
1642 if (tentry.serverPartition[k] == attributes->partition) {
1648 if (!match) continue;
1651 /* Does this volume have the desired flags */
1652 if (attributes->Mask & VLLIST_FLAG) {
1653 if (!(tentry.flags & attributes->flag))
1657 vllist = (single_nvldbentry *) malloc(sizeof(single_nvldbentry));
1658 if (vllist == NULL) {
1660 ubik_AbortTrans(trans);
1663 vlentry_to_nvldbentry(&tentry, &vllist->VldbEntry);
1664 vllist->next_vldb = NULL;
1666 *vllistptr = vllist; /* Thread onto list */
1667 vllistptr = &vllist->next_vldb;
1669 if (smallMem && (*nentries >= VLDBALLOCCOUNT)) {
1671 ubik_AbortTrans(trans);
1672 return VL_SIZEEXCEEDED;
1677 return(ubik_EndTrans(trans));
1680 /* Get back vldb header statistics (allocs, frees, maxvolumeid, totalentries, etc) and dynamic statistics (number of requests and/or aborts per remote procedure call, etc) */
1681 VL_GetStats(rxcall, stats, vital_header)
1682 struct rx_call *rxcall;
1684 vital_vlheader *vital_header;
1685 { register afs_int32 errorcode;
1686 struct ubik_trans *trans;
1688 COUNT_REQ(VLGETSTATS);
1690 /* Allow users to get statistics freely */
1691 if (!afsconf_SuperUser(vldb_confdir, rxcall, (char *)0)) /* Must be in 'UserList' to use */
1694 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1696 VLog(5, ("GetStats %\n", rxinfo(rxcall)));
1697 bcopy((char *)&cheader.vital_header, (char *) vital_header, sizeof(vital_vlheader));
1698 bcopy((char *)&dynamic_statistics, (char *) stats, sizeof(vldstats));
1699 return(ubik_EndTrans(trans));
1702 /* Get the list of file server addresses from the VLDB. Currently it's pretty
1703 * easy to do. In the future, it might require a little bit of grunging
1704 * through the VLDB, but that's life.
1706 VL_GetAddrs(rxcall, Handle, spare2, spare3, nentries, addrsp)
1707 struct rx_call *rxcall;
1708 afs_int32 Handle, spare2;
1709 struct VLCallBack *spare3;
1710 afs_int32 *nentries;
1712 { register afs_int32 errorcode;
1713 struct ubik_trans *trans;
1717 COUNT_REQ(VLGETADDRS);
1718 addrsp->bulkaddrs_len = *nentries = 0;
1719 addrsp->bulkaddrs_val = 0;
1720 bzero (spare3, sizeof (struct VLCallBack));
1722 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1725 VLog(5, ("GetAddrs\n"));
1726 addrsp->bulkaddrs_val = taddrp = (afs_uint32 *)malloc(sizeof(afs_int32)*(MAXSERVERID+1));
1727 nservers= *nentries = addrsp->bulkaddrs_len = 0;
1731 ubik_AbortTrans(trans);
1735 for (i=0; i <= MAXSERVERID; i++) {
1736 if (*taddrp = ntohl(cheader.IpMappedAddr[i])) {
1742 addrsp->bulkaddrs_len = *nentries = nservers;
1743 return(ubik_EndTrans(trans));
1746 #define PADDR(addr) printf("%d.%d.%d.%d", (addr>>24)&0xff, (addr>>16)&0xff, (addr>>8) &0xff, addr&0xff);
1748 VL_RegisterAddrs(rxcall, uuidp, spare1, addrsp)
1749 struct rx_call *rxcall;
1755 struct ubik_trans *trans;
1756 int cnt, h, i, j, k, m, hostslot, base, index;
1757 struct extentaddr *exp = 0, *tex;
1759 afs_uint32 addrs[VL_MAXIPADDRS_PERMH];
1760 afs_int32 fbase, findex;
1761 int count, willChangeEntry, foundUuidEntry, willReplaceCnt;
1762 int WillReplaceEntry, WillChange[MAXSERVERID+1], FoundUuid, ReplaceEntry;
1765 COUNT_REQ(VLREGADDR);
1766 if (!afsconf_SuperUser(vldb_confdir, rxcall, (char *)0))
1768 if (code = Init_VLdbase(&trans, LOCKWRITE, this_op))
1771 /* Eliminate duplicates from IP address list */
1772 for (k=0, cnt=0; k<addrsp->bulkaddrs_len; k++) {
1773 if (addrsp->bulkaddrs_val[k] == 0)
1775 for (m=0; m < cnt; m++) {
1776 if (addrs[m] == addrsp->bulkaddrs_val[k])
1780 if (m == VL_MAXIPADDRS_PERMH) {
1781 VLog(0, ("Number of addresses exceeds %d. Cannot register IP addr 0x%x in VLDB\n",
1782 VL_MAXIPADDRS_PERMH, addrsp->bulkaddrs_val[k]));
1784 addrs[m] = addrsp->bulkaddrs_val[k];
1790 ubik_AbortTrans(trans);
1791 return VL_INDEXERANGE;
1797 /* For each server registered within the VLDB */
1798 for (srvidx=0; srvidx <= MAXSERVERID;srvidx++) {
1799 willChangeEntry = 0;
1800 WillReplaceEntry = 1;
1801 if ((HostAddress[srvidx] & 0xff000000) == 0xff000000) {
1802 /* The server is registered as a multihomed */
1803 base = (HostAddress[srvidx] >> 16) & 0xff;
1804 index = HostAddress[srvidx] & 0x0000ffff;
1805 if (base >= VL_MAX_ADDREXTBLKS) {
1806 VLog(0, ("Internal error: Multihome extent base is too large. Base %d index %d\n",
1810 if (index >= VL_MHSRV_PERBLK) {
1811 VLog(0, ("Internal error: Multihome extent index is too large. Base %d index %d\n",
1815 if (!ex_addr[base]) {
1816 VLog(0, ("Internal error: Multihome extent does not exist. Base %d\n", base));
1820 /* See if the addresses to register will change this server entry */
1821 exp = &ex_addr[base][index];
1822 tuuid = exp->ex_hostuuid;
1823 afs_ntohuuid(&tuuid);
1824 if (afs_uuid_equal(uuidp, &tuuid)) {
1828 for (mhidx=0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
1829 if (!exp->ex_addrs[mhidx]) continue;
1830 for (k=0; k<cnt; k++) {
1831 if (ntohl(exp->ex_addrs[mhidx]) == addrs[k]) {
1832 willChangeEntry = 1;
1833 WillChange[count] = srvidx;
1837 if (k >= cnt) WillReplaceEntry = 0;
1841 /* The server is not registered as a multihomed.
1842 * See if the addresses to register will replace this server entry.
1844 for (k=0; k<cnt; k++) {
1845 if (HostAddress[srvidx] == addrs[k]) {
1846 willChangeEntry = 1;
1847 WillChange[count] = srvidx;
1848 WillReplaceEntry = 1;
1853 if (willChangeEntry) {
1854 if (WillReplaceEntry) {
1856 ReplaceEntry = srvidx;
1862 /* If we found the uuid in the VLDB and if we are replacing another
1863 * entire entry, then complain and fail. Also, if we did not find
1864 * the uuid in the VLDB and the IP addresses being registered was
1865 * found in more than one other entry, then we don't know which one
1866 * to replace and will complain and fail.
1868 if ( ( foundUuidEntry && (willReplaceCnt > 0)) ||
1869 (!foundUuidEntry && (count > 1)) ) {
1870 VLog(0, ("The following fileserver is being registered in the VLDB:\n"));
1872 for (k=0; k<cnt; k++) {
1873 if (k>0) printf(" ");
1878 if (foundUuidEntry) {
1879 printf(" It would have replaced the existing VLDB server entry:\n");
1880 printf(" entry %d: [", FoundUuid);
1881 base = (HostAddress[FoundUuid] >> 16) & 0xff;
1882 index = HostAddress[FoundUuid] & 0x0000ffff;
1883 exp = &ex_addr[base][index];
1884 for (mhidx=0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
1885 if (!exp->ex_addrs[mhidx]) continue;
1886 if (mhidx > 0) printf(" ");
1887 PADDR(ntohl(exp->ex_addrs[mhidx]));
1892 if (count == 1) printf(" Yet another VLDB server entry exists:\n");
1893 else printf(" Yet other VLDB server entries exist:\n");
1894 for (j=0; j<count; j++) {
1895 srvidx = WillChange[j];
1896 printf(" entry %d: ", srvidx);
1897 if ((HostAddress[srvidx] & 0xff000000) == 0xff000000) {
1899 base = (HostAddress[srvidx] >> 16) & 0xff;
1900 index = HostAddress[srvidx] & 0x0000ffff;
1901 exp = &ex_addr[base][index];
1902 for (mhidx=0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
1903 if (!exp->ex_addrs[mhidx]) continue;
1904 if (mhidx > 0) printf(" ");
1905 PADDR(ntohl(exp->ex_addrs[mhidx]));
1909 PADDR(HostAddress[srvidx]);
1915 printf(" You must 'vos changeaddr' this other server entry\n");
1917 printf(" You must 'vos changeaddr' these other server entries\n");
1919 printf(" and/or remove the sysid file from the registering fileserver\n");
1920 printf(" before the fileserver can be registered in the VLDB.\n");
1922 ubik_AbortTrans(trans);
1923 return VL_MULTIPADDR;
1926 /* Passed the checks. Now find and update the existing mh entry, or create
1929 if (foundUuidEntry) {
1930 /* Found the entry with same uuid. See if we need to change it */
1933 fbase = (HostAddress[FoundUuid] >> 16) & 0xff;
1934 index = HostAddress[FoundUuid] & 0x0000ffff;
1935 exp = &ex_addr[fbase][index];
1937 /* Determine if the entry has changed */
1938 for (k=0; ((k < cnt) && !change); k++) {
1939 if (ntohl(exp->ex_addrs[k]) != addrs[k])
1942 for (; ((k < VL_MAXIPADDRS_PERMH) && !change); k++) {
1943 if (exp->ex_addrs[k] != 0)
1947 return(ubik_EndTrans(trans));
1951 VLog(0, ("The following fileserver is being registered in the VLDB:\n"));
1953 for (k=0; k<cnt; k++) {
1954 if (k>0) printf(" ");
1959 if (foundUuidEntry) {
1960 printf(" It will replace the following existing entry in the VLDB (same uuid):\n");
1961 printf(" entry %d: [", FoundUuid);
1962 for (k=0; k < VL_MAXIPADDRS_PERMH; k++) {
1963 if (exp->ex_addrs[k] == 0) continue;
1964 if (k>0) printf(" ");
1965 PADDR(ntohl(exp->ex_addrs[k]));
1969 else if (willReplaceCnt || (count == 1)) {
1970 /* If we are not replacing an entry and there is only one entry to change,
1971 * then we will replace that entry.
1973 if (!willReplaceCnt) {
1974 ReplaceEntry = WillChange[0];
1978 /* Have an entry that needs to be replaced */
1979 if ((HostAddress[ReplaceEntry] & 0xff000000) == 0xff000000) {
1980 fbase = (HostAddress[ReplaceEntry] >> 16) & 0xff;
1981 index = HostAddress[ReplaceEntry] & 0x0000ffff;
1982 exp = &ex_addr[fbase][index];
1984 printf(" It will replace the following existing entry in the VLDB (new uuid):\n");
1985 printf(" entry %d: [", ReplaceEntry);
1986 for (k=0; k < VL_MAXIPADDRS_PERMH; k++) {
1987 if (exp->ex_addrs[k] == 0) continue;
1988 if (k>0) printf(" ");
1989 PADDR(ntohl(exp->ex_addrs[k]));
1993 /* Not a mh entry. So we have to create a new mh entry and
1994 * put it on the ReplaceEntry slot of the HostAddress array.
1996 printf(" It will replace existing entry %d, ", ReplaceEntry);
1997 PADDR(HostAddress[ReplaceEntry]);
1998 printf(", in the VLDB (new uuid):\n");
2000 code = FindExtentBlock(trans, uuidp, 1, ReplaceEntry, &exp, &fbase);
2002 ubik_AbortTrans(trans);
2003 return (code ? code : VL_IO);
2007 /* There is no entry for this server, must create a new mh entry as
2008 * well as use a new slot of the HostAddress array.
2010 printf(" It will create a new entry in the VLDB.\n");
2011 code = FindExtentBlock(trans, uuidp, 1, -1, &exp, &fbase);
2013 ubik_AbortTrans(trans);
2014 return (code ? code : VL_IO);
2018 /* Now we have a mh entry to fill in. Update the uuid, bump the
2019 * uniquifier, and fill in its IP addresses.
2022 afs_htonuuid(&tuuid);
2023 exp->ex_hostuuid = tuuid;
2024 exp->ex_uniquifier = htonl(ntohl(exp->ex_uniquifier)+1);
2025 for (k=0; k < cnt; k++) {
2026 exp->ex_addrs[k] = htonl(addrs[k]);
2028 for (; k < VL_MAXIPADDRS_PERMH; k++) {
2029 exp->ex_addrs[k] = 0;
2032 /* Write the new mh entry out */
2033 if (vlwrite(trans, DOFFSET(ntohl(ex_addr[0]->ex_contaddrs[fbase]),
2034 (char *)ex_addr[fbase], (char *)exp),
2035 (char *)exp, sizeof(*exp))) {
2036 ubik_AbortTrans(trans);
2040 /* Remove any common addresses from other mh entres. We know these entries
2041 * are being changed and not replaced so they are mh entries.
2044 for (i=0; i<count; i++) {
2047 /* Skip the entry we replaced */
2048 if (willReplaceCnt && (WillChange[i] == ReplaceEntry))
2051 base = (HostAddress[WillChange[i]] >> 16) & 0xff;
2052 index = HostAddress[WillChange[i]] & 0x0000ffff;
2053 tex = &ex_addr[fbase][index];
2056 printf(" The following existing entries in the VLDB will be updated:\n");
2058 printf(" entry %d: [", WillChange[i]);
2059 for (h=j=0; j < VL_MAXIPADDRS_PERMH; j++) {
2060 if (tex->ex_addrs[j]) {
2061 if (j>0) printf(" ");
2062 PADDR(ntohl(tex->ex_addrs[j]));
2065 for (k=0; k<cnt; k++) {
2066 if (ntohl(tex->ex_addrs[j]) == addrs[k]) break;
2069 /* Not found, so we keep it */
2070 tex->ex_addrs[h] = tex->ex_addrs[j];
2074 for (j=h; j < VL_MAXIPADDRS_PERMH; j++) {
2075 tex->ex_addrs[j] = 0; /* zero rest of mh entry */
2079 /* Write out the modified mh entry */
2080 tex->ex_uniquifier = htonl(ntohl(tex->ex_uniquifier)+1);
2081 doff=DOFFSET(ntohl(ex_addr[0]->ex_contaddrs[base]),
2082 (char *)ex_addr[base], (char *)tex);
2083 if (vlwrite(trans, doff, (char*)tex, sizeof(*tex))) {
2084 ubik_AbortTrans(trans);
2089 return(ubik_EndTrans(trans));
2092 VL_GetAddrsU(rxcall, attributes, uuidpo, uniquifier, nentries, addrsp)
2093 struct rx_call *rxcall;
2094 struct ListAddrByAttributes *attributes;
2096 afs_int32 *uniquifier, *nentries;
2098 { register afs_int32 errorcode, index=-1, op, offset;
2099 struct ubik_trans *trans;
2100 int nservers, i, j, k, base=0;
2101 struct extentaddr *exp=0;
2103 afs_uint32 *taddrp, taddr;
2105 COUNT_REQ(VLGETADDRSU);
2106 addrsp->bulkaddrs_len = *nentries = 0;
2107 addrsp->bulkaddrs_val = 0;
2108 VLog(5, ("GetAddrsU %s\n", rxinfo(rxcall)));
2109 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
2112 if (attributes->Mask & VLADDR_IPADDR) {
2113 if (attributes->Mask & (VLADDR_INDEX|VLADDR_UUID)) {
2114 ubik_AbortTrans(trans);
2117 for (base = 0; base < VL_MAX_ADDREXTBLKS; base++) {
2120 for (i = 1; i < VL_MHSRV_PERBLK; i++) {
2121 exp = &ex_addr[base][i];
2122 tuuid = exp->ex_hostuuid;
2123 afs_ntohuuid(&tuuid);
2124 if (afs_uuid_is_nil(&tuuid)) continue;
2125 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2126 if (exp->ex_addrs[j] && (ntohl(exp->ex_addrs[j]) == attributes->ipaddr)) {
2130 if (j < VL_MAXIPADDRS_PERMH) break;
2132 if (i < VL_MHSRV_PERBLK) break;
2134 if (base >= VL_MAX_ADDREXTBLKS) {
2135 ubik_AbortTrans(trans);
2138 } else if (attributes->Mask & VLADDR_INDEX) {
2139 if (attributes->Mask & (VLADDR_IPADDR|VLADDR_UUID)) {
2140 ubik_AbortTrans(trans);
2143 index = attributes->index;
2144 if (index < 1 || index >= (VL_MAX_ADDREXTBLKS*VL_MHSRV_PERBLK)) {
2145 ubik_AbortTrans(trans);
2146 return VL_INDEXERANGE;
2148 base = index / VL_MHSRV_PERBLK;
2149 offset = index % VL_MHSRV_PERBLK;
2151 ubik_AbortTrans(trans);
2154 if (!ex_addr[base]) {
2155 ubik_AbortTrans(trans);
2156 return VL_INDEXERANGE;
2158 exp = &ex_addr[base][offset];
2159 } else if (attributes->Mask & VLADDR_UUID) {
2160 if (attributes->Mask & (VLADDR_IPADDR|VLADDR_INDEX)) {
2161 ubik_AbortTrans(trans);
2164 if (!ex_addr[0]) { /* mh servers probably aren't setup on this vldb */
2165 ubik_AbortTrans(trans);
2168 if (errorcode = FindExtentBlock(trans, &attributes->uuid, 0, -1, &exp, &base)) {
2169 ubik_AbortTrans(trans);
2173 ubik_AbortTrans(trans);
2177 if (exp == (struct extentaddr *)0) {
2178 ubik_AbortTrans(trans);
2181 addrsp->bulkaddrs_val = taddrp = (afs_uint32 *)malloc(sizeof(afs_int32)*(MAXSERVERID+1));
2182 nservers= *nentries = addrsp->bulkaddrs_len = 0;
2185 ubik_AbortTrans(trans);
2188 tuuid = exp->ex_hostuuid;
2189 afs_ntohuuid(&tuuid);
2190 if (afs_uuid_is_nil(&tuuid)) {
2191 ubik_AbortTrans(trans);
2194 if (uuidpo) *uuidpo = tuuid;
2195 if (uniquifier) *uniquifier = ntohl(exp->ex_uniquifier);
2196 for (i = 0; i < VL_MAXIPADDRS_PERMH; i++) {
2197 if (exp->ex_addrs[i]) {
2198 taddr = ntohl(exp->ex_addrs[i]);
2199 /* Weed out duplicates */
2200 for (j = 0; j < nservers; j++) {
2201 if (taddrp[j] == taddr)
2204 if ((j == nservers) && (j <= MAXSERVERID)) {
2205 taddrp[nservers] = taddr;
2210 addrsp->bulkaddrs_len = *nentries = nservers;
2211 return(ubik_EndTrans(trans));
2214 /* ============> End of Exported vldb RPC functions <============= */
2217 /* Routine that copies the given vldb entry to the output buffer, vldbentries. */
2219 put_attributeentry(Vldbentry, VldbentryFirst, VldbentryLast, vldbentries, entry, nentries, alloccnt)
2220 struct vldbentry **Vldbentry, **VldbentryFirst, **VldbentryLast;
2221 bulkentries *vldbentries;
2222 struct nvlentry *entry;
2223 afs_int32 *nentries, *alloccnt;
2228 if (*Vldbentry == *VldbentryLast) {
2229 if (smallMem) return VL_SIZEEXCEEDED; /* no growing if smallMem defined */
2231 /* Allocate another set of memory; each time allocate twice as
2232 * many blocks as the last time. When we reach VLDBALLOCLIMIT,
2233 * then grow in increments of VLDBALLOCINCR.
2235 allo = (*alloccnt > VLDBALLOCLIMIT) ? VLDBALLOCINCR : *alloccnt;
2236 reall = (vldbentry *) realloc(*VldbentryFirst, (*alloccnt+allo)*sizeof(vldbentry));
2237 if (reall == NULL) return VL_NOMEM;
2239 *VldbentryFirst = vldbentries->bulkentries_val = reall;
2240 *Vldbentry = *VldbentryFirst + *alloccnt;
2241 *VldbentryLast = *Vldbentry + allo;
2244 vlentry_to_vldbentry(entry, *Vldbentry);
2247 vldbentries->bulkentries_len++;
2252 put_nattributeentry(Vldbentry, VldbentryFirst, VldbentryLast, vldbentries, entry,
2253 matchtype, matchindex, nentries, alloccnt)
2254 struct nvldbentry **Vldbentry, **VldbentryFirst, **VldbentryLast;
2255 nbulkentries *vldbentries;
2256 struct nvlentry *entry;
2257 afs_int32 matchtype, matchindex, *nentries, *alloccnt;
2262 if (*Vldbentry == *VldbentryLast) {
2263 if (smallMem) return VL_SIZEEXCEEDED; /* no growing if smallMem defined */
2265 /* Allocate another set of memory; each time allocate twice as
2266 * many blocks as the last time. When we reach VLDBALLOCLIMIT,
2267 * then grow in increments of VLDBALLOCINCR.
2269 allo = (*alloccnt > VLDBALLOCLIMIT) ? VLDBALLOCINCR : *alloccnt;
2270 reall = (nvldbentry *)realloc(*VldbentryFirst, (*alloccnt+allo)*sizeof(nvldbentry));
2271 if (reall == NULL) return VL_NOMEM;
2273 *VldbentryFirst = vldbentries->nbulkentries_val = reall;
2274 *Vldbentry = *VldbentryFirst + *alloccnt;
2275 *VldbentryLast = *Vldbentry + allo;
2278 vlentry_to_nvldbentry(entry, *Vldbentry);
2279 (*Vldbentry)->matchindex = (matchtype << 16) + matchindex;
2282 vldbentries->nbulkentries_len++;
2287 /* Common code to actually remove a vldb entry from the database. */
2289 RemoveEntry(trans, entryptr, tentry)
2290 struct ubik_trans *trans;
2292 struct nvlentry *tentry;
2294 register int errorcode;
2296 if (errorcode = UnthreadVLentry(trans, entryptr, tentry))
2298 if (errorcode = FreeBlock(trans, entryptr))
2304 ReleaseEntry(tentry, releasetype)
2305 struct nvlentry *tentry;
2306 afs_int32 releasetype;
2308 if (releasetype & LOCKREL_TIMESTAMP)
2309 tentry->LockTimestamp = 0;
2310 if (releasetype & LOCKREL_OPCODE)
2311 tentry->flags &= ~VLOP_ALLOPERS;
2312 if (releasetype & LOCKREL_AFSID)
2313 tentry->LockAfsId = 0;
2317 /* Verify that the incoming vldb entry is valid; multi type of error codes are returned. */
2319 check_vldbentry(aentry)
2320 struct vldbentry *aentry;
2324 if (InvalidVolname(aentry->name))
2326 if (aentry->nServers <= 0 || aentry->nServers > OMAXNSERVERS)
2327 return VL_BADSERVER;
2328 for (i=0; i < aentry->nServers; i++) {
2329 /* if (aentry->serverNumber[i] < 0 || aentry->serverNumber[i] > MAXSERVERID)
2330 return VL_BADSERVER; */
2331 if (aentry->serverPartition[i] < 0 || aentry->serverPartition[i] > MAXPARTITIONID)
2332 return VL_BADPARTITION;
2333 if (aentry->serverFlags[i] < 0 || aentry->serverFlags[i] > MAXSERVERFLAG)
2334 return VL_BADSERVERFLAG;
2340 check_nvldbentry(aentry)
2341 struct nvldbentry *aentry;
2345 if (InvalidVolname(aentry->name))
2347 if (aentry->nServers <= 0 || aentry->nServers > NMAXNSERVERS)
2348 return VL_BADSERVER;
2349 for (i=0; i < aentry->nServers; i++) {
2350 /* if (aentry->serverNumber[i] < 0 || aentry->serverNumber[i] > MAXSERVERID)
2351 return VL_BADSERVER; */
2352 if (aentry->serverPartition[i] < 0 || aentry->serverPartition[i] > MAXPARTITIONID)
2353 return VL_BADPARTITION;
2354 if (aentry->serverFlags[i] < 0 || aentry->serverFlags[i] > MAXSERVERFLAG)
2355 return VL_BADSERVERFLAG;
2361 /* Convert from the external vldb entry representation to its internal
2362 (more compact) form. This call should not change the hash chains! */
2364 vldbentry_to_vlentry(atrans, VldbEntry, VlEntry)
2365 struct ubik_trans *atrans;
2366 struct vldbentry *VldbEntry;
2367 struct nvlentry *VlEntry;
2371 if (strcmp(VlEntry->name, VldbEntry->name))
2372 strncpy(VlEntry->name, VldbEntry->name, sizeof(VlEntry->name));
2373 for (i=0; i<VldbEntry->nServers; i++) {
2374 serverindex = IpAddrToRelAddr(VldbEntry->serverNumber[i], atrans);
2375 if (serverindex == -1) return VL_BADSERVER;
2376 VlEntry->serverNumber[i] = serverindex;
2377 VlEntry->serverPartition[i] = VldbEntry->serverPartition[i];
2378 VlEntry->serverFlags[i] = VldbEntry->serverFlags[i];
2380 for (;i < OMAXNSERVERS; i++)
2381 VlEntry->serverNumber[i] = VlEntry->serverPartition[i] = VlEntry->serverFlags[i] = BADSERVERID;
2382 for (i=0; i < MAXTYPES; i++)
2383 VlEntry->volumeId[i] = VldbEntry->volumeId[i];
2384 VlEntry->cloneId = VldbEntry->cloneId;
2385 VlEntry->flags = VldbEntry->flags;
2390 nvldbentry_to_vlentry(atrans, VldbEntry, VlEntry)
2391 struct ubik_trans *atrans;
2392 struct nvldbentry *VldbEntry;
2393 struct nvlentry *VlEntry;
2397 if (strcmp(VlEntry->name, VldbEntry->name))
2398 strncpy(VlEntry->name, VldbEntry->name, sizeof(VlEntry->name));
2399 for (i=0; i<VldbEntry->nServers; i++) {
2400 serverindex = IpAddrToRelAddr(VldbEntry->serverNumber[i], atrans);
2401 if (serverindex == -1) return VL_BADSERVER;
2402 VlEntry->serverNumber[i] = serverindex;
2403 VlEntry->serverPartition[i] = VldbEntry->serverPartition[i];
2404 VlEntry->serverFlags[i] = VldbEntry->serverFlags[i];
2406 for (;i < NMAXNSERVERS; i++)
2407 VlEntry->serverNumber[i] = VlEntry->serverPartition[i] = VlEntry->serverFlags[i] = BADSERVERID;
2408 for (i=0; i < MAXTYPES; i++)
2409 VlEntry->volumeId[i] = VldbEntry->volumeId[i];
2410 VlEntry->cloneId = VldbEntry->cloneId;
2411 VlEntry->flags = VldbEntry->flags;
2416 /* 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. */
2418 get_vldbupdateentry(trans, blockindex, updateentry, VlEntry)
2419 struct ubik_trans *trans;
2420 afs_int32 blockindex;
2421 struct VldbUpdateEntry *updateentry;
2422 struct nvlentry *VlEntry;
2424 int i, j, errorcode, serverindex;
2426 if (updateentry->Mask & VLUPDATE_VOLUMENAME) {
2427 if (InvalidVolname(updateentry->name))
2429 if (errorcode = UnhashVolname(trans, blockindex, VlEntry))
2431 strncpy(VlEntry->name, updateentry->name, sizeof(VlEntry->name));
2432 HashVolname(trans, blockindex, VlEntry);
2435 if (updateentry->Mask & VLUPDATE_VOLNAMEHASH) {
2436 if (errorcode = UnhashVolname(trans, blockindex, VlEntry)) {
2437 if (errorcode != VL_NOENT)
2440 HashVolname(trans, blockindex, VlEntry);
2443 if (updateentry->Mask & VLUPDATE_FLAGS) {
2444 VlEntry->flags = updateentry->flags;
2446 if (updateentry->Mask & VLUPDATE_CLONEID) {
2447 VlEntry->cloneId = updateentry->cloneId;
2449 if (updateentry->Mask & VLUPDATE_RWID) {
2450 if (errorcode = UnhashVolid(trans, RWVOL, blockindex, VlEntry)) {
2451 if (errorcode != VL_NOENT)
2454 VlEntry->volumeId[RWVOL] = updateentry->spares3; /* rw id */
2455 if (errorcode = HashVolid(trans, RWVOL, blockindex, VlEntry))
2458 if (updateentry->Mask & VLUPDATE_READONLYID) {
2459 if (errorcode = UnhashVolid(trans, ROVOL, blockindex, VlEntry)) {
2460 if (errorcode != VL_NOENT)
2463 VlEntry->volumeId[ROVOL] = updateentry->ReadOnlyId;
2464 if (errorcode = HashVolid(trans, ROVOL, blockindex, VlEntry))
2467 if (updateentry->Mask & VLUPDATE_BACKUPID) {
2468 if (errorcode = UnhashVolid(trans, BACKVOL, blockindex, VlEntry)) {
2469 if (errorcode != VL_NOENT)
2472 VlEntry->volumeId[BACKVOL] = updateentry->BackupId;
2473 if (errorcode = HashVolid(trans, BACKVOL, blockindex, VlEntry))
2476 if (updateentry->Mask & VLUPDATE_REPSITES) {
2477 if (updateentry->nModifiedRepsites <= 0 || updateentry->nModifiedRepsites > OMAXNSERVERS)
2478 return VL_BADSERVER;
2479 for (i=0; i < updateentry->nModifiedRepsites; i++) {
2480 /* if (updateentry->RepsitesTargetServer[i] < 0 || updateentry->RepsitesTargetServer[i] > MAXSERVERID)
2481 return VL_BADSERVER; */
2482 if (updateentry->RepsitesTargetPart[i] < 0 || updateentry->RepsitesTargetPart[i] > MAXPARTITIONID)
2483 return VL_BADPARTITION;
2484 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_DELETE) {
2485 if ((j = repsite_exists(VlEntry, IpAddrToRelAddr(updateentry->RepsitesTargetServer[i], trans), updateentry->RepsitesTargetPart[i])) != -1)
2486 repsite_compress(VlEntry, j);
2487 else return VL_NOREPSERVER;
2489 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_ADD) {
2490 /* if (updateentry->RepsitesNewServer[i] < 0 || updateentry->RepsitesNewServer[i] > MAXSERVERID)
2491 return VL_BADSERVER; */
2492 if (updateentry->RepsitesNewPart[i] < 0 || updateentry->RepsitesNewPart[i] > MAXPARTITIONID)
2493 return VL_BADPARTITION;
2494 if (repsite_exists(VlEntry, IpAddrToRelAddr(updateentry->RepsitesNewServer[i], trans), updateentry->RepsitesNewPart[i]) != -1)
2495 return VL_DUPREPSERVER;
2496 for (j=0; VlEntry->serverNumber[j] != BADSERVERID && j < OMAXNSERVERS; j++);
2497 if (j >= OMAXNSERVERS) return VL_REPSFULL;
2498 if ((serverindex = IpAddrToRelAddr(updateentry->RepsitesNewServer[i], trans)) == -1)
2499 return VL_BADSERVER;
2500 VlEntry->serverNumber[j] = serverindex;
2501 VlEntry->serverPartition[j] = updateentry->RepsitesNewPart[i];
2502 if (updateentry->RepsitesNewFlags[i] < 0 || updateentry->RepsitesNewFlags[i] > MAXSERVERFLAG)
2503 return VL_BADSERVERFLAG;
2504 VlEntry->serverFlags[j] = updateentry->RepsitesNewFlags[i];
2506 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODSERV) {
2507 /*n if (updateentry->RepsitesNewServer[i] < 0 || updateentry->RepsitesNewServer[i] > MAXSERVERID)
2508 return VL_BADSERVER; */
2509 if ((j = repsite_exists(VlEntry, IpAddrToRelAddr(updateentry->RepsitesTargetServer[i], trans), updateentry->RepsitesTargetPart[i])) != -1) {
2510 VlEntry->serverNumber[j] = IpAddrToRelAddr(updateentry->RepsitesNewServer[i], trans);
2512 else return VL_NOREPSERVER;
2514 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODPART) {
2515 if (updateentry->RepsitesNewPart[i] < 0 || updateentry->RepsitesNewPart[i] > MAXPARTITIONID)
2516 return VL_BADPARTITION;
2517 if ((j = repsite_exists(VlEntry, IpAddrToRelAddr(updateentry->RepsitesTargetServer[i], trans), updateentry->RepsitesTargetPart[i])) != -1)
2518 VlEntry->serverPartition[j] = updateentry->RepsitesNewPart[i];
2519 else return VL_NOREPSERVER;
2521 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODFLAG) {
2522 if ((j = repsite_exists(VlEntry, IpAddrToRelAddr(updateentry->RepsitesTargetServer[i], trans), updateentry->RepsitesTargetPart[i])) != -1) {
2523 if (updateentry->RepsitesNewFlags[i] < 0 || updateentry->RepsitesNewFlags[i] > MAXSERVERFLAG)
2524 return VL_BADSERVERFLAG;
2525 VlEntry->serverFlags[j] = updateentry->RepsitesNewFlags[i];
2526 } else return VL_NOREPSERVER;
2534 /* 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. */
2536 repsite_exists(VlEntry, server, partition)
2537 struct nvlentry *VlEntry;
2538 int server, partition;
2542 for (i=0; VlEntry->serverNumber[i] != BADSERVERID && i < OMAXNSERVERS; i++) {
2543 if ((VlEntry->serverNumber[i] == server) && (VlEntry->serverPartition[i] == partition))
2551 /* Repsite table compression: used when deleting a repsite entry so that all active repsite entries are on the top of the table. */
2553 repsite_compress(VlEntry, offset)
2554 struct nvlentry *VlEntry;
2557 int repsite_offset = offset;
2558 for (; VlEntry->serverNumber[repsite_offset] != BADSERVERID && repsite_offset < OMAXNSERVERS-1; repsite_offset++) {
2559 VlEntry->serverNumber[repsite_offset] = VlEntry->serverNumber[repsite_offset+1];
2560 VlEntry->serverPartition[repsite_offset] = VlEntry->serverPartition[repsite_offset+1];
2561 VlEntry->serverFlags[repsite_offset] = VlEntry->serverFlags[repsite_offset+1];
2563 VlEntry->serverNumber[repsite_offset] = BADSERVERID;
2567 /* Convert from the internal (compacted) vldb entry to the external representation used by the interface. */
2569 vlentry_to_vldbentry(VlEntry, VldbEntry)
2570 struct nvlentry *VlEntry;
2571 struct vldbentry *VldbEntry;
2575 bzero(VldbEntry, sizeof(struct vldbentry));
2576 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
2577 for (i=0; i < OMAXNSERVERS; i++) {
2578 if (VlEntry->serverNumber[i] == BADSERVERID) break;
2579 if ((HostAddress[j = VlEntry->serverNumber[i]] & 0xff000000) == 0xff000000) {
2580 struct extentaddr *exp;
2583 base = (HostAddress[j] >> 16) & 0xff;
2584 index = HostAddress[j] & 0x0000ffff;
2585 exp = &ex_addr[base][index];
2586 /* For now return the first ip address back */
2587 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2588 if (exp->ex_addrs[j]) {
2589 VldbEntry->serverNumber[i] = ntohl(exp->ex_addrs[j]);
2594 VldbEntry->serverNumber[i] = HostAddress[VlEntry->serverNumber[i]];
2595 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
2596 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
2598 VldbEntry->nServers = i;
2599 for (i=0; i<MAXTYPES; i++)
2600 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
2601 VldbEntry->cloneId = VlEntry->cloneId;
2602 VldbEntry->flags = VlEntry->flags;
2606 /* Convert from the internal (compacted) vldb entry to the external representation used by the interface. */
2607 static vlentry_to_nvldbentry(VlEntry, VldbEntry)
2608 struct nvlentry *VlEntry;
2609 struct nvldbentry *VldbEntry;
2613 bzero(VldbEntry, sizeof(struct vldbentry));
2614 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
2615 for (i=0; i < NMAXNSERVERS; i++) {
2616 if (VlEntry->serverNumber[i] == BADSERVERID) break;
2617 if ((HostAddress[j = VlEntry->serverNumber[i]] & 0xff000000) == 0xff000000) {
2618 struct extentaddr *exp;
2621 base = (HostAddress[j] >> 16) & 0xff;
2622 index = HostAddress[j] & 0x0000ffff;
2623 exp = &ex_addr[base][index];
2624 /* For now return the first ip address back */
2625 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2626 if (exp->ex_addrs[j]) {
2627 VldbEntry->serverNumber[i] = ntohl(exp->ex_addrs[j]);
2632 VldbEntry->serverNumber[i] = HostAddress[VlEntry->serverNumber[i]];
2633 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
2634 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
2636 VldbEntry->nServers = i;
2637 for (i=0; i<MAXTYPES; i++)
2638 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
2639 VldbEntry->cloneId = VlEntry->cloneId;
2640 VldbEntry->flags = VlEntry->flags;
2643 static vlentry_to_uvldbentry(VlEntry, VldbEntry)
2644 struct nvlentry *VlEntry;
2645 struct uvldbentry *VldbEntry;
2649 bzero(VldbEntry, sizeof(struct vldbentry));
2650 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
2651 for (i=0; i < NMAXNSERVERS; i++) {
2652 if (VlEntry->serverNumber[i] == BADSERVERID) break;
2653 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
2654 VldbEntry->serverUnique[i] = 0;
2655 if ((HostAddress[j = VlEntry->serverNumber[i]] & 0xff000000) == 0xff000000) {
2656 struct extentaddr *exp;
2660 base = (HostAddress[j] >> 16) & 0xff;
2661 index = HostAddress[j] & 0x0000ffff;
2662 exp = &ex_addr[base][index];
2663 tuuid = exp->ex_hostuuid;
2664 afs_ntohuuid(&tuuid);
2665 VldbEntry->serverFlags[i] |= VLSERVER_FLAG_UUID;
2666 VldbEntry->serverNumber[i] = tuuid;
2667 VldbEntry->serverUnique[i] = ntohl(exp->ex_uniquifier);
2669 VldbEntry->serverNumber[i].time_low = HostAddress[VlEntry->serverNumber[i]];
2671 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
2674 VldbEntry->nServers = i;
2675 for (i=0; i<MAXTYPES; i++)
2676 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
2677 VldbEntry->cloneId = VlEntry->cloneId;
2678 VldbEntry->flags = VlEntry->flags;
2681 #define LEGALCHARS ".ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
2684 /* Verify that the volname is a valid volume name. */
2686 InvalidVolname(volname)
2693 slen = strlen(volname);
2694 if (slen >= VL_MAXNAMELEN) return 1;
2695 return(slen != strspn(volname, map));
2699 /* Verify that the given volume type is valid. */
2701 InvalidVoltype(voltype)
2704 if (voltype != RWVOL && voltype != ROVOL && voltype != BACKVOL)
2711 InvalidOperation(voloper)
2714 if (voloper != VLOP_MOVE && voloper != VLOP_RELEASE && voloper != VLOP_BACKUP && voloper != VLOP_DELETE && voloper != VLOP_DUMP)
2720 InvalidReleasetype(releasetype)
2721 afs_int32 releasetype;
2723 if ((releasetype & LOCKREL_TIMESTAMP) || (releasetype & LOCKREL_OPCODE) || (releasetype & LOCKREL_AFSID))
2729 IpAddrToRelAddr(ipaddr, atrans)
2730 struct ubik_trans *atrans;
2731 register afs_uint32 ipaddr;
2734 register afs_int32 code, base, index;
2735 struct extentaddr *exp;
2737 for (i = 0; i <= MAXSERVERID; i++) {
2738 if (HostAddress[i] == ipaddr)
2740 if ((HostAddress[i] & 0xff000000) == 0xff000000) {
2741 base = (HostAddress[i] >> 16) & 0xff;
2742 index = HostAddress[i] & 0x0000ffff;
2743 if (base >= VL_MAX_ADDREXTBLKS) {
2744 VLog(0, ("Internal error: Multihome extent base is too large. Base %d index %d\n", base, index));
2745 return -1; /* EINVAL */
2747 if (index >= VL_MHSRV_PERBLK) {
2748 VLog(0, ("Internal error: Multihome extent index is too large. Base %d index %d\n", base, index));
2749 return -1; /* EINVAL */
2751 if (!ex_addr[base]) {
2752 VLog(0, ("Internal error: Multihome extent does not exist. Base %d\n", base));
2753 return -1; /* EINVAL */
2755 exp = &ex_addr[base][index];
2756 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2757 if (exp->ex_addrs[j] && (ntohl(exp->ex_addrs[j]) == ipaddr)) {
2764 /* allocate the new server a server id pronto */
2766 for(i=0;i <= MAXSERVERID;i++) {
2767 if (cheader.IpMappedAddr[i] == 0) {
2768 cheader.IpMappedAddr[i] = htonl(ipaddr);
2769 code = vlwrite(atrans, DOFFSET(0, &cheader, &cheader.IpMappedAddr[i]), (char *) &cheader.IpMappedAddr[i], sizeof(afs_int32));
2770 HostAddress[i] = ipaddr;
2771 if (code) return -1;
2780 ChangeIPAddr(ipaddr1, ipaddr2, atrans)
2781 struct ubik_trans *atrans;
2782 register afs_uint32 ipaddr1, ipaddr2;
2786 struct extentaddr *exp;
2787 int base, index, mhidx;
2789 afs_int32 blockindex, count;
2791 struct nvlentry tentry;
2794 return VL_CREATEFAIL;
2796 /* Don't let addr change to 256.*.*.* : Causes internal error below */
2797 if ((ipaddr2 & 0xff000000) == 0xff000000)
2798 return(VL_BADSERVER);
2800 /* If we are removing an address, ip1 will be -1 and ip2 will be
2801 * the original address. This prevents an older revision vlserver
2802 * from removing the IP address (won't find server 0xfffffff in
2803 * the VLDB). An older revision vlserver does not have the check
2804 * to see if any volumes exist on the server being removed.
2806 if (ipaddr1 == 0xffffffff) {
2811 for (i = 0; i <= MAXSERVERID; i++) {
2812 if ((HostAddress[i] & 0xff000000) == 0xff000000) {
2813 base = (HostAddress[i] >> 16) & 0xff;
2814 index = HostAddress[i] & 0x0000ffff;
2815 if ((base >= VL_MAX_ADDREXTBLKS) || (index >= VL_MHSRV_PERBLK)) {
2816 VLog(0, ("Internal error: Multihome extent addr is too large. Base %d index %d\n",
2818 return -1; /* EINVAL */
2821 exp = &ex_addr[base][index];
2822 for (mhidx=0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2823 if (!exp->ex_addrs[mhidx]) continue;
2824 if (ntohl(exp->ex_addrs[mhidx]) == ipaddr1)
2827 if (mhidx < VL_MAXIPADDRS_PERMH) {
2831 else if (HostAddress[i] == ipaddr1) {
2832 exp = (struct extentaddr *)0;
2837 if (i >= MAXSERVERID) {
2838 return VL_NOENT; /* not found */
2841 /* If we are removing a server entry, a volume cannot
2842 * exist on the server. If one does, don't remove the
2843 * server entry: return error "volume entry exists".
2846 for (blockindex = NextEntry(atrans, 0, &tentry, &count);
2848 blockindex = NextEntry(atrans, blockindex, &tentry, &count)) {
2849 if (++pollcount > 50) {
2853 for (j=0; j<NMAXNSERVERS; j++) {
2854 if (tentry.serverNumber[j] == BADSERVERID) break;
2855 if (tentry.serverNumber[j] == i) {
2862 /* Log a message saying we are changing/removing an IP address */
2863 VLog(0, ("The following IP address is being %s:\n",
2864 (ipaddr2?"changed":"removed")));
2865 printf(" entry %d: ", i);
2868 for (mhidx=0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2869 if (!exp->ex_addrs[mhidx]) continue;
2870 if (mhidx>0) printf(" ");
2871 PADDR(ntohl(exp->ex_addrs[mhidx]));
2883 /* Change the registered uuuid addresses */
2885 bzero(&tuuid, sizeof(afsUUID));
2886 afs_htonuuid(&tuuid);
2887 exp->ex_hostuuid = tuuid;
2888 code = vlwrite(atrans, DOFFSET(ntohl(ex_addr[0]->ex_contaddrs[base]),
2889 (char *)ex_addr[base], (char *)exp),
2890 (char *)&tuuid, sizeof(tuuid));
2895 /* Now change the host address entry */
2896 cheader.IpMappedAddr[i] = htonl(ipaddr2);
2897 code = vlwrite(atrans, DOFFSET(0, &cheader, &cheader.IpMappedAddr[i]), (char *)
2898 &cheader.IpMappedAddr[i], sizeof(afs_int32));
2899 HostAddress[i] = ipaddr2;
2906 /* see if the vlserver is back yet */
2907 VL_ProbeServer(rxcall)
2908 struct rx_call *rxcall; {