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>
20 #include <afs/afsutil.h>
27 #include <netinet/in.h>
31 #include "afs/audit.h"
35 #ifdef HAVE_POSIX_REGEX /* use POSIX regexp library */
41 extern struct afsconf_dir *vldb_confdir;
42 extern struct ubik_dbase *VL_dbase;
43 struct vlheader cheader; /* kept in network byte order */
44 extern afs_uint32 HostAddress[]; /* host addresses kept in host byte order */
46 struct extentaddr *ex_addr[VL_MAX_ADDREXTBLKS] = { 0, 0, 0, 0 };
47 static char rxinfo_str[128]; /* Need rxinfo string to be non-local */
48 #define ABORT(c) { errorcode = (c); goto abort; }
50 #define END(c) { errorcode = (c); goto end; }
52 #define VLDBALLOCLIMIT 10000
53 #define VLDBALLOCINCR 2048
55 static int put_attributeentry();
56 static int put_nattributeentry();
57 static int RemoveEntry();
58 static void ReleaseEntry();
59 static int check_vldbentry();
60 static int check_nvldbentry();
61 static int vldbentry_to_vlentry();
62 static int nvldbentry_to_vlentry();
63 static get_vldbupdateentry();
64 static int repsite_exists();
65 static void repsite_compress();
66 static void vlentry_to_vldbentry();
67 static void vlentry_to_nvldbentry();
68 static void vlentry_to_uvldbentry();
69 static int InvalidVolname();
70 static int InvalidVoltype();
71 static int InvalidOperation();
72 static int InvalidReleasetype();
73 static int IpAddrToRelAddr();
74 static int ChangeIPAddr();
78 struct rx_call *rxcall;
81 register struct rx_connection *tconn;
86 struct in_addr hostAddr;
88 tconn = rx_ConnectionOf(rxcall);
89 hostAddr.s_addr = rx_HostOf(rx_PeerOf(tconn));
91 rxkad_GetServerInfo(rxcall->conn, NULL, &exp, tname, tinst, tcell,
94 sprintf(rxinfo_str, "%s %s%s%s%s%s", inet_ntoa(hostAddr), tname,
95 tinst?".":"", tinst?tinst:"", tcell?"@":"", tcell?tcell:"");
97 sprintf(rxinfo_str, "%s noauth", inet_ntoa(hostAddr));
101 /* This is called to initialize the database, set the appropriate locks and make sure that the vldb header is valid */
103 Init_VLdbase(trans, locktype, this_op)
104 struct ubik_trans **trans;
105 int locktype; /* indicate read or write transaction */
108 int errorcode = 0, pass, wl;
110 for (pass = 1; pass <= 3; pass++) {
111 if (pass == 2) { /* take write lock to rebuild the db */
112 errorcode = ubik_BeginTrans(VL_dbase, UBIK_WRITETRANS, trans);
114 } else if (locktype == LOCKREAD) {
116 ubik_BeginTransReadAny(VL_dbase, UBIK_READTRANS, trans);
119 errorcode = ubik_BeginTrans(VL_dbase, UBIK_WRITETRANS, trans);
125 errorcode = ubik_SetLock(*trans, 1, 1, locktype);
128 ubik_AbortTrans(*trans);
132 /* check that dbase is initialized and setup cheader */
133 /* 2nd pass we try to rebuild the header */
134 errorcode = CheckInit(*trans, ((pass == 2) ? 1 : 0));
135 if (!errorcode && wl && extent_mod)
136 errorcode = readExtents(*trans); /* Fix the mh extent blocks */
139 ubik_AbortTrans(*trans);
140 /* Only rebuld if the database is empty */
141 /* Exit if can't rebuild */
142 if ((pass == 1) && (errorcode != VL_EMPTY))
146 } else { /* No errorcode */
148 ubik_EndTrans(*trans); /* Rebuilt db. End trans, then retake original lock */
150 break; /* didn't rebuild and successful - exit */
158 /* Create a new vldb entry; both new volume id and name must be unique (non-existant in vldb). */
161 SVL_CreateEntry(rxcall, newentry)
162 struct rx_call *rxcall;
163 struct vldbentry *newentry;
165 struct ubik_trans *trans;
166 afs_int32 errorcode, blockindex;
167 struct nvlentry tentry;
169 COUNT_REQ(VLCREATEENTRY);
170 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) {
175 /* Do some validity tests on new entry */
176 if ((errorcode = check_vldbentry(newentry))
177 || (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
181 ("OCreate Volume %d %s\n", newentry->volumeId[RWVOL],
183 /* XXX shouldn't we check to see if the r/o volume is duplicated? */
184 if (newentry->volumeId[RWVOL]
185 && FindByID(trans, newentry->volumeId[RWVOL], RWVOL, &tentry, &errorcode)) { /* entry already exists, we fail */
186 errorcode = VL_IDEXIST;
188 } else if (errorcode) {
192 /* Is this following check (by volume name) necessary?? */
193 /* If entry already exists, we fail */
194 if (FindByName(trans, newentry->name, &tentry, &errorcode)) {
195 errorcode = VL_NAMEEXIST;
197 } else if (errorcode) {
201 blockindex = AllocBlock(trans, &tentry);
202 if (blockindex == 0) {
203 errorcode = VL_CREATEFAIL;
207 memset(&tentry, 0, sizeof(struct nvlentry));
208 /* Convert to its internal representation; both in host byte order */
209 if (errorcode = vldbentry_to_vlentry(trans, newentry, &tentry)) {
210 FreeBlock(trans, blockindex);
214 /* Actually insert the entry in vldb */
215 errorcode = ThreadVLentry(trans, blockindex, &tentry);
217 FreeBlock(trans, blockindex);
220 errorcode = ubik_EndTrans(trans);
226 ubik_AbortTrans(trans);
229 osi_auditU(rxcall, VLCreateEntryEvent, errorcode, AUD_STR,
230 (newentry ? newentry->name : NULL), AUD_END);
236 SVL_CreateEntryN(rxcall, newentry)
237 struct rx_call *rxcall;
238 struct nvldbentry *newentry;
240 struct ubik_trans *trans;
241 afs_int32 errorcode, blockindex;
242 struct nvlentry tentry;
244 COUNT_REQ(VLCREATEENTRYN);
245 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) {
250 /* Do some validity tests on new entry */
251 if ((errorcode = check_nvldbentry(newentry))
252 || (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
256 ("Create Volume %d %s\n", newentry->volumeId[RWVOL],
258 /* XXX shouldn't we check to see if the r/o volume is duplicated? */
259 if (newentry->volumeId[RWVOL]
260 && FindByID(trans, newentry->volumeId[RWVOL], RWVOL, &tentry, &errorcode)) { /* entry already exists, we fail */
261 errorcode = VL_IDEXIST;
263 } else if (errorcode) {
267 /* Is this following check (by volume name) necessary?? */
268 /* If entry already exists, we fail */
269 if (FindByName(trans, newentry->name, &tentry, &errorcode)) {
270 errorcode = VL_NAMEEXIST;
272 } else if (errorcode) {
276 blockindex = AllocBlock(trans, &tentry);
277 if (blockindex == 0) {
278 errorcode = VL_CREATEFAIL;
282 memset(&tentry, 0, sizeof(struct nvlentry));
283 /* Convert to its internal representation; both in host byte order */
284 if (errorcode = nvldbentry_to_vlentry(trans, newentry, &tentry)) {
285 FreeBlock(trans, blockindex);
289 /* Actually insert the entry in vldb */
290 errorcode = ThreadVLentry(trans, blockindex, &tentry);
292 FreeBlock(trans, blockindex);
295 errorcode = ubik_EndTrans(trans);
301 ubik_AbortTrans(trans);
304 osi_auditU(rxcall, VLCreateEntryEvent, errorcode, AUD_STR,
305 (newentry ? newentry->name : NULL), AUD_END);
311 SVL_ChangeAddr(rxcall, ip1, ip2)
312 struct rx_call *rxcall;
315 struct ubik_trans *trans;
318 COUNT_REQ(VLCHANGEADDR);
319 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) {
324 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
327 VLog(1, ("Change Addr %u -> %u %s\n", ip1, ip2, rxinfo(rxcall)));
328 if (errorcode = ChangeIPAddr(ip1, ip2, trans))
331 errorcode = ubik_EndTrans(trans);
337 ubik_AbortTrans(trans);
340 osi_auditU(rxcall, VLChangeAddrEvent, errorcode, AUD_LONG, ip1, AUD_LONG,
345 /* Delete a vldb entry given the volume id. */
347 SVL_DeleteEntry(rxcall, volid, voltype)
348 struct rx_call *rxcall;
352 struct ubik_trans *trans;
353 afs_int32 blockindex, errorcode;
354 struct nvlentry tentry;
356 COUNT_REQ(VLDELETEENTRY);
357 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
360 if ((voltype != -1) && (InvalidVoltype(voltype)))
363 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
366 VLog(1, ("Delete Volume %u %s\n", volid, rxinfo(rxcall)));
367 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
368 if (blockindex == 0) { /* volid not found */
370 errorcode = VL_NOENT;
374 if (tentry.flags & VLDELETED) { /* Already deleted; return */
375 ABORT(VL_ENTDELETED);
377 if (errorcode = RemoveEntry(trans, blockindex, &tentry)) {
380 errorcode = (ubik_EndTrans(trans));
385 ubik_AbortTrans(trans);
388 osi_auditU(rxcall, VLDeleteEntryEvent, errorcode, AUD_LONG, volid,
394 /* Get a vldb entry given its volume id; make sure it's not a deleted entry. */
395 GetEntryByID(rxcall, volid, voltype, aentry, new, this_op)
396 struct rx_call *rxcall;
398 afs_int32 voltype, new, this_op;
399 char *aentry; /* entry data copied here */
401 struct ubik_trans *trans;
402 afs_int32 blockindex, errorcode;
403 struct nvlentry tentry;
405 if ((voltype != -1) && (InvalidVoltype(voltype)))
406 return VL_BADVOLTYPE;
407 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
410 VLog(5, ("GetVolumeByID %u (%d) %s\n", volid, new, rxinfo(rxcall)));
411 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
412 if (blockindex == 0) { /* entry not found */
414 errorcode = VL_NOENT;
416 ubik_AbortTrans(trans);
419 if (tentry.flags & VLDELETED) { /* Entry is deleted! */
421 ubik_AbortTrans(trans);
422 return VL_ENTDELETED;
424 /* Convert from the internal to external form */
426 vlentry_to_nvldbentry(&tentry, (struct nvldbentry *)aentry);
428 vlentry_to_uvldbentry(&tentry, (struct uvldbentry *)aentry);
430 vlentry_to_vldbentry(&tentry, (struct vldbentry *)aentry);
431 return (ubik_EndTrans(trans));
435 SVL_GetEntryByID(rxcall, volid, voltype, aentry)
436 struct rx_call *rxcall;
439 vldbentry *aentry; /* entry data copied here */
441 COUNT_REQ(VLGETENTRYBYID);
442 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 0, this_op));
446 SVL_GetEntryByIDN(rxcall, volid, voltype, aentry)
447 struct rx_call *rxcall;
450 nvldbentry *aentry; /* entry data copied here */
452 COUNT_REQ(VLGETENTRYBYIDN);
453 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 1, this_op));
457 SVL_GetEntryByIDU(rxcall, volid, voltype, aentry)
458 struct rx_call *rxcall;
461 uvldbentry *aentry; /* entry data copied here */
463 COUNT_REQ(VLGETENTRYBYIDU);
464 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 2, this_op));
469 /* returns true if the id is a decimal integer, in which case we interpret it
470 as an id. make the cache manager much simpler */
473 register char *aname;
476 while (tc = *aname++) {
477 if (tc > '9' || tc < '0')
483 /* Get a vldb entry given the volume's name; of course, very similar to VLGetEntryByID() above. */
484 GetEntryByName(rxcall, volname, aentry, new, this_op)
485 struct rx_call *rxcall;
487 char *aentry; /* entry data copied here */
490 struct ubik_trans *trans;
491 afs_int32 blockindex, errorcode;
492 struct nvlentry tentry;
494 if (NameIsId(volname)) {
495 return GetEntryByID(rxcall, atoi(volname), -1, aentry, new, this_op);
497 if (InvalidVolname(volname))
499 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
501 VLog(5, ("GetVolumeByName %s (%d) %s\n", volname, new, rxinfo(rxcall)));
502 blockindex = FindByName(trans, volname, &tentry, &errorcode);
503 if (blockindex == 0) { /* entry not found */
505 errorcode = VL_NOENT;
507 ubik_AbortTrans(trans);
510 if (tentry.flags & VLDELETED) { /* Entry is deleted */
512 ubik_AbortTrans(trans);
513 return VL_ENTDELETED;
515 /* Convert to external entry representation */
517 vlentry_to_nvldbentry(&tentry, (struct nvldbentry *)aentry);
519 vlentry_to_uvldbentry(&tentry, (struct uvldbentry *)aentry);
521 vlentry_to_vldbentry(&tentry, (struct vldbentry *)aentry);
522 return (ubik_EndTrans(trans));
526 SVL_GetEntryByNameO(rxcall, volname, aentry)
527 struct rx_call *rxcall;
529 struct vldbentry *aentry; /* entry data copied here */
531 COUNT_REQ(VLGETENTRYBYNAME);
532 return (GetEntryByName(rxcall, volname, (char *)aentry, 0, this_op));
537 SVL_GetEntryByNameN(rxcall, volname, aentry)
538 struct rx_call *rxcall;
540 struct nvldbentry *aentry; /* entry data copied here */
542 COUNT_REQ(VLGETENTRYBYNAMEN);
543 return (GetEntryByName(rxcall, volname, (char *)aentry, 1, this_op));
547 SVL_GetEntryByNameU(rxcall, volname, aentry)
548 struct rx_call *rxcall;
550 struct uvldbentry *aentry; /* entry data copied here */
552 COUNT_REQ(VLGETENTRYBYNAMEU);
553 return (GetEntryByName(rxcall, volname, (char *)aentry, 2, this_op));
558 /* Get the current value of the maximum volume id and bump the volume id counter by Maxvolidbump. */
560 SVL_GetNewVolumeId(rxcall, Maxvolidbump, newvolumeid)
561 struct rx_call *rxcall;
562 afs_uint32 Maxvolidbump;
563 afs_uint32 *newvolumeid;
565 register afs_int32 errorcode;
566 afs_uint32 maxvolumeid;
567 struct ubik_trans *trans;
569 COUNT_REQ(VLGETNEWVOLUMEID);
570 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
573 if (Maxvolidbump < 0 || Maxvolidbump > MAXBUMPCOUNT)
574 END(VL_BADVOLIDBUMP);
576 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
579 *newvolumeid = maxvolumeid = ntohl(cheader.vital_header.MaxVolumeId);
580 maxvolumeid += Maxvolidbump;
581 VLog(1, ("GetNewVolid newmax=%u %s\n", maxvolumeid, rxinfo(rxcall)));
582 cheader.vital_header.MaxVolumeId = htonl(maxvolumeid);
583 if (write_vital_vlheader(trans)) {
586 errorcode = (ubik_EndTrans(trans));
591 ubik_AbortTrans(trans);
594 osi_auditU(rxcall, VLGetNewVolumeIdEvent, errorcode, AUD_END);
599 /* Simple replace the contents of the vldb entry, volid, with
600 * newentry. No individual checking/updating per field (alike
601 * VLUpdateEntry) is done. */
604 SVL_ReplaceEntry(rxcall, volid, voltype, newentry, releasetype)
605 struct rx_call *rxcall;
608 struct vldbentry *newentry;
609 afs_int32 releasetype;
611 struct ubik_trans *trans;
612 afs_int32 blockindex, errorcode, typeindex;
614 int hashVol[MAXTYPES];
615 struct nvlentry tentry;
617 COUNT_REQ(VLREPLACEENTRY);
618 for (typeindex = 0; typeindex < MAXTYPES; typeindex++)
619 hashVol[typeindex] = 0;
621 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
624 if (errorcode = check_vldbentry(newentry))
627 if (voltype != -1 && InvalidVoltype(voltype))
630 if (releasetype && InvalidReleasetype(releasetype))
631 END(VL_BADRELLOCKTYPE);
632 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
635 VLog(1, ("OReplace Volume %u %s\n", volid, rxinfo(rxcall)));
636 /* find vlentry we're changing */
637 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
638 if (blockindex == 0) { /* entry not found */
640 errorcode = VL_NOENT;
644 /* check that we're not trying to change the RW vol ID */
645 if (newentry->volumeId[RWVOL] != tentry.volumeId[RWVOL]) {
649 /* unhash volid entries if they're disappearing or changing.
650 * Remember if we need to hash in the new value (we don't have to
651 * rehash if volid stays same */
652 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
653 if (tentry.volumeId[typeindex] != newentry->volumeId[typeindex]) {
654 if (tentry.volumeId[typeindex])
656 UnhashVolid(trans, typeindex, blockindex, &tentry)) {
659 /* we must rehash new id if the id is different and the ID is nonzero */
660 hashVol[typeindex] = 1; /* must rehash this guy if he exists */
664 /* Rehash volname if it changes */
665 if (strcmp(newentry->name, tentry.name)) { /* Name changes; redo hashing */
666 if (errorcode = UnhashVolname(trans, blockindex, &tentry)) {
672 /* after this, tentry is new entry, not old one. vldbentry_to_vlentry
673 * doesn't touch hash chains */
674 if (errorcode = vldbentry_to_vlentry(trans, newentry, &tentry)) {
678 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
679 if (hashVol[typeindex] && tentry.volumeId[typeindex]) {
680 if (errorcode = HashVolid(trans, typeindex, blockindex, &tentry)) {
687 HashVolname(trans, blockindex, &tentry);
690 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
691 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
695 END(ubik_EndTrans(trans));
699 ubik_AbortTrans(trans);
702 osi_auditU(rxcall, VLReplaceVLEntryEvent, errorcode, AUD_LONG, volid,
708 SVL_ReplaceEntryN(rxcall, volid, voltype, newentry, releasetype)
709 struct rx_call *rxcall;
712 struct nvldbentry *newentry;
713 afs_int32 releasetype;
715 struct ubik_trans *trans;
716 afs_int32 blockindex, errorcode, typeindex;
718 int hashVol[MAXTYPES];
719 struct nvlentry tentry;
721 COUNT_REQ(VLREPLACEENTRYN);
722 for (typeindex = 0; typeindex < MAXTYPES; typeindex++)
723 hashVol[typeindex] = 0;
725 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
728 if (errorcode = check_nvldbentry(newentry))
731 if (voltype != -1 && InvalidVoltype(voltype))
734 if (releasetype && InvalidReleasetype(releasetype))
735 END(VL_BADRELLOCKTYPE);
736 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
739 VLog(1, ("Replace Volume %u %s\n", volid, rxinfo(rxcall)));
740 /* find vlentry we're changing */
741 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
742 if (blockindex == 0) { /* entry not found */
744 errorcode = VL_NOENT;
748 /* check that we're not trying to change the RW vol ID */
749 if (newentry->volumeId[RWVOL] != tentry.volumeId[RWVOL]) {
753 /* unhash volid entries if they're disappearing or changing.
754 * Remember if we need to hash in the new value (we don't have to
755 * rehash if volid stays same */
756 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
757 if (tentry.volumeId[typeindex] != newentry->volumeId[typeindex]) {
758 if (tentry.volumeId[typeindex])
760 UnhashVolid(trans, typeindex, blockindex, &tentry)) {
763 /* we must rehash new id if the id is different and the ID is nonzero */
764 hashVol[typeindex] = 1; /* must rehash this guy if he exists */
768 /* Rehash volname if it changes */
769 if (strcmp(newentry->name, tentry.name)) { /* Name changes; redo hashing */
770 if (errorcode = UnhashVolname(trans, blockindex, &tentry)) {
776 /* after this, tentry is new entry, not old one. vldbentry_to_vlentry
777 * doesn't touch hash chains */
778 if (errorcode = nvldbentry_to_vlentry(trans, newentry, &tentry)) {
782 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
783 if (hashVol[typeindex] && tentry.volumeId[typeindex]) {
784 if (errorcode = HashVolid(trans, typeindex, blockindex, &tentry)) {
791 HashVolname(trans, blockindex, &tentry);
794 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
795 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
799 END(ubik_EndTrans(trans));
803 ubik_AbortTrans(trans);
806 osi_auditU(rxcall, VLReplaceVLEntryEvent, errorcode, AUD_LONG, volid,
812 /* 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. */
813 /* this routine may never have been tested; use replace entry instead unless you're brave */
815 SVL_UpdateEntry(rxcall, volid, voltype, updateentry, releasetype)
816 struct rx_call *rxcall;
819 afs_int32 releasetype;
820 struct VldbUpdateEntry *updateentry; /* Update entry copied here */
822 struct ubik_trans *trans;
823 afs_int32 blockindex, errorcode;
824 struct nvlentry tentry;
826 COUNT_REQ(VLUPDATEENTRY);
827 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
829 if ((voltype != -1) && (InvalidVoltype(voltype)))
831 if (releasetype && InvalidReleasetype(releasetype))
832 END(VL_BADRELLOCKTYPE);
833 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
836 VLog(1, ("Update Volume %u %s\n", volid, rxinfo(rxcall)));
837 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
838 if (blockindex == 0) { /* entry not found */
840 errorcode = VL_NOENT;
844 /* Do the actual updating of the entry, tentry. */
846 get_vldbupdateentry(trans, blockindex, updateentry, &tentry)) {
850 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
851 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
854 END(ubik_EndTrans(trans));
858 ubik_AbortTrans(trans);
861 osi_auditU(rxcall, VLUpdateEntryEvent, errorcode, AUD_LONG, volid,
868 SVL_UpdateEntryByName(rxcall, volname, updateentry, releasetype)
869 struct rx_call *rxcall;
871 afs_int32 releasetype;
872 struct VldbUpdateEntry *updateentry; /* Update entry copied here */
874 struct ubik_trans *trans;
875 afs_int32 blockindex, errorcode;
876 struct nvlentry tentry;
878 COUNT_REQ(VLUPDATEENTRYBYNAME);
879 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
881 if (releasetype && InvalidReleasetype(releasetype))
882 END(VL_BADRELLOCKTYPE);
883 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
886 blockindex = FindByName(trans, volname, &tentry, &errorcode);
887 if (blockindex == 0) { /* entry not found */
889 errorcode = VL_NOENT;
893 /* Do the actual updating of the entry, tentry. */
895 get_vldbupdateentry(trans, blockindex, updateentry, &tentry)) {
899 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
900 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
903 END(ubik_EndTrans(trans));
907 ubik_AbortTrans(trans);
910 osi_auditU(rxcall, VLUpdateEntryEvent, errorcode, AUD_LONG, -1, AUD_END);
915 /* Set a lock to the vldb entry for volid (of type voltype if not -1). */
917 SVL_SetLock(rxcall, volid, voltype, voloper)
918 struct rx_call *rxcall;
923 afs_int32 timestamp, blockindex, errorcode;
924 struct ubik_trans *trans;
925 struct nvlentry tentry;
927 COUNT_REQ(VLSETLOCK);
928 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
930 if ((voltype != -1) && (InvalidVoltype(voltype)))
932 if (InvalidOperation(voloper))
934 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
937 VLog(1, ("SetLock Volume %u %s\n", volid, rxinfo(rxcall)));
938 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
939 if (blockindex == NULLO) {
941 errorcode = VL_NOENT;
944 if (tentry.flags & VLDELETED) {
945 ABORT(VL_ENTDELETED);
947 timestamp = FT_ApproxTime();
949 /* Check if entry is already locked; note that we unlock any entry
950 * locked more than MAXLOCKTIME seconds */
951 if ((tentry.LockTimestamp)
952 && ((timestamp - tentry.LockTimestamp) < MAXLOCKTIME)) {
953 ABORT(VL_ENTRYLOCKED);
956 /* Consider it an unlocked entry: set current timestamp, caller
957 * and active vol operation */
958 tentry.LockTimestamp = timestamp;
959 tentry.LockAfsId = 0; /* Not implemented yet */
960 if (tentry.flags & VLOP_RELEASE) {
963 tentry.flags &= ~VLOP_ALLOPERS; /* Clear any possible older operation bit */
964 tentry.flags |= voloper;
966 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
969 END(ubik_EndTrans(trans));
973 ubik_AbortTrans(trans);
976 osi_auditU(rxcall, VLSetLockEvent, errorcode, AUD_LONG, volid, AUD_END);
981 /* Release an already locked vldb entry. Releasetype determines what
982 * fields (afsid and/or volume operation) will be cleared along with
983 * the lock time stamp. */
986 SVL_ReleaseLock(rxcall, volid, voltype, releasetype)
987 struct rx_call *rxcall;
990 afs_int32 releasetype;
992 afs_int32 blockindex, errorcode;
993 struct ubik_trans *trans;
994 struct nvlentry tentry;
996 COUNT_REQ(VLRELEASELOCK);
997 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
999 if ((voltype != -1) && (InvalidVoltype(voltype)))
1001 if (releasetype && InvalidReleasetype(releasetype))
1002 END(VL_BADRELLOCKTYPE);
1003 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
1006 VLog(1, ("ReleaseLock Volume %u %s\n", volid, rxinfo(rxcall)));
1007 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
1008 if (blockindex == NULLO) {
1010 errorcode = VL_NOENT;
1013 if (tentry.flags & VLDELETED) {
1014 ABORT(VL_ENTDELETED);
1017 ReleaseEntry(&tentry, releasetype); /* Unlock the appropriate fields */
1018 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
1021 END(ubik_EndTrans(trans));
1025 ubik_AbortTrans(trans);
1028 osi_auditU(rxcall, VLReleaseLockEvent, errorcode, AUD_LONG, volid,
1034 /* 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. */
1036 SVL_ListEntry(rxcall, previous_index, count, next_index, aentry)
1037 struct rx_call *rxcall;
1038 afs_int32 previous_index;
1040 afs_int32 *next_index;
1041 struct vldbentry *aentry;
1044 struct ubik_trans *trans;
1045 struct nvlentry tentry;
1047 COUNT_REQ(VLLISTENTRY);
1048 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1050 VLog(25, ("OListEntry index=%d %s\n", previous_index, rxinfo(rxcall)));
1051 *next_index = NextEntry(trans, previous_index, &tentry, count);
1053 vlentry_to_vldbentry(&tentry, aentry);
1054 return (ubik_EndTrans(trans));
1057 /* 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. */
1059 SVL_ListEntryN(rxcall, previous_index, count, next_index, aentry)
1060 struct rx_call *rxcall;
1061 afs_int32 previous_index;
1063 afs_int32 *next_index;
1064 struct nvldbentry *aentry;
1067 struct ubik_trans *trans;
1068 struct nvlentry tentry;
1070 COUNT_REQ(VLLISTENTRYN);
1071 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1073 VLog(25, ("ListEntry index=%d %s\n", previous_index, rxinfo(rxcall)));
1074 *next_index = NextEntry(trans, previous_index, &tentry, count);
1076 vlentry_to_nvldbentry(&tentry, aentry);
1077 return (ubik_EndTrans(trans));
1081 /* 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. */
1083 SVL_ListAttributes(rxcall, attributes, nentries, vldbentries)
1084 struct rx_call *rxcall;
1085 struct VldbListByAttributes *attributes;
1086 afs_int32 *nentries;
1087 bulkentries *vldbentries;
1089 int errorcode, allocCount = 0;
1090 struct ubik_trans *trans;
1091 struct nvlentry tentry;
1092 struct vldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1095 COUNT_REQ(VLLISTATTRIBUTES);
1096 vldbentries->bulkentries_val = 0;
1097 vldbentries->bulkentries_len = *nentries = 0;
1098 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1100 allocCount = VLDBALLOCCOUNT;
1101 Vldbentry = VldbentryFirst = vldbentries->bulkentries_val =
1102 (vldbentry *) malloc(allocCount * sizeof(vldbentry));
1103 if (Vldbentry == NULL) {
1105 ubik_AbortTrans(trans);
1108 VldbentryLast = VldbentryFirst + allocCount;
1109 /* Handle the attribute by volume id totally separate of the rest (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!) */
1110 if (attributes->Mask & VLLIST_VOLUMEID) {
1111 afs_int32 blockindex;
1114 FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1115 if (blockindex == 0) {
1117 errorcode = VL_NOENT;
1119 ubik_AbortTrans(trans);
1120 if (vldbentries->bulkentries_val)
1121 free((char *)vldbentries->bulkentries_val);
1122 vldbentries->bulkentries_val = 0;
1123 vldbentries->bulkentries_len = 0;
1127 put_attributeentry(&Vldbentry, &VldbentryFirst, &VldbentryLast,
1128 vldbentries, &tentry, nentries, &allocCount)) {
1130 ubik_AbortTrans(trans);
1131 if (vldbentries->bulkentries_val)
1132 free((char *)vldbentries->bulkentries_val);
1133 vldbentries->bulkentries_val = 0;
1134 vldbentries->bulkentries_len = 0;
1135 return VL_SIZEEXCEEDED;
1138 afs_int32 nextblockindex = 0, count = 0, k = 0, match = 0;
1139 while (nextblockindex =
1140 NextEntry(trans, nextblockindex, &tentry, &count)) {
1141 if (++pollcount > 50) {
1142 #ifndef AFS_PTHREAD_ENV
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 = 0, match = 0;
1279 while (nextblockindex =
1280 NextEntry(trans, nextblockindex, &tentry, &count)) {
1281 if (++pollcount > 50) {
1282 #ifndef AFS_PTHREAD_ENV
1289 if (attributes->Mask & VLLIST_SERVER) {
1292 IpAddrToRelAddr(attributes->server,
1293 (struct ubik_trans *)0)) == -1)
1295 for (k = 0; k < NMAXNSERVERS; k++) {
1296 if (tentry.serverNumber[k] == BADSERVERID)
1298 if (tentry.serverNumber[k] == serverindex) {
1306 if (attributes->Mask & VLLIST_PARTITION) {
1308 if (tentry.serverPartition[k] != attributes->partition)
1311 for (k = 0; k < NMAXNSERVERS; k++) {
1312 if (tentry.serverNumber[k] == BADSERVERID)
1314 if (tentry.serverPartition[k] ==
1315 attributes->partition) {
1325 if (attributes->Mask & VLLIST_FLAG) {
1326 if (!(tentry.flags & attributes->flag))
1330 put_nattributeentry(&Vldbentry, &VldbentryFirst,
1331 &VldbentryLast, vldbentries, &tentry, 0,
1332 0, nentries, &allocCount)) {
1334 ubik_AbortTrans(trans);
1335 if (vldbentries->nbulkentries_val)
1336 free((char *)vldbentries->nbulkentries_val);
1337 vldbentries->nbulkentries_val = 0;
1338 vldbentries->nbulkentries_len = 0;
1343 if (vldbentries->nbulkentries_len
1344 && (allocCount > vldbentries->nbulkentries_len)) {
1346 vldbentries->nbulkentries_val =
1347 (nvldbentry *) realloc(vldbentries->nbulkentries_val,
1348 vldbentries->nbulkentries_len *
1349 sizeof(nvldbentry));
1350 if (vldbentries->nbulkentries_val == NULL) {
1352 ubik_AbortTrans(trans);
1357 ("NListAttrs nentries=%d %s\n", vldbentries->nbulkentries_len,
1359 return (ubik_EndTrans(trans));
1364 SVL_ListAttributesN2(rxcall, attributes, name, startindex, nentries,
1365 vldbentries, nextstartindex)
1366 struct rx_call *rxcall;
1367 struct VldbListByAttributes *attributes;
1368 char *name; /* Wildcarded volume name */
1369 afs_int32 startindex;
1370 afs_int32 *nentries;
1371 nbulkentries *vldbentries;
1372 afs_int32 *nextstartindex;
1374 int errorcode = 0, maxCount = VLDBALLOCCOUNT;
1375 struct ubik_trans *trans;
1376 struct nvlentry tentry;
1377 struct nvldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1378 afs_int32 blockindex = 0, count = 0, k, match;
1379 afs_int32 matchindex = 0;
1380 int serverindex = -1; /* no server found */
1381 int findserver = 0, findpartition = 0, findflag = 0, findname = 0;
1384 int namematchRWBK, namematchRO, thismatch;
1386 char volumename[VL_MAXNAMELEN];
1387 #ifdef HAVE_POSIX_REGEX
1389 int need_regfree = 0;
1392 COUNT_REQ(VLLISTATTRIBUTESN2);
1393 vldbentries->nbulkentries_val = 0;
1394 vldbentries->nbulkentries_len = 0;
1396 *nextstartindex = -1;
1398 errorcode = Init_VLdbase(&trans, LOCKREAD, this_op);
1402 Vldbentry = VldbentryFirst = vldbentries->nbulkentries_val =
1403 (nvldbentry *) malloc(maxCount * sizeof(nvldbentry));
1404 if (Vldbentry == NULL) {
1406 ubik_AbortTrans(trans);
1410 VldbentryLast = VldbentryFirst + maxCount;
1412 /* Handle the attribute by volume id totally separate of the rest
1413 * (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!)
1415 if (attributes->Mask & VLLIST_VOLUMEID) {
1417 FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1418 if (blockindex == 0) {
1420 errorcode = VL_NOENT;
1423 put_nattributeentry(&Vldbentry, &VldbentryFirst,
1424 &VldbentryLast, vldbentries, &tentry, 0,
1425 0, nentries, &maxCount);
1431 /* Search each entry in the database and return all entries
1432 * that match the request. It checks volumename (with
1433 * wildcarding), entry flags, server, and partition.
1436 /* Get the server index for matching server address */
1437 if (attributes->Mask & VLLIST_SERVER) {
1439 IpAddrToRelAddr(attributes->server, (struct ubik_trans *)0);
1440 if (serverindex == -1)
1444 findpartition = ((attributes->Mask & VLLIST_PARTITION) ? 1 : 0);
1445 findflag = ((attributes->Mask & VLLIST_FLAG) ? 1 : 0);
1446 if (name && (strcmp(name, ".*") != 0) && (strcmp(name, "") != 0)) {
1447 sprintf(volumename, "^%s$", name);
1448 #ifdef HAVE_POSIX_REGEX
1449 if (regcomp(&re, volumename, REG_NOSUB) != 0) {
1450 errorcode = VL_BADNAME;
1455 t = (char *)re_comp(volumename);
1457 errorcode = VL_BADNAME;
1464 /* Read each entry and see if it is the one we want */
1465 blockindex = startindex;
1466 while (blockindex = NextEntry(trans, blockindex, &tentry, &count)) {
1467 if (++pollcount > 50) {
1468 #ifndef AFS_PTHREAD_ENV
1474 /* Step through each server index searching for a match.
1475 * Match to an existing RW, BK, or RO volume name (preference
1476 * is in this order). Remember which index we matched against.
1478 namematchRWBK = namematchRO = 0; /* 0->notTried; 1->match; 2->noMatch */
1482 && (tentry.serverNumber[k] != BADSERVERID)); k++) {
1483 thismatch = 0; /* does this index match */
1485 /* Match against the RW or BK volume name. Remember
1486 * results in namematchRWBK. Prefer RW over BK.
1488 if (tentry.serverFlags[k] & VLSF_RWVOL) {
1489 /* Does the name match the RW name */
1490 if (tentry.flags & VLF_RWEXISTS) {
1492 sprintf(volumename, "%s", tentry.name);
1493 #ifdef HAVE_POSIX_REGEX
1494 if (regexec(&re, volumename, 0, NULL, 0) == 0) {
1495 thismatch = VLSF_RWVOL;
1498 if (re_exec(volumename)) {
1499 thismatch = VLSF_RWVOL;
1503 thismatch = VLSF_RWVOL;
1507 /* Does the name match the BK name */
1508 if (!thismatch && (tentry.flags & VLF_BACKEXISTS)) {
1510 sprintf(volumename, "%s.backup", tentry.name);
1511 #ifdef HAVE_POSIX_REGEX
1512 if (regexec(&re, volumename, 0, NULL, 0) == 0) {
1513 thismatch = VLSF_BACKVOL;
1516 if (re_exec(volumename)) {
1517 thismatch = VLSF_BACKVOL;
1521 thismatch = VLSF_BACKVOL;
1525 namematchRWBK = (thismatch ? 1 : 2);
1528 /* Match with the RO volume name. Compare once and
1529 * remember results in namematchRO. Note that this will
1530 * pick up entries marked NEWREPSITEs and DONTUSE.
1533 if (tentry.flags & VLF_ROEXISTS) {
1537 ((namematchRO == 1) ? VLSF_ROVOL : 0);
1539 sprintf(volumename, "%s.readonly",
1541 #ifdef HAVE_POSIX_REGEX
1542 if (regexec(&re, volumename, 0, NULL, 0) == 0) {
1543 thismatch = VLSF_ROVOL;
1546 if (re_exec(volumename))
1547 thismatch = VLSF_ROVOL;
1551 thismatch = VLSF_ROVOL;
1554 namematchRO = (thismatch ? 1 : 2);
1557 /* Is there a server match */
1558 if (thismatch && findserver
1559 && (tentry.serverNumber[k] != serverindex))
1562 /* Is there a partition match */
1563 if (thismatch && findpartition
1564 && (tentry.serverPartition[k] != attributes->partition))
1567 /* Is there a flag match */
1568 if (thismatch && findflag
1569 && !(tentry.flags & attributes->flag))
1572 /* We found a match. Remember the index, and type */
1576 matchtype = thismatch;
1579 /* Since we prefer RW and BK volume matches over RO matches,
1580 * if we have already checked the RWBK name, then we already
1581 * found the best match and so end the search.
1583 * If we tried matching against the RW, BK, and RO volume names
1584 * and both failed, then we end the search (none will match).
1586 if ((match && namematchRWBK)
1587 || ((namematchRWBK == 2) && (namematchRO == 2)))
1591 /* Passed all the tests. Take it */
1594 put_nattributeentry(&Vldbentry, &VldbentryFirst,
1595 &VldbentryLast, vldbentries, &tentry,
1596 matchtype, matchindex, nentries,
1601 if (*nentries >= maxCount)
1602 break; /* collected the max */
1605 *nextstartindex = (blockindex ? blockindex : -1);
1609 #ifdef HAVE_POSIX_REGEX
1616 ubik_AbortTrans(trans);
1617 if (vldbentries->nbulkentries_val)
1618 free((char *)vldbentries->nbulkentries_val);
1619 vldbentries->nbulkentries_val = 0;
1620 vldbentries->nbulkentries_len = 0;
1621 *nextstartindex = -1;
1625 ("N2ListAttrs nentries=%d %s\n", vldbentries->nbulkentries_len,
1627 return (ubik_EndTrans(trans));
1632 /* Retrieves in vldbentries all vldb entries that match the specified
1633 * attributes (by server number, partition, volume type, and flag); if
1634 * volume id is specified then the associated list for that entry is
1635 * returned. CAUTION: This could be a very expensive call since in most
1636 * cases sequential search of all vldb entries is performed.
1639 SVL_LinkedList(rxcall, attributes, nentries, vldbentries)
1640 struct rx_call *rxcall;
1641 struct VldbListByAttributes *attributes;
1642 afs_int32 *nentries;
1643 vldb_list *vldbentries;
1646 struct ubik_trans *trans;
1647 struct nvlentry tentry;
1648 vldblist vllist, *vllistptr;
1649 afs_int32 blockindex, count, match;
1654 COUNT_REQ(VLLINKEDLIST);
1655 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1659 vldbentries->node = NULL;
1660 vllistptr = &vldbentries->node;
1662 /* List by volumeid */
1663 if (attributes->Mask & VLLIST_VOLUMEID) {
1665 FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1668 ubik_AbortTrans(trans);
1669 return (errorcode ? errorcode : VL_NOENT);
1672 vllist = (single_vldbentry *) malloc(sizeof(single_vldbentry));
1673 if (vllist == NULL) {
1675 ubik_AbortTrans(trans);
1678 vlentry_to_vldbentry(&tentry, &vllist->VldbEntry);
1679 vllist->next_vldb = NULL;
1681 *vllistptr = vllist; /* Thread onto list */
1682 vllistptr = &vllist->next_vldb;
1686 /* Search by server, partition, and flags */
1688 for (blockindex = NextEntry(trans, 0, &tentry, &count); blockindex;
1689 blockindex = NextEntry(trans, blockindex, &tentry, &count)) {
1692 if (++pollcount > 50) {
1693 #ifndef AFS_PTHREAD_ENV
1699 /* Does this volume exist on the desired server */
1700 if (attributes->Mask & VLLIST_SERVER) {
1702 IpAddrToRelAddr(attributes->server,
1703 (struct ubik_trans *)0);
1704 if (serverindex == -1)
1706 for (k = 0; k < OMAXNSERVERS; k++) {
1707 if (tentry.serverNumber[k] == BADSERVERID)
1709 if (tentry.serverNumber[k] == serverindex) {
1718 /* Does this volume exist on the desired partition */
1719 if (attributes->Mask & VLLIST_PARTITION) {
1721 if (tentry.serverPartition[k] != attributes->partition)
1724 for (k = 0; k < OMAXNSERVERS; k++) {
1725 if (tentry.serverNumber[k] == BADSERVERID)
1727 if (tentry.serverPartition[k] ==
1728 attributes->partition) {
1738 /* Does this volume have the desired flags */
1739 if (attributes->Mask & VLLIST_FLAG) {
1740 if (!(tentry.flags & attributes->flag))
1744 vllist = (single_vldbentry *) malloc(sizeof(single_vldbentry));
1745 if (vllist == NULL) {
1747 ubik_AbortTrans(trans);
1750 vlentry_to_vldbentry(&tentry, &vllist->VldbEntry);
1751 vllist->next_vldb = NULL;
1753 *vllistptr = vllist; /* Thread onto list */
1754 vllistptr = &vllist->next_vldb;
1756 if (smallMem && (*nentries >= VLDBALLOCCOUNT)) {
1758 ubik_AbortTrans(trans);
1759 return VL_SIZEEXCEEDED;
1764 return (ubik_EndTrans(trans));
1768 SVL_LinkedListN(rxcall, attributes, nentries, vldbentries)
1769 struct rx_call *rxcall;
1770 struct VldbListByAttributes *attributes;
1771 afs_int32 *nentries;
1772 nvldb_list *vldbentries;
1775 struct ubik_trans *trans;
1776 struct nvlentry tentry;
1777 nvldblist vllist, *vllistptr;
1778 afs_int32 blockindex, count, match;
1783 COUNT_REQ(VLLINKEDLISTN);
1784 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1788 vldbentries->node = NULL;
1789 vllistptr = &vldbentries->node;
1791 /* List by volumeid */
1792 if (attributes->Mask & VLLIST_VOLUMEID) {
1794 FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1797 ubik_AbortTrans(trans);
1798 return (errorcode ? errorcode : VL_NOENT);
1801 vllist = (single_nvldbentry *) malloc(sizeof(single_nvldbentry));
1802 if (vllist == NULL) {
1804 ubik_AbortTrans(trans);
1807 vlentry_to_nvldbentry(&tentry, &vllist->VldbEntry);
1808 vllist->next_vldb = NULL;
1810 *vllistptr = vllist; /* Thread onto list */
1811 vllistptr = &vllist->next_vldb;
1815 /* Search by server, partition, and flags */
1817 for (blockindex = NextEntry(trans, 0, &tentry, &count); blockindex;
1818 blockindex = NextEntry(trans, blockindex, &tentry, &count)) {
1821 if (++pollcount > 50) {
1822 #ifndef AFS_PTHREAD_ENV
1828 /* Does this volume exist on the desired server */
1829 if (attributes->Mask & VLLIST_SERVER) {
1831 IpAddrToRelAddr(attributes->server,
1832 (struct ubik_trans *)0);
1833 if (serverindex == -1)
1835 for (k = 0; k < NMAXNSERVERS; k++) {
1836 if (tentry.serverNumber[k] == BADSERVERID)
1838 if (tentry.serverNumber[k] == serverindex) {
1847 /* Does this volume exist on the desired partition */
1848 if (attributes->Mask & VLLIST_PARTITION) {
1850 if (tentry.serverPartition[k] != attributes->partition)
1853 for (k = 0; k < NMAXNSERVERS; k++) {
1854 if (tentry.serverNumber[k] == BADSERVERID)
1856 if (tentry.serverPartition[k] ==
1857 attributes->partition) {
1867 /* Does this volume have the desired flags */
1868 if (attributes->Mask & VLLIST_FLAG) {
1869 if (!(tentry.flags & attributes->flag))
1873 vllist = (single_nvldbentry *) malloc(sizeof(single_nvldbentry));
1874 if (vllist == NULL) {
1876 ubik_AbortTrans(trans);
1879 vlentry_to_nvldbentry(&tentry, &vllist->VldbEntry);
1880 vllist->next_vldb = NULL;
1882 *vllistptr = vllist; /* Thread onto list */
1883 vllistptr = &vllist->next_vldb;
1885 if (smallMem && (*nentries >= VLDBALLOCCOUNT)) {
1887 ubik_AbortTrans(trans);
1888 return VL_SIZEEXCEEDED;
1893 return (ubik_EndTrans(trans));
1896 /* Get back vldb header statistics (allocs, frees, maxvolumeid, totalentries, etc) and dynamic statistics (number of requests and/or aborts per remote procedure call, etc) */
1898 SVL_GetStats(rxcall, stats, vital_header)
1899 struct rx_call *rxcall;
1901 vital_vlheader *vital_header;
1903 register afs_int32 errorcode;
1904 struct ubik_trans *trans;
1906 COUNT_REQ(VLGETSTATS);
1908 /* Allow users to get statistics freely */
1909 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) /* Must be in 'UserList' to use */
1912 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1914 VLog(5, ("GetStats %s\n", rxinfo(rxcall)));
1915 memcpy((char *)vital_header, (char *)&cheader.vital_header,
1916 sizeof(vital_vlheader));
1917 memcpy((char *)stats, (char *)&dynamic_statistics, sizeof(vldstats));
1918 return (ubik_EndTrans(trans));
1921 /* Get the list of file server addresses from the VLDB. Currently it's pretty
1922 * easy to do. In the future, it might require a little bit of grunging
1923 * through the VLDB, but that's life.
1926 SVL_GetAddrs(rxcall, Handle, spare2, spare3, nentries, addrsp)
1927 struct rx_call *rxcall;
1928 afs_int32 Handle, spare2;
1929 struct VLCallBack *spare3;
1930 afs_int32 *nentries;
1933 register afs_int32 errorcode;
1934 struct ubik_trans *trans;
1938 COUNT_REQ(VLGETADDRS);
1939 addrsp->bulkaddrs_len = *nentries = 0;
1940 addrsp->bulkaddrs_val = 0;
1941 memset(spare3, 0, sizeof(struct VLCallBack));
1943 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1946 VLog(5, ("GetAddrs\n"));
1947 addrsp->bulkaddrs_val = taddrp =
1948 (afs_uint32 *) malloc(sizeof(afs_int32) * (MAXSERVERID + 1));
1949 nservers = *nentries = addrsp->bulkaddrs_len = 0;
1953 ubik_AbortTrans(trans);
1957 for (i = 0; i <= MAXSERVERID; i++) {
1958 if (*taddrp = ntohl(cheader.IpMappedAddr[i])) {
1964 addrsp->bulkaddrs_len = *nentries = nservers;
1965 return (ubik_EndTrans(trans));
1968 #define PADDR(addr) VLog(0,("%d.%d.%d.%d", (addr>>24)&0xff, (addr>>16)&0xff, (addr>>8) &0xff, addr&0xff));
1971 SVL_RegisterAddrs(rxcall, uuidp, spare1, addrsp)
1972 struct rx_call *rxcall;
1978 struct ubik_trans *trans;
1979 int cnt, h, i, j, k, m, base, index;
1980 struct extentaddr *exp = 0, *tex;
1982 afs_uint32 addrs[VL_MAXIPADDRS_PERMH];
1984 int count, willChangeEntry, foundUuidEntry, willReplaceCnt;
1985 int WillReplaceEntry, WillChange[MAXSERVERID + 1];
1987 int ReplaceEntry = 0;
1990 COUNT_REQ(VLREGADDR);
1991 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
1993 if (code = Init_VLdbase(&trans, LOCKWRITE, this_op))
1996 /* Eliminate duplicates from IP address list */
1997 for (k = 0, cnt = 0; k < addrsp->bulkaddrs_len; k++) {
1998 if (addrsp->bulkaddrs_val[k] == 0)
2000 for (m = 0; m < cnt; m++) {
2001 if (addrs[m] == addrsp->bulkaddrs_val[k])
2005 if (m == VL_MAXIPADDRS_PERMH) {
2007 ("Number of addresses exceeds %d. Cannot register IP addr 0x%x in VLDB\n",
2008 VL_MAXIPADDRS_PERMH, addrsp->bulkaddrs_val[k]));
2010 addrs[m] = addrsp->bulkaddrs_val[k];
2016 ubik_AbortTrans(trans);
2017 return VL_INDEXERANGE;
2023 /* For each server registered within the VLDB */
2024 for (srvidx = 0; srvidx <= MAXSERVERID; srvidx++) {
2025 willChangeEntry = 0;
2026 WillReplaceEntry = 1;
2027 if ((HostAddress[srvidx] & 0xff000000) == 0xff000000) {
2028 /* The server is registered as a multihomed */
2029 base = (HostAddress[srvidx] >> 16) & 0xff;
2030 index = HostAddress[srvidx] & 0x0000ffff;
2031 if (base >= VL_MAX_ADDREXTBLKS) {
2033 ("Internal error: Multihome extent base is too large. Base %d index %d\n",
2037 if (index >= VL_MHSRV_PERBLK) {
2039 ("Internal error: Multihome extent index is too large. Base %d index %d\n",
2043 if (!ex_addr[base]) {
2045 ("Internal error: Multihome extent does not exist. Base %d\n",
2050 /* See if the addresses to register will change this server entry */
2051 exp = &ex_addr[base][index];
2052 tuuid = exp->ex_hostuuid;
2053 afs_ntohuuid(&tuuid);
2054 if (afs_uuid_equal(uuidp, &tuuid)) {
2058 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2059 if (!exp->ex_addrs[mhidx])
2061 for (k = 0; k < cnt; k++) {
2062 if (ntohl(exp->ex_addrs[mhidx]) == addrs[k]) {
2063 willChangeEntry = 1;
2064 WillChange[count] = srvidx;
2069 WillReplaceEntry = 0;
2073 /* The server is not registered as a multihomed.
2074 * See if the addresses to register will replace this server entry.
2076 for (k = 0; k < cnt; k++) {
2077 if (HostAddress[srvidx] == addrs[k]) {
2078 willChangeEntry = 1;
2079 WillChange[count] = srvidx;
2080 WillReplaceEntry = 1;
2085 if (willChangeEntry) {
2086 if (WillReplaceEntry) {
2088 ReplaceEntry = srvidx;
2094 /* If we found the uuid in the VLDB and if we are replacing another
2095 * entire entry, then complain and fail. Also, if we did not find
2096 * the uuid in the VLDB and the IP addresses being registered was
2097 * found in more than one other entry, then we don't know which one
2098 * to replace and will complain and fail.
2100 if ((foundUuidEntry && (willReplaceCnt > 0))
2101 || (!foundUuidEntry && (count > 1))) {
2103 ("The following fileserver is being registered in the VLDB:\n"));
2105 for (k = 0; k < cnt; k++) {
2112 if (foundUuidEntry) {
2114 (" It would have replaced the existing VLDB server entry:\n"));
2115 VLog(0, (" entry %d: [", FoundUuid));
2116 base = (HostAddress[FoundUuid] >> 16) & 0xff;
2117 index = HostAddress[FoundUuid] & 0x0000ffff;
2118 exp = &ex_addr[base][index];
2119 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2120 if (!exp->ex_addrs[mhidx])
2124 PADDR(ntohl(exp->ex_addrs[mhidx]));
2130 VLog(0, (" Yet another VLDB server entry exists:\n"));
2132 VLog(0, (" Yet other VLDB server entries exist:\n"));
2133 for (j = 0; j < count; j++) {
2134 srvidx = WillChange[j];
2135 VLog(0, (" entry %d: ", srvidx));
2136 if ((HostAddress[srvidx] & 0xff000000) == 0xff000000) {
2138 base = (HostAddress[srvidx] >> 16) & 0xff;
2139 index = HostAddress[srvidx] & 0x0000ffff;
2140 exp = &ex_addr[base][index];
2141 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2142 if (!exp->ex_addrs[mhidx])
2146 PADDR(ntohl(exp->ex_addrs[mhidx]));
2150 PADDR(HostAddress[srvidx]);
2156 VLog(0, (" You must 'vos changeaddr' this other server entry\n"));
2159 (" You must 'vos changeaddr' these other server entries\n"));
2162 (" and/or remove the sysid file from the registering fileserver\n"));
2163 VLog(0, (" before the fileserver can be registered in the VLDB.\n"));
2165 ubik_AbortTrans(trans);
2166 return VL_MULTIPADDR;
2169 /* Passed the checks. Now find and update the existing mh entry, or create
2172 if (foundUuidEntry) {
2173 /* Found the entry with same uuid. See if we need to change it */
2176 fbase = (HostAddress[FoundUuid] >> 16) & 0xff;
2177 index = HostAddress[FoundUuid] & 0x0000ffff;
2178 exp = &ex_addr[fbase][index];
2180 /* Determine if the entry has changed */
2181 for (k = 0; ((k < cnt) && !change); k++) {
2182 if (ntohl(exp->ex_addrs[k]) != addrs[k])
2185 for (; ((k < VL_MAXIPADDRS_PERMH) && !change); k++) {
2186 if (exp->ex_addrs[k] != 0)
2190 return (ubik_EndTrans(trans));
2194 VLog(0, ("The following fileserver is being registered in the VLDB:\n"));
2196 for (k = 0; k < cnt; k++) {
2203 if (foundUuidEntry) {
2205 (" It will replace the following existing entry in the VLDB (same uuid):\n"));
2206 VLog(0, (" entry %d: [", FoundUuid));
2207 for (k = 0; k < VL_MAXIPADDRS_PERMH; k++) {
2208 if (exp->ex_addrs[k] == 0)
2212 PADDR(ntohl(exp->ex_addrs[k]));
2215 } else if (willReplaceCnt || (count == 1)) {
2216 /* If we are not replacing an entry and there is only one entry to change,
2217 * then we will replace that entry.
2219 if (!willReplaceCnt) {
2220 ReplaceEntry = WillChange[0];
2224 /* Have an entry that needs to be replaced */
2225 if ((HostAddress[ReplaceEntry] & 0xff000000) == 0xff000000) {
2226 fbase = (HostAddress[ReplaceEntry] >> 16) & 0xff;
2227 index = HostAddress[ReplaceEntry] & 0x0000ffff;
2228 exp = &ex_addr[fbase][index];
2231 (" It will replace the following existing entry in the VLDB (new uuid):\n"));
2232 VLog(0, (" entry %d: [", ReplaceEntry));
2233 for (k = 0; k < VL_MAXIPADDRS_PERMH; k++) {
2234 if (exp->ex_addrs[k] == 0)
2238 PADDR(ntohl(exp->ex_addrs[k]));
2242 /* Not a mh entry. So we have to create a new mh entry and
2243 * put it on the ReplaceEntry slot of the HostAddress array.
2245 VLog(0, (" It will replace existing entry %d, ", ReplaceEntry));
2246 PADDR(HostAddress[ReplaceEntry]);
2247 VLog(0,(", in the VLDB (new uuid):\n"));
2250 FindExtentBlock(trans, uuidp, 1, ReplaceEntry, &exp, &fbase);
2252 ubik_AbortTrans(trans);
2253 return (code ? code : VL_IO);
2257 /* There is no entry for this server, must create a new mh entry as
2258 * well as use a new slot of the HostAddress array.
2260 VLog(0, (" It will create a new entry in the VLDB.\n"));
2261 code = FindExtentBlock(trans, uuidp, 1, -1, &exp, &fbase);
2263 ubik_AbortTrans(trans);
2264 return (code ? code : VL_IO);
2268 /* Now we have a mh entry to fill in. Update the uuid, bump the
2269 * uniquifier, and fill in its IP addresses.
2272 afs_htonuuid(&tuuid);
2273 exp->ex_hostuuid = tuuid;
2274 exp->ex_uniquifier = htonl(ntohl(exp->ex_uniquifier) + 1);
2275 for (k = 0; k < cnt; k++) {
2276 exp->ex_addrs[k] = htonl(addrs[k]);
2278 for (; k < VL_MAXIPADDRS_PERMH; k++) {
2279 exp->ex_addrs[k] = 0;
2282 /* Write the new mh entry out */
2285 DOFFSET(ntohl(ex_addr[0]->ex_contaddrs[fbase]),
2286 (char *)ex_addr[fbase], (char *)exp), (char *)exp,
2288 ubik_AbortTrans(trans);
2292 /* Remove any common addresses from other mh entres. We know these entries
2293 * are being changed and not replaced so they are mh entries.
2296 for (i = 0; i < count; i++) {
2299 /* Skip the entry we replaced */
2300 if (willReplaceCnt && (WillChange[i] == ReplaceEntry))
2303 base = (HostAddress[WillChange[i]] >> 16) & 0xff;
2304 index = HostAddress[WillChange[i]] & 0x0000ffff;
2305 tex = &ex_addr[fbase][index];
2309 (" The following existing entries in the VLDB will be updated:\n"));
2311 VLog(0, (" entry %d: [", WillChange[i]));
2312 for (h = j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2313 if (tex->ex_addrs[j]) {
2316 PADDR(ntohl(tex->ex_addrs[j]));
2319 for (k = 0; k < cnt; k++) {
2320 if (ntohl(tex->ex_addrs[j]) == addrs[k])
2324 /* Not found, so we keep it */
2325 tex->ex_addrs[h] = tex->ex_addrs[j];
2329 for (j = h; j < VL_MAXIPADDRS_PERMH; j++) {
2330 tex->ex_addrs[j] = 0; /* zero rest of mh entry */
2334 /* Write out the modified mh entry */
2335 tex->ex_uniquifier = htonl(ntohl(tex->ex_uniquifier) + 1);
2337 DOFFSET(ntohl(ex_addr[0]->ex_contaddrs[base]),
2338 (char *)ex_addr[base], (char *)tex);
2339 if (vlwrite(trans, doff, (char *)tex, sizeof(*tex))) {
2340 ubik_AbortTrans(trans);
2345 return (ubik_EndTrans(trans));
2349 SVL_GetAddrsU(rxcall, attributes, uuidpo, uniquifier, nentries, addrsp)
2350 struct rx_call *rxcall;
2351 struct ListAddrByAttributes *attributes;
2353 afs_int32 *uniquifier, *nentries;
2356 register afs_int32 errorcode, index = -1, offset;
2357 struct ubik_trans *trans;
2358 int nservers, i, j, base = 0;
2359 struct extentaddr *exp = 0;
2361 afs_uint32 *taddrp, taddr;
2363 COUNT_REQ(VLGETADDRSU);
2364 addrsp->bulkaddrs_len = *nentries = 0;
2365 addrsp->bulkaddrs_val = 0;
2366 VLog(5, ("GetAddrsU %s\n", rxinfo(rxcall)));
2367 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
2370 if (attributes->Mask & VLADDR_IPADDR) {
2371 if (attributes->Mask & (VLADDR_INDEX | VLADDR_UUID)) {
2372 ubik_AbortTrans(trans);
2375 for (base = 0; base < VL_MAX_ADDREXTBLKS; base++) {
2378 for (i = 1; i < VL_MHSRV_PERBLK; i++) {
2379 exp = &ex_addr[base][i];
2380 tuuid = exp->ex_hostuuid;
2381 afs_ntohuuid(&tuuid);
2382 if (afs_uuid_is_nil(&tuuid))
2384 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2385 if (exp->ex_addrs[j]
2386 && (ntohl(exp->ex_addrs[j]) == attributes->ipaddr)) {
2390 if (j < VL_MAXIPADDRS_PERMH)
2393 if (i < VL_MHSRV_PERBLK)
2396 if (base >= VL_MAX_ADDREXTBLKS) {
2397 ubik_AbortTrans(trans);
2400 } else if (attributes->Mask & VLADDR_INDEX) {
2401 if (attributes->Mask & (VLADDR_IPADDR | VLADDR_UUID)) {
2402 ubik_AbortTrans(trans);
2405 index = attributes->index;
2406 if (index < 1 || index >= (VL_MAX_ADDREXTBLKS * VL_MHSRV_PERBLK)) {
2407 ubik_AbortTrans(trans);
2408 return VL_INDEXERANGE;
2410 base = index / VL_MHSRV_PERBLK;
2411 offset = index % VL_MHSRV_PERBLK;
2413 ubik_AbortTrans(trans);
2416 if (!ex_addr[base]) {
2417 ubik_AbortTrans(trans);
2418 return VL_INDEXERANGE;
2420 exp = &ex_addr[base][offset];
2421 } else if (attributes->Mask & VLADDR_UUID) {
2422 if (attributes->Mask & (VLADDR_IPADDR | VLADDR_INDEX)) {
2423 ubik_AbortTrans(trans);
2426 if (!ex_addr[0]) { /* mh servers probably aren't setup on this vldb */
2427 ubik_AbortTrans(trans);
2431 FindExtentBlock(trans, &attributes->uuid, 0, -1, &exp, &base)) {
2432 ubik_AbortTrans(trans);
2436 ubik_AbortTrans(trans);
2441 ubik_AbortTrans(trans);
2444 addrsp->bulkaddrs_val = taddrp =
2445 (afs_uint32 *) malloc(sizeof(afs_int32) * (MAXSERVERID + 1));
2446 nservers = *nentries = addrsp->bulkaddrs_len = 0;
2449 ubik_AbortTrans(trans);
2452 tuuid = exp->ex_hostuuid;
2453 afs_ntohuuid(&tuuid);
2454 if (afs_uuid_is_nil(&tuuid)) {
2455 ubik_AbortTrans(trans);
2461 *uniquifier = ntohl(exp->ex_uniquifier);
2462 for (i = 0; i < VL_MAXIPADDRS_PERMH; i++) {
2463 if (exp->ex_addrs[i]) {
2464 taddr = ntohl(exp->ex_addrs[i]);
2465 /* Weed out duplicates */
2466 for (j = 0; j < nservers; j++) {
2467 if (taddrp[j] == taddr)
2470 if ((j == nservers) && (j <= MAXSERVERID)) {
2471 taddrp[nservers] = taddr;
2476 addrsp->bulkaddrs_len = *nentries = nservers;
2477 return (ubik_EndTrans(trans));
2480 /* ============> End of Exported vldb RPC functions <============= */
2483 /* Routine that copies the given vldb entry to the output buffer, vldbentries. */
2485 put_attributeentry(Vldbentry, VldbentryFirst, VldbentryLast, vldbentries,
2486 entry, nentries, alloccnt)
2487 struct vldbentry **Vldbentry, **VldbentryFirst, **VldbentryLast;
2488 bulkentries *vldbentries;
2489 struct nvlentry *entry;
2490 afs_int32 *nentries, *alloccnt;
2495 if (*Vldbentry == *VldbentryLast) {
2497 return VL_SIZEEXCEEDED; /* no growing if smallMem defined */
2499 /* Allocate another set of memory; each time allocate twice as
2500 * many blocks as the last time. When we reach VLDBALLOCLIMIT,
2501 * then grow in increments of VLDBALLOCINCR.
2503 allo = (*alloccnt > VLDBALLOCLIMIT) ? VLDBALLOCINCR : *alloccnt;
2505 (vldbentry *) realloc(*VldbentryFirst,
2506 (*alloccnt + allo) * sizeof(vldbentry));
2510 *VldbentryFirst = vldbentries->bulkentries_val = reall;
2511 *Vldbentry = *VldbentryFirst + *alloccnt;
2512 *VldbentryLast = *Vldbentry + allo;
2515 vlentry_to_vldbentry(entry, *Vldbentry);
2518 vldbentries->bulkentries_len++;
2523 put_nattributeentry(Vldbentry, VldbentryFirst, VldbentryLast, vldbentries,
2524 entry, matchtype, matchindex, nentries, alloccnt)
2525 struct nvldbentry **Vldbentry, **VldbentryFirst, **VldbentryLast;
2526 nbulkentries *vldbentries;
2527 struct nvlentry *entry;
2528 afs_int32 matchtype, matchindex, *nentries, *alloccnt;
2533 if (*Vldbentry == *VldbentryLast) {
2535 return VL_SIZEEXCEEDED; /* no growing if smallMem defined */
2537 /* Allocate another set of memory; each time allocate twice as
2538 * many blocks as the last time. When we reach VLDBALLOCLIMIT,
2539 * then grow in increments of VLDBALLOCINCR.
2541 allo = (*alloccnt > VLDBALLOCLIMIT) ? VLDBALLOCINCR : *alloccnt;
2543 (nvldbentry *) realloc(*VldbentryFirst,
2544 (*alloccnt + allo) * sizeof(nvldbentry));
2548 *VldbentryFirst = vldbentries->nbulkentries_val = reall;
2549 *Vldbentry = *VldbentryFirst + *alloccnt;
2550 *VldbentryLast = *Vldbentry + allo;
2553 vlentry_to_nvldbentry(entry, *Vldbentry);
2554 (*Vldbentry)->matchindex = (matchtype << 16) + matchindex;
2557 vldbentries->nbulkentries_len++;
2562 /* Common code to actually remove a vldb entry from the database. */
2564 RemoveEntry(trans, entryptr, tentry)
2565 struct ubik_trans *trans;
2567 struct nvlentry *tentry;
2569 register int errorcode;
2571 if (errorcode = UnthreadVLentry(trans, entryptr, tentry))
2573 if (errorcode = FreeBlock(trans, entryptr))
2579 ReleaseEntry(tentry, releasetype)
2580 struct nvlentry *tentry;
2581 afs_int32 releasetype;
2583 if (releasetype & LOCKREL_TIMESTAMP)
2584 tentry->LockTimestamp = 0;
2585 if (releasetype & LOCKREL_OPCODE)
2586 tentry->flags &= ~VLOP_ALLOPERS;
2587 if (releasetype & LOCKREL_AFSID)
2588 tentry->LockAfsId = 0;
2592 /* Verify that the incoming vldb entry is valid; multi type of error codes are returned. */
2594 check_vldbentry(aentry)
2595 struct vldbentry *aentry;
2599 if (InvalidVolname(aentry->name))
2601 if (aentry->nServers <= 0 || aentry->nServers > OMAXNSERVERS)
2602 return VL_BADSERVER;
2603 for (i = 0; i < aentry->nServers; i++) {
2604 /* if (aentry->serverNumber[i] < 0 || aentry->serverNumber[i] > MAXSERVERID)
2605 return VL_BADSERVER; */
2606 if (aentry->serverPartition[i] < 0
2607 || aentry->serverPartition[i] > MAXPARTITIONID)
2608 return VL_BADPARTITION;
2609 if (aentry->serverFlags[i] < 0
2610 || aentry->serverFlags[i] > MAXSERVERFLAG)
2611 return VL_BADSERVERFLAG;
2617 check_nvldbentry(aentry)
2618 struct nvldbentry *aentry;
2622 if (InvalidVolname(aentry->name))
2624 if (aentry->nServers <= 0 || aentry->nServers > NMAXNSERVERS)
2625 return VL_BADSERVER;
2626 for (i = 0; i < aentry->nServers; i++) {
2627 /* if (aentry->serverNumber[i] < 0 || aentry->serverNumber[i] > MAXSERVERID)
2628 return VL_BADSERVER; */
2629 if (aentry->serverPartition[i] < 0
2630 || aentry->serverPartition[i] > MAXPARTITIONID)
2631 return VL_BADPARTITION;
2632 if (aentry->serverFlags[i] < 0
2633 || aentry->serverFlags[i] > MAXSERVERFLAG)
2634 return VL_BADSERVERFLAG;
2640 /* Convert from the external vldb entry representation to its internal
2641 (more compact) form. This call should not change the hash chains! */
2643 vldbentry_to_vlentry(atrans, VldbEntry, VlEntry)
2644 struct ubik_trans *atrans;
2645 struct vldbentry *VldbEntry;
2646 struct nvlentry *VlEntry;
2650 if (strcmp(VlEntry->name, VldbEntry->name))
2651 strncpy(VlEntry->name, VldbEntry->name, sizeof(VlEntry->name));
2652 for (i = 0; i < VldbEntry->nServers; i++) {
2653 serverindex = IpAddrToRelAddr(VldbEntry->serverNumber[i], atrans);
2654 if (serverindex == -1)
2655 return VL_BADSERVER;
2656 VlEntry->serverNumber[i] = serverindex;
2657 VlEntry->serverPartition[i] = VldbEntry->serverPartition[i];
2658 VlEntry->serverFlags[i] = VldbEntry->serverFlags[i];
2660 for (; i < OMAXNSERVERS; i++)
2661 VlEntry->serverNumber[i] = VlEntry->serverPartition[i] =
2662 VlEntry->serverFlags[i] = BADSERVERID;
2663 for (i = 0; i < MAXTYPES; i++)
2664 VlEntry->volumeId[i] = VldbEntry->volumeId[i];
2665 VlEntry->cloneId = VldbEntry->cloneId;
2666 VlEntry->flags = VldbEntry->flags;
2671 nvldbentry_to_vlentry(atrans, VldbEntry, VlEntry)
2672 struct ubik_trans *atrans;
2673 struct nvldbentry *VldbEntry;
2674 struct nvlentry *VlEntry;
2678 if (strcmp(VlEntry->name, VldbEntry->name))
2679 strncpy(VlEntry->name, VldbEntry->name, sizeof(VlEntry->name));
2680 for (i = 0; i < VldbEntry->nServers; i++) {
2681 serverindex = IpAddrToRelAddr(VldbEntry->serverNumber[i], atrans);
2682 if (serverindex == -1)
2683 return VL_BADSERVER;
2684 VlEntry->serverNumber[i] = serverindex;
2685 VlEntry->serverPartition[i] = VldbEntry->serverPartition[i];
2686 VlEntry->serverFlags[i] = VldbEntry->serverFlags[i];
2688 for (; i < NMAXNSERVERS; i++)
2689 VlEntry->serverNumber[i] = VlEntry->serverPartition[i] =
2690 VlEntry->serverFlags[i] = BADSERVERID;
2691 for (i = 0; i < MAXTYPES; i++)
2692 VlEntry->volumeId[i] = VldbEntry->volumeId[i];
2693 VlEntry->cloneId = VldbEntry->cloneId;
2694 VlEntry->flags = VldbEntry->flags;
2699 /* 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. */
2701 get_vldbupdateentry(trans, blockindex, updateentry, VlEntry)
2702 struct ubik_trans *trans;
2703 afs_int32 blockindex;
2704 struct VldbUpdateEntry *updateentry;
2705 struct nvlentry *VlEntry;
2707 int i, j, errorcode, serverindex;
2709 if (updateentry->Mask & VLUPDATE_VOLUMENAME) {
2710 if (InvalidVolname(updateentry->name))
2712 if (errorcode = UnhashVolname(trans, blockindex, VlEntry))
2714 strncpy(VlEntry->name, updateentry->name, sizeof(VlEntry->name));
2715 HashVolname(trans, blockindex, VlEntry);
2718 if (updateentry->Mask & VLUPDATE_VOLNAMEHASH) {
2719 if (errorcode = UnhashVolname(trans, blockindex, VlEntry)) {
2720 if (errorcode != VL_NOENT)
2723 HashVolname(trans, blockindex, VlEntry);
2726 if (updateentry->Mask & VLUPDATE_FLAGS) {
2727 VlEntry->flags = updateentry->flags;
2729 if (updateentry->Mask & VLUPDATE_CLONEID) {
2730 VlEntry->cloneId = updateentry->cloneId;
2732 if (updateentry->Mask & VLUPDATE_RWID) {
2733 if (errorcode = UnhashVolid(trans, RWVOL, blockindex, VlEntry)) {
2734 if (errorcode != VL_NOENT)
2737 VlEntry->volumeId[RWVOL] = updateentry->spares3; /* rw id */
2738 if (errorcode = HashVolid(trans, RWVOL, blockindex, VlEntry))
2741 if (updateentry->Mask & VLUPDATE_READONLYID) {
2742 if (errorcode = UnhashVolid(trans, ROVOL, blockindex, VlEntry)) {
2743 if (errorcode != VL_NOENT)
2746 VlEntry->volumeId[ROVOL] = updateentry->ReadOnlyId;
2747 if (errorcode = HashVolid(trans, ROVOL, blockindex, VlEntry))
2750 if (updateentry->Mask & VLUPDATE_BACKUPID) {
2751 if (errorcode = UnhashVolid(trans, BACKVOL, blockindex, VlEntry)) {
2752 if (errorcode != VL_NOENT)
2755 VlEntry->volumeId[BACKVOL] = updateentry->BackupId;
2756 if (errorcode = HashVolid(trans, BACKVOL, blockindex, VlEntry))
2759 if (updateentry->Mask & VLUPDATE_REPSITES) {
2760 if (updateentry->nModifiedRepsites <= 0
2761 || updateentry->nModifiedRepsites > OMAXNSERVERS)
2762 return VL_BADSERVER;
2763 for (i = 0; i < updateentry->nModifiedRepsites; i++) {
2764 /* if (updateentry->RepsitesTargetServer[i] < 0 || updateentry->RepsitesTargetServer[i] > MAXSERVERID)
2765 return VL_BADSERVER; */
2766 if (updateentry->RepsitesTargetPart[i] < 0
2767 || updateentry->RepsitesTargetPart[i] > MAXPARTITIONID)
2768 return VL_BADPARTITION;
2769 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_DELETE) {
2771 repsite_exists(VlEntry,
2772 IpAddrToRelAddr(updateentry->
2773 RepsitesTargetServer[i],
2775 updateentry->RepsitesTargetPart[i])) !=
2777 repsite_compress(VlEntry, j);
2779 return VL_NOREPSERVER;
2781 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_ADD) {
2782 /* if (updateentry->RepsitesNewServer[i] < 0 || updateentry->RepsitesNewServer[i] > MAXSERVERID)
2783 return VL_BADSERVER; */
2784 if (updateentry->RepsitesNewPart[i] < 0
2785 || updateentry->RepsitesNewPart[i] > MAXPARTITIONID)
2786 return VL_BADPARTITION;
2789 IpAddrToRelAddr(updateentry->RepsitesNewServer[i],
2791 updateentry->RepsitesNewPart[i]) != -1)
2792 return VL_DUPREPSERVER;
2794 VlEntry->serverNumber[j] != BADSERVERID
2795 && j < OMAXNSERVERS; j++);
2796 if (j >= OMAXNSERVERS)
2799 IpAddrToRelAddr(updateentry->RepsitesNewServer[i],
2801 return VL_BADSERVER;
2802 VlEntry->serverNumber[j] = serverindex;
2803 VlEntry->serverPartition[j] = updateentry->RepsitesNewPart[i];
2804 if (updateentry->RepsitesNewFlags[i] < 0
2805 || updateentry->RepsitesNewFlags[i] > MAXSERVERFLAG)
2806 return VL_BADSERVERFLAG;
2807 VlEntry->serverFlags[j] = updateentry->RepsitesNewFlags[i];
2809 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODSERV) {
2810 /*n if (updateentry->RepsitesNewServer[i] < 0 || updateentry->RepsitesNewServer[i] > MAXSERVERID)
2811 return VL_BADSERVER; */
2813 repsite_exists(VlEntry,
2814 IpAddrToRelAddr(updateentry->
2815 RepsitesTargetServer[i],
2817 updateentry->RepsitesTargetPart[i])) !=
2819 VlEntry->serverNumber[j] =
2820 IpAddrToRelAddr(updateentry->RepsitesNewServer[i],
2823 return VL_NOREPSERVER;
2825 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODPART) {
2826 if (updateentry->RepsitesNewPart[i] < 0
2827 || updateentry->RepsitesNewPart[i] > MAXPARTITIONID)
2828 return VL_BADPARTITION;
2830 repsite_exists(VlEntry,
2831 IpAddrToRelAddr(updateentry->
2832 RepsitesTargetServer[i],
2834 updateentry->RepsitesTargetPart[i])) !=
2836 VlEntry->serverPartition[j] =
2837 updateentry->RepsitesNewPart[i];
2839 return VL_NOREPSERVER;
2841 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODFLAG) {
2843 repsite_exists(VlEntry,
2844 IpAddrToRelAddr(updateentry->
2845 RepsitesTargetServer[i],
2847 updateentry->RepsitesTargetPart[i])) !=
2849 if (updateentry->RepsitesNewFlags[i] < 0
2850 || updateentry->RepsitesNewFlags[i] > MAXSERVERFLAG)
2851 return VL_BADSERVERFLAG;
2852 VlEntry->serverFlags[j] =
2853 updateentry->RepsitesNewFlags[i];
2855 return VL_NOREPSERVER;
2863 /* 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. */
2865 repsite_exists(VlEntry, server, partition)
2866 struct nvlentry *VlEntry;
2867 int server, partition;
2871 for (i = 0; VlEntry->serverNumber[i] != BADSERVERID && i < OMAXNSERVERS;
2873 if ((VlEntry->serverNumber[i] == server)
2874 && (VlEntry->serverPartition[i] == partition))
2882 /* Repsite table compression: used when deleting a repsite entry so that all active repsite entries are on the top of the table. */
2884 repsite_compress(VlEntry, offset)
2885 struct nvlentry *VlEntry;
2888 int repsite_offset = offset;
2890 VlEntry->serverNumber[repsite_offset] != BADSERVERID
2891 && repsite_offset < OMAXNSERVERS - 1; repsite_offset++) {
2892 VlEntry->serverNumber[repsite_offset] =
2893 VlEntry->serverNumber[repsite_offset + 1];
2894 VlEntry->serverPartition[repsite_offset] =
2895 VlEntry->serverPartition[repsite_offset + 1];
2896 VlEntry->serverFlags[repsite_offset] =
2897 VlEntry->serverFlags[repsite_offset + 1];
2899 VlEntry->serverNumber[repsite_offset] = BADSERVERID;
2903 /* Convert from the internal (compacted) vldb entry to the external representation used by the interface. */
2905 vlentry_to_vldbentry(VlEntry, VldbEntry)
2906 struct nvlentry *VlEntry;
2907 struct vldbentry *VldbEntry;
2911 memset(VldbEntry, 0, sizeof(struct vldbentry));
2912 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
2913 for (i = 0; i < OMAXNSERVERS; i++) {
2914 if (VlEntry->serverNumber[i] == BADSERVERID)
2916 if ((HostAddress[j = VlEntry->serverNumber[i]] & 0xff000000) ==
2918 struct extentaddr *exp;
2921 base = (HostAddress[j] >> 16) & 0xff;
2922 index = HostAddress[j] & 0x0000ffff;
2923 exp = &ex_addr[base][index];
2924 /* For now return the first ip address back */
2925 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2926 if (exp->ex_addrs[j]) {
2927 VldbEntry->serverNumber[i] = ntohl(exp->ex_addrs[j]);
2932 VldbEntry->serverNumber[i] =
2933 HostAddress[VlEntry->serverNumber[i]];
2934 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
2935 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
2937 VldbEntry->nServers = i;
2938 for (i = 0; i < MAXTYPES; i++)
2939 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
2940 VldbEntry->cloneId = VlEntry->cloneId;
2941 VldbEntry->flags = VlEntry->flags;
2945 /* Convert from the internal (compacted) vldb entry to the external representation used by the interface. */
2947 vlentry_to_nvldbentry(VlEntry, VldbEntry)
2948 struct nvlentry *VlEntry;
2949 struct nvldbentry *VldbEntry;
2953 memset(VldbEntry, 0, sizeof(struct vldbentry));
2954 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
2955 for (i = 0; i < NMAXNSERVERS; i++) {
2956 if (VlEntry->serverNumber[i] == BADSERVERID)
2958 if ((HostAddress[j = VlEntry->serverNumber[i]] & 0xff000000) ==
2960 struct extentaddr *exp;
2963 base = (HostAddress[j] >> 16) & 0xff;
2964 index = HostAddress[j] & 0x0000ffff;
2965 exp = &ex_addr[base][index];
2966 /* For now return the first ip address back */
2967 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2968 if (exp->ex_addrs[j]) {
2969 VldbEntry->serverNumber[i] = ntohl(exp->ex_addrs[j]);
2974 VldbEntry->serverNumber[i] =
2975 HostAddress[VlEntry->serverNumber[i]];
2976 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
2977 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
2979 VldbEntry->nServers = i;
2980 for (i = 0; i < MAXTYPES; i++)
2981 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
2982 VldbEntry->cloneId = VlEntry->cloneId;
2983 VldbEntry->flags = VlEntry->flags;
2987 vlentry_to_uvldbentry(VlEntry, VldbEntry)
2988 struct nvlentry *VlEntry;
2989 struct uvldbentry *VldbEntry;
2993 memset(VldbEntry, 0, sizeof(struct vldbentry));
2994 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
2995 for (i = 0; i < NMAXNSERVERS; i++) {
2996 if (VlEntry->serverNumber[i] == BADSERVERID)
2998 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
2999 VldbEntry->serverUnique[i] = 0;
3000 if ((HostAddress[j = VlEntry->serverNumber[i]] & 0xff000000) ==
3002 struct extentaddr *exp;
3006 base = (HostAddress[j] >> 16) & 0xff;
3007 index = HostAddress[j] & 0x0000ffff;
3008 exp = &ex_addr[base][index];
3009 tuuid = exp->ex_hostuuid;
3010 afs_ntohuuid(&tuuid);
3011 VldbEntry->serverFlags[i] |= VLSERVER_FLAG_UUID;
3012 VldbEntry->serverNumber[i] = tuuid;
3013 VldbEntry->serverUnique[i] = ntohl(exp->ex_uniquifier);
3015 VldbEntry->serverNumber[i].time_low =
3016 HostAddress[VlEntry->serverNumber[i]];
3018 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
3021 VldbEntry->nServers = i;
3022 for (i = 0; i < MAXTYPES; i++)
3023 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
3024 VldbEntry->cloneId = VlEntry->cloneId;
3025 VldbEntry->flags = VlEntry->flags;
3028 #define LEGALCHARS ".ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
3031 /* Verify that the volname is a valid volume name. */
3033 InvalidVolname(volname)
3040 slen = strlen(volname);
3041 if (slen >= VL_MAXNAMELEN)
3043 return (slen != strspn(volname, map));
3047 /* Verify that the given volume type is valid. */
3049 InvalidVoltype(voltype)
3052 if (voltype != RWVOL && voltype != ROVOL && voltype != BACKVOL)
3059 InvalidOperation(voloper)
3062 if (voloper != VLOP_MOVE && voloper != VLOP_RELEASE
3063 && voloper != VLOP_BACKUP && voloper != VLOP_DELETE
3064 && voloper != VLOP_DUMP)
3070 InvalidReleasetype(releasetype)
3071 afs_int32 releasetype;
3073 if ((releasetype & LOCKREL_TIMESTAMP) || (releasetype & LOCKREL_OPCODE)
3074 || (releasetype & LOCKREL_AFSID))
3080 IpAddrToRelAddr(ipaddr, atrans)
3081 struct ubik_trans *atrans;
3082 register afs_uint32 ipaddr;
3085 register afs_int32 code, base, index;
3086 struct extentaddr *exp;
3088 for (i = 0; i <= MAXSERVERID; i++) {
3089 if (HostAddress[i] == ipaddr)
3091 if ((HostAddress[i] & 0xff000000) == 0xff000000) {
3092 base = (HostAddress[i] >> 16) & 0xff;
3093 index = HostAddress[i] & 0x0000ffff;
3094 if (base >= VL_MAX_ADDREXTBLKS) {
3096 ("Internal error: Multihome extent base is too large. Base %d index %d\n",
3098 return -1; /* EINVAL */
3100 if (index >= VL_MHSRV_PERBLK) {
3102 ("Internal error: Multihome extent index is too large. Base %d index %d\n",
3104 return -1; /* EINVAL */
3106 if (!ex_addr[base]) {
3108 ("Internal error: Multihome extent does not exist. Base %d\n",
3110 return -1; /* EINVAL */
3112 exp = &ex_addr[base][index];
3113 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
3114 if (exp->ex_addrs[j] && (ntohl(exp->ex_addrs[j]) == ipaddr)) {
3121 /* allocate the new server a server id pronto */
3123 for (i = 0; i <= MAXSERVERID; i++) {
3124 if (cheader.IpMappedAddr[i] == 0) {
3125 cheader.IpMappedAddr[i] = htonl(ipaddr);
3128 DOFFSET(0, &cheader, &cheader.IpMappedAddr[i]),
3129 (char *)&cheader.IpMappedAddr[i],
3131 HostAddress[i] = ipaddr;
3142 ChangeIPAddr(ipaddr1, ipaddr2, atrans)
3143 struct ubik_trans *atrans;
3144 register afs_uint32 ipaddr1, ipaddr2;
3148 struct extentaddr *exp = NULL;
3152 afs_int32 blockindex, count;
3154 struct nvlentry tentry;
3157 return VL_CREATEFAIL;
3159 /* Don't let addr change to 256.*.*.* : Causes internal error below */
3160 if ((ipaddr2 & 0xff000000) == 0xff000000)
3161 return (VL_BADSERVER);
3163 /* If we are removing an address, ip1 will be -1 and ip2 will be
3164 * the original address. This prevents an older revision vlserver
3165 * from removing the IP address (won't find server 0xfffffff in
3166 * the VLDB). An older revision vlserver does not have the check
3167 * to see if any volumes exist on the server being removed.
3169 if (ipaddr1 == 0xffffffff) {
3174 for (i = 0; i <= MAXSERVERID; i++) {
3175 if ((HostAddress[i] & 0xff000000) == 0xff000000) {
3176 base = (HostAddress[i] >> 16) & 0xff;
3177 index = HostAddress[i] & 0x0000ffff;
3178 if ((base >= VL_MAX_ADDREXTBLKS) || (index >= VL_MHSRV_PERBLK)) {
3180 ("Internal error: Multihome extent addr is too large. Base %d index %d\n",
3182 return -1; /* EINVAL */
3185 exp = &ex_addr[base][index];
3186 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
3187 if (!exp->ex_addrs[mhidx])
3189 if (ntohl(exp->ex_addrs[mhidx]) == ipaddr1)
3192 if (mhidx < VL_MAXIPADDRS_PERMH) {
3195 } else if (HostAddress[i] == ipaddr1) {
3201 if (i >= MAXSERVERID) {
3202 return VL_NOENT; /* not found */
3205 /* If we are removing a server entry, a volume cannot
3206 * exist on the server. If one does, don't remove the
3207 * server entry: return error "volume entry exists".
3210 for (blockindex = NextEntry(atrans, 0, &tentry, &count); blockindex;
3211 blockindex = NextEntry(atrans, blockindex, &tentry, &count)) {
3212 if (++pollcount > 50) {
3213 #ifndef AFS_PTHREAD_ENV
3218 for (j = 0; j < NMAXNSERVERS; j++) {
3219 if (tentry.serverNumber[j] == BADSERVERID)
3221 if (tentry.serverNumber[j] == i) {
3228 /* Log a message saying we are changing/removing an IP address */
3230 ("The following IP address is being %s:\n",
3231 (ipaddr2 ? "changed" : "removed")));
3232 VLog(0, (" entry %d: ", i));
3235 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
3236 if (!exp->ex_addrs[mhidx])
3240 PADDR(ntohl(exp->ex_addrs[mhidx]));
3252 /* Change the registered uuuid addresses */
3254 memset(&tuuid, 0, sizeof(afsUUID));
3255 afs_htonuuid(&tuuid);
3256 exp->ex_hostuuid = tuuid;
3259 DOFFSET(ntohl(ex_addr[0]->ex_contaddrs[base]),
3260 (char *)ex_addr[base], (char *)exp),
3261 (char *)&tuuid, sizeof(tuuid));
3266 /* Now change the host address entry */
3267 cheader.IpMappedAddr[i] = htonl(ipaddr2);
3269 vlwrite(atrans, DOFFSET(0, &cheader, &cheader.IpMappedAddr[i]),
3271 &cheader.IpMappedAddr[i], sizeof(afs_int32));
3272 HostAddress[i] = ipaddr2;
3279 /* see if the vlserver is back yet */
3281 SVL_ProbeServer(rxcall)
3282 struct rx_call *rxcall;