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>
14 #include <sys/types.h>
18 #include <afs/afsutil.h>
26 #include <netinet/in.h>
29 #include <afs/cellconfig.h>
31 #include "vlserver_internal.h"
32 #include "afs/audit.h"
36 #ifdef HAVE_POSIX_REGEX /* use POSIX regexp library */
41 extern int extent_mod;
42 extern struct afsconf_dir *vldb_confdir;
43 extern struct ubik_dbase *VL_dbase;
44 struct vlheader cheader; /* kept in network byte order */
45 extern afs_uint32 HostAddress[]; /* host addresses kept in host byte order */
47 struct extentaddr *ex_addr[VL_MAX_ADDREXTBLKS] = { 0, 0, 0, 0 };
48 static char rxinfo_str[128]; /* Need rxinfo string to be non-local */
49 #define ABORT(c) { errorcode = (c); goto abort; }
51 #define END(c) { errorcode = (c); goto end; }
53 #define VLDBALLOCLIMIT 10000
54 #define VLDBALLOCINCR 2048
56 static int put_attributeentry(struct vldbentry **, struct vldbentry **,
57 struct vldbentry **, bulkentries *,
58 struct nvlentry *, afs_int32 *, afs_int32 *);
59 static int put_nattributeentry(struct nvldbentry **, struct nvldbentry **,
60 struct nvldbentry **, nbulkentries *,
61 struct nvlentry *, afs_int32, afs_int32,
62 afs_int32 *, afs_int32 *);
63 static int RemoveEntry(struct ubik_trans *trans, afs_int32 entryptr,
64 struct nvlentry *tentry);
65 static void ReleaseEntry(struct nvlentry *tentry, afs_int32 releasetype);
66 static int check_vldbentry(struct vldbentry *aentry);
67 static int check_nvldbentry(struct nvldbentry *aentry);
68 static int vldbentry_to_vlentry(struct ubik_trans *atrans,
69 struct vldbentry *VldbEntry,
70 struct nvlentry *VlEntry);
71 static int nvldbentry_to_vlentry(struct ubik_trans *atrans,
72 struct nvldbentry *VldbEntry,
73 struct nvlentry *VlEntry);
74 static int get_vldbupdateentry(struct ubik_trans *trans, afs_int32 blockindex,
75 struct VldbUpdateEntry *updateentry,
76 struct nvlentry *VlEntry);
77 static int repsite_exists(struct nvlentry *VlEntry, int server, int partition);
78 static void repsite_compress(struct nvlentry *VlEntry, int offset);
79 static void vlentry_to_vldbentry(struct nvlentry *VlEntry,
80 struct vldbentry *VldbEntry);
81 static void vlentry_to_nvldbentry(struct nvlentry *VlEntry,
82 struct nvldbentry *VldbEntry);
83 static void vlentry_to_uvldbentry(struct nvlentry *VlEntry,
84 struct uvldbentry *VldbEntry);
85 static int InvalidVolname(char *volname);
86 static int InvalidVoltype(afs_int32 voltype);
87 static int InvalidOperation(afs_int32 voloper);
88 static int InvalidReleasetype(afs_int32 releasetype);
89 static int IpAddrToRelAddr(afs_uint32 ipaddr, struct ubik_trans *atrans);
90 static int ChangeIPAddr(afs_uint32 ipaddr1, afs_uint32 ipaddr2,
91 struct ubik_trans *atrans);
94 rxinfo(struct rx_call *rxcall)
97 register struct rx_connection *tconn;
102 struct in_addr hostAddr;
104 tconn = rx_ConnectionOf(rxcall);
105 hostAddr.s_addr = rx_HostOf(rx_PeerOf(tconn));
107 rxkad_GetServerInfo(rxcall->conn, NULL, &exp, tname, tinst, tcell,
110 sprintf(rxinfo_str, "%s %s%s%s%s%s", inet_ntoa(hostAddr), tname,
111 tinst?".":"", tinst?tinst:"", tcell?"@":"", tcell?tcell:"");
113 sprintf(rxinfo_str, "%s noauth", inet_ntoa(hostAddr));
117 /* This is called to initialize the database, set the appropriate locks and make sure that the vldb header is valid */
119 Init_VLdbase(struct ubik_trans **trans,
120 int locktype, /* indicate read or write transaction */
123 int errorcode = 0, pass, wl;
125 for (pass = 1; pass <= 3; pass++) {
126 if (pass == 2) { /* take write lock to rebuild the db */
127 errorcode = ubik_BeginTrans(VL_dbase, UBIK_WRITETRANS, trans);
129 } else if (locktype == LOCKREAD) {
131 ubik_BeginTransReadAny(VL_dbase, UBIK_READTRANS, trans);
134 errorcode = ubik_BeginTrans(VL_dbase, UBIK_WRITETRANS, trans);
140 errorcode = ubik_SetLock(*trans, 1, 1, locktype);
143 ubik_AbortTrans(*trans);
147 /* check that dbase is initialized and setup cheader */
148 /* 2nd pass we try to rebuild the header */
149 errorcode = CheckInit(*trans, ((pass == 2) ? 1 : 0));
150 if (!errorcode && wl && extent_mod)
151 errorcode = readExtents(*trans); /* Fix the mh extent blocks */
154 ubik_AbortTrans(*trans);
155 /* Only rebuld if the database is empty */
156 /* Exit if can't rebuild */
157 if ((pass == 1) && (errorcode != VL_EMPTY))
161 } else { /* No errorcode */
163 ubik_EndTrans(*trans); /* Rebuilt db. End trans, then retake original lock */
165 break; /* didn't rebuild and successful - exit */
173 /* Create a new vldb entry; both new volume id and name must be unique
174 * (non-existant in vldb).
178 SVL_CreateEntry(struct rx_call *rxcall, struct vldbentry *newentry)
180 struct ubik_trans *trans;
181 afs_int32 errorcode, blockindex;
182 struct nvlentry tentry;
184 COUNT_REQ(VLCREATEENTRY);
185 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) {
190 /* Do some validity tests on new entry */
191 if ((errorcode = check_vldbentry(newentry))
192 || (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
196 ("OCreate Volume %d %s\n", newentry->volumeId[RWVOL],
198 /* XXX shouldn't we check to see if the r/o volume is duplicated? */
199 if (newentry->volumeId[RWVOL]
200 && FindByID(trans, newentry->volumeId[RWVOL], RWVOL, &tentry, &errorcode)) { /* entry already exists, we fail */
201 errorcode = VL_IDEXIST;
203 } else if (errorcode) {
207 /* Is this following check (by volume name) necessary?? */
208 /* If entry already exists, we fail */
209 if (FindByName(trans, newentry->name, &tentry, &errorcode)) {
210 errorcode = VL_NAMEEXIST;
212 } else if (errorcode) {
216 blockindex = AllocBlock(trans, &tentry);
217 if (blockindex == 0) {
218 errorcode = VL_CREATEFAIL;
222 memset(&tentry, 0, sizeof(struct nvlentry));
223 /* Convert to its internal representation; both in host byte order */
224 if ((errorcode = vldbentry_to_vlentry(trans, newentry, &tentry))) {
225 FreeBlock(trans, blockindex);
229 /* Actually insert the entry in vldb */
230 errorcode = ThreadVLentry(trans, blockindex, &tentry);
232 FreeBlock(trans, blockindex);
235 errorcode = ubik_EndTrans(trans);
241 ubik_AbortTrans(trans);
244 osi_auditU(rxcall, VLCreateEntryEvent, errorcode, AUD_STR,
245 (newentry ? newentry->name : NULL), AUD_END);
251 SVL_CreateEntryN(struct rx_call *rxcall, struct nvldbentry *newentry)
253 struct ubik_trans *trans;
254 afs_int32 errorcode, blockindex;
255 struct nvlentry tentry;
257 COUNT_REQ(VLCREATEENTRYN);
258 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) {
263 /* Do some validity tests on new entry */
264 if ((errorcode = check_nvldbentry(newentry))
265 || (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
269 ("Create Volume %d %s\n", newentry->volumeId[RWVOL],
271 /* XXX shouldn't we check to see if the r/o volume is duplicated? */
272 if (newentry->volumeId[RWVOL]
273 && FindByID(trans, newentry->volumeId[RWVOL], RWVOL, &tentry, &errorcode)) { /* entry already exists, we fail */
274 errorcode = VL_IDEXIST;
276 } else if (errorcode) {
280 /* Is this following check (by volume name) necessary?? */
281 /* If entry already exists, we fail */
282 if (FindByName(trans, newentry->name, &tentry, &errorcode)) {
283 errorcode = VL_NAMEEXIST;
285 } else if (errorcode) {
289 blockindex = AllocBlock(trans, &tentry);
290 if (blockindex == 0) {
291 errorcode = VL_CREATEFAIL;
295 memset(&tentry, 0, sizeof(struct nvlentry));
296 /* Convert to its internal representation; both in host byte order */
297 if ((errorcode = nvldbentry_to_vlentry(trans, newentry, &tentry))) {
298 FreeBlock(trans, blockindex);
302 /* Actually insert the entry in vldb */
303 errorcode = ThreadVLentry(trans, blockindex, &tentry);
305 FreeBlock(trans, blockindex);
308 errorcode = ubik_EndTrans(trans);
314 ubik_AbortTrans(trans);
317 osi_auditU(rxcall, VLCreateEntryEvent, errorcode, AUD_STR,
318 (newentry ? newentry->name : NULL), AUD_END);
324 SVL_ChangeAddr(struct rx_call *rxcall, afs_uint32 ip1, afs_uint32 ip2)
326 struct ubik_trans *trans;
329 COUNT_REQ(VLCHANGEADDR);
330 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) {
335 if ((errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
338 VLog(1, ("Change Addr %u -> %u %s\n", ip1, ip2, rxinfo(rxcall)));
339 if ((errorcode = ChangeIPAddr(ip1, ip2, trans)))
342 errorcode = ubik_EndTrans(trans);
348 ubik_AbortTrans(trans);
351 osi_auditU(rxcall, VLChangeAddrEvent, errorcode, AUD_LONG, ip1, AUD_LONG,
356 /* Delete a vldb entry given the volume id. */
358 SVL_DeleteEntry(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype)
360 struct ubik_trans *trans;
361 afs_int32 blockindex, errorcode;
362 struct nvlentry tentry;
364 COUNT_REQ(VLDELETEENTRY);
365 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
368 if ((voltype != -1) && (InvalidVoltype(voltype)))
371 if ((errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
374 VLog(1, ("Delete Volume %u %s\n", volid, rxinfo(rxcall)));
375 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
376 if (blockindex == 0) { /* volid not found */
378 errorcode = VL_NOENT;
382 if (tentry.flags & VLDELETED) { /* Already deleted; return */
383 ABORT(VL_ENTDELETED);
385 if ((errorcode = RemoveEntry(trans, blockindex, &tentry))) {
388 errorcode = (ubik_EndTrans(trans));
393 ubik_AbortTrans(trans);
396 osi_auditU(rxcall, VLDeleteEntryEvent, errorcode, AUD_LONG, volid,
402 /* Get a vldb entry given its volume id; make sure it's not a deleted entry. */
404 GetEntryByID(struct rx_call *rxcall,
407 char *aentry, /* entry data copied here */
411 struct ubik_trans *trans;
412 afs_int32 blockindex, errorcode;
413 struct nvlentry tentry;
415 if ((voltype != -1) && (InvalidVoltype(voltype)))
416 return VL_BADVOLTYPE;
417 if ((errorcode = Init_VLdbase(&trans, LOCKREAD, this_op)))
420 VLog(5, ("GetVolumeByID %u (%d) %s\n", volid, new, rxinfo(rxcall)));
421 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
422 if (blockindex == 0) { /* entry not found */
424 errorcode = VL_NOENT;
426 ubik_AbortTrans(trans);
429 if (tentry.flags & VLDELETED) { /* Entry is deleted! */
431 ubik_AbortTrans(trans);
432 return VL_ENTDELETED;
434 /* Convert from the internal to external form */
436 vlentry_to_nvldbentry(&tentry, (struct nvldbentry *)aentry);
438 vlentry_to_uvldbentry(&tentry, (struct uvldbentry *)aentry);
440 vlentry_to_vldbentry(&tentry, (struct vldbentry *)aentry);
441 return (ubik_EndTrans(trans));
445 SVL_GetEntryByID(struct rx_call *rxcall,
448 vldbentry *aentry) /* entry data copied here */
450 COUNT_REQ(VLGETENTRYBYID);
451 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 0, this_op));
455 SVL_GetEntryByIDN(struct rx_call *rxcall,
458 nvldbentry *aentry) /* entry data copied here */
460 COUNT_REQ(VLGETENTRYBYIDN);
461 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 1, this_op));
465 SVL_GetEntryByIDU(struct rx_call *rxcall,
468 uvldbentry *aentry) /* entry data copied here */
470 COUNT_REQ(VLGETENTRYBYIDU);
471 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 2, this_op));
476 /* returns true if the id is a decimal integer, in which case we interpret
477 * it as an id. make the cache manager much simpler */
479 NameIsId(char *aname)
482 while ((tc = *aname++)) {
483 if (tc > '9' || tc < '0')
489 /* Get a vldb entry given the volume's name; of course, very similar to
490 * VLGetEntryByID() above. */
492 GetEntryByName(struct rx_call *rxcall,
494 char *aentry, /* entry data copied here */
498 struct ubik_trans *trans;
499 afs_int32 blockindex, errorcode;
500 struct nvlentry tentry;
502 if (NameIsId(volname)) {
503 return GetEntryByID(rxcall, atoi(volname), -1, aentry, new, this_op);
505 if (InvalidVolname(volname))
507 if ((errorcode = Init_VLdbase(&trans, LOCKREAD, this_op)))
509 VLog(5, ("GetVolumeByName %s (%d) %s\n", volname, new, rxinfo(rxcall)));
510 blockindex = FindByName(trans, volname, &tentry, &errorcode);
511 if (blockindex == 0) { /* entry not found */
513 errorcode = VL_NOENT;
515 ubik_AbortTrans(trans);
518 if (tentry.flags & VLDELETED) { /* Entry is deleted */
520 ubik_AbortTrans(trans);
521 return VL_ENTDELETED;
523 /* Convert to external entry representation */
525 vlentry_to_nvldbentry(&tentry, (struct nvldbentry *)aentry);
527 vlentry_to_uvldbentry(&tentry, (struct uvldbentry *)aentry);
529 vlentry_to_vldbentry(&tentry, (struct vldbentry *)aentry);
530 return (ubik_EndTrans(trans));
534 SVL_GetEntryByNameO(struct rx_call *rxcall,
536 struct vldbentry *aentry) /* entry data copied here */
538 COUNT_REQ(VLGETENTRYBYNAME);
539 return (GetEntryByName(rxcall, volname, (char *)aentry, 0, this_op));
544 SVL_GetEntryByNameN(struct rx_call *rxcall,
546 struct nvldbentry *aentry) /* entry data copied here */
548 COUNT_REQ(VLGETENTRYBYNAMEN);
549 return (GetEntryByName(rxcall, volname, (char *)aentry, 1, this_op));
553 SVL_GetEntryByNameU(struct rx_call *rxcall,
555 struct uvldbentry *aentry) /* entry data copied here */
557 COUNT_REQ(VLGETENTRYBYNAMEU);
558 return (GetEntryByName(rxcall, volname, (char *)aentry, 2, this_op));
563 /* Get the current value of the maximum volume id and bump the volume id counter by Maxvolidbump. */
565 SVL_GetNewVolumeId(struct rx_call *rxcall, afs_uint32 Maxvolidbump,
566 afs_uint32 *newvolumeid)
568 register afs_int32 errorcode;
569 afs_uint32 maxvolumeid;
570 struct ubik_trans *trans;
572 COUNT_REQ(VLGETNEWVOLUMEID);
573 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
576 if (Maxvolidbump < 0 || Maxvolidbump > MAXBUMPCOUNT)
577 END(VL_BADVOLIDBUMP);
579 if ((errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
582 *newvolumeid = maxvolumeid = ntohl(cheader.vital_header.MaxVolumeId);
583 maxvolumeid += Maxvolidbump;
584 VLog(1, ("GetNewVolid newmax=%u %s\n", maxvolumeid, rxinfo(rxcall)));
585 cheader.vital_header.MaxVolumeId = htonl(maxvolumeid);
586 if (write_vital_vlheader(trans)) {
589 errorcode = (ubik_EndTrans(trans));
594 ubik_AbortTrans(trans);
597 osi_auditU(rxcall, VLGetNewVolumeIdEvent, errorcode, AUD_END);
602 /* Simple replace the contents of the vldb entry, volid, with
603 * newentry. No individual checking/updating per field (alike
604 * VLUpdateEntry) is done. */
607 SVL_ReplaceEntry(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype,
608 struct vldbentry *newentry, afs_int32 releasetype)
610 struct ubik_trans *trans;
611 afs_int32 blockindex, errorcode, typeindex;
613 int hashVol[MAXTYPES];
614 struct nvlentry tentry;
616 COUNT_REQ(VLREPLACEENTRY);
617 for (typeindex = 0; typeindex < MAXTYPES; typeindex++)
618 hashVol[typeindex] = 0;
620 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
623 if ((errorcode = check_vldbentry(newentry)))
626 if (voltype != -1 && InvalidVoltype(voltype))
629 if (releasetype && InvalidReleasetype(releasetype))
630 END(VL_BADRELLOCKTYPE);
631 if ((errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
634 VLog(1, ("OReplace Volume %u %s\n", volid, rxinfo(rxcall)));
635 /* find vlentry we're changing */
636 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
637 if (blockindex == 0) { /* entry not found */
639 errorcode = VL_NOENT;
643 /* check that we're not trying to change the RW vol ID */
644 if (newentry->volumeId[RWVOL] != tentry.volumeId[RWVOL]) {
648 /* unhash volid entries if they're disappearing or changing.
649 * Remember if we need to hash in the new value (we don't have to
650 * rehash if volid stays same */
651 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
652 if (tentry.volumeId[typeindex] != newentry->volumeId[typeindex]) {
653 if (tentry.volumeId[typeindex])
655 UnhashVolid(trans, typeindex, blockindex, &tentry))) {
658 /* we must rehash new id if the id is different and the ID is nonzero */
659 hashVol[typeindex] = 1; /* must rehash this guy if he exists */
663 /* Rehash volname if it changes */
664 if (strcmp(newentry->name, tentry.name)) { /* Name changes; redo hashing */
665 if ((errorcode = UnhashVolname(trans, blockindex, &tentry))) {
671 /* after this, tentry is new entry, not old one. vldbentry_to_vlentry
672 * doesn't touch hash chains */
673 if ((errorcode = vldbentry_to_vlentry(trans, newentry, &tentry))) {
677 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
678 if (hashVol[typeindex] && tentry.volumeId[typeindex]) {
679 if ((errorcode = HashVolid(trans, typeindex, blockindex, &tentry))) {
686 HashVolname(trans, blockindex, &tentry);
689 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
690 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
694 END(ubik_EndTrans(trans));
698 ubik_AbortTrans(trans);
701 osi_auditU(rxcall, VLReplaceVLEntryEvent, errorcode, AUD_LONG, volid,
707 SVL_ReplaceEntryN(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype,
708 struct nvldbentry *newentry, afs_int32 releasetype)
710 struct ubik_trans *trans;
711 afs_int32 blockindex, errorcode, typeindex;
713 int hashVol[MAXTYPES];
714 struct nvlentry tentry;
716 COUNT_REQ(VLREPLACEENTRYN);
717 for (typeindex = 0; typeindex < MAXTYPES; typeindex++)
718 hashVol[typeindex] = 0;
720 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
723 if ((errorcode = check_nvldbentry(newentry)))
726 if (voltype != -1 && InvalidVoltype(voltype))
729 if (releasetype && InvalidReleasetype(releasetype))
730 END(VL_BADRELLOCKTYPE);
731 if ((errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
734 VLog(1, ("Replace Volume %u %s\n", volid, rxinfo(rxcall)));
735 /* find vlentry we're changing */
736 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
737 if (blockindex == 0) { /* entry not found */
739 errorcode = VL_NOENT;
743 /* check that we're not trying to change the RW vol ID */
744 if (newentry->volumeId[RWVOL] != tentry.volumeId[RWVOL]) {
748 /* unhash volid entries if they're disappearing or changing.
749 * Remember if we need to hash in the new value (we don't have to
750 * rehash if volid stays same */
751 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
752 if (tentry.volumeId[typeindex] != newentry->volumeId[typeindex]) {
753 if (tentry.volumeId[typeindex])
755 UnhashVolid(trans, typeindex, blockindex, &tentry))) {
758 /* we must rehash new id if the id is different and the ID is nonzero */
759 hashVol[typeindex] = 1; /* must rehash this guy if he exists */
763 /* Rehash volname if it changes */
764 if (strcmp(newentry->name, tentry.name)) { /* Name changes; redo hashing */
765 if ((errorcode = UnhashVolname(trans, blockindex, &tentry))) {
771 /* after this, tentry is new entry, not old one. vldbentry_to_vlentry
772 * doesn't touch hash chains */
773 if ((errorcode = nvldbentry_to_vlentry(trans, newentry, &tentry))) {
777 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
778 if (hashVol[typeindex] && tentry.volumeId[typeindex]) {
779 if ((errorcode = HashVolid(trans, typeindex, blockindex, &tentry))) {
786 HashVolname(trans, blockindex, &tentry);
789 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
790 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
794 END(ubik_EndTrans(trans));
798 ubik_AbortTrans(trans);
801 osi_auditU(rxcall, VLReplaceVLEntryEvent, errorcode, AUD_LONG, volid,
807 /* Update a vldb entry (accessed thru its volume id). Almost all of the
808 * entry's fields can be modified in a single call by setting the
809 * appropriate bits in the Mask field in VldbUpdateentry. */
810 /* this routine may never have been tested; use replace entry instead
811 * unless you're brave */
813 SVL_UpdateEntry(struct rx_call *rxcall,
816 struct VldbUpdateEntry *updateentry, /* Update entry copied here */
817 afs_int32 releasetype)
819 struct ubik_trans *trans;
820 afs_int32 blockindex, errorcode;
821 struct nvlentry tentry;
823 COUNT_REQ(VLUPDATEENTRY);
824 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
826 if ((voltype != -1) && (InvalidVoltype(voltype)))
828 if (releasetype && InvalidReleasetype(releasetype))
829 END(VL_BADRELLOCKTYPE);
830 if ((errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
833 VLog(1, ("Update Volume %u %s\n", volid, rxinfo(rxcall)));
834 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
835 if (blockindex == 0) { /* entry not found */
837 errorcode = VL_NOENT;
841 /* Do the actual updating of the entry, tentry. */
843 get_vldbupdateentry(trans, blockindex, updateentry, &tentry))) {
847 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
848 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
851 END(ubik_EndTrans(trans));
855 ubik_AbortTrans(trans);
858 osi_auditU(rxcall, VLUpdateEntryEvent, errorcode, AUD_LONG, volid,
865 SVL_UpdateEntryByName(struct rx_call *rxcall,
867 struct VldbUpdateEntry *updateentry, /* Update entry copied here */
868 afs_int32 releasetype)
870 struct ubik_trans *trans;
871 afs_int32 blockindex, errorcode;
872 struct nvlentry tentry;
874 COUNT_REQ(VLUPDATEENTRYBYNAME);
875 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
877 if (releasetype && InvalidReleasetype(releasetype))
878 END(VL_BADRELLOCKTYPE);
879 if ((errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
882 blockindex = FindByName(trans, volname, &tentry, &errorcode);
883 if (blockindex == 0) { /* entry not found */
885 errorcode = VL_NOENT;
889 /* Do the actual updating of the entry, tentry. */
891 get_vldbupdateentry(trans, blockindex, updateentry, &tentry))) {
895 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
896 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
899 END(ubik_EndTrans(trans));
903 ubik_AbortTrans(trans);
906 osi_auditU(rxcall, VLUpdateEntryEvent, errorcode, AUD_LONG, -1, AUD_END);
911 /* Set a lock to the vldb entry for volid (of type voltype if not -1). */
913 SVL_SetLock(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype,
916 afs_int32 timestamp, blockindex, errorcode;
917 struct ubik_trans *trans;
918 struct nvlentry tentry;
920 COUNT_REQ(VLSETLOCK);
921 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
923 if ((voltype != -1) && (InvalidVoltype(voltype)))
925 if (InvalidOperation(voloper))
927 if ((errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
930 VLog(1, ("SetLock Volume %u %s\n", volid, rxinfo(rxcall)));
931 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
932 if (blockindex == NULLO) {
934 errorcode = VL_NOENT;
937 if (tentry.flags & VLDELETED) {
938 ABORT(VL_ENTDELETED);
940 timestamp = FT_ApproxTime();
942 /* Check if entry is already locked; note that we unlock any entry
943 * locked more than MAXLOCKTIME seconds */
944 if ((tentry.LockTimestamp)
945 && ((timestamp - tentry.LockTimestamp) < MAXLOCKTIME)) {
946 ABORT(VL_ENTRYLOCKED);
949 /* Consider it an unlocked entry: set current timestamp, caller
950 * and active vol operation */
951 tentry.LockTimestamp = timestamp;
952 tentry.LockAfsId = 0; /* Not implemented yet */
953 if (tentry.flags & VLOP_RELEASE) {
956 tentry.flags &= ~VLOP_ALLOPERS; /* Clear any possible older operation bit */
957 tentry.flags |= voloper;
959 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
962 END(ubik_EndTrans(trans));
966 ubik_AbortTrans(trans);
969 osi_auditU(rxcall, VLSetLockEvent, errorcode, AUD_LONG, volid, AUD_END);
974 /* Release an already locked vldb entry. Releasetype determines what
975 * fields (afsid and/or volume operation) will be cleared along with
976 * the lock time stamp. */
979 SVL_ReleaseLock(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype,
980 afs_int32 releasetype)
982 afs_int32 blockindex, errorcode;
983 struct ubik_trans *trans;
984 struct nvlentry tentry;
986 COUNT_REQ(VLRELEASELOCK);
987 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
989 if ((voltype != -1) && (InvalidVoltype(voltype)))
991 if (releasetype && InvalidReleasetype(releasetype))
992 END(VL_BADRELLOCKTYPE);
993 if ((errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
996 VLog(1, ("ReleaseLock Volume %u %s\n", volid, rxinfo(rxcall)));
997 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
998 if (blockindex == NULLO) {
1000 errorcode = VL_NOENT;
1003 if (tentry.flags & VLDELETED) {
1004 ABORT(VL_ENTDELETED);
1007 ReleaseEntry(&tentry, releasetype); /* Unlock the appropriate fields */
1008 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
1011 END(ubik_EndTrans(trans));
1015 ubik_AbortTrans(trans);
1018 osi_auditU(rxcall, VLReleaseLockEvent, errorcode, AUD_LONG, volid,
1024 /* ListEntry returns a single vldb entry, aentry, with offset previous_index;
1025 * the remaining parameters (i.e. next_index) are used so that sequential
1026 * calls to this routine will get the next (all) vldb entries.
1029 SVL_ListEntry(struct rx_call *rxcall, afs_int32 previous_index,
1030 afs_int32 *count, afs_int32 *next_index,
1031 struct vldbentry *aentry)
1034 struct ubik_trans *trans;
1035 struct nvlentry tentry;
1037 COUNT_REQ(VLLISTENTRY);
1038 if ((errorcode = Init_VLdbase(&trans, LOCKREAD, this_op)))
1040 VLog(25, ("OListEntry index=%d %s\n", previous_index, rxinfo(rxcall)));
1041 *next_index = NextEntry(trans, previous_index, &tentry, count);
1043 vlentry_to_vldbentry(&tentry, aentry);
1044 return (ubik_EndTrans(trans));
1047 /* ListEntry returns a single vldb entry, aentry, with offset previous_index;
1048 * the remaining parameters (i.e. next_index) are used so that sequential
1049 * calls to this routine will get the next (all) vldb entries.
1052 SVL_ListEntryN(struct rx_call *rxcall, afs_int32 previous_index,
1053 afs_int32 *count, afs_int32 *next_index,
1054 struct nvldbentry *aentry)
1057 struct ubik_trans *trans;
1058 struct nvlentry tentry;
1060 COUNT_REQ(VLLISTENTRYN);
1061 if ((errorcode = Init_VLdbase(&trans, LOCKREAD, this_op)))
1063 VLog(25, ("ListEntry index=%d %s\n", previous_index, rxinfo(rxcall)));
1064 *next_index = NextEntry(trans, previous_index, &tentry, count);
1066 vlentry_to_nvldbentry(&tentry, aentry);
1067 return (ubik_EndTrans(trans));
1071 /* Retrieves in vldbentries all vldb entries that match the specified
1072 * attributes (by server number, partition, volume type, and flag); if volume
1073 * id is specified then the associated list for that entry is returned.
1074 * CAUTION: This could be a very expensive call since in most cases
1075 * sequential search of all vldb entries is performed.
1078 SVL_ListAttributes(struct rx_call *rxcall,
1079 struct VldbListByAttributes *attributes,
1080 afs_int32 *nentries,
1081 bulkentries *vldbentries)
1083 int errorcode, allocCount = 0;
1084 struct ubik_trans *trans;
1085 struct nvlentry tentry;
1086 struct vldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1089 COUNT_REQ(VLLISTATTRIBUTES);
1090 vldbentries->bulkentries_val = 0;
1091 vldbentries->bulkentries_len = *nentries = 0;
1092 if ((errorcode = Init_VLdbase(&trans, LOCKREAD, this_op)))
1094 allocCount = VLDBALLOCCOUNT;
1095 Vldbentry = VldbentryFirst = vldbentries->bulkentries_val =
1096 (vldbentry *) malloc(allocCount * sizeof(vldbentry));
1097 if (Vldbentry == NULL) {
1099 ubik_AbortTrans(trans);
1102 VldbentryLast = VldbentryFirst + allocCount;
1103 /* Handle the attribute by volume id totally separate of the rest
1104 * (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!) */
1105 if (attributes->Mask & VLLIST_VOLUMEID) {
1106 afs_int32 blockindex;
1109 FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1110 if (blockindex == 0) {
1112 errorcode = VL_NOENT;
1114 ubik_AbortTrans(trans);
1115 if (vldbentries->bulkentries_val)
1116 free((char *)vldbentries->bulkentries_val);
1117 vldbentries->bulkentries_val = 0;
1118 vldbentries->bulkentries_len = 0;
1122 put_attributeentry(&Vldbentry, &VldbentryFirst, &VldbentryLast,
1123 vldbentries, &tentry, nentries, &allocCount))) {
1125 ubik_AbortTrans(trans);
1126 if (vldbentries->bulkentries_val)
1127 free((char *)vldbentries->bulkentries_val);
1128 vldbentries->bulkentries_val = 0;
1129 vldbentries->bulkentries_len = 0;
1130 return VL_SIZEEXCEEDED;
1133 afs_int32 nextblockindex = 0, count = 0, k = 0, match = 0;
1134 while ((nextblockindex =
1135 NextEntry(trans, nextblockindex, &tentry, &count))) {
1136 if (++pollcount > 50) {
1137 #ifndef AFS_PTHREAD_ENV
1143 if (attributes->Mask & VLLIST_SERVER) {
1146 IpAddrToRelAddr(attributes->server, NULL)) == -1)
1148 for (k = 0; k < OMAXNSERVERS; k++) {
1149 if (tentry.serverNumber[k] == BADSERVERID)
1151 if (tentry.serverNumber[k] == serverindex) {
1159 if (attributes->Mask & VLLIST_PARTITION) {
1161 if (tentry.serverPartition[k] != attributes->partition)
1164 for (k = 0; k < OMAXNSERVERS; k++) {
1165 if (tentry.serverNumber[k] == BADSERVERID)
1167 if (tentry.serverPartition[k] ==
1168 attributes->partition) {
1178 if (attributes->Mask & VLLIST_FLAG) {
1179 if (!(tentry.flags & attributes->flag))
1183 put_attributeentry(&Vldbentry, &VldbentryFirst,
1184 &VldbentryLast, vldbentries, &tentry,
1185 nentries, &allocCount))) {
1187 ubik_AbortTrans(trans);
1188 if (vldbentries->bulkentries_val)
1189 free((char *)vldbentries->bulkentries_val);
1190 vldbentries->bulkentries_val = 0;
1191 vldbentries->bulkentries_len = 0;
1196 if (vldbentries->bulkentries_len
1197 && (allocCount > vldbentries->bulkentries_len)) {
1199 vldbentries->bulkentries_val =
1200 (vldbentry *) realloc(vldbentries->bulkentries_val,
1201 vldbentries->bulkentries_len *
1203 if (vldbentries->bulkentries_val == NULL) {
1205 ubik_AbortTrans(trans);
1210 ("ListAttrs nentries=%d %s\n", vldbentries->bulkentries_len,
1212 return (ubik_EndTrans(trans));
1216 SVL_ListAttributesN(struct rx_call *rxcall,
1217 struct VldbListByAttributes *attributes,
1218 afs_int32 *nentries,
1219 nbulkentries *vldbentries)
1221 int errorcode, allocCount = 0;
1222 struct ubik_trans *trans;
1223 struct nvlentry tentry;
1224 struct nvldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1227 COUNT_REQ(VLLISTATTRIBUTESN);
1228 vldbentries->nbulkentries_val = 0;
1229 vldbentries->nbulkentries_len = *nentries = 0;
1230 if ((errorcode = Init_VLdbase(&trans, LOCKREAD, this_op)))
1232 allocCount = VLDBALLOCCOUNT;
1233 Vldbentry = VldbentryFirst = vldbentries->nbulkentries_val =
1234 (nvldbentry *) malloc(allocCount * sizeof(nvldbentry));
1235 if (Vldbentry == NULL) {
1237 ubik_AbortTrans(trans);
1240 VldbentryLast = VldbentryFirst + allocCount;
1241 /* Handle the attribute by volume id totally separate of the rest
1242 * (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!) */
1243 if (attributes->Mask & VLLIST_VOLUMEID) {
1244 afs_int32 blockindex;
1247 FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1248 if (blockindex == 0) {
1250 errorcode = VL_NOENT;
1252 ubik_AbortTrans(trans);
1253 if (vldbentries->nbulkentries_val)
1254 free((char *)vldbentries->nbulkentries_val);
1255 vldbentries->nbulkentries_val = 0;
1256 vldbentries->nbulkentries_len = 0;
1260 put_nattributeentry(&Vldbentry, &VldbentryFirst, &VldbentryLast,
1261 vldbentries, &tentry, 0, 0, nentries,
1264 ubik_AbortTrans(trans);
1265 if (vldbentries->nbulkentries_val)
1266 free((char *)vldbentries->nbulkentries_val);
1267 vldbentries->nbulkentries_val = 0;
1268 vldbentries->nbulkentries_len = 0;
1269 return VL_SIZEEXCEEDED;
1272 afs_int32 nextblockindex = 0, count = 0, k = 0, match = 0;
1273 while ((nextblockindex =
1274 NextEntry(trans, nextblockindex, &tentry, &count))) {
1275 if (++pollcount > 50) {
1276 #ifndef AFS_PTHREAD_ENV
1283 if (attributes->Mask & VLLIST_SERVER) {
1286 IpAddrToRelAddr(attributes->server, NULL)) == -1)
1288 for (k = 0; k < NMAXNSERVERS; k++) {
1289 if (tentry.serverNumber[k] == BADSERVERID)
1291 if (tentry.serverNumber[k] == serverindex) {
1299 if (attributes->Mask & VLLIST_PARTITION) {
1301 if (tentry.serverPartition[k] != attributes->partition)
1304 for (k = 0; k < NMAXNSERVERS; k++) {
1305 if (tentry.serverNumber[k] == BADSERVERID)
1307 if (tentry.serverPartition[k] ==
1308 attributes->partition) {
1318 if (attributes->Mask & VLLIST_FLAG) {
1319 if (!(tentry.flags & attributes->flag))
1323 put_nattributeentry(&Vldbentry, &VldbentryFirst,
1324 &VldbentryLast, vldbentries, &tentry, 0,
1325 0, nentries, &allocCount))) {
1327 ubik_AbortTrans(trans);
1328 if (vldbentries->nbulkentries_val)
1329 free((char *)vldbentries->nbulkentries_val);
1330 vldbentries->nbulkentries_val = 0;
1331 vldbentries->nbulkentries_len = 0;
1336 if (vldbentries->nbulkentries_len
1337 && (allocCount > vldbentries->nbulkentries_len)) {
1339 vldbentries->nbulkentries_val =
1340 (nvldbentry *) realloc(vldbentries->nbulkentries_val,
1341 vldbentries->nbulkentries_len *
1342 sizeof(nvldbentry));
1343 if (vldbentries->nbulkentries_val == NULL) {
1345 ubik_AbortTrans(trans);
1350 ("NListAttrs nentries=%d %s\n", vldbentries->nbulkentries_len,
1352 return (ubik_EndTrans(trans));
1357 SVL_ListAttributesN2(struct rx_call *rxcall,
1358 struct VldbListByAttributes *attributes,
1359 char *name, /* Wildcarded volume name */
1360 afs_int32 startindex,
1361 afs_int32 *nentries,
1362 nbulkentries *vldbentries,
1363 afs_int32 *nextstartindex)
1365 int errorcode = 0, maxCount = VLDBALLOCCOUNT;
1366 struct ubik_trans *trans;
1367 struct nvlentry tentry;
1368 struct nvldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1369 afs_int32 blockindex = 0, count = 0, k, match;
1370 afs_int32 matchindex = 0;
1371 int serverindex = -1; /* no server found */
1372 int findserver = 0, findpartition = 0, findflag = 0, findname = 0;
1374 int namematchRWBK, namematchRO, thismatch;
1376 char volumename[VL_MAXNAMELEN];
1377 #ifdef HAVE_POSIX_REGEX
1379 int need_regfree = 0;
1384 COUNT_REQ(VLLISTATTRIBUTESN2);
1385 vldbentries->nbulkentries_val = 0;
1386 vldbentries->nbulkentries_len = 0;
1388 *nextstartindex = -1;
1390 errorcode = Init_VLdbase(&trans, LOCKREAD, this_op);
1394 Vldbentry = VldbentryFirst = vldbentries->nbulkentries_val =
1395 (nvldbentry *) malloc(maxCount * sizeof(nvldbentry));
1396 if (Vldbentry == NULL) {
1398 ubik_AbortTrans(trans);
1402 VldbentryLast = VldbentryFirst + maxCount;
1404 /* Handle the attribute by volume id totally separate of the rest
1405 * (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!)
1407 if (attributes->Mask & VLLIST_VOLUMEID) {
1409 FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1410 if (blockindex == 0) {
1412 errorcode = VL_NOENT;
1415 put_nattributeentry(&Vldbentry, &VldbentryFirst,
1416 &VldbentryLast, vldbentries, &tentry, 0,
1417 0, nentries, &maxCount);
1423 /* Search each entry in the database and return all entries
1424 * that match the request. It checks volumename (with
1425 * wildcarding), entry flags, server, and partition.
1428 /* Get the server index for matching server address */
1429 if (attributes->Mask & VLLIST_SERVER) {
1431 IpAddrToRelAddr(attributes->server, NULL);
1432 if (serverindex == -1)
1436 findpartition = ((attributes->Mask & VLLIST_PARTITION) ? 1 : 0);
1437 findflag = ((attributes->Mask & VLLIST_FLAG) ? 1 : 0);
1438 if (name && (strcmp(name, ".*") != 0) && (strcmp(name, "") != 0)) {
1439 sprintf(volumename, "^%s$", name);
1440 #ifdef HAVE_POSIX_REGEX
1441 if (regcomp(&re, volumename, REG_NOSUB) != 0) {
1442 errorcode = VL_BADNAME;
1447 t = (char *)re_comp(volumename);
1449 errorcode = VL_BADNAME;
1456 /* Read each entry and see if it is the one we want */
1457 blockindex = startindex;
1458 while ((blockindex = NextEntry(trans, blockindex, &tentry, &count))) {
1459 if (++pollcount > 50) {
1460 #ifndef AFS_PTHREAD_ENV
1466 /* Step through each server index searching for a match.
1467 * Match to an existing RW, BK, or RO volume name (preference
1468 * is in this order). Remember which index we matched against.
1470 namematchRWBK = namematchRO = 0; /* 0->notTried; 1->match; 2->noMatch */
1474 && (tentry.serverNumber[k] != BADSERVERID)); k++) {
1475 thismatch = 0; /* does this index match */
1477 /* Match against the RW or BK volume name. Remember
1478 * results in namematchRWBK. Prefer RW over BK.
1480 if (tentry.serverFlags[k] & VLSF_RWVOL) {
1481 /* Does the name match the RW name */
1482 if (tentry.flags & VLF_RWEXISTS) {
1484 sprintf(volumename, "%s", tentry.name);
1485 #ifdef HAVE_POSIX_REGEX
1486 if (regexec(&re, volumename, 0, NULL, 0) == 0) {
1487 thismatch = VLSF_RWVOL;
1490 if (re_exec(volumename)) {
1491 thismatch = VLSF_RWVOL;
1495 thismatch = VLSF_RWVOL;
1499 /* Does the name match the BK name */
1500 if (!thismatch && (tentry.flags & VLF_BACKEXISTS)) {
1502 sprintf(volumename, "%s.backup", tentry.name);
1503 #ifdef HAVE_POSIX_REGEX
1504 if (regexec(&re, volumename, 0, NULL, 0) == 0) {
1505 thismatch = VLSF_BACKVOL;
1508 if (re_exec(volumename)) {
1509 thismatch = VLSF_BACKVOL;
1513 thismatch = VLSF_BACKVOL;
1517 namematchRWBK = (thismatch ? 1 : 2);
1520 /* Match with the RO volume name. Compare once and
1521 * remember results in namematchRO. Note that this will
1522 * pick up entries marked NEWREPSITEs and DONTUSE.
1525 if (tentry.flags & VLF_ROEXISTS) {
1529 ((namematchRO == 1) ? VLSF_ROVOL : 0);
1531 sprintf(volumename, "%s.readonly",
1533 #ifdef HAVE_POSIX_REGEX
1534 if (regexec(&re, volumename, 0, NULL, 0) == 0) {
1535 thismatch = VLSF_ROVOL;
1538 if (re_exec(volumename))
1539 thismatch = VLSF_ROVOL;
1543 thismatch = VLSF_ROVOL;
1546 namematchRO = (thismatch ? 1 : 2);
1549 /* Is there a server match */
1550 if (thismatch && findserver
1551 && (tentry.serverNumber[k] != serverindex))
1554 /* Is there a partition match */
1555 if (thismatch && findpartition
1556 && (tentry.serverPartition[k] != attributes->partition))
1559 /* Is there a flag match */
1560 if (thismatch && findflag
1561 && !(tentry.flags & attributes->flag))
1564 /* We found a match. Remember the index, and type */
1568 matchtype = thismatch;
1571 /* Since we prefer RW and BK volume matches over RO matches,
1572 * if we have already checked the RWBK name, then we already
1573 * found the best match and so end the search.
1575 * If we tried matching against the RW, BK, and RO volume names
1576 * and both failed, then we end the search (none will match).
1578 if ((match && namematchRWBK)
1579 || ((namematchRWBK == 2) && (namematchRO == 2)))
1583 /* Passed all the tests. Take it */
1586 put_nattributeentry(&Vldbentry, &VldbentryFirst,
1587 &VldbentryLast, vldbentries, &tentry,
1588 matchtype, matchindex, nentries,
1593 if (*nentries >= maxCount)
1594 break; /* collected the max */
1597 *nextstartindex = (blockindex ? blockindex : -1);
1601 #ifdef HAVE_POSIX_REGEX
1608 ubik_AbortTrans(trans);
1609 if (vldbentries->nbulkentries_val)
1610 free((char *)vldbentries->nbulkentries_val);
1611 vldbentries->nbulkentries_val = 0;
1612 vldbentries->nbulkentries_len = 0;
1613 *nextstartindex = -1;
1617 ("N2ListAttrs nentries=%d %s\n", vldbentries->nbulkentries_len,
1619 return (ubik_EndTrans(trans));
1624 /* Retrieves in vldbentries all vldb entries that match the specified
1625 * attributes (by server number, partition, volume type, and flag); if
1626 * volume id is specified then the associated list for that entry is
1627 * returned. CAUTION: This could be a very expensive call since in most
1628 * cases sequential search of all vldb entries is performed.
1631 SVL_LinkedList(struct rx_call *rxcall,
1632 struct VldbListByAttributes *attributes,
1633 afs_int32 *nentries,
1634 vldb_list *vldbentries)
1637 struct ubik_trans *trans;
1638 struct nvlentry tentry;
1639 vldblist vllist, *vllistptr;
1640 afs_int32 blockindex, count, match;
1645 COUNT_REQ(VLLINKEDLIST);
1646 if ((errorcode = Init_VLdbase(&trans, LOCKREAD, this_op)))
1650 vldbentries->node = NULL;
1651 vllistptr = &vldbentries->node;
1653 /* List by volumeid */
1654 if (attributes->Mask & VLLIST_VOLUMEID) {
1656 FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1659 ubik_AbortTrans(trans);
1660 return (errorcode ? errorcode : VL_NOENT);
1663 vllist = (single_vldbentry *) malloc(sizeof(single_vldbentry));
1664 if (vllist == NULL) {
1666 ubik_AbortTrans(trans);
1669 vlentry_to_vldbentry(&tentry, &vllist->VldbEntry);
1670 vllist->next_vldb = NULL;
1672 *vllistptr = vllist; /* Thread onto list */
1673 vllistptr = &vllist->next_vldb;
1677 /* Search by server, partition, and flags */
1679 for (blockindex = NextEntry(trans, 0, &tentry, &count); blockindex;
1680 blockindex = NextEntry(trans, blockindex, &tentry, &count)) {
1683 if (++pollcount > 50) {
1684 #ifndef AFS_PTHREAD_ENV
1690 /* Does this volume exist on the desired server */
1691 if (attributes->Mask & VLLIST_SERVER) {
1693 IpAddrToRelAddr(attributes->server, NULL);
1694 if (serverindex == -1)
1696 for (k = 0; k < OMAXNSERVERS; k++) {
1697 if (tentry.serverNumber[k] == BADSERVERID)
1699 if (tentry.serverNumber[k] == serverindex) {
1708 /* Does this volume exist on the desired partition */
1709 if (attributes->Mask & VLLIST_PARTITION) {
1711 if (tentry.serverPartition[k] != attributes->partition)
1714 for (k = 0; k < OMAXNSERVERS; k++) {
1715 if (tentry.serverNumber[k] == BADSERVERID)
1717 if (tentry.serverPartition[k] ==
1718 attributes->partition) {
1728 /* Does this volume have the desired flags */
1729 if (attributes->Mask & VLLIST_FLAG) {
1730 if (!(tentry.flags & attributes->flag))
1734 vllist = (single_vldbentry *) malloc(sizeof(single_vldbentry));
1735 if (vllist == NULL) {
1737 ubik_AbortTrans(trans);
1740 vlentry_to_vldbentry(&tentry, &vllist->VldbEntry);
1741 vllist->next_vldb = NULL;
1743 *vllistptr = vllist; /* Thread onto list */
1744 vllistptr = &vllist->next_vldb;
1746 if (smallMem && (*nentries >= VLDBALLOCCOUNT)) {
1748 ubik_AbortTrans(trans);
1749 return VL_SIZEEXCEEDED;
1754 return (ubik_EndTrans(trans));
1758 SVL_LinkedListN(struct rx_call *rxcall,
1759 struct VldbListByAttributes *attributes,
1760 afs_int32 *nentries,
1761 nvldb_list *vldbentries)
1764 struct ubik_trans *trans;
1765 struct nvlentry tentry;
1766 nvldblist vllist, *vllistptr;
1767 afs_int32 blockindex, count, match;
1772 COUNT_REQ(VLLINKEDLISTN);
1773 if ((errorcode = Init_VLdbase(&trans, LOCKREAD, this_op)))
1777 vldbentries->node = NULL;
1778 vllistptr = &vldbentries->node;
1780 /* List by volumeid */
1781 if (attributes->Mask & VLLIST_VOLUMEID) {
1783 FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1786 ubik_AbortTrans(trans);
1787 return (errorcode ? errorcode : VL_NOENT);
1790 vllist = (single_nvldbentry *) malloc(sizeof(single_nvldbentry));
1791 if (vllist == NULL) {
1793 ubik_AbortTrans(trans);
1796 vlentry_to_nvldbentry(&tentry, &vllist->VldbEntry);
1797 vllist->next_vldb = NULL;
1799 *vllistptr = vllist; /* Thread onto list */
1800 vllistptr = &vllist->next_vldb;
1804 /* Search by server, partition, and flags */
1806 for (blockindex = NextEntry(trans, 0, &tentry, &count); blockindex;
1807 blockindex = NextEntry(trans, blockindex, &tentry, &count)) {
1810 if (++pollcount > 50) {
1811 #ifndef AFS_PTHREAD_ENV
1817 /* Does this volume exist on the desired server */
1818 if (attributes->Mask & VLLIST_SERVER) {
1820 IpAddrToRelAddr(attributes->server, NULL);
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,
1885 * totalentries, etc) and dynamic statistics (number of requests and/or
1886 * aborts per remote procedure call, etc)
1889 SVL_GetStats(struct rx_call *rxcall,
1891 vital_vlheader *vital_header)
1893 register afs_int32 errorcode;
1894 struct ubik_trans *trans;
1896 COUNT_REQ(VLGETSTATS);
1898 /* Allow users to get statistics freely */
1899 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) /* Must be in 'UserList' to use */
1902 if ((errorcode = Init_VLdbase(&trans, LOCKREAD, this_op)))
1904 VLog(5, ("GetStats %s\n", rxinfo(rxcall)));
1905 memcpy((char *)vital_header, (char *)&cheader.vital_header,
1906 sizeof(vital_vlheader));
1907 memcpy((char *)stats, (char *)&dynamic_statistics, sizeof(vldstats));
1908 return (ubik_EndTrans(trans));
1911 /* Get the list of file server addresses from the VLDB. Currently it's pretty
1912 * easy to do. In the future, it might require a little bit of grunging
1913 * through the VLDB, but that's life.
1916 SVL_GetAddrs(struct rx_call *rxcall,
1919 struct VLCallBack *spare3,
1920 afs_int32 *nentries,
1923 register afs_int32 errorcode;
1924 struct ubik_trans *trans;
1928 COUNT_REQ(VLGETADDRS);
1929 addrsp->bulkaddrs_len = *nentries = 0;
1930 addrsp->bulkaddrs_val = 0;
1931 memset(spare3, 0, sizeof(struct VLCallBack));
1933 if ((errorcode = Init_VLdbase(&trans, LOCKREAD, this_op)))
1936 VLog(5, ("GetAddrs\n"));
1937 addrsp->bulkaddrs_val = taddrp =
1938 (afs_uint32 *) malloc(sizeof(afs_int32) * (MAXSERVERID + 1));
1939 nservers = *nentries = addrsp->bulkaddrs_len = 0;
1943 ubik_AbortTrans(trans);
1947 for (i = 0; i <= MAXSERVERID; i++) {
1948 if ((*taddrp = ntohl(cheader.IpMappedAddr[i]))) {
1954 addrsp->bulkaddrs_len = *nentries = nservers;
1955 return (ubik_EndTrans(trans));
1958 #define PADDR(addr) VLog(0,("%d.%d.%d.%d", (addr>>24)&0xff, (addr>>16)&0xff, (addr>>8) &0xff, addr&0xff));
1961 SVL_RegisterAddrs(struct rx_call *rxcall, afsUUID *uuidp, afs_int32 spare1,
1965 struct ubik_trans *trans;
1966 int cnt, h, i, j, k, m, base, index;
1967 struct extentaddr *exp = 0, *tex;
1969 afs_uint32 addrs[VL_MAXIPADDRS_PERMH];
1971 int count, willChangeEntry, foundUuidEntry, willReplaceCnt;
1972 int WillReplaceEntry, WillChange[MAXSERVERID + 1];
1974 int ReplaceEntry = 0;
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(struct rx_call *rxcall,
2337 struct ListAddrByAttributes *attributes,
2339 afs_int32 *uniquifier,
2340 afs_int32 *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(struct vldbentry **Vldbentry,
2473 struct vldbentry **VldbentryFirst,
2474 struct vldbentry **VldbentryLast,
2475 bulkentries *vldbentries,
2476 struct nvlentry *entry,
2477 afs_int32 *nentries,
2478 afs_int32 *alloccnt)
2483 if (*Vldbentry == *VldbentryLast) {
2485 return VL_SIZEEXCEEDED; /* no growing if smallMem defined */
2487 /* Allocate another set of memory; each time allocate twice as
2488 * many blocks as the last time. When we reach VLDBALLOCLIMIT,
2489 * then grow in increments of VLDBALLOCINCR.
2491 allo = (*alloccnt > VLDBALLOCLIMIT) ? VLDBALLOCINCR : *alloccnt;
2493 (vldbentry *) realloc(*VldbentryFirst,
2494 (*alloccnt + allo) * sizeof(vldbentry));
2498 *VldbentryFirst = vldbentries->bulkentries_val = reall;
2499 *Vldbentry = *VldbentryFirst + *alloccnt;
2500 *VldbentryLast = *Vldbentry + allo;
2503 vlentry_to_vldbentry(entry, *Vldbentry);
2506 vldbentries->bulkentries_len++;
2511 put_nattributeentry(struct nvldbentry **Vldbentry,
2512 struct nvldbentry **VldbentryFirst,
2513 struct nvldbentry **VldbentryLast,
2514 nbulkentries *vldbentries,
2515 struct nvlentry *entry,
2516 afs_int32 matchtype,
2517 afs_int32 matchindex,
2518 afs_int32 *nentries,
2519 afs_int32 *alloccnt)
2524 if (*Vldbentry == *VldbentryLast) {
2526 return VL_SIZEEXCEEDED; /* no growing if smallMem defined */
2528 /* Allocate another set of memory; each time allocate twice as
2529 * many blocks as the last time. When we reach VLDBALLOCLIMIT,
2530 * then grow in increments of VLDBALLOCINCR.
2532 allo = (*alloccnt > VLDBALLOCLIMIT) ? VLDBALLOCINCR : *alloccnt;
2534 (nvldbentry *) realloc(*VldbentryFirst,
2535 (*alloccnt + allo) * sizeof(nvldbentry));
2539 *VldbentryFirst = vldbentries->nbulkentries_val = reall;
2540 *Vldbentry = *VldbentryFirst + *alloccnt;
2541 *VldbentryLast = *Vldbentry + allo;
2544 vlentry_to_nvldbentry(entry, *Vldbentry);
2545 (*Vldbentry)->matchindex = (matchtype << 16) + matchindex;
2548 vldbentries->nbulkentries_len++;
2553 /* Common code to actually remove a vldb entry from the database. */
2555 RemoveEntry(struct ubik_trans *trans, afs_int32 entryptr,
2556 struct nvlentry *tentry)
2558 register int errorcode;
2560 if ((errorcode = UnthreadVLentry(trans, entryptr, tentry)))
2562 if ((errorcode = FreeBlock(trans, entryptr)))
2568 ReleaseEntry(struct nvlentry *tentry, 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
2582 check_vldbentry(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(struct nvldbentry *aentry)
2608 if (InvalidVolname(aentry->name))
2610 if (aentry->nServers <= 0 || aentry->nServers > NMAXNSERVERS)
2611 return VL_BADSERVER;
2612 for (i = 0; i < aentry->nServers; i++) {
2613 /* if (aentry->serverNumber[i] < 0 || aentry->serverNumber[i] > MAXSERVERID)
2614 return VL_BADSERVER; */
2615 if (aentry->serverPartition[i] < 0
2616 || aentry->serverPartition[i] > MAXPARTITIONID)
2617 return VL_BADPARTITION;
2618 if (aentry->serverFlags[i] < 0
2619 || aentry->serverFlags[i] > MAXSERVERFLAG)
2620 return VL_BADSERVERFLAG;
2626 /* Convert from the external vldb entry representation to its internal
2627 (more compact) form. This call should not change the hash chains! */
2629 vldbentry_to_vlentry(struct ubik_trans *atrans,
2630 struct vldbentry *VldbEntry,
2631 struct nvlentry *VlEntry)
2635 if (strcmp(VlEntry->name, VldbEntry->name))
2636 strncpy(VlEntry->name, VldbEntry->name, sizeof(VlEntry->name));
2637 for (i = 0; i < VldbEntry->nServers; i++) {
2638 serverindex = IpAddrToRelAddr(VldbEntry->serverNumber[i], atrans);
2639 if (serverindex == -1)
2640 return VL_BADSERVER;
2641 VlEntry->serverNumber[i] = serverindex;
2642 VlEntry->serverPartition[i] = VldbEntry->serverPartition[i];
2643 VlEntry->serverFlags[i] = VldbEntry->serverFlags[i];
2645 for (; i < OMAXNSERVERS; i++)
2646 VlEntry->serverNumber[i] = VlEntry->serverPartition[i] =
2647 VlEntry->serverFlags[i] = BADSERVERID;
2648 for (i = 0; i < MAXTYPES; i++)
2649 VlEntry->volumeId[i] = VldbEntry->volumeId[i];
2650 VlEntry->cloneId = VldbEntry->cloneId;
2651 VlEntry->flags = VldbEntry->flags;
2656 nvldbentry_to_vlentry(struct ubik_trans *atrans,
2657 struct nvldbentry *VldbEntry,
2658 struct nvlentry *VlEntry)
2662 if (strcmp(VlEntry->name, VldbEntry->name))
2663 strncpy(VlEntry->name, VldbEntry->name, sizeof(VlEntry->name));
2664 for (i = 0; i < VldbEntry->nServers; i++) {
2665 serverindex = IpAddrToRelAddr(VldbEntry->serverNumber[i], atrans);
2666 if (serverindex == -1)
2667 return VL_BADSERVER;
2668 VlEntry->serverNumber[i] = serverindex;
2669 VlEntry->serverPartition[i] = VldbEntry->serverPartition[i];
2670 VlEntry->serverFlags[i] = VldbEntry->serverFlags[i];
2672 for (; i < NMAXNSERVERS; i++)
2673 VlEntry->serverNumber[i] = VlEntry->serverPartition[i] =
2674 VlEntry->serverFlags[i] = BADSERVERID;
2675 for (i = 0; i < MAXTYPES; i++)
2676 VlEntry->volumeId[i] = VldbEntry->volumeId[i];
2677 VlEntry->cloneId = VldbEntry->cloneId;
2678 VlEntry->flags = VldbEntry->flags;
2683 /* Update the vldb entry with the new fields as indicated by the value of
2684 * the Mask entry in the updateentry structure. All necessary validation
2685 * checks are performed.
2688 get_vldbupdateentry(struct ubik_trans *trans,
2689 afs_int32 blockindex,
2690 struct VldbUpdateEntry *updateentry,
2691 struct nvlentry *VlEntry)
2693 int i, j, errorcode, serverindex;
2695 if (updateentry->Mask & VLUPDATE_VOLUMENAME) {
2696 if (InvalidVolname(updateentry->name))
2698 if ((errorcode = UnhashVolname(trans, blockindex, VlEntry)))
2700 strncpy(VlEntry->name, updateentry->name, sizeof(VlEntry->name));
2701 HashVolname(trans, blockindex, VlEntry);
2704 if (updateentry->Mask & VLUPDATE_VOLNAMEHASH) {
2705 if ((errorcode = UnhashVolname(trans, blockindex, VlEntry))) {
2706 if (errorcode != VL_NOENT)
2709 HashVolname(trans, blockindex, VlEntry);
2712 if (updateentry->Mask & VLUPDATE_FLAGS) {
2713 VlEntry->flags = updateentry->flags;
2715 if (updateentry->Mask & VLUPDATE_CLONEID) {
2716 VlEntry->cloneId = updateentry->cloneId;
2718 if (updateentry->Mask & VLUPDATE_RWID) {
2719 if ((errorcode = UnhashVolid(trans, RWVOL, blockindex, VlEntry))) {
2720 if (errorcode != VL_NOENT)
2723 VlEntry->volumeId[RWVOL] = updateentry->spares3; /* rw id */
2724 if ((errorcode = HashVolid(trans, RWVOL, blockindex, VlEntry)))
2727 if (updateentry->Mask & VLUPDATE_READONLYID) {
2728 if ((errorcode = UnhashVolid(trans, ROVOL, blockindex, VlEntry))) {
2729 if (errorcode != VL_NOENT)
2732 VlEntry->volumeId[ROVOL] = updateentry->ReadOnlyId;
2733 if ((errorcode = HashVolid(trans, ROVOL, blockindex, VlEntry)))
2736 if (updateentry->Mask & VLUPDATE_BACKUPID) {
2737 if ((errorcode = UnhashVolid(trans, BACKVOL, blockindex, VlEntry))) {
2738 if (errorcode != VL_NOENT)
2741 VlEntry->volumeId[BACKVOL] = updateentry->BackupId;
2742 if ((errorcode = HashVolid(trans, BACKVOL, blockindex, VlEntry)))
2745 if (updateentry->Mask & VLUPDATE_REPSITES) {
2746 if (updateentry->nModifiedRepsites <= 0
2747 || updateentry->nModifiedRepsites > OMAXNSERVERS)
2748 return VL_BADSERVER;
2749 for (i = 0; i < updateentry->nModifiedRepsites; i++) {
2750 /* if (updateentry->RepsitesTargetServer[i] < 0 || updateentry->RepsitesTargetServer[i] > MAXSERVERID)
2751 return VL_BADSERVER; */
2752 if (updateentry->RepsitesTargetPart[i] < 0
2753 || updateentry->RepsitesTargetPart[i] > MAXPARTITIONID)
2754 return VL_BADPARTITION;
2755 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_DELETE) {
2757 repsite_exists(VlEntry,
2758 IpAddrToRelAddr(updateentry->
2759 RepsitesTargetServer[i],
2761 updateentry->RepsitesTargetPart[i])) !=
2763 repsite_compress(VlEntry, j);
2765 return VL_NOREPSERVER;
2767 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_ADD) {
2768 /* if (updateentry->RepsitesNewServer[i] < 0 || updateentry->RepsitesNewServer[i] > MAXSERVERID)
2769 return VL_BADSERVER; */
2770 if (updateentry->RepsitesNewPart[i] < 0
2771 || updateentry->RepsitesNewPart[i] > MAXPARTITIONID)
2772 return VL_BADPARTITION;
2775 IpAddrToRelAddr(updateentry->RepsitesNewServer[i],
2777 updateentry->RepsitesNewPart[i]) != -1)
2778 return VL_DUPREPSERVER;
2780 VlEntry->serverNumber[j] != BADSERVERID
2781 && j < OMAXNSERVERS; j++);
2782 if (j >= OMAXNSERVERS)
2785 IpAddrToRelAddr(updateentry->RepsitesNewServer[i],
2787 return VL_BADSERVER;
2788 VlEntry->serverNumber[j] = serverindex;
2789 VlEntry->serverPartition[j] = updateentry->RepsitesNewPart[i];
2790 if (updateentry->RepsitesNewFlags[i] < 0
2791 || updateentry->RepsitesNewFlags[i] > MAXSERVERFLAG)
2792 return VL_BADSERVERFLAG;
2793 VlEntry->serverFlags[j] = updateentry->RepsitesNewFlags[i];
2795 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODSERV) {
2796 /*n if (updateentry->RepsitesNewServer[i] < 0 || updateentry->RepsitesNewServer[i] > MAXSERVERID)
2797 return VL_BADSERVER; */
2799 repsite_exists(VlEntry,
2800 IpAddrToRelAddr(updateentry->
2801 RepsitesTargetServer[i],
2803 updateentry->RepsitesTargetPart[i])) !=
2805 VlEntry->serverNumber[j] =
2806 IpAddrToRelAddr(updateentry->RepsitesNewServer[i],
2809 return VL_NOREPSERVER;
2811 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODPART) {
2812 if (updateentry->RepsitesNewPart[i] < 0
2813 || updateentry->RepsitesNewPart[i] > MAXPARTITIONID)
2814 return VL_BADPARTITION;
2816 repsite_exists(VlEntry,
2817 IpAddrToRelAddr(updateentry->
2818 RepsitesTargetServer[i],
2820 updateentry->RepsitesTargetPart[i])) !=
2822 VlEntry->serverPartition[j] =
2823 updateentry->RepsitesNewPart[i];
2825 return VL_NOREPSERVER;
2827 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODFLAG) {
2829 repsite_exists(VlEntry,
2830 IpAddrToRelAddr(updateentry->
2831 RepsitesTargetServer[i],
2833 updateentry->RepsitesTargetPart[i])) !=
2835 if (updateentry->RepsitesNewFlags[i] < 0
2836 || updateentry->RepsitesNewFlags[i] > MAXSERVERFLAG)
2837 return VL_BADSERVERFLAG;
2838 VlEntry->serverFlags[j] =
2839 updateentry->RepsitesNewFlags[i];
2841 return VL_NOREPSERVER;
2849 /* Check if the specified [server,partition] entry is found in the vldb
2850 * entry's repsite table; it's offset in the table is returned, if it's
2853 repsite_exists(struct nvlentry *VlEntry, int server, int partition)
2857 for (i = 0; VlEntry->serverNumber[i] != BADSERVERID && i < OMAXNSERVERS;
2859 if ((VlEntry->serverNumber[i] == server)
2860 && (VlEntry->serverPartition[i] == partition))
2868 /* Repsite table compression: used when deleting a repsite entry so that
2869 * all active repsite entries are on the top of the table. */
2871 repsite_compress(struct nvlentry *VlEntry, int offset)
2873 int repsite_offset = offset;
2875 VlEntry->serverNumber[repsite_offset] != BADSERVERID
2876 && repsite_offset < OMAXNSERVERS - 1; repsite_offset++) {
2877 VlEntry->serverNumber[repsite_offset] =
2878 VlEntry->serverNumber[repsite_offset + 1];
2879 VlEntry->serverPartition[repsite_offset] =
2880 VlEntry->serverPartition[repsite_offset + 1];
2881 VlEntry->serverFlags[repsite_offset] =
2882 VlEntry->serverFlags[repsite_offset + 1];
2884 VlEntry->serverNumber[repsite_offset] = BADSERVERID;
2888 /* Convert from the internal (compacted) vldb entry to the external
2889 * representation used by the interface. */
2891 vlentry_to_vldbentry(struct nvlentry *VlEntry, struct vldbentry *VldbEntry)
2895 memset(VldbEntry, 0, sizeof(struct vldbentry));
2896 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
2897 for (i = 0; i < OMAXNSERVERS; i++) {
2898 if (VlEntry->serverNumber[i] == BADSERVERID)
2900 if ((HostAddress[j = VlEntry->serverNumber[i]] & 0xff000000) ==
2902 struct extentaddr *exp;
2905 base = (HostAddress[j] >> 16) & 0xff;
2906 index = HostAddress[j] & 0x0000ffff;
2907 exp = &ex_addr[base][index];
2908 /* For now return the first ip address back */
2909 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2910 if (exp->ex_addrs[j]) {
2911 VldbEntry->serverNumber[i] = ntohl(exp->ex_addrs[j]);
2916 VldbEntry->serverNumber[i] =
2917 HostAddress[VlEntry->serverNumber[i]];
2918 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
2919 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
2921 VldbEntry->nServers = i;
2922 for (i = 0; i < MAXTYPES; i++)
2923 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
2924 VldbEntry->cloneId = VlEntry->cloneId;
2925 VldbEntry->flags = VlEntry->flags;
2929 /* Convert from the internal (compacted) vldb entry to the external
2930 * representation used by the interface. */
2932 vlentry_to_nvldbentry(struct nvlentry *VlEntry, struct nvldbentry *VldbEntry)
2936 memset(VldbEntry, 0, sizeof(struct vldbentry));
2937 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
2938 for (i = 0; i < NMAXNSERVERS; i++) {
2939 if (VlEntry->serverNumber[i] == BADSERVERID)
2941 if ((HostAddress[j = VlEntry->serverNumber[i]] & 0xff000000) ==
2943 struct extentaddr *exp;
2946 base = (HostAddress[j] >> 16) & 0xff;
2947 index = HostAddress[j] & 0x0000ffff;
2948 exp = &ex_addr[base][index];
2949 /* For now return the first ip address back */
2950 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2951 if (exp->ex_addrs[j]) {
2952 VldbEntry->serverNumber[i] = ntohl(exp->ex_addrs[j]);
2957 VldbEntry->serverNumber[i] =
2958 HostAddress[VlEntry->serverNumber[i]];
2959 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
2960 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
2962 VldbEntry->nServers = i;
2963 for (i = 0; i < MAXTYPES; i++)
2964 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
2965 VldbEntry->cloneId = VlEntry->cloneId;
2966 VldbEntry->flags = VlEntry->flags;
2970 vlentry_to_uvldbentry(struct nvlentry *VlEntry, struct uvldbentry *VldbEntry)
2974 memset(VldbEntry, 0, sizeof(struct vldbentry));
2975 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
2976 for (i = 0; i < NMAXNSERVERS; i++) {
2977 if (VlEntry->serverNumber[i] == BADSERVERID)
2979 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
2980 VldbEntry->serverUnique[i] = 0;
2981 if ((HostAddress[j = VlEntry->serverNumber[i]] & 0xff000000) ==
2983 struct extentaddr *exp;
2987 base = (HostAddress[j] >> 16) & 0xff;
2988 index = HostAddress[j] & 0x0000ffff;
2989 exp = &ex_addr[base][index];
2990 tuuid = exp->ex_hostuuid;
2991 afs_ntohuuid(&tuuid);
2992 VldbEntry->serverFlags[i] |= VLSERVER_FLAG_UUID;
2993 VldbEntry->serverNumber[i] = tuuid;
2994 VldbEntry->serverUnique[i] = ntohl(exp->ex_uniquifier);
2996 VldbEntry->serverNumber[i].time_low =
2997 HostAddress[VlEntry->serverNumber[i]];
2999 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
3002 VldbEntry->nServers = i;
3003 for (i = 0; i < MAXTYPES; i++)
3004 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
3005 VldbEntry->cloneId = VlEntry->cloneId;
3006 VldbEntry->flags = VlEntry->flags;
3009 #define LEGALCHARS ".ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
3012 /* Verify that the volname is a valid volume name. */
3014 InvalidVolname(char *volname)
3020 slen = strlen(volname);
3021 if (slen >= VL_MAXNAMELEN)
3023 return (slen != strspn(volname, map));
3027 /* Verify that the given volume type is valid. */
3029 InvalidVoltype(afs_int32 voltype)
3031 if (voltype != RWVOL && voltype != ROVOL && voltype != BACKVOL)
3038 InvalidOperation(afs_int32 voloper)
3040 if (voloper != VLOP_MOVE && voloper != VLOP_RELEASE
3041 && voloper != VLOP_BACKUP && voloper != VLOP_DELETE
3042 && voloper != VLOP_DUMP)
3048 InvalidReleasetype(afs_int32 releasetype)
3050 if ((releasetype & LOCKREL_TIMESTAMP) || (releasetype & LOCKREL_OPCODE)
3051 || (releasetype & LOCKREL_AFSID))
3057 IpAddrToRelAddr(register afs_uint32 ipaddr, struct ubik_trans *atrans)
3060 register afs_int32 code, base, index;
3061 struct extentaddr *exp;
3063 for (i = 0; i <= MAXSERVERID; i++) {
3064 if (HostAddress[i] == ipaddr)
3066 if ((HostAddress[i] & 0xff000000) == 0xff000000) {
3067 base = (HostAddress[i] >> 16) & 0xff;
3068 index = HostAddress[i] & 0x0000ffff;
3069 if (base >= VL_MAX_ADDREXTBLKS) {
3071 ("Internal error: Multihome extent base is too large. Base %d index %d\n",
3073 return -1; /* EINVAL */
3075 if (index >= VL_MHSRV_PERBLK) {
3077 ("Internal error: Multihome extent index is too large. Base %d index %d\n",
3079 return -1; /* EINVAL */
3081 if (!ex_addr[base]) {
3083 ("Internal error: Multihome extent does not exist. Base %d\n",
3085 return -1; /* EINVAL */
3087 exp = &ex_addr[base][index];
3088 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
3089 if (exp->ex_addrs[j] && (ntohl(exp->ex_addrs[j]) == ipaddr)) {
3096 /* allocate the new server a server id pronto */
3098 for (i = 0; i <= MAXSERVERID; i++) {
3099 if (cheader.IpMappedAddr[i] == 0) {
3100 cheader.IpMappedAddr[i] = htonl(ipaddr);
3103 DOFFSET(0, &cheader, &cheader.IpMappedAddr[i]),
3104 (char *)&cheader.IpMappedAddr[i],
3106 HostAddress[i] = ipaddr;
3117 ChangeIPAddr(afs_uint32 ipaddr1, afs_uint32 ipaddr2, struct ubik_trans *atrans)
3121 struct extentaddr *exp = NULL;
3125 afs_int32 blockindex, count;
3127 struct nvlentry tentry;
3130 return VL_CREATEFAIL;
3132 /* Don't let addr change to 256.*.*.* : Causes internal error below */
3133 if ((ipaddr2 & 0xff000000) == 0xff000000)
3134 return (VL_BADSERVER);
3136 /* If we are removing an address, ip1 will be -1 and ip2 will be
3137 * the original address. This prevents an older revision vlserver
3138 * from removing the IP address (won't find server 0xfffffff in
3139 * the VLDB). An older revision vlserver does not have the check
3140 * to see if any volumes exist on the server being removed.
3142 if (ipaddr1 == 0xffffffff) {
3147 for (i = 0; i <= MAXSERVERID; i++) {
3148 if ((HostAddress[i] & 0xff000000) == 0xff000000) {
3149 base = (HostAddress[i] >> 16) & 0xff;
3150 index = HostAddress[i] & 0x0000ffff;
3151 if ((base >= VL_MAX_ADDREXTBLKS) || (index >= VL_MHSRV_PERBLK)) {
3153 ("Internal error: Multihome extent addr is too large. Base %d index %d\n",
3155 return -1; /* EINVAL */
3158 exp = &ex_addr[base][index];
3159 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
3160 if (!exp->ex_addrs[mhidx])
3162 if (ntohl(exp->ex_addrs[mhidx]) == ipaddr1)
3165 if (mhidx < VL_MAXIPADDRS_PERMH) {
3168 } else if (HostAddress[i] == ipaddr1) {
3174 if (i >= MAXSERVERID) {
3175 return VL_NOENT; /* not found */
3178 /* If we are removing a server entry, a volume cannot
3179 * exist on the server. If one does, don't remove the
3180 * server entry: return error "volume entry exists".
3183 for (blockindex = NextEntry(atrans, 0, &tentry, &count); blockindex;
3184 blockindex = NextEntry(atrans, blockindex, &tentry, &count)) {
3185 if (++pollcount > 50) {
3186 #ifndef AFS_PTHREAD_ENV
3191 for (j = 0; j < NMAXNSERVERS; j++) {
3192 if (tentry.serverNumber[j] == BADSERVERID)
3194 if (tentry.serverNumber[j] == i) {
3201 /* Log a message saying we are changing/removing an IP address */
3203 ("The following IP address is being %s:\n",
3204 (ipaddr2 ? "changed" : "removed")));
3205 VLog(0, (" entry %d: ", i));
3208 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
3209 if (!exp->ex_addrs[mhidx])
3213 PADDR(ntohl(exp->ex_addrs[mhidx]));
3225 /* Change the registered uuuid addresses */
3227 memset(&tuuid, 0, sizeof(afsUUID));
3228 afs_htonuuid(&tuuid);
3229 exp->ex_hostuuid = tuuid;
3232 DOFFSET(ntohl(ex_addr[0]->ex_contaddrs[base]),
3233 (char *)ex_addr[base], (char *)exp),
3234 (char *)&tuuid, sizeof(tuuid));
3239 /* Now change the host address entry */
3240 cheader.IpMappedAddr[i] = htonl(ipaddr2);
3242 vlwrite(atrans, DOFFSET(0, &cheader, &cheader.IpMappedAddr[i]),
3244 &cheader.IpMappedAddr[i], sizeof(afs_int32));
3245 HostAddress[i] = ipaddr2;
3252 /* see if the vlserver is back yet */
3254 SVL_ProbeServer(struct rx_call *rxcall)