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>
15 #include <sys/types.h>
18 #include <afs/afsutil.h>
25 #include <netinet/in.h>
29 #include "afs/audit.h"
36 extern struct afsconf_dir *vldb_confdir;
37 extern struct ubik_dbase *VL_dbase;
38 struct vlheader cheader; /* kept in network byte order */
39 extern afs_uint32 HostAddress[]; /* host addresses kept in host byte order */
41 struct extentaddr *ex_addr[VL_MAX_ADDREXTBLKS] = { 0, 0, 0, 0};
42 static char rxinfo_str[128]; /* Need rxinfo string to be non-local */
43 #define ABORT(c) { errorcode = (c); goto abort; }
45 #define END(c) { errorcode = (c); goto end; }
47 #define VLDBALLOCLIMIT 10000
48 #define VLDBALLOCINCR 2048
50 static int put_attributeentry();
51 static int put_nattributeentry();
52 static int RemoveEntry();
53 static ReleaseEntry();
54 static int check_vldbentry();
55 static int check_nvldbentry();
56 static int vldbentry_to_vlentry();
57 static int nvldbentry_to_vlentry();
58 static get_vldbupdateentry();
59 static int repsite_exists();
60 static repsite_compress();
61 static vlentry_to_vldbentry();
62 static vlentry_to_nvldbentry();
63 static vlentry_to_uvldbentry();
64 static int InvalidVolname();
65 static int InvalidVoltype();
66 static int InvalidOperation();
67 static int InvalidReleasetype();
68 static int IpAddrToRelAddr();
69 static int ChangeIPAddr();
72 struct rx_call *rxcall;
75 register struct rx_connection *tconn;
80 struct in_addr hostAddr;
82 tconn = rx_ConnectionOf(rxcall);
83 hostAddr.s_addr = rx_HostOf(rx_PeerOf(tconn));
84 code = rxkad_GetServerInfo(rxcall->conn, (afs_int32 *) 0, &exp, tname, tinst, tcell, (afs_int32 *) 0);
86 sprintf(rxinfo_str,"%s %s", inet_ntoa(hostAddr), tname);
88 sprintf(rxinfo_str,"%s noauth",inet_ntoa(hostAddr));
92 /* This is called to initialize the database, set the appropriate locks and make sure that the vldb header is valid */
93 int Init_VLdbase (trans, locktype, this_op)
94 struct ubik_trans **trans;
95 int locktype; /* indicate read or write transaction */
98 int errorcode=0, pass, wl;
100 for (pass=1; pass<=3; pass++) {
101 if (pass == 2) { /* take write lock to rebuild the db */
102 errorcode = ubik_BeginTrans (VL_dbase, UBIK_WRITETRANS, trans);
105 else if (locktype == LOCKREAD) {
106 errorcode = ubik_BeginTransReadAny (VL_dbase, UBIK_READTRANS, trans);
110 errorcode = ubik_BeginTrans (VL_dbase, UBIK_WRITETRANS, trans);
116 errorcode = ubik_SetLock (*trans, 1, 1, locktype);
119 ubik_AbortTrans (*trans);
123 /* check that dbase is initialized and setup cheader */
124 /* 2nd pass we try to rebuild the header */
125 errorcode = CheckInit(*trans, ((pass==2)?1:0));
126 if (!errorcode && wl && extent_mod)
127 errorcode = readExtents(*trans); /* Fix the mh extent blocks */
130 ubik_AbortTrans(*trans);
131 /* Only rebuld if the database is empty */
132 /* Exit if can't rebuild */
133 if ((pass == 1) && (errorcode != VL_EMPTY)) return errorcode;
134 if (pass == 2) return errorcode;
136 else { /* No errorcode */
138 ubik_EndTrans(*trans); /* Rebuilt db. End trans, then retake original lock */
141 break; /* didn't rebuild and successful - exit */
149 /* Create a new vldb entry; both new volume id and name must be unique (non-existant in vldb). */
151 SVL_CreateEntry(rxcall, newentry)
152 struct rx_call *rxcall;
153 struct vldbentry *newentry;
154 { struct ubik_trans *trans;
155 afs_int32 errorcode, blockindex;
156 struct nvlentry tentry;
158 COUNT_REQ (VLCREATEENTRY);
159 if (!afsconf_SuperUser(vldb_confdir, rxcall, (char *)0)) {
164 /* Do some validity tests on new entry */
165 if ( (errorcode = check_vldbentry(newentry))
166 || (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
169 VLog(1, ("OCreate Volume %d %s\n", newentry->volumeId[RWVOL], rxinfo(rxcall)));
170 /* XXX shouldn't we check to see if the r/o volume is duplicated? */
171 if (newentry->volumeId[RWVOL]
172 && FindByID(trans, newentry->volumeId[RWVOL], RWVOL, &tentry,
173 &errorcode)) { /* entry already exists, we fail */
174 errorcode = VL_IDEXIST;
176 } else if (errorcode) {
180 /* Is this following check (by volume name) necessary?? */
181 /* If entry already exists, we fail */
182 if (FindByName(trans, newentry->name, &tentry, &errorcode)) {
183 errorcode = VL_NAMEEXIST;
185 } else if (errorcode) {
189 blockindex = AllocBlock(trans, &tentry);
190 if (blockindex == 0) {
191 errorcode = VL_CREATEFAIL;
195 memset(&tentry, 0, sizeof(struct nvlentry));
196 /* Convert to its internal representation; both in host byte order */
197 if (errorcode = vldbentry_to_vlentry(trans, newentry, &tentry)) {
198 FreeBlock(trans, blockindex);
202 /* Actually insert the entry in vldb */
203 errorcode = ThreadVLentry(trans, blockindex, &tentry);
205 FreeBlock(trans, blockindex);
209 errorcode = ubik_EndTrans(trans);
215 ubik_AbortTrans(trans);
218 osi_auditU (rxcall, VLCreateEntryEvent, errorcode,
219 AUD_STR, (newentry ? newentry->name : (char *)0), AUD_END);
224 SVL_CreateEntryN(rxcall, newentry)
225 struct rx_call *rxcall;
226 struct nvldbentry *newentry;
227 { struct ubik_trans *trans;
228 afs_int32 errorcode, blockindex;
229 struct nvlentry tentry;
231 COUNT_REQ (VLCREATEENTRYN);
232 if (!afsconf_SuperUser(vldb_confdir, rxcall, (char *)0)) {
237 /* Do some validity tests on new entry */
238 if ( (errorcode = check_nvldbentry(newentry))
239 || (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
242 VLog(1, ("Create Volume %d %s\n", newentry->volumeId[RWVOL], rxinfo(rxcall)));
243 /* XXX shouldn't we check to see if the r/o volume is duplicated? */
244 if (newentry->volumeId[RWVOL]
245 && FindByID(trans, newentry->volumeId[RWVOL], RWVOL, &tentry,
246 &errorcode)) { /* entry already exists, we fail */
247 errorcode = VL_IDEXIST;
249 } else if (errorcode) {
253 /* Is this following check (by volume name) necessary?? */
254 /* If entry already exists, we fail */
255 if (FindByName(trans, newentry->name, &tentry, &errorcode)) {
256 errorcode = VL_NAMEEXIST;
258 } else if (errorcode) {
262 blockindex = AllocBlock(trans, &tentry);
263 if (blockindex == 0) {
264 errorcode = VL_CREATEFAIL;
268 memset(&tentry, 0, sizeof(struct nvlentry));
269 /* Convert to its internal representation; both in host byte order */
270 if (errorcode = nvldbentry_to_vlentry(trans, newentry, &tentry)) {
271 FreeBlock(trans, blockindex);
275 /* Actually insert the entry in vldb */
276 errorcode = ThreadVLentry(trans, blockindex, &tentry);
278 FreeBlock(trans, blockindex);
282 errorcode = ubik_EndTrans(trans);
288 ubik_AbortTrans(trans);
291 osi_auditU (rxcall, VLCreateEntryEvent, errorcode,
292 AUD_STR, (newentry ? newentry->name : (char *)0), AUD_END);
297 SVL_ChangeAddr(rxcall, ip1, ip2)
298 struct rx_call *rxcall;
300 { struct ubik_trans *trans;
303 COUNT_REQ (VLCHANGEADDR);
304 if (!afsconf_SuperUser(vldb_confdir, rxcall, (char *)0)) {
309 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
312 VLog(1, ("Change Addr %d -> %d %s\n", ip1, ip2, rxinfo(rxcall)));
313 if (errorcode = ChangeIPAddr(ip1, ip2, trans))
316 errorcode = ubik_EndTrans(trans);
322 ubik_AbortTrans(trans);
325 osi_auditU (rxcall, VLChangeAddrEvent, errorcode, AUD_LONG, ip1,
326 AUD_LONG, ip2, AUD_END);
330 /* Delete a vldb entry given the volume id. */
331 SVL_DeleteEntry(rxcall, volid, voltype)
332 struct rx_call *rxcall;
335 { struct ubik_trans *trans;
336 afs_int32 blockindex, errorcode;
337 struct nvlentry tentry;
339 COUNT_REQ (VLDELETEENTRY);
340 if (!afsconf_SuperUser(vldb_confdir, rxcall, (char *)0))
343 if ((voltype != -1 ) && (InvalidVoltype(voltype)))
344 END( VL_BADVOLTYPE );
346 if (errorcode = Init_VLdbase (&trans, LOCKWRITE, this_op))
349 VLog(1, ("Delete Volume %d %s\n", volid, rxinfo(rxcall)));
350 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
351 if (blockindex == 0) { /* volid not found */
352 if (!errorcode) errorcode = VL_NOENT;
356 if (tentry.flags & VLDELETED) { /* Already deleted; return */
357 ABORT( VL_ENTDELETED );
359 if (errorcode = RemoveEntry(trans, blockindex, &tentry)) {
362 errorcode = (ubik_EndTrans(trans));
367 ubik_AbortTrans(trans);
370 osi_auditU (rxcall, VLDeleteEntryEvent, errorcode, AUD_LONG, volid, AUD_END);
375 /* Get a vldb entry given its volume id; make sure it's not a deleted entry. */
376 GetEntryByID (rxcall, volid, voltype, aentry, new, this_op)
377 struct rx_call *rxcall;
379 afs_int32 voltype, new, this_op;
380 char *aentry; /* entry data copied here */
381 { struct ubik_trans *trans;
382 afs_int32 blockindex, errorcode;
383 struct nvlentry tentry;
385 if ((voltype != -1 ) && (InvalidVoltype(voltype)))
386 return VL_BADVOLTYPE;
387 if (errorcode = Init_VLdbase (&trans, LOCKREAD, this_op))
390 VLog(5, ("GetVolumeByID %d (%d) %s\n", volid, new, rxinfo(rxcall)));
391 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
392 if (blockindex == 0) { /* entry not found */
393 if (!errorcode) errorcode = VL_NOENT;
395 ubik_AbortTrans (trans);
398 if (tentry.flags & VLDELETED) { /* Entry is deleted! */
400 ubik_AbortTrans (trans);
401 return VL_ENTDELETED;
403 /* Convert from the internal to external form */
405 vlentry_to_nvldbentry(&tentry, (struct nvldbentry *)aentry);
407 vlentry_to_uvldbentry(&tentry, (struct uvldbentry *)aentry);
409 vlentry_to_vldbentry(&tentry, (struct vldbentry *)aentry);
410 return(ubik_EndTrans(trans));
413 SVL_GetEntryByID (rxcall, volid, voltype, aentry)
414 struct rx_call *rxcall;
415 afs_int32 volid, voltype;
416 vldbentry *aentry; /* entry data copied here */
418 COUNT_REQ (VLGETENTRYBYID);
419 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 0, this_op));
422 SVL_GetEntryByIDN (rxcall, volid, voltype, aentry)
423 struct rx_call *rxcall;
424 afs_int32 volid, voltype;
425 nvldbentry *aentry; /* entry data copied here */
427 COUNT_REQ (VLGETENTRYBYIDN);
428 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 1, this_op));
431 SVL_GetEntryByIDU (rxcall, volid, voltype, aentry)
432 struct rx_call *rxcall;
433 afs_int32 volid, voltype;
434 uvldbentry *aentry; /* entry data copied here */
436 COUNT_REQ (VLGETENTRYBYIDU);
437 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 2, this_op));
442 /* returns true if the id is a decimal integer, in which case we interpret it
443 as an id. make the cache manager much simpler */
444 static int NameIsId(aname)
445 register char *aname; {
447 while (tc = *aname++) {
448 if (tc > '9' || tc < '0') return 0;
453 /* Get a vldb entry given the volume's name; of course, very similar to VLGetEntryByID() above. */
454 GetEntryByName (rxcall, volname, aentry, new, this_op)
455 struct rx_call *rxcall;
457 char *aentry; /* entry data copied here */
459 { struct ubik_trans *trans;
460 afs_int32 blockindex, errorcode;
461 struct nvlentry tentry;
463 if (NameIsId(volname)) {
464 return GetEntryByID(rxcall, atoi(volname), -1, aentry, new, this_op);
466 if (InvalidVolname(volname))
468 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
470 VLog(5, ("GetVolumeByName %s (%d) %s\n", volname, new, rxinfo(rxcall)));
471 blockindex = FindByName(trans, volname, &tentry, &errorcode);
472 if (blockindex == 0) { /* entry not found */
473 if (!errorcode) errorcode = VL_NOENT;
475 ubik_AbortTrans(trans);
478 if (tentry.flags & VLDELETED) { /* Entry is deleted */
480 ubik_AbortTrans(trans);
481 return VL_ENTDELETED;
483 /* Convert to external entry representation */
485 vlentry_to_nvldbentry(&tentry, (struct nvldbentry *)aentry);
487 vlentry_to_uvldbentry(&tentry, (struct uvldbentry *)aentry);
489 vlentry_to_vldbentry(&tentry, (struct vldbentry *)aentry);
490 return(ubik_EndTrans(trans));
493 SVL_GetEntryByNameO (rxcall, volname, aentry)
494 struct rx_call *rxcall;
496 struct vldbentry *aentry; /* entry data copied here */
498 COUNT_REQ (VLGETENTRYBYNAME);
499 return (GetEntryByName(rxcall, volname, (char *)aentry, 0, this_op));
503 SVL_GetEntryByNameN (rxcall, volname, aentry)
504 struct rx_call *rxcall;
506 struct nvldbentry *aentry; /* entry data copied here */
508 COUNT_REQ (VLGETENTRYBYNAMEN);
509 return (GetEntryByName(rxcall, volname, (char *)aentry, 1, this_op));
512 SVL_GetEntryByNameU (rxcall, volname, aentry)
513 struct rx_call *rxcall;
515 struct uvldbentry *aentry; /* entry data copied here */
517 COUNT_REQ (VLGETENTRYBYNAMEU);
518 return (GetEntryByName(rxcall, volname, (char *)aentry, 2, this_op));
523 /* Get the current value of the maximum volume id and bump the volume id counter by Maxvolidbump. */
524 SVL_GetNewVolumeId (rxcall, Maxvolidbump, newvolumeid)
525 struct rx_call *rxcall;
526 afs_int32 Maxvolidbump;
527 afs_int32 *newvolumeid;
528 { register afs_int32 errorcode, maxvolumeid;
529 struct ubik_trans *trans;
531 COUNT_REQ (VLGETNEWVOLUMEID);
532 if (!afsconf_SuperUser(vldb_confdir, rxcall, (char *)0))
535 if (Maxvolidbump < 0 || Maxvolidbump > MAXBUMPCOUNT)
536 END ( VL_BADVOLIDBUMP );
538 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
541 *newvolumeid = maxvolumeid = ntohl(cheader.vital_header.MaxVolumeId);
542 maxvolumeid += Maxvolidbump;
543 VLog(1, ("GetNewVolid newmax=%d %s\n", maxvolumeid, rxinfo(rxcall)));
544 cheader.vital_header.MaxVolumeId = htonl(maxvolumeid);
545 if (write_vital_vlheader(trans)) {
548 errorcode = (ubik_EndTrans(trans));
553 ubik_AbortTrans(trans);
556 osi_auditU (rxcall, VLGetNewVolumeIdEvent, errorcode, AUD_END);
561 /* Simple replace the contents of the vldb entry, volid, with
562 * newentry. No individual checking/updating per field (alike
563 * VLUpdateEntry) is done. */
565 SVL_ReplaceEntry (rxcall, volid, voltype, newentry, releasetype)
566 struct rx_call *rxcall;
569 struct vldbentry *newentry;
570 afs_int32 releasetype;
571 { struct ubik_trans *trans;
572 afs_int32 blockindex, errorcode, typeindex;
574 int hashVol[MAXTYPES];
575 struct nvlentry tentry;
577 COUNT_REQ (VLREPLACEENTRY);
578 for(typeindex = 0; typeindex < MAXTYPES; typeindex++)
579 hashVol[typeindex] = 0;
581 if (!afsconf_SuperUser(vldb_confdir, rxcall, (char *)0))
584 if (errorcode = check_vldbentry(newentry))
587 if (voltype != -1 && InvalidVoltype(voltype))
588 END ( VL_BADVOLTYPE );
590 if (releasetype && InvalidReleasetype(releasetype))
591 END( VL_BADRELLOCKTYPE );
592 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
595 VLog(1, ("OReplace Volume %d %s\n", volid, rxinfo(rxcall)));
596 /* find vlentry we're changing */
597 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
598 if (blockindex == 0) { /* entry not found */
599 if (!errorcode) errorcode = VL_NOENT;
603 /* check that we're not trying to change the RW vol ID */
604 if (newentry->volumeId[RWVOL] != tentry.volumeId[RWVOL]) {
605 ABORT( VL_BADENTRY );
608 /* unhash volid entries if they're disappearing or changing.
609 * Remember if we need to hash in the new value (we don't have to
610 * rehash if volid stays same */
611 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
612 if (tentry.volumeId[typeindex] != newentry->volumeId[typeindex]) {
613 if (tentry.volumeId[typeindex])
614 if (errorcode = UnhashVolid(trans, typeindex, blockindex,
618 /* we must rehash new id if the id is different and the ID is nonzero */
619 hashVol[typeindex] = 1; /* must rehash this guy if he exists */
623 /* Rehash volname if it changes */
624 if (strcmp(newentry->name, tentry.name)) { /* Name changes; redo hashing */
625 if (errorcode = UnhashVolname(trans, blockindex, &tentry)) {
631 /* after this, tentry is new entry, not old one. vldbentry_to_vlentry
632 doesn't touch hash chains */
633 if (errorcode = vldbentry_to_vlentry(trans, newentry, &tentry)) {
637 for(typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
638 if (hashVol[typeindex] && tentry.volumeId[typeindex]) {
639 if (errorcode = HashVolid(trans, typeindex, blockindex, &tentry)) {
646 HashVolname(trans, blockindex, &tentry);
649 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
650 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
654 END (ubik_EndTrans(trans));
658 ubik_AbortTrans(trans);
661 osi_auditU (rxcall, VLReplaceVLEntryEvent, errorcode, AUD_LONG, volid, AUD_END);
665 SVL_ReplaceEntryN (rxcall, volid, voltype, newentry, releasetype)
666 struct rx_call *rxcall;
669 struct nvldbentry *newentry;
670 afs_int32 releasetype;
671 { struct ubik_trans *trans;
672 afs_int32 blockindex, errorcode, typeindex;
674 int hashVol[MAXTYPES];
675 struct nvlentry tentry;
677 COUNT_REQ (VLREPLACEENTRYN);
678 for(typeindex = 0; typeindex < MAXTYPES; typeindex++)
679 hashVol[typeindex] = 0;
681 if (!afsconf_SuperUser(vldb_confdir, rxcall, (char *)0))
684 if (errorcode = check_nvldbentry(newentry))
687 if (voltype != -1 && InvalidVoltype(voltype))
688 END ( VL_BADVOLTYPE );
690 if (releasetype && InvalidReleasetype(releasetype))
691 END( VL_BADRELLOCKTYPE );
692 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
695 VLog(1, ("Replace Volume %d %s\n", volid, rxinfo(rxcall)));
696 /* find vlentry we're changing */
697 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
698 if (blockindex == 0) { /* entry not found */
699 if (!errorcode) errorcode = VL_NOENT;
703 /* check that we're not trying to change the RW vol ID */
704 if (newentry->volumeId[RWVOL] != tentry.volumeId[RWVOL]) {
705 ABORT( VL_BADENTRY );
708 /* unhash volid entries if they're disappearing or changing.
709 * Remember if we need to hash in the new value (we don't have to
710 * rehash if volid stays same */
711 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
712 if (tentry.volumeId[typeindex] != newentry->volumeId[typeindex]) {
713 if (tentry.volumeId[typeindex])
714 if (errorcode = UnhashVolid(trans, typeindex, blockindex,
718 /* we must rehash new id if the id is different and the ID is nonzero */
719 hashVol[typeindex] = 1; /* must rehash this guy if he exists */
723 /* Rehash volname if it changes */
724 if (strcmp(newentry->name, tentry.name)) { /* Name changes; redo hashing */
725 if (errorcode = UnhashVolname(trans, blockindex, &tentry)) {
731 /* after this, tentry is new entry, not old one. vldbentry_to_vlentry
732 doesn't touch hash chains */
733 if (errorcode = nvldbentry_to_vlentry(trans, newentry, &tentry)) {
737 for(typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
738 if (hashVol[typeindex] && tentry.volumeId[typeindex]) {
739 if (errorcode = HashVolid(trans, typeindex, blockindex, &tentry)) {
746 HashVolname(trans, blockindex, &tentry);
749 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
750 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
754 END (ubik_EndTrans(trans));
758 ubik_AbortTrans(trans);
761 osi_auditU (rxcall, VLReplaceVLEntryEvent, errorcode, AUD_LONG, volid, AUD_END);
766 /* 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. */
767 /* this routine may never have been tested; use replace entry instead unless you're brave */
768 SVL_UpdateEntry (rxcall, volid, voltype, updateentry, releasetype)
769 struct rx_call *rxcall;
772 afs_int32 releasetype;
773 struct VldbUpdateEntry *updateentry; /* Update entry copied here */
774 { struct ubik_trans *trans;
775 afs_int32 blockindex, errorcode;
776 struct nvlentry tentry;
778 COUNT_REQ (VLUPDATEENTRY);
779 if (!afsconf_SuperUser(vldb_confdir, rxcall, (char *)0))
781 if ((voltype != -1 ) && (InvalidVoltype(voltype)))
782 END( VL_BADVOLTYPE );
783 if (releasetype && InvalidReleasetype(releasetype))
784 END( VL_BADRELLOCKTYPE );
785 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
788 VLog(1, ("Update Volume %d %s\n", volid, rxinfo(rxcall)));
789 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
790 if (blockindex == 0) { /* entry not found */
791 if (!errorcode) errorcode = VL_NOENT;
795 /* Do the actual updating of the entry, tentry. */
796 if (errorcode = get_vldbupdateentry(trans, blockindex, updateentry, &tentry)) {
800 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
801 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
804 END(ubik_EndTrans(trans));
808 ubik_AbortTrans(trans);
811 osi_auditU (rxcall, VLUpdateEntryEvent, errorcode, AUD_LONG, volid, AUD_END);
816 SVL_UpdateEntryByName (rxcall, volname, updateentry, releasetype)
817 struct rx_call *rxcall;
819 afs_int32 releasetype;
820 struct VldbUpdateEntry *updateentry; /* Update entry copied here */
821 { struct ubik_trans *trans;
822 afs_int32 blockindex, errorcode;
823 struct nvlentry tentry;
825 COUNT_REQ (VLUPDATEENTRYBYNAME);
826 if (!afsconf_SuperUser(vldb_confdir, rxcall, (char *)0))
828 if (releasetype && InvalidReleasetype(releasetype))
829 END( VL_BADRELLOCKTYPE );
830 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
833 blockindex = FindByName(trans, volname, &tentry, &errorcode);
834 if (blockindex == 0) { /* entry not found */
835 if (!errorcode) errorcode = VL_NOENT;
839 /* Do the actual updating of the entry, tentry. */
840 if (errorcode = get_vldbupdateentry(trans, blockindex, updateentry, &tentry)) {
844 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
845 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
848 END(ubik_EndTrans(trans));
852 ubik_AbortTrans(trans);
855 osi_auditU (rxcall, VLUpdateEntryEvent, errorcode, AUD_LONG, -1, AUD_END);
860 /* Set a lock to the vldb entry for volid (of type voltype if not -1). */
861 SVL_SetLock (rxcall, volid, voltype, voloper)
862 struct rx_call *rxcall;
866 { afs_int32 timestamp, blockindex, errorcode;
867 struct ubik_trans *trans;
868 struct nvlentry tentry;
870 COUNT_REQ(VLSETLOCK);
871 if (!afsconf_SuperUser(vldb_confdir, rxcall, (char *)0))
873 if ((voltype != -1 ) && (InvalidVoltype(voltype)))
874 END( VL_BADVOLTYPE );
875 if (InvalidOperation(voloper))
876 END( VL_BADVOLOPER );
877 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
880 VLog(1, ("SetLock Volume %d %s\n", volid, rxinfo(rxcall)));
881 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
882 if (blockindex == NULLO) {
883 if (!errorcode) errorcode = VL_NOENT;
886 if (tentry.flags & VLDELETED) {
887 ABORT( VL_ENTDELETED );
889 timestamp = FT_ApproxTime();
891 /* Check if entry is already locked; note that we unlock any entry
892 * locked more than MAXLOCKTIME seconds */
893 if ((tentry.LockTimestamp)
894 && ((timestamp - tentry.LockTimestamp) < MAXLOCKTIME)) {
895 ABORT( VL_ENTRYLOCKED );
898 /* Consider it an unlocked entry: set current timestamp, caller
899 * and active vol operation */
900 tentry.LockTimestamp = timestamp;
901 tentry.LockAfsId = 0; /* Not implemented yet */
902 if (tentry.flags & VLOP_RELEASE) {
903 ABORT( VL_RERELEASE );
905 tentry.flags &= ~VLOP_ALLOPERS; /* Clear any possible older operation bit */
906 tentry.flags |= voloper;
908 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
911 END(ubik_EndTrans(trans));
915 ubik_AbortTrans(trans);
918 osi_auditU (rxcall, VLSetLockEvent, errorcode, AUD_LONG, volid, AUD_END);
923 /* Release an already locked vldb entry. Releasetype determines what
924 * fields (afsid and/or volume operation) will be cleared along with
925 * the lock time stamp. */
927 SVL_ReleaseLock (rxcall, volid, voltype, releasetype)
928 struct rx_call *rxcall;
931 afs_int32 releasetype;
932 { afs_int32 blockindex, errorcode;
933 struct ubik_trans *trans;
934 struct nvlentry tentry;
936 COUNT_REQ(VLRELEASELOCK);
937 if (!afsconf_SuperUser(vldb_confdir, rxcall, (char *)0))
939 if ((voltype != -1 ) && (InvalidVoltype(voltype)))
940 END( VL_BADVOLTYPE );
941 if (releasetype && InvalidReleasetype(releasetype))
942 END( VL_BADRELLOCKTYPE );
943 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
946 VLog(1, ("ReleaseLock Volume %d %s\n", volid, rxinfo(rxcall)));
947 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
948 if (blockindex == NULLO) {
949 if (!errorcode) errorcode = VL_NOENT;
952 if (tentry.flags & VLDELETED) {
953 ABORT( VL_ENTDELETED );
956 ReleaseEntry(&tentry, releasetype); /* Unlock the appropriate fields */
957 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
960 END(ubik_EndTrans(trans));
964 ubik_AbortTrans(trans);
967 osi_auditU (rxcall, VLReleaseLockEvent, errorcode, AUD_LONG, volid, AUD_END);
972 /* 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. */
973 SVL_ListEntry (rxcall, previous_index, count, next_index, aentry)
974 struct rx_call *rxcall;
975 afs_int32 previous_index;
977 afs_int32 *next_index;
978 struct vldbentry *aentry;
980 struct ubik_trans *trans;
981 struct nvlentry tentry;
983 COUNT_REQ(VLLISTENTRY);
984 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
986 VLog(25, ("OListEntry index=%d %s\n", previous_index, rxinfo(rxcall)));
987 *next_index = NextEntry(trans, previous_index, &tentry, count);
989 vlentry_to_vldbentry(&tentry, aentry);
990 return(ubik_EndTrans(trans));
993 /* 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. */
994 SVL_ListEntryN (rxcall, previous_index, count, next_index, aentry)
995 struct rx_call *rxcall;
996 afs_int32 previous_index;
998 afs_int32 *next_index;
999 struct nvldbentry *aentry;
1001 struct ubik_trans *trans;
1002 struct nvlentry tentry;
1004 COUNT_REQ(VLLISTENTRYN);
1005 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1007 VLog(25, ("ListEntry index=%d %s\n", previous_index, rxinfo(rxcall)));
1008 *next_index = NextEntry(trans, previous_index, &tentry, count);
1010 vlentry_to_nvldbentry(&tentry, aentry);
1011 return(ubik_EndTrans(trans));
1015 /* 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. */
1016 SVL_ListAttributes(rxcall, attributes, nentries, vldbentries)
1017 struct rx_call *rxcall;
1018 struct VldbListByAttributes *attributes;
1019 afs_int32 *nentries;
1020 bulkentries *vldbentries;
1021 { int errorcode, allocCount = 0;
1022 struct ubik_trans *trans;
1023 struct nvlentry tentry;
1024 struct vldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1027 COUNT_REQ (VLLISTATTRIBUTES);
1028 vldbentries->bulkentries_val = 0;
1029 vldbentries->bulkentries_len = *nentries = 0;
1030 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1032 allocCount = VLDBALLOCCOUNT;
1033 Vldbentry = VldbentryFirst = vldbentries->bulkentries_val = (vldbentry *)malloc(allocCount * sizeof(vldbentry));
1034 if (Vldbentry == NULL) {
1036 ubik_AbortTrans(trans);
1039 VldbentryLast = VldbentryFirst + allocCount;
1040 /* Handle the attribute by volume id totally separate of the rest (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!) */
1041 if (attributes->Mask & VLLIST_VOLUMEID) {
1042 afs_int32 blockindex;
1044 blockindex = FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1045 if (blockindex == 0) {
1046 if (!errorcode) errorcode = VL_NOENT;
1048 ubik_AbortTrans(trans);
1049 if(vldbentries->bulkentries_val)free((char *)vldbentries->bulkentries_val);
1050 vldbentries->bulkentries_val = 0;
1051 vldbentries->bulkentries_len = 0;
1054 if (errorcode = put_attributeentry(&Vldbentry, &VldbentryFirst, &VldbentryLast, vldbentries, &tentry, nentries, &allocCount)) {
1056 ubik_AbortTrans(trans);
1057 if(vldbentries->bulkentries_val)free((char *)vldbentries->bulkentries_val);
1058 vldbentries->bulkentries_val = 0;
1059 vldbentries->bulkentries_len = 0;
1060 return VL_SIZEEXCEEDED;
1063 afs_int32 nextblockindex=0, count=0, k, match=0;
1064 while (nextblockindex = NextEntry(trans, nextblockindex, &tentry, &count)) {
1065 if (++pollcount > 50) {
1070 if (attributes->Mask & VLLIST_SERVER) {
1072 if ((serverindex = IpAddrToRelAddr(attributes->server, (struct ubik_trans *) 0)) == -1) continue;
1073 for (k=0; k<OMAXNSERVERS;k++) {
1074 if (tentry.serverNumber[k] == BADSERVERID) break;
1075 if (tentry.serverNumber[k] == serverindex) {
1080 if (!match) continue;
1082 if (attributes->Mask & VLLIST_PARTITION) {
1084 if (tentry.serverPartition[k] != attributes->partition) continue;
1086 for (k=0; k<OMAXNSERVERS;k++) {
1087 if (tentry.serverNumber[k] == BADSERVERID) break;
1088 if (tentry.serverPartition[k] == attributes->partition) {
1093 if (!match) continue;
1097 if (attributes->Mask & VLLIST_FLAG) {
1098 if (!(tentry.flags & attributes->flag)) continue;
1100 if (errorcode = put_attributeentry(&Vldbentry, &VldbentryFirst, &VldbentryLast, vldbentries, &tentry, nentries, &allocCount)) {
1102 ubik_AbortTrans(trans);
1103 if(vldbentries->bulkentries_val)free((char *)vldbentries->bulkentries_val);
1104 vldbentries->bulkentries_val = 0;
1105 vldbentries->bulkentries_len = 0;
1110 if (vldbentries->bulkentries_len && (allocCount > vldbentries->bulkentries_len)) {
1112 vldbentries->bulkentries_val = (vldbentry *) realloc(vldbentries->bulkentries_val, vldbentries->bulkentries_len * sizeof(vldbentry));
1113 if (vldbentries->bulkentries_val == NULL) {
1115 ubik_AbortTrans(trans);
1119 VLog(5, ("ListAttrs nentries=%d %s\n", vldbentries->bulkentries_len, rxinfo(rxcall)));
1120 return(ubik_EndTrans(trans));
1123 SVL_ListAttributesN(rxcall, attributes, nentries, vldbentries)
1124 struct rx_call *rxcall;
1125 struct VldbListByAttributes *attributes;
1126 afs_int32 *nentries;
1127 nbulkentries *vldbentries;
1128 { int errorcode, allocCount = 0;
1129 struct ubik_trans *trans;
1130 struct nvlentry tentry;
1131 struct nvldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1134 COUNT_REQ (VLLISTATTRIBUTESN);
1135 vldbentries->nbulkentries_val = 0;
1136 vldbentries->nbulkentries_len = *nentries = 0;
1137 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1139 allocCount = VLDBALLOCCOUNT;
1140 Vldbentry = VldbentryFirst = vldbentries->nbulkentries_val = (nvldbentry *)malloc(allocCount * sizeof(nvldbentry));
1141 if (Vldbentry == NULL) {
1143 ubik_AbortTrans(trans);
1146 VldbentryLast = VldbentryFirst + allocCount;
1147 /* Handle the attribute by volume id totally separate of the rest (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!) */
1148 if (attributes->Mask & VLLIST_VOLUMEID) {
1149 afs_int32 blockindex;
1151 blockindex = FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1152 if (blockindex == 0) {
1153 if (!errorcode) errorcode = VL_NOENT;
1155 ubik_AbortTrans(trans);
1156 if(vldbentries->nbulkentries_val)free((char *)vldbentries->nbulkentries_val);
1157 vldbentries->nbulkentries_val = 0;
1158 vldbentries->nbulkentries_len = 0;
1161 if (errorcode = put_nattributeentry(&Vldbentry, &VldbentryFirst, &VldbentryLast, vldbentries,
1162 &tentry, 0, 0, nentries, &allocCount)) {
1164 ubik_AbortTrans(trans);
1165 if(vldbentries->nbulkentries_val)free((char *)vldbentries->nbulkentries_val);
1166 vldbentries->nbulkentries_val = 0;
1167 vldbentries->nbulkentries_len = 0;
1168 return VL_SIZEEXCEEDED;
1171 afs_int32 nextblockindex=0, count=0, k, match=0;
1172 while (nextblockindex = NextEntry(trans, nextblockindex, &tentry, &count)) {
1173 if (++pollcount > 50) {
1179 if (attributes->Mask & VLLIST_SERVER) {
1181 if ((serverindex = IpAddrToRelAddr(attributes->server, (struct ubik_trans *) 0)) == -1) continue;
1182 for (k=0; k<NMAXNSERVERS;k++) {
1183 if (tentry.serverNumber[k] == BADSERVERID) break;
1184 if (tentry.serverNumber[k] == serverindex) {
1189 if (!match) continue;
1191 if (attributes->Mask & VLLIST_PARTITION) {
1193 if (tentry.serverPartition[k] != attributes->partition) continue;
1195 for (k=0; k<NMAXNSERVERS;k++) {
1196 if (tentry.serverNumber[k] == BADSERVERID) break;
1197 if (tentry.serverPartition[k] == attributes->partition) {
1202 if (!match) continue;
1206 if (attributes->Mask & VLLIST_FLAG) {
1207 if (!(tentry.flags & attributes->flag)) continue;
1209 if (errorcode = put_nattributeentry(&Vldbentry, &VldbentryFirst, &VldbentryLast,
1210 vldbentries, &tentry, 0, 0, nentries, &allocCount)) {
1212 ubik_AbortTrans(trans);
1213 if(vldbentries->nbulkentries_val)free((char *)vldbentries->nbulkentries_val);
1214 vldbentries->nbulkentries_val = 0;
1215 vldbentries->nbulkentries_len = 0;
1220 if (vldbentries->nbulkentries_len && (allocCount > vldbentries->nbulkentries_len)) {
1222 vldbentries->nbulkentries_val = (nvldbentry *) realloc(vldbentries->nbulkentries_val,
1223 vldbentries->nbulkentries_len * sizeof(nvldbentry));
1224 if (vldbentries->nbulkentries_val == NULL) {
1226 ubik_AbortTrans(trans);
1230 VLog(5, ("NListAttrs nentries=%d %s\n", vldbentries->nbulkentries_len, rxinfo(rxcall)));
1231 return(ubik_EndTrans(trans));
1235 SVL_ListAttributesN2(rxcall, attributes, name, startindex, nentries, vldbentries, nextstartindex)
1236 struct rx_call *rxcall;
1237 struct VldbListByAttributes *attributes;
1238 char * name; /* Wildcarded volume name */
1239 afs_int32 startindex;
1240 afs_int32 *nentries;
1241 nbulkentries *vldbentries;
1242 afs_int32 *nextstartindex;
1244 int errorcode=0, maxCount=VLDBALLOCCOUNT;
1245 struct ubik_trans *trans;
1246 struct nvlentry tentry;
1247 struct nvldbentry *Vldbentry=0, *VldbentryFirst=0, *VldbentryLast=0;
1248 afs_int32 blockindex=0, count=0, k, match, matchindex;
1249 int serverindex=-1; /* no server found */
1250 int findserver=0, findpartition=0, findflag=0, findname=0;
1253 int namematchRWBK, namematchRO, thismatch, matchtype;
1254 char volumename[VL_MAXNAMELEN];
1256 COUNT_REQ (VLLISTATTRIBUTESN2);
1257 vldbentries->nbulkentries_val = 0;
1258 vldbentries->nbulkentries_len = 0;
1260 *nextstartindex = -1;
1262 errorcode = Init_VLdbase(&trans, LOCKREAD, this_op);
1263 if (errorcode) return errorcode;
1265 Vldbentry = VldbentryFirst = vldbentries->nbulkentries_val = (nvldbentry *)malloc(maxCount * sizeof(nvldbentry));
1266 if (Vldbentry == NULL) {
1268 ubik_AbortTrans(trans);
1272 VldbentryLast = VldbentryFirst + maxCount;
1274 /* Handle the attribute by volume id totally separate of the rest
1275 * (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!)
1277 if (attributes->Mask & VLLIST_VOLUMEID) {
1278 blockindex = FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1279 if (blockindex == 0) {
1280 if (!errorcode) errorcode = VL_NOENT;
1282 errorcode = put_nattributeentry(&Vldbentry, &VldbentryFirst, &VldbentryLast,
1283 vldbentries, &tentry, 0, 0, nentries, &maxCount);
1284 if (errorcode) goto done;
1288 /* Search each entry in the database and return all entries
1289 * that match the request. It checks volumename (with
1290 * wildcarding), entry flags, server, and partition.
1293 /* Get the server index for matching server address */
1294 if (attributes->Mask & VLLIST_SERVER) {
1295 serverindex = IpAddrToRelAddr(attributes->server, (struct ubik_trans *)0);
1296 if (serverindex == -1) goto done;
1299 findpartition = ((attributes->Mask & VLLIST_PARTITION) ? 1 : 0);
1300 findflag = ((attributes->Mask & VLLIST_FLAG) ? 1 : 0);
1301 if (name && (strcmp(name,".*") != 0) && (strcmp(name,"") != 0)) {
1302 sprintf(volumename, "^%s$", name);
1303 t = (char *)re_comp(volumename);
1305 errorcode = VL_BADNAME;
1311 /* Read each entry and see if it is the one we want */
1312 blockindex = startindex;
1313 while (blockindex = NextEntry(trans, blockindex, &tentry, &count)) {
1314 if (++pollcount > 50) {
1319 /* Step through each server index searching for a match.
1320 * Match to an existing RW, BK, or RO volume name (preference
1321 * is in this order). Remember which index we matched against.
1323 namematchRWBK = namematchRO = 0; /* 0->notTried; 1->match; 2->noMatch */
1325 for (k=0; (k<NMAXNSERVERS && (tentry.serverNumber[k]!=BADSERVERID)); k++) {
1326 thismatch = 0; /* does this index match */
1328 /* Match against the RW or BK volume name. Remember
1329 * results in namematchRWBK. Prefer RW over BK.
1331 if (tentry.serverFlags[k] & VLSF_RWVOL) {
1332 /* Does the name match the RW name */
1333 if (tentry.flags & VLF_RWEXISTS) {
1335 sprintf(volumename, "%s", tentry.name);
1336 if (re_exec(volumename)) {
1337 thismatch = VLSF_RWVOL;
1340 thismatch = VLSF_RWVOL;
1344 /* Does the name match the BK name */
1345 if (!thismatch && (tentry.flags & VLF_BACKEXISTS)) {
1347 sprintf(volumename, "%s.backup", tentry.name);
1348 if (re_exec(volumename)) {
1349 thismatch = VLSF_BACKVOL;
1352 thismatch = VLSF_BACKVOL;
1356 namematchRWBK = (thismatch?1:2);
1359 /* Match with the RO volume name. Compare once and
1360 * remember results in namematchRO. Note that this will
1361 * pick up entries marked NEWREPSITEs and DONTUSE.
1364 if (tentry.flags & VLF_ROEXISTS) {
1367 thismatch = ((namematchRO == 1)?VLSF_ROVOL:0);
1369 sprintf(volumename, "%s.readonly", tentry.name);
1370 if (re_exec(volumename))
1371 thismatch = VLSF_ROVOL;
1374 thismatch = VLSF_ROVOL;
1377 namematchRO = (thismatch?1:2);
1380 /* Is there a server match */
1381 if (thismatch && findserver &&
1382 (tentry.serverNumber[k] != serverindex))
1385 /* Is there a partition match */
1386 if (thismatch && findpartition &&
1387 (tentry.serverPartition[k] != attributes->partition))
1390 /* Is there a flag match */
1391 if (thismatch && findflag && !(tentry.flags & attributes->flag))
1394 /* We found a match. Remember the index, and type */
1398 matchtype = thismatch;
1401 /* Since we prefer RW and BK volume matches over RO matches,
1402 * if we have already checked the RWBK name, then we already
1403 * found the best match and so end the search.
1405 * If we tried matching against the RW, BK, and RO volume names
1406 * and both failed, then we end the search (none will match).
1408 if ( (match && namematchRWBK) ||
1409 ((namematchRWBK==2) && (namematchRO==2)) )
1413 /* Passed all the tests. Take it */
1415 errorcode = put_nattributeentry(&Vldbentry,
1416 &VldbentryFirst, &VldbentryLast,
1417 vldbentries, &tentry, matchtype, matchindex,
1418 nentries, &maxCount);
1419 if (errorcode) goto done;
1421 if (*nentries >= maxCount) break; /* collected the max */
1424 *nextstartindex = (blockindex ? blockindex : -1);
1430 ubik_AbortTrans(trans);
1431 if (vldbentries->nbulkentries_val)
1432 free((char *)vldbentries->nbulkentries_val);
1433 vldbentries->nbulkentries_val = 0;
1434 vldbentries->nbulkentries_len = 0;
1435 *nextstartindex = -1;
1438 VLog(5, ("N2ListAttrs nentries=%d %s\n", vldbentries->nbulkentries_len, rxinfo(rxcall)));
1439 return(ubik_EndTrans(trans));
1444 /* Retrieves in vldbentries all vldb entries that match the specified
1445 * attributes (by server number, partition, volume type, and flag); if
1446 * volume id is specified then the associated list for that entry is
1447 * returned. CAUTION: This could be a very expensive call since in most
1448 * cases sequential search of all vldb entries is performed.
1450 SVL_LinkedList(rxcall, attributes, nentries, vldbentries)
1451 struct rx_call *rxcall;
1452 struct VldbListByAttributes *attributes;
1453 afs_int32 *nentries;
1454 vldb_list *vldbentries;
1457 struct ubik_trans *trans;
1458 struct nvlentry tentry;
1459 vldblist vllist, *vllistptr;
1460 afs_int32 blockindex, count, k, match;
1464 COUNT_REQ (VLLINKEDLIST);
1465 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1469 vldbentries->node = NULL;
1470 vllistptr = &vldbentries->node;
1472 /* List by volumeid */
1473 if (attributes->Mask & VLLIST_VOLUMEID) {
1474 blockindex = FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1477 ubik_AbortTrans(trans);
1478 return (errorcode ? errorcode : VL_NOENT);
1481 vllist = (single_vldbentry *) malloc(sizeof(single_vldbentry));
1482 if (vllist == NULL) {
1484 ubik_AbortTrans(trans);
1487 vlentry_to_vldbentry(&tentry, &vllist->VldbEntry);
1488 vllist->next_vldb = NULL;
1490 *vllistptr = vllist; /* Thread onto list */
1491 vllistptr = &vllist->next_vldb;
1495 /* Search by server, partition, and flags */
1497 for (blockindex = NextEntry(trans, 0, &tentry, &count);
1499 blockindex = NextEntry(trans, blockindex, &tentry, &count)) {
1502 if (++pollcount > 50) {
1507 /* Does this volume exist on the desired server */
1508 if (attributes->Mask & VLLIST_SERVER) {
1509 serverindex = IpAddrToRelAddr(attributes->server, (struct ubik_trans *)0);
1510 if (serverindex == -1) continue;
1511 for (k=0; k < OMAXNSERVERS; k++) {
1512 if (tentry.serverNumber[k] == BADSERVERID) break;
1513 if (tentry.serverNumber[k] == serverindex) {
1518 if (!match) continue;
1521 /* Does this volume exist on the desired partition */
1522 if (attributes->Mask & VLLIST_PARTITION) {
1524 if (tentry.serverPartition[k] != attributes->partition)
1527 for (k=0; k < OMAXNSERVERS; k++) {
1528 if (tentry.serverNumber[k] == BADSERVERID) break;
1529 if (tentry.serverPartition[k] == attributes->partition) {
1535 if (!match) continue;
1538 /* Does this volume have the desired flags */
1539 if (attributes->Mask & VLLIST_FLAG) {
1540 if (!(tentry.flags & attributes->flag))
1544 vllist = (single_vldbentry *) malloc(sizeof(single_vldbentry));
1545 if (vllist == NULL) {
1547 ubik_AbortTrans(trans);
1550 vlentry_to_vldbentry(&tentry, &vllist->VldbEntry);
1551 vllist->next_vldb = NULL;
1553 *vllistptr = vllist; /* Thread onto list */
1554 vllistptr = &vllist->next_vldb;
1556 if (smallMem && (*nentries >= VLDBALLOCCOUNT)) {
1558 ubik_AbortTrans(trans);
1559 return VL_SIZEEXCEEDED;
1564 return(ubik_EndTrans(trans));
1567 SVL_LinkedListN(rxcall, attributes, nentries, vldbentries)
1568 struct rx_call *rxcall;
1569 struct VldbListByAttributes *attributes;
1570 afs_int32 *nentries;
1571 nvldb_list *vldbentries;
1574 struct ubik_trans *trans;
1575 struct nvlentry tentry;
1576 nvldblist vllist, *vllistptr;
1577 afs_int32 blockindex, count, k, match;
1581 COUNT_REQ (VLLINKEDLISTN);
1582 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1586 vldbentries->node = NULL;
1587 vllistptr = &vldbentries->node;
1589 /* List by volumeid */
1590 if (attributes->Mask & VLLIST_VOLUMEID) {
1591 blockindex = FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1594 ubik_AbortTrans(trans);
1595 return (errorcode ? errorcode : VL_NOENT);
1598 vllist = (single_nvldbentry *) malloc(sizeof(single_nvldbentry));
1599 if (vllist == NULL) {
1601 ubik_AbortTrans(trans);
1604 vlentry_to_nvldbentry(&tentry, &vllist->VldbEntry);
1605 vllist->next_vldb = NULL;
1607 *vllistptr = vllist; /* Thread onto list */
1608 vllistptr = &vllist->next_vldb;
1612 /* Search by server, partition, and flags */
1614 for (blockindex = NextEntry(trans, 0, &tentry, &count);
1616 blockindex = NextEntry(trans, blockindex, &tentry, &count)) {
1619 if (++pollcount > 50) {
1624 /* Does this volume exist on the desired server */
1625 if (attributes->Mask & VLLIST_SERVER) {
1626 serverindex = IpAddrToRelAddr(attributes->server, (struct ubik_trans *)0);
1627 if (serverindex == -1) continue;
1628 for (k=0; k < NMAXNSERVERS; k++) {
1629 if (tentry.serverNumber[k] == BADSERVERID) break;
1630 if (tentry.serverNumber[k] == serverindex) {
1635 if (!match) continue;
1638 /* Does this volume exist on the desired partition */
1639 if (attributes->Mask & VLLIST_PARTITION) {
1641 if (tentry.serverPartition[k] != attributes->partition)
1644 for (k=0; k < NMAXNSERVERS; k++) {
1645 if (tentry.serverNumber[k] == BADSERVERID) break;
1646 if (tentry.serverPartition[k] == attributes->partition) {
1652 if (!match) continue;
1655 /* Does this volume have the desired flags */
1656 if (attributes->Mask & VLLIST_FLAG) {
1657 if (!(tentry.flags & attributes->flag))
1661 vllist = (single_nvldbentry *) malloc(sizeof(single_nvldbentry));
1662 if (vllist == NULL) {
1664 ubik_AbortTrans(trans);
1667 vlentry_to_nvldbentry(&tentry, &vllist->VldbEntry);
1668 vllist->next_vldb = NULL;
1670 *vllistptr = vllist; /* Thread onto list */
1671 vllistptr = &vllist->next_vldb;
1673 if (smallMem && (*nentries >= VLDBALLOCCOUNT)) {
1675 ubik_AbortTrans(trans);
1676 return VL_SIZEEXCEEDED;
1681 return(ubik_EndTrans(trans));
1684 /* Get back vldb header statistics (allocs, frees, maxvolumeid, totalentries, etc) and dynamic statistics (number of requests and/or aborts per remote procedure call, etc) */
1685 SVL_GetStats(rxcall, stats, vital_header)
1686 struct rx_call *rxcall;
1688 vital_vlheader *vital_header;
1689 { register afs_int32 errorcode;
1690 struct ubik_trans *trans;
1692 COUNT_REQ(VLGETSTATS);
1694 /* Allow users to get statistics freely */
1695 if (!afsconf_SuperUser(vldb_confdir, rxcall, (char *)0)) /* Must be in 'UserList' to use */
1698 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1700 VLog(5, ("GetStats %\n", rxinfo(rxcall)));
1701 memcpy((char *) vital_header, (char *)&cheader.vital_header, sizeof(vital_vlheader));
1702 memcpy((char *) stats, (char *)&dynamic_statistics, sizeof(vldstats));
1703 return(ubik_EndTrans(trans));
1706 /* Get the list of file server addresses from the VLDB. Currently it's pretty
1707 * easy to do. In the future, it might require a little bit of grunging
1708 * through the VLDB, but that's life.
1710 SVL_GetAddrs(rxcall, Handle, spare2, spare3, nentries, addrsp)
1711 struct rx_call *rxcall;
1712 afs_int32 Handle, spare2;
1713 struct VLCallBack *spare3;
1714 afs_int32 *nentries;
1716 { register afs_int32 errorcode;
1717 struct ubik_trans *trans;
1721 COUNT_REQ(VLGETADDRS);
1722 addrsp->bulkaddrs_len = *nentries = 0;
1723 addrsp->bulkaddrs_val = 0;
1724 memset(spare3, 0, sizeof (struct VLCallBack));
1726 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1729 VLog(5, ("GetAddrs\n"));
1730 addrsp->bulkaddrs_val = taddrp = (afs_uint32 *)malloc(sizeof(afs_int32)*(MAXSERVERID+1));
1731 nservers= *nentries = addrsp->bulkaddrs_len = 0;
1735 ubik_AbortTrans(trans);
1739 for (i=0; i <= MAXSERVERID; i++) {
1740 if (*taddrp = ntohl(cheader.IpMappedAddr[i])) {
1746 addrsp->bulkaddrs_len = *nentries = nservers;
1747 return(ubik_EndTrans(trans));
1750 #define PADDR(addr) printf("%d.%d.%d.%d", (addr>>24)&0xff, (addr>>16)&0xff, (addr>>8) &0xff, addr&0xff);
1752 SVL_RegisterAddrs(rxcall, uuidp, spare1, addrsp)
1753 struct rx_call *rxcall;
1759 struct ubik_trans *trans;
1760 int cnt, h, i, j, k, m, base, index;
1761 struct extentaddr *exp = 0, *tex;
1763 afs_uint32 addrs[VL_MAXIPADDRS_PERMH];
1765 int count, willChangeEntry, foundUuidEntry, willReplaceCnt;
1766 int WillReplaceEntry, WillChange[MAXSERVERID+1], FoundUuid, ReplaceEntry;
1769 COUNT_REQ(VLREGADDR);
1770 if (!afsconf_SuperUser(vldb_confdir, rxcall, (char *)0))
1772 if (code = Init_VLdbase(&trans, LOCKWRITE, this_op))
1775 /* Eliminate duplicates from IP address list */
1776 for (k=0, cnt=0; k<addrsp->bulkaddrs_len; k++) {
1777 if (addrsp->bulkaddrs_val[k] == 0)
1779 for (m=0; m < cnt; m++) {
1780 if (addrs[m] == addrsp->bulkaddrs_val[k])
1784 if (m == VL_MAXIPADDRS_PERMH) {
1785 VLog(0, ("Number of addresses exceeds %d. Cannot register IP addr 0x%x in VLDB\n",
1786 VL_MAXIPADDRS_PERMH, addrsp->bulkaddrs_val[k]));
1788 addrs[m] = addrsp->bulkaddrs_val[k];
1794 ubik_AbortTrans(trans);
1795 return VL_INDEXERANGE;
1801 /* For each server registered within the VLDB */
1802 for (srvidx=0; srvidx <= MAXSERVERID;srvidx++) {
1803 willChangeEntry = 0;
1804 WillReplaceEntry = 1;
1805 if ((HostAddress[srvidx] & 0xff000000) == 0xff000000) {
1806 /* The server is registered as a multihomed */
1807 base = (HostAddress[srvidx] >> 16) & 0xff;
1808 index = HostAddress[srvidx] & 0x0000ffff;
1809 if (base >= VL_MAX_ADDREXTBLKS) {
1810 VLog(0, ("Internal error: Multihome extent base is too large. Base %d index %d\n",
1814 if (index >= VL_MHSRV_PERBLK) {
1815 VLog(0, ("Internal error: Multihome extent index is too large. Base %d index %d\n",
1819 if (!ex_addr[base]) {
1820 VLog(0, ("Internal error: Multihome extent does not exist. Base %d\n", base));
1824 /* See if the addresses to register will change this server entry */
1825 exp = &ex_addr[base][index];
1826 tuuid = exp->ex_hostuuid;
1827 afs_ntohuuid(&tuuid);
1828 if (afs_uuid_equal(uuidp, &tuuid)) {
1832 for (mhidx=0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
1833 if (!exp->ex_addrs[mhidx]) continue;
1834 for (k=0; k<cnt; k++) {
1835 if (ntohl(exp->ex_addrs[mhidx]) == addrs[k]) {
1836 willChangeEntry = 1;
1837 WillChange[count] = srvidx;
1841 if (k >= cnt) WillReplaceEntry = 0;
1845 /* The server is not registered as a multihomed.
1846 * See if the addresses to register will replace this server entry.
1848 for (k=0; k<cnt; k++) {
1849 if (HostAddress[srvidx] == addrs[k]) {
1850 willChangeEntry = 1;
1851 WillChange[count] = srvidx;
1852 WillReplaceEntry = 1;
1857 if (willChangeEntry) {
1858 if (WillReplaceEntry) {
1860 ReplaceEntry = srvidx;
1866 /* If we found the uuid in the VLDB and if we are replacing another
1867 * entire entry, then complain and fail. Also, if we did not find
1868 * the uuid in the VLDB and the IP addresses being registered was
1869 * found in more than one other entry, then we don't know which one
1870 * to replace and will complain and fail.
1872 if ( ( foundUuidEntry && (willReplaceCnt > 0)) ||
1873 (!foundUuidEntry && (count > 1)) ) {
1874 VLog(0, ("The following fileserver is being registered in the VLDB:\n"));
1876 for (k=0; k<cnt; k++) {
1877 if (k>0) printf(" ");
1882 if (foundUuidEntry) {
1883 printf(" It would have replaced the existing VLDB server entry:\n");
1884 printf(" entry %d: [", FoundUuid);
1885 base = (HostAddress[FoundUuid] >> 16) & 0xff;
1886 index = HostAddress[FoundUuid] & 0x0000ffff;
1887 exp = &ex_addr[base][index];
1888 for (mhidx=0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
1889 if (!exp->ex_addrs[mhidx]) continue;
1890 if (mhidx > 0) printf(" ");
1891 PADDR(ntohl(exp->ex_addrs[mhidx]));
1896 if (count == 1) printf(" Yet another VLDB server entry exists:\n");
1897 else printf(" Yet other VLDB server entries exist:\n");
1898 for (j=0; j<count; j++) {
1899 srvidx = WillChange[j];
1900 printf(" entry %d: ", srvidx);
1901 if ((HostAddress[srvidx] & 0xff000000) == 0xff000000) {
1903 base = (HostAddress[srvidx] >> 16) & 0xff;
1904 index = HostAddress[srvidx] & 0x0000ffff;
1905 exp = &ex_addr[base][index];
1906 for (mhidx=0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
1907 if (!exp->ex_addrs[mhidx]) continue;
1908 if (mhidx > 0) printf(" ");
1909 PADDR(ntohl(exp->ex_addrs[mhidx]));
1913 PADDR(HostAddress[srvidx]);
1919 printf(" You must 'vos changeaddr' this other server entry\n");
1921 printf(" You must 'vos changeaddr' these other server entries\n");
1923 printf(" and/or remove the sysid file from the registering fileserver\n");
1924 printf(" before the fileserver can be registered in the VLDB.\n");
1926 ubik_AbortTrans(trans);
1927 return VL_MULTIPADDR;
1930 /* Passed the checks. Now find and update the existing mh entry, or create
1933 if (foundUuidEntry) {
1934 /* Found the entry with same uuid. See if we need to change it */
1937 fbase = (HostAddress[FoundUuid] >> 16) & 0xff;
1938 index = HostAddress[FoundUuid] & 0x0000ffff;
1939 exp = &ex_addr[fbase][index];
1941 /* Determine if the entry has changed */
1942 for (k=0; ((k < cnt) && !change); k++) {
1943 if (ntohl(exp->ex_addrs[k]) != addrs[k])
1946 for (; ((k < VL_MAXIPADDRS_PERMH) && !change); k++) {
1947 if (exp->ex_addrs[k] != 0)
1951 return(ubik_EndTrans(trans));
1955 VLog(0, ("The following fileserver is being registered in the VLDB:\n"));
1957 for (k=0; k<cnt; k++) {
1958 if (k>0) printf(" ");
1963 if (foundUuidEntry) {
1964 printf(" It will replace the following existing entry in the VLDB (same uuid):\n");
1965 printf(" entry %d: [", FoundUuid);
1966 for (k=0; k < VL_MAXIPADDRS_PERMH; k++) {
1967 if (exp->ex_addrs[k] == 0) continue;
1968 if (k>0) printf(" ");
1969 PADDR(ntohl(exp->ex_addrs[k]));
1973 else if (willReplaceCnt || (count == 1)) {
1974 /* If we are not replacing an entry and there is only one entry to change,
1975 * then we will replace that entry.
1977 if (!willReplaceCnt) {
1978 ReplaceEntry = WillChange[0];
1982 /* Have an entry that needs to be replaced */
1983 if ((HostAddress[ReplaceEntry] & 0xff000000) == 0xff000000) {
1984 fbase = (HostAddress[ReplaceEntry] >> 16) & 0xff;
1985 index = HostAddress[ReplaceEntry] & 0x0000ffff;
1986 exp = &ex_addr[fbase][index];
1988 printf(" It will replace the following existing entry in the VLDB (new uuid):\n");
1989 printf(" entry %d: [", ReplaceEntry);
1990 for (k=0; k < VL_MAXIPADDRS_PERMH; k++) {
1991 if (exp->ex_addrs[k] == 0) continue;
1992 if (k>0) printf(" ");
1993 PADDR(ntohl(exp->ex_addrs[k]));
1997 /* Not a mh entry. So we have to create a new mh entry and
1998 * put it on the ReplaceEntry slot of the HostAddress array.
2000 printf(" It will replace existing entry %d, ", ReplaceEntry);
2001 PADDR(HostAddress[ReplaceEntry]);
2002 printf(", in the VLDB (new uuid):\n");
2004 code = FindExtentBlock(trans, uuidp, 1, ReplaceEntry, &exp, &fbase);
2006 ubik_AbortTrans(trans);
2007 return (code ? code : VL_IO);
2011 /* There is no entry for this server, must create a new mh entry as
2012 * well as use a new slot of the HostAddress array.
2014 printf(" It will create a new entry in the VLDB.\n");
2015 code = FindExtentBlock(trans, uuidp, 1, -1, &exp, &fbase);
2017 ubik_AbortTrans(trans);
2018 return (code ? code : VL_IO);
2022 /* Now we have a mh entry to fill in. Update the uuid, bump the
2023 * uniquifier, and fill in its IP addresses.
2026 afs_htonuuid(&tuuid);
2027 exp->ex_hostuuid = tuuid;
2028 exp->ex_uniquifier = htonl(ntohl(exp->ex_uniquifier)+1);
2029 for (k=0; k < cnt; k++) {
2030 exp->ex_addrs[k] = htonl(addrs[k]);
2032 for (; k < VL_MAXIPADDRS_PERMH; k++) {
2033 exp->ex_addrs[k] = 0;
2036 /* Write the new mh entry out */
2037 if (vlwrite(trans, DOFFSET(ntohl(ex_addr[0]->ex_contaddrs[fbase]),
2038 (char *)ex_addr[fbase], (char *)exp),
2039 (char *)exp, sizeof(*exp))) {
2040 ubik_AbortTrans(trans);
2044 /* Remove any common addresses from other mh entres. We know these entries
2045 * are being changed and not replaced so they are mh entries.
2048 for (i=0; i<count; i++) {
2051 /* Skip the entry we replaced */
2052 if (willReplaceCnt && (WillChange[i] == ReplaceEntry))
2055 base = (HostAddress[WillChange[i]] >> 16) & 0xff;
2056 index = HostAddress[WillChange[i]] & 0x0000ffff;
2057 tex = &ex_addr[fbase][index];
2060 printf(" The following existing entries in the VLDB will be updated:\n");
2062 printf(" entry %d: [", WillChange[i]);
2063 for (h=j=0; j < VL_MAXIPADDRS_PERMH; j++) {
2064 if (tex->ex_addrs[j]) {
2065 if (j>0) printf(" ");
2066 PADDR(ntohl(tex->ex_addrs[j]));
2069 for (k=0; k<cnt; k++) {
2070 if (ntohl(tex->ex_addrs[j]) == addrs[k]) break;
2073 /* Not found, so we keep it */
2074 tex->ex_addrs[h] = tex->ex_addrs[j];
2078 for (j=h; j < VL_MAXIPADDRS_PERMH; j++) {
2079 tex->ex_addrs[j] = 0; /* zero rest of mh entry */
2083 /* Write out the modified mh entry */
2084 tex->ex_uniquifier = htonl(ntohl(tex->ex_uniquifier)+1);
2085 doff=DOFFSET(ntohl(ex_addr[0]->ex_contaddrs[base]),
2086 (char *)ex_addr[base], (char *)tex);
2087 if (vlwrite(trans, doff, (char*)tex, sizeof(*tex))) {
2088 ubik_AbortTrans(trans);
2093 return(ubik_EndTrans(trans));
2096 SVL_GetAddrsU(rxcall, attributes, uuidpo, uniquifier, nentries, addrsp)
2097 struct rx_call *rxcall;
2098 struct ListAddrByAttributes *attributes;
2100 afs_int32 *uniquifier, *nentries;
2102 { register afs_int32 errorcode, index=-1, offset;
2103 struct ubik_trans *trans;
2104 int nservers, i, j, base=0;
2105 struct extentaddr *exp=0;
2107 afs_uint32 *taddrp, taddr;
2109 COUNT_REQ(VLGETADDRSU);
2110 addrsp->bulkaddrs_len = *nentries = 0;
2111 addrsp->bulkaddrs_val = 0;
2112 VLog(5, ("GetAddrsU %s\n", rxinfo(rxcall)));
2113 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
2116 if (attributes->Mask & VLADDR_IPADDR) {
2117 if (attributes->Mask & (VLADDR_INDEX|VLADDR_UUID)) {
2118 ubik_AbortTrans(trans);
2121 for (base = 0; base < VL_MAX_ADDREXTBLKS; base++) {
2124 for (i = 1; i < VL_MHSRV_PERBLK; i++) {
2125 exp = &ex_addr[base][i];
2126 tuuid = exp->ex_hostuuid;
2127 afs_ntohuuid(&tuuid);
2128 if (afs_uuid_is_nil(&tuuid)) continue;
2129 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2130 if (exp->ex_addrs[j] && (ntohl(exp->ex_addrs[j]) == attributes->ipaddr)) {
2134 if (j < VL_MAXIPADDRS_PERMH) break;
2136 if (i < VL_MHSRV_PERBLK) break;
2138 if (base >= VL_MAX_ADDREXTBLKS) {
2139 ubik_AbortTrans(trans);
2142 } else if (attributes->Mask & VLADDR_INDEX) {
2143 if (attributes->Mask & (VLADDR_IPADDR|VLADDR_UUID)) {
2144 ubik_AbortTrans(trans);
2147 index = attributes->index;
2148 if (index < 1 || index >= (VL_MAX_ADDREXTBLKS*VL_MHSRV_PERBLK)) {
2149 ubik_AbortTrans(trans);
2150 return VL_INDEXERANGE;
2152 base = index / VL_MHSRV_PERBLK;
2153 offset = index % VL_MHSRV_PERBLK;
2155 ubik_AbortTrans(trans);
2158 if (!ex_addr[base]) {
2159 ubik_AbortTrans(trans);
2160 return VL_INDEXERANGE;
2162 exp = &ex_addr[base][offset];
2163 } else if (attributes->Mask & VLADDR_UUID) {
2164 if (attributes->Mask & (VLADDR_IPADDR|VLADDR_INDEX)) {
2165 ubik_AbortTrans(trans);
2168 if (!ex_addr[0]) { /* mh servers probably aren't setup on this vldb */
2169 ubik_AbortTrans(trans);
2172 if (errorcode = FindExtentBlock(trans, &attributes->uuid, 0, -1, &exp, &base)) {
2173 ubik_AbortTrans(trans);
2177 ubik_AbortTrans(trans);
2181 if (exp == (struct extentaddr *)0) {
2182 ubik_AbortTrans(trans);
2185 addrsp->bulkaddrs_val = taddrp = (afs_uint32 *)malloc(sizeof(afs_int32)*(MAXSERVERID+1));
2186 nservers= *nentries = addrsp->bulkaddrs_len = 0;
2189 ubik_AbortTrans(trans);
2192 tuuid = exp->ex_hostuuid;
2193 afs_ntohuuid(&tuuid);
2194 if (afs_uuid_is_nil(&tuuid)) {
2195 ubik_AbortTrans(trans);
2198 if (uuidpo) *uuidpo = tuuid;
2199 if (uniquifier) *uniquifier = ntohl(exp->ex_uniquifier);
2200 for (i = 0; i < VL_MAXIPADDRS_PERMH; i++) {
2201 if (exp->ex_addrs[i]) {
2202 taddr = ntohl(exp->ex_addrs[i]);
2203 /* Weed out duplicates */
2204 for (j = 0; j < nservers; j++) {
2205 if (taddrp[j] == taddr)
2208 if ((j == nservers) && (j <= MAXSERVERID)) {
2209 taddrp[nservers] = taddr;
2214 addrsp->bulkaddrs_len = *nentries = nservers;
2215 return(ubik_EndTrans(trans));
2218 /* ============> End of Exported vldb RPC functions <============= */
2221 /* Routine that copies the given vldb entry to the output buffer, vldbentries. */
2223 put_attributeentry(Vldbentry, VldbentryFirst, VldbentryLast, vldbentries, entry, nentries, alloccnt)
2224 struct vldbentry **Vldbentry, **VldbentryFirst, **VldbentryLast;
2225 bulkentries *vldbentries;
2226 struct nvlentry *entry;
2227 afs_int32 *nentries, *alloccnt;
2232 if (*Vldbentry == *VldbentryLast) {
2233 if (smallMem) return VL_SIZEEXCEEDED; /* no growing if smallMem defined */
2235 /* Allocate another set of memory; each time allocate twice as
2236 * many blocks as the last time. When we reach VLDBALLOCLIMIT,
2237 * then grow in increments of VLDBALLOCINCR.
2239 allo = (*alloccnt > VLDBALLOCLIMIT) ? VLDBALLOCINCR : *alloccnt;
2240 reall = (vldbentry *) realloc(*VldbentryFirst, (*alloccnt+allo)*sizeof(vldbentry));
2241 if (reall == NULL) return VL_NOMEM;
2243 *VldbentryFirst = vldbentries->bulkentries_val = reall;
2244 *Vldbentry = *VldbentryFirst + *alloccnt;
2245 *VldbentryLast = *Vldbentry + allo;
2248 vlentry_to_vldbentry(entry, *Vldbentry);
2251 vldbentries->bulkentries_len++;
2256 put_nattributeentry(Vldbentry, VldbentryFirst, VldbentryLast, vldbentries, entry,
2257 matchtype, matchindex, nentries, alloccnt)
2258 struct nvldbentry **Vldbentry, **VldbentryFirst, **VldbentryLast;
2259 nbulkentries *vldbentries;
2260 struct nvlentry *entry;
2261 afs_int32 matchtype, matchindex, *nentries, *alloccnt;
2266 if (*Vldbentry == *VldbentryLast) {
2267 if (smallMem) return VL_SIZEEXCEEDED; /* no growing if smallMem defined */
2269 /* Allocate another set of memory; each time allocate twice as
2270 * many blocks as the last time. When we reach VLDBALLOCLIMIT,
2271 * then grow in increments of VLDBALLOCINCR.
2273 allo = (*alloccnt > VLDBALLOCLIMIT) ? VLDBALLOCINCR : *alloccnt;
2274 reall = (nvldbentry *)realloc(*VldbentryFirst, (*alloccnt+allo)*sizeof(nvldbentry));
2275 if (reall == NULL) return VL_NOMEM;
2277 *VldbentryFirst = vldbentries->nbulkentries_val = reall;
2278 *Vldbentry = *VldbentryFirst + *alloccnt;
2279 *VldbentryLast = *Vldbentry + allo;
2282 vlentry_to_nvldbentry(entry, *Vldbentry);
2283 (*Vldbentry)->matchindex = (matchtype << 16) + matchindex;
2286 vldbentries->nbulkentries_len++;
2291 /* Common code to actually remove a vldb entry from the database. */
2293 RemoveEntry(trans, entryptr, tentry)
2294 struct ubik_trans *trans;
2296 struct nvlentry *tentry;
2298 register int errorcode;
2300 if (errorcode = UnthreadVLentry(trans, entryptr, tentry))
2302 if (errorcode = FreeBlock(trans, entryptr))
2308 ReleaseEntry(tentry, releasetype)
2309 struct nvlentry *tentry;
2310 afs_int32 releasetype;
2312 if (releasetype & LOCKREL_TIMESTAMP)
2313 tentry->LockTimestamp = 0;
2314 if (releasetype & LOCKREL_OPCODE)
2315 tentry->flags &= ~VLOP_ALLOPERS;
2316 if (releasetype & LOCKREL_AFSID)
2317 tentry->LockAfsId = 0;
2321 /* Verify that the incoming vldb entry is valid; multi type of error codes are returned. */
2323 check_vldbentry(aentry)
2324 struct vldbentry *aentry;
2328 if (InvalidVolname(aentry->name))
2330 if (aentry->nServers <= 0 || aentry->nServers > OMAXNSERVERS)
2331 return VL_BADSERVER;
2332 for (i=0; i < aentry->nServers; i++) {
2333 /* if (aentry->serverNumber[i] < 0 || aentry->serverNumber[i] > MAXSERVERID)
2334 return VL_BADSERVER; */
2335 if (aentry->serverPartition[i] < 0 || aentry->serverPartition[i] > MAXPARTITIONID)
2336 return VL_BADPARTITION;
2337 if (aentry->serverFlags[i] < 0 || aentry->serverFlags[i] > MAXSERVERFLAG)
2338 return VL_BADSERVERFLAG;
2344 check_nvldbentry(aentry)
2345 struct nvldbentry *aentry;
2349 if (InvalidVolname(aentry->name))
2351 if (aentry->nServers <= 0 || aentry->nServers > NMAXNSERVERS)
2352 return VL_BADSERVER;
2353 for (i=0; i < aentry->nServers; i++) {
2354 /* if (aentry->serverNumber[i] < 0 || aentry->serverNumber[i] > MAXSERVERID)
2355 return VL_BADSERVER; */
2356 if (aentry->serverPartition[i] < 0 || aentry->serverPartition[i] > MAXPARTITIONID)
2357 return VL_BADPARTITION;
2358 if (aentry->serverFlags[i] < 0 || aentry->serverFlags[i] > MAXSERVERFLAG)
2359 return VL_BADSERVERFLAG;
2365 /* Convert from the external vldb entry representation to its internal
2366 (more compact) form. This call should not change the hash chains! */
2368 vldbentry_to_vlentry(atrans, VldbEntry, VlEntry)
2369 struct ubik_trans *atrans;
2370 struct vldbentry *VldbEntry;
2371 struct nvlentry *VlEntry;
2375 if (strcmp(VlEntry->name, VldbEntry->name))
2376 strncpy(VlEntry->name, VldbEntry->name, sizeof(VlEntry->name));
2377 for (i=0; i<VldbEntry->nServers; i++) {
2378 serverindex = IpAddrToRelAddr(VldbEntry->serverNumber[i], atrans);
2379 if (serverindex == -1) return VL_BADSERVER;
2380 VlEntry->serverNumber[i] = serverindex;
2381 VlEntry->serverPartition[i] = VldbEntry->serverPartition[i];
2382 VlEntry->serverFlags[i] = VldbEntry->serverFlags[i];
2384 for (;i < OMAXNSERVERS; i++)
2385 VlEntry->serverNumber[i] = VlEntry->serverPartition[i] = VlEntry->serverFlags[i] = BADSERVERID;
2386 for (i=0; i < MAXTYPES; i++)
2387 VlEntry->volumeId[i] = VldbEntry->volumeId[i];
2388 VlEntry->cloneId = VldbEntry->cloneId;
2389 VlEntry->flags = VldbEntry->flags;
2394 nvldbentry_to_vlentry(atrans, VldbEntry, VlEntry)
2395 struct ubik_trans *atrans;
2396 struct nvldbentry *VldbEntry;
2397 struct nvlentry *VlEntry;
2401 if (strcmp(VlEntry->name, VldbEntry->name))
2402 strncpy(VlEntry->name, VldbEntry->name, sizeof(VlEntry->name));
2403 for (i=0; i<VldbEntry->nServers; i++) {
2404 serverindex = IpAddrToRelAddr(VldbEntry->serverNumber[i], atrans);
2405 if (serverindex == -1) return VL_BADSERVER;
2406 VlEntry->serverNumber[i] = serverindex;
2407 VlEntry->serverPartition[i] = VldbEntry->serverPartition[i];
2408 VlEntry->serverFlags[i] = VldbEntry->serverFlags[i];
2410 for (;i < NMAXNSERVERS; i++)
2411 VlEntry->serverNumber[i] = VlEntry->serverPartition[i] = VlEntry->serverFlags[i] = BADSERVERID;
2412 for (i=0; i < MAXTYPES; i++)
2413 VlEntry->volumeId[i] = VldbEntry->volumeId[i];
2414 VlEntry->cloneId = VldbEntry->cloneId;
2415 VlEntry->flags = VldbEntry->flags;
2420 /* 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. */
2422 get_vldbupdateentry(trans, blockindex, updateentry, VlEntry)
2423 struct ubik_trans *trans;
2424 afs_int32 blockindex;
2425 struct VldbUpdateEntry *updateentry;
2426 struct nvlentry *VlEntry;
2428 int i, j, errorcode, serverindex;
2430 if (updateentry->Mask & VLUPDATE_VOLUMENAME) {
2431 if (InvalidVolname(updateentry->name))
2433 if (errorcode = UnhashVolname(trans, blockindex, VlEntry))
2435 strncpy(VlEntry->name, updateentry->name, sizeof(VlEntry->name));
2436 HashVolname(trans, blockindex, VlEntry);
2439 if (updateentry->Mask & VLUPDATE_VOLNAMEHASH) {
2440 if (errorcode = UnhashVolname(trans, blockindex, VlEntry)) {
2441 if (errorcode != VL_NOENT)
2444 HashVolname(trans, blockindex, VlEntry);
2447 if (updateentry->Mask & VLUPDATE_FLAGS) {
2448 VlEntry->flags = updateentry->flags;
2450 if (updateentry->Mask & VLUPDATE_CLONEID) {
2451 VlEntry->cloneId = updateentry->cloneId;
2453 if (updateentry->Mask & VLUPDATE_RWID) {
2454 if (errorcode = UnhashVolid(trans, RWVOL, blockindex, VlEntry)) {
2455 if (errorcode != VL_NOENT)
2458 VlEntry->volumeId[RWVOL] = updateentry->spares3; /* rw id */
2459 if (errorcode = HashVolid(trans, RWVOL, blockindex, VlEntry))
2462 if (updateentry->Mask & VLUPDATE_READONLYID) {
2463 if (errorcode = UnhashVolid(trans, ROVOL, blockindex, VlEntry)) {
2464 if (errorcode != VL_NOENT)
2467 VlEntry->volumeId[ROVOL] = updateentry->ReadOnlyId;
2468 if (errorcode = HashVolid(trans, ROVOL, blockindex, VlEntry))
2471 if (updateentry->Mask & VLUPDATE_BACKUPID) {
2472 if (errorcode = UnhashVolid(trans, BACKVOL, blockindex, VlEntry)) {
2473 if (errorcode != VL_NOENT)
2476 VlEntry->volumeId[BACKVOL] = updateentry->BackupId;
2477 if (errorcode = HashVolid(trans, BACKVOL, blockindex, VlEntry))
2480 if (updateentry->Mask & VLUPDATE_REPSITES) {
2481 if (updateentry->nModifiedRepsites <= 0 || updateentry->nModifiedRepsites > OMAXNSERVERS)
2482 return VL_BADSERVER;
2483 for (i=0; i < updateentry->nModifiedRepsites; i++) {
2484 /* if (updateentry->RepsitesTargetServer[i] < 0 || updateentry->RepsitesTargetServer[i] > MAXSERVERID)
2485 return VL_BADSERVER; */
2486 if (updateentry->RepsitesTargetPart[i] < 0 || updateentry->RepsitesTargetPart[i] > MAXPARTITIONID)
2487 return VL_BADPARTITION;
2488 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_DELETE) {
2489 if ((j = repsite_exists(VlEntry, IpAddrToRelAddr(updateentry->RepsitesTargetServer[i], trans), updateentry->RepsitesTargetPart[i])) != -1)
2490 repsite_compress(VlEntry, j);
2491 else return VL_NOREPSERVER;
2493 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_ADD) {
2494 /* if (updateentry->RepsitesNewServer[i] < 0 || updateentry->RepsitesNewServer[i] > MAXSERVERID)
2495 return VL_BADSERVER; */
2496 if (updateentry->RepsitesNewPart[i] < 0 || updateentry->RepsitesNewPart[i] > MAXPARTITIONID)
2497 return VL_BADPARTITION;
2498 if (repsite_exists(VlEntry, IpAddrToRelAddr(updateentry->RepsitesNewServer[i], trans), updateentry->RepsitesNewPart[i]) != -1)
2499 return VL_DUPREPSERVER;
2500 for (j=0; VlEntry->serverNumber[j] != BADSERVERID && j < OMAXNSERVERS; j++);
2501 if (j >= OMAXNSERVERS) return VL_REPSFULL;
2502 if ((serverindex = IpAddrToRelAddr(updateentry->RepsitesNewServer[i], trans)) == -1)
2503 return VL_BADSERVER;
2504 VlEntry->serverNumber[j] = serverindex;
2505 VlEntry->serverPartition[j] = updateentry->RepsitesNewPart[i];
2506 if (updateentry->RepsitesNewFlags[i] < 0 || updateentry->RepsitesNewFlags[i] > MAXSERVERFLAG)
2507 return VL_BADSERVERFLAG;
2508 VlEntry->serverFlags[j] = updateentry->RepsitesNewFlags[i];
2510 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODSERV) {
2511 /*n if (updateentry->RepsitesNewServer[i] < 0 || updateentry->RepsitesNewServer[i] > MAXSERVERID)
2512 return VL_BADSERVER; */
2513 if ((j = repsite_exists(VlEntry, IpAddrToRelAddr(updateentry->RepsitesTargetServer[i], trans), updateentry->RepsitesTargetPart[i])) != -1) {
2514 VlEntry->serverNumber[j] = IpAddrToRelAddr(updateentry->RepsitesNewServer[i], trans);
2516 else return VL_NOREPSERVER;
2518 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODPART) {
2519 if (updateentry->RepsitesNewPart[i] < 0 || updateentry->RepsitesNewPart[i] > MAXPARTITIONID)
2520 return VL_BADPARTITION;
2521 if ((j = repsite_exists(VlEntry, IpAddrToRelAddr(updateentry->RepsitesTargetServer[i], trans), updateentry->RepsitesTargetPart[i])) != -1)
2522 VlEntry->serverPartition[j] = updateentry->RepsitesNewPart[i];
2523 else return VL_NOREPSERVER;
2525 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODFLAG) {
2526 if ((j = repsite_exists(VlEntry, IpAddrToRelAddr(updateentry->RepsitesTargetServer[i], trans), updateentry->RepsitesTargetPart[i])) != -1) {
2527 if (updateentry->RepsitesNewFlags[i] < 0 || updateentry->RepsitesNewFlags[i] > MAXSERVERFLAG)
2528 return VL_BADSERVERFLAG;
2529 VlEntry->serverFlags[j] = updateentry->RepsitesNewFlags[i];
2530 } else return VL_NOREPSERVER;
2538 /* 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. */
2540 repsite_exists(VlEntry, server, partition)
2541 struct nvlentry *VlEntry;
2542 int server, partition;
2546 for (i=0; VlEntry->serverNumber[i] != BADSERVERID && i < OMAXNSERVERS; i++) {
2547 if ((VlEntry->serverNumber[i] == server) && (VlEntry->serverPartition[i] == partition))
2555 /* Repsite table compression: used when deleting a repsite entry so that all active repsite entries are on the top of the table. */
2557 repsite_compress(VlEntry, offset)
2558 struct nvlentry *VlEntry;
2561 int repsite_offset = offset;
2562 for (; VlEntry->serverNumber[repsite_offset] != BADSERVERID && repsite_offset < OMAXNSERVERS-1; repsite_offset++) {
2563 VlEntry->serverNumber[repsite_offset] = VlEntry->serverNumber[repsite_offset+1];
2564 VlEntry->serverPartition[repsite_offset] = VlEntry->serverPartition[repsite_offset+1];
2565 VlEntry->serverFlags[repsite_offset] = VlEntry->serverFlags[repsite_offset+1];
2567 VlEntry->serverNumber[repsite_offset] = BADSERVERID;
2571 /* Convert from the internal (compacted) vldb entry to the external representation used by the interface. */
2573 vlentry_to_vldbentry(VlEntry, VldbEntry)
2574 struct nvlentry *VlEntry;
2575 struct vldbentry *VldbEntry;
2579 memset(VldbEntry, 0, sizeof(struct vldbentry));
2580 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
2581 for (i=0; i < OMAXNSERVERS; i++) {
2582 if (VlEntry->serverNumber[i] == BADSERVERID) break;
2583 if ((HostAddress[j = VlEntry->serverNumber[i]] & 0xff000000) == 0xff000000) {
2584 struct extentaddr *exp;
2587 base = (HostAddress[j] >> 16) & 0xff;
2588 index = HostAddress[j] & 0x0000ffff;
2589 exp = &ex_addr[base][index];
2590 /* For now return the first ip address back */
2591 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2592 if (exp->ex_addrs[j]) {
2593 VldbEntry->serverNumber[i] = ntohl(exp->ex_addrs[j]);
2598 VldbEntry->serverNumber[i] = HostAddress[VlEntry->serverNumber[i]];
2599 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
2600 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
2602 VldbEntry->nServers = i;
2603 for (i=0; i<MAXTYPES; i++)
2604 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
2605 VldbEntry->cloneId = VlEntry->cloneId;
2606 VldbEntry->flags = VlEntry->flags;
2610 /* Convert from the internal (compacted) vldb entry to the external representation used by the interface. */
2611 static vlentry_to_nvldbentry(VlEntry, VldbEntry)
2612 struct nvlentry *VlEntry;
2613 struct nvldbentry *VldbEntry;
2617 memset(VldbEntry, 0, sizeof(struct vldbentry));
2618 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
2619 for (i=0; i < NMAXNSERVERS; i++) {
2620 if (VlEntry->serverNumber[i] == BADSERVERID) break;
2621 if ((HostAddress[j = VlEntry->serverNumber[i]] & 0xff000000) == 0xff000000) {
2622 struct extentaddr *exp;
2625 base = (HostAddress[j] >> 16) & 0xff;
2626 index = HostAddress[j] & 0x0000ffff;
2627 exp = &ex_addr[base][index];
2628 /* For now return the first ip address back */
2629 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2630 if (exp->ex_addrs[j]) {
2631 VldbEntry->serverNumber[i] = ntohl(exp->ex_addrs[j]);
2636 VldbEntry->serverNumber[i] = HostAddress[VlEntry->serverNumber[i]];
2637 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
2638 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
2640 VldbEntry->nServers = i;
2641 for (i=0; i<MAXTYPES; i++)
2642 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
2643 VldbEntry->cloneId = VlEntry->cloneId;
2644 VldbEntry->flags = VlEntry->flags;
2647 static vlentry_to_uvldbentry(VlEntry, VldbEntry)
2648 struct nvlentry *VlEntry;
2649 struct uvldbentry *VldbEntry;
2653 memset(VldbEntry, 0, sizeof(struct vldbentry));
2654 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
2655 for (i=0; i < NMAXNSERVERS; i++) {
2656 if (VlEntry->serverNumber[i] == BADSERVERID) break;
2657 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
2658 VldbEntry->serverUnique[i] = 0;
2659 if ((HostAddress[j = VlEntry->serverNumber[i]] & 0xff000000) == 0xff000000) {
2660 struct extentaddr *exp;
2664 base = (HostAddress[j] >> 16) & 0xff;
2665 index = HostAddress[j] & 0x0000ffff;
2666 exp = &ex_addr[base][index];
2667 tuuid = exp->ex_hostuuid;
2668 afs_ntohuuid(&tuuid);
2669 VldbEntry->serverFlags[i] |= VLSERVER_FLAG_UUID;
2670 VldbEntry->serverNumber[i] = tuuid;
2671 VldbEntry->serverUnique[i] = ntohl(exp->ex_uniquifier);
2673 VldbEntry->serverNumber[i].time_low = HostAddress[VlEntry->serverNumber[i]];
2675 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
2678 VldbEntry->nServers = i;
2679 for (i=0; i<MAXTYPES; i++)
2680 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
2681 VldbEntry->cloneId = VlEntry->cloneId;
2682 VldbEntry->flags = VlEntry->flags;
2685 #define LEGALCHARS ".ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
2688 /* Verify that the volname is a valid volume name. */
2690 InvalidVolname(volname)
2697 slen = strlen(volname);
2698 if (slen >= VL_MAXNAMELEN) return 1;
2699 return(slen != strspn(volname, map));
2703 /* Verify that the given volume type is valid. */
2705 InvalidVoltype(voltype)
2708 if (voltype != RWVOL && voltype != ROVOL && voltype != BACKVOL)
2715 InvalidOperation(voloper)
2718 if (voloper != VLOP_MOVE && voloper != VLOP_RELEASE && voloper != VLOP_BACKUP && voloper != VLOP_DELETE && voloper != VLOP_DUMP)
2724 InvalidReleasetype(releasetype)
2725 afs_int32 releasetype;
2727 if ((releasetype & LOCKREL_TIMESTAMP) || (releasetype & LOCKREL_OPCODE) || (releasetype & LOCKREL_AFSID))
2733 IpAddrToRelAddr(ipaddr, atrans)
2734 struct ubik_trans *atrans;
2735 register afs_uint32 ipaddr;
2738 register afs_int32 code, base, index;
2739 struct extentaddr *exp;
2741 for (i = 0; i <= MAXSERVERID; i++) {
2742 if (HostAddress[i] == ipaddr)
2744 if ((HostAddress[i] & 0xff000000) == 0xff000000) {
2745 base = (HostAddress[i] >> 16) & 0xff;
2746 index = HostAddress[i] & 0x0000ffff;
2747 if (base >= VL_MAX_ADDREXTBLKS) {
2748 VLog(0, ("Internal error: Multihome extent base is too large. Base %d index %d\n", base, index));
2749 return -1; /* EINVAL */
2751 if (index >= VL_MHSRV_PERBLK) {
2752 VLog(0, ("Internal error: Multihome extent index is too large. Base %d index %d\n", base, index));
2753 return -1; /* EINVAL */
2755 if (!ex_addr[base]) {
2756 VLog(0, ("Internal error: Multihome extent does not exist. Base %d\n", base));
2757 return -1; /* EINVAL */
2759 exp = &ex_addr[base][index];
2760 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2761 if (exp->ex_addrs[j] && (ntohl(exp->ex_addrs[j]) == ipaddr)) {
2768 /* allocate the new server a server id pronto */
2770 for(i=0;i <= MAXSERVERID;i++) {
2771 if (cheader.IpMappedAddr[i] == 0) {
2772 cheader.IpMappedAddr[i] = htonl(ipaddr);
2773 code = vlwrite(atrans, DOFFSET(0, &cheader, &cheader.IpMappedAddr[i]), (char *) &cheader.IpMappedAddr[i], sizeof(afs_int32));
2774 HostAddress[i] = ipaddr;
2775 if (code) return -1;
2784 ChangeIPAddr(ipaddr1, ipaddr2, atrans)
2785 struct ubik_trans *atrans;
2786 register afs_uint32 ipaddr1, ipaddr2;
2790 struct extentaddr *exp;
2791 int base, index, mhidx;
2793 afs_int32 blockindex, count;
2795 struct nvlentry tentry;
2798 return VL_CREATEFAIL;
2800 /* Don't let addr change to 256.*.*.* : Causes internal error below */
2801 if ((ipaddr2 & 0xff000000) == 0xff000000)
2802 return(VL_BADSERVER);
2804 /* If we are removing an address, ip1 will be -1 and ip2 will be
2805 * the original address. This prevents an older revision vlserver
2806 * from removing the IP address (won't find server 0xfffffff in
2807 * the VLDB). An older revision vlserver does not have the check
2808 * to see if any volumes exist on the server being removed.
2810 if (ipaddr1 == 0xffffffff) {
2815 for (i = 0; i <= MAXSERVERID; i++) {
2816 if ((HostAddress[i] & 0xff000000) == 0xff000000) {
2817 base = (HostAddress[i] >> 16) & 0xff;
2818 index = HostAddress[i] & 0x0000ffff;
2819 if ((base >= VL_MAX_ADDREXTBLKS) || (index >= VL_MHSRV_PERBLK)) {
2820 VLog(0, ("Internal error: Multihome extent addr is too large. Base %d index %d\n",
2822 return -1; /* EINVAL */
2825 exp = &ex_addr[base][index];
2826 for (mhidx=0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2827 if (!exp->ex_addrs[mhidx]) continue;
2828 if (ntohl(exp->ex_addrs[mhidx]) == ipaddr1)
2831 if (mhidx < VL_MAXIPADDRS_PERMH) {
2835 else if (HostAddress[i] == ipaddr1) {
2836 exp = (struct extentaddr *)0;
2841 if (i >= MAXSERVERID) {
2842 return VL_NOENT; /* not found */
2845 /* If we are removing a server entry, a volume cannot
2846 * exist on the server. If one does, don't remove the
2847 * server entry: return error "volume entry exists".
2850 for (blockindex = NextEntry(atrans, 0, &tentry, &count);
2852 blockindex = NextEntry(atrans, blockindex, &tentry, &count)) {
2853 if (++pollcount > 50) {
2857 for (j=0; j<NMAXNSERVERS; j++) {
2858 if (tentry.serverNumber[j] == BADSERVERID) break;
2859 if (tentry.serverNumber[j] == i) {
2866 /* Log a message saying we are changing/removing an IP address */
2867 VLog(0, ("The following IP address is being %s:\n",
2868 (ipaddr2?"changed":"removed")));
2869 printf(" entry %d: ", i);
2872 for (mhidx=0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2873 if (!exp->ex_addrs[mhidx]) continue;
2874 if (mhidx>0) printf(" ");
2875 PADDR(ntohl(exp->ex_addrs[mhidx]));
2887 /* Change the registered uuuid addresses */
2889 memset(&tuuid, 0, sizeof(afsUUID));
2890 afs_htonuuid(&tuuid);
2891 exp->ex_hostuuid = tuuid;
2892 code = vlwrite(atrans, DOFFSET(ntohl(ex_addr[0]->ex_contaddrs[base]),
2893 (char *)ex_addr[base], (char *)exp),
2894 (char *)&tuuid, sizeof(tuuid));
2899 /* Now change the host address entry */
2900 cheader.IpMappedAddr[i] = htonl(ipaddr2);
2901 code = vlwrite(atrans, DOFFSET(0, &cheader, &cheader.IpMappedAddr[i]), (char *)
2902 &cheader.IpMappedAddr[i], sizeof(afs_int32));
2903 HostAddress[i] = ipaddr2;
2910 /* see if the vlserver is back yet */
2911 SVL_ProbeServer(rxcall)
2912 struct rx_call *rxcall; {