2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include <afs/param.h>
16 #include <sys/types.h>
19 #include <afs/afsutil.h>
26 #include <netinet/in.h>
37 #include "afs/audit.h"
41 #ifdef HAVE_POSIX_REGEX /* use POSIX regexp library */
47 extern struct afsconf_dir *vldb_confdir;
48 extern struct ubik_dbase *VL_dbase;
49 struct vlheader cheader; /* kept in network byte order */
50 extern afs_uint32 HostAddress[]; /* host addresses kept in host byte order */
52 struct extentaddr *ex_addr[VL_MAX_ADDREXTBLKS] = { 0, 0, 0, 0 };
53 static char rxinfo_str[128]; /* Need rxinfo string to be non-local */
54 #define ABORT(c) { errorcode = (c); goto abort; }
56 #define END(c) { errorcode = (c); goto end; }
58 #define VLDBALLOCLIMIT 10000
59 #define VLDBALLOCINCR 2048
61 static int put_attributeentry();
62 static int put_nattributeentry();
63 static int RemoveEntry();
64 static ReleaseEntry();
65 static int check_vldbentry();
66 static int check_nvldbentry();
67 static int vldbentry_to_vlentry();
68 static int nvldbentry_to_vlentry();
69 static get_vldbupdateentry();
70 static int repsite_exists();
71 static repsite_compress();
72 static vlentry_to_vldbentry();
73 static vlentry_to_nvldbentry();
74 static vlentry_to_uvldbentry();
75 static int InvalidVolname();
76 static int InvalidVoltype();
77 static int InvalidOperation();
78 static int InvalidReleasetype();
79 static int IpAddrToRelAddr();
80 static int ChangeIPAddr();
84 struct rx_call *rxcall;
87 register struct rx_connection *tconn;
92 struct in_addr hostAddr;
94 tconn = rx_ConnectionOf(rxcall);
95 hostAddr.s_addr = rx_HostOf(rx_PeerOf(tconn));
97 rxkad_GetServerInfo(rxcall->conn, NULL, &exp, tname, tinst, tcell,
100 sprintf(rxinfo_str, "%s %s%s%s%s%s", inet_ntoa(hostAddr), tname,
101 tinst?".":"", tinst?tinst:"", tcell?"@":"", tcell?tcell:"");
103 sprintf(rxinfo_str, "%s noauth", inet_ntoa(hostAddr));
107 /* This is called to initialize the database, set the appropriate locks and make sure that the vldb header is valid */
109 Init_VLdbase(trans, locktype, this_op)
110 struct ubik_trans **trans;
111 int locktype; /* indicate read or write transaction */
114 int errorcode = 0, pass, wl;
116 for (pass = 1; pass <= 3; pass++) {
117 if (pass == 2) { /* take write lock to rebuild the db */
118 errorcode = ubik_BeginTrans(VL_dbase, UBIK_WRITETRANS, trans);
120 } else if (locktype == LOCKREAD) {
122 ubik_BeginTransReadAny(VL_dbase, UBIK_READTRANS, trans);
125 errorcode = ubik_BeginTrans(VL_dbase, UBIK_WRITETRANS, trans);
131 errorcode = ubik_SetLock(*trans, 1, 1, locktype);
134 ubik_AbortTrans(*trans);
138 /* check that dbase is initialized and setup cheader */
139 /* 2nd pass we try to rebuild the header */
140 errorcode = CheckInit(*trans, ((pass == 2) ? 1 : 0));
141 if (!errorcode && wl && extent_mod)
142 errorcode = readExtents(*trans); /* Fix the mh extent blocks */
145 ubik_AbortTrans(*trans);
146 /* Only rebuld if the database is empty */
147 /* Exit if can't rebuild */
148 if ((pass == 1) && (errorcode != VL_EMPTY))
152 } else { /* No errorcode */
154 ubik_EndTrans(*trans); /* Rebuilt db. End trans, then retake original lock */
156 break; /* didn't rebuild and successful - exit */
164 /* Create a new vldb entry; both new volume id and name must be unique (non-existant in vldb). */
167 SVL_CreateEntry(rxcall, newentry)
168 struct rx_call *rxcall;
169 struct vldbentry *newentry;
171 struct ubik_trans *trans;
172 afs_int32 errorcode, blockindex;
173 struct nvlentry tentry;
175 COUNT_REQ(VLCREATEENTRY);
176 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) {
181 /* Do some validity tests on new entry */
182 if ((errorcode = check_vldbentry(newentry))
183 || (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
187 ("OCreate Volume %d %s\n", newentry->volumeId[RWVOL],
189 /* XXX shouldn't we check to see if the r/o volume is duplicated? */
190 if (newentry->volumeId[RWVOL]
191 && FindByID(trans, newentry->volumeId[RWVOL], RWVOL, &tentry, &errorcode)) { /* entry already exists, we fail */
192 errorcode = VL_IDEXIST;
194 } else if (errorcode) {
198 /* Is this following check (by volume name) necessary?? */
199 /* If entry already exists, we fail */
200 if (FindByName(trans, newentry->name, &tentry, &errorcode)) {
201 errorcode = VL_NAMEEXIST;
203 } else if (errorcode) {
207 blockindex = AllocBlock(trans, &tentry);
208 if (blockindex == 0) {
209 errorcode = VL_CREATEFAIL;
213 memset(&tentry, 0, sizeof(struct nvlentry));
214 /* Convert to its internal representation; both in host byte order */
215 if (errorcode = vldbentry_to_vlentry(trans, newentry, &tentry)) {
216 FreeBlock(trans, blockindex);
220 /* Actually insert the entry in vldb */
221 errorcode = ThreadVLentry(trans, blockindex, &tentry);
223 FreeBlock(trans, blockindex);
226 errorcode = ubik_EndTrans(trans);
232 ubik_AbortTrans(trans);
235 osi_auditU(rxcall, VLCreateEntryEvent, errorcode, AUD_STR,
236 (newentry ? newentry->name : NULL), AUD_END);
242 SVL_CreateEntryN(rxcall, newentry)
243 struct rx_call *rxcall;
244 struct nvldbentry *newentry;
246 struct ubik_trans *trans;
247 afs_int32 errorcode, blockindex;
248 struct nvlentry tentry;
250 COUNT_REQ(VLCREATEENTRYN);
251 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) {
256 /* Do some validity tests on new entry */
257 if ((errorcode = check_nvldbentry(newentry))
258 || (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
262 ("Create Volume %d %s\n", newentry->volumeId[RWVOL],
264 /* XXX shouldn't we check to see if the r/o volume is duplicated? */
265 if (newentry->volumeId[RWVOL]
266 && FindByID(trans, newentry->volumeId[RWVOL], RWVOL, &tentry, &errorcode)) { /* entry already exists, we fail */
267 errorcode = VL_IDEXIST;
269 } else if (errorcode) {
273 /* Is this following check (by volume name) necessary?? */
274 /* If entry already exists, we fail */
275 if (FindByName(trans, newentry->name, &tentry, &errorcode)) {
276 errorcode = VL_NAMEEXIST;
278 } else if (errorcode) {
282 blockindex = AllocBlock(trans, &tentry);
283 if (blockindex == 0) {
284 errorcode = VL_CREATEFAIL;
288 memset(&tentry, 0, sizeof(struct nvlentry));
289 /* Convert to its internal representation; both in host byte order */
290 if (errorcode = nvldbentry_to_vlentry(trans, newentry, &tentry)) {
291 FreeBlock(trans, blockindex);
295 /* Actually insert the entry in vldb */
296 errorcode = ThreadVLentry(trans, blockindex, &tentry);
298 FreeBlock(trans, blockindex);
301 errorcode = ubik_EndTrans(trans);
307 ubik_AbortTrans(trans);
310 osi_auditU(rxcall, VLCreateEntryEvent, errorcode, AUD_STR,
311 (newentry ? newentry->name : NULL), AUD_END);
317 SVL_ChangeAddr(rxcall, ip1, ip2)
318 struct rx_call *rxcall;
321 struct ubik_trans *trans;
324 COUNT_REQ(VLCHANGEADDR);
325 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) {
330 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
333 VLog(1, ("Change Addr %d -> %d %s\n", ip1, ip2, rxinfo(rxcall)));
334 if (errorcode = ChangeIPAddr(ip1, ip2, trans))
337 errorcode = ubik_EndTrans(trans);
343 ubik_AbortTrans(trans);
346 osi_auditU(rxcall, VLChangeAddrEvent, errorcode, AUD_LONG, ip1, AUD_LONG,
351 /* Delete a vldb entry given the volume id. */
353 SVL_DeleteEntry(rxcall, volid, voltype)
354 struct rx_call *rxcall;
358 struct ubik_trans *trans;
359 afs_int32 blockindex, errorcode;
360 struct nvlentry tentry;
362 COUNT_REQ(VLDELETEENTRY);
363 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
366 if ((voltype != -1) && (InvalidVoltype(voltype)))
369 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
372 VLog(1, ("Delete Volume %d %s\n", volid, rxinfo(rxcall)));
373 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
374 if (blockindex == 0) { /* volid not found */
376 errorcode = VL_NOENT;
380 if (tentry.flags & VLDELETED) { /* Already deleted; return */
381 ABORT(VL_ENTDELETED);
383 if (errorcode = RemoveEntry(trans, blockindex, &tentry)) {
386 errorcode = (ubik_EndTrans(trans));
391 ubik_AbortTrans(trans);
394 osi_auditU(rxcall, VLDeleteEntryEvent, errorcode, AUD_LONG, volid,
400 /* Get a vldb entry given its volume id; make sure it's not a deleted entry. */
401 GetEntryByID(rxcall, volid, voltype, aentry, new, this_op)
402 struct rx_call *rxcall;
404 afs_int32 voltype, new, this_op;
405 char *aentry; /* entry data copied here */
407 struct ubik_trans *trans;
408 afs_int32 blockindex, errorcode;
409 struct nvlentry tentry;
411 if ((voltype != -1) && (InvalidVoltype(voltype)))
412 return VL_BADVOLTYPE;
413 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
416 VLog(5, ("GetVolumeByID %d (%d) %s\n", volid, new, rxinfo(rxcall)));
417 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
418 if (blockindex == 0) { /* entry not found */
420 errorcode = VL_NOENT;
422 ubik_AbortTrans(trans);
425 if (tentry.flags & VLDELETED) { /* Entry is deleted! */
427 ubik_AbortTrans(trans);
428 return VL_ENTDELETED;
430 /* Convert from the internal to external form */
432 vlentry_to_nvldbentry(&tentry, (struct nvldbentry *)aentry);
434 vlentry_to_uvldbentry(&tentry, (struct uvldbentry *)aentry);
436 vlentry_to_vldbentry(&tentry, (struct vldbentry *)aentry);
437 return (ubik_EndTrans(trans));
441 SVL_GetEntryByID(rxcall, volid, voltype, aentry)
442 struct rx_call *rxcall;
443 afs_int32 volid, voltype;
444 vldbentry *aentry; /* entry data copied here */
446 COUNT_REQ(VLGETENTRYBYID);
447 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 0, this_op));
451 SVL_GetEntryByIDN(rxcall, volid, voltype, aentry)
452 struct rx_call *rxcall;
453 afs_int32 volid, voltype;
454 nvldbentry *aentry; /* entry data copied here */
456 COUNT_REQ(VLGETENTRYBYIDN);
457 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 1, this_op));
461 SVL_GetEntryByIDU(rxcall, volid, voltype, aentry)
462 struct rx_call *rxcall;
463 afs_int32 volid, voltype;
464 uvldbentry *aentry; /* entry data copied here */
466 COUNT_REQ(VLGETENTRYBYIDU);
467 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 2, this_op));
472 /* returns true if the id is a decimal integer, in which case we interpret it
473 as an id. make the cache manager much simpler */
476 register char *aname;
479 while (tc = *aname++) {
480 if (tc > '9' || tc < '0')
486 /* Get a vldb entry given the volume's name; of course, very similar to VLGetEntryByID() above. */
487 GetEntryByName(rxcall, volname, aentry, new, this_op)
488 struct rx_call *rxcall;
490 char *aentry; /* entry data copied here */
493 struct ubik_trans *trans;
494 afs_int32 blockindex, errorcode;
495 struct nvlentry tentry;
497 if (NameIsId(volname)) {
498 return GetEntryByID(rxcall, atoi(volname), -1, aentry, new, this_op);
500 if (InvalidVolname(volname))
502 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
504 VLog(5, ("GetVolumeByName %s (%d) %s\n", volname, new, rxinfo(rxcall)));
505 blockindex = FindByName(trans, volname, &tentry, &errorcode);
506 if (blockindex == 0) { /* entry not found */
508 errorcode = VL_NOENT;
510 ubik_AbortTrans(trans);
513 if (tentry.flags & VLDELETED) { /* Entry is deleted */
515 ubik_AbortTrans(trans);
516 return VL_ENTDELETED;
518 /* Convert to external entry representation */
520 vlentry_to_nvldbentry(&tentry, (struct nvldbentry *)aentry);
522 vlentry_to_uvldbentry(&tentry, (struct uvldbentry *)aentry);
524 vlentry_to_vldbentry(&tentry, (struct vldbentry *)aentry);
525 return (ubik_EndTrans(trans));
529 SVL_GetEntryByNameO(rxcall, volname, aentry)
530 struct rx_call *rxcall;
532 struct vldbentry *aentry; /* entry data copied here */
534 COUNT_REQ(VLGETENTRYBYNAME);
535 return (GetEntryByName(rxcall, volname, (char *)aentry, 0, this_op));
540 SVL_GetEntryByNameN(rxcall, volname, aentry)
541 struct rx_call *rxcall;
543 struct nvldbentry *aentry; /* entry data copied here */
545 COUNT_REQ(VLGETENTRYBYNAMEN);
546 return (GetEntryByName(rxcall, volname, (char *)aentry, 1, this_op));
550 SVL_GetEntryByNameU(rxcall, volname, aentry)
551 struct rx_call *rxcall;
553 struct uvldbentry *aentry; /* entry data copied here */
555 COUNT_REQ(VLGETENTRYBYNAMEU);
556 return (GetEntryByName(rxcall, volname, (char *)aentry, 2, this_op));
561 /* Get the current value of the maximum volume id and bump the volume id counter by Maxvolidbump. */
563 SVL_GetNewVolumeId(rxcall, Maxvolidbump, newvolumeid)
564 struct rx_call *rxcall;
565 afs_int32 Maxvolidbump;
566 afs_int32 *newvolumeid;
568 register afs_int32 errorcode, maxvolumeid;
569 struct ubik_trans *trans;
571 COUNT_REQ(VLGETNEWVOLUMEID);
572 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
575 if (Maxvolidbump < 0 || Maxvolidbump > MAXBUMPCOUNT)
576 END(VL_BADVOLIDBUMP);
578 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
581 *newvolumeid = maxvolumeid = ntohl(cheader.vital_header.MaxVolumeId);
582 maxvolumeid += Maxvolidbump;
583 VLog(1, ("GetNewVolid newmax=%d %s\n", maxvolumeid, rxinfo(rxcall)));
584 cheader.vital_header.MaxVolumeId = htonl(maxvolumeid);
585 if (write_vital_vlheader(trans)) {
588 errorcode = (ubik_EndTrans(trans));
593 ubik_AbortTrans(trans);
596 osi_auditU(rxcall, VLGetNewVolumeIdEvent, errorcode, AUD_END);
601 /* Simple replace the contents of the vldb entry, volid, with
602 * newentry. No individual checking/updating per field (alike
603 * VLUpdateEntry) is done. */
606 SVL_ReplaceEntry(rxcall, volid, voltype, newentry, releasetype)
607 struct rx_call *rxcall;
610 struct vldbentry *newentry;
611 afs_int32 releasetype;
613 struct ubik_trans *trans;
614 afs_int32 blockindex, errorcode, typeindex;
616 int hashVol[MAXTYPES];
617 struct nvlentry tentry;
619 COUNT_REQ(VLREPLACEENTRY);
620 for (typeindex = 0; typeindex < MAXTYPES; typeindex++)
621 hashVol[typeindex] = 0;
623 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
626 if (errorcode = check_vldbentry(newentry))
629 if (voltype != -1 && InvalidVoltype(voltype))
632 if (releasetype && InvalidReleasetype(releasetype))
633 END(VL_BADRELLOCKTYPE);
634 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
637 VLog(1, ("OReplace Volume %d %s\n", volid, rxinfo(rxcall)));
638 /* find vlentry we're changing */
639 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
640 if (blockindex == 0) { /* entry not found */
642 errorcode = VL_NOENT;
646 /* check that we're not trying to change the RW vol ID */
647 if (newentry->volumeId[RWVOL] != tentry.volumeId[RWVOL]) {
651 /* unhash volid entries if they're disappearing or changing.
652 * Remember if we need to hash in the new value (we don't have to
653 * rehash if volid stays same */
654 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
655 if (tentry.volumeId[typeindex] != newentry->volumeId[typeindex]) {
656 if (tentry.volumeId[typeindex])
658 UnhashVolid(trans, typeindex, blockindex, &tentry)) {
661 /* we must rehash new id if the id is different and the ID is nonzero */
662 hashVol[typeindex] = 1; /* must rehash this guy if he exists */
666 /* Rehash volname if it changes */
667 if (strcmp(newentry->name, tentry.name)) { /* Name changes; redo hashing */
668 if (errorcode = UnhashVolname(trans, blockindex, &tentry)) {
674 /* after this, tentry is new entry, not old one. vldbentry_to_vlentry
675 * doesn't touch hash chains */
676 if (errorcode = vldbentry_to_vlentry(trans, newentry, &tentry)) {
680 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
681 if (hashVol[typeindex] && tentry.volumeId[typeindex]) {
682 if (errorcode = HashVolid(trans, typeindex, blockindex, &tentry)) {
689 HashVolname(trans, blockindex, &tentry);
692 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
693 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
697 END(ubik_EndTrans(trans));
701 ubik_AbortTrans(trans);
704 osi_auditU(rxcall, VLReplaceVLEntryEvent, errorcode, AUD_LONG, volid,
710 SVL_ReplaceEntryN(rxcall, volid, voltype, newentry, releasetype)
711 struct rx_call *rxcall;
714 struct nvldbentry *newentry;
715 afs_int32 releasetype;
717 struct ubik_trans *trans;
718 afs_int32 blockindex, errorcode, typeindex;
720 int hashVol[MAXTYPES];
721 struct nvlentry tentry;
723 COUNT_REQ(VLREPLACEENTRYN);
724 for (typeindex = 0; typeindex < MAXTYPES; typeindex++)
725 hashVol[typeindex] = 0;
727 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
730 if (errorcode = check_nvldbentry(newentry))
733 if (voltype != -1 && InvalidVoltype(voltype))
736 if (releasetype && InvalidReleasetype(releasetype))
737 END(VL_BADRELLOCKTYPE);
738 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
741 VLog(1, ("Replace Volume %d %s\n", volid, rxinfo(rxcall)));
742 /* find vlentry we're changing */
743 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
744 if (blockindex == 0) { /* entry not found */
746 errorcode = VL_NOENT;
750 /* check that we're not trying to change the RW vol ID */
751 if (newentry->volumeId[RWVOL] != tentry.volumeId[RWVOL]) {
755 /* unhash volid entries if they're disappearing or changing.
756 * Remember if we need to hash in the new value (we don't have to
757 * rehash if volid stays same */
758 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
759 if (tentry.volumeId[typeindex] != newentry->volumeId[typeindex]) {
760 if (tentry.volumeId[typeindex])
762 UnhashVolid(trans, typeindex, blockindex, &tentry)) {
765 /* we must rehash new id if the id is different and the ID is nonzero */
766 hashVol[typeindex] = 1; /* must rehash this guy if he exists */
770 /* Rehash volname if it changes */
771 if (strcmp(newentry->name, tentry.name)) { /* Name changes; redo hashing */
772 if (errorcode = UnhashVolname(trans, blockindex, &tentry)) {
778 /* after this, tentry is new entry, not old one. vldbentry_to_vlentry
779 * doesn't touch hash chains */
780 if (errorcode = nvldbentry_to_vlentry(trans, newentry, &tentry)) {
784 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
785 if (hashVol[typeindex] && tentry.volumeId[typeindex]) {
786 if (errorcode = HashVolid(trans, typeindex, blockindex, &tentry)) {
793 HashVolname(trans, blockindex, &tentry);
796 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
797 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
801 END(ubik_EndTrans(trans));
805 ubik_AbortTrans(trans);
808 osi_auditU(rxcall, VLReplaceVLEntryEvent, errorcode, AUD_LONG, volid,
814 /* 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. */
815 /* this routine may never have been tested; use replace entry instead unless you're brave */
817 SVL_UpdateEntry(rxcall, volid, voltype, updateentry, releasetype)
818 struct rx_call *rxcall;
821 afs_int32 releasetype;
822 struct VldbUpdateEntry *updateentry; /* Update entry copied here */
824 struct ubik_trans *trans;
825 afs_int32 blockindex, errorcode;
826 struct nvlentry tentry;
828 COUNT_REQ(VLUPDATEENTRY);
829 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
831 if ((voltype != -1) && (InvalidVoltype(voltype)))
833 if (releasetype && InvalidReleasetype(releasetype))
834 END(VL_BADRELLOCKTYPE);
835 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
838 VLog(1, ("Update Volume %d %s\n", volid, rxinfo(rxcall)));
839 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
840 if (blockindex == 0) { /* entry not found */
842 errorcode = VL_NOENT;
846 /* Do the actual updating of the entry, tentry. */
848 get_vldbupdateentry(trans, blockindex, updateentry, &tentry)) {
852 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
853 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
856 END(ubik_EndTrans(trans));
860 ubik_AbortTrans(trans);
863 osi_auditU(rxcall, VLUpdateEntryEvent, errorcode, AUD_LONG, volid,
870 SVL_UpdateEntryByName(rxcall, volname, updateentry, releasetype)
871 struct rx_call *rxcall;
873 afs_int32 releasetype;
874 struct VldbUpdateEntry *updateentry; /* Update entry copied here */
876 struct ubik_trans *trans;
877 afs_int32 blockindex, errorcode;
878 struct nvlentry tentry;
880 COUNT_REQ(VLUPDATEENTRYBYNAME);
881 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
883 if (releasetype && InvalidReleasetype(releasetype))
884 END(VL_BADRELLOCKTYPE);
885 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
888 blockindex = FindByName(trans, volname, &tentry, &errorcode);
889 if (blockindex == 0) { /* entry not found */
891 errorcode = VL_NOENT;
895 /* Do the actual updating of the entry, tentry. */
897 get_vldbupdateentry(trans, blockindex, updateentry, &tentry)) {
901 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
902 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
905 END(ubik_EndTrans(trans));
909 ubik_AbortTrans(trans);
912 osi_auditU(rxcall, VLUpdateEntryEvent, errorcode, AUD_LONG, -1, AUD_END);
917 /* Set a lock to the vldb entry for volid (of type voltype if not -1). */
919 SVL_SetLock(rxcall, volid, voltype, voloper)
920 struct rx_call *rxcall;
925 afs_int32 timestamp, blockindex, errorcode;
926 struct ubik_trans *trans;
927 struct nvlentry tentry;
929 COUNT_REQ(VLSETLOCK);
930 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
932 if ((voltype != -1) && (InvalidVoltype(voltype)))
934 if (InvalidOperation(voloper))
936 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
939 VLog(1, ("SetLock Volume %d %s\n", volid, rxinfo(rxcall)));
940 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
941 if (blockindex == NULLO) {
943 errorcode = VL_NOENT;
946 if (tentry.flags & VLDELETED) {
947 ABORT(VL_ENTDELETED);
949 timestamp = FT_ApproxTime();
951 /* Check if entry is already locked; note that we unlock any entry
952 * locked more than MAXLOCKTIME seconds */
953 if ((tentry.LockTimestamp)
954 && ((timestamp - tentry.LockTimestamp) < MAXLOCKTIME)) {
955 ABORT(VL_ENTRYLOCKED);
958 /* Consider it an unlocked entry: set current timestamp, caller
959 * and active vol operation */
960 tentry.LockTimestamp = timestamp;
961 tentry.LockAfsId = 0; /* Not implemented yet */
962 if (tentry.flags & VLOP_RELEASE) {
965 tentry.flags &= ~VLOP_ALLOPERS; /* Clear any possible older operation bit */
966 tentry.flags |= voloper;
968 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
971 END(ubik_EndTrans(trans));
975 ubik_AbortTrans(trans);
978 osi_auditU(rxcall, VLSetLockEvent, errorcode, AUD_LONG, volid, AUD_END);
983 /* Release an already locked vldb entry. Releasetype determines what
984 * fields (afsid and/or volume operation) will be cleared along with
985 * the lock time stamp. */
988 SVL_ReleaseLock(rxcall, volid, voltype, releasetype)
989 struct rx_call *rxcall;
992 afs_int32 releasetype;
994 afs_int32 blockindex, errorcode;
995 struct ubik_trans *trans;
996 struct nvlentry tentry;
998 COUNT_REQ(VLRELEASELOCK);
999 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
1001 if ((voltype != -1) && (InvalidVoltype(voltype)))
1003 if (releasetype && InvalidReleasetype(releasetype))
1004 END(VL_BADRELLOCKTYPE);
1005 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
1008 VLog(1, ("ReleaseLock Volume %d %s\n", volid, rxinfo(rxcall)));
1009 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
1010 if (blockindex == NULLO) {
1012 errorcode = VL_NOENT;
1015 if (tentry.flags & VLDELETED) {
1016 ABORT(VL_ENTDELETED);
1019 ReleaseEntry(&tentry, releasetype); /* Unlock the appropriate fields */
1020 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
1023 END(ubik_EndTrans(trans));
1027 ubik_AbortTrans(trans);
1030 osi_auditU(rxcall, VLReleaseLockEvent, errorcode, AUD_LONG, volid,
1036 /* 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. */
1038 SVL_ListEntry(rxcall, previous_index, count, next_index, aentry)
1039 struct rx_call *rxcall;
1040 afs_int32 previous_index;
1042 afs_int32 *next_index;
1043 struct vldbentry *aentry;
1046 struct ubik_trans *trans;
1047 struct nvlentry tentry;
1049 COUNT_REQ(VLLISTENTRY);
1050 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1052 VLog(25, ("OListEntry index=%d %s\n", previous_index, rxinfo(rxcall)));
1053 *next_index = NextEntry(trans, previous_index, &tentry, count);
1055 vlentry_to_vldbentry(&tentry, aentry);
1056 return (ubik_EndTrans(trans));
1059 /* 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. */
1061 SVL_ListEntryN(rxcall, previous_index, count, next_index, aentry)
1062 struct rx_call *rxcall;
1063 afs_int32 previous_index;
1065 afs_int32 *next_index;
1066 struct nvldbentry *aentry;
1069 struct ubik_trans *trans;
1070 struct nvlentry tentry;
1072 COUNT_REQ(VLLISTENTRYN);
1073 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1075 VLog(25, ("ListEntry index=%d %s\n", previous_index, rxinfo(rxcall)));
1076 *next_index = NextEntry(trans, previous_index, &tentry, count);
1078 vlentry_to_nvldbentry(&tentry, aentry);
1079 return (ubik_EndTrans(trans));
1083 /* 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. */
1085 SVL_ListAttributes(rxcall, attributes, nentries, vldbentries)
1086 struct rx_call *rxcall;
1087 struct VldbListByAttributes *attributes;
1088 afs_int32 *nentries;
1089 bulkentries *vldbentries;
1091 int errorcode, allocCount = 0;
1092 struct ubik_trans *trans;
1093 struct nvlentry tentry;
1094 struct vldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1097 COUNT_REQ(VLLISTATTRIBUTES);
1098 vldbentries->bulkentries_val = 0;
1099 vldbentries->bulkentries_len = *nentries = 0;
1100 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1102 allocCount = VLDBALLOCCOUNT;
1103 Vldbentry = VldbentryFirst = vldbentries->bulkentries_val =
1104 (vldbentry *) malloc(allocCount * sizeof(vldbentry));
1105 if (Vldbentry == NULL) {
1107 ubik_AbortTrans(trans);
1110 VldbentryLast = VldbentryFirst + allocCount;
1111 /* Handle the attribute by volume id totally separate of the rest (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!) */
1112 if (attributes->Mask & VLLIST_VOLUMEID) {
1113 afs_int32 blockindex;
1116 FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1117 if (blockindex == 0) {
1119 errorcode = VL_NOENT;
1121 ubik_AbortTrans(trans);
1122 if (vldbentries->bulkentries_val)
1123 free((char *)vldbentries->bulkentries_val);
1124 vldbentries->bulkentries_val = 0;
1125 vldbentries->bulkentries_len = 0;
1129 put_attributeentry(&Vldbentry, &VldbentryFirst, &VldbentryLast,
1130 vldbentries, &tentry, nentries, &allocCount)) {
1132 ubik_AbortTrans(trans);
1133 if (vldbentries->bulkentries_val)
1134 free((char *)vldbentries->bulkentries_val);
1135 vldbentries->bulkentries_val = 0;
1136 vldbentries->bulkentries_len = 0;
1137 return VL_SIZEEXCEEDED;
1140 afs_int32 nextblockindex = 0, count = 0, k, match = 0;
1141 while (nextblockindex =
1142 NextEntry(trans, nextblockindex, &tentry, &count)) {
1143 if (++pollcount > 50) {
1148 if (attributes->Mask & VLLIST_SERVER) {
1151 IpAddrToRelAddr(attributes->server,
1152 (struct ubik_trans *)0)) == -1)
1154 for (k = 0; k < OMAXNSERVERS; k++) {
1155 if (tentry.serverNumber[k] == BADSERVERID)
1157 if (tentry.serverNumber[k] == serverindex) {
1165 if (attributes->Mask & VLLIST_PARTITION) {
1167 if (tentry.serverPartition[k] != attributes->partition)
1170 for (k = 0; k < OMAXNSERVERS; k++) {
1171 if (tentry.serverNumber[k] == BADSERVERID)
1173 if (tentry.serverPartition[k] ==
1174 attributes->partition) {
1184 if (attributes->Mask & VLLIST_FLAG) {
1185 if (!(tentry.flags & attributes->flag))
1189 put_attributeentry(&Vldbentry, &VldbentryFirst,
1190 &VldbentryLast, vldbentries, &tentry,
1191 nentries, &allocCount)) {
1193 ubik_AbortTrans(trans);
1194 if (vldbentries->bulkentries_val)
1195 free((char *)vldbentries->bulkentries_val);
1196 vldbentries->bulkentries_val = 0;
1197 vldbentries->bulkentries_len = 0;
1202 if (vldbentries->bulkentries_len
1203 && (allocCount > vldbentries->bulkentries_len)) {
1205 vldbentries->bulkentries_val =
1206 (vldbentry *) realloc(vldbentries->bulkentries_val,
1207 vldbentries->bulkentries_len *
1209 if (vldbentries->bulkentries_val == NULL) {
1211 ubik_AbortTrans(trans);
1216 ("ListAttrs nentries=%d %s\n", vldbentries->bulkentries_len,
1218 return (ubik_EndTrans(trans));
1222 SVL_ListAttributesN(rxcall, attributes, nentries, vldbentries)
1223 struct rx_call *rxcall;
1224 struct VldbListByAttributes *attributes;
1225 afs_int32 *nentries;
1226 nbulkentries *vldbentries;
1228 int errorcode, allocCount = 0;
1229 struct ubik_trans *trans;
1230 struct nvlentry tentry;
1231 struct nvldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1234 COUNT_REQ(VLLISTATTRIBUTESN);
1235 vldbentries->nbulkentries_val = 0;
1236 vldbentries->nbulkentries_len = *nentries = 0;
1237 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1239 allocCount = VLDBALLOCCOUNT;
1240 Vldbentry = VldbentryFirst = vldbentries->nbulkentries_val =
1241 (nvldbentry *) malloc(allocCount * sizeof(nvldbentry));
1242 if (Vldbentry == NULL) {
1244 ubik_AbortTrans(trans);
1247 VldbentryLast = VldbentryFirst + allocCount;
1248 /* Handle the attribute by volume id totally separate of the rest (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!) */
1249 if (attributes->Mask & VLLIST_VOLUMEID) {
1250 afs_int32 blockindex;
1253 FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1254 if (blockindex == 0) {
1256 errorcode = VL_NOENT;
1258 ubik_AbortTrans(trans);
1259 if (vldbentries->nbulkentries_val)
1260 free((char *)vldbentries->nbulkentries_val);
1261 vldbentries->nbulkentries_val = 0;
1262 vldbentries->nbulkentries_len = 0;
1266 put_nattributeentry(&Vldbentry, &VldbentryFirst, &VldbentryLast,
1267 vldbentries, &tentry, 0, 0, nentries,
1270 ubik_AbortTrans(trans);
1271 if (vldbentries->nbulkentries_val)
1272 free((char *)vldbentries->nbulkentries_val);
1273 vldbentries->nbulkentries_val = 0;
1274 vldbentries->nbulkentries_len = 0;
1275 return VL_SIZEEXCEEDED;
1278 afs_int32 nextblockindex = 0, count = 0, k, match = 0;
1279 while (nextblockindex =
1280 NextEntry(trans, nextblockindex, &tentry, &count)) {
1281 if (++pollcount > 50) {
1287 if (attributes->Mask & VLLIST_SERVER) {
1290 IpAddrToRelAddr(attributes->server,
1291 (struct ubik_trans *)0)) == -1)
1293 for (k = 0; k < NMAXNSERVERS; k++) {
1294 if (tentry.serverNumber[k] == BADSERVERID)
1296 if (tentry.serverNumber[k] == serverindex) {
1304 if (attributes->Mask & VLLIST_PARTITION) {
1306 if (tentry.serverPartition[k] != attributes->partition)
1309 for (k = 0; k < NMAXNSERVERS; k++) {
1310 if (tentry.serverNumber[k] == BADSERVERID)
1312 if (tentry.serverPartition[k] ==
1313 attributes->partition) {
1323 if (attributes->Mask & VLLIST_FLAG) {
1324 if (!(tentry.flags & attributes->flag))
1328 put_nattributeentry(&Vldbentry, &VldbentryFirst,
1329 &VldbentryLast, vldbentries, &tentry, 0,
1330 0, nentries, &allocCount)) {
1332 ubik_AbortTrans(trans);
1333 if (vldbentries->nbulkentries_val)
1334 free((char *)vldbentries->nbulkentries_val);
1335 vldbentries->nbulkentries_val = 0;
1336 vldbentries->nbulkentries_len = 0;
1341 if (vldbentries->nbulkentries_len
1342 && (allocCount > vldbentries->nbulkentries_len)) {
1344 vldbentries->nbulkentries_val =
1345 (nvldbentry *) realloc(vldbentries->nbulkentries_val,
1346 vldbentries->nbulkentries_len *
1347 sizeof(nvldbentry));
1348 if (vldbentries->nbulkentries_val == NULL) {
1350 ubik_AbortTrans(trans);
1355 ("NListAttrs nentries=%d %s\n", vldbentries->nbulkentries_len,
1357 return (ubik_EndTrans(trans));
1362 SVL_ListAttributesN2(rxcall, attributes, name, startindex, nentries,
1363 vldbentries, nextstartindex)
1364 struct rx_call *rxcall;
1365 struct VldbListByAttributes *attributes;
1366 char *name; /* Wildcarded volume name */
1367 afs_int32 startindex;
1368 afs_int32 *nentries;
1369 nbulkentries *vldbentries;
1370 afs_int32 *nextstartindex;
1372 int errorcode = 0, maxCount = VLDBALLOCCOUNT;
1373 struct ubik_trans *trans;
1374 struct nvlentry tentry;
1375 struct nvldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1376 afs_int32 blockindex = 0, count = 0, k, match, matchindex;
1377 int serverindex = -1; /* no server found */
1378 int findserver = 0, findpartition = 0, findflag = 0, findname = 0;
1381 int namematchRWBK, namematchRO, thismatch, matchtype;
1382 char volumename[VL_MAXNAMELEN];
1383 #ifdef HAVE_POSIX_REGEX
1385 int need_regfree = 0;
1388 COUNT_REQ(VLLISTATTRIBUTESN2);
1389 vldbentries->nbulkentries_val = 0;
1390 vldbentries->nbulkentries_len = 0;
1392 *nextstartindex = -1;
1394 errorcode = Init_VLdbase(&trans, LOCKREAD, this_op);
1398 Vldbentry = VldbentryFirst = vldbentries->nbulkentries_val =
1399 (nvldbentry *) malloc(maxCount * sizeof(nvldbentry));
1400 if (Vldbentry == NULL) {
1402 ubik_AbortTrans(trans);
1406 VldbentryLast = VldbentryFirst + maxCount;
1408 /* Handle the attribute by volume id totally separate of the rest
1409 * (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!)
1411 if (attributes->Mask & VLLIST_VOLUMEID) {
1413 FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1414 if (blockindex == 0) {
1416 errorcode = VL_NOENT;
1419 put_nattributeentry(&Vldbentry, &VldbentryFirst,
1420 &VldbentryLast, vldbentries, &tentry, 0,
1421 0, nentries, &maxCount);
1427 /* Search each entry in the database and return all entries
1428 * that match the request. It checks volumename (with
1429 * wildcarding), entry flags, server, and partition.
1432 /* Get the server index for matching server address */
1433 if (attributes->Mask & VLLIST_SERVER) {
1435 IpAddrToRelAddr(attributes->server, (struct ubik_trans *)0);
1436 if (serverindex == -1)
1440 findpartition = ((attributes->Mask & VLLIST_PARTITION) ? 1 : 0);
1441 findflag = ((attributes->Mask & VLLIST_FLAG) ? 1 : 0);
1442 if (name && (strcmp(name, ".*") != 0) && (strcmp(name, "") != 0)) {
1443 sprintf(volumename, "^%s$", name);
1444 #ifdef HAVE_POSIX_REGEX
1445 if (regcomp(&re, volumename, REG_NOSUB) != 0) {
1446 errorcode = VL_BADNAME;
1451 t = (char *)re_comp(volumename);
1453 errorcode = VL_BADNAME;
1460 /* Read each entry and see if it is the one we want */
1461 blockindex = startindex;
1462 while (blockindex = NextEntry(trans, blockindex, &tentry, &count)) {
1463 if (++pollcount > 50) {
1468 /* Step through each server index searching for a match.
1469 * Match to an existing RW, BK, or RO volume name (preference
1470 * is in this order). Remember which index we matched against.
1472 namematchRWBK = namematchRO = 0; /* 0->notTried; 1->match; 2->noMatch */
1476 && (tentry.serverNumber[k] != BADSERVERID)); k++) {
1477 thismatch = 0; /* does this index match */
1479 /* Match against the RW or BK volume name. Remember
1480 * results in namematchRWBK. Prefer RW over BK.
1482 if (tentry.serverFlags[k] & VLSF_RWVOL) {
1483 /* Does the name match the RW name */
1484 if (tentry.flags & VLF_RWEXISTS) {
1486 sprintf(volumename, "%s", tentry.name);
1487 #ifdef HAVE_POSIX_REGEX
1488 if (regexec(&re, volumename, 0, NULL, 0) == 0) {
1489 thismatch = VLSF_RWVOL;
1492 if (re_exec(volumename)) {
1493 thismatch = VLSF_RWVOL;
1497 thismatch = VLSF_RWVOL;
1501 /* Does the name match the BK name */
1502 if (!thismatch && (tentry.flags & VLF_BACKEXISTS)) {
1504 sprintf(volumename, "%s.backup", tentry.name);
1505 #ifdef HAVE_POSIX_REGEX
1506 if (regexec(&re, volumename, 0, NULL, 0) == 0) {
1507 thismatch = VLSF_BACKVOL;
1510 if (re_exec(volumename)) {
1511 thismatch = VLSF_BACKVOL;
1515 thismatch = VLSF_BACKVOL;
1519 namematchRWBK = (thismatch ? 1 : 2);
1522 /* Match with the RO volume name. Compare once and
1523 * remember results in namematchRO. Note that this will
1524 * pick up entries marked NEWREPSITEs and DONTUSE.
1527 if (tentry.flags & VLF_ROEXISTS) {
1531 ((namematchRO == 1) ? VLSF_ROVOL : 0);
1533 sprintf(volumename, "%s.readonly",
1535 #ifdef HAVE_POSIX_REGEX
1536 if (regexec(&re, volumename, 0, NULL, 0) == 0) {
1537 thismatch = VLSF_ROVOL;
1540 if (re_exec(volumename))
1541 thismatch = VLSF_ROVOL;
1545 thismatch = VLSF_ROVOL;
1548 namematchRO = (thismatch ? 1 : 2);
1551 /* Is there a server match */
1552 if (thismatch && findserver
1553 && (tentry.serverNumber[k] != serverindex))
1556 /* Is there a partition match */
1557 if (thismatch && findpartition
1558 && (tentry.serverPartition[k] != attributes->partition))
1561 /* Is there a flag match */
1562 if (thismatch && findflag
1563 && !(tentry.flags & attributes->flag))
1566 /* We found a match. Remember the index, and type */
1570 matchtype = thismatch;
1573 /* Since we prefer RW and BK volume matches over RO matches,
1574 * if we have already checked the RWBK name, then we already
1575 * found the best match and so end the search.
1577 * If we tried matching against the RW, BK, and RO volume names
1578 * and both failed, then we end the search (none will match).
1580 if ((match && namematchRWBK)
1581 || ((namematchRWBK == 2) && (namematchRO == 2)))
1585 /* Passed all the tests. Take it */
1588 put_nattributeentry(&Vldbentry, &VldbentryFirst,
1589 &VldbentryLast, vldbentries, &tentry,
1590 matchtype, matchindex, nentries,
1595 if (*nentries >= maxCount)
1596 break; /* collected the max */
1599 *nextstartindex = (blockindex ? blockindex : -1);
1603 #ifdef HAVE_POSIX_REGEX
1610 ubik_AbortTrans(trans);
1611 if (vldbentries->nbulkentries_val)
1612 free((char *)vldbentries->nbulkentries_val);
1613 vldbentries->nbulkentries_val = 0;
1614 vldbentries->nbulkentries_len = 0;
1615 *nextstartindex = -1;
1619 ("N2ListAttrs nentries=%d %s\n", vldbentries->nbulkentries_len,
1621 return (ubik_EndTrans(trans));
1626 /* Retrieves in vldbentries all vldb entries that match the specified
1627 * attributes (by server number, partition, volume type, and flag); if
1628 * volume id is specified then the associated list for that entry is
1629 * returned. CAUTION: This could be a very expensive call since in most
1630 * cases sequential search of all vldb entries is performed.
1633 SVL_LinkedList(rxcall, attributes, nentries, vldbentries)
1634 struct rx_call *rxcall;
1635 struct VldbListByAttributes *attributes;
1636 afs_int32 *nentries;
1637 vldb_list *vldbentries;
1640 struct ubik_trans *trans;
1641 struct nvlentry tentry;
1642 vldblist vllist, *vllistptr;
1643 afs_int32 blockindex, count, k, match;
1647 COUNT_REQ(VLLINKEDLIST);
1648 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1652 vldbentries->node = NULL;
1653 vllistptr = &vldbentries->node;
1655 /* List by volumeid */
1656 if (attributes->Mask & VLLIST_VOLUMEID) {
1658 FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1661 ubik_AbortTrans(trans);
1662 return (errorcode ? errorcode : VL_NOENT);
1665 vllist = (single_vldbentry *) malloc(sizeof(single_vldbentry));
1666 if (vllist == NULL) {
1668 ubik_AbortTrans(trans);
1671 vlentry_to_vldbentry(&tentry, &vllist->VldbEntry);
1672 vllist->next_vldb = NULL;
1674 *vllistptr = vllist; /* Thread onto list */
1675 vllistptr = &vllist->next_vldb;
1679 /* Search by server, partition, and flags */
1681 for (blockindex = NextEntry(trans, 0, &tentry, &count); blockindex;
1682 blockindex = NextEntry(trans, blockindex, &tentry, &count)) {
1685 if (++pollcount > 50) {
1690 /* Does this volume exist on the desired server */
1691 if (attributes->Mask & VLLIST_SERVER) {
1693 IpAddrToRelAddr(attributes->server,
1694 (struct ubik_trans *)0);
1695 if (serverindex == -1)
1697 for (k = 0; k < OMAXNSERVERS; k++) {
1698 if (tentry.serverNumber[k] == BADSERVERID)
1700 if (tentry.serverNumber[k] == serverindex) {
1709 /* Does this volume exist on the desired partition */
1710 if (attributes->Mask & VLLIST_PARTITION) {
1712 if (tentry.serverPartition[k] != attributes->partition)
1715 for (k = 0; k < OMAXNSERVERS; k++) {
1716 if (tentry.serverNumber[k] == BADSERVERID)
1718 if (tentry.serverPartition[k] ==
1719 attributes->partition) {
1729 /* Does this volume have the desired flags */
1730 if (attributes->Mask & VLLIST_FLAG) {
1731 if (!(tentry.flags & attributes->flag))
1735 vllist = (single_vldbentry *) malloc(sizeof(single_vldbentry));
1736 if (vllist == NULL) {
1738 ubik_AbortTrans(trans);
1741 vlentry_to_vldbentry(&tentry, &vllist->VldbEntry);
1742 vllist->next_vldb = NULL;
1744 *vllistptr = vllist; /* Thread onto list */
1745 vllistptr = &vllist->next_vldb;
1747 if (smallMem && (*nentries >= VLDBALLOCCOUNT)) {
1749 ubik_AbortTrans(trans);
1750 return VL_SIZEEXCEEDED;
1755 return (ubik_EndTrans(trans));
1759 SVL_LinkedListN(rxcall, attributes, nentries, vldbentries)
1760 struct rx_call *rxcall;
1761 struct VldbListByAttributes *attributes;
1762 afs_int32 *nentries;
1763 nvldb_list *vldbentries;
1766 struct ubik_trans *trans;
1767 struct nvlentry tentry;
1768 nvldblist vllist, *vllistptr;
1769 afs_int32 blockindex, count, k, match;
1773 COUNT_REQ(VLLINKEDLISTN);
1774 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1778 vldbentries->node = NULL;
1779 vllistptr = &vldbentries->node;
1781 /* List by volumeid */
1782 if (attributes->Mask & VLLIST_VOLUMEID) {
1784 FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1787 ubik_AbortTrans(trans);
1788 return (errorcode ? errorcode : VL_NOENT);
1791 vllist = (single_nvldbentry *) malloc(sizeof(single_nvldbentry));
1792 if (vllist == NULL) {
1794 ubik_AbortTrans(trans);
1797 vlentry_to_nvldbentry(&tentry, &vllist->VldbEntry);
1798 vllist->next_vldb = NULL;
1800 *vllistptr = vllist; /* Thread onto list */
1801 vllistptr = &vllist->next_vldb;
1805 /* Search by server, partition, and flags */
1807 for (blockindex = NextEntry(trans, 0, &tentry, &count); blockindex;
1808 blockindex = NextEntry(trans, blockindex, &tentry, &count)) {
1811 if (++pollcount > 50) {
1816 /* Does this volume exist on the desired server */
1817 if (attributes->Mask & VLLIST_SERVER) {
1819 IpAddrToRelAddr(attributes->server,
1820 (struct ubik_trans *)0);
1821 if (serverindex == -1)
1823 for (k = 0; k < NMAXNSERVERS; k++) {
1824 if (tentry.serverNumber[k] == BADSERVERID)
1826 if (tentry.serverNumber[k] == serverindex) {
1835 /* Does this volume exist on the desired partition */
1836 if (attributes->Mask & VLLIST_PARTITION) {
1838 if (tentry.serverPartition[k] != attributes->partition)
1841 for (k = 0; k < NMAXNSERVERS; k++) {
1842 if (tentry.serverNumber[k] == BADSERVERID)
1844 if (tentry.serverPartition[k] ==
1845 attributes->partition) {
1855 /* Does this volume have the desired flags */
1856 if (attributes->Mask & VLLIST_FLAG) {
1857 if (!(tentry.flags & attributes->flag))
1861 vllist = (single_nvldbentry *) malloc(sizeof(single_nvldbentry));
1862 if (vllist == NULL) {
1864 ubik_AbortTrans(trans);
1867 vlentry_to_nvldbentry(&tentry, &vllist->VldbEntry);
1868 vllist->next_vldb = NULL;
1870 *vllistptr = vllist; /* Thread onto list */
1871 vllistptr = &vllist->next_vldb;
1873 if (smallMem && (*nentries >= VLDBALLOCCOUNT)) {
1875 ubik_AbortTrans(trans);
1876 return VL_SIZEEXCEEDED;
1881 return (ubik_EndTrans(trans));
1884 /* Get back vldb header statistics (allocs, frees, maxvolumeid, totalentries, etc) and dynamic statistics (number of requests and/or aborts per remote procedure call, etc) */
1886 SVL_GetStats(rxcall, stats, vital_header)
1887 struct rx_call *rxcall;
1889 vital_vlheader *vital_header;
1891 register afs_int32 errorcode;
1892 struct ubik_trans *trans;
1894 COUNT_REQ(VLGETSTATS);
1896 /* Allow users to get statistics freely */
1897 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) /* Must be in 'UserList' to use */
1900 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1902 VLog(5, ("GetStats %s\n", rxinfo(rxcall)));
1903 memcpy((char *)vital_header, (char *)&cheader.vital_header,
1904 sizeof(vital_vlheader));
1905 memcpy((char *)stats, (char *)&dynamic_statistics, sizeof(vldstats));
1906 return (ubik_EndTrans(trans));
1909 /* Get the list of file server addresses from the VLDB. Currently it's pretty
1910 * easy to do. In the future, it might require a little bit of grunging
1911 * through the VLDB, but that's life.
1914 SVL_GetAddrs(rxcall, Handle, spare2, spare3, nentries, addrsp)
1915 struct rx_call *rxcall;
1916 afs_int32 Handle, spare2;
1917 struct VLCallBack *spare3;
1918 afs_int32 *nentries;
1921 register afs_int32 errorcode;
1922 struct ubik_trans *trans;
1926 COUNT_REQ(VLGETADDRS);
1927 addrsp->bulkaddrs_len = *nentries = 0;
1928 addrsp->bulkaddrs_val = 0;
1929 memset(spare3, 0, sizeof(struct VLCallBack));
1931 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1934 VLog(5, ("GetAddrs\n"));
1935 addrsp->bulkaddrs_val = taddrp =
1936 (afs_uint32 *) malloc(sizeof(afs_int32) * (MAXSERVERID + 1));
1937 nservers = *nentries = addrsp->bulkaddrs_len = 0;
1941 ubik_AbortTrans(trans);
1945 for (i = 0; i <= MAXSERVERID; i++) {
1946 if (*taddrp = ntohl(cheader.IpMappedAddr[i])) {
1952 addrsp->bulkaddrs_len = *nentries = nservers;
1953 return (ubik_EndTrans(trans));
1956 #define PADDR(addr) VLog(0,("%d.%d.%d.%d", (addr>>24)&0xff, (addr>>16)&0xff, (addr>>8) &0xff, addr&0xff));
1959 SVL_RegisterAddrs(rxcall, uuidp, spare1, addrsp)
1960 struct rx_call *rxcall;
1966 struct ubik_trans *trans;
1967 int cnt, h, i, j, k, m, base, index;
1968 struct extentaddr *exp = 0, *tex;
1970 afs_uint32 addrs[VL_MAXIPADDRS_PERMH];
1972 int count, willChangeEntry, foundUuidEntry, willReplaceCnt;
1973 int WillReplaceEntry, WillChange[MAXSERVERID + 1], FoundUuid,
1977 COUNT_REQ(VLREGADDR);
1978 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
1980 if (code = Init_VLdbase(&trans, LOCKWRITE, this_op))
1983 /* Eliminate duplicates from IP address list */
1984 for (k = 0, cnt = 0; k < addrsp->bulkaddrs_len; k++) {
1985 if (addrsp->bulkaddrs_val[k] == 0)
1987 for (m = 0; m < cnt; m++) {
1988 if (addrs[m] == addrsp->bulkaddrs_val[k])
1992 if (m == VL_MAXIPADDRS_PERMH) {
1994 ("Number of addresses exceeds %d. Cannot register IP addr 0x%x in VLDB\n",
1995 VL_MAXIPADDRS_PERMH, addrsp->bulkaddrs_val[k]));
1997 addrs[m] = addrsp->bulkaddrs_val[k];
2003 ubik_AbortTrans(trans);
2004 return VL_INDEXERANGE;
2010 /* For each server registered within the VLDB */
2011 for (srvidx = 0; srvidx <= MAXSERVERID; srvidx++) {
2012 willChangeEntry = 0;
2013 WillReplaceEntry = 1;
2014 if ((HostAddress[srvidx] & 0xff000000) == 0xff000000) {
2015 /* The server is registered as a multihomed */
2016 base = (HostAddress[srvidx] >> 16) & 0xff;
2017 index = HostAddress[srvidx] & 0x0000ffff;
2018 if (base >= VL_MAX_ADDREXTBLKS) {
2020 ("Internal error: Multihome extent base is too large. Base %d index %d\n",
2024 if (index >= VL_MHSRV_PERBLK) {
2026 ("Internal error: Multihome extent index is too large. Base %d index %d\n",
2030 if (!ex_addr[base]) {
2032 ("Internal error: Multihome extent does not exist. Base %d\n",
2037 /* See if the addresses to register will change this server entry */
2038 exp = &ex_addr[base][index];
2039 tuuid = exp->ex_hostuuid;
2040 afs_ntohuuid(&tuuid);
2041 if (afs_uuid_equal(uuidp, &tuuid)) {
2045 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2046 if (!exp->ex_addrs[mhidx])
2048 for (k = 0; k < cnt; k++) {
2049 if (ntohl(exp->ex_addrs[mhidx]) == addrs[k]) {
2050 willChangeEntry = 1;
2051 WillChange[count] = srvidx;
2056 WillReplaceEntry = 0;
2060 /* The server is not registered as a multihomed.
2061 * See if the addresses to register will replace this server entry.
2063 for (k = 0; k < cnt; k++) {
2064 if (HostAddress[srvidx] == addrs[k]) {
2065 willChangeEntry = 1;
2066 WillChange[count] = srvidx;
2067 WillReplaceEntry = 1;
2072 if (willChangeEntry) {
2073 if (WillReplaceEntry) {
2075 ReplaceEntry = srvidx;
2081 /* If we found the uuid in the VLDB and if we are replacing another
2082 * entire entry, then complain and fail. Also, if we did not find
2083 * the uuid in the VLDB and the IP addresses being registered was
2084 * found in more than one other entry, then we don't know which one
2085 * to replace and will complain and fail.
2087 if ((foundUuidEntry && (willReplaceCnt > 0))
2088 || (!foundUuidEntry && (count > 1))) {
2090 ("The following fileserver is being registered in the VLDB:\n"));
2092 for (k = 0; k < cnt; k++) {
2099 if (foundUuidEntry) {
2101 (" It would have replaced the existing VLDB server entry:\n"));
2102 VLog(0, (" entry %d: [", FoundUuid));
2103 base = (HostAddress[FoundUuid] >> 16) & 0xff;
2104 index = HostAddress[FoundUuid] & 0x0000ffff;
2105 exp = &ex_addr[base][index];
2106 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2107 if (!exp->ex_addrs[mhidx])
2111 PADDR(ntohl(exp->ex_addrs[mhidx]));
2117 VLog(0, (" Yet another VLDB server entry exists:\n"));
2119 VLog(0, (" Yet other VLDB server entries exist:\n"));
2120 for (j = 0; j < count; j++) {
2121 srvidx = WillChange[j];
2122 VLog(0, (" entry %d: ", srvidx));
2123 if ((HostAddress[srvidx] & 0xff000000) == 0xff000000) {
2125 base = (HostAddress[srvidx] >> 16) & 0xff;
2126 index = HostAddress[srvidx] & 0x0000ffff;
2127 exp = &ex_addr[base][index];
2128 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2129 if (!exp->ex_addrs[mhidx])
2133 PADDR(ntohl(exp->ex_addrs[mhidx]));
2137 PADDR(HostAddress[srvidx]);
2143 VLog(0, (" You must 'vos changeaddr' this other server entry\n"));
2146 (" You must 'vos changeaddr' these other server entries\n"));
2149 (" and/or remove the sysid file from the registering fileserver\n"));
2150 VLog(0, (" before the fileserver can be registered in the VLDB.\n"));
2152 ubik_AbortTrans(trans);
2153 return VL_MULTIPADDR;
2156 /* Passed the checks. Now find and update the existing mh entry, or create
2159 if (foundUuidEntry) {
2160 /* Found the entry with same uuid. See if we need to change it */
2163 fbase = (HostAddress[FoundUuid] >> 16) & 0xff;
2164 index = HostAddress[FoundUuid] & 0x0000ffff;
2165 exp = &ex_addr[fbase][index];
2167 /* Determine if the entry has changed */
2168 for (k = 0; ((k < cnt) && !change); k++) {
2169 if (ntohl(exp->ex_addrs[k]) != addrs[k])
2172 for (; ((k < VL_MAXIPADDRS_PERMH) && !change); k++) {
2173 if (exp->ex_addrs[k] != 0)
2177 return (ubik_EndTrans(trans));
2181 VLog(0, ("The following fileserver is being registered in the VLDB:\n"));
2183 for (k = 0; k < cnt; k++) {
2190 if (foundUuidEntry) {
2192 (" It will replace the following existing entry in the VLDB (same uuid):\n"));
2193 VLog(0, (" entry %d: [", FoundUuid));
2194 for (k = 0; k < VL_MAXIPADDRS_PERMH; k++) {
2195 if (exp->ex_addrs[k] == 0)
2199 PADDR(ntohl(exp->ex_addrs[k]));
2202 } else if (willReplaceCnt || (count == 1)) {
2203 /* If we are not replacing an entry and there is only one entry to change,
2204 * then we will replace that entry.
2206 if (!willReplaceCnt) {
2207 ReplaceEntry = WillChange[0];
2211 /* Have an entry that needs to be replaced */
2212 if ((HostAddress[ReplaceEntry] & 0xff000000) == 0xff000000) {
2213 fbase = (HostAddress[ReplaceEntry] >> 16) & 0xff;
2214 index = HostAddress[ReplaceEntry] & 0x0000ffff;
2215 exp = &ex_addr[fbase][index];
2218 (" It will replace the following existing entry in the VLDB (new uuid):\n"));
2219 VLog(0, (" entry %d: [", ReplaceEntry));
2220 for (k = 0; k < VL_MAXIPADDRS_PERMH; k++) {
2221 if (exp->ex_addrs[k] == 0)
2225 PADDR(ntohl(exp->ex_addrs[k]));
2229 /* Not a mh entry. So we have to create a new mh entry and
2230 * put it on the ReplaceEntry slot of the HostAddress array.
2232 VLog(0, (" It will replace existing entry %d, ", ReplaceEntry));
2233 PADDR(HostAddress[ReplaceEntry]);
2234 VLog(0,(", in the VLDB (new uuid):\n"));
2237 FindExtentBlock(trans, uuidp, 1, ReplaceEntry, &exp, &fbase);
2239 ubik_AbortTrans(trans);
2240 return (code ? code : VL_IO);
2244 /* There is no entry for this server, must create a new mh entry as
2245 * well as use a new slot of the HostAddress array.
2247 VLog(0, (" It will create a new entry in the VLDB.\n"));
2248 code = FindExtentBlock(trans, uuidp, 1, -1, &exp, &fbase);
2250 ubik_AbortTrans(trans);
2251 return (code ? code : VL_IO);
2255 /* Now we have a mh entry to fill in. Update the uuid, bump the
2256 * uniquifier, and fill in its IP addresses.
2259 afs_htonuuid(&tuuid);
2260 exp->ex_hostuuid = tuuid;
2261 exp->ex_uniquifier = htonl(ntohl(exp->ex_uniquifier) + 1);
2262 for (k = 0; k < cnt; k++) {
2263 exp->ex_addrs[k] = htonl(addrs[k]);
2265 for (; k < VL_MAXIPADDRS_PERMH; k++) {
2266 exp->ex_addrs[k] = 0;
2269 /* Write the new mh entry out */
2272 DOFFSET(ntohl(ex_addr[0]->ex_contaddrs[fbase]),
2273 (char *)ex_addr[fbase], (char *)exp), (char *)exp,
2275 ubik_AbortTrans(trans);
2279 /* Remove any common addresses from other mh entres. We know these entries
2280 * are being changed and not replaced so they are mh entries.
2283 for (i = 0; i < count; i++) {
2286 /* Skip the entry we replaced */
2287 if (willReplaceCnt && (WillChange[i] == ReplaceEntry))
2290 base = (HostAddress[WillChange[i]] >> 16) & 0xff;
2291 index = HostAddress[WillChange[i]] & 0x0000ffff;
2292 tex = &ex_addr[fbase][index];
2296 (" The following existing entries in the VLDB will be updated:\n"));
2298 VLog(0, (" entry %d: [", WillChange[i]));
2299 for (h = j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2300 if (tex->ex_addrs[j]) {
2303 PADDR(ntohl(tex->ex_addrs[j]));
2306 for (k = 0; k < cnt; k++) {
2307 if (ntohl(tex->ex_addrs[j]) == addrs[k])
2311 /* Not found, so we keep it */
2312 tex->ex_addrs[h] = tex->ex_addrs[j];
2316 for (j = h; j < VL_MAXIPADDRS_PERMH; j++) {
2317 tex->ex_addrs[j] = 0; /* zero rest of mh entry */
2321 /* Write out the modified mh entry */
2322 tex->ex_uniquifier = htonl(ntohl(tex->ex_uniquifier) + 1);
2324 DOFFSET(ntohl(ex_addr[0]->ex_contaddrs[base]),
2325 (char *)ex_addr[base], (char *)tex);
2326 if (vlwrite(trans, doff, (char *)tex, sizeof(*tex))) {
2327 ubik_AbortTrans(trans);
2332 return (ubik_EndTrans(trans));
2336 SVL_GetAddrsU(rxcall, attributes, uuidpo, uniquifier, nentries, addrsp)
2337 struct rx_call *rxcall;
2338 struct ListAddrByAttributes *attributes;
2340 afs_int32 *uniquifier, *nentries;
2343 register afs_int32 errorcode, index = -1, offset;
2344 struct ubik_trans *trans;
2345 int nservers, i, j, base = 0;
2346 struct extentaddr *exp = 0;
2348 afs_uint32 *taddrp, taddr;
2350 COUNT_REQ(VLGETADDRSU);
2351 addrsp->bulkaddrs_len = *nentries = 0;
2352 addrsp->bulkaddrs_val = 0;
2353 VLog(5, ("GetAddrsU %s\n", rxinfo(rxcall)));
2354 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
2357 if (attributes->Mask & VLADDR_IPADDR) {
2358 if (attributes->Mask & (VLADDR_INDEX | VLADDR_UUID)) {
2359 ubik_AbortTrans(trans);
2362 for (base = 0; base < VL_MAX_ADDREXTBLKS; base++) {
2365 for (i = 1; i < VL_MHSRV_PERBLK; i++) {
2366 exp = &ex_addr[base][i];
2367 tuuid = exp->ex_hostuuid;
2368 afs_ntohuuid(&tuuid);
2369 if (afs_uuid_is_nil(&tuuid))
2371 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2372 if (exp->ex_addrs[j]
2373 && (ntohl(exp->ex_addrs[j]) == attributes->ipaddr)) {
2377 if (j < VL_MAXIPADDRS_PERMH)
2380 if (i < VL_MHSRV_PERBLK)
2383 if (base >= VL_MAX_ADDREXTBLKS) {
2384 ubik_AbortTrans(trans);
2387 } else if (attributes->Mask & VLADDR_INDEX) {
2388 if (attributes->Mask & (VLADDR_IPADDR | VLADDR_UUID)) {
2389 ubik_AbortTrans(trans);
2392 index = attributes->index;
2393 if (index < 1 || index >= (VL_MAX_ADDREXTBLKS * VL_MHSRV_PERBLK)) {
2394 ubik_AbortTrans(trans);
2395 return VL_INDEXERANGE;
2397 base = index / VL_MHSRV_PERBLK;
2398 offset = index % VL_MHSRV_PERBLK;
2400 ubik_AbortTrans(trans);
2403 if (!ex_addr[base]) {
2404 ubik_AbortTrans(trans);
2405 return VL_INDEXERANGE;
2407 exp = &ex_addr[base][offset];
2408 } else if (attributes->Mask & VLADDR_UUID) {
2409 if (attributes->Mask & (VLADDR_IPADDR | VLADDR_INDEX)) {
2410 ubik_AbortTrans(trans);
2413 if (!ex_addr[0]) { /* mh servers probably aren't setup on this vldb */
2414 ubik_AbortTrans(trans);
2418 FindExtentBlock(trans, &attributes->uuid, 0, -1, &exp, &base)) {
2419 ubik_AbortTrans(trans);
2423 ubik_AbortTrans(trans);
2428 ubik_AbortTrans(trans);
2431 addrsp->bulkaddrs_val = taddrp =
2432 (afs_uint32 *) malloc(sizeof(afs_int32) * (MAXSERVERID + 1));
2433 nservers = *nentries = addrsp->bulkaddrs_len = 0;
2436 ubik_AbortTrans(trans);
2439 tuuid = exp->ex_hostuuid;
2440 afs_ntohuuid(&tuuid);
2441 if (afs_uuid_is_nil(&tuuid)) {
2442 ubik_AbortTrans(trans);
2448 *uniquifier = ntohl(exp->ex_uniquifier);
2449 for (i = 0; i < VL_MAXIPADDRS_PERMH; i++) {
2450 if (exp->ex_addrs[i]) {
2451 taddr = ntohl(exp->ex_addrs[i]);
2452 /* Weed out duplicates */
2453 for (j = 0; j < nservers; j++) {
2454 if (taddrp[j] == taddr)
2457 if ((j == nservers) && (j <= MAXSERVERID)) {
2458 taddrp[nservers] = taddr;
2463 addrsp->bulkaddrs_len = *nentries = nservers;
2464 return (ubik_EndTrans(trans));
2467 /* ============> End of Exported vldb RPC functions <============= */
2470 /* Routine that copies the given vldb entry to the output buffer, vldbentries. */
2472 put_attributeentry(Vldbentry, VldbentryFirst, VldbentryLast, vldbentries,
2473 entry, nentries, alloccnt)
2474 struct vldbentry **Vldbentry, **VldbentryFirst, **VldbentryLast;
2475 bulkentries *vldbentries;
2476 struct nvlentry *entry;
2477 afs_int32 *nentries, *alloccnt;
2482 if (*Vldbentry == *VldbentryLast) {
2484 return VL_SIZEEXCEEDED; /* no growing if smallMem defined */
2486 /* Allocate another set of memory; each time allocate twice as
2487 * many blocks as the last time. When we reach VLDBALLOCLIMIT,
2488 * then grow in increments of VLDBALLOCINCR.
2490 allo = (*alloccnt > VLDBALLOCLIMIT) ? VLDBALLOCINCR : *alloccnt;
2492 (vldbentry *) realloc(*VldbentryFirst,
2493 (*alloccnt + allo) * sizeof(vldbentry));
2497 *VldbentryFirst = vldbentries->bulkentries_val = reall;
2498 *Vldbentry = *VldbentryFirst + *alloccnt;
2499 *VldbentryLast = *Vldbentry + allo;
2502 vlentry_to_vldbentry(entry, *Vldbentry);
2505 vldbentries->bulkentries_len++;
2510 put_nattributeentry(Vldbentry, VldbentryFirst, VldbentryLast, vldbentries,
2511 entry, matchtype, matchindex, nentries, alloccnt)
2512 struct nvldbentry **Vldbentry, **VldbentryFirst, **VldbentryLast;
2513 nbulkentries *vldbentries;
2514 struct nvlentry *entry;
2515 afs_int32 matchtype, matchindex, *nentries, *alloccnt;
2520 if (*Vldbentry == *VldbentryLast) {
2522 return VL_SIZEEXCEEDED; /* no growing if smallMem defined */
2524 /* Allocate another set of memory; each time allocate twice as
2525 * many blocks as the last time. When we reach VLDBALLOCLIMIT,
2526 * then grow in increments of VLDBALLOCINCR.
2528 allo = (*alloccnt > VLDBALLOCLIMIT) ? VLDBALLOCINCR : *alloccnt;
2530 (nvldbentry *) realloc(*VldbentryFirst,
2531 (*alloccnt + allo) * sizeof(nvldbentry));
2535 *VldbentryFirst = vldbentries->nbulkentries_val = reall;
2536 *Vldbentry = *VldbentryFirst + *alloccnt;
2537 *VldbentryLast = *Vldbentry + allo;
2540 vlentry_to_nvldbentry(entry, *Vldbentry);
2541 (*Vldbentry)->matchindex = (matchtype << 16) + matchindex;
2544 vldbentries->nbulkentries_len++;
2549 /* Common code to actually remove a vldb entry from the database. */
2551 RemoveEntry(trans, entryptr, tentry)
2552 struct ubik_trans *trans;
2554 struct nvlentry *tentry;
2556 register int errorcode;
2558 if (errorcode = UnthreadVLentry(trans, entryptr, tentry))
2560 if (errorcode = FreeBlock(trans, entryptr))
2566 ReleaseEntry(tentry, releasetype)
2567 struct nvlentry *tentry;
2568 afs_int32 releasetype;
2570 if (releasetype & LOCKREL_TIMESTAMP)
2571 tentry->LockTimestamp = 0;
2572 if (releasetype & LOCKREL_OPCODE)
2573 tentry->flags &= ~VLOP_ALLOPERS;
2574 if (releasetype & LOCKREL_AFSID)
2575 tentry->LockAfsId = 0;
2579 /* Verify that the incoming vldb entry is valid; multi type of error codes are returned. */
2581 check_vldbentry(aentry)
2582 struct vldbentry *aentry;
2586 if (InvalidVolname(aentry->name))
2588 if (aentry->nServers <= 0 || aentry->nServers > OMAXNSERVERS)
2589 return VL_BADSERVER;
2590 for (i = 0; i < aentry->nServers; i++) {
2591 /* if (aentry->serverNumber[i] < 0 || aentry->serverNumber[i] > MAXSERVERID)
2592 return VL_BADSERVER; */
2593 if (aentry->serverPartition[i] < 0
2594 || aentry->serverPartition[i] > MAXPARTITIONID)
2595 return VL_BADPARTITION;
2596 if (aentry->serverFlags[i] < 0
2597 || aentry->serverFlags[i] > MAXSERVERFLAG)
2598 return VL_BADSERVERFLAG;
2604 check_nvldbentry(aentry)
2605 struct nvldbentry *aentry;
2609 if (InvalidVolname(aentry->name))
2611 if (aentry->nServers <= 0 || aentry->nServers > NMAXNSERVERS)
2612 return VL_BADSERVER;
2613 for (i = 0; i < aentry->nServers; i++) {
2614 /* if (aentry->serverNumber[i] < 0 || aentry->serverNumber[i] > MAXSERVERID)
2615 return VL_BADSERVER; */
2616 if (aentry->serverPartition[i] < 0
2617 || aentry->serverPartition[i] > MAXPARTITIONID)
2618 return VL_BADPARTITION;
2619 if (aentry->serverFlags[i] < 0
2620 || aentry->serverFlags[i] > MAXSERVERFLAG)
2621 return VL_BADSERVERFLAG;
2627 /* Convert from the external vldb entry representation to its internal
2628 (more compact) form. This call should not change the hash chains! */
2630 vldbentry_to_vlentry(atrans, VldbEntry, VlEntry)
2631 struct ubik_trans *atrans;
2632 struct vldbentry *VldbEntry;
2633 struct nvlentry *VlEntry;
2637 if (strcmp(VlEntry->name, VldbEntry->name))
2638 strncpy(VlEntry->name, VldbEntry->name, sizeof(VlEntry->name));
2639 for (i = 0; i < VldbEntry->nServers; i++) {
2640 serverindex = IpAddrToRelAddr(VldbEntry->serverNumber[i], atrans);
2641 if (serverindex == -1)
2642 return VL_BADSERVER;
2643 VlEntry->serverNumber[i] = serverindex;
2644 VlEntry->serverPartition[i] = VldbEntry->serverPartition[i];
2645 VlEntry->serverFlags[i] = VldbEntry->serverFlags[i];
2647 for (; i < OMAXNSERVERS; i++)
2648 VlEntry->serverNumber[i] = VlEntry->serverPartition[i] =
2649 VlEntry->serverFlags[i] = BADSERVERID;
2650 for (i = 0; i < MAXTYPES; i++)
2651 VlEntry->volumeId[i] = VldbEntry->volumeId[i];
2652 VlEntry->cloneId = VldbEntry->cloneId;
2653 VlEntry->flags = VldbEntry->flags;
2658 nvldbentry_to_vlentry(atrans, VldbEntry, VlEntry)
2659 struct ubik_trans *atrans;
2660 struct nvldbentry *VldbEntry;
2661 struct nvlentry *VlEntry;
2665 if (strcmp(VlEntry->name, VldbEntry->name))
2666 strncpy(VlEntry->name, VldbEntry->name, sizeof(VlEntry->name));
2667 for (i = 0; i < VldbEntry->nServers; i++) {
2668 serverindex = IpAddrToRelAddr(VldbEntry->serverNumber[i], atrans);
2669 if (serverindex == -1)
2670 return VL_BADSERVER;
2671 VlEntry->serverNumber[i] = serverindex;
2672 VlEntry->serverPartition[i] = VldbEntry->serverPartition[i];
2673 VlEntry->serverFlags[i] = VldbEntry->serverFlags[i];
2675 for (; i < NMAXNSERVERS; i++)
2676 VlEntry->serverNumber[i] = VlEntry->serverPartition[i] =
2677 VlEntry->serverFlags[i] = BADSERVERID;
2678 for (i = 0; i < MAXTYPES; i++)
2679 VlEntry->volumeId[i] = VldbEntry->volumeId[i];
2680 VlEntry->cloneId = VldbEntry->cloneId;
2681 VlEntry->flags = VldbEntry->flags;
2686 /* 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. */
2688 get_vldbupdateentry(trans, blockindex, updateentry, VlEntry)
2689 struct ubik_trans *trans;
2690 afs_int32 blockindex;
2691 struct VldbUpdateEntry *updateentry;
2692 struct nvlentry *VlEntry;
2694 int i, j, errorcode, serverindex;
2696 if (updateentry->Mask & VLUPDATE_VOLUMENAME) {
2697 if (InvalidVolname(updateentry->name))
2699 if (errorcode = UnhashVolname(trans, blockindex, VlEntry))
2701 strncpy(VlEntry->name, updateentry->name, sizeof(VlEntry->name));
2702 HashVolname(trans, blockindex, VlEntry);
2705 if (updateentry->Mask & VLUPDATE_VOLNAMEHASH) {
2706 if (errorcode = UnhashVolname(trans, blockindex, VlEntry)) {
2707 if (errorcode != VL_NOENT)
2710 HashVolname(trans, blockindex, VlEntry);
2713 if (updateentry->Mask & VLUPDATE_FLAGS) {
2714 VlEntry->flags = updateentry->flags;
2716 if (updateentry->Mask & VLUPDATE_CLONEID) {
2717 VlEntry->cloneId = updateentry->cloneId;
2719 if (updateentry->Mask & VLUPDATE_RWID) {
2720 if (errorcode = UnhashVolid(trans, RWVOL, blockindex, VlEntry)) {
2721 if (errorcode != VL_NOENT)
2724 VlEntry->volumeId[RWVOL] = updateentry->spares3; /* rw id */
2725 if (errorcode = HashVolid(trans, RWVOL, blockindex, VlEntry))
2728 if (updateentry->Mask & VLUPDATE_READONLYID) {
2729 if (errorcode = UnhashVolid(trans, ROVOL, blockindex, VlEntry)) {
2730 if (errorcode != VL_NOENT)
2733 VlEntry->volumeId[ROVOL] = updateentry->ReadOnlyId;
2734 if (errorcode = HashVolid(trans, ROVOL, blockindex, VlEntry))
2737 if (updateentry->Mask & VLUPDATE_BACKUPID) {
2738 if (errorcode = UnhashVolid(trans, BACKVOL, blockindex, VlEntry)) {
2739 if (errorcode != VL_NOENT)
2742 VlEntry->volumeId[BACKVOL] = updateentry->BackupId;
2743 if (errorcode = HashVolid(trans, BACKVOL, blockindex, VlEntry))
2746 if (updateentry->Mask & VLUPDATE_REPSITES) {
2747 if (updateentry->nModifiedRepsites <= 0
2748 || updateentry->nModifiedRepsites > OMAXNSERVERS)
2749 return VL_BADSERVER;
2750 for (i = 0; i < updateentry->nModifiedRepsites; i++) {
2751 /* if (updateentry->RepsitesTargetServer[i] < 0 || updateentry->RepsitesTargetServer[i] > MAXSERVERID)
2752 return VL_BADSERVER; */
2753 if (updateentry->RepsitesTargetPart[i] < 0
2754 || updateentry->RepsitesTargetPart[i] > MAXPARTITIONID)
2755 return VL_BADPARTITION;
2756 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_DELETE) {
2758 repsite_exists(VlEntry,
2759 IpAddrToRelAddr(updateentry->
2760 RepsitesTargetServer[i],
2762 updateentry->RepsitesTargetPart[i])) !=
2764 repsite_compress(VlEntry, j);
2766 return VL_NOREPSERVER;
2768 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_ADD) {
2769 /* if (updateentry->RepsitesNewServer[i] < 0 || updateentry->RepsitesNewServer[i] > MAXSERVERID)
2770 return VL_BADSERVER; */
2771 if (updateentry->RepsitesNewPart[i] < 0
2772 || updateentry->RepsitesNewPart[i] > MAXPARTITIONID)
2773 return VL_BADPARTITION;
2776 IpAddrToRelAddr(updateentry->RepsitesNewServer[i],
2778 updateentry->RepsitesNewPart[i]) != -1)
2779 return VL_DUPREPSERVER;
2781 VlEntry->serverNumber[j] != BADSERVERID
2782 && j < OMAXNSERVERS; j++);
2783 if (j >= OMAXNSERVERS)
2786 IpAddrToRelAddr(updateentry->RepsitesNewServer[i],
2788 return VL_BADSERVER;
2789 VlEntry->serverNumber[j] = serverindex;
2790 VlEntry->serverPartition[j] = updateentry->RepsitesNewPart[i];
2791 if (updateentry->RepsitesNewFlags[i] < 0
2792 || updateentry->RepsitesNewFlags[i] > MAXSERVERFLAG)
2793 return VL_BADSERVERFLAG;
2794 VlEntry->serverFlags[j] = updateentry->RepsitesNewFlags[i];
2796 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODSERV) {
2797 /*n if (updateentry->RepsitesNewServer[i] < 0 || updateentry->RepsitesNewServer[i] > MAXSERVERID)
2798 return VL_BADSERVER; */
2800 repsite_exists(VlEntry,
2801 IpAddrToRelAddr(updateentry->
2802 RepsitesTargetServer[i],
2804 updateentry->RepsitesTargetPart[i])) !=
2806 VlEntry->serverNumber[j] =
2807 IpAddrToRelAddr(updateentry->RepsitesNewServer[i],
2810 return VL_NOREPSERVER;
2812 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODPART) {
2813 if (updateentry->RepsitesNewPart[i] < 0
2814 || updateentry->RepsitesNewPart[i] > MAXPARTITIONID)
2815 return VL_BADPARTITION;
2817 repsite_exists(VlEntry,
2818 IpAddrToRelAddr(updateentry->
2819 RepsitesTargetServer[i],
2821 updateentry->RepsitesTargetPart[i])) !=
2823 VlEntry->serverPartition[j] =
2824 updateentry->RepsitesNewPart[i];
2826 return VL_NOREPSERVER;
2828 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODFLAG) {
2830 repsite_exists(VlEntry,
2831 IpAddrToRelAddr(updateentry->
2832 RepsitesTargetServer[i],
2834 updateentry->RepsitesTargetPart[i])) !=
2836 if (updateentry->RepsitesNewFlags[i] < 0
2837 || updateentry->RepsitesNewFlags[i] > MAXSERVERFLAG)
2838 return VL_BADSERVERFLAG;
2839 VlEntry->serverFlags[j] =
2840 updateentry->RepsitesNewFlags[i];
2842 return VL_NOREPSERVER;
2850 /* 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. */
2852 repsite_exists(VlEntry, server, partition)
2853 struct nvlentry *VlEntry;
2854 int server, partition;
2858 for (i = 0; VlEntry->serverNumber[i] != BADSERVERID && i < OMAXNSERVERS;
2860 if ((VlEntry->serverNumber[i] == server)
2861 && (VlEntry->serverPartition[i] == partition))
2869 /* Repsite table compression: used when deleting a repsite entry so that all active repsite entries are on the top of the table. */
2871 repsite_compress(VlEntry, offset)
2872 struct nvlentry *VlEntry;
2875 int repsite_offset = offset;
2877 VlEntry->serverNumber[repsite_offset] != BADSERVERID
2878 && repsite_offset < OMAXNSERVERS - 1; repsite_offset++) {
2879 VlEntry->serverNumber[repsite_offset] =
2880 VlEntry->serverNumber[repsite_offset + 1];
2881 VlEntry->serverPartition[repsite_offset] =
2882 VlEntry->serverPartition[repsite_offset + 1];
2883 VlEntry->serverFlags[repsite_offset] =
2884 VlEntry->serverFlags[repsite_offset + 1];
2886 VlEntry->serverNumber[repsite_offset] = BADSERVERID;
2890 /* Convert from the internal (compacted) vldb entry to the external representation used by the interface. */
2892 vlentry_to_vldbentry(VlEntry, VldbEntry)
2893 struct nvlentry *VlEntry;
2894 struct vldbentry *VldbEntry;
2898 memset(VldbEntry, 0, sizeof(struct vldbentry));
2899 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
2900 for (i = 0; i < OMAXNSERVERS; i++) {
2901 if (VlEntry->serverNumber[i] == BADSERVERID)
2903 if ((HostAddress[j = VlEntry->serverNumber[i]] & 0xff000000) ==
2905 struct extentaddr *exp;
2908 base = (HostAddress[j] >> 16) & 0xff;
2909 index = HostAddress[j] & 0x0000ffff;
2910 exp = &ex_addr[base][index];
2911 /* For now return the first ip address back */
2912 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2913 if (exp->ex_addrs[j]) {
2914 VldbEntry->serverNumber[i] = ntohl(exp->ex_addrs[j]);
2919 VldbEntry->serverNumber[i] =
2920 HostAddress[VlEntry->serverNumber[i]];
2921 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
2922 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
2924 VldbEntry->nServers = i;
2925 for (i = 0; i < MAXTYPES; i++)
2926 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
2927 VldbEntry->cloneId = VlEntry->cloneId;
2928 VldbEntry->flags = VlEntry->flags;
2932 /* Convert from the internal (compacted) vldb entry to the external representation used by the interface. */
2934 vlentry_to_nvldbentry(VlEntry, VldbEntry)
2935 struct nvlentry *VlEntry;
2936 struct nvldbentry *VldbEntry;
2940 memset(VldbEntry, 0, sizeof(struct vldbentry));
2941 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
2942 for (i = 0; i < NMAXNSERVERS; i++) {
2943 if (VlEntry->serverNumber[i] == BADSERVERID)
2945 if ((HostAddress[j = VlEntry->serverNumber[i]] & 0xff000000) ==
2947 struct extentaddr *exp;
2950 base = (HostAddress[j] >> 16) & 0xff;
2951 index = HostAddress[j] & 0x0000ffff;
2952 exp = &ex_addr[base][index];
2953 /* For now return the first ip address back */
2954 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2955 if (exp->ex_addrs[j]) {
2956 VldbEntry->serverNumber[i] = ntohl(exp->ex_addrs[j]);
2961 VldbEntry->serverNumber[i] =
2962 HostAddress[VlEntry->serverNumber[i]];
2963 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
2964 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
2966 VldbEntry->nServers = i;
2967 for (i = 0; i < MAXTYPES; i++)
2968 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
2969 VldbEntry->cloneId = VlEntry->cloneId;
2970 VldbEntry->flags = VlEntry->flags;
2974 vlentry_to_uvldbentry(VlEntry, VldbEntry)
2975 struct nvlentry *VlEntry;
2976 struct uvldbentry *VldbEntry;
2980 memset(VldbEntry, 0, sizeof(struct vldbentry));
2981 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
2982 for (i = 0; i < NMAXNSERVERS; i++) {
2983 if (VlEntry->serverNumber[i] == BADSERVERID)
2985 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
2986 VldbEntry->serverUnique[i] = 0;
2987 if ((HostAddress[j = VlEntry->serverNumber[i]] & 0xff000000) ==
2989 struct extentaddr *exp;
2993 base = (HostAddress[j] >> 16) & 0xff;
2994 index = HostAddress[j] & 0x0000ffff;
2995 exp = &ex_addr[base][index];
2996 tuuid = exp->ex_hostuuid;
2997 afs_ntohuuid(&tuuid);
2998 VldbEntry->serverFlags[i] |= VLSERVER_FLAG_UUID;
2999 VldbEntry->serverNumber[i] = tuuid;
3000 VldbEntry->serverUnique[i] = ntohl(exp->ex_uniquifier);
3002 VldbEntry->serverNumber[i].time_low =
3003 HostAddress[VlEntry->serverNumber[i]];
3005 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
3008 VldbEntry->nServers = i;
3009 for (i = 0; i < MAXTYPES; i++)
3010 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
3011 VldbEntry->cloneId = VlEntry->cloneId;
3012 VldbEntry->flags = VlEntry->flags;
3015 #define LEGALCHARS ".ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
3018 /* Verify that the volname is a valid volume name. */
3020 InvalidVolname(volname)
3027 slen = strlen(volname);
3028 if (slen >= VL_MAXNAMELEN)
3030 return (slen != strspn(volname, map));
3034 /* Verify that the given volume type is valid. */
3036 InvalidVoltype(voltype)
3039 if (voltype != RWVOL && voltype != ROVOL && voltype != BACKVOL)
3046 InvalidOperation(voloper)
3049 if (voloper != VLOP_MOVE && voloper != VLOP_RELEASE
3050 && voloper != VLOP_BACKUP && voloper != VLOP_DELETE
3051 && voloper != VLOP_DUMP)
3057 InvalidReleasetype(releasetype)
3058 afs_int32 releasetype;
3060 if ((releasetype & LOCKREL_TIMESTAMP) || (releasetype & LOCKREL_OPCODE)
3061 || (releasetype & LOCKREL_AFSID))
3067 IpAddrToRelAddr(ipaddr, atrans)
3068 struct ubik_trans *atrans;
3069 register afs_uint32 ipaddr;
3072 register afs_int32 code, base, index;
3073 struct extentaddr *exp;
3075 for (i = 0; i <= MAXSERVERID; i++) {
3076 if (HostAddress[i] == ipaddr)
3078 if ((HostAddress[i] & 0xff000000) == 0xff000000) {
3079 base = (HostAddress[i] >> 16) & 0xff;
3080 index = HostAddress[i] & 0x0000ffff;
3081 if (base >= VL_MAX_ADDREXTBLKS) {
3083 ("Internal error: Multihome extent base is too large. Base %d index %d\n",
3085 return -1; /* EINVAL */
3087 if (index >= VL_MHSRV_PERBLK) {
3089 ("Internal error: Multihome extent index is too large. Base %d index %d\n",
3091 return -1; /* EINVAL */
3093 if (!ex_addr[base]) {
3095 ("Internal error: Multihome extent does not exist. Base %d\n",
3097 return -1; /* EINVAL */
3099 exp = &ex_addr[base][index];
3100 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
3101 if (exp->ex_addrs[j] && (ntohl(exp->ex_addrs[j]) == ipaddr)) {
3108 /* allocate the new server a server id pronto */
3110 for (i = 0; i <= MAXSERVERID; i++) {
3111 if (cheader.IpMappedAddr[i] == 0) {
3112 cheader.IpMappedAddr[i] = htonl(ipaddr);
3115 DOFFSET(0, &cheader, &cheader.IpMappedAddr[i]),
3116 (char *)&cheader.IpMappedAddr[i],
3118 HostAddress[i] = ipaddr;
3129 ChangeIPAddr(ipaddr1, ipaddr2, atrans)
3130 struct ubik_trans *atrans;
3131 register afs_uint32 ipaddr1, ipaddr2;
3135 struct extentaddr *exp;
3136 int base, index, mhidx;
3138 afs_int32 blockindex, count;
3140 struct nvlentry tentry;
3143 return VL_CREATEFAIL;
3145 /* Don't let addr change to 256.*.*.* : Causes internal error below */
3146 if ((ipaddr2 & 0xff000000) == 0xff000000)
3147 return (VL_BADSERVER);
3149 /* If we are removing an address, ip1 will be -1 and ip2 will be
3150 * the original address. This prevents an older revision vlserver
3151 * from removing the IP address (won't find server 0xfffffff in
3152 * the VLDB). An older revision vlserver does not have the check
3153 * to see if any volumes exist on the server being removed.
3155 if (ipaddr1 == 0xffffffff) {
3160 for (i = 0; i <= MAXSERVERID; i++) {
3161 if ((HostAddress[i] & 0xff000000) == 0xff000000) {
3162 base = (HostAddress[i] >> 16) & 0xff;
3163 index = HostAddress[i] & 0x0000ffff;
3164 if ((base >= VL_MAX_ADDREXTBLKS) || (index >= VL_MHSRV_PERBLK)) {
3166 ("Internal error: Multihome extent addr is too large. Base %d index %d\n",
3168 return -1; /* EINVAL */
3171 exp = &ex_addr[base][index];
3172 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
3173 if (!exp->ex_addrs[mhidx])
3175 if (ntohl(exp->ex_addrs[mhidx]) == ipaddr1)
3178 if (mhidx < VL_MAXIPADDRS_PERMH) {
3181 } else if (HostAddress[i] == ipaddr1) {
3187 if (i >= MAXSERVERID) {
3188 return VL_NOENT; /* not found */
3191 /* If we are removing a server entry, a volume cannot
3192 * exist on the server. If one does, don't remove the
3193 * server entry: return error "volume entry exists".
3196 for (blockindex = NextEntry(atrans, 0, &tentry, &count); blockindex;
3197 blockindex = NextEntry(atrans, blockindex, &tentry, &count)) {
3198 if (++pollcount > 50) {
3202 for (j = 0; j < NMAXNSERVERS; j++) {
3203 if (tentry.serverNumber[j] == BADSERVERID)
3205 if (tentry.serverNumber[j] == i) {
3212 /* Log a message saying we are changing/removing an IP address */
3214 ("The following IP address is being %s:\n",
3215 (ipaddr2 ? "changed" : "removed")));
3216 VLog(0, (" entry %d: ", i));
3219 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
3220 if (!exp->ex_addrs[mhidx])
3224 PADDR(ntohl(exp->ex_addrs[mhidx]));
3236 /* Change the registered uuuid addresses */
3238 memset(&tuuid, 0, sizeof(afsUUID));
3239 afs_htonuuid(&tuuid);
3240 exp->ex_hostuuid = tuuid;
3243 DOFFSET(ntohl(ex_addr[0]->ex_contaddrs[base]),
3244 (char *)ex_addr[base], (char *)exp),
3245 (char *)&tuuid, sizeof(tuuid));
3250 /* Now change the host address entry */
3251 cheader.IpMappedAddr[i] = htonl(ipaddr2);
3253 vlwrite(atrans, DOFFSET(0, &cheader, &cheader.IpMappedAddr[i]),
3255 &cheader.IpMappedAddr[i], sizeof(afs_int32));
3256 HostAddress[i] = ipaddr2;
3263 /* see if the vlserver is back yet */
3265 SVL_ProbeServer(rxcall)
3266 struct rx_call *rxcall;