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>
25 #include <netinet/in.h>
29 #include "afs/audit.h"
33 #ifdef HAVE_POSIX_REGEX /* use POSIX regexp library */
39 extern struct afsconf_dir *vldb_confdir;
40 extern struct ubik_dbase *VL_dbase;
41 struct vlheader cheader; /* kept in network byte order */
42 extern afs_uint32 HostAddress[]; /* host addresses kept in host byte order */
44 struct extentaddr *ex_addr[VL_MAX_ADDREXTBLKS] = { 0, 0, 0, 0 };
45 static char rxinfo_str[128]; /* Need rxinfo string to be non-local */
46 #define ABORT(c) { errorcode = (c); goto abort; }
48 #define END(c) { errorcode = (c); goto end; }
50 #define VLDBALLOCLIMIT 10000
51 #define VLDBALLOCINCR 2048
53 static int put_attributeentry();
54 static int put_nattributeentry();
55 static int RemoveEntry();
56 static void ReleaseEntry();
57 static int check_vldbentry();
58 static int check_nvldbentry();
59 static int vldbentry_to_vlentry();
60 static int nvldbentry_to_vlentry();
61 static get_vldbupdateentry();
62 static int repsite_exists();
63 static void repsite_compress();
64 static void vlentry_to_vldbentry();
65 static void vlentry_to_nvldbentry();
66 static void vlentry_to_uvldbentry();
67 static int InvalidVolname();
68 static int InvalidVoltype();
69 static int InvalidOperation();
70 static int InvalidReleasetype();
71 static int IpAddrToRelAddr();
72 static int ChangeIPAddr();
76 struct rx_call *rxcall;
79 register struct rx_connection *tconn;
84 struct in_addr hostAddr;
86 tconn = rx_ConnectionOf(rxcall);
87 hostAddr.s_addr = rx_HostOf(rx_PeerOf(tconn));
89 rxkad_GetServerInfo(rxcall->conn, NULL, &exp, tname, tinst, tcell,
92 sprintf(rxinfo_str, "%s %s%s%s%s%s", inet_ntoa(hostAddr), tname,
93 tinst?".":"", tinst?tinst:"", tcell?"@":"", tcell?tcell:"");
95 sprintf(rxinfo_str, "%s noauth", inet_ntoa(hostAddr));
99 /* This is called to initialize the database, set the appropriate locks and make sure that the vldb header is valid */
101 Init_VLdbase(trans, locktype, this_op)
102 struct ubik_trans **trans;
103 int locktype; /* indicate read or write transaction */
106 int errorcode = 0, pass, wl;
108 for (pass = 1; pass <= 3; pass++) {
109 if (pass == 2) { /* take write lock to rebuild the db */
110 errorcode = ubik_BeginTrans(VL_dbase, UBIK_WRITETRANS, trans);
112 } else if (locktype == LOCKREAD) {
114 ubik_BeginTransReadAny(VL_dbase, UBIK_READTRANS, trans);
117 errorcode = ubik_BeginTrans(VL_dbase, UBIK_WRITETRANS, trans);
123 errorcode = ubik_SetLock(*trans, 1, 1, locktype);
126 ubik_AbortTrans(*trans);
130 /* check that dbase is initialized and setup cheader */
131 /* 2nd pass we try to rebuild the header */
132 errorcode = CheckInit(*trans, ((pass == 2) ? 1 : 0));
133 if (!errorcode && wl && extent_mod)
134 errorcode = readExtents(*trans); /* Fix the mh extent blocks */
137 ubik_AbortTrans(*trans);
138 /* Only rebuld if the database is empty */
139 /* Exit if can't rebuild */
140 if ((pass == 1) && (errorcode != VL_EMPTY))
144 } else { /* No errorcode */
146 ubik_EndTrans(*trans); /* Rebuilt db. End trans, then retake original lock */
148 break; /* didn't rebuild and successful - exit */
156 /* Create a new vldb entry; both new volume id and name must be unique (non-existant in vldb). */
159 SVL_CreateEntry(rxcall, newentry)
160 struct rx_call *rxcall;
161 struct vldbentry *newentry;
163 struct ubik_trans *trans;
164 afs_int32 errorcode, blockindex;
165 struct nvlentry tentry;
167 COUNT_REQ(VLCREATEENTRY);
168 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) {
173 /* Do some validity tests on new entry */
174 if ((errorcode = check_vldbentry(newentry))
175 || (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
179 ("OCreate Volume %d %s\n", newentry->volumeId[RWVOL],
181 /* XXX shouldn't we check to see if the r/o volume is duplicated? */
182 if (newentry->volumeId[RWVOL]
183 && FindByID(trans, newentry->volumeId[RWVOL], RWVOL, &tentry, &errorcode)) { /* entry already exists, we fail */
184 errorcode = VL_IDEXIST;
186 } else if (errorcode) {
190 /* Is this following check (by volume name) necessary?? */
191 /* If entry already exists, we fail */
192 if (FindByName(trans, newentry->name, &tentry, &errorcode)) {
193 errorcode = VL_NAMEEXIST;
195 } else if (errorcode) {
199 blockindex = AllocBlock(trans, &tentry);
200 if (blockindex == 0) {
201 errorcode = VL_CREATEFAIL;
205 memset(&tentry, 0, sizeof(struct nvlentry));
206 /* Convert to its internal representation; both in host byte order */
207 if (errorcode = vldbentry_to_vlentry(trans, newentry, &tentry)) {
208 FreeBlock(trans, blockindex);
212 /* Actually insert the entry in vldb */
213 errorcode = ThreadVLentry(trans, blockindex, &tentry);
215 FreeBlock(trans, blockindex);
218 errorcode = ubik_EndTrans(trans);
224 ubik_AbortTrans(trans);
227 osi_auditU(rxcall, VLCreateEntryEvent, errorcode, AUD_STR,
228 (newentry ? newentry->name : NULL), AUD_END);
234 SVL_CreateEntryN(rxcall, newentry)
235 struct rx_call *rxcall;
236 struct nvldbentry *newentry;
238 struct ubik_trans *trans;
239 afs_int32 errorcode, blockindex;
240 struct nvlentry tentry;
242 COUNT_REQ(VLCREATEENTRYN);
243 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) {
248 /* Do some validity tests on new entry */
249 if ((errorcode = check_nvldbentry(newentry))
250 || (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
254 ("Create Volume %d %s\n", newentry->volumeId[RWVOL],
256 /* XXX shouldn't we check to see if the r/o volume is duplicated? */
257 if (newentry->volumeId[RWVOL]
258 && FindByID(trans, newentry->volumeId[RWVOL], RWVOL, &tentry, &errorcode)) { /* entry already exists, we fail */
259 errorcode = VL_IDEXIST;
261 } else if (errorcode) {
265 /* Is this following check (by volume name) necessary?? */
266 /* If entry already exists, we fail */
267 if (FindByName(trans, newentry->name, &tentry, &errorcode)) {
268 errorcode = VL_NAMEEXIST;
270 } else if (errorcode) {
274 blockindex = AllocBlock(trans, &tentry);
275 if (blockindex == 0) {
276 errorcode = VL_CREATEFAIL;
280 memset(&tentry, 0, sizeof(struct nvlentry));
281 /* Convert to its internal representation; both in host byte order */
282 if (errorcode = nvldbentry_to_vlentry(trans, newentry, &tentry)) {
283 FreeBlock(trans, blockindex);
287 /* Actually insert the entry in vldb */
288 errorcode = ThreadVLentry(trans, blockindex, &tentry);
290 FreeBlock(trans, blockindex);
293 errorcode = ubik_EndTrans(trans);
299 ubik_AbortTrans(trans);
302 osi_auditU(rxcall, VLCreateEntryEvent, errorcode, AUD_STR,
303 (newentry ? newentry->name : NULL), AUD_END);
309 SVL_ChangeAddr(rxcall, ip1, ip2)
310 struct rx_call *rxcall;
313 struct ubik_trans *trans;
316 COUNT_REQ(VLCHANGEADDR);
317 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) {
322 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
325 VLog(1, ("Change Addr %u -> %u %s\n", ip1, ip2, rxinfo(rxcall)));
326 if (errorcode = ChangeIPAddr(ip1, ip2, trans))
329 errorcode = ubik_EndTrans(trans);
335 ubik_AbortTrans(trans);
338 osi_auditU(rxcall, VLChangeAddrEvent, errorcode, AUD_LONG, ip1, AUD_LONG,
343 /* Delete a vldb entry given the volume id. */
345 SVL_DeleteEntry(rxcall, volid, voltype)
346 struct rx_call *rxcall;
350 struct ubik_trans *trans;
351 afs_int32 blockindex, errorcode;
352 struct nvlentry tentry;
354 COUNT_REQ(VLDELETEENTRY);
355 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
358 if ((voltype != -1) && (InvalidVoltype(voltype)))
361 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
364 VLog(1, ("Delete Volume %u %s\n", volid, rxinfo(rxcall)));
365 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
366 if (blockindex == 0) { /* volid not found */
368 errorcode = VL_NOENT;
372 if (tentry.flags & VLDELETED) { /* Already deleted; return */
373 ABORT(VL_ENTDELETED);
375 if (errorcode = RemoveEntry(trans, blockindex, &tentry)) {
378 errorcode = (ubik_EndTrans(trans));
383 ubik_AbortTrans(trans);
386 osi_auditU(rxcall, VLDeleteEntryEvent, errorcode, AUD_LONG, volid,
392 /* Get a vldb entry given its volume id; make sure it's not a deleted entry. */
393 GetEntryByID(rxcall, volid, voltype, aentry, new, this_op)
394 struct rx_call *rxcall;
396 afs_int32 voltype, new, this_op;
397 char *aentry; /* entry data copied here */
399 struct ubik_trans *trans;
400 afs_int32 blockindex, errorcode;
401 struct nvlentry tentry;
403 if ((voltype != -1) && (InvalidVoltype(voltype)))
404 return VL_BADVOLTYPE;
405 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
408 VLog(5, ("GetVolumeByID %u (%d) %s\n", volid, new, rxinfo(rxcall)));
409 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
410 if (blockindex == 0) { /* entry not found */
412 errorcode = VL_NOENT;
414 ubik_AbortTrans(trans);
417 if (tentry.flags & VLDELETED) { /* Entry is deleted! */
419 ubik_AbortTrans(trans);
420 return VL_ENTDELETED;
422 /* Convert from the internal to external form */
424 vlentry_to_nvldbentry(&tentry, (struct nvldbentry *)aentry);
426 vlentry_to_uvldbentry(&tentry, (struct uvldbentry *)aentry);
428 vlentry_to_vldbentry(&tentry, (struct vldbentry *)aentry);
429 return (ubik_EndTrans(trans));
433 SVL_GetEntryByID(rxcall, volid, voltype, aentry)
434 struct rx_call *rxcall;
437 vldbentry *aentry; /* entry data copied here */
439 COUNT_REQ(VLGETENTRYBYID);
440 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 0, this_op));
444 SVL_GetEntryByIDN(rxcall, volid, voltype, aentry)
445 struct rx_call *rxcall;
448 nvldbentry *aentry; /* entry data copied here */
450 COUNT_REQ(VLGETENTRYBYIDN);
451 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 1, this_op));
455 SVL_GetEntryByIDU(rxcall, volid, voltype, aentry)
456 struct rx_call *rxcall;
459 uvldbentry *aentry; /* entry data copied here */
461 COUNT_REQ(VLGETENTRYBYIDU);
462 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 2, this_op));
467 /* returns true if the id is a decimal integer, in which case we interpret it
468 as an id. make the cache manager much simpler */
471 register char *aname;
474 while (tc = *aname++) {
475 if (tc > '9' || tc < '0')
481 /* Get a vldb entry given the volume's name; of course, very similar to VLGetEntryByID() above. */
482 GetEntryByName(rxcall, volname, aentry, new, this_op)
483 struct rx_call *rxcall;
485 char *aentry; /* entry data copied here */
488 struct ubik_trans *trans;
489 afs_int32 blockindex, errorcode;
490 struct nvlentry tentry;
492 if (NameIsId(volname)) {
493 return GetEntryByID(rxcall, atoi(volname), -1, aentry, new, this_op);
495 if (InvalidVolname(volname))
497 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
499 VLog(5, ("GetVolumeByName %s (%d) %s\n", volname, new, rxinfo(rxcall)));
500 blockindex = FindByName(trans, volname, &tentry, &errorcode);
501 if (blockindex == 0) { /* entry not found */
503 errorcode = VL_NOENT;
505 ubik_AbortTrans(trans);
508 if (tentry.flags & VLDELETED) { /* Entry is deleted */
510 ubik_AbortTrans(trans);
511 return VL_ENTDELETED;
513 /* Convert to external entry representation */
515 vlentry_to_nvldbentry(&tentry, (struct nvldbentry *)aentry);
517 vlentry_to_uvldbentry(&tentry, (struct uvldbentry *)aentry);
519 vlentry_to_vldbentry(&tentry, (struct vldbentry *)aentry);
520 return (ubik_EndTrans(trans));
524 SVL_GetEntryByNameO(rxcall, volname, aentry)
525 struct rx_call *rxcall;
527 struct vldbentry *aentry; /* entry data copied here */
529 COUNT_REQ(VLGETENTRYBYNAME);
530 return (GetEntryByName(rxcall, volname, (char *)aentry, 0, this_op));
535 SVL_GetEntryByNameN(rxcall, volname, aentry)
536 struct rx_call *rxcall;
538 struct nvldbentry *aentry; /* entry data copied here */
540 COUNT_REQ(VLGETENTRYBYNAMEN);
541 return (GetEntryByName(rxcall, volname, (char *)aentry, 1, this_op));
545 SVL_GetEntryByNameU(rxcall, volname, aentry)
546 struct rx_call *rxcall;
548 struct uvldbentry *aentry; /* entry data copied here */
550 COUNT_REQ(VLGETENTRYBYNAMEU);
551 return (GetEntryByName(rxcall, volname, (char *)aentry, 2, this_op));
556 /* Get the current value of the maximum volume id and bump the volume id counter by Maxvolidbump. */
558 SVL_GetNewVolumeId(rxcall, Maxvolidbump, newvolumeid)
559 struct rx_call *rxcall;
560 afs_uint32 Maxvolidbump;
561 afs_uint32 *newvolumeid;
563 register afs_int32 errorcode;
564 afs_uint32 maxvolumeid;
565 struct ubik_trans *trans;
567 COUNT_REQ(VLGETNEWVOLUMEID);
568 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
571 if (Maxvolidbump < 0 || Maxvolidbump > MAXBUMPCOUNT)
572 END(VL_BADVOLIDBUMP);
574 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
577 *newvolumeid = maxvolumeid = ntohl(cheader.vital_header.MaxVolumeId);
578 maxvolumeid += Maxvolidbump;
579 VLog(1, ("GetNewVolid newmax=%u %s\n", maxvolumeid, rxinfo(rxcall)));
580 cheader.vital_header.MaxVolumeId = htonl(maxvolumeid);
581 if (write_vital_vlheader(trans)) {
584 errorcode = (ubik_EndTrans(trans));
589 ubik_AbortTrans(trans);
592 osi_auditU(rxcall, VLGetNewVolumeIdEvent, errorcode, AUD_END);
597 /* Simple replace the contents of the vldb entry, volid, with
598 * newentry. No individual checking/updating per field (alike
599 * VLUpdateEntry) is done. */
602 SVL_ReplaceEntry(rxcall, volid, voltype, newentry, releasetype)
603 struct rx_call *rxcall;
606 struct vldbentry *newentry;
607 afs_int32 releasetype;
609 struct ubik_trans *trans;
610 afs_int32 blockindex, errorcode, typeindex;
612 int hashVol[MAXTYPES];
613 struct nvlentry tentry;
615 COUNT_REQ(VLREPLACEENTRY);
616 for (typeindex = 0; typeindex < MAXTYPES; typeindex++)
617 hashVol[typeindex] = 0;
619 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
622 if (errorcode = check_vldbentry(newentry))
625 if (voltype != -1 && InvalidVoltype(voltype))
628 if (releasetype && InvalidReleasetype(releasetype))
629 END(VL_BADRELLOCKTYPE);
630 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
633 VLog(1, ("OReplace Volume %u %s\n", volid, rxinfo(rxcall)));
634 /* find vlentry we're changing */
635 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
636 if (blockindex == 0) { /* entry not found */
638 errorcode = VL_NOENT;
642 /* check that we're not trying to change the RW vol ID */
643 if (newentry->volumeId[RWVOL] != tentry.volumeId[RWVOL]) {
647 /* unhash volid entries if they're disappearing or changing.
648 * Remember if we need to hash in the new value (we don't have to
649 * rehash if volid stays same */
650 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
651 if (tentry.volumeId[typeindex] != newentry->volumeId[typeindex]) {
652 if (tentry.volumeId[typeindex])
654 UnhashVolid(trans, typeindex, blockindex, &tentry)) {
657 /* we must rehash new id if the id is different and the ID is nonzero */
658 hashVol[typeindex] = 1; /* must rehash this guy if he exists */
662 /* Rehash volname if it changes */
663 if (strcmp(newentry->name, tentry.name)) { /* Name changes; redo hashing */
664 if (errorcode = UnhashVolname(trans, blockindex, &tentry)) {
670 /* after this, tentry is new entry, not old one. vldbentry_to_vlentry
671 * doesn't touch hash chains */
672 if (errorcode = vldbentry_to_vlentry(trans, newentry, &tentry)) {
676 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
677 if (hashVol[typeindex] && tentry.volumeId[typeindex]) {
678 if (errorcode = HashVolid(trans, typeindex, blockindex, &tentry)) {
685 HashVolname(trans, blockindex, &tentry);
688 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
689 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
693 END(ubik_EndTrans(trans));
697 ubik_AbortTrans(trans);
700 osi_auditU(rxcall, VLReplaceVLEntryEvent, errorcode, AUD_LONG, volid,
706 SVL_ReplaceEntryN(rxcall, volid, voltype, newentry, releasetype)
707 struct rx_call *rxcall;
710 struct nvldbentry *newentry;
711 afs_int32 releasetype;
713 struct ubik_trans *trans;
714 afs_int32 blockindex, errorcode, typeindex;
716 int hashVol[MAXTYPES];
717 struct nvlentry tentry;
719 COUNT_REQ(VLREPLACEENTRYN);
720 for (typeindex = 0; typeindex < MAXTYPES; typeindex++)
721 hashVol[typeindex] = 0;
723 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
726 if (errorcode = check_nvldbentry(newentry))
729 if (voltype != -1 && InvalidVoltype(voltype))
732 if (releasetype && InvalidReleasetype(releasetype))
733 END(VL_BADRELLOCKTYPE);
734 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
737 VLog(1, ("Replace Volume %u %s\n", volid, rxinfo(rxcall)));
738 /* find vlentry we're changing */
739 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
740 if (blockindex == 0) { /* entry not found */
742 errorcode = VL_NOENT;
746 /* check that we're not trying to change the RW vol ID */
747 if (newentry->volumeId[RWVOL] != tentry.volumeId[RWVOL]) {
751 /* unhash volid entries if they're disappearing or changing.
752 * Remember if we need to hash in the new value (we don't have to
753 * rehash if volid stays same */
754 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
755 if (tentry.volumeId[typeindex] != newentry->volumeId[typeindex]) {
756 if (tentry.volumeId[typeindex])
758 UnhashVolid(trans, typeindex, blockindex, &tentry)) {
761 /* we must rehash new id if the id is different and the ID is nonzero */
762 hashVol[typeindex] = 1; /* must rehash this guy if he exists */
766 /* Rehash volname if it changes */
767 if (strcmp(newentry->name, tentry.name)) { /* Name changes; redo hashing */
768 if (errorcode = UnhashVolname(trans, blockindex, &tentry)) {
774 /* after this, tentry is new entry, not old one. vldbentry_to_vlentry
775 * doesn't touch hash chains */
776 if (errorcode = nvldbentry_to_vlentry(trans, newentry, &tentry)) {
780 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
781 if (hashVol[typeindex] && tentry.volumeId[typeindex]) {
782 if (errorcode = HashVolid(trans, typeindex, blockindex, &tentry)) {
789 HashVolname(trans, blockindex, &tentry);
792 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
793 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
797 END(ubik_EndTrans(trans));
801 ubik_AbortTrans(trans);
804 osi_auditU(rxcall, VLReplaceVLEntryEvent, errorcode, AUD_LONG, volid,
810 /* 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. */
811 /* this routine may never have been tested; use replace entry instead unless you're brave */
813 SVL_UpdateEntry(rxcall, volid, voltype, updateentry, releasetype)
814 struct rx_call *rxcall;
817 afs_int32 releasetype;
818 struct VldbUpdateEntry *updateentry; /* Update entry copied here */
820 struct ubik_trans *trans;
821 afs_int32 blockindex, errorcode;
822 struct nvlentry tentry;
824 COUNT_REQ(VLUPDATEENTRY);
825 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
827 if ((voltype != -1) && (InvalidVoltype(voltype)))
829 if (releasetype && InvalidReleasetype(releasetype))
830 END(VL_BADRELLOCKTYPE);
831 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
834 VLog(1, ("Update Volume %u %s\n", volid, rxinfo(rxcall)));
835 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
836 if (blockindex == 0) { /* entry not found */
838 errorcode = VL_NOENT;
842 /* Do the actual updating of the entry, tentry. */
844 get_vldbupdateentry(trans, blockindex, updateentry, &tentry)) {
848 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
849 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
852 END(ubik_EndTrans(trans));
856 ubik_AbortTrans(trans);
859 osi_auditU(rxcall, VLUpdateEntryEvent, errorcode, AUD_LONG, volid,
866 SVL_UpdateEntryByName(rxcall, volname, updateentry, releasetype)
867 struct rx_call *rxcall;
869 afs_int32 releasetype;
870 struct VldbUpdateEntry *updateentry; /* Update entry copied here */
872 struct ubik_trans *trans;
873 afs_int32 blockindex, errorcode;
874 struct nvlentry tentry;
876 COUNT_REQ(VLUPDATEENTRYBYNAME);
877 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
879 if (releasetype && InvalidReleasetype(releasetype))
880 END(VL_BADRELLOCKTYPE);
881 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
884 blockindex = FindByName(trans, volname, &tentry, &errorcode);
885 if (blockindex == 0) { /* entry not found */
887 errorcode = VL_NOENT;
891 /* Do the actual updating of the entry, tentry. */
893 get_vldbupdateentry(trans, blockindex, updateentry, &tentry)) {
897 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
898 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
901 END(ubik_EndTrans(trans));
905 ubik_AbortTrans(trans);
908 osi_auditU(rxcall, VLUpdateEntryEvent, errorcode, AUD_LONG, -1, AUD_END);
913 /* Set a lock to the vldb entry for volid (of type voltype if not -1). */
915 SVL_SetLock(rxcall, volid, voltype, voloper)
916 struct rx_call *rxcall;
921 afs_int32 timestamp, blockindex, errorcode;
922 struct ubik_trans *trans;
923 struct nvlentry tentry;
925 COUNT_REQ(VLSETLOCK);
926 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
928 if ((voltype != -1) && (InvalidVoltype(voltype)))
930 if (InvalidOperation(voloper))
932 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
935 VLog(1, ("SetLock Volume %u %s\n", volid, rxinfo(rxcall)));
936 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
937 if (blockindex == NULLO) {
939 errorcode = VL_NOENT;
942 if (tentry.flags & VLDELETED) {
943 ABORT(VL_ENTDELETED);
945 timestamp = FT_ApproxTime();
947 /* Check if entry is already locked; note that we unlock any entry
948 * locked more than MAXLOCKTIME seconds */
949 if ((tentry.LockTimestamp)
950 && ((timestamp - tentry.LockTimestamp) < MAXLOCKTIME)) {
951 ABORT(VL_ENTRYLOCKED);
954 /* Consider it an unlocked entry: set current timestamp, caller
955 * and active vol operation */
956 tentry.LockTimestamp = timestamp;
957 tentry.LockAfsId = 0; /* Not implemented yet */
958 if (tentry.flags & VLOP_RELEASE) {
961 tentry.flags &= ~VLOP_ALLOPERS; /* Clear any possible older operation bit */
962 tentry.flags |= voloper;
964 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
967 END(ubik_EndTrans(trans));
971 ubik_AbortTrans(trans);
974 osi_auditU(rxcall, VLSetLockEvent, errorcode, AUD_LONG, volid, AUD_END);
979 /* Release an already locked vldb entry. Releasetype determines what
980 * fields (afsid and/or volume operation) will be cleared along with
981 * the lock time stamp. */
984 SVL_ReleaseLock(rxcall, volid, voltype, releasetype)
985 struct rx_call *rxcall;
988 afs_int32 releasetype;
990 afs_int32 blockindex, errorcode;
991 struct ubik_trans *trans;
992 struct nvlentry tentry;
994 COUNT_REQ(VLRELEASELOCK);
995 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
997 if ((voltype != -1) && (InvalidVoltype(voltype)))
999 if (releasetype && InvalidReleasetype(releasetype))
1000 END(VL_BADRELLOCKTYPE);
1001 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
1004 VLog(1, ("ReleaseLock Volume %u %s\n", volid, rxinfo(rxcall)));
1005 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
1006 if (blockindex == NULLO) {
1008 errorcode = VL_NOENT;
1011 if (tentry.flags & VLDELETED) {
1012 ABORT(VL_ENTDELETED);
1015 ReleaseEntry(&tentry, releasetype); /* Unlock the appropriate fields */
1016 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
1019 END(ubik_EndTrans(trans));
1023 ubik_AbortTrans(trans);
1026 osi_auditU(rxcall, VLReleaseLockEvent, errorcode, AUD_LONG, volid,
1032 /* 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. */
1034 SVL_ListEntry(rxcall, previous_index, count, next_index, aentry)
1035 struct rx_call *rxcall;
1036 afs_int32 previous_index;
1038 afs_int32 *next_index;
1039 struct vldbentry *aentry;
1042 struct ubik_trans *trans;
1043 struct nvlentry tentry;
1045 COUNT_REQ(VLLISTENTRY);
1046 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1048 VLog(25, ("OListEntry index=%d %s\n", previous_index, rxinfo(rxcall)));
1049 *next_index = NextEntry(trans, previous_index, &tentry, count);
1051 vlentry_to_vldbentry(&tentry, aentry);
1052 return (ubik_EndTrans(trans));
1055 /* 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. */
1057 SVL_ListEntryN(rxcall, previous_index, count, next_index, aentry)
1058 struct rx_call *rxcall;
1059 afs_int32 previous_index;
1061 afs_int32 *next_index;
1062 struct nvldbentry *aentry;
1065 struct ubik_trans *trans;
1066 struct nvlentry tentry;
1068 COUNT_REQ(VLLISTENTRYN);
1069 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1071 VLog(25, ("ListEntry index=%d %s\n", previous_index, rxinfo(rxcall)));
1072 *next_index = NextEntry(trans, previous_index, &tentry, count);
1074 vlentry_to_nvldbentry(&tentry, aentry);
1075 return (ubik_EndTrans(trans));
1079 /* 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. */
1081 SVL_ListAttributes(rxcall, attributes, nentries, vldbentries)
1082 struct rx_call *rxcall;
1083 struct VldbListByAttributes *attributes;
1084 afs_int32 *nentries;
1085 bulkentries *vldbentries;
1087 int errorcode, allocCount = 0;
1088 struct ubik_trans *trans;
1089 struct nvlentry tentry;
1090 struct vldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1093 COUNT_REQ(VLLISTATTRIBUTES);
1094 vldbentries->bulkentries_val = 0;
1095 vldbentries->bulkentries_len = *nentries = 0;
1096 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1098 allocCount = VLDBALLOCCOUNT;
1099 Vldbentry = VldbentryFirst = vldbentries->bulkentries_val =
1100 (vldbentry *) malloc(allocCount * sizeof(vldbentry));
1101 if (Vldbentry == NULL) {
1103 ubik_AbortTrans(trans);
1106 VldbentryLast = VldbentryFirst + allocCount;
1107 /* Handle the attribute by volume id totally separate of the rest (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!) */
1108 if (attributes->Mask & VLLIST_VOLUMEID) {
1109 afs_int32 blockindex;
1112 FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1113 if (blockindex == 0) {
1115 errorcode = VL_NOENT;
1117 ubik_AbortTrans(trans);
1118 if (vldbentries->bulkentries_val)
1119 free((char *)vldbentries->bulkentries_val);
1120 vldbentries->bulkentries_val = 0;
1121 vldbentries->bulkentries_len = 0;
1125 put_attributeentry(&Vldbentry, &VldbentryFirst, &VldbentryLast,
1126 vldbentries, &tentry, nentries, &allocCount)) {
1128 ubik_AbortTrans(trans);
1129 if (vldbentries->bulkentries_val)
1130 free((char *)vldbentries->bulkentries_val);
1131 vldbentries->bulkentries_val = 0;
1132 vldbentries->bulkentries_len = 0;
1133 return VL_SIZEEXCEEDED;
1136 afs_int32 nextblockindex = 0, count = 0, k = 0, match = 0;
1137 while (nextblockindex =
1138 NextEntry(trans, nextblockindex, &tentry, &count)) {
1139 if (++pollcount > 50) {
1140 #ifndef AFS_PTHREAD_ENV
1146 if (attributes->Mask & VLLIST_SERVER) {
1149 IpAddrToRelAddr(attributes->server,
1150 (struct ubik_trans *)0)) == -1)
1152 for (k = 0; k < OMAXNSERVERS; k++) {
1153 if (tentry.serverNumber[k] == BADSERVERID)
1155 if (tentry.serverNumber[k] == serverindex) {
1163 if (attributes->Mask & VLLIST_PARTITION) {
1165 if (tentry.serverPartition[k] != attributes->partition)
1168 for (k = 0; k < OMAXNSERVERS; k++) {
1169 if (tentry.serverNumber[k] == BADSERVERID)
1171 if (tentry.serverPartition[k] ==
1172 attributes->partition) {
1182 if (attributes->Mask & VLLIST_FLAG) {
1183 if (!(tentry.flags & attributes->flag))
1187 put_attributeentry(&Vldbentry, &VldbentryFirst,
1188 &VldbentryLast, vldbentries, &tentry,
1189 nentries, &allocCount)) {
1191 ubik_AbortTrans(trans);
1192 if (vldbentries->bulkentries_val)
1193 free((char *)vldbentries->bulkentries_val);
1194 vldbentries->bulkentries_val = 0;
1195 vldbentries->bulkentries_len = 0;
1200 if (vldbentries->bulkentries_len
1201 && (allocCount > vldbentries->bulkentries_len)) {
1203 vldbentries->bulkentries_val =
1204 (vldbentry *) realloc(vldbentries->bulkentries_val,
1205 vldbentries->bulkentries_len *
1207 if (vldbentries->bulkentries_val == NULL) {
1209 ubik_AbortTrans(trans);
1214 ("ListAttrs nentries=%d %s\n", vldbentries->bulkentries_len,
1216 return (ubik_EndTrans(trans));
1220 SVL_ListAttributesN(rxcall, attributes, nentries, vldbentries)
1221 struct rx_call *rxcall;
1222 struct VldbListByAttributes *attributes;
1223 afs_int32 *nentries;
1224 nbulkentries *vldbentries;
1226 int errorcode, allocCount = 0;
1227 struct ubik_trans *trans;
1228 struct nvlentry tentry;
1229 struct nvldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1232 COUNT_REQ(VLLISTATTRIBUTESN);
1233 vldbentries->nbulkentries_val = 0;
1234 vldbentries->nbulkentries_len = *nentries = 0;
1235 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1237 allocCount = VLDBALLOCCOUNT;
1238 Vldbentry = VldbentryFirst = vldbentries->nbulkentries_val =
1239 (nvldbentry *) malloc(allocCount * sizeof(nvldbentry));
1240 if (Vldbentry == NULL) {
1242 ubik_AbortTrans(trans);
1245 VldbentryLast = VldbentryFirst + allocCount;
1246 /* Handle the attribute by volume id totally separate of the rest (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!) */
1247 if (attributes->Mask & VLLIST_VOLUMEID) {
1248 afs_int32 blockindex;
1251 FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1252 if (blockindex == 0) {
1254 errorcode = VL_NOENT;
1256 ubik_AbortTrans(trans);
1257 if (vldbentries->nbulkentries_val)
1258 free((char *)vldbentries->nbulkentries_val);
1259 vldbentries->nbulkentries_val = 0;
1260 vldbentries->nbulkentries_len = 0;
1264 put_nattributeentry(&Vldbentry, &VldbentryFirst, &VldbentryLast,
1265 vldbentries, &tentry, 0, 0, nentries,
1268 ubik_AbortTrans(trans);
1269 if (vldbentries->nbulkentries_val)
1270 free((char *)vldbentries->nbulkentries_val);
1271 vldbentries->nbulkentries_val = 0;
1272 vldbentries->nbulkentries_len = 0;
1273 return VL_SIZEEXCEEDED;
1276 afs_int32 nextblockindex = 0, count = 0, k = 0, match = 0;
1277 while (nextblockindex =
1278 NextEntry(trans, nextblockindex, &tentry, &count)) {
1279 if (++pollcount > 50) {
1280 #ifndef AFS_PTHREAD_ENV
1287 if (attributes->Mask & VLLIST_SERVER) {
1290 IpAddrToRelAddr(attributes->server,
1291 (struct ubik_trans *)0)) == -1)
1293 for (k = 0; k < NMAXNSERVERS; k++) {
1294 if (tentry.serverNumber[k] == BADSERVERID)
1296 if (tentry.serverNumber[k] == serverindex) {
1304 if (attributes->Mask & VLLIST_PARTITION) {
1306 if (tentry.serverPartition[k] != attributes->partition)
1309 for (k = 0; k < NMAXNSERVERS; k++) {
1310 if (tentry.serverNumber[k] == BADSERVERID)
1312 if (tentry.serverPartition[k] ==
1313 attributes->partition) {
1323 if (attributes->Mask & VLLIST_FLAG) {
1324 if (!(tentry.flags & attributes->flag))
1328 put_nattributeentry(&Vldbentry, &VldbentryFirst,
1329 &VldbentryLast, vldbentries, &tentry, 0,
1330 0, nentries, &allocCount)) {
1332 ubik_AbortTrans(trans);
1333 if (vldbentries->nbulkentries_val)
1334 free((char *)vldbentries->nbulkentries_val);
1335 vldbentries->nbulkentries_val = 0;
1336 vldbentries->nbulkentries_len = 0;
1341 if (vldbentries->nbulkentries_len
1342 && (allocCount > vldbentries->nbulkentries_len)) {
1344 vldbentries->nbulkentries_val =
1345 (nvldbentry *) realloc(vldbentries->nbulkentries_val,
1346 vldbentries->nbulkentries_len *
1347 sizeof(nvldbentry));
1348 if (vldbentries->nbulkentries_val == NULL) {
1350 ubik_AbortTrans(trans);
1355 ("NListAttrs nentries=%d %s\n", vldbentries->nbulkentries_len,
1357 return (ubik_EndTrans(trans));
1362 SVL_ListAttributesN2(rxcall, attributes, name, startindex, nentries,
1363 vldbentries, nextstartindex)
1364 struct rx_call *rxcall;
1365 struct VldbListByAttributes *attributes;
1366 char *name; /* Wildcarded volume name */
1367 afs_int32 startindex;
1368 afs_int32 *nentries;
1369 nbulkentries *vldbentries;
1370 afs_int32 *nextstartindex;
1372 int errorcode = 0, maxCount = VLDBALLOCCOUNT;
1373 struct ubik_trans *trans;
1374 struct nvlentry tentry;
1375 struct nvldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1376 afs_int32 blockindex = 0, count = 0, k, match;
1377 afs_int32 matchindex = 0;
1378 int serverindex = -1; /* no server found */
1379 int findserver = 0, findpartition = 0, findflag = 0, findname = 0;
1382 int namematchRWBK, namematchRO, thismatch;
1384 char volumename[VL_MAXNAMELEN];
1385 #ifdef HAVE_POSIX_REGEX
1387 int need_regfree = 0;
1390 COUNT_REQ(VLLISTATTRIBUTESN2);
1391 vldbentries->nbulkentries_val = 0;
1392 vldbentries->nbulkentries_len = 0;
1394 *nextstartindex = -1;
1396 errorcode = Init_VLdbase(&trans, LOCKREAD, this_op);
1400 Vldbentry = VldbentryFirst = vldbentries->nbulkentries_val =
1401 (nvldbentry *) malloc(maxCount * sizeof(nvldbentry));
1402 if (Vldbentry == NULL) {
1404 ubik_AbortTrans(trans);
1408 VldbentryLast = VldbentryFirst + maxCount;
1410 /* Handle the attribute by volume id totally separate of the rest
1411 * (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!)
1413 if (attributes->Mask & VLLIST_VOLUMEID) {
1415 FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1416 if (blockindex == 0) {
1418 errorcode = VL_NOENT;
1421 put_nattributeentry(&Vldbentry, &VldbentryFirst,
1422 &VldbentryLast, vldbentries, &tentry, 0,
1423 0, nentries, &maxCount);
1429 /* Search each entry in the database and return all entries
1430 * that match the request. It checks volumename (with
1431 * wildcarding), entry flags, server, and partition.
1434 /* Get the server index for matching server address */
1435 if (attributes->Mask & VLLIST_SERVER) {
1437 IpAddrToRelAddr(attributes->server, (struct ubik_trans *)0);
1438 if (serverindex == -1)
1442 findpartition = ((attributes->Mask & VLLIST_PARTITION) ? 1 : 0);
1443 findflag = ((attributes->Mask & VLLIST_FLAG) ? 1 : 0);
1444 if (name && (strcmp(name, ".*") != 0) && (strcmp(name, "") != 0)) {
1445 sprintf(volumename, "^%s$", name);
1446 #ifdef HAVE_POSIX_REGEX
1447 if (regcomp(&re, volumename, REG_NOSUB) != 0) {
1448 errorcode = VL_BADNAME;
1453 t = (char *)re_comp(volumename);
1455 errorcode = VL_BADNAME;
1462 /* Read each entry and see if it is the one we want */
1463 blockindex = startindex;
1464 while (blockindex = NextEntry(trans, blockindex, &tentry, &count)) {
1465 if (++pollcount > 50) {
1466 #ifndef AFS_PTHREAD_ENV
1472 /* Step through each server index searching for a match.
1473 * Match to an existing RW, BK, or RO volume name (preference
1474 * is in this order). Remember which index we matched against.
1476 namematchRWBK = namematchRO = 0; /* 0->notTried; 1->match; 2->noMatch */
1480 && (tentry.serverNumber[k] != BADSERVERID)); k++) {
1481 thismatch = 0; /* does this index match */
1483 /* Match against the RW or BK volume name. Remember
1484 * results in namematchRWBK. Prefer RW over BK.
1486 if (tentry.serverFlags[k] & VLSF_RWVOL) {
1487 /* Does the name match the RW name */
1488 if (tentry.flags & VLF_RWEXISTS) {
1490 sprintf(volumename, "%s", tentry.name);
1491 #ifdef HAVE_POSIX_REGEX
1492 if (regexec(&re, volumename, 0, NULL, 0) == 0) {
1493 thismatch = VLSF_RWVOL;
1496 if (re_exec(volumename)) {
1497 thismatch = VLSF_RWVOL;
1501 thismatch = VLSF_RWVOL;
1505 /* Does the name match the BK name */
1506 if (!thismatch && (tentry.flags & VLF_BACKEXISTS)) {
1508 sprintf(volumename, "%s.backup", tentry.name);
1509 #ifdef HAVE_POSIX_REGEX
1510 if (regexec(&re, volumename, 0, NULL, 0) == 0) {
1511 thismatch = VLSF_BACKVOL;
1514 if (re_exec(volumename)) {
1515 thismatch = VLSF_BACKVOL;
1519 thismatch = VLSF_BACKVOL;
1523 namematchRWBK = (thismatch ? 1 : 2);
1526 /* Match with the RO volume name. Compare once and
1527 * remember results in namematchRO. Note that this will
1528 * pick up entries marked NEWREPSITEs and DONTUSE.
1531 if (tentry.flags & VLF_ROEXISTS) {
1535 ((namematchRO == 1) ? VLSF_ROVOL : 0);
1537 sprintf(volumename, "%s.readonly",
1539 #ifdef HAVE_POSIX_REGEX
1540 if (regexec(&re, volumename, 0, NULL, 0) == 0) {
1541 thismatch = VLSF_ROVOL;
1544 if (re_exec(volumename))
1545 thismatch = VLSF_ROVOL;
1549 thismatch = VLSF_ROVOL;
1552 namematchRO = (thismatch ? 1 : 2);
1555 /* Is there a server match */
1556 if (thismatch && findserver
1557 && (tentry.serverNumber[k] != serverindex))
1560 /* Is there a partition match */
1561 if (thismatch && findpartition
1562 && (tentry.serverPartition[k] != attributes->partition))
1565 /* Is there a flag match */
1566 if (thismatch && findflag
1567 && !(tentry.flags & attributes->flag))
1570 /* We found a match. Remember the index, and type */
1574 matchtype = thismatch;
1577 /* Since we prefer RW and BK volume matches over RO matches,
1578 * if we have already checked the RWBK name, then we already
1579 * found the best match and so end the search.
1581 * If we tried matching against the RW, BK, and RO volume names
1582 * and both failed, then we end the search (none will match).
1584 if ((match && namematchRWBK)
1585 || ((namematchRWBK == 2) && (namematchRO == 2)))
1589 /* Passed all the tests. Take it */
1592 put_nattributeentry(&Vldbentry, &VldbentryFirst,
1593 &VldbentryLast, vldbentries, &tentry,
1594 matchtype, matchindex, nentries,
1599 if (*nentries >= maxCount)
1600 break; /* collected the max */
1603 *nextstartindex = (blockindex ? blockindex : -1);
1607 #ifdef HAVE_POSIX_REGEX
1614 ubik_AbortTrans(trans);
1615 if (vldbentries->nbulkentries_val)
1616 free((char *)vldbentries->nbulkentries_val);
1617 vldbentries->nbulkentries_val = 0;
1618 vldbentries->nbulkentries_len = 0;
1619 *nextstartindex = -1;
1623 ("N2ListAttrs nentries=%d %s\n", vldbentries->nbulkentries_len,
1625 return (ubik_EndTrans(trans));
1630 /* Retrieves in vldbentries all vldb entries that match the specified
1631 * attributes (by server number, partition, volume type, and flag); if
1632 * volume id is specified then the associated list for that entry is
1633 * returned. CAUTION: This could be a very expensive call since in most
1634 * cases sequential search of all vldb entries is performed.
1637 SVL_LinkedList(rxcall, attributes, nentries, vldbentries)
1638 struct rx_call *rxcall;
1639 struct VldbListByAttributes *attributes;
1640 afs_int32 *nentries;
1641 vldb_list *vldbentries;
1644 struct ubik_trans *trans;
1645 struct nvlentry tentry;
1646 vldblist vllist, *vllistptr;
1647 afs_int32 blockindex, count, match;
1652 COUNT_REQ(VLLINKEDLIST);
1653 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1657 vldbentries->node = NULL;
1658 vllistptr = &vldbentries->node;
1660 /* List by volumeid */
1661 if (attributes->Mask & VLLIST_VOLUMEID) {
1663 FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1666 ubik_AbortTrans(trans);
1667 return (errorcode ? errorcode : VL_NOENT);
1670 vllist = (single_vldbentry *) malloc(sizeof(single_vldbentry));
1671 if (vllist == NULL) {
1673 ubik_AbortTrans(trans);
1676 vlentry_to_vldbentry(&tentry, &vllist->VldbEntry);
1677 vllist->next_vldb = NULL;
1679 *vllistptr = vllist; /* Thread onto list */
1680 vllistptr = &vllist->next_vldb;
1684 /* Search by server, partition, and flags */
1686 for (blockindex = NextEntry(trans, 0, &tentry, &count); blockindex;
1687 blockindex = NextEntry(trans, blockindex, &tentry, &count)) {
1690 if (++pollcount > 50) {
1691 #ifndef AFS_PTHREAD_ENV
1697 /* Does this volume exist on the desired server */
1698 if (attributes->Mask & VLLIST_SERVER) {
1700 IpAddrToRelAddr(attributes->server,
1701 (struct ubik_trans *)0);
1702 if (serverindex == -1)
1704 for (k = 0; k < OMAXNSERVERS; k++) {
1705 if (tentry.serverNumber[k] == BADSERVERID)
1707 if (tentry.serverNumber[k] == serverindex) {
1716 /* Does this volume exist on the desired partition */
1717 if (attributes->Mask & VLLIST_PARTITION) {
1719 if (tentry.serverPartition[k] != attributes->partition)
1722 for (k = 0; k < OMAXNSERVERS; k++) {
1723 if (tentry.serverNumber[k] == BADSERVERID)
1725 if (tentry.serverPartition[k] ==
1726 attributes->partition) {
1736 /* Does this volume have the desired flags */
1737 if (attributes->Mask & VLLIST_FLAG) {
1738 if (!(tentry.flags & attributes->flag))
1742 vllist = (single_vldbentry *) malloc(sizeof(single_vldbentry));
1743 if (vllist == NULL) {
1745 ubik_AbortTrans(trans);
1748 vlentry_to_vldbentry(&tentry, &vllist->VldbEntry);
1749 vllist->next_vldb = NULL;
1751 *vllistptr = vllist; /* Thread onto list */
1752 vllistptr = &vllist->next_vldb;
1754 if (smallMem && (*nentries >= VLDBALLOCCOUNT)) {
1756 ubik_AbortTrans(trans);
1757 return VL_SIZEEXCEEDED;
1762 return (ubik_EndTrans(trans));
1766 SVL_LinkedListN(rxcall, attributes, nentries, vldbentries)
1767 struct rx_call *rxcall;
1768 struct VldbListByAttributes *attributes;
1769 afs_int32 *nentries;
1770 nvldb_list *vldbentries;
1773 struct ubik_trans *trans;
1774 struct nvlentry tentry;
1775 nvldblist vllist, *vllistptr;
1776 afs_int32 blockindex, count, match;
1781 COUNT_REQ(VLLINKEDLISTN);
1782 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1786 vldbentries->node = NULL;
1787 vllistptr = &vldbentries->node;
1789 /* List by volumeid */
1790 if (attributes->Mask & VLLIST_VOLUMEID) {
1792 FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1795 ubik_AbortTrans(trans);
1796 return (errorcode ? errorcode : VL_NOENT);
1799 vllist = (single_nvldbentry *) malloc(sizeof(single_nvldbentry));
1800 if (vllist == NULL) {
1802 ubik_AbortTrans(trans);
1805 vlentry_to_nvldbentry(&tentry, &vllist->VldbEntry);
1806 vllist->next_vldb = NULL;
1808 *vllistptr = vllist; /* Thread onto list */
1809 vllistptr = &vllist->next_vldb;
1813 /* Search by server, partition, and flags */
1815 for (blockindex = NextEntry(trans, 0, &tentry, &count); blockindex;
1816 blockindex = NextEntry(trans, blockindex, &tentry, &count)) {
1819 if (++pollcount > 50) {
1820 #ifndef AFS_PTHREAD_ENV
1826 /* Does this volume exist on the desired server */
1827 if (attributes->Mask & VLLIST_SERVER) {
1829 IpAddrToRelAddr(attributes->server,
1830 (struct ubik_trans *)0);
1831 if (serverindex == -1)
1833 for (k = 0; k < NMAXNSERVERS; k++) {
1834 if (tentry.serverNumber[k] == BADSERVERID)
1836 if (tentry.serverNumber[k] == serverindex) {
1845 /* Does this volume exist on the desired partition */
1846 if (attributes->Mask & VLLIST_PARTITION) {
1848 if (tentry.serverPartition[k] != attributes->partition)
1851 for (k = 0; k < NMAXNSERVERS; k++) {
1852 if (tentry.serverNumber[k] == BADSERVERID)
1854 if (tentry.serverPartition[k] ==
1855 attributes->partition) {
1865 /* Does this volume have the desired flags */
1866 if (attributes->Mask & VLLIST_FLAG) {
1867 if (!(tentry.flags & attributes->flag))
1871 vllist = (single_nvldbentry *) malloc(sizeof(single_nvldbentry));
1872 if (vllist == NULL) {
1874 ubik_AbortTrans(trans);
1877 vlentry_to_nvldbentry(&tentry, &vllist->VldbEntry);
1878 vllist->next_vldb = NULL;
1880 *vllistptr = vllist; /* Thread onto list */
1881 vllistptr = &vllist->next_vldb;
1883 if (smallMem && (*nentries >= VLDBALLOCCOUNT)) {
1885 ubik_AbortTrans(trans);
1886 return VL_SIZEEXCEEDED;
1891 return (ubik_EndTrans(trans));
1894 /* Get back vldb header statistics (allocs, frees, maxvolumeid, totalentries, etc) and dynamic statistics (number of requests and/or aborts per remote procedure call, etc) */
1896 SVL_GetStats(rxcall, stats, vital_header)
1897 struct rx_call *rxcall;
1899 vital_vlheader *vital_header;
1901 register afs_int32 errorcode;
1902 struct ubik_trans *trans;
1904 COUNT_REQ(VLGETSTATS);
1906 /* Allow users to get statistics freely */
1907 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) /* Must be in 'UserList' to use */
1910 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1912 VLog(5, ("GetStats %s\n", rxinfo(rxcall)));
1913 memcpy((char *)vital_header, (char *)&cheader.vital_header,
1914 sizeof(vital_vlheader));
1915 memcpy((char *)stats, (char *)&dynamic_statistics, sizeof(vldstats));
1916 return (ubik_EndTrans(trans));
1919 /* Get the list of file server addresses from the VLDB. Currently it's pretty
1920 * easy to do. In the future, it might require a little bit of grunging
1921 * through the VLDB, but that's life.
1924 SVL_GetAddrs(rxcall, Handle, spare2, spare3, nentries, addrsp)
1925 struct rx_call *rxcall;
1926 afs_int32 Handle, spare2;
1927 struct VLCallBack *spare3;
1928 afs_int32 *nentries;
1931 register afs_int32 errorcode;
1932 struct ubik_trans *trans;
1936 COUNT_REQ(VLGETADDRS);
1937 addrsp->bulkaddrs_len = *nentries = 0;
1938 addrsp->bulkaddrs_val = 0;
1939 memset(spare3, 0, sizeof(struct VLCallBack));
1941 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1944 VLog(5, ("GetAddrs\n"));
1945 addrsp->bulkaddrs_val = taddrp =
1946 (afs_uint32 *) malloc(sizeof(afs_int32) * (MAXSERVERID + 1));
1947 nservers = *nentries = addrsp->bulkaddrs_len = 0;
1951 ubik_AbortTrans(trans);
1955 for (i = 0; i <= MAXSERVERID; i++) {
1956 if (*taddrp = ntohl(cheader.IpMappedAddr[i])) {
1962 addrsp->bulkaddrs_len = *nentries = nservers;
1963 return (ubik_EndTrans(trans));
1966 #define PADDR(addr) VLog(0,("%d.%d.%d.%d", (addr>>24)&0xff, (addr>>16)&0xff, (addr>>8) &0xff, addr&0xff));
1969 SVL_RegisterAddrs(rxcall, uuidp, spare1, addrsp)
1970 struct rx_call *rxcall;
1976 struct ubik_trans *trans;
1977 int cnt, h, i, j, k, m, base, index;
1978 struct extentaddr *exp = 0, *tex;
1980 afs_uint32 addrs[VL_MAXIPADDRS_PERMH];
1982 int count, willChangeEntry, foundUuidEntry, willReplaceCnt;
1983 int WillReplaceEntry, WillChange[MAXSERVERID + 1];
1985 int ReplaceEntry = 0;
1988 COUNT_REQ(VLREGADDR);
1989 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
1991 if (code = Init_VLdbase(&trans, LOCKWRITE, this_op))
1994 /* Eliminate duplicates from IP address list */
1995 for (k = 0, cnt = 0; k < addrsp->bulkaddrs_len; k++) {
1996 if (addrsp->bulkaddrs_val[k] == 0)
1998 for (m = 0; m < cnt; m++) {
1999 if (addrs[m] == addrsp->bulkaddrs_val[k])
2003 if (m == VL_MAXIPADDRS_PERMH) {
2005 ("Number of addresses exceeds %d. Cannot register IP addr 0x%x in VLDB\n",
2006 VL_MAXIPADDRS_PERMH, addrsp->bulkaddrs_val[k]));
2008 addrs[m] = addrsp->bulkaddrs_val[k];
2014 ubik_AbortTrans(trans);
2015 return VL_INDEXERANGE;
2021 /* For each server registered within the VLDB */
2022 for (srvidx = 0; srvidx <= MAXSERVERID; srvidx++) {
2023 willChangeEntry = 0;
2024 WillReplaceEntry = 1;
2025 if ((HostAddress[srvidx] & 0xff000000) == 0xff000000) {
2026 /* The server is registered as a multihomed */
2027 base = (HostAddress[srvidx] >> 16) & 0xff;
2028 index = HostAddress[srvidx] & 0x0000ffff;
2029 if (base >= VL_MAX_ADDREXTBLKS) {
2031 ("Internal error: Multihome extent base is too large. Base %d index %d\n",
2035 if (index >= VL_MHSRV_PERBLK) {
2037 ("Internal error: Multihome extent index is too large. Base %d index %d\n",
2041 if (!ex_addr[base]) {
2043 ("Internal error: Multihome extent does not exist. Base %d\n",
2048 /* See if the addresses to register will change this server entry */
2049 exp = &ex_addr[base][index];
2050 tuuid = exp->ex_hostuuid;
2051 afs_ntohuuid(&tuuid);
2052 if (afs_uuid_equal(uuidp, &tuuid)) {
2056 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2057 if (!exp->ex_addrs[mhidx])
2059 for (k = 0; k < cnt; k++) {
2060 if (ntohl(exp->ex_addrs[mhidx]) == addrs[k]) {
2061 willChangeEntry = 1;
2062 WillChange[count] = srvidx;
2067 WillReplaceEntry = 0;
2071 /* The server is not registered as a multihomed.
2072 * See if the addresses to register will replace this server entry.
2074 for (k = 0; k < cnt; k++) {
2075 if (HostAddress[srvidx] == addrs[k]) {
2076 willChangeEntry = 1;
2077 WillChange[count] = srvidx;
2078 WillReplaceEntry = 1;
2083 if (willChangeEntry) {
2084 if (WillReplaceEntry) {
2086 ReplaceEntry = srvidx;
2092 /* If we found the uuid in the VLDB and if we are replacing another
2093 * entire entry, then complain and fail. Also, if we did not find
2094 * the uuid in the VLDB and the IP addresses being registered was
2095 * found in more than one other entry, then we don't know which one
2096 * to replace and will complain and fail.
2098 if ((foundUuidEntry && (willReplaceCnt > 0))
2099 || (!foundUuidEntry && (count > 1))) {
2101 ("The following fileserver is being registered in the VLDB:\n"));
2103 for (k = 0; k < cnt; k++) {
2110 if (foundUuidEntry) {
2112 (" It would have replaced the existing VLDB server entry:\n"));
2113 VLog(0, (" entry %d: [", FoundUuid));
2114 base = (HostAddress[FoundUuid] >> 16) & 0xff;
2115 index = HostAddress[FoundUuid] & 0x0000ffff;
2116 exp = &ex_addr[base][index];
2117 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2118 if (!exp->ex_addrs[mhidx])
2122 PADDR(ntohl(exp->ex_addrs[mhidx]));
2128 VLog(0, (" Yet another VLDB server entry exists:\n"));
2130 VLog(0, (" Yet other VLDB server entries exist:\n"));
2131 for (j = 0; j < count; j++) {
2132 srvidx = WillChange[j];
2133 VLog(0, (" entry %d: ", srvidx));
2134 if ((HostAddress[srvidx] & 0xff000000) == 0xff000000) {
2136 base = (HostAddress[srvidx] >> 16) & 0xff;
2137 index = HostAddress[srvidx] & 0x0000ffff;
2138 exp = &ex_addr[base][index];
2139 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2140 if (!exp->ex_addrs[mhidx])
2144 PADDR(ntohl(exp->ex_addrs[mhidx]));
2148 PADDR(HostAddress[srvidx]);
2154 VLog(0, (" You must 'vos changeaddr' this other server entry\n"));
2157 (" You must 'vos changeaddr' these other server entries\n"));
2160 (" and/or remove the sysid file from the registering fileserver\n"));
2161 VLog(0, (" before the fileserver can be registered in the VLDB.\n"));
2163 ubik_AbortTrans(trans);
2164 return VL_MULTIPADDR;
2167 /* Passed the checks. Now find and update the existing mh entry, or create
2170 if (foundUuidEntry) {
2171 /* Found the entry with same uuid. See if we need to change it */
2174 fbase = (HostAddress[FoundUuid] >> 16) & 0xff;
2175 index = HostAddress[FoundUuid] & 0x0000ffff;
2176 exp = &ex_addr[fbase][index];
2178 /* Determine if the entry has changed */
2179 for (k = 0; ((k < cnt) && !change); k++) {
2180 if (ntohl(exp->ex_addrs[k]) != addrs[k])
2183 for (; ((k < VL_MAXIPADDRS_PERMH) && !change); k++) {
2184 if (exp->ex_addrs[k] != 0)
2188 return (ubik_EndTrans(trans));
2192 VLog(0, ("The following fileserver is being registered in the VLDB:\n"));
2194 for (k = 0; k < cnt; k++) {
2201 if (foundUuidEntry) {
2203 (" It will replace the following existing entry in the VLDB (same uuid):\n"));
2204 VLog(0, (" entry %d: [", FoundUuid));
2205 for (k = 0; k < VL_MAXIPADDRS_PERMH; k++) {
2206 if (exp->ex_addrs[k] == 0)
2210 PADDR(ntohl(exp->ex_addrs[k]));
2213 } else if (willReplaceCnt || (count == 1)) {
2214 /* If we are not replacing an entry and there is only one entry to change,
2215 * then we will replace that entry.
2217 if (!willReplaceCnt) {
2218 ReplaceEntry = WillChange[0];
2222 /* Have an entry that needs to be replaced */
2223 if ((HostAddress[ReplaceEntry] & 0xff000000) == 0xff000000) {
2224 fbase = (HostAddress[ReplaceEntry] >> 16) & 0xff;
2225 index = HostAddress[ReplaceEntry] & 0x0000ffff;
2226 exp = &ex_addr[fbase][index];
2229 (" It will replace the following existing entry in the VLDB (new uuid):\n"));
2230 VLog(0, (" entry %d: [", ReplaceEntry));
2231 for (k = 0; k < VL_MAXIPADDRS_PERMH; k++) {
2232 if (exp->ex_addrs[k] == 0)
2236 PADDR(ntohl(exp->ex_addrs[k]));
2240 /* Not a mh entry. So we have to create a new mh entry and
2241 * put it on the ReplaceEntry slot of the HostAddress array.
2243 VLog(0, (" It will replace existing entry %d, ", ReplaceEntry));
2244 PADDR(HostAddress[ReplaceEntry]);
2245 VLog(0,(", in the VLDB (new uuid):\n"));
2248 FindExtentBlock(trans, uuidp, 1, ReplaceEntry, &exp, &fbase);
2250 ubik_AbortTrans(trans);
2251 return (code ? code : VL_IO);
2255 /* There is no entry for this server, must create a new mh entry as
2256 * well as use a new slot of the HostAddress array.
2258 VLog(0, (" It will create a new entry in the VLDB.\n"));
2259 code = FindExtentBlock(trans, uuidp, 1, -1, &exp, &fbase);
2261 ubik_AbortTrans(trans);
2262 return (code ? code : VL_IO);
2266 /* Now we have a mh entry to fill in. Update the uuid, bump the
2267 * uniquifier, and fill in its IP addresses.
2270 afs_htonuuid(&tuuid);
2271 exp->ex_hostuuid = tuuid;
2272 exp->ex_uniquifier = htonl(ntohl(exp->ex_uniquifier) + 1);
2273 for (k = 0; k < cnt; k++) {
2274 exp->ex_addrs[k] = htonl(addrs[k]);
2276 for (; k < VL_MAXIPADDRS_PERMH; k++) {
2277 exp->ex_addrs[k] = 0;
2280 /* Write the new mh entry out */
2283 DOFFSET(ntohl(ex_addr[0]->ex_contaddrs[fbase]),
2284 (char *)ex_addr[fbase], (char *)exp), (char *)exp,
2286 ubik_AbortTrans(trans);
2290 /* Remove any common addresses from other mh entres. We know these entries
2291 * are being changed and not replaced so they are mh entries.
2294 for (i = 0; i < count; i++) {
2297 /* Skip the entry we replaced */
2298 if (willReplaceCnt && (WillChange[i] == ReplaceEntry))
2301 base = (HostAddress[WillChange[i]] >> 16) & 0xff;
2302 index = HostAddress[WillChange[i]] & 0x0000ffff;
2303 tex = &ex_addr[fbase][index];
2307 (" The following existing entries in the VLDB will be updated:\n"));
2309 VLog(0, (" entry %d: [", WillChange[i]));
2310 for (h = j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2311 if (tex->ex_addrs[j]) {
2314 PADDR(ntohl(tex->ex_addrs[j]));
2317 for (k = 0; k < cnt; k++) {
2318 if (ntohl(tex->ex_addrs[j]) == addrs[k])
2322 /* Not found, so we keep it */
2323 tex->ex_addrs[h] = tex->ex_addrs[j];
2327 for (j = h; j < VL_MAXIPADDRS_PERMH; j++) {
2328 tex->ex_addrs[j] = 0; /* zero rest of mh entry */
2332 /* Write out the modified mh entry */
2333 tex->ex_uniquifier = htonl(ntohl(tex->ex_uniquifier) + 1);
2335 DOFFSET(ntohl(ex_addr[0]->ex_contaddrs[base]),
2336 (char *)ex_addr[base], (char *)tex);
2337 if (vlwrite(trans, doff, (char *)tex, sizeof(*tex))) {
2338 ubik_AbortTrans(trans);
2343 return (ubik_EndTrans(trans));
2347 SVL_GetAddrsU(rxcall, attributes, uuidpo, uniquifier, nentries, addrsp)
2348 struct rx_call *rxcall;
2349 struct ListAddrByAttributes *attributes;
2351 afs_int32 *uniquifier, *nentries;
2354 register afs_int32 errorcode, index = -1, offset;
2355 struct ubik_trans *trans;
2356 int nservers, i, j, base = 0;
2357 struct extentaddr *exp = 0;
2359 afs_uint32 *taddrp, taddr;
2361 COUNT_REQ(VLGETADDRSU);
2362 addrsp->bulkaddrs_len = *nentries = 0;
2363 addrsp->bulkaddrs_val = 0;
2364 VLog(5, ("GetAddrsU %s\n", rxinfo(rxcall)));
2365 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
2368 if (attributes->Mask & VLADDR_IPADDR) {
2369 if (attributes->Mask & (VLADDR_INDEX | VLADDR_UUID)) {
2370 ubik_AbortTrans(trans);
2373 for (base = 0; base < VL_MAX_ADDREXTBLKS; base++) {
2376 for (i = 1; i < VL_MHSRV_PERBLK; i++) {
2377 exp = &ex_addr[base][i];
2378 tuuid = exp->ex_hostuuid;
2379 afs_ntohuuid(&tuuid);
2380 if (afs_uuid_is_nil(&tuuid))
2382 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2383 if (exp->ex_addrs[j]
2384 && (ntohl(exp->ex_addrs[j]) == attributes->ipaddr)) {
2388 if (j < VL_MAXIPADDRS_PERMH)
2391 if (i < VL_MHSRV_PERBLK)
2394 if (base >= VL_MAX_ADDREXTBLKS) {
2395 ubik_AbortTrans(trans);
2398 } else if (attributes->Mask & VLADDR_INDEX) {
2399 if (attributes->Mask & (VLADDR_IPADDR | VLADDR_UUID)) {
2400 ubik_AbortTrans(trans);
2403 index = attributes->index;
2404 if (index < 1 || index >= (VL_MAX_ADDREXTBLKS * VL_MHSRV_PERBLK)) {
2405 ubik_AbortTrans(trans);
2406 return VL_INDEXERANGE;
2408 base = index / VL_MHSRV_PERBLK;
2409 offset = index % VL_MHSRV_PERBLK;
2411 ubik_AbortTrans(trans);
2414 if (!ex_addr[base]) {
2415 ubik_AbortTrans(trans);
2416 return VL_INDEXERANGE;
2418 exp = &ex_addr[base][offset];
2419 } else if (attributes->Mask & VLADDR_UUID) {
2420 if (attributes->Mask & (VLADDR_IPADDR | VLADDR_INDEX)) {
2421 ubik_AbortTrans(trans);
2424 if (!ex_addr[0]) { /* mh servers probably aren't setup on this vldb */
2425 ubik_AbortTrans(trans);
2429 FindExtentBlock(trans, &attributes->uuid, 0, -1, &exp, &base)) {
2430 ubik_AbortTrans(trans);
2434 ubik_AbortTrans(trans);
2439 ubik_AbortTrans(trans);
2442 addrsp->bulkaddrs_val = taddrp =
2443 (afs_uint32 *) malloc(sizeof(afs_int32) * (MAXSERVERID + 1));
2444 nservers = *nentries = addrsp->bulkaddrs_len = 0;
2447 ubik_AbortTrans(trans);
2450 tuuid = exp->ex_hostuuid;
2451 afs_ntohuuid(&tuuid);
2452 if (afs_uuid_is_nil(&tuuid)) {
2453 ubik_AbortTrans(trans);
2459 *uniquifier = ntohl(exp->ex_uniquifier);
2460 for (i = 0; i < VL_MAXIPADDRS_PERMH; i++) {
2461 if (exp->ex_addrs[i]) {
2462 taddr = ntohl(exp->ex_addrs[i]);
2463 /* Weed out duplicates */
2464 for (j = 0; j < nservers; j++) {
2465 if (taddrp[j] == taddr)
2468 if ((j == nservers) && (j <= MAXSERVERID)) {
2469 taddrp[nservers] = taddr;
2474 addrsp->bulkaddrs_len = *nentries = nservers;
2475 return (ubik_EndTrans(trans));
2478 /* ============> End of Exported vldb RPC functions <============= */
2481 /* Routine that copies the given vldb entry to the output buffer, vldbentries. */
2483 put_attributeentry(Vldbentry, VldbentryFirst, VldbentryLast, vldbentries,
2484 entry, nentries, alloccnt)
2485 struct vldbentry **Vldbentry, **VldbentryFirst, **VldbentryLast;
2486 bulkentries *vldbentries;
2487 struct nvlentry *entry;
2488 afs_int32 *nentries, *alloccnt;
2493 if (*Vldbentry == *VldbentryLast) {
2495 return VL_SIZEEXCEEDED; /* no growing if smallMem defined */
2497 /* Allocate another set of memory; each time allocate twice as
2498 * many blocks as the last time. When we reach VLDBALLOCLIMIT,
2499 * then grow in increments of VLDBALLOCINCR.
2501 allo = (*alloccnt > VLDBALLOCLIMIT) ? VLDBALLOCINCR : *alloccnt;
2503 (vldbentry *) realloc(*VldbentryFirst,
2504 (*alloccnt + allo) * sizeof(vldbentry));
2508 *VldbentryFirst = vldbentries->bulkentries_val = reall;
2509 *Vldbentry = *VldbentryFirst + *alloccnt;
2510 *VldbentryLast = *Vldbentry + allo;
2513 vlentry_to_vldbentry(entry, *Vldbentry);
2516 vldbentries->bulkentries_len++;
2521 put_nattributeentry(Vldbentry, VldbentryFirst, VldbentryLast, vldbentries,
2522 entry, matchtype, matchindex, nentries, alloccnt)
2523 struct nvldbentry **Vldbentry, **VldbentryFirst, **VldbentryLast;
2524 nbulkentries *vldbentries;
2525 struct nvlentry *entry;
2526 afs_int32 matchtype, matchindex, *nentries, *alloccnt;
2531 if (*Vldbentry == *VldbentryLast) {
2533 return VL_SIZEEXCEEDED; /* no growing if smallMem defined */
2535 /* Allocate another set of memory; each time allocate twice as
2536 * many blocks as the last time. When we reach VLDBALLOCLIMIT,
2537 * then grow in increments of VLDBALLOCINCR.
2539 allo = (*alloccnt > VLDBALLOCLIMIT) ? VLDBALLOCINCR : *alloccnt;
2541 (nvldbentry *) realloc(*VldbentryFirst,
2542 (*alloccnt + allo) * sizeof(nvldbentry));
2546 *VldbentryFirst = vldbentries->nbulkentries_val = reall;
2547 *Vldbentry = *VldbentryFirst + *alloccnt;
2548 *VldbentryLast = *Vldbentry + allo;
2551 vlentry_to_nvldbentry(entry, *Vldbentry);
2552 (*Vldbentry)->matchindex = (matchtype << 16) + matchindex;
2555 vldbentries->nbulkentries_len++;
2560 /* Common code to actually remove a vldb entry from the database. */
2562 RemoveEntry(trans, entryptr, tentry)
2563 struct ubik_trans *trans;
2565 struct nvlentry *tentry;
2567 register int errorcode;
2569 if (errorcode = UnthreadVLentry(trans, entryptr, tentry))
2571 if (errorcode = FreeBlock(trans, entryptr))
2577 ReleaseEntry(tentry, releasetype)
2578 struct nvlentry *tentry;
2579 afs_int32 releasetype;
2581 if (releasetype & LOCKREL_TIMESTAMP)
2582 tentry->LockTimestamp = 0;
2583 if (releasetype & LOCKREL_OPCODE)
2584 tentry->flags &= ~VLOP_ALLOPERS;
2585 if (releasetype & LOCKREL_AFSID)
2586 tentry->LockAfsId = 0;
2590 /* Verify that the incoming vldb entry is valid; multi type of error codes are returned. */
2592 check_vldbentry(aentry)
2593 struct vldbentry *aentry;
2597 if (InvalidVolname(aentry->name))
2599 if (aentry->nServers <= 0 || aentry->nServers > OMAXNSERVERS)
2600 return VL_BADSERVER;
2601 for (i = 0; i < aentry->nServers; i++) {
2602 /* if (aentry->serverNumber[i] < 0 || aentry->serverNumber[i] > MAXSERVERID)
2603 return VL_BADSERVER; */
2604 if (aentry->serverPartition[i] < 0
2605 || aentry->serverPartition[i] > MAXPARTITIONID)
2606 return VL_BADPARTITION;
2607 if (aentry->serverFlags[i] < 0
2608 || aentry->serverFlags[i] > MAXSERVERFLAG)
2609 return VL_BADSERVERFLAG;
2615 check_nvldbentry(aentry)
2616 struct nvldbentry *aentry;
2620 if (InvalidVolname(aentry->name))
2622 if (aentry->nServers <= 0 || aentry->nServers > NMAXNSERVERS)
2623 return VL_BADSERVER;
2624 for (i = 0; i < aentry->nServers; i++) {
2625 /* if (aentry->serverNumber[i] < 0 || aentry->serverNumber[i] > MAXSERVERID)
2626 return VL_BADSERVER; */
2627 if (aentry->serverPartition[i] < 0
2628 || aentry->serverPartition[i] > MAXPARTITIONID)
2629 return VL_BADPARTITION;
2630 if (aentry->serverFlags[i] < 0
2631 || aentry->serverFlags[i] > MAXSERVERFLAG)
2632 return VL_BADSERVERFLAG;
2638 /* Convert from the external vldb entry representation to its internal
2639 (more compact) form. This call should not change the hash chains! */
2641 vldbentry_to_vlentry(atrans, VldbEntry, VlEntry)
2642 struct ubik_trans *atrans;
2643 struct vldbentry *VldbEntry;
2644 struct nvlentry *VlEntry;
2648 if (strcmp(VlEntry->name, VldbEntry->name))
2649 strncpy(VlEntry->name, VldbEntry->name, sizeof(VlEntry->name));
2650 for (i = 0; i < VldbEntry->nServers; i++) {
2651 serverindex = IpAddrToRelAddr(VldbEntry->serverNumber[i], atrans);
2652 if (serverindex == -1)
2653 return VL_BADSERVER;
2654 VlEntry->serverNumber[i] = serverindex;
2655 VlEntry->serverPartition[i] = VldbEntry->serverPartition[i];
2656 VlEntry->serverFlags[i] = VldbEntry->serverFlags[i];
2658 for (; i < OMAXNSERVERS; i++)
2659 VlEntry->serverNumber[i] = VlEntry->serverPartition[i] =
2660 VlEntry->serverFlags[i] = BADSERVERID;
2661 for (i = 0; i < MAXTYPES; i++)
2662 VlEntry->volumeId[i] = VldbEntry->volumeId[i];
2663 VlEntry->cloneId = VldbEntry->cloneId;
2664 VlEntry->flags = VldbEntry->flags;
2669 nvldbentry_to_vlentry(atrans, VldbEntry, VlEntry)
2670 struct ubik_trans *atrans;
2671 struct nvldbentry *VldbEntry;
2672 struct nvlentry *VlEntry;
2676 if (strcmp(VlEntry->name, VldbEntry->name))
2677 strncpy(VlEntry->name, VldbEntry->name, sizeof(VlEntry->name));
2678 for (i = 0; i < VldbEntry->nServers; i++) {
2679 serverindex = IpAddrToRelAddr(VldbEntry->serverNumber[i], atrans);
2680 if (serverindex == -1)
2681 return VL_BADSERVER;
2682 VlEntry->serverNumber[i] = serverindex;
2683 VlEntry->serverPartition[i] = VldbEntry->serverPartition[i];
2684 VlEntry->serverFlags[i] = VldbEntry->serverFlags[i];
2686 for (; i < NMAXNSERVERS; i++)
2687 VlEntry->serverNumber[i] = VlEntry->serverPartition[i] =
2688 VlEntry->serverFlags[i] = BADSERVERID;
2689 for (i = 0; i < MAXTYPES; i++)
2690 VlEntry->volumeId[i] = VldbEntry->volumeId[i];
2691 VlEntry->cloneId = VldbEntry->cloneId;
2692 VlEntry->flags = VldbEntry->flags;
2697 /* 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. */
2699 get_vldbupdateentry(trans, blockindex, updateentry, VlEntry)
2700 struct ubik_trans *trans;
2701 afs_int32 blockindex;
2702 struct VldbUpdateEntry *updateentry;
2703 struct nvlentry *VlEntry;
2705 int i, j, errorcode, serverindex;
2707 if (updateentry->Mask & VLUPDATE_VOLUMENAME) {
2708 if (InvalidVolname(updateentry->name))
2710 if (errorcode = UnhashVolname(trans, blockindex, VlEntry))
2712 strncpy(VlEntry->name, updateentry->name, sizeof(VlEntry->name));
2713 HashVolname(trans, blockindex, VlEntry);
2716 if (updateentry->Mask & VLUPDATE_VOLNAMEHASH) {
2717 if (errorcode = UnhashVolname(trans, blockindex, VlEntry)) {
2718 if (errorcode != VL_NOENT)
2721 HashVolname(trans, blockindex, VlEntry);
2724 if (updateentry->Mask & VLUPDATE_FLAGS) {
2725 VlEntry->flags = updateentry->flags;
2727 if (updateentry->Mask & VLUPDATE_CLONEID) {
2728 VlEntry->cloneId = updateentry->cloneId;
2730 if (updateentry->Mask & VLUPDATE_RWID) {
2731 if (errorcode = UnhashVolid(trans, RWVOL, blockindex, VlEntry)) {
2732 if (errorcode != VL_NOENT)
2735 VlEntry->volumeId[RWVOL] = updateentry->spares3; /* rw id */
2736 if (errorcode = HashVolid(trans, RWVOL, blockindex, VlEntry))
2739 if (updateentry->Mask & VLUPDATE_READONLYID) {
2740 if (errorcode = UnhashVolid(trans, ROVOL, blockindex, VlEntry)) {
2741 if (errorcode != VL_NOENT)
2744 VlEntry->volumeId[ROVOL] = updateentry->ReadOnlyId;
2745 if (errorcode = HashVolid(trans, ROVOL, blockindex, VlEntry))
2748 if (updateentry->Mask & VLUPDATE_BACKUPID) {
2749 if (errorcode = UnhashVolid(trans, BACKVOL, blockindex, VlEntry)) {
2750 if (errorcode != VL_NOENT)
2753 VlEntry->volumeId[BACKVOL] = updateentry->BackupId;
2754 if (errorcode = HashVolid(trans, BACKVOL, blockindex, VlEntry))
2757 if (updateentry->Mask & VLUPDATE_REPSITES) {
2758 if (updateentry->nModifiedRepsites <= 0
2759 || updateentry->nModifiedRepsites > OMAXNSERVERS)
2760 return VL_BADSERVER;
2761 for (i = 0; i < updateentry->nModifiedRepsites; i++) {
2762 /* if (updateentry->RepsitesTargetServer[i] < 0 || updateentry->RepsitesTargetServer[i] > MAXSERVERID)
2763 return VL_BADSERVER; */
2764 if (updateentry->RepsitesTargetPart[i] < 0
2765 || updateentry->RepsitesTargetPart[i] > MAXPARTITIONID)
2766 return VL_BADPARTITION;
2767 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_DELETE) {
2769 repsite_exists(VlEntry,
2770 IpAddrToRelAddr(updateentry->
2771 RepsitesTargetServer[i],
2773 updateentry->RepsitesTargetPart[i])) !=
2775 repsite_compress(VlEntry, j);
2777 return VL_NOREPSERVER;
2779 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_ADD) {
2780 /* if (updateentry->RepsitesNewServer[i] < 0 || updateentry->RepsitesNewServer[i] > MAXSERVERID)
2781 return VL_BADSERVER; */
2782 if (updateentry->RepsitesNewPart[i] < 0
2783 || updateentry->RepsitesNewPart[i] > MAXPARTITIONID)
2784 return VL_BADPARTITION;
2787 IpAddrToRelAddr(updateentry->RepsitesNewServer[i],
2789 updateentry->RepsitesNewPart[i]) != -1)
2790 return VL_DUPREPSERVER;
2792 VlEntry->serverNumber[j] != BADSERVERID
2793 && j < OMAXNSERVERS; j++);
2794 if (j >= OMAXNSERVERS)
2797 IpAddrToRelAddr(updateentry->RepsitesNewServer[i],
2799 return VL_BADSERVER;
2800 VlEntry->serverNumber[j] = serverindex;
2801 VlEntry->serverPartition[j] = updateentry->RepsitesNewPart[i];
2802 if (updateentry->RepsitesNewFlags[i] < 0
2803 || updateentry->RepsitesNewFlags[i] > MAXSERVERFLAG)
2804 return VL_BADSERVERFLAG;
2805 VlEntry->serverFlags[j] = updateentry->RepsitesNewFlags[i];
2807 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODSERV) {
2808 /*n if (updateentry->RepsitesNewServer[i] < 0 || updateentry->RepsitesNewServer[i] > MAXSERVERID)
2809 return VL_BADSERVER; */
2811 repsite_exists(VlEntry,
2812 IpAddrToRelAddr(updateentry->
2813 RepsitesTargetServer[i],
2815 updateentry->RepsitesTargetPart[i])) !=
2817 VlEntry->serverNumber[j] =
2818 IpAddrToRelAddr(updateentry->RepsitesNewServer[i],
2821 return VL_NOREPSERVER;
2823 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODPART) {
2824 if (updateentry->RepsitesNewPart[i] < 0
2825 || updateentry->RepsitesNewPart[i] > MAXPARTITIONID)
2826 return VL_BADPARTITION;
2828 repsite_exists(VlEntry,
2829 IpAddrToRelAddr(updateentry->
2830 RepsitesTargetServer[i],
2832 updateentry->RepsitesTargetPart[i])) !=
2834 VlEntry->serverPartition[j] =
2835 updateentry->RepsitesNewPart[i];
2837 return VL_NOREPSERVER;
2839 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODFLAG) {
2841 repsite_exists(VlEntry,
2842 IpAddrToRelAddr(updateentry->
2843 RepsitesTargetServer[i],
2845 updateentry->RepsitesTargetPart[i])) !=
2847 if (updateentry->RepsitesNewFlags[i] < 0
2848 || updateentry->RepsitesNewFlags[i] > MAXSERVERFLAG)
2849 return VL_BADSERVERFLAG;
2850 VlEntry->serverFlags[j] =
2851 updateentry->RepsitesNewFlags[i];
2853 return VL_NOREPSERVER;
2861 /* 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. */
2863 repsite_exists(VlEntry, server, partition)
2864 struct nvlentry *VlEntry;
2865 int server, partition;
2869 for (i = 0; VlEntry->serverNumber[i] != BADSERVERID && i < OMAXNSERVERS;
2871 if ((VlEntry->serverNumber[i] == server)
2872 && (VlEntry->serverPartition[i] == partition))
2880 /* Repsite table compression: used when deleting a repsite entry so that all active repsite entries are on the top of the table. */
2882 repsite_compress(VlEntry, offset)
2883 struct nvlentry *VlEntry;
2886 int repsite_offset = offset;
2888 VlEntry->serverNumber[repsite_offset] != BADSERVERID
2889 && repsite_offset < OMAXNSERVERS - 1; repsite_offset++) {
2890 VlEntry->serverNumber[repsite_offset] =
2891 VlEntry->serverNumber[repsite_offset + 1];
2892 VlEntry->serverPartition[repsite_offset] =
2893 VlEntry->serverPartition[repsite_offset + 1];
2894 VlEntry->serverFlags[repsite_offset] =
2895 VlEntry->serverFlags[repsite_offset + 1];
2897 VlEntry->serverNumber[repsite_offset] = BADSERVERID;
2901 /* Convert from the internal (compacted) vldb entry to the external representation used by the interface. */
2903 vlentry_to_vldbentry(VlEntry, VldbEntry)
2904 struct nvlentry *VlEntry;
2905 struct vldbentry *VldbEntry;
2909 memset(VldbEntry, 0, sizeof(struct vldbentry));
2910 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
2911 for (i = 0; i < OMAXNSERVERS; i++) {
2912 if (VlEntry->serverNumber[i] == BADSERVERID)
2914 if ((HostAddress[j = VlEntry->serverNumber[i]] & 0xff000000) ==
2916 struct extentaddr *exp;
2919 base = (HostAddress[j] >> 16) & 0xff;
2920 index = HostAddress[j] & 0x0000ffff;
2921 exp = &ex_addr[base][index];
2922 /* For now return the first ip address back */
2923 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2924 if (exp->ex_addrs[j]) {
2925 VldbEntry->serverNumber[i] = ntohl(exp->ex_addrs[j]);
2930 VldbEntry->serverNumber[i] =
2931 HostAddress[VlEntry->serverNumber[i]];
2932 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
2933 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
2935 VldbEntry->nServers = i;
2936 for (i = 0; i < MAXTYPES; i++)
2937 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
2938 VldbEntry->cloneId = VlEntry->cloneId;
2939 VldbEntry->flags = VlEntry->flags;
2943 /* Convert from the internal (compacted) vldb entry to the external representation used by the interface. */
2945 vlentry_to_nvldbentry(VlEntry, VldbEntry)
2946 struct nvlentry *VlEntry;
2947 struct nvldbentry *VldbEntry;
2951 memset(VldbEntry, 0, sizeof(struct vldbentry));
2952 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
2953 for (i = 0; i < NMAXNSERVERS; i++) {
2954 if (VlEntry->serverNumber[i] == BADSERVERID)
2956 if ((HostAddress[j = VlEntry->serverNumber[i]] & 0xff000000) ==
2958 struct extentaddr *exp;
2961 base = (HostAddress[j] >> 16) & 0xff;
2962 index = HostAddress[j] & 0x0000ffff;
2963 exp = &ex_addr[base][index];
2964 /* For now return the first ip address back */
2965 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2966 if (exp->ex_addrs[j]) {
2967 VldbEntry->serverNumber[i] = ntohl(exp->ex_addrs[j]);
2972 VldbEntry->serverNumber[i] =
2973 HostAddress[VlEntry->serverNumber[i]];
2974 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
2975 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
2977 VldbEntry->nServers = i;
2978 for (i = 0; i < MAXTYPES; i++)
2979 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
2980 VldbEntry->cloneId = VlEntry->cloneId;
2981 VldbEntry->flags = VlEntry->flags;
2985 vlentry_to_uvldbentry(VlEntry, VldbEntry)
2986 struct nvlentry *VlEntry;
2987 struct uvldbentry *VldbEntry;
2991 memset(VldbEntry, 0, sizeof(struct vldbentry));
2992 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
2993 for (i = 0; i < NMAXNSERVERS; i++) {
2994 if (VlEntry->serverNumber[i] == BADSERVERID)
2996 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
2997 VldbEntry->serverUnique[i] = 0;
2998 if ((HostAddress[j = VlEntry->serverNumber[i]] & 0xff000000) ==
3000 struct extentaddr *exp;
3004 base = (HostAddress[j] >> 16) & 0xff;
3005 index = HostAddress[j] & 0x0000ffff;
3006 exp = &ex_addr[base][index];
3007 tuuid = exp->ex_hostuuid;
3008 afs_ntohuuid(&tuuid);
3009 VldbEntry->serverFlags[i] |= VLSERVER_FLAG_UUID;
3010 VldbEntry->serverNumber[i] = tuuid;
3011 VldbEntry->serverUnique[i] = ntohl(exp->ex_uniquifier);
3013 VldbEntry->serverNumber[i].time_low =
3014 HostAddress[VlEntry->serverNumber[i]];
3016 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
3019 VldbEntry->nServers = i;
3020 for (i = 0; i < MAXTYPES; i++)
3021 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
3022 VldbEntry->cloneId = VlEntry->cloneId;
3023 VldbEntry->flags = VlEntry->flags;
3026 #define LEGALCHARS ".ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
3029 /* Verify that the volname is a valid volume name. */
3031 InvalidVolname(volname)
3038 slen = strlen(volname);
3039 if (slen >= VL_MAXNAMELEN)
3041 return (slen != strspn(volname, map));
3045 /* Verify that the given volume type is valid. */
3047 InvalidVoltype(voltype)
3050 if (voltype != RWVOL && voltype != ROVOL && voltype != BACKVOL)
3057 InvalidOperation(voloper)
3060 if (voloper != VLOP_MOVE && voloper != VLOP_RELEASE
3061 && voloper != VLOP_BACKUP && voloper != VLOP_DELETE
3062 && voloper != VLOP_DUMP)
3068 InvalidReleasetype(releasetype)
3069 afs_int32 releasetype;
3071 if ((releasetype & LOCKREL_TIMESTAMP) || (releasetype & LOCKREL_OPCODE)
3072 || (releasetype & LOCKREL_AFSID))
3078 IpAddrToRelAddr(ipaddr, atrans)
3079 struct ubik_trans *atrans;
3080 register afs_uint32 ipaddr;
3083 register afs_int32 code, base, index;
3084 struct extentaddr *exp;
3086 for (i = 0; i <= MAXSERVERID; i++) {
3087 if (HostAddress[i] == ipaddr)
3089 if ((HostAddress[i] & 0xff000000) == 0xff000000) {
3090 base = (HostAddress[i] >> 16) & 0xff;
3091 index = HostAddress[i] & 0x0000ffff;
3092 if (base >= VL_MAX_ADDREXTBLKS) {
3094 ("Internal error: Multihome extent base is too large. Base %d index %d\n",
3096 return -1; /* EINVAL */
3098 if (index >= VL_MHSRV_PERBLK) {
3100 ("Internal error: Multihome extent index is too large. Base %d index %d\n",
3102 return -1; /* EINVAL */
3104 if (!ex_addr[base]) {
3106 ("Internal error: Multihome extent does not exist. Base %d\n",
3108 return -1; /* EINVAL */
3110 exp = &ex_addr[base][index];
3111 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
3112 if (exp->ex_addrs[j] && (ntohl(exp->ex_addrs[j]) == ipaddr)) {
3119 /* allocate the new server a server id pronto */
3121 for (i = 0; i <= MAXSERVERID; i++) {
3122 if (cheader.IpMappedAddr[i] == 0) {
3123 cheader.IpMappedAddr[i] = htonl(ipaddr);
3126 DOFFSET(0, &cheader, &cheader.IpMappedAddr[i]),
3127 (char *)&cheader.IpMappedAddr[i],
3129 HostAddress[i] = ipaddr;
3140 ChangeIPAddr(ipaddr1, ipaddr2, atrans)
3141 struct ubik_trans *atrans;
3142 register afs_uint32 ipaddr1, ipaddr2;
3146 struct extentaddr *exp = NULL;
3150 afs_int32 blockindex, count;
3152 struct nvlentry tentry;
3155 return VL_CREATEFAIL;
3157 /* Don't let addr change to 256.*.*.* : Causes internal error below */
3158 if ((ipaddr2 & 0xff000000) == 0xff000000)
3159 return (VL_BADSERVER);
3161 /* If we are removing an address, ip1 will be -1 and ip2 will be
3162 * the original address. This prevents an older revision vlserver
3163 * from removing the IP address (won't find server 0xfffffff in
3164 * the VLDB). An older revision vlserver does not have the check
3165 * to see if any volumes exist on the server being removed.
3167 if (ipaddr1 == 0xffffffff) {
3172 for (i = 0; i <= MAXSERVERID; i++) {
3173 if ((HostAddress[i] & 0xff000000) == 0xff000000) {
3174 base = (HostAddress[i] >> 16) & 0xff;
3175 index = HostAddress[i] & 0x0000ffff;
3176 if ((base >= VL_MAX_ADDREXTBLKS) || (index >= VL_MHSRV_PERBLK)) {
3178 ("Internal error: Multihome extent addr is too large. Base %d index %d\n",
3180 return -1; /* EINVAL */
3183 exp = &ex_addr[base][index];
3184 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
3185 if (!exp->ex_addrs[mhidx])
3187 if (ntohl(exp->ex_addrs[mhidx]) == ipaddr1)
3190 if (mhidx < VL_MAXIPADDRS_PERMH) {
3193 } else if (HostAddress[i] == ipaddr1) {
3199 if (i >= MAXSERVERID) {
3200 return VL_NOENT; /* not found */
3203 /* If we are removing a server entry, a volume cannot
3204 * exist on the server. If one does, don't remove the
3205 * server entry: return error "volume entry exists".
3208 for (blockindex = NextEntry(atrans, 0, &tentry, &count); blockindex;
3209 blockindex = NextEntry(atrans, blockindex, &tentry, &count)) {
3210 if (++pollcount > 50) {
3211 #ifndef AFS_PTHREAD_ENV
3216 for (j = 0; j < NMAXNSERVERS; j++) {
3217 if (tentry.serverNumber[j] == BADSERVERID)
3219 if (tentry.serverNumber[j] == i) {
3226 /* Log a message saying we are changing/removing an IP address */
3228 ("The following IP address is being %s:\n",
3229 (ipaddr2 ? "changed" : "removed")));
3230 VLog(0, (" entry %d: ", i));
3233 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
3234 if (!exp->ex_addrs[mhidx])
3238 PADDR(ntohl(exp->ex_addrs[mhidx]));
3250 /* Change the registered uuuid addresses */
3252 memset(&tuuid, 0, sizeof(afsUUID));
3253 afs_htonuuid(&tuuid);
3254 exp->ex_hostuuid = tuuid;
3257 DOFFSET(ntohl(ex_addr[0]->ex_contaddrs[base]),
3258 (char *)ex_addr[base], (char *)exp),
3259 (char *)&tuuid, sizeof(tuuid));
3264 /* Now change the host address entry */
3265 cheader.IpMappedAddr[i] = htonl(ipaddr2);
3267 vlwrite(atrans, DOFFSET(0, &cheader, &cheader.IpMappedAddr[i]),
3269 &cheader.IpMappedAddr[i], sizeof(afs_int32));
3270 HostAddress[i] = ipaddr2;
3277 /* see if the vlserver is back yet */
3279 SVL_ProbeServer(rxcall)
3280 struct rx_call *rxcall;