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 VL_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 bzero(&tentry, 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 VL_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 bzero(&tentry, 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 VL_ChangeAddr(rxcall, ip1, ip2)
298 struct rx_call *rxcall;
300 { struct ubik_trans *trans;
301 afs_int32 errorcode, blockindex;
302 struct nvlentry tentry;
304 COUNT_REQ (VLCHANGEADDR);
305 if (!afsconf_SuperUser(vldb_confdir, rxcall, (char *)0)) {
310 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
313 VLog(1, ("Change Addr %d -> %d %s\n", ip1, ip2, rxinfo(rxcall)));
314 if (errorcode = ChangeIPAddr(ip1, ip2, trans))
317 errorcode = ubik_EndTrans(trans);
323 ubik_AbortTrans(trans);
326 osi_auditU (rxcall, VLChangeAddrEvent, errorcode, AUD_LONG, ip1,
327 AUD_LONG, ip2, AUD_END);
331 /* Delete a vldb entry given the volume id. */
332 VL_DeleteEntry(rxcall, volid, voltype)
333 struct rx_call *rxcall;
336 { struct ubik_trans *trans;
337 afs_int32 blockindex, errorcode;
338 struct nvlentry tentry;
340 COUNT_REQ (VLDELETEENTRY);
341 if (!afsconf_SuperUser(vldb_confdir, rxcall, (char *)0))
344 if ((voltype != -1 ) && (InvalidVoltype(voltype)))
345 END( VL_BADVOLTYPE );
347 if (errorcode = Init_VLdbase (&trans, LOCKWRITE, this_op))
350 VLog(1, ("Delete Volume %d %s\n", volid, rxinfo(rxcall)));
351 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
352 if (blockindex == 0) { /* volid not found */
353 if (!errorcode) errorcode = VL_NOENT;
357 if (tentry.flags & VLDELETED) { /* Already deleted; return */
358 ABORT( VL_ENTDELETED );
360 if (errorcode = RemoveEntry(trans, blockindex, &tentry)) {
363 errorcode = (ubik_EndTrans(trans));
368 ubik_AbortTrans(trans);
371 osi_auditU (rxcall, VLDeleteEntryEvent, errorcode, AUD_LONG, volid, AUD_END);
376 /* Get a vldb entry given its volume id; make sure it's not a deleted entry. */
377 GetEntryByID (rxcall, volid, voltype, aentry, new, this_op)
378 struct rx_call *rxcall;
380 afs_int32 voltype, new, this_op;
381 char *aentry; /* entry data copied here */
382 { struct ubik_trans *trans;
383 afs_int32 blockindex, errorcode;
384 struct nvlentry tentry;
386 if ((voltype != -1 ) && (InvalidVoltype(voltype)))
387 return VL_BADVOLTYPE;
388 if (errorcode = Init_VLdbase (&trans, LOCKREAD, this_op))
391 VLog(5, ("GetVolumeByID %d (%d) %s\n", volid, new, rxinfo(rxcall)));
392 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
393 if (blockindex == 0) { /* entry not found */
394 if (!errorcode) errorcode = VL_NOENT;
396 ubik_AbortTrans (trans);
399 if (tentry.flags & VLDELETED) { /* Entry is deleted! */
401 ubik_AbortTrans (trans);
402 return VL_ENTDELETED;
404 /* Convert from the internal to external form */
406 vlentry_to_nvldbentry(&tentry, (struct nvldbentry *)aentry);
408 vlentry_to_uvldbentry(&tentry, (struct uvldbentry *)aentry);
410 vlentry_to_vldbentry(&tentry, (struct vldbentry *)aentry);
411 return(ubik_EndTrans(trans));
414 VL_GetEntryByID (rxcall, volid, voltype, aentry)
415 struct rx_call *rxcall;
416 afs_int32 volid, voltype;
417 vldbentry *aentry; /* entry data copied here */
419 COUNT_REQ (VLGETENTRYBYID);
420 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 0, this_op));
423 VL_GetEntryByIDN (rxcall, volid, voltype, aentry)
424 struct rx_call *rxcall;
425 afs_int32 volid, voltype;
426 nvldbentry *aentry; /* entry data copied here */
428 COUNT_REQ (VLGETENTRYBYIDN);
429 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 1, this_op));
432 VL_GetEntryByIDU (rxcall, volid, voltype, aentry)
433 struct rx_call *rxcall;
434 afs_int32 volid, voltype;
435 uvldbentry *aentry; /* entry data copied here */
437 COUNT_REQ (VLGETENTRYBYIDU);
438 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 2, this_op));
443 /* returns true if the id is a decimal integer, in which case we interpret it
444 as an id. make the cache manager much simpler */
445 static int NameIsId(aname)
446 register char *aname; {
448 while (tc = *aname++) {
449 if (tc > '9' || tc < '0') return 0;
454 /* Get a vldb entry given the volume's name; of course, very similar to VLGetEntryByID() above. */
455 GetEntryByName (rxcall, volname, aentry, new, this_op)
456 struct rx_call *rxcall;
458 char *aentry; /* entry data copied here */
460 { struct ubik_trans *trans;
461 afs_int32 blockindex, errorcode;
462 struct nvlentry tentry;
464 if (NameIsId(volname)) {
465 return GetEntryByID(rxcall, atoi(volname), -1, aentry, new, this_op);
467 if (InvalidVolname(volname))
469 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
471 VLog(5, ("GetVolumeByName %s (%d) %s\n", volname, new, rxinfo(rxcall)));
472 blockindex = FindByName(trans, volname, &tentry, &errorcode);
473 if (blockindex == 0) { /* entry not found */
474 if (!errorcode) errorcode = VL_NOENT;
476 ubik_AbortTrans(trans);
479 if (tentry.flags & VLDELETED) { /* Entry is deleted */
481 ubik_AbortTrans(trans);
482 return VL_ENTDELETED;
484 /* Convert to external entry representation */
486 vlentry_to_nvldbentry(&tentry, (struct nvldbentry *)aentry);
488 vlentry_to_uvldbentry(&tentry, (struct uvldbentry *)aentry);
490 vlentry_to_vldbentry(&tentry, (struct vldbentry *)aentry);
491 return(ubik_EndTrans(trans));
494 VL_GetEntryByNameO (rxcall, volname, aentry)
495 struct rx_call *rxcall;
497 struct vldbentry *aentry; /* entry data copied here */
499 COUNT_REQ (VLGETENTRYBYNAME);
500 return (GetEntryByName(rxcall, volname, (char *)aentry, 0, this_op));
504 VL_GetEntryByNameN (rxcall, volname, aentry)
505 struct rx_call *rxcall;
507 struct nvldbentry *aentry; /* entry data copied here */
509 COUNT_REQ (VLGETENTRYBYNAMEN);
510 return (GetEntryByName(rxcall, volname, (char *)aentry, 1, this_op));
513 VL_GetEntryByNameU (rxcall, volname, aentry)
514 struct rx_call *rxcall;
516 struct uvldbentry *aentry; /* entry data copied here */
518 COUNT_REQ (VLGETENTRYBYNAMEU);
519 return (GetEntryByName(rxcall, volname, (char *)aentry, 2, this_op));
524 /* Get the current value of the maximum volume id and bump the volume id counter by Maxvolidbump. */
525 VL_GetNewVolumeId (rxcall, Maxvolidbump, newvolumeid)
526 struct rx_call *rxcall;
527 afs_int32 Maxvolidbump;
528 afs_int32 *newvolumeid;
529 { register afs_int32 errorcode, maxvolumeid;
530 struct ubik_trans *trans;
532 COUNT_REQ (VLGETNEWVOLUMEID);
533 if (!afsconf_SuperUser(vldb_confdir, rxcall, (char *)0))
536 if (Maxvolidbump < 0 || Maxvolidbump > MAXBUMPCOUNT)
537 END ( VL_BADVOLIDBUMP );
539 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
542 *newvolumeid = maxvolumeid = ntohl(cheader.vital_header.MaxVolumeId);
543 maxvolumeid += Maxvolidbump;
544 VLog(1, ("GetNewVolid newmax=%d %s\n", maxvolumeid, rxinfo(rxcall)));
545 cheader.vital_header.MaxVolumeId = htonl(maxvolumeid);
546 if (write_vital_vlheader(trans)) {
549 errorcode = (ubik_EndTrans(trans));
554 ubik_AbortTrans(trans);
557 osi_auditU (rxcall, VLGetNewVolumeIdEvent, errorcode, AUD_END);
562 /* Simple replace the contents of the vldb entry, volid, with
563 * newentry. No individual checking/updating per field (alike
564 * VLUpdateEntry) is done. */
566 VL_ReplaceEntry (rxcall, volid, voltype, newentry, releasetype)
567 struct rx_call *rxcall;
570 struct vldbentry *newentry;
571 afs_int32 releasetype;
572 { struct ubik_trans *trans;
573 afs_int32 blockindex, errorcode, typeindex;
575 int hashVol[MAXTYPES];
576 struct nvlentry tentry;
578 COUNT_REQ (VLREPLACEENTRY);
579 for(typeindex = 0; typeindex < MAXTYPES; typeindex++)
580 hashVol[typeindex] = 0;
582 if (!afsconf_SuperUser(vldb_confdir, rxcall, (char *)0))
585 if (errorcode = check_vldbentry(newentry))
588 if (voltype != -1 && InvalidVoltype(voltype))
589 END ( VL_BADVOLTYPE );
591 if (releasetype && InvalidReleasetype(releasetype))
592 END( VL_BADRELLOCKTYPE );
593 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
596 VLog(1, ("OReplace Volume %d %s\n", volid, rxinfo(rxcall)));
597 /* find vlentry we're changing */
598 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
599 if (blockindex == 0) { /* entry not found */
600 if (!errorcode) errorcode = VL_NOENT;
604 /* check that we're not trying to change the RW vol ID */
605 if (newentry->volumeId[RWVOL] != tentry.volumeId[RWVOL]) {
606 ABORT( VL_BADENTRY );
609 /* unhash volid entries if they're disappearing or changing.
610 * Remember if we need to hash in the new value (we don't have to
611 * rehash if volid stays same */
612 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
613 if (tentry.volumeId[typeindex] != newentry->volumeId[typeindex]) {
614 if (tentry.volumeId[typeindex])
615 if (errorcode = UnhashVolid(trans, typeindex, blockindex,
619 /* we must rehash new id if the id is different and the ID is nonzero */
620 hashVol[typeindex] = 1; /* must rehash this guy if he exists */
624 /* Rehash volname if it changes */
625 if (strcmp(newentry->name, tentry.name)) { /* Name changes; redo hashing */
626 if (errorcode = UnhashVolname(trans, blockindex, &tentry)) {
632 /* after this, tentry is new entry, not old one. vldbentry_to_vlentry
633 doesn't touch hash chains */
634 if (errorcode = vldbentry_to_vlentry(trans, newentry, &tentry)) {
638 for(typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
639 if (hashVol[typeindex] && tentry.volumeId[typeindex]) {
640 if (errorcode = HashVolid(trans, typeindex, blockindex, &tentry)) {
647 HashVolname(trans, blockindex, &tentry);
650 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
651 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
655 END (ubik_EndTrans(trans));
659 ubik_AbortTrans(trans);
662 osi_auditU (rxcall, VLReplaceVLEntryEvent, errorcode, AUD_LONG, volid, AUD_END);
666 VL_ReplaceEntryN (rxcall, volid, voltype, newentry, releasetype)
667 struct rx_call *rxcall;
670 struct nvldbentry *newentry;
671 afs_int32 releasetype;
672 { struct ubik_trans *trans;
673 afs_int32 blockindex, errorcode, typeindex;
675 int hashVol[MAXTYPES];
676 struct nvlentry tentry;
678 COUNT_REQ (VLREPLACEENTRYN);
679 for(typeindex = 0; typeindex < MAXTYPES; typeindex++)
680 hashVol[typeindex] = 0;
682 if (!afsconf_SuperUser(vldb_confdir, rxcall, (char *)0))
685 if (errorcode = check_nvldbentry(newentry))
688 if (voltype != -1 && InvalidVoltype(voltype))
689 END ( VL_BADVOLTYPE );
691 if (releasetype && InvalidReleasetype(releasetype))
692 END( VL_BADRELLOCKTYPE );
693 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
696 VLog(1, ("Replace Volume %d %s\n", volid, rxinfo(rxcall)));
697 /* find vlentry we're changing */
698 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
699 if (blockindex == 0) { /* entry not found */
700 if (!errorcode) errorcode = VL_NOENT;
704 /* check that we're not trying to change the RW vol ID */
705 if (newentry->volumeId[RWVOL] != tentry.volumeId[RWVOL]) {
706 ABORT( VL_BADENTRY );
709 /* unhash volid entries if they're disappearing or changing.
710 * Remember if we need to hash in the new value (we don't have to
711 * rehash if volid stays same */
712 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
713 if (tentry.volumeId[typeindex] != newentry->volumeId[typeindex]) {
714 if (tentry.volumeId[typeindex])
715 if (errorcode = UnhashVolid(trans, typeindex, blockindex,
719 /* we must rehash new id if the id is different and the ID is nonzero */
720 hashVol[typeindex] = 1; /* must rehash this guy if he exists */
724 /* Rehash volname if it changes */
725 if (strcmp(newentry->name, tentry.name)) { /* Name changes; redo hashing */
726 if (errorcode = UnhashVolname(trans, blockindex, &tentry)) {
732 /* after this, tentry is new entry, not old one. vldbentry_to_vlentry
733 doesn't touch hash chains */
734 if (errorcode = nvldbentry_to_vlentry(trans, newentry, &tentry)) {
738 for(typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
739 if (hashVol[typeindex] && tentry.volumeId[typeindex]) {
740 if (errorcode = HashVolid(trans, typeindex, blockindex, &tentry)) {
747 HashVolname(trans, blockindex, &tentry);
750 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
751 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
755 END (ubik_EndTrans(trans));
759 ubik_AbortTrans(trans);
762 osi_auditU (rxcall, VLReplaceVLEntryEvent, errorcode, AUD_LONG, volid, AUD_END);
767 /* 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. */
768 /* this routine may never have been tested; use replace entry instead unless you're brave */
769 VL_UpdateEntry (rxcall, volid, voltype, updateentry, releasetype)
770 struct rx_call *rxcall;
773 afs_int32 releasetype;
774 struct VldbUpdateEntry *updateentry; /* Update entry copied here */
775 { struct ubik_trans *trans;
776 afs_int32 blockindex, errorcode;
777 struct nvlentry tentry;
779 COUNT_REQ (VLUPDATEENTRY);
780 if (!afsconf_SuperUser(vldb_confdir, rxcall, (char *)0))
782 if ((voltype != -1 ) && (InvalidVoltype(voltype)))
783 END( VL_BADVOLTYPE );
784 if (releasetype && InvalidReleasetype(releasetype))
785 END( VL_BADRELLOCKTYPE );
786 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
789 VLog(1, ("Update Volume %d %s\n", volid, rxinfo(rxcall)));
790 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
791 if (blockindex == 0) { /* entry not found */
792 if (!errorcode) errorcode = VL_NOENT;
796 /* Do the actual updating of the entry, tentry. */
797 if (errorcode = get_vldbupdateentry(trans, blockindex, updateentry, &tentry)) {
801 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
802 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
805 END(ubik_EndTrans(trans));
809 ubik_AbortTrans(trans);
812 osi_auditU (rxcall, VLUpdateEntryEvent, errorcode, AUD_LONG, volid, AUD_END);
817 VL_UpdateEntryByName (rxcall, volname, updateentry, releasetype)
818 struct rx_call *rxcall;
820 afs_int32 releasetype;
821 struct VldbUpdateEntry *updateentry; /* Update entry copied here */
822 { struct ubik_trans *trans;
823 afs_int32 blockindex, errorcode;
824 struct nvlentry tentry;
826 COUNT_REQ (VLUPDATEENTRYBYNAME);
827 if (!afsconf_SuperUser(vldb_confdir, rxcall, (char *)0))
829 if (releasetype && InvalidReleasetype(releasetype))
830 END( VL_BADRELLOCKTYPE );
831 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
834 blockindex = FindByName(trans, volname, &tentry, &errorcode);
835 if (blockindex == 0) { /* entry not found */
836 if (!errorcode) errorcode = VL_NOENT;
840 /* Do the actual updating of the entry, tentry. */
841 if (errorcode = get_vldbupdateentry(trans, blockindex, updateentry, &tentry)) {
845 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
846 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
849 END(ubik_EndTrans(trans));
853 ubik_AbortTrans(trans);
856 osi_auditU (rxcall, VLUpdateEntryEvent, errorcode, AUD_LONG, -1, AUD_END);
861 /* Set a lock to the vldb entry for volid (of type voltype if not -1). */
862 VL_SetLock (rxcall, volid, voltype, voloper)
863 struct rx_call *rxcall;
867 { afs_int32 timestamp, blockindex, errorcode;
868 struct ubik_trans *trans;
869 struct nvlentry tentry;
871 COUNT_REQ(VLSETLOCK);
872 if (!afsconf_SuperUser(vldb_confdir, rxcall, (char *)0))
874 if ((voltype != -1 ) && (InvalidVoltype(voltype)))
875 END( VL_BADVOLTYPE );
876 if (InvalidOperation(voloper))
877 END( VL_BADVOLOPER );
878 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
881 VLog(1, ("SetLock Volume %d %s\n", volid, rxinfo(rxcall)));
882 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
883 if (blockindex == NULLO) {
884 if (!errorcode) errorcode = VL_NOENT;
887 if (tentry.flags & VLDELETED) {
888 ABORT( VL_ENTDELETED );
890 timestamp = FT_ApproxTime();
892 /* Check if entry is already locked; note that we unlock any entry
893 * locked more than MAXLOCKTIME seconds */
894 if ((tentry.LockTimestamp)
895 && ((timestamp - tentry.LockTimestamp) < MAXLOCKTIME)) {
896 ABORT( VL_ENTRYLOCKED );
899 /* Consider it an unlocked entry: set current timestamp, caller
900 * and active vol operation */
901 tentry.LockTimestamp = timestamp;
902 tentry.LockAfsId = 0; /* Not implemented yet */
903 if (tentry.flags & VLOP_RELEASE) {
904 ABORT( VL_RERELEASE );
906 tentry.flags &= ~VLOP_ALLOPERS; /* Clear any possible older operation bit */
907 tentry.flags |= voloper;
909 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
912 END(ubik_EndTrans(trans));
916 ubik_AbortTrans(trans);
919 osi_auditU (rxcall, VLSetLockEvent, errorcode, AUD_LONG, volid, AUD_END);
924 /* Release an already locked vldb entry. Releasetype determines what
925 * fields (afsid and/or volume operation) will be cleared along with
926 * the lock time stamp. */
928 VL_ReleaseLock (rxcall, volid, voltype, releasetype)
929 struct rx_call *rxcall;
932 afs_int32 releasetype;
933 { afs_int32 blockindex, errorcode;
934 struct ubik_trans *trans;
935 struct nvlentry tentry;
937 COUNT_REQ(VLRELEASELOCK);
938 if (!afsconf_SuperUser(vldb_confdir, rxcall, (char *)0))
940 if ((voltype != -1 ) && (InvalidVoltype(voltype)))
941 END( VL_BADVOLTYPE );
942 if (releasetype && InvalidReleasetype(releasetype))
943 END( VL_BADRELLOCKTYPE );
944 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
947 VLog(1, ("ReleaseLock Volume %d %s\n", volid, rxinfo(rxcall)));
948 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
949 if (blockindex == NULLO) {
950 if (!errorcode) errorcode = VL_NOENT;
953 if (tentry.flags & VLDELETED) {
954 ABORT( VL_ENTDELETED );
957 ReleaseEntry(&tentry, releasetype); /* Unlock the appropriate fields */
958 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
961 END(ubik_EndTrans(trans));
965 ubik_AbortTrans(trans);
968 osi_auditU (rxcall, VLReleaseLockEvent, errorcode, AUD_LONG, volid, AUD_END);
973 /* 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. */
974 VL_ListEntry (rxcall, previous_index, count, next_index, aentry)
975 struct rx_call *rxcall;
976 afs_int32 previous_index;
978 afs_int32 *next_index;
979 struct vldbentry *aentry;
981 struct ubik_trans *trans;
982 struct nvlentry tentry;
984 COUNT_REQ(VLLISTENTRY);
985 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
987 VLog(25, ("OListEntry index=%d %s\n", previous_index, rxinfo(rxcall)));
988 *next_index = NextEntry(trans, previous_index, &tentry, count);
990 vlentry_to_vldbentry(&tentry, aentry);
991 return(ubik_EndTrans(trans));
994 /* 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. */
995 VL_ListEntryN (rxcall, previous_index, count, next_index, aentry)
996 struct rx_call *rxcall;
997 afs_int32 previous_index;
999 afs_int32 *next_index;
1000 struct nvldbentry *aentry;
1002 struct ubik_trans *trans;
1003 struct nvlentry tentry;
1005 COUNT_REQ(VLLISTENTRYN);
1006 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1008 VLog(25, ("ListEntry index=%d %s\n", previous_index, rxinfo(rxcall)));
1009 *next_index = NextEntry(trans, previous_index, &tentry, count);
1011 vlentry_to_nvldbentry(&tentry, aentry);
1012 return(ubik_EndTrans(trans));
1016 /* 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. */
1017 VL_ListAttributes(rxcall, attributes, nentries, vldbentries)
1018 struct rx_call *rxcall;
1019 struct VldbListByAttributes *attributes;
1020 afs_int32 *nentries;
1021 bulkentries *vldbentries;
1022 { int errorcode, allocCount = 0;
1023 struct ubik_trans *trans;
1024 struct nvlentry tentry;
1025 struct vldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1028 COUNT_REQ (VLLISTATTRIBUTES);
1029 vldbentries->bulkentries_val = 0;
1030 vldbentries->bulkentries_len = *nentries = 0;
1031 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1033 allocCount = VLDBALLOCCOUNT;
1034 Vldbentry = VldbentryFirst = vldbentries->bulkentries_val = (vldbentry *)malloc(allocCount * sizeof(vldbentry));
1035 if (Vldbentry == NULL) {
1037 ubik_AbortTrans(trans);
1040 VldbentryLast = VldbentryFirst + allocCount;
1041 /* Handle the attribute by volume id totally separate of the rest (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!) */
1042 if (attributes->Mask & VLLIST_VOLUMEID) {
1043 afs_int32 blockindex, chain;
1044 struct nvlentry tempentry;
1046 blockindex = FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1047 if (blockindex == 0) {
1048 if (!errorcode) errorcode = VL_NOENT;
1050 ubik_AbortTrans(trans);
1051 if(vldbentries->bulkentries_val)free((char *)vldbentries->bulkentries_val);
1052 vldbentries->bulkentries_val = 0;
1053 vldbentries->bulkentries_len = 0;
1056 if (errorcode = put_attributeentry(&Vldbentry, &VldbentryFirst, &VldbentryLast, vldbentries, &tentry, nentries, &allocCount)) {
1058 ubik_AbortTrans(trans);
1059 if(vldbentries->bulkentries_val)free((char *)vldbentries->bulkentries_val);
1060 vldbentries->bulkentries_val = 0;
1061 vldbentries->bulkentries_len = 0;
1062 return VL_SIZEEXCEEDED;
1065 afs_int32 nextblockindex=0, count=0, k, match=0;
1066 while (nextblockindex = NextEntry(trans, nextblockindex, &tentry, &count)) {
1067 if (++pollcount > 50) {
1072 if (attributes->Mask & VLLIST_SERVER) {
1074 if ((serverindex = IpAddrToRelAddr(attributes->server, (struct ubik_trans *) 0)) == -1) continue;
1075 for (k=0; k<OMAXNSERVERS;k++) {
1076 if (tentry.serverNumber[k] == BADSERVERID) break;
1077 if (tentry.serverNumber[k] == serverindex) {
1082 if (!match) continue;
1084 if (attributes->Mask & VLLIST_PARTITION) {
1086 if (tentry.serverPartition[k] != attributes->partition) continue;
1088 for (k=0; k<OMAXNSERVERS;k++) {
1089 if (tentry.serverNumber[k] == BADSERVERID) break;
1090 if (tentry.serverPartition[k] == attributes->partition) {
1095 if (!match) continue;
1099 if (attributes->Mask & VLLIST_FLAG) {
1100 if (!(tentry.flags & attributes->flag)) continue;
1102 if (errorcode = put_attributeentry(&Vldbentry, &VldbentryFirst, &VldbentryLast, vldbentries, &tentry, nentries, &allocCount)) {
1104 ubik_AbortTrans(trans);
1105 if(vldbentries->bulkentries_val)free((char *)vldbentries->bulkentries_val);
1106 vldbentries->bulkentries_val = 0;
1107 vldbentries->bulkentries_len = 0;
1112 if (vldbentries->bulkentries_len && (allocCount > vldbentries->bulkentries_len)) {
1114 vldbentries->bulkentries_val = (vldbentry *) realloc(vldbentries->bulkentries_val, vldbentries->bulkentries_len * sizeof(vldbentry));
1115 if (vldbentries->bulkentries_val == NULL) {
1117 ubik_AbortTrans(trans);
1121 VLog(5, ("ListAttrs nentries=%d %s\n", vldbentries->bulkentries_len, rxinfo(rxcall)));
1122 return(ubik_EndTrans(trans));
1125 VL_ListAttributesN(rxcall, attributes, nentries, vldbentries)
1126 struct rx_call *rxcall;
1127 struct VldbListByAttributes *attributes;
1128 afs_int32 *nentries;
1129 nbulkentries *vldbentries;
1130 { int errorcode, allocCount = 0;
1131 struct ubik_trans *trans;
1132 struct nvlentry tentry;
1133 struct nvldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1136 COUNT_REQ (VLLISTATTRIBUTESN);
1137 vldbentries->nbulkentries_val = 0;
1138 vldbentries->nbulkentries_len = *nentries = 0;
1139 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1141 allocCount = VLDBALLOCCOUNT;
1142 Vldbentry = VldbentryFirst = vldbentries->nbulkentries_val = (nvldbentry *)malloc(allocCount * sizeof(nvldbentry));
1143 if (Vldbentry == NULL) {
1145 ubik_AbortTrans(trans);
1148 VldbentryLast = VldbentryFirst + allocCount;
1149 /* Handle the attribute by volume id totally separate of the rest (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!) */
1150 if (attributes->Mask & VLLIST_VOLUMEID) {
1151 afs_int32 blockindex, chain;
1152 struct nvlentry tempentry;
1154 blockindex = FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1155 if (blockindex == 0) {
1156 if (!errorcode) errorcode = VL_NOENT;
1158 ubik_AbortTrans(trans);
1159 if(vldbentries->nbulkentries_val)free((char *)vldbentries->nbulkentries_val);
1160 vldbentries->nbulkentries_val = 0;
1161 vldbentries->nbulkentries_len = 0;
1164 if (errorcode = put_nattributeentry(&Vldbentry, &VldbentryFirst, &VldbentryLast, vldbentries,
1165 &tentry, 0, 0, nentries, &allocCount)) {
1167 ubik_AbortTrans(trans);
1168 if(vldbentries->nbulkentries_val)free((char *)vldbentries->nbulkentries_val);
1169 vldbentries->nbulkentries_val = 0;
1170 vldbentries->nbulkentries_len = 0;
1171 return VL_SIZEEXCEEDED;
1174 afs_int32 nextblockindex=0, count=0, k, match=0;
1175 while (nextblockindex = NextEntry(trans, nextblockindex, &tentry, &count)) {
1176 if (++pollcount > 50) {
1182 if (attributes->Mask & VLLIST_SERVER) {
1184 if ((serverindex = IpAddrToRelAddr(attributes->server, (struct ubik_trans *) 0)) == -1) continue;
1185 for (k=0; k<NMAXNSERVERS;k++) {
1186 if (tentry.serverNumber[k] == BADSERVERID) break;
1187 if (tentry.serverNumber[k] == serverindex) {
1192 if (!match) continue;
1194 if (attributes->Mask & VLLIST_PARTITION) {
1196 if (tentry.serverPartition[k] != attributes->partition) continue;
1198 for (k=0; k<NMAXNSERVERS;k++) {
1199 if (tentry.serverNumber[k] == BADSERVERID) break;
1200 if (tentry.serverPartition[k] == attributes->partition) {
1205 if (!match) continue;
1209 if (attributes->Mask & VLLIST_FLAG) {
1210 if (!(tentry.flags & attributes->flag)) continue;
1212 if (errorcode = put_nattributeentry(&Vldbentry, &VldbentryFirst, &VldbentryLast,
1213 vldbentries, &tentry, 0, 0, nentries, &allocCount)) {
1215 ubik_AbortTrans(trans);
1216 if(vldbentries->nbulkentries_val)free((char *)vldbentries->nbulkentries_val);
1217 vldbentries->nbulkentries_val = 0;
1218 vldbentries->nbulkentries_len = 0;
1223 if (vldbentries->nbulkentries_len && (allocCount > vldbentries->nbulkentries_len)) {
1225 vldbentries->nbulkentries_val = (nvldbentry *) realloc(vldbentries->nbulkentries_val,
1226 vldbentries->nbulkentries_len * sizeof(nvldbentry));
1227 if (vldbentries->nbulkentries_val == NULL) {
1229 ubik_AbortTrans(trans);
1233 VLog(5, ("NListAttrs nentries=%d %s\n", vldbentries->nbulkentries_len, rxinfo(rxcall)));
1234 return(ubik_EndTrans(trans));
1238 VL_ListAttributesN2(rxcall, attributes, name, startindex, nentries, vldbentries, nextstartindex)
1239 struct rx_call *rxcall;
1240 struct VldbListByAttributes *attributes;
1241 char * name; /* Wildcarded volume name */
1242 afs_int32 startindex;
1243 afs_int32 *nentries;
1244 nbulkentries *vldbentries;
1245 afs_int32 *nextstartindex;
1247 int errorcode=0, maxCount=VLDBALLOCCOUNT;
1248 struct ubik_trans *trans;
1249 struct nvlentry tentry;
1250 struct nvldbentry *Vldbentry=0, *VldbentryFirst=0, *VldbentryLast=0, tVldbentry;
1251 afs_int32 blockindex=0, count=0, k, match, matchindex;
1252 int serverindex=-1; /* no server found */
1253 int findserver=0, findpartition=0, findflag=0, findname=0;
1256 int namematchRWBK, namematchRO, thismatch, matchtype;
1257 char volumename[VL_MAXNAMELEN];
1259 COUNT_REQ (VLLISTATTRIBUTESN2);
1260 vldbentries->nbulkentries_val = 0;
1261 vldbentries->nbulkentries_len = 0;
1263 *nextstartindex = -1;
1265 errorcode = Init_VLdbase(&trans, LOCKREAD, this_op);
1266 if (errorcode) return errorcode;
1268 Vldbentry = VldbentryFirst = vldbentries->nbulkentries_val = (nvldbentry *)malloc(maxCount * sizeof(nvldbentry));
1269 if (Vldbentry == NULL) {
1271 ubik_AbortTrans(trans);
1275 VldbentryLast = VldbentryFirst + maxCount;
1277 /* Handle the attribute by volume id totally separate of the rest
1278 * (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!)
1280 if (attributes->Mask & VLLIST_VOLUMEID) {
1281 blockindex = FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1282 if (blockindex == 0) {
1283 if (!errorcode) errorcode = VL_NOENT;
1285 errorcode = put_nattributeentry(&Vldbentry, &VldbentryFirst, &VldbentryLast,
1286 vldbentries, &tentry, 0, 0, nentries, &maxCount);
1287 if (errorcode) goto done;
1291 /* Search each entry in the database and return all entries
1292 * that match the request. It checks volumename (with
1293 * wildcarding), entry flags, server, and partition.
1296 /* Get the server index for matching server address */
1297 if (attributes->Mask & VLLIST_SERVER) {
1298 serverindex = IpAddrToRelAddr(attributes->server, (struct ubik_trans *)0);
1299 if (serverindex == -1) goto done;
1302 findpartition = ((attributes->Mask & VLLIST_PARTITION) ? 1 : 0);
1303 findflag = ((attributes->Mask & VLLIST_FLAG) ? 1 : 0);
1304 if (name && (strcmp(name,".*") != 0) && (strcmp(name,"") != 0)) {
1305 sprintf(volumename, "^%s$", name);
1306 t = (char *)re_comp(volumename);
1308 errorcode = VL_BADNAME;
1314 /* Read each entry and see if it is the one we want */
1315 blockindex = startindex;
1316 while (blockindex = NextEntry(trans, blockindex, &tentry, &count)) {
1317 if (++pollcount > 50) {
1322 /* Step through each server index searching for a match.
1323 * Match to an existing RW, BK, or RO volume name (preference
1324 * is in this order). Remember which index we matched against.
1326 namematchRWBK = namematchRO = 0; /* 0->notTried; 1->match; 2->noMatch */
1328 for (k=0; (k<NMAXNSERVERS && (tentry.serverNumber[k]!=BADSERVERID)); k++) {
1329 thismatch = 0; /* does this index match */
1331 /* Match against the RW or BK volume name. Remember
1332 * results in namematchRWBK. Prefer RW over BK.
1334 if (tentry.serverFlags[k] & VLSF_RWVOL) {
1335 /* Does the name match the RW name */
1336 if (tentry.flags & VLF_RWEXISTS) {
1338 sprintf(volumename, "%s", tentry.name);
1339 if (re_exec(volumename)) {
1340 thismatch = VLSF_RWVOL;
1343 thismatch = VLSF_RWVOL;
1347 /* Does the name match the BK name */
1348 if (!thismatch && (tentry.flags & VLF_BACKEXISTS)) {
1350 sprintf(volumename, "%s.backup", tentry.name);
1351 if (re_exec(volumename)) {
1352 thismatch = VLSF_BACKVOL;
1355 thismatch = VLSF_BACKVOL;
1359 namematchRWBK = (thismatch?1:2);
1362 /* Match with the RO volume name. Compare once and
1363 * remember results in namematchRO. Note that this will
1364 * pick up entries marked NEWREPSITEs and DONTUSE.
1367 if (tentry.flags & VLF_ROEXISTS) {
1370 thismatch = ((namematchRO == 1)?VLSF_ROVOL:0);
1372 sprintf(volumename, "%s.readonly", tentry.name);
1373 if (re_exec(volumename))
1374 thismatch = VLSF_ROVOL;
1377 thismatch = VLSF_ROVOL;
1380 namematchRO = (thismatch?1:2);
1383 /* Is there a server match */
1384 if (thismatch && findserver &&
1385 (tentry.serverNumber[k] != serverindex))
1388 /* Is there a partition match */
1389 if (thismatch && findpartition &&
1390 (tentry.serverPartition[k] != attributes->partition))
1393 /* Is there a flag match */
1394 if (thismatch && findflag && !(tentry.flags & attributes->flag))
1397 /* We found a match. Remember the index, and type */
1401 matchtype = thismatch;
1404 /* Since we prefer RW and BK volume matches over RO matches,
1405 * if we have already checked the RWBK name, then we already
1406 * found the best match and so end the search.
1408 * If we tried matching against the RW, BK, and RO volume names
1409 * and both failed, then we end the search (none will match).
1411 if ( (match && namematchRWBK) ||
1412 ((namematchRWBK==2) && (namematchRO==2)) )
1416 /* Passed all the tests. Take it */
1418 errorcode = put_nattributeentry(&Vldbentry,
1419 &VldbentryFirst, &VldbentryLast,
1420 vldbentries, &tentry, matchtype, matchindex,
1421 nentries, &maxCount);
1422 if (errorcode) goto done;
1424 if (*nentries >= maxCount) break; /* collected the max */
1427 *nextstartindex = (blockindex ? blockindex : -1);
1433 ubik_AbortTrans(trans);
1434 if (vldbentries->nbulkentries_val)
1435 free((char *)vldbentries->nbulkentries_val);
1436 vldbentries->nbulkentries_val = 0;
1437 vldbentries->nbulkentries_len = 0;
1438 *nextstartindex = -1;
1441 VLog(5, ("N2ListAttrs nentries=%d %s\n", vldbentries->nbulkentries_len, rxinfo(rxcall)));
1442 return(ubik_EndTrans(trans));
1447 /* Retrieves in vldbentries all vldb entries that match the specified
1448 * attributes (by server number, partition, volume type, and flag); if
1449 * volume id is specified then the associated list for that entry is
1450 * returned. CAUTION: This could be a very expensive call since in most
1451 * cases sequential search of all vldb entries is performed.
1453 VL_LinkedList(rxcall, attributes, nentries, vldbentries)
1454 struct rx_call *rxcall;
1455 struct VldbListByAttributes *attributes;
1456 afs_int32 *nentries;
1457 vldb_list *vldbentries;
1460 struct ubik_trans *trans;
1461 struct nvlentry tentry;
1462 vldblist vllist, *vllistptr;
1463 afs_int32 blockindex, count, k, match;
1467 COUNT_REQ (VLLINKEDLIST);
1468 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1472 vldbentries->node = NULL;
1473 vllistptr = &vldbentries->node;
1475 /* List by volumeid */
1476 if (attributes->Mask & VLLIST_VOLUMEID) {
1477 blockindex = FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1480 ubik_AbortTrans(trans);
1481 return (errorcode ? errorcode : VL_NOENT);
1484 vllist = (single_vldbentry *) malloc(sizeof(single_vldbentry));
1485 if (vllist == NULL) {
1487 ubik_AbortTrans(trans);
1490 vlentry_to_vldbentry(&tentry, &vllist->VldbEntry);
1491 vllist->next_vldb = NULL;
1493 *vllistptr = vllist; /* Thread onto list */
1494 vllistptr = &vllist->next_vldb;
1498 /* Search by server, partition, and flags */
1500 for (blockindex = NextEntry(trans, 0, &tentry, &count);
1502 blockindex = NextEntry(trans, blockindex, &tentry, &count)) {
1505 if (++pollcount > 50) {
1510 /* Does this volume exist on the desired server */
1511 if (attributes->Mask & VLLIST_SERVER) {
1512 serverindex = IpAddrToRelAddr(attributes->server, (struct ubik_trans *)0);
1513 if (serverindex == -1) continue;
1514 for (k=0; k < OMAXNSERVERS; k++) {
1515 if (tentry.serverNumber[k] == BADSERVERID) break;
1516 if (tentry.serverNumber[k] == serverindex) {
1521 if (!match) continue;
1524 /* Does this volume exist on the desired partition */
1525 if (attributes->Mask & VLLIST_PARTITION) {
1527 if (tentry.serverPartition[k] != attributes->partition)
1530 for (k=0; k < OMAXNSERVERS; k++) {
1531 if (tentry.serverNumber[k] == BADSERVERID) break;
1532 if (tentry.serverPartition[k] == attributes->partition) {
1538 if (!match) continue;
1541 /* Does this volume have the desired flags */
1542 if (attributes->Mask & VLLIST_FLAG) {
1543 if (!(tentry.flags & attributes->flag))
1547 vllist = (single_vldbentry *) malloc(sizeof(single_vldbentry));
1548 if (vllist == NULL) {
1550 ubik_AbortTrans(trans);
1553 vlentry_to_vldbentry(&tentry, &vllist->VldbEntry);
1554 vllist->next_vldb = NULL;
1556 *vllistptr = vllist; /* Thread onto list */
1557 vllistptr = &vllist->next_vldb;
1559 if (smallMem && (*nentries >= VLDBALLOCCOUNT)) {
1561 ubik_AbortTrans(trans);
1562 return VL_SIZEEXCEEDED;
1567 return(ubik_EndTrans(trans));
1570 VL_LinkedListN(rxcall, attributes, nentries, vldbentries)
1571 struct rx_call *rxcall;
1572 struct VldbListByAttributes *attributes;
1573 afs_int32 *nentries;
1574 nvldb_list *vldbentries;
1577 struct ubik_trans *trans;
1578 struct nvlentry tentry;
1579 nvldblist vllist, *vllistptr;
1580 afs_int32 blockindex, count, k, match;
1584 COUNT_REQ (VLLINKEDLISTN);
1585 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1589 vldbentries->node = NULL;
1590 vllistptr = &vldbentries->node;
1592 /* List by volumeid */
1593 if (attributes->Mask & VLLIST_VOLUMEID) {
1594 blockindex = FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1597 ubik_AbortTrans(trans);
1598 return (errorcode ? errorcode : VL_NOENT);
1601 vllist = (single_nvldbentry *) malloc(sizeof(single_nvldbentry));
1602 if (vllist == NULL) {
1604 ubik_AbortTrans(trans);
1607 vlentry_to_nvldbentry(&tentry, &vllist->VldbEntry);
1608 vllist->next_vldb = NULL;
1610 *vllistptr = vllist; /* Thread onto list */
1611 vllistptr = &vllist->next_vldb;
1615 /* Search by server, partition, and flags */
1617 for (blockindex = NextEntry(trans, 0, &tentry, &count);
1619 blockindex = NextEntry(trans, blockindex, &tentry, &count)) {
1622 if (++pollcount > 50) {
1627 /* Does this volume exist on the desired server */
1628 if (attributes->Mask & VLLIST_SERVER) {
1629 serverindex = IpAddrToRelAddr(attributes->server, (struct ubik_trans *)0);
1630 if (serverindex == -1) continue;
1631 for (k=0; k < NMAXNSERVERS; k++) {
1632 if (tentry.serverNumber[k] == BADSERVERID) break;
1633 if (tentry.serverNumber[k] == serverindex) {
1638 if (!match) continue;
1641 /* Does this volume exist on the desired partition */
1642 if (attributes->Mask & VLLIST_PARTITION) {
1644 if (tentry.serverPartition[k] != attributes->partition)
1647 for (k=0; k < NMAXNSERVERS; k++) {
1648 if (tentry.serverNumber[k] == BADSERVERID) break;
1649 if (tentry.serverPartition[k] == attributes->partition) {
1655 if (!match) continue;
1658 /* Does this volume have the desired flags */
1659 if (attributes->Mask & VLLIST_FLAG) {
1660 if (!(tentry.flags & attributes->flag))
1664 vllist = (single_nvldbentry *) malloc(sizeof(single_nvldbentry));
1665 if (vllist == NULL) {
1667 ubik_AbortTrans(trans);
1670 vlentry_to_nvldbentry(&tentry, &vllist->VldbEntry);
1671 vllist->next_vldb = NULL;
1673 *vllistptr = vllist; /* Thread onto list */
1674 vllistptr = &vllist->next_vldb;
1676 if (smallMem && (*nentries >= VLDBALLOCCOUNT)) {
1678 ubik_AbortTrans(trans);
1679 return VL_SIZEEXCEEDED;
1684 return(ubik_EndTrans(trans));
1687 /* Get back vldb header statistics (allocs, frees, maxvolumeid, totalentries, etc) and dynamic statistics (number of requests and/or aborts per remote procedure call, etc) */
1688 VL_GetStats(rxcall, stats, vital_header)
1689 struct rx_call *rxcall;
1691 vital_vlheader *vital_header;
1692 { register afs_int32 errorcode;
1693 struct ubik_trans *trans;
1695 COUNT_REQ(VLGETSTATS);
1697 /* Allow users to get statistics freely */
1698 if (!afsconf_SuperUser(vldb_confdir, rxcall, (char *)0)) /* Must be in 'UserList' to use */
1701 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1703 VLog(5, ("GetStats %\n", rxinfo(rxcall)));
1704 bcopy((char *)&cheader.vital_header, (char *) vital_header, sizeof(vital_vlheader));
1705 bcopy((char *)&dynamic_statistics, (char *) stats, sizeof(vldstats));
1706 return(ubik_EndTrans(trans));
1709 /* Get the list of file server addresses from the VLDB. Currently it's pretty
1710 * easy to do. In the future, it might require a little bit of grunging
1711 * through the VLDB, but that's life.
1713 VL_GetAddrs(rxcall, Handle, spare2, spare3, nentries, addrsp)
1714 struct rx_call *rxcall;
1715 afs_int32 Handle, spare2;
1716 struct VLCallBack *spare3;
1717 afs_int32 *nentries;
1719 { register afs_int32 errorcode;
1720 struct ubik_trans *trans;
1724 COUNT_REQ(VLGETADDRS);
1725 addrsp->bulkaddrs_len = *nentries = 0;
1726 addrsp->bulkaddrs_val = 0;
1727 bzero (spare3, sizeof (struct VLCallBack));
1729 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1732 VLog(5, ("GetAddrs\n"));
1733 addrsp->bulkaddrs_val = taddrp = (afs_uint32 *)malloc(sizeof(afs_int32)*(MAXSERVERID+1));
1734 nservers= *nentries = addrsp->bulkaddrs_len = 0;
1738 ubik_AbortTrans(trans);
1742 for (i=0; i <= MAXSERVERID; i++) {
1743 if (*taddrp = ntohl(cheader.IpMappedAddr[i])) {
1749 addrsp->bulkaddrs_len = *nentries = nservers;
1750 return(ubik_EndTrans(trans));
1753 #define PADDR(addr) printf("%d.%d.%d.%d", (addr>>24)&0xff, (addr>>16)&0xff, (addr>>8) &0xff, addr&0xff);
1755 VL_RegisterAddrs(rxcall, uuidp, spare1, addrsp)
1756 struct rx_call *rxcall;
1762 struct ubik_trans *trans;
1763 int cnt, h, i, j, k, m, hostslot, base, index;
1764 struct extentaddr *exp = 0, *tex;
1766 afs_uint32 addrs[VL_MAXIPADDRS_PERMH];
1767 afs_int32 fbase, findex;
1768 int count, willChangeEntry, foundUuidEntry, willReplaceCnt;
1769 int WillReplaceEntry, WillChange[MAXSERVERID+1], FoundUuid, ReplaceEntry;
1772 COUNT_REQ(VLREGADDR);
1773 if (!afsconf_SuperUser(vldb_confdir, rxcall, (char *)0))
1775 if (code = Init_VLdbase(&trans, LOCKWRITE, this_op))
1778 /* Eliminate duplicates from IP address list */
1779 for (k=0, cnt=0; k<addrsp->bulkaddrs_len; k++) {
1780 if (addrsp->bulkaddrs_val[k] == 0)
1782 for (m=0; m < cnt; m++) {
1783 if (addrs[m] == addrsp->bulkaddrs_val[k])
1787 if (m == VL_MAXIPADDRS_PERMH) {
1788 VLog(0, ("Number of addresses exceeds %d. Cannot register IP addr 0x%x in VLDB\n",
1789 VL_MAXIPADDRS_PERMH, addrsp->bulkaddrs_val[k]));
1791 addrs[m] = addrsp->bulkaddrs_val[k];
1797 ubik_AbortTrans(trans);
1798 return VL_INDEXERANGE;
1804 /* For each server registered within the VLDB */
1805 for (srvidx=0; srvidx <= MAXSERVERID;srvidx++) {
1806 willChangeEntry = 0;
1807 WillReplaceEntry = 1;
1808 if ((HostAddress[srvidx] & 0xff000000) == 0xff000000) {
1809 /* The server is registered as a multihomed */
1810 base = (HostAddress[srvidx] >> 16) & 0xff;
1811 index = HostAddress[srvidx] & 0x0000ffff;
1812 if (base >= VL_MAX_ADDREXTBLKS) {
1813 VLog(0, ("Internal error: Multihome extent base is too large. Base %d index %d\n",
1817 if (index >= VL_MHSRV_PERBLK) {
1818 VLog(0, ("Internal error: Multihome extent index is too large. Base %d index %d\n",
1822 if (!ex_addr[base]) {
1823 VLog(0, ("Internal error: Multihome extent does not exist. Base %d\n", base));
1827 /* See if the addresses to register will change this server entry */
1828 exp = &ex_addr[base][index];
1829 tuuid = exp->ex_hostuuid;
1830 afs_ntohuuid(&tuuid);
1831 if (afs_uuid_equal(uuidp, &tuuid)) {
1835 for (mhidx=0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
1836 if (!exp->ex_addrs[mhidx]) continue;
1837 for (k=0; k<cnt; k++) {
1838 if (ntohl(exp->ex_addrs[mhidx]) == addrs[k]) {
1839 willChangeEntry = 1;
1840 WillChange[count] = srvidx;
1844 if (k >= cnt) WillReplaceEntry = 0;
1848 /* The server is not registered as a multihomed.
1849 * See if the addresses to register will replace this server entry.
1851 for (k=0; k<cnt; k++) {
1852 if (HostAddress[srvidx] == addrs[k]) {
1853 willChangeEntry = 1;
1854 WillChange[count] = srvidx;
1855 WillReplaceEntry = 1;
1860 if (willChangeEntry) {
1861 if (WillReplaceEntry) {
1863 ReplaceEntry = srvidx;
1869 /* If we found the uuid in the VLDB and if we are replacing another
1870 * entire entry, then complain and fail. Also, if we did not find
1871 * the uuid in the VLDB and the IP addresses being registered was
1872 * found in more than one other entry, then we don't know which one
1873 * to replace and will complain and fail.
1875 if ( ( foundUuidEntry && (willReplaceCnt > 0)) ||
1876 (!foundUuidEntry && (count > 1)) ) {
1877 VLog(0, ("The following fileserver is being registered in the VLDB:\n"));
1879 for (k=0; k<cnt; k++) {
1880 if (k>0) printf(" ");
1885 if (foundUuidEntry) {
1886 printf(" It would have replaced the existing VLDB server entry:\n");
1887 printf(" entry %d: [", FoundUuid);
1888 base = (HostAddress[FoundUuid] >> 16) & 0xff;
1889 index = HostAddress[FoundUuid] & 0x0000ffff;
1890 exp = &ex_addr[base][index];
1891 for (mhidx=0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
1892 if (!exp->ex_addrs[mhidx]) continue;
1893 if (mhidx > 0) printf(" ");
1894 PADDR(ntohl(exp->ex_addrs[mhidx]));
1899 if (count == 1) printf(" Yet another VLDB server entry exists:\n");
1900 else printf(" Yet other VLDB server entries exist:\n");
1901 for (j=0; j<count; j++) {
1902 srvidx = WillChange[j];
1903 printf(" entry %d: ", srvidx);
1904 if ((HostAddress[srvidx] & 0xff000000) == 0xff000000) {
1906 base = (HostAddress[srvidx] >> 16) & 0xff;
1907 index = HostAddress[srvidx] & 0x0000ffff;
1908 exp = &ex_addr[base][index];
1909 for (mhidx=0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
1910 if (!exp->ex_addrs[mhidx]) continue;
1911 if (mhidx > 0) printf(" ");
1912 PADDR(ntohl(exp->ex_addrs[mhidx]));
1916 PADDR(HostAddress[srvidx]);
1922 printf(" You must 'vos changeaddr' this other server entry\n");
1924 printf(" You must 'vos changeaddr' these other server entries\n");
1926 printf(" and/or remove the sysid file from the registering fileserver\n");
1927 printf(" before the fileserver can be registered in the VLDB.\n");
1929 ubik_AbortTrans(trans);
1930 return VL_MULTIPADDR;
1933 /* Passed the checks. Now find and update the existing mh entry, or create
1936 if (foundUuidEntry) {
1937 /* Found the entry with same uuid. See if we need to change it */
1940 fbase = (HostAddress[FoundUuid] >> 16) & 0xff;
1941 index = HostAddress[FoundUuid] & 0x0000ffff;
1942 exp = &ex_addr[fbase][index];
1944 /* Determine if the entry has changed */
1945 for (k=0; ((k < cnt) && !change); k++) {
1946 if (ntohl(exp->ex_addrs[k]) != addrs[k])
1949 for (; ((k < VL_MAXIPADDRS_PERMH) && !change); k++) {
1950 if (exp->ex_addrs[k] != 0)
1954 return(ubik_EndTrans(trans));
1958 VLog(0, ("The following fileserver is being registered in the VLDB:\n"));
1960 for (k=0; k<cnt; k++) {
1961 if (k>0) printf(" ");
1966 if (foundUuidEntry) {
1967 printf(" It will replace the following existing entry in the VLDB (same uuid):\n");
1968 printf(" entry %d: [", FoundUuid);
1969 for (k=0; k < VL_MAXIPADDRS_PERMH; k++) {
1970 if (exp->ex_addrs[k] == 0) continue;
1971 if (k>0) printf(" ");
1972 PADDR(ntohl(exp->ex_addrs[k]));
1976 else if (willReplaceCnt || (count == 1)) {
1977 /* If we are not replacing an entry and there is only one entry to change,
1978 * then we will replace that entry.
1980 if (!willReplaceCnt) {
1981 ReplaceEntry = WillChange[0];
1985 /* Have an entry that needs to be replaced */
1986 if ((HostAddress[ReplaceEntry] & 0xff000000) == 0xff000000) {
1987 fbase = (HostAddress[ReplaceEntry] >> 16) & 0xff;
1988 index = HostAddress[ReplaceEntry] & 0x0000ffff;
1989 exp = &ex_addr[fbase][index];
1991 printf(" It will replace the following existing entry in the VLDB (new uuid):\n");
1992 printf(" entry %d: [", ReplaceEntry);
1993 for (k=0; k < VL_MAXIPADDRS_PERMH; k++) {
1994 if (exp->ex_addrs[k] == 0) continue;
1995 if (k>0) printf(" ");
1996 PADDR(ntohl(exp->ex_addrs[k]));
2000 /* Not a mh entry. So we have to create a new mh entry and
2001 * put it on the ReplaceEntry slot of the HostAddress array.
2003 printf(" It will replace existing entry %d, ", ReplaceEntry);
2004 PADDR(HostAddress[ReplaceEntry]);
2005 printf(", in the VLDB (new uuid):\n");
2007 code = FindExtentBlock(trans, uuidp, 1, ReplaceEntry, &exp, &fbase);
2009 ubik_AbortTrans(trans);
2010 return (code ? code : VL_IO);
2014 /* There is no entry for this server, must create a new mh entry as
2015 * well as use a new slot of the HostAddress array.
2017 printf(" It will create a new entry in the VLDB.\n");
2018 code = FindExtentBlock(trans, uuidp, 1, -1, &exp, &fbase);
2020 ubik_AbortTrans(trans);
2021 return (code ? code : VL_IO);
2025 /* Now we have a mh entry to fill in. Update the uuid, bump the
2026 * uniquifier, and fill in its IP addresses.
2029 afs_htonuuid(&tuuid);
2030 exp->ex_hostuuid = tuuid;
2031 exp->ex_uniquifier = htonl(ntohl(exp->ex_uniquifier)+1);
2032 for (k=0; k < cnt; k++) {
2033 exp->ex_addrs[k] = htonl(addrs[k]);
2035 for (; k < VL_MAXIPADDRS_PERMH; k++) {
2036 exp->ex_addrs[k] = 0;
2039 /* Write the new mh entry out */
2040 if (vlwrite(trans, DOFFSET(ntohl(ex_addr[0]->ex_contaddrs[fbase]),
2041 (char *)ex_addr[fbase], (char *)exp),
2042 (char *)exp, sizeof(*exp))) {
2043 ubik_AbortTrans(trans);
2047 /* Remove any common addresses from other mh entres. We know these entries
2048 * are being changed and not replaced so they are mh entries.
2051 for (i=0; i<count; i++) {
2054 /* Skip the entry we replaced */
2055 if (willReplaceCnt && (WillChange[i] == ReplaceEntry))
2058 base = (HostAddress[WillChange[i]] >> 16) & 0xff;
2059 index = HostAddress[WillChange[i]] & 0x0000ffff;
2060 tex = &ex_addr[fbase][index];
2063 printf(" The following existing entries in the VLDB will be updated:\n");
2065 printf(" entry %d: [", WillChange[i]);
2066 for (h=j=0; j < VL_MAXIPADDRS_PERMH; j++) {
2067 if (tex->ex_addrs[j]) {
2068 if (j>0) printf(" ");
2069 PADDR(ntohl(tex->ex_addrs[j]));
2072 for (k=0; k<cnt; k++) {
2073 if (ntohl(tex->ex_addrs[j]) == addrs[k]) break;
2076 /* Not found, so we keep it */
2077 tex->ex_addrs[h] = tex->ex_addrs[j];
2081 for (j=h; j < VL_MAXIPADDRS_PERMH; j++) {
2082 tex->ex_addrs[j] = 0; /* zero rest of mh entry */
2086 /* Write out the modified mh entry */
2087 tex->ex_uniquifier = htonl(ntohl(tex->ex_uniquifier)+1);
2088 doff=DOFFSET(ntohl(ex_addr[0]->ex_contaddrs[base]),
2089 (char *)ex_addr[base], (char *)tex);
2090 if (vlwrite(trans, doff, (char*)tex, sizeof(*tex))) {
2091 ubik_AbortTrans(trans);
2096 return(ubik_EndTrans(trans));
2099 VL_GetAddrsU(rxcall, attributes, uuidpo, uniquifier, nentries, addrsp)
2100 struct rx_call *rxcall;
2101 struct ListAddrByAttributes *attributes;
2103 afs_int32 *uniquifier, *nentries;
2105 { register afs_int32 errorcode, index=-1, op, offset;
2106 struct ubik_trans *trans;
2107 int nservers, i, j, k, base=0;
2108 struct extentaddr *exp=0;
2110 afs_uint32 *taddrp, taddr;
2112 COUNT_REQ(VLGETADDRSU);
2113 addrsp->bulkaddrs_len = *nentries = 0;
2114 addrsp->bulkaddrs_val = 0;
2115 VLog(5, ("GetAddrsU %s\n", rxinfo(rxcall)));
2116 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
2119 if (attributes->Mask & VLADDR_IPADDR) {
2120 if (attributes->Mask & (VLADDR_INDEX|VLADDR_UUID)) {
2121 ubik_AbortTrans(trans);
2124 for (base = 0; base < VL_MAX_ADDREXTBLKS; base++) {
2127 for (i = 1; i < VL_MHSRV_PERBLK; i++) {
2128 exp = &ex_addr[base][i];
2129 tuuid = exp->ex_hostuuid;
2130 afs_ntohuuid(&tuuid);
2131 if (afs_uuid_is_nil(&tuuid)) continue;
2132 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2133 if (exp->ex_addrs[j] && (ntohl(exp->ex_addrs[j]) == attributes->ipaddr)) {
2137 if (j < VL_MAXIPADDRS_PERMH) break;
2139 if (i < VL_MHSRV_PERBLK) break;
2141 if (base >= VL_MAX_ADDREXTBLKS) {
2142 ubik_AbortTrans(trans);
2145 } else if (attributes->Mask & VLADDR_INDEX) {
2146 if (attributes->Mask & (VLADDR_IPADDR|VLADDR_UUID)) {
2147 ubik_AbortTrans(trans);
2150 index = attributes->index;
2151 if (index < 1 || index >= (VL_MAX_ADDREXTBLKS*VL_MHSRV_PERBLK)) {
2152 ubik_AbortTrans(trans);
2153 return VL_INDEXERANGE;
2155 base = index / VL_MHSRV_PERBLK;
2156 offset = index % VL_MHSRV_PERBLK;
2158 ubik_AbortTrans(trans);
2161 if (!ex_addr[base]) {
2162 ubik_AbortTrans(trans);
2163 return VL_INDEXERANGE;
2165 exp = &ex_addr[base][offset];
2166 } else if (attributes->Mask & VLADDR_UUID) {
2167 if (attributes->Mask & (VLADDR_IPADDR|VLADDR_INDEX)) {
2168 ubik_AbortTrans(trans);
2171 if (!ex_addr[0]) { /* mh servers probably aren't setup on this vldb */
2172 ubik_AbortTrans(trans);
2175 if (errorcode = FindExtentBlock(trans, &attributes->uuid, 0, -1, &exp, &base)) {
2176 ubik_AbortTrans(trans);
2180 ubik_AbortTrans(trans);
2184 if (exp == (struct extentaddr *)0) {
2185 ubik_AbortTrans(trans);
2188 addrsp->bulkaddrs_val = taddrp = (afs_uint32 *)malloc(sizeof(afs_int32)*(MAXSERVERID+1));
2189 nservers= *nentries = addrsp->bulkaddrs_len = 0;
2192 ubik_AbortTrans(trans);
2195 tuuid = exp->ex_hostuuid;
2196 afs_ntohuuid(&tuuid);
2197 if (afs_uuid_is_nil(&tuuid)) {
2198 ubik_AbortTrans(trans);
2201 if (uuidpo) *uuidpo = tuuid;
2202 if (uniquifier) *uniquifier = ntohl(exp->ex_uniquifier);
2203 for (i = 0; i < VL_MAXIPADDRS_PERMH; i++) {
2204 if (exp->ex_addrs[i]) {
2205 taddr = ntohl(exp->ex_addrs[i]);
2206 /* Weed out duplicates */
2207 for (j = 0; j < nservers; j++) {
2208 if (taddrp[j] == taddr)
2211 if ((j == nservers) && (j <= MAXSERVERID)) {
2212 taddrp[nservers] = taddr;
2217 addrsp->bulkaddrs_len = *nentries = nservers;
2218 return(ubik_EndTrans(trans));
2221 /* ============> End of Exported vldb RPC functions <============= */
2224 /* Routine that copies the given vldb entry to the output buffer, vldbentries. */
2226 put_attributeentry(Vldbentry, VldbentryFirst, VldbentryLast, vldbentries, entry, nentries, alloccnt)
2227 struct vldbentry **Vldbentry, **VldbentryFirst, **VldbentryLast;
2228 bulkentries *vldbentries;
2229 struct nvlentry *entry;
2230 afs_int32 *nentries, *alloccnt;
2235 if (*Vldbentry == *VldbentryLast) {
2236 if (smallMem) return VL_SIZEEXCEEDED; /* no growing if smallMem defined */
2238 /* Allocate another set of memory; each time allocate twice as
2239 * many blocks as the last time. When we reach VLDBALLOCLIMIT,
2240 * then grow in increments of VLDBALLOCINCR.
2242 allo = (*alloccnt > VLDBALLOCLIMIT) ? VLDBALLOCINCR : *alloccnt;
2243 reall = (vldbentry *) realloc(*VldbentryFirst, (*alloccnt+allo)*sizeof(vldbentry));
2244 if (reall == NULL) return VL_NOMEM;
2246 *VldbentryFirst = vldbentries->bulkentries_val = reall;
2247 *Vldbentry = *VldbentryFirst + *alloccnt;
2248 *VldbentryLast = *Vldbentry + allo;
2251 vlentry_to_vldbentry(entry, *Vldbentry);
2254 vldbentries->bulkentries_len++;
2259 put_nattributeentry(Vldbentry, VldbentryFirst, VldbentryLast, vldbentries, entry,
2260 matchtype, matchindex, nentries, alloccnt)
2261 struct nvldbentry **Vldbentry, **VldbentryFirst, **VldbentryLast;
2262 nbulkentries *vldbentries;
2263 struct nvlentry *entry;
2264 afs_int32 matchtype, matchindex, *nentries, *alloccnt;
2269 if (*Vldbentry == *VldbentryLast) {
2270 if (smallMem) return VL_SIZEEXCEEDED; /* no growing if smallMem defined */
2272 /* Allocate another set of memory; each time allocate twice as
2273 * many blocks as the last time. When we reach VLDBALLOCLIMIT,
2274 * then grow in increments of VLDBALLOCINCR.
2276 allo = (*alloccnt > VLDBALLOCLIMIT) ? VLDBALLOCINCR : *alloccnt;
2277 reall = (nvldbentry *)realloc(*VldbentryFirst, (*alloccnt+allo)*sizeof(nvldbentry));
2278 if (reall == NULL) return VL_NOMEM;
2280 *VldbentryFirst = vldbentries->nbulkentries_val = reall;
2281 *Vldbentry = *VldbentryFirst + *alloccnt;
2282 *VldbentryLast = *Vldbentry + allo;
2285 vlentry_to_nvldbentry(entry, *Vldbentry);
2286 (*Vldbentry)->matchindex = (matchtype << 16) + matchindex;
2289 vldbentries->nbulkentries_len++;
2294 /* Common code to actually remove a vldb entry from the database. */
2296 RemoveEntry(trans, entryptr, tentry)
2297 struct ubik_trans *trans;
2299 struct nvlentry *tentry;
2301 register int errorcode;
2303 if (errorcode = UnthreadVLentry(trans, entryptr, tentry))
2305 if (errorcode = FreeBlock(trans, entryptr))
2311 ReleaseEntry(tentry, releasetype)
2312 struct nvlentry *tentry;
2313 afs_int32 releasetype;
2315 if (releasetype & LOCKREL_TIMESTAMP)
2316 tentry->LockTimestamp = 0;
2317 if (releasetype & LOCKREL_OPCODE)
2318 tentry->flags &= ~VLOP_ALLOPERS;
2319 if (releasetype & LOCKREL_AFSID)
2320 tentry->LockAfsId = 0;
2324 /* Verify that the incoming vldb entry is valid; multi type of error codes are returned. */
2326 check_vldbentry(aentry)
2327 struct vldbentry *aentry;
2331 if (InvalidVolname(aentry->name))
2333 if (aentry->nServers <= 0 || aentry->nServers > OMAXNSERVERS)
2334 return VL_BADSERVER;
2335 for (i=0; i < aentry->nServers; i++) {
2336 /* if (aentry->serverNumber[i] < 0 || aentry->serverNumber[i] > MAXSERVERID)
2337 return VL_BADSERVER; */
2338 if (aentry->serverPartition[i] < 0 || aentry->serverPartition[i] > MAXPARTITIONID)
2339 return VL_BADPARTITION;
2340 if (aentry->serverFlags[i] < 0 || aentry->serverFlags[i] > MAXSERVERFLAG)
2341 return VL_BADSERVERFLAG;
2347 check_nvldbentry(aentry)
2348 struct nvldbentry *aentry;
2352 if (InvalidVolname(aentry->name))
2354 if (aentry->nServers <= 0 || aentry->nServers > NMAXNSERVERS)
2355 return VL_BADSERVER;
2356 for (i=0; i < aentry->nServers; i++) {
2357 /* if (aentry->serverNumber[i] < 0 || aentry->serverNumber[i] > MAXSERVERID)
2358 return VL_BADSERVER; */
2359 if (aentry->serverPartition[i] < 0 || aentry->serverPartition[i] > MAXPARTITIONID)
2360 return VL_BADPARTITION;
2361 if (aentry->serverFlags[i] < 0 || aentry->serverFlags[i] > MAXSERVERFLAG)
2362 return VL_BADSERVERFLAG;
2368 /* Convert from the external vldb entry representation to its internal
2369 (more compact) form. This call should not change the hash chains! */
2371 vldbentry_to_vlentry(atrans, VldbEntry, VlEntry)
2372 struct ubik_trans *atrans;
2373 struct vldbentry *VldbEntry;
2374 struct nvlentry *VlEntry;
2378 if (strcmp(VlEntry->name, VldbEntry->name))
2379 strncpy(VlEntry->name, VldbEntry->name, sizeof(VlEntry->name));
2380 for (i=0; i<VldbEntry->nServers; i++) {
2381 serverindex = IpAddrToRelAddr(VldbEntry->serverNumber[i], atrans);
2382 if (serverindex == -1) return VL_BADSERVER;
2383 VlEntry->serverNumber[i] = serverindex;
2384 VlEntry->serverPartition[i] = VldbEntry->serverPartition[i];
2385 VlEntry->serverFlags[i] = VldbEntry->serverFlags[i];
2387 for (;i < OMAXNSERVERS; i++)
2388 VlEntry->serverNumber[i] = VlEntry->serverPartition[i] = VlEntry->serverFlags[i] = BADSERVERID;
2389 for (i=0; i < MAXTYPES; i++)
2390 VlEntry->volumeId[i] = VldbEntry->volumeId[i];
2391 VlEntry->cloneId = VldbEntry->cloneId;
2392 VlEntry->flags = VldbEntry->flags;
2397 nvldbentry_to_vlentry(atrans, VldbEntry, VlEntry)
2398 struct ubik_trans *atrans;
2399 struct nvldbentry *VldbEntry;
2400 struct nvlentry *VlEntry;
2404 if (strcmp(VlEntry->name, VldbEntry->name))
2405 strncpy(VlEntry->name, VldbEntry->name, sizeof(VlEntry->name));
2406 for (i=0; i<VldbEntry->nServers; i++) {
2407 serverindex = IpAddrToRelAddr(VldbEntry->serverNumber[i], atrans);
2408 if (serverindex == -1) return VL_BADSERVER;
2409 VlEntry->serverNumber[i] = serverindex;
2410 VlEntry->serverPartition[i] = VldbEntry->serverPartition[i];
2411 VlEntry->serverFlags[i] = VldbEntry->serverFlags[i];
2413 for (;i < NMAXNSERVERS; i++)
2414 VlEntry->serverNumber[i] = VlEntry->serverPartition[i] = VlEntry->serverFlags[i] = BADSERVERID;
2415 for (i=0; i < MAXTYPES; i++)
2416 VlEntry->volumeId[i] = VldbEntry->volumeId[i];
2417 VlEntry->cloneId = VldbEntry->cloneId;
2418 VlEntry->flags = VldbEntry->flags;
2423 /* 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. */
2425 get_vldbupdateentry(trans, blockindex, updateentry, VlEntry)
2426 struct ubik_trans *trans;
2427 afs_int32 blockindex;
2428 struct VldbUpdateEntry *updateentry;
2429 struct nvlentry *VlEntry;
2431 int i, j, errorcode, serverindex;
2433 if (updateentry->Mask & VLUPDATE_VOLUMENAME) {
2434 if (InvalidVolname(updateentry->name))
2436 if (errorcode = UnhashVolname(trans, blockindex, VlEntry))
2438 strncpy(VlEntry->name, updateentry->name, sizeof(VlEntry->name));
2439 HashVolname(trans, blockindex, VlEntry);
2442 if (updateentry->Mask & VLUPDATE_VOLNAMEHASH) {
2443 if (errorcode = UnhashVolname(trans, blockindex, VlEntry)) {
2444 if (errorcode != VL_NOENT)
2447 HashVolname(trans, blockindex, VlEntry);
2450 if (updateentry->Mask & VLUPDATE_FLAGS) {
2451 VlEntry->flags = updateentry->flags;
2453 if (updateentry->Mask & VLUPDATE_CLONEID) {
2454 VlEntry->cloneId = updateentry->cloneId;
2456 if (updateentry->Mask & VLUPDATE_RWID) {
2457 if (errorcode = UnhashVolid(trans, RWVOL, blockindex, VlEntry)) {
2458 if (errorcode != VL_NOENT)
2461 VlEntry->volumeId[RWVOL] = updateentry->spares3; /* rw id */
2462 if (errorcode = HashVolid(trans, RWVOL, blockindex, VlEntry))
2465 if (updateentry->Mask & VLUPDATE_READONLYID) {
2466 if (errorcode = UnhashVolid(trans, ROVOL, blockindex, VlEntry)) {
2467 if (errorcode != VL_NOENT)
2470 VlEntry->volumeId[ROVOL] = updateentry->ReadOnlyId;
2471 if (errorcode = HashVolid(trans, ROVOL, blockindex, VlEntry))
2474 if (updateentry->Mask & VLUPDATE_BACKUPID) {
2475 if (errorcode = UnhashVolid(trans, BACKVOL, blockindex, VlEntry)) {
2476 if (errorcode != VL_NOENT)
2479 VlEntry->volumeId[BACKVOL] = updateentry->BackupId;
2480 if (errorcode = HashVolid(trans, BACKVOL, blockindex, VlEntry))
2483 if (updateentry->Mask & VLUPDATE_REPSITES) {
2484 if (updateentry->nModifiedRepsites <= 0 || updateentry->nModifiedRepsites > OMAXNSERVERS)
2485 return VL_BADSERVER;
2486 for (i=0; i < updateentry->nModifiedRepsites; i++) {
2487 /* if (updateentry->RepsitesTargetServer[i] < 0 || updateentry->RepsitesTargetServer[i] > MAXSERVERID)
2488 return VL_BADSERVER; */
2489 if (updateentry->RepsitesTargetPart[i] < 0 || updateentry->RepsitesTargetPart[i] > MAXPARTITIONID)
2490 return VL_BADPARTITION;
2491 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_DELETE) {
2492 if ((j = repsite_exists(VlEntry, IpAddrToRelAddr(updateentry->RepsitesTargetServer[i], trans), updateentry->RepsitesTargetPart[i])) != -1)
2493 repsite_compress(VlEntry, j);
2494 else return VL_NOREPSERVER;
2496 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_ADD) {
2497 /* if (updateentry->RepsitesNewServer[i] < 0 || updateentry->RepsitesNewServer[i] > MAXSERVERID)
2498 return VL_BADSERVER; */
2499 if (updateentry->RepsitesNewPart[i] < 0 || updateentry->RepsitesNewPart[i] > MAXPARTITIONID)
2500 return VL_BADPARTITION;
2501 if (repsite_exists(VlEntry, IpAddrToRelAddr(updateentry->RepsitesNewServer[i], trans), updateentry->RepsitesNewPart[i]) != -1)
2502 return VL_DUPREPSERVER;
2503 for (j=0; VlEntry->serverNumber[j] != BADSERVERID && j < OMAXNSERVERS; j++);
2504 if (j >= OMAXNSERVERS) return VL_REPSFULL;
2505 if ((serverindex = IpAddrToRelAddr(updateentry->RepsitesNewServer[i], trans)) == -1)
2506 return VL_BADSERVER;
2507 VlEntry->serverNumber[j] = serverindex;
2508 VlEntry->serverPartition[j] = updateentry->RepsitesNewPart[i];
2509 if (updateentry->RepsitesNewFlags[i] < 0 || updateentry->RepsitesNewFlags[i] > MAXSERVERFLAG)
2510 return VL_BADSERVERFLAG;
2511 VlEntry->serverFlags[j] = updateentry->RepsitesNewFlags[i];
2513 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODSERV) {
2514 /*n if (updateentry->RepsitesNewServer[i] < 0 || updateentry->RepsitesNewServer[i] > MAXSERVERID)
2515 return VL_BADSERVER; */
2516 if ((j = repsite_exists(VlEntry, IpAddrToRelAddr(updateentry->RepsitesTargetServer[i], trans), updateentry->RepsitesTargetPart[i])) != -1) {
2517 VlEntry->serverNumber[j] = IpAddrToRelAddr(updateentry->RepsitesNewServer[i], trans);
2519 else return VL_NOREPSERVER;
2521 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODPART) {
2522 if (updateentry->RepsitesNewPart[i] < 0 || updateentry->RepsitesNewPart[i] > MAXPARTITIONID)
2523 return VL_BADPARTITION;
2524 if ((j = repsite_exists(VlEntry, IpAddrToRelAddr(updateentry->RepsitesTargetServer[i], trans), updateentry->RepsitesTargetPart[i])) != -1)
2525 VlEntry->serverPartition[j] = updateentry->RepsitesNewPart[i];
2526 else return VL_NOREPSERVER;
2528 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODFLAG) {
2529 if ((j = repsite_exists(VlEntry, IpAddrToRelAddr(updateentry->RepsitesTargetServer[i], trans), updateentry->RepsitesTargetPart[i])) != -1) {
2530 if (updateentry->RepsitesNewFlags[i] < 0 || updateentry->RepsitesNewFlags[i] > MAXSERVERFLAG)
2531 return VL_BADSERVERFLAG;
2532 VlEntry->serverFlags[j] = updateentry->RepsitesNewFlags[i];
2533 } else return VL_NOREPSERVER;
2541 /* 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. */
2543 repsite_exists(VlEntry, server, partition)
2544 struct nvlentry *VlEntry;
2545 int server, partition;
2549 for (i=0; VlEntry->serverNumber[i] != BADSERVERID && i < OMAXNSERVERS; i++) {
2550 if ((VlEntry->serverNumber[i] == server) && (VlEntry->serverPartition[i] == partition))
2558 /* Repsite table compression: used when deleting a repsite entry so that all active repsite entries are on the top of the table. */
2560 repsite_compress(VlEntry, offset)
2561 struct nvlentry *VlEntry;
2564 int repsite_offset = offset;
2565 for (; VlEntry->serverNumber[repsite_offset] != BADSERVERID && repsite_offset < OMAXNSERVERS-1; repsite_offset++) {
2566 VlEntry->serverNumber[repsite_offset] = VlEntry->serverNumber[repsite_offset+1];
2567 VlEntry->serverPartition[repsite_offset] = VlEntry->serverPartition[repsite_offset+1];
2568 VlEntry->serverFlags[repsite_offset] = VlEntry->serverFlags[repsite_offset+1];
2570 VlEntry->serverNumber[repsite_offset] = BADSERVERID;
2574 /* Convert from the internal (compacted) vldb entry to the external representation used by the interface. */
2576 vlentry_to_vldbentry(VlEntry, VldbEntry)
2577 struct nvlentry *VlEntry;
2578 struct vldbentry *VldbEntry;
2582 bzero(VldbEntry, sizeof(struct vldbentry));
2583 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
2584 for (i=0; i < OMAXNSERVERS; i++) {
2585 if (VlEntry->serverNumber[i] == BADSERVERID) break;
2586 if ((HostAddress[j = VlEntry->serverNumber[i]] & 0xff000000) == 0xff000000) {
2587 struct extentaddr *exp;
2590 base = (HostAddress[j] >> 16) & 0xff;
2591 index = HostAddress[j] & 0x0000ffff;
2592 exp = &ex_addr[base][index];
2593 /* For now return the first ip address back */
2594 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2595 if (exp->ex_addrs[j]) {
2596 VldbEntry->serverNumber[i] = ntohl(exp->ex_addrs[j]);
2601 VldbEntry->serverNumber[i] = HostAddress[VlEntry->serverNumber[i]];
2602 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
2603 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
2605 VldbEntry->nServers = i;
2606 for (i=0; i<MAXTYPES; i++)
2607 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
2608 VldbEntry->cloneId = VlEntry->cloneId;
2609 VldbEntry->flags = VlEntry->flags;
2613 /* Convert from the internal (compacted) vldb entry to the external representation used by the interface. */
2614 static vlentry_to_nvldbentry(VlEntry, VldbEntry)
2615 struct nvlentry *VlEntry;
2616 struct nvldbentry *VldbEntry;
2620 bzero(VldbEntry, sizeof(struct vldbentry));
2621 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
2622 for (i=0; i < NMAXNSERVERS; i++) {
2623 if (VlEntry->serverNumber[i] == BADSERVERID) break;
2624 if ((HostAddress[j = VlEntry->serverNumber[i]] & 0xff000000) == 0xff000000) {
2625 struct extentaddr *exp;
2628 base = (HostAddress[j] >> 16) & 0xff;
2629 index = HostAddress[j] & 0x0000ffff;
2630 exp = &ex_addr[base][index];
2631 /* For now return the first ip address back */
2632 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2633 if (exp->ex_addrs[j]) {
2634 VldbEntry->serverNumber[i] = ntohl(exp->ex_addrs[j]);
2639 VldbEntry->serverNumber[i] = HostAddress[VlEntry->serverNumber[i]];
2640 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
2641 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
2643 VldbEntry->nServers = i;
2644 for (i=0; i<MAXTYPES; i++)
2645 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
2646 VldbEntry->cloneId = VlEntry->cloneId;
2647 VldbEntry->flags = VlEntry->flags;
2650 static vlentry_to_uvldbentry(VlEntry, VldbEntry)
2651 struct nvlentry *VlEntry;
2652 struct uvldbentry *VldbEntry;
2656 bzero(VldbEntry, sizeof(struct vldbentry));
2657 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
2658 for (i=0; i < NMAXNSERVERS; i++) {
2659 if (VlEntry->serverNumber[i] == BADSERVERID) break;
2660 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
2661 VldbEntry->serverUnique[i] = 0;
2662 if ((HostAddress[j = VlEntry->serverNumber[i]] & 0xff000000) == 0xff000000) {
2663 struct extentaddr *exp;
2667 base = (HostAddress[j] >> 16) & 0xff;
2668 index = HostAddress[j] & 0x0000ffff;
2669 exp = &ex_addr[base][index];
2670 tuuid = exp->ex_hostuuid;
2671 afs_ntohuuid(&tuuid);
2672 VldbEntry->serverFlags[i] |= VLSERVER_FLAG_UUID;
2673 VldbEntry->serverNumber[i] = tuuid;
2674 VldbEntry->serverUnique[i] = ntohl(exp->ex_uniquifier);
2676 VldbEntry->serverNumber[i].time_low = HostAddress[VlEntry->serverNumber[i]];
2678 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
2681 VldbEntry->nServers = i;
2682 for (i=0; i<MAXTYPES; i++)
2683 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
2684 VldbEntry->cloneId = VlEntry->cloneId;
2685 VldbEntry->flags = VlEntry->flags;
2688 #define LEGALCHARS ".ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
2691 /* Verify that the volname is a valid volume name. */
2693 InvalidVolname(volname)
2700 slen = strlen(volname);
2701 if (slen >= VL_MAXNAMELEN) return 1;
2702 return(slen != strspn(volname, map));
2706 /* Verify that the given volume type is valid. */
2708 InvalidVoltype(voltype)
2711 if (voltype != RWVOL && voltype != ROVOL && voltype != BACKVOL)
2718 InvalidOperation(voloper)
2721 if (voloper != VLOP_MOVE && voloper != VLOP_RELEASE && voloper != VLOP_BACKUP && voloper != VLOP_DELETE && voloper != VLOP_DUMP)
2727 InvalidReleasetype(releasetype)
2728 afs_int32 releasetype;
2730 if ((releasetype & LOCKREL_TIMESTAMP) || (releasetype & LOCKREL_OPCODE) || (releasetype & LOCKREL_AFSID))
2736 IpAddrToRelAddr(ipaddr, atrans)
2737 struct ubik_trans *atrans;
2738 register afs_uint32 ipaddr;
2741 register afs_int32 code, base, index;
2742 struct extentaddr *exp;
2744 for (i = 0; i <= MAXSERVERID; i++) {
2745 if (HostAddress[i] == ipaddr)
2747 if ((HostAddress[i] & 0xff000000) == 0xff000000) {
2748 base = (HostAddress[i] >> 16) & 0xff;
2749 index = HostAddress[i] & 0x0000ffff;
2750 if (base >= VL_MAX_ADDREXTBLKS) {
2751 VLog(0, ("Internal error: Multihome extent base is too large. Base %d index %d\n", base, index));
2752 return -1; /* EINVAL */
2754 if (index >= VL_MHSRV_PERBLK) {
2755 VLog(0, ("Internal error: Multihome extent index is too large. Base %d index %d\n", base, index));
2756 return -1; /* EINVAL */
2758 if (!ex_addr[base]) {
2759 VLog(0, ("Internal error: Multihome extent does not exist. Base %d\n", base));
2760 return -1; /* EINVAL */
2762 exp = &ex_addr[base][index];
2763 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2764 if (exp->ex_addrs[j] && (ntohl(exp->ex_addrs[j]) == ipaddr)) {
2771 /* allocate the new server a server id pronto */
2773 for(i=0;i <= MAXSERVERID;i++) {
2774 if (cheader.IpMappedAddr[i] == 0) {
2775 cheader.IpMappedAddr[i] = htonl(ipaddr);
2776 code = vlwrite(atrans, DOFFSET(0, &cheader, &cheader.IpMappedAddr[i]), (char *) &cheader.IpMappedAddr[i], sizeof(afs_int32));
2777 HostAddress[i] = ipaddr;
2778 if (code) return -1;
2787 ChangeIPAddr(ipaddr1, ipaddr2, atrans)
2788 struct ubik_trans *atrans;
2789 register afs_uint32 ipaddr1, ipaddr2;
2793 struct extentaddr *exp;
2794 int base, index, mhidx;
2796 afs_int32 blockindex, count;
2798 struct nvlentry tentry;
2801 return VL_CREATEFAIL;
2803 /* Don't let addr change to 256.*.*.* : Causes internal error below */
2804 if ((ipaddr2 & 0xff000000) == 0xff000000)
2805 return(VL_BADSERVER);
2807 /* If we are removing an address, ip1 will be -1 and ip2 will be
2808 * the original address. This prevents an older revision vlserver
2809 * from removing the IP address (won't find server 0xfffffff in
2810 * the VLDB). An older revision vlserver does not have the check
2811 * to see if any volumes exist on the server being removed.
2813 if (ipaddr1 == 0xffffffff) {
2818 for (i = 0; i <= MAXSERVERID; i++) {
2819 if ((HostAddress[i] & 0xff000000) == 0xff000000) {
2820 base = (HostAddress[i] >> 16) & 0xff;
2821 index = HostAddress[i] & 0x0000ffff;
2822 if ((base >= VL_MAX_ADDREXTBLKS) || (index >= VL_MHSRV_PERBLK)) {
2823 VLog(0, ("Internal error: Multihome extent addr is too large. Base %d index %d\n",
2825 return -1; /* EINVAL */
2828 exp = &ex_addr[base][index];
2829 for (mhidx=0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2830 if (!exp->ex_addrs[mhidx]) continue;
2831 if (ntohl(exp->ex_addrs[mhidx]) == ipaddr1)
2834 if (mhidx < VL_MAXIPADDRS_PERMH) {
2838 else if (HostAddress[i] == ipaddr1) {
2839 exp = (struct extentaddr *)0;
2844 if (i >= MAXSERVERID) {
2845 return VL_NOENT; /* not found */
2848 /* If we are removing a server entry, a volume cannot
2849 * exist on the server. If one does, don't remove the
2850 * server entry: return error "volume entry exists".
2853 for (blockindex = NextEntry(atrans, 0, &tentry, &count);
2855 blockindex = NextEntry(atrans, blockindex, &tentry, &count)) {
2856 if (++pollcount > 50) {
2860 for (j=0; j<NMAXNSERVERS; j++) {
2861 if (tentry.serverNumber[j] == BADSERVERID) break;
2862 if (tentry.serverNumber[j] == i) {
2869 /* Log a message saying we are changing/removing an IP address */
2870 VLog(0, ("The following IP address is being %s:\n",
2871 (ipaddr2?"changed":"removed")));
2872 printf(" entry %d: ", i);
2875 for (mhidx=0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2876 if (!exp->ex_addrs[mhidx]) continue;
2877 if (mhidx>0) printf(" ");
2878 PADDR(ntohl(exp->ex_addrs[mhidx]));
2890 /* Change the registered uuuid addresses */
2892 bzero(&tuuid, sizeof(afsUUID));
2893 afs_htonuuid(&tuuid);
2894 exp->ex_hostuuid = tuuid;
2895 code = vlwrite(atrans, DOFFSET(ntohl(ex_addr[0]->ex_contaddrs[base]),
2896 (char *)ex_addr[base], (char *)exp),
2897 (char *)&tuuid, sizeof(tuuid));
2902 /* Now change the host address entry */
2903 cheader.IpMappedAddr[i] = htonl(ipaddr2);
2904 code = vlwrite(atrans, DOFFSET(0, &cheader, &cheader.IpMappedAddr[i]), (char *)
2905 &cheader.IpMappedAddr[i], sizeof(afs_int32));
2906 HostAddress[i] = ipaddr2;
2913 /* see if the vlserver is back yet */
2914 VL_ProbeServer(rxcall)
2915 struct rx_call *rxcall; {