2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include <afs/param.h>
14 #include <sys/types.h>
18 #include <afs/afsutil.h>
26 #include <netinet/in.h>
29 #include <afs/cellconfig.h>
31 #include "vlserver_internal.h"
32 #include "afs/audit.h"
36 #ifdef HAVE_POSIX_REGEX /* use POSIX regexp library */
41 extern int extent_mod;
42 extern struct afsconf_dir *vldb_confdir;
43 extern struct ubik_dbase *VL_dbase;
44 struct vlheader cheader; /* kept in network byte order */
45 extern afs_uint32 HostAddress[]; /* host addresses kept in host byte order */
47 struct extentaddr *ex_addr[VL_MAX_ADDREXTBLKS] = { 0, 0, 0, 0 };
48 static char rxinfo_str[128]; /* Need rxinfo string to be non-local */
49 #define ABORT(c) { errorcode = (c); goto abort; }
51 #define END(c) { errorcode = (c); goto end; }
53 #define VLDBALLOCLIMIT 10000
54 #define VLDBALLOCINCR 2048
56 static int put_attributeentry(struct vldbentry **, struct vldbentry **,
57 struct vldbentry **, bulkentries *,
58 struct nvlentry *, afs_int32 *, afs_int32 *);
59 static int put_nattributeentry(struct nvldbentry **, struct nvldbentry **,
60 struct nvldbentry **, nbulkentries *,
61 struct nvlentry *, afs_int32, afs_int32,
62 afs_int32 *, afs_int32 *);
63 static int RemoveEntry(struct ubik_trans *trans, afs_int32 entryptr,
64 struct nvlentry *tentry);
65 static void ReleaseEntry(struct nvlentry *tentry, afs_int32 releasetype);
66 static int check_vldbentry(struct vldbentry *aentry);
67 static int check_nvldbentry(struct nvldbentry *aentry);
68 static int vldbentry_to_vlentry(struct ubik_trans *atrans,
69 struct vldbentry *VldbEntry,
70 struct nvlentry *VlEntry);
71 static int nvldbentry_to_vlentry(struct ubik_trans *atrans,
72 struct nvldbentry *VldbEntry,
73 struct nvlentry *VlEntry);
74 static int get_vldbupdateentry(struct ubik_trans *trans, afs_int32 blockindex,
75 struct VldbUpdateEntry *updateentry,
76 struct nvlentry *VlEntry);
77 static int repsite_exists(struct nvlentry *VlEntry, int server, int partition);
78 static void repsite_compress(struct nvlentry *VlEntry, int offset);
79 static void vlentry_to_vldbentry(struct nvlentry *VlEntry,
80 struct vldbentry *VldbEntry);
81 static void vlentry_to_nvldbentry(struct nvlentry *VlEntry,
82 struct nvldbentry *VldbEntry);
83 static void vlentry_to_uvldbentry(struct nvlentry *VlEntry,
84 struct uvldbentry *VldbEntry);
85 static int InvalidVolname(char *volname);
86 static int InvalidVoltype(afs_int32 voltype);
87 static int InvalidOperation(afs_int32 voloper);
88 static int InvalidReleasetype(afs_int32 releasetype);
89 static int IpAddrToRelAddr(afs_uint32 ipaddr, struct ubik_trans *atrans);
90 static int ChangeIPAddr(afs_uint32 ipaddr1, afs_uint32 ipaddr2,
91 struct ubik_trans *atrans);
94 rxinfo(struct rx_call *rxcall)
97 register struct rx_connection *tconn;
102 struct in_addr hostAddr;
104 tconn = rx_ConnectionOf(rxcall);
105 hostAddr.s_addr = rx_HostOf(rx_PeerOf(tconn));
107 rxkad_GetServerInfo(rxcall->conn, NULL, &exp, tname, tinst, tcell,
110 sprintf(rxinfo_str, "%s %s%s%s%s%s", inet_ntoa(hostAddr), tname,
111 (tinst[0] == '\0') ? "" : ".",
112 (tinst[0] == '\0') ? "" : tinst,
113 (tcell[0] == '\0') ? "" : "@",
114 (tcell[0] == '\0') ? "" : tcell);
116 sprintf(rxinfo_str, "%s noauth", inet_ntoa(hostAddr));
120 /* This is called to initialize the database, set the appropriate locks and make sure that the vldb header is valid */
122 Init_VLdbase(struct ubik_trans **trans,
123 int locktype, /* indicate read or write transaction */
126 int errorcode = 0, pass, wl;
128 for (pass = 1; pass <= 3; pass++) {
129 if (pass == 2) { /* take write lock to rebuild the db */
130 errorcode = ubik_BeginTrans(VL_dbase, UBIK_WRITETRANS, trans);
132 } else if (locktype == LOCKREAD) {
134 ubik_BeginTransReadAny(VL_dbase, UBIK_READTRANS, trans);
137 errorcode = ubik_BeginTrans(VL_dbase, UBIK_WRITETRANS, trans);
143 errorcode = ubik_SetLock(*trans, 1, 1, locktype);
146 ubik_AbortTrans(*trans);
150 /* check that dbase is initialized and setup cheader */
151 /* 2nd pass we try to rebuild the header */
152 errorcode = CheckInit(*trans, ((pass == 2) ? 1 : 0));
153 if (!errorcode && wl && extent_mod)
154 errorcode = readExtents(*trans); /* Fix the mh extent blocks */
157 ubik_AbortTrans(*trans);
158 /* Only rebuld if the database is empty */
159 /* Exit if can't rebuild */
160 if ((pass == 1) && (errorcode != VL_EMPTY))
164 } else { /* No errorcode */
166 ubik_EndTrans(*trans); /* Rebuilt db. End trans, then retake original lock */
168 break; /* didn't rebuild and successful - exit */
176 /* Create a new vldb entry; both new volume id and name must be unique
177 * (non-existant in vldb).
181 SVL_CreateEntry(struct rx_call *rxcall, struct vldbentry *newentry)
183 struct ubik_trans *trans;
184 afs_int32 errorcode, blockindex;
185 struct nvlentry tentry;
187 COUNT_REQ(VLCREATEENTRY);
188 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) {
193 /* Do some validity tests on new entry */
194 if ((errorcode = check_vldbentry(newentry))
195 || (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
199 ("OCreate Volume %d %s\n", newentry->volumeId[RWVOL],
201 if (EntryIDExists(trans, newentry->volumeId, MAXTYPES, &errorcode)) {
202 /* at least one of the specified IDs already exists; we fail */
203 errorcode = VL_IDEXIST;
205 } else if (errorcode) {
209 /* Is this following check (by volume name) necessary?? */
210 /* If entry already exists, we fail */
211 if (FindByName(trans, newentry->name, &tentry, &errorcode)) {
212 errorcode = VL_NAMEEXIST;
214 } else if (errorcode) {
218 blockindex = AllocBlock(trans, &tentry);
219 if (blockindex == 0) {
220 errorcode = VL_CREATEFAIL;
224 memset(&tentry, 0, sizeof(struct nvlentry));
225 /* Convert to its internal representation; both in host byte order */
226 if ((errorcode = vldbentry_to_vlentry(trans, newentry, &tentry))) {
227 FreeBlock(trans, blockindex);
231 /* Actually insert the entry in vldb */
232 errorcode = ThreadVLentry(trans, blockindex, &tentry);
234 FreeBlock(trans, blockindex);
237 errorcode = ubik_EndTrans(trans);
243 ubik_AbortTrans(trans);
246 osi_auditU(rxcall, VLCreateEntryEvent, errorcode, AUD_STR,
247 (newentry ? newentry->name : NULL), AUD_END);
253 SVL_CreateEntryN(struct rx_call *rxcall, struct nvldbentry *newentry)
255 struct ubik_trans *trans;
256 afs_int32 errorcode, blockindex;
257 struct nvlentry tentry;
259 COUNT_REQ(VLCREATEENTRYN);
260 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) {
265 /* Do some validity tests on new entry */
266 if ((errorcode = check_nvldbentry(newentry))
267 || (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
271 ("Create Volume %d %s\n", newentry->volumeId[RWVOL],
273 if (EntryIDExists(trans, newentry->volumeId, MAXTYPES, &errorcode)) {
274 /* at least one of the specified IDs already exists; we fail */
275 errorcode = VL_IDEXIST;
277 } else if (errorcode) {
281 /* Is this following check (by volume name) necessary?? */
282 /* If entry already exists, we fail */
283 if (FindByName(trans, newentry->name, &tentry, &errorcode)) {
284 errorcode = VL_NAMEEXIST;
286 } else if (errorcode) {
290 blockindex = AllocBlock(trans, &tentry);
291 if (blockindex == 0) {
292 errorcode = VL_CREATEFAIL;
296 memset(&tentry, 0, sizeof(struct nvlentry));
297 /* Convert to its internal representation; both in host byte order */
298 if ((errorcode = nvldbentry_to_vlentry(trans, newentry, &tentry))) {
299 FreeBlock(trans, blockindex);
303 /* Actually insert the entry in vldb */
304 errorcode = ThreadVLentry(trans, blockindex, &tentry);
306 FreeBlock(trans, blockindex);
309 errorcode = ubik_EndTrans(trans);
315 ubik_AbortTrans(trans);
318 osi_auditU(rxcall, VLCreateEntryEvent, errorcode, AUD_STR,
319 (newentry ? newentry->name : NULL), AUD_END);
325 SVL_ChangeAddr(struct rx_call *rxcall, afs_uint32 ip1, afs_uint32 ip2)
327 struct ubik_trans *trans;
330 COUNT_REQ(VLCHANGEADDR);
331 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) {
336 if ((errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
339 VLog(1, ("Change Addr %u -> %u %s\n", ip1, ip2, rxinfo(rxcall)));
340 if ((errorcode = ChangeIPAddr(ip1, ip2, trans)))
343 errorcode = ubik_EndTrans(trans);
349 ubik_AbortTrans(trans);
352 osi_auditU(rxcall, VLChangeAddrEvent, errorcode, AUD_LONG, ip1, AUD_LONG,
357 /* Delete a vldb entry given the volume id. */
359 SVL_DeleteEntry(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype)
361 struct ubik_trans *trans;
362 afs_int32 blockindex, errorcode;
363 struct nvlentry tentry;
365 COUNT_REQ(VLDELETEENTRY);
366 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
369 if ((voltype != -1) && (InvalidVoltype(voltype)))
372 if ((errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
375 VLog(1, ("Delete Volume %u %s\n", volid, rxinfo(rxcall)));
376 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
377 if (blockindex == 0) { /* volid not found */
379 errorcode = VL_NOENT;
383 if (tentry.flags & VLDELETED) { /* Already deleted; return */
384 ABORT(VL_ENTDELETED);
386 if ((errorcode = RemoveEntry(trans, blockindex, &tentry))) {
389 errorcode = (ubik_EndTrans(trans));
394 ubik_AbortTrans(trans);
397 osi_auditU(rxcall, VLDeleteEntryEvent, errorcode, AUD_LONG, volid,
403 /* Get a vldb entry given its volume id; make sure it's not a deleted entry. */
405 GetEntryByID(struct rx_call *rxcall,
408 char *aentry, /* entry data copied here */
412 struct ubik_trans *trans;
413 afs_int32 blockindex, errorcode;
414 struct nvlentry tentry;
416 if ((voltype != -1) && (InvalidVoltype(voltype)))
417 return VL_BADVOLTYPE;
418 if ((errorcode = Init_VLdbase(&trans, LOCKREAD, this_op)))
421 VLog(5, ("GetVolumeByID %u (%d) %s\n", volid, new, rxinfo(rxcall)));
422 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
423 if (blockindex == 0) { /* entry not found */
425 errorcode = VL_NOENT;
427 ubik_AbortTrans(trans);
430 if (tentry.flags & VLDELETED) { /* Entry is deleted! */
432 ubik_AbortTrans(trans);
433 return VL_ENTDELETED;
435 /* Convert from the internal to external form */
437 vlentry_to_nvldbentry(&tentry, (struct nvldbentry *)aentry);
439 vlentry_to_uvldbentry(&tentry, (struct uvldbentry *)aentry);
441 vlentry_to_vldbentry(&tentry, (struct vldbentry *)aentry);
442 return (ubik_EndTrans(trans));
446 SVL_GetEntryByID(struct rx_call *rxcall,
449 vldbentry *aentry) /* entry data copied here */
451 COUNT_REQ(VLGETENTRYBYID);
452 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 0, this_op));
456 SVL_GetEntryByIDN(struct rx_call *rxcall,
459 nvldbentry *aentry) /* entry data copied here */
461 COUNT_REQ(VLGETENTRYBYIDN);
462 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 1, this_op));
466 SVL_GetEntryByIDU(struct rx_call *rxcall,
469 uvldbentry *aentry) /* entry data copied here */
471 COUNT_REQ(VLGETENTRYBYIDU);
472 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 2, this_op));
477 /* returns true if the id is a decimal integer, in which case we interpret
478 * it as an id. make the cache manager much simpler */
480 NameIsId(char *aname)
483 while ((tc = *aname++)) {
484 if (tc > '9' || tc < '0')
490 /* Get a vldb entry given the volume's name; of course, very similar to
491 * VLGetEntryByID() above. */
493 GetEntryByName(struct rx_call *rxcall,
495 char *aentry, /* entry data copied here */
499 struct ubik_trans *trans;
500 afs_int32 blockindex, errorcode;
501 struct nvlentry tentry;
503 if (NameIsId(volname)) {
504 return GetEntryByID(rxcall, atoi(volname), -1, aentry, new, this_op);
506 if (InvalidVolname(volname))
508 if ((errorcode = Init_VLdbase(&trans, LOCKREAD, this_op)))
510 VLog(5, ("GetVolumeByName %s (%d) %s\n", volname, new, rxinfo(rxcall)));
511 blockindex = FindByName(trans, volname, &tentry, &errorcode);
512 if (blockindex == 0) { /* entry not found */
514 errorcode = VL_NOENT;
516 ubik_AbortTrans(trans);
519 if (tentry.flags & VLDELETED) { /* Entry is deleted */
521 ubik_AbortTrans(trans);
522 return VL_ENTDELETED;
524 /* Convert to external entry representation */
526 vlentry_to_nvldbentry(&tentry, (struct nvldbentry *)aentry);
528 vlentry_to_uvldbentry(&tentry, (struct uvldbentry *)aentry);
530 vlentry_to_vldbentry(&tentry, (struct vldbentry *)aentry);
531 return (ubik_EndTrans(trans));
535 SVL_GetEntryByNameO(struct rx_call *rxcall,
537 struct vldbentry *aentry) /* entry data copied here */
539 COUNT_REQ(VLGETENTRYBYNAME);
540 return (GetEntryByName(rxcall, volname, (char *)aentry, 0, this_op));
545 SVL_GetEntryByNameN(struct rx_call *rxcall,
547 struct nvldbentry *aentry) /* entry data copied here */
549 COUNT_REQ(VLGETENTRYBYNAMEN);
550 return (GetEntryByName(rxcall, volname, (char *)aentry, 1, this_op));
554 SVL_GetEntryByNameU(struct rx_call *rxcall,
556 struct uvldbentry *aentry) /* entry data copied here */
558 COUNT_REQ(VLGETENTRYBYNAMEU);
559 return (GetEntryByName(rxcall, volname, (char *)aentry, 2, this_op));
564 /* Get the current value of the maximum volume id and bump the volume id counter by Maxvolidbump. */
566 SVL_GetNewVolumeId(struct rx_call *rxcall, afs_uint32 Maxvolidbump,
567 afs_uint32 *newvolumeid)
570 afs_uint32 maxvolumeid;
571 struct ubik_trans *trans;
573 COUNT_REQ(VLGETNEWVOLUMEID);
574 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
577 if (Maxvolidbump < 0 || Maxvolidbump > MAXBUMPCOUNT)
578 END(VL_BADVOLIDBUMP);
580 if ((errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
583 *newvolumeid = maxvolumeid = NextUnusedID(trans,
584 ntohl(cheader.vital_header.MaxVolumeId), Maxvolidbump, &errorcode);
589 maxvolumeid += Maxvolidbump;
590 VLog(1, ("GetNewVolid newmax=%u %s\n", maxvolumeid, rxinfo(rxcall)));
591 cheader.vital_header.MaxVolumeId = htonl(maxvolumeid);
592 if (write_vital_vlheader(trans)) {
595 errorcode = (ubik_EndTrans(trans));
600 ubik_AbortTrans(trans);
603 osi_auditU(rxcall, VLGetNewVolumeIdEvent, errorcode, AUD_END);
608 /* Simple replace the contents of the vldb entry, volid, with
609 * newentry. No individual checking/updating per field (alike
610 * VLUpdateEntry) is done. */
613 SVL_ReplaceEntry(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype,
614 struct vldbentry *newentry, afs_int32 releasetype)
616 struct ubik_trans *trans;
617 afs_int32 blockindex, errorcode, typeindex;
619 int hashVol[MAXTYPES];
620 struct nvlentry tentry;
621 afs_uint32 checkids[MAXTYPES];
623 COUNT_REQ(VLREPLACEENTRY);
624 for (typeindex = 0; typeindex < MAXTYPES; typeindex++)
625 hashVol[typeindex] = 0;
627 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
630 if ((errorcode = check_vldbentry(newentry)))
633 if (voltype != -1 && InvalidVoltype(voltype))
636 if (releasetype && InvalidReleasetype(releasetype))
637 END(VL_BADRELLOCKTYPE);
638 if ((errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
641 VLog(1, ("OReplace Volume %u %s\n", volid, rxinfo(rxcall)));
642 /* find vlentry we're changing */
643 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
644 if (blockindex == 0) { /* entry not found */
646 errorcode = VL_NOENT;
650 /* check that we're not trying to change the RW vol ID */
651 if (newentry->volumeId[RWVOL] != tentry.volumeId[RWVOL]) {
655 /* make sure none of the IDs we are changing to are already in use */
656 memset(&checkids, 0, sizeof(checkids));
657 for (typeindex = ROVOL; typeindex < MAXTYPES; typeindex++) {
658 if (tentry.volumeId[typeindex] != newentry->volumeId[typeindex]) {
659 checkids[typeindex] = newentry->volumeId[typeindex];
662 if (EntryIDExists(trans, checkids, MAXTYPES, &errorcode)) {
664 } else if (errorcode) {
668 /* make sure the name we're changing to doesn't already exist */
669 if (strcmp(newentry->name, tentry.name)) {
670 struct nvlentry tmp_entry;
671 if (FindByName(trans, newentry->name, &tmp_entry, &errorcode)) {
673 } else if (errorcode) {
678 /* unhash volid entries if they're disappearing or changing.
679 * Remember if we need to hash in the new value (we don't have to
680 * rehash if volid stays same */
681 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
682 if (tentry.volumeId[typeindex] != newentry->volumeId[typeindex]) {
683 if (tentry.volumeId[typeindex])
685 UnhashVolid(trans, typeindex, blockindex, &tentry))) {
688 /* we must rehash new id if the id is different and the ID is nonzero */
689 hashVol[typeindex] = 1; /* must rehash this guy if he exists */
693 /* Rehash volname if it changes */
694 if (strcmp(newentry->name, tentry.name)) { /* Name changes; redo hashing */
695 if ((errorcode = UnhashVolname(trans, blockindex, &tentry))) {
701 /* after this, tentry is new entry, not old one. vldbentry_to_vlentry
702 * doesn't touch hash chains */
703 if ((errorcode = vldbentry_to_vlentry(trans, newentry, &tentry))) {
707 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
708 if (hashVol[typeindex] && tentry.volumeId[typeindex]) {
709 if ((errorcode = HashVolid(trans, typeindex, blockindex, &tentry))) {
716 HashVolname(trans, blockindex, &tentry);
719 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
720 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
724 END(ubik_EndTrans(trans));
728 ubik_AbortTrans(trans);
731 osi_auditU(rxcall, VLReplaceVLEntryEvent, errorcode, AUD_LONG, volid,
737 SVL_ReplaceEntryN(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype,
738 struct nvldbentry *newentry, afs_int32 releasetype)
740 struct ubik_trans *trans;
741 afs_int32 blockindex, errorcode, typeindex;
743 int hashVol[MAXTYPES];
744 struct nvlentry tentry;
746 COUNT_REQ(VLREPLACEENTRYN);
747 for (typeindex = 0; typeindex < MAXTYPES; typeindex++)
748 hashVol[typeindex] = 0;
750 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
753 if ((errorcode = check_nvldbentry(newentry)))
756 if (voltype != -1 && InvalidVoltype(voltype))
759 if (releasetype && InvalidReleasetype(releasetype))
760 END(VL_BADRELLOCKTYPE);
761 if ((errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
764 VLog(1, ("Replace Volume %u %s\n", volid, rxinfo(rxcall)));
765 /* find vlentry we're changing */
766 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
767 if (blockindex == 0) { /* entry not found */
769 errorcode = VL_NOENT;
773 /* check that we're not trying to change the RW vol ID */
774 if (newentry->volumeId[RWVOL] != tentry.volumeId[RWVOL]) {
778 /* unhash volid entries if they're disappearing or changing.
779 * Remember if we need to hash in the new value (we don't have to
780 * rehash if volid stays same */
781 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
782 if (tentry.volumeId[typeindex] != newentry->volumeId[typeindex]) {
783 if (tentry.volumeId[typeindex])
785 UnhashVolid(trans, typeindex, blockindex, &tentry))) {
788 /* we must rehash new id if the id is different and the ID is nonzero */
789 hashVol[typeindex] = 1; /* must rehash this guy if he exists */
793 /* Rehash volname if it changes */
794 if (strcmp(newentry->name, tentry.name)) { /* Name changes; redo hashing */
795 if ((errorcode = UnhashVolname(trans, blockindex, &tentry))) {
801 /* after this, tentry is new entry, not old one. vldbentry_to_vlentry
802 * doesn't touch hash chains */
803 if ((errorcode = nvldbentry_to_vlentry(trans, newentry, &tentry))) {
807 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
808 if (hashVol[typeindex] && tentry.volumeId[typeindex]) {
809 if ((errorcode = HashVolid(trans, typeindex, blockindex, &tentry))) {
816 HashVolname(trans, blockindex, &tentry);
819 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
820 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
824 END(ubik_EndTrans(trans));
828 ubik_AbortTrans(trans);
831 osi_auditU(rxcall, VLReplaceVLEntryEvent, errorcode, AUD_LONG, volid,
837 /* Update a vldb entry (accessed thru its volume id). Almost all of the
838 * entry's fields can be modified in a single call by setting the
839 * appropriate bits in the Mask field in VldbUpdateentry. */
840 /* this routine may never have been tested; use replace entry instead
841 * unless you're brave */
843 SVL_UpdateEntry(struct rx_call *rxcall,
846 struct VldbUpdateEntry *updateentry, /* Update entry copied here */
847 afs_int32 releasetype)
849 struct ubik_trans *trans;
850 afs_int32 blockindex, errorcode;
851 struct nvlentry tentry;
853 COUNT_REQ(VLUPDATEENTRY);
854 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
856 if ((voltype != -1) && (InvalidVoltype(voltype)))
858 if (releasetype && InvalidReleasetype(releasetype))
859 END(VL_BADRELLOCKTYPE);
860 if ((errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
863 VLog(1, ("Update Volume %u %s\n", volid, rxinfo(rxcall)));
864 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
865 if (blockindex == 0) { /* entry not found */
867 errorcode = VL_NOENT;
871 /* Do the actual updating of the entry, tentry. */
873 get_vldbupdateentry(trans, blockindex, updateentry, &tentry))) {
877 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
878 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
881 END(ubik_EndTrans(trans));
885 ubik_AbortTrans(trans);
888 osi_auditU(rxcall, VLUpdateEntryEvent, errorcode, AUD_LONG, volid,
895 SVL_UpdateEntryByName(struct rx_call *rxcall,
897 struct VldbUpdateEntry *updateentry, /* Update entry copied here */
898 afs_int32 releasetype)
900 struct ubik_trans *trans;
901 afs_int32 blockindex, errorcode;
902 struct nvlentry tentry;
904 COUNT_REQ(VLUPDATEENTRYBYNAME);
905 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
907 if (releasetype && InvalidReleasetype(releasetype))
908 END(VL_BADRELLOCKTYPE);
909 if ((errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
912 blockindex = FindByName(trans, volname, &tentry, &errorcode);
913 if (blockindex == 0) { /* entry not found */
915 errorcode = VL_NOENT;
919 /* Do the actual updating of the entry, tentry. */
921 get_vldbupdateentry(trans, blockindex, updateentry, &tentry))) {
925 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
926 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
929 END(ubik_EndTrans(trans));
933 ubik_AbortTrans(trans);
936 osi_auditU(rxcall, VLUpdateEntryEvent, errorcode, AUD_LONG, -1, AUD_END);
941 /* Set a lock to the vldb entry for volid (of type voltype if not -1). */
943 SVL_SetLock(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype,
946 afs_int32 timestamp, blockindex, errorcode;
947 struct ubik_trans *trans;
948 struct nvlentry tentry;
950 COUNT_REQ(VLSETLOCK);
951 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
953 if ((voltype != -1) && (InvalidVoltype(voltype)))
955 if (InvalidOperation(voloper))
957 if ((errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
960 VLog(1, ("SetLock Volume %u %s\n", volid, rxinfo(rxcall)));
961 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
962 if (blockindex == NULLO) {
964 errorcode = VL_NOENT;
967 if (tentry.flags & VLDELETED) {
968 ABORT(VL_ENTDELETED);
970 timestamp = FT_ApproxTime();
972 /* Check if entry is already locked; note that we unlock any entry
973 * locked more than MAXLOCKTIME seconds */
974 if ((tentry.LockTimestamp)
975 && ((timestamp - tentry.LockTimestamp) < MAXLOCKTIME)) {
976 ABORT(VL_ENTRYLOCKED);
979 /* Consider it an unlocked entry: set current timestamp, caller
980 * and active vol operation */
981 tentry.LockTimestamp = timestamp;
982 tentry.LockAfsId = 0; /* Not implemented yet */
983 if (tentry.flags & VLOP_RELEASE) {
986 tentry.flags &= ~VLOP_ALLOPERS; /* Clear any possible older operation bit */
987 tentry.flags |= voloper;
989 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
992 END(ubik_EndTrans(trans));
996 ubik_AbortTrans(trans);
999 osi_auditU(rxcall, VLSetLockEvent, errorcode, AUD_LONG, volid, AUD_END);
1004 /* Release an already locked vldb entry. Releasetype determines what
1005 * fields (afsid and/or volume operation) will be cleared along with
1006 * the lock time stamp. */
1009 SVL_ReleaseLock(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype,
1010 afs_int32 releasetype)
1012 afs_int32 blockindex, errorcode;
1013 struct ubik_trans *trans;
1014 struct nvlentry tentry;
1016 COUNT_REQ(VLRELEASELOCK);
1017 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
1019 if ((voltype != -1) && (InvalidVoltype(voltype)))
1021 if (releasetype && InvalidReleasetype(releasetype))
1022 END(VL_BADRELLOCKTYPE);
1023 if ((errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
1026 VLog(1, ("ReleaseLock Volume %u %s\n", volid, rxinfo(rxcall)));
1027 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
1028 if (blockindex == NULLO) {
1030 errorcode = VL_NOENT;
1033 if (tentry.flags & VLDELETED) {
1034 ABORT(VL_ENTDELETED);
1037 ReleaseEntry(&tentry, releasetype); /* Unlock the appropriate fields */
1038 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
1041 END(ubik_EndTrans(trans));
1045 ubik_AbortTrans(trans);
1048 osi_auditU(rxcall, VLReleaseLockEvent, errorcode, AUD_LONG, volid,
1054 /* ListEntry returns a single vldb entry, aentry, with offset previous_index;
1055 * the remaining parameters (i.e. next_index) are used so that sequential
1056 * calls to this routine will get the next (all) vldb entries.
1059 SVL_ListEntry(struct rx_call *rxcall, afs_int32 previous_index,
1060 afs_int32 *count, afs_int32 *next_index,
1061 struct vldbentry *aentry)
1064 struct ubik_trans *trans;
1065 struct nvlentry tentry;
1067 COUNT_REQ(VLLISTENTRY);
1068 if ((errorcode = Init_VLdbase(&trans, LOCKREAD, this_op)))
1070 VLog(25, ("OListEntry index=%d %s\n", previous_index, rxinfo(rxcall)));
1071 *next_index = NextEntry(trans, previous_index, &tentry, count);
1073 vlentry_to_vldbentry(&tentry, aentry);
1074 return (ubik_EndTrans(trans));
1077 /* ListEntry returns a single vldb entry, aentry, with offset previous_index;
1078 * the remaining parameters (i.e. next_index) are used so that sequential
1079 * calls to this routine will get the next (all) vldb entries.
1082 SVL_ListEntryN(struct rx_call *rxcall, afs_int32 previous_index,
1083 afs_int32 *count, afs_int32 *next_index,
1084 struct nvldbentry *aentry)
1087 struct ubik_trans *trans;
1088 struct nvlentry tentry;
1090 COUNT_REQ(VLLISTENTRYN);
1091 if ((errorcode = Init_VLdbase(&trans, LOCKREAD, this_op)))
1093 VLog(25, ("ListEntry index=%d %s\n", previous_index, rxinfo(rxcall)));
1094 *next_index = NextEntry(trans, previous_index, &tentry, count);
1096 vlentry_to_nvldbentry(&tentry, aentry);
1097 return (ubik_EndTrans(trans));
1101 /* Retrieves in vldbentries all vldb entries that match the specified
1102 * attributes (by server number, partition, volume type, and flag); if volume
1103 * id is specified then the associated list for that entry is returned.
1104 * CAUTION: This could be a very expensive call since in most cases
1105 * sequential search of all vldb entries is performed.
1108 SVL_ListAttributes(struct rx_call *rxcall,
1109 struct VldbListByAttributes *attributes,
1110 afs_int32 *nentries,
1111 bulkentries *vldbentries)
1113 int errorcode, allocCount = 0;
1114 struct ubik_trans *trans;
1115 struct nvlentry tentry;
1116 struct vldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1119 COUNT_REQ(VLLISTATTRIBUTES);
1120 vldbentries->bulkentries_val = 0;
1121 vldbentries->bulkentries_len = *nentries = 0;
1122 if ((errorcode = Init_VLdbase(&trans, LOCKREAD, this_op)))
1124 allocCount = VLDBALLOCCOUNT;
1125 Vldbentry = VldbentryFirst = vldbentries->bulkentries_val =
1126 (vldbentry *) malloc(allocCount * sizeof(vldbentry));
1127 if (Vldbentry == NULL) {
1129 ubik_AbortTrans(trans);
1132 VldbentryLast = VldbentryFirst + allocCount;
1133 /* Handle the attribute by volume id totally separate of the rest
1134 * (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!) */
1135 if (attributes->Mask & VLLIST_VOLUMEID) {
1136 afs_int32 blockindex;
1139 FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1140 if (blockindex == 0) {
1142 errorcode = VL_NOENT;
1144 ubik_AbortTrans(trans);
1145 if (vldbentries->bulkentries_val)
1146 free((char *)vldbentries->bulkentries_val);
1147 vldbentries->bulkentries_val = 0;
1148 vldbentries->bulkentries_len = 0;
1152 put_attributeentry(&Vldbentry, &VldbentryFirst, &VldbentryLast,
1153 vldbentries, &tentry, nentries, &allocCount))) {
1155 ubik_AbortTrans(trans);
1156 if (vldbentries->bulkentries_val)
1157 free((char *)vldbentries->bulkentries_val);
1158 vldbentries->bulkentries_val = 0;
1159 vldbentries->bulkentries_len = 0;
1160 return VL_SIZEEXCEEDED;
1163 afs_int32 nextblockindex = 0, count = 0, k = 0, match = 0;
1164 while ((nextblockindex =
1165 NextEntry(trans, nextblockindex, &tentry, &count))) {
1166 if (++pollcount > 50) {
1167 #ifndef AFS_PTHREAD_ENV
1173 if (attributes->Mask & VLLIST_SERVER) {
1176 IpAddrToRelAddr(attributes->server, NULL)) == -1)
1178 for (k = 0; k < OMAXNSERVERS; k++) {
1179 if (tentry.serverNumber[k] == BADSERVERID)
1181 if (tentry.serverNumber[k] == serverindex) {
1189 if (attributes->Mask & VLLIST_PARTITION) {
1191 if (tentry.serverPartition[k] != attributes->partition)
1194 for (k = 0; k < OMAXNSERVERS; k++) {
1195 if (tentry.serverNumber[k] == BADSERVERID)
1197 if (tentry.serverPartition[k] ==
1198 attributes->partition) {
1208 if (attributes->Mask & VLLIST_FLAG) {
1209 if (!(tentry.flags & attributes->flag))
1213 put_attributeentry(&Vldbentry, &VldbentryFirst,
1214 &VldbentryLast, vldbentries, &tentry,
1215 nentries, &allocCount))) {
1217 ubik_AbortTrans(trans);
1218 if (vldbentries->bulkentries_val)
1219 free((char *)vldbentries->bulkentries_val);
1220 vldbentries->bulkentries_val = 0;
1221 vldbentries->bulkentries_len = 0;
1226 if (vldbentries->bulkentries_len
1227 && (allocCount > vldbentries->bulkentries_len)) {
1229 vldbentries->bulkentries_val =
1230 (vldbentry *) realloc(vldbentries->bulkentries_val,
1231 vldbentries->bulkentries_len *
1233 if (vldbentries->bulkentries_val == NULL) {
1235 ubik_AbortTrans(trans);
1240 ("ListAttrs nentries=%d %s\n", vldbentries->bulkentries_len,
1242 return (ubik_EndTrans(trans));
1246 SVL_ListAttributesN(struct rx_call *rxcall,
1247 struct VldbListByAttributes *attributes,
1248 afs_int32 *nentries,
1249 nbulkentries *vldbentries)
1251 int errorcode, allocCount = 0;
1252 struct ubik_trans *trans;
1253 struct nvlentry tentry;
1254 struct nvldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1257 COUNT_REQ(VLLISTATTRIBUTESN);
1258 vldbentries->nbulkentries_val = 0;
1259 vldbentries->nbulkentries_len = *nentries = 0;
1260 if ((errorcode = Init_VLdbase(&trans, LOCKREAD, this_op)))
1262 allocCount = VLDBALLOCCOUNT;
1263 Vldbentry = VldbentryFirst = vldbentries->nbulkentries_val =
1264 (nvldbentry *) malloc(allocCount * sizeof(nvldbentry));
1265 if (Vldbentry == NULL) {
1267 ubik_AbortTrans(trans);
1270 VldbentryLast = VldbentryFirst + allocCount;
1271 /* Handle the attribute by volume id totally separate of the rest
1272 * (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!) */
1273 if (attributes->Mask & VLLIST_VOLUMEID) {
1274 afs_int32 blockindex;
1277 FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1278 if (blockindex == 0) {
1280 errorcode = VL_NOENT;
1282 ubik_AbortTrans(trans);
1283 if (vldbentries->nbulkentries_val)
1284 free((char *)vldbentries->nbulkentries_val);
1285 vldbentries->nbulkentries_val = 0;
1286 vldbentries->nbulkentries_len = 0;
1290 put_nattributeentry(&Vldbentry, &VldbentryFirst, &VldbentryLast,
1291 vldbentries, &tentry, 0, 0, nentries,
1294 ubik_AbortTrans(trans);
1295 if (vldbentries->nbulkentries_val)
1296 free((char *)vldbentries->nbulkentries_val);
1297 vldbentries->nbulkentries_val = 0;
1298 vldbentries->nbulkentries_len = 0;
1299 return VL_SIZEEXCEEDED;
1302 afs_int32 nextblockindex = 0, count = 0, k = 0, match = 0;
1303 while ((nextblockindex =
1304 NextEntry(trans, nextblockindex, &tentry, &count))) {
1305 if (++pollcount > 50) {
1306 #ifndef AFS_PTHREAD_ENV
1313 if (attributes->Mask & VLLIST_SERVER) {
1316 IpAddrToRelAddr(attributes->server, NULL)) == -1)
1318 for (k = 0; k < NMAXNSERVERS; k++) {
1319 if (tentry.serverNumber[k] == BADSERVERID)
1321 if (tentry.serverNumber[k] == serverindex) {
1329 if (attributes->Mask & VLLIST_PARTITION) {
1331 if (tentry.serverPartition[k] != attributes->partition)
1334 for (k = 0; k < NMAXNSERVERS; k++) {
1335 if (tentry.serverNumber[k] == BADSERVERID)
1337 if (tentry.serverPartition[k] ==
1338 attributes->partition) {
1348 if (attributes->Mask & VLLIST_FLAG) {
1349 if (!(tentry.flags & attributes->flag))
1353 put_nattributeentry(&Vldbentry, &VldbentryFirst,
1354 &VldbentryLast, vldbentries, &tentry, 0,
1355 0, nentries, &allocCount))) {
1357 ubik_AbortTrans(trans);
1358 if (vldbentries->nbulkentries_val)
1359 free((char *)vldbentries->nbulkentries_val);
1360 vldbentries->nbulkentries_val = 0;
1361 vldbentries->nbulkentries_len = 0;
1366 if (vldbentries->nbulkentries_len
1367 && (allocCount > vldbentries->nbulkentries_len)) {
1369 vldbentries->nbulkentries_val =
1370 (nvldbentry *) realloc(vldbentries->nbulkentries_val,
1371 vldbentries->nbulkentries_len *
1372 sizeof(nvldbentry));
1373 if (vldbentries->nbulkentries_val == NULL) {
1375 ubik_AbortTrans(trans);
1380 ("NListAttrs nentries=%d %s\n", vldbentries->nbulkentries_len,
1382 return (ubik_EndTrans(trans));
1387 SVL_ListAttributesN2(struct rx_call *rxcall,
1388 struct VldbListByAttributes *attributes,
1389 char *name, /* Wildcarded volume name */
1390 afs_int32 startindex,
1391 afs_int32 *nentries,
1392 nbulkentries *vldbentries,
1393 afs_int32 *nextstartindex)
1395 int errorcode = 0, maxCount = VLDBALLOCCOUNT;
1396 struct ubik_trans *trans;
1397 struct nvlentry tentry;
1398 struct nvldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1399 afs_int32 blockindex = 0, count = 0, k, match;
1400 afs_int32 matchindex = 0;
1401 int serverindex = -1; /* no server found */
1402 int findserver = 0, findpartition = 0, findflag = 0, findname = 0;
1404 int namematchRWBK, namematchRO, thismatch;
1406 char volumename[VL_MAXNAMELEN];
1407 #ifdef HAVE_POSIX_REGEX
1409 int need_regfree = 0;
1414 COUNT_REQ(VLLISTATTRIBUTESN2);
1415 vldbentries->nbulkentries_val = 0;
1416 vldbentries->nbulkentries_len = 0;
1418 *nextstartindex = -1;
1420 errorcode = Init_VLdbase(&trans, LOCKREAD, this_op);
1424 Vldbentry = VldbentryFirst = vldbentries->nbulkentries_val =
1425 (nvldbentry *) malloc(maxCount * sizeof(nvldbentry));
1426 if (Vldbentry == NULL) {
1428 ubik_AbortTrans(trans);
1432 VldbentryLast = VldbentryFirst + maxCount;
1434 /* Handle the attribute by volume id totally separate of the rest
1435 * (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!)
1437 if (attributes->Mask & VLLIST_VOLUMEID) {
1439 FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1440 if (blockindex == 0) {
1442 errorcode = VL_NOENT;
1445 put_nattributeentry(&Vldbentry, &VldbentryFirst,
1446 &VldbentryLast, vldbentries, &tentry, 0,
1447 0, nentries, &maxCount);
1453 /* Search each entry in the database and return all entries
1454 * that match the request. It checks volumename (with
1455 * wildcarding), entry flags, server, and partition.
1458 /* Get the server index for matching server address */
1459 if (attributes->Mask & VLLIST_SERVER) {
1461 IpAddrToRelAddr(attributes->server, NULL);
1462 if (serverindex == -1)
1466 findpartition = ((attributes->Mask & VLLIST_PARTITION) ? 1 : 0);
1467 findflag = ((attributes->Mask & VLLIST_FLAG) ? 1 : 0);
1468 if (name && (strcmp(name, ".*") != 0) && (strcmp(name, "") != 0)) {
1469 sprintf(volumename, "^%s$", name);
1470 #ifdef HAVE_POSIX_REGEX
1471 if (regcomp(&re, volumename, REG_NOSUB) != 0) {
1472 errorcode = VL_BADNAME;
1477 t = (char *)re_comp(volumename);
1479 errorcode = VL_BADNAME;
1486 /* Read each entry and see if it is the one we want */
1487 blockindex = startindex;
1488 while ((blockindex = NextEntry(trans, blockindex, &tentry, &count))) {
1489 if (++pollcount > 50) {
1490 #ifndef AFS_PTHREAD_ENV
1496 /* Step through each server index searching for a match.
1497 * Match to an existing RW, BK, or RO volume name (preference
1498 * is in this order). Remember which index we matched against.
1500 namematchRWBK = namematchRO = 0; /* 0->notTried; 1->match; 2->noMatch */
1504 && (tentry.serverNumber[k] != BADSERVERID)); k++) {
1505 thismatch = 0; /* does this index match */
1507 /* Match against the RW or BK volume name. Remember
1508 * results in namematchRWBK. Prefer RW over BK.
1510 if (tentry.serverFlags[k] & VLSF_RWVOL) {
1511 /* Does the name match the RW name */
1512 if (tentry.flags & VLF_RWEXISTS) {
1514 sprintf(volumename, "%s", tentry.name);
1515 #ifdef HAVE_POSIX_REGEX
1516 if (regexec(&re, volumename, 0, NULL, 0) == 0) {
1517 thismatch = VLSF_RWVOL;
1520 if (re_exec(volumename)) {
1521 thismatch = VLSF_RWVOL;
1525 thismatch = VLSF_RWVOL;
1529 /* Does the name match the BK name */
1530 if (!thismatch && (tentry.flags & VLF_BACKEXISTS)) {
1532 sprintf(volumename, "%s.backup", tentry.name);
1533 #ifdef HAVE_POSIX_REGEX
1534 if (regexec(&re, volumename, 0, NULL, 0) == 0) {
1535 thismatch = VLSF_BACKVOL;
1538 if (re_exec(volumename)) {
1539 thismatch = VLSF_BACKVOL;
1543 thismatch = VLSF_BACKVOL;
1547 namematchRWBK = (thismatch ? 1 : 2);
1550 /* Match with the RO volume name. Compare once and
1551 * remember results in namematchRO. Note that this will
1552 * pick up entries marked NEWREPSITEs and DONTUSE.
1555 if (tentry.flags & VLF_ROEXISTS) {
1559 ((namematchRO == 1) ? VLSF_ROVOL : 0);
1561 sprintf(volumename, "%s.readonly",
1563 #ifdef HAVE_POSIX_REGEX
1564 if (regexec(&re, volumename, 0, NULL, 0) == 0) {
1565 thismatch = VLSF_ROVOL;
1568 if (re_exec(volumename))
1569 thismatch = VLSF_ROVOL;
1573 thismatch = VLSF_ROVOL;
1576 namematchRO = (thismatch ? 1 : 2);
1579 /* Is there a server match */
1580 if (thismatch && findserver
1581 && (tentry.serverNumber[k] != serverindex))
1584 /* Is there a partition match */
1585 if (thismatch && findpartition
1586 && (tentry.serverPartition[k] != attributes->partition))
1589 /* Is there a flag match */
1590 if (thismatch && findflag
1591 && !(tentry.flags & attributes->flag))
1594 /* We found a match. Remember the index, and type */
1598 matchtype = thismatch;
1601 /* Since we prefer RW and BK volume matches over RO matches,
1602 * if we have already checked the RWBK name, then we already
1603 * found the best match and so end the search.
1605 * If we tried matching against the RW, BK, and RO volume names
1606 * and both failed, then we end the search (none will match).
1608 if ((match && namematchRWBK)
1609 || ((namematchRWBK == 2) && (namematchRO == 2)))
1613 /* Passed all the tests. Take it */
1616 put_nattributeentry(&Vldbentry, &VldbentryFirst,
1617 &VldbentryLast, vldbentries, &tentry,
1618 matchtype, matchindex, nentries,
1623 if (*nentries >= maxCount)
1624 break; /* collected the max */
1627 *nextstartindex = (blockindex ? blockindex : -1);
1631 #ifdef HAVE_POSIX_REGEX
1638 ubik_AbortTrans(trans);
1639 if (vldbentries->nbulkentries_val)
1640 free((char *)vldbentries->nbulkentries_val);
1641 vldbentries->nbulkentries_val = 0;
1642 vldbentries->nbulkentries_len = 0;
1643 *nextstartindex = -1;
1647 ("N2ListAttrs nentries=%d %s\n", vldbentries->nbulkentries_len,
1649 return (ubik_EndTrans(trans));
1654 /* Retrieves in vldbentries all vldb entries that match the specified
1655 * attributes (by server number, partition, volume type, and flag); if
1656 * volume id is specified then the associated list for that entry is
1657 * returned. CAUTION: This could be a very expensive call since in most
1658 * cases sequential search of all vldb entries is performed.
1661 SVL_LinkedList(struct rx_call *rxcall,
1662 struct VldbListByAttributes *attributes,
1663 afs_int32 *nentries,
1664 vldb_list *vldbentries)
1667 struct ubik_trans *trans;
1668 struct nvlentry tentry;
1669 vldblist vllist, *vllistptr;
1670 afs_int32 blockindex, count, match;
1675 COUNT_REQ(VLLINKEDLIST);
1676 if ((errorcode = Init_VLdbase(&trans, LOCKREAD, this_op)))
1680 vldbentries->node = NULL;
1681 vllistptr = &vldbentries->node;
1683 /* List by volumeid */
1684 if (attributes->Mask & VLLIST_VOLUMEID) {
1686 FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1689 ubik_AbortTrans(trans);
1690 return (errorcode ? errorcode : VL_NOENT);
1693 vllist = (single_vldbentry *) malloc(sizeof(single_vldbentry));
1694 if (vllist == NULL) {
1696 ubik_AbortTrans(trans);
1699 vlentry_to_vldbentry(&tentry, &vllist->VldbEntry);
1700 vllist->next_vldb = NULL;
1702 *vllistptr = vllist; /* Thread onto list */
1703 vllistptr = &vllist->next_vldb;
1707 /* Search by server, partition, and flags */
1709 for (blockindex = NextEntry(trans, 0, &tentry, &count); blockindex;
1710 blockindex = NextEntry(trans, blockindex, &tentry, &count)) {
1713 if (++pollcount > 50) {
1714 #ifndef AFS_PTHREAD_ENV
1720 /* Does this volume exist on the desired server */
1721 if (attributes->Mask & VLLIST_SERVER) {
1723 IpAddrToRelAddr(attributes->server, NULL);
1724 if (serverindex == -1)
1726 for (k = 0; k < OMAXNSERVERS; k++) {
1727 if (tentry.serverNumber[k] == BADSERVERID)
1729 if (tentry.serverNumber[k] == serverindex) {
1738 /* Does this volume exist on the desired partition */
1739 if (attributes->Mask & VLLIST_PARTITION) {
1741 if (tentry.serverPartition[k] != attributes->partition)
1744 for (k = 0; k < OMAXNSERVERS; k++) {
1745 if (tentry.serverNumber[k] == BADSERVERID)
1747 if (tentry.serverPartition[k] ==
1748 attributes->partition) {
1758 /* Does this volume have the desired flags */
1759 if (attributes->Mask & VLLIST_FLAG) {
1760 if (!(tentry.flags & attributes->flag))
1764 vllist = (single_vldbentry *) malloc(sizeof(single_vldbentry));
1765 if (vllist == NULL) {
1767 ubik_AbortTrans(trans);
1770 vlentry_to_vldbentry(&tentry, &vllist->VldbEntry);
1771 vllist->next_vldb = NULL;
1773 *vllistptr = vllist; /* Thread onto list */
1774 vllistptr = &vllist->next_vldb;
1776 if (smallMem && (*nentries >= VLDBALLOCCOUNT)) {
1778 ubik_AbortTrans(trans);
1779 return VL_SIZEEXCEEDED;
1784 return (ubik_EndTrans(trans));
1788 SVL_LinkedListN(struct rx_call *rxcall,
1789 struct VldbListByAttributes *attributes,
1790 afs_int32 *nentries,
1791 nvldb_list *vldbentries)
1794 struct ubik_trans *trans;
1795 struct nvlentry tentry;
1796 nvldblist vllist, *vllistptr;
1797 afs_int32 blockindex, count, match;
1802 COUNT_REQ(VLLINKEDLISTN);
1803 if ((errorcode = Init_VLdbase(&trans, LOCKREAD, this_op)))
1807 vldbentries->node = NULL;
1808 vllistptr = &vldbentries->node;
1810 /* List by volumeid */
1811 if (attributes->Mask & VLLIST_VOLUMEID) {
1813 FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1816 ubik_AbortTrans(trans);
1817 return (errorcode ? errorcode : VL_NOENT);
1820 vllist = (single_nvldbentry *) malloc(sizeof(single_nvldbentry));
1821 if (vllist == NULL) {
1823 ubik_AbortTrans(trans);
1826 vlentry_to_nvldbentry(&tentry, &vllist->VldbEntry);
1827 vllist->next_vldb = NULL;
1829 *vllistptr = vllist; /* Thread onto list */
1830 vllistptr = &vllist->next_vldb;
1834 /* Search by server, partition, and flags */
1836 for (blockindex = NextEntry(trans, 0, &tentry, &count); blockindex;
1837 blockindex = NextEntry(trans, blockindex, &tentry, &count)) {
1840 if (++pollcount > 50) {
1841 #ifndef AFS_PTHREAD_ENV
1847 /* Does this volume exist on the desired server */
1848 if (attributes->Mask & VLLIST_SERVER) {
1850 IpAddrToRelAddr(attributes->server, NULL);
1851 if (serverindex == -1)
1853 for (k = 0; k < NMAXNSERVERS; k++) {
1854 if (tentry.serverNumber[k] == BADSERVERID)
1856 if (tentry.serverNumber[k] == serverindex) {
1865 /* Does this volume exist on the desired partition */
1866 if (attributes->Mask & VLLIST_PARTITION) {
1868 if (tentry.serverPartition[k] != attributes->partition)
1871 for (k = 0; k < NMAXNSERVERS; k++) {
1872 if (tentry.serverNumber[k] == BADSERVERID)
1874 if (tentry.serverPartition[k] ==
1875 attributes->partition) {
1885 /* Does this volume have the desired flags */
1886 if (attributes->Mask & VLLIST_FLAG) {
1887 if (!(tentry.flags & attributes->flag))
1891 vllist = (single_nvldbentry *) malloc(sizeof(single_nvldbentry));
1892 if (vllist == NULL) {
1894 ubik_AbortTrans(trans);
1897 vlentry_to_nvldbentry(&tentry, &vllist->VldbEntry);
1898 vllist->next_vldb = NULL;
1900 *vllistptr = vllist; /* Thread onto list */
1901 vllistptr = &vllist->next_vldb;
1903 if (smallMem && (*nentries >= VLDBALLOCCOUNT)) {
1905 ubik_AbortTrans(trans);
1906 return VL_SIZEEXCEEDED;
1911 return (ubik_EndTrans(trans));
1914 /* Get back vldb header statistics (allocs, frees, maxvolumeid,
1915 * totalentries, etc) and dynamic statistics (number of requests and/or
1916 * aborts per remote procedure call, etc)
1919 SVL_GetStats(struct rx_call *rxcall,
1921 vital_vlheader *vital_header)
1923 register afs_int32 errorcode;
1924 struct ubik_trans *trans;
1926 COUNT_REQ(VLGETSTATS);
1928 /* Allow users to get statistics freely */
1929 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) /* Must be in 'UserList' to use */
1932 if ((errorcode = Init_VLdbase(&trans, LOCKREAD, this_op)))
1934 VLog(5, ("GetStats %s\n", rxinfo(rxcall)));
1935 memcpy((char *)vital_header, (char *)&cheader.vital_header,
1936 sizeof(vital_vlheader));
1937 memcpy((char *)stats, (char *)&dynamic_statistics, sizeof(vldstats));
1938 return (ubik_EndTrans(trans));
1941 /* Get the list of file server addresses from the VLDB. Currently it's pretty
1942 * easy to do. In the future, it might require a little bit of grunging
1943 * through the VLDB, but that's life.
1946 SVL_GetAddrs(struct rx_call *rxcall,
1949 struct VLCallBack *spare3,
1950 afs_int32 *nentries,
1953 register afs_int32 errorcode;
1954 struct ubik_trans *trans;
1958 COUNT_REQ(VLGETADDRS);
1959 addrsp->bulkaddrs_len = *nentries = 0;
1960 addrsp->bulkaddrs_val = 0;
1961 memset(spare3, 0, sizeof(struct VLCallBack));
1963 if ((errorcode = Init_VLdbase(&trans, LOCKREAD, this_op)))
1966 VLog(5, ("GetAddrs\n"));
1967 addrsp->bulkaddrs_val = taddrp =
1968 (afs_uint32 *) malloc(sizeof(afs_int32) * (MAXSERVERID + 1));
1969 nservers = *nentries = addrsp->bulkaddrs_len = 0;
1973 ubik_AbortTrans(trans);
1977 for (i = 0; i <= MAXSERVERID; i++) {
1978 if ((*taddrp = ntohl(cheader.IpMappedAddr[i]))) {
1984 addrsp->bulkaddrs_len = *nentries = nservers;
1985 return (ubik_EndTrans(trans));
1988 #define PADDR(addr) VLog(0,("%d.%d.%d.%d", (addr>>24)&0xff, (addr>>16)&0xff, (addr>>8) &0xff, addr&0xff));
1991 SVL_RegisterAddrs(struct rx_call *rxcall, afsUUID *uuidp, afs_int32 spare1,
1995 struct ubik_trans *trans;
1996 int cnt, h, i, j, k, m, base, index;
1997 struct extentaddr *exp = 0, *tex;
1999 afs_uint32 addrs[VL_MAXIPADDRS_PERMH];
2001 int count, willChangeEntry, foundUuidEntry, willReplaceCnt;
2002 int WillReplaceEntry, WillChange[MAXSERVERID + 1];
2004 int ReplaceEntry = 0;
2007 COUNT_REQ(VLREGADDR);
2008 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
2010 if ((code = Init_VLdbase(&trans, LOCKWRITE, this_op)))
2013 /* Eliminate duplicates from IP address list */
2014 for (k = 0, cnt = 0; k < addrsp->bulkaddrs_len; k++) {
2015 if (addrsp->bulkaddrs_val[k] == 0)
2017 for (m = 0; m < cnt; m++) {
2018 if (addrs[m] == addrsp->bulkaddrs_val[k])
2022 if (m == VL_MAXIPADDRS_PERMH) {
2024 ("Number of addresses exceeds %d. Cannot register IP addr 0x%x in VLDB\n",
2025 VL_MAXIPADDRS_PERMH, addrsp->bulkaddrs_val[k]));
2027 addrs[m] = addrsp->bulkaddrs_val[k];
2033 ubik_AbortTrans(trans);
2034 return VL_INDEXERANGE;
2040 /* For each server registered within the VLDB */
2041 for (srvidx = 0; srvidx <= MAXSERVERID; srvidx++) {
2042 willChangeEntry = 0;
2043 WillReplaceEntry = 1;
2044 if ((HostAddress[srvidx] & 0xff000000) == 0xff000000) {
2045 /* The server is registered as a multihomed */
2046 base = (HostAddress[srvidx] >> 16) & 0xff;
2047 index = HostAddress[srvidx] & 0x0000ffff;
2048 if (base >= VL_MAX_ADDREXTBLKS) {
2050 ("Internal error: Multihome extent base is too large. Base %d index %d\n",
2054 if (index >= VL_MHSRV_PERBLK) {
2056 ("Internal error: Multihome extent index is too large. Base %d index %d\n",
2060 if (!ex_addr[base]) {
2062 ("Internal error: Multihome extent does not exist. Base %d\n",
2067 /* See if the addresses to register will change this server entry */
2068 exp = &ex_addr[base][index];
2069 tuuid = exp->ex_hostuuid;
2070 afs_ntohuuid(&tuuid);
2071 if (afs_uuid_equal(uuidp, &tuuid)) {
2075 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2076 if (!exp->ex_addrs[mhidx])
2078 for (k = 0; k < cnt; k++) {
2079 if (ntohl(exp->ex_addrs[mhidx]) == addrs[k]) {
2080 willChangeEntry = 1;
2081 WillChange[count] = srvidx;
2086 WillReplaceEntry = 0;
2090 /* The server is not registered as a multihomed.
2091 * See if the addresses to register will replace this server entry.
2093 for (k = 0; k < cnt; k++) {
2094 if (HostAddress[srvidx] == addrs[k]) {
2095 willChangeEntry = 1;
2096 WillChange[count] = srvidx;
2097 WillReplaceEntry = 1;
2102 if (willChangeEntry) {
2103 if (WillReplaceEntry) {
2105 ReplaceEntry = srvidx;
2111 /* If we found the uuid in the VLDB and if we are replacing another
2112 * entire entry, then complain and fail. Also, if we did not find
2113 * the uuid in the VLDB and the IP addresses being registered was
2114 * found in more than one other entry, then we don't know which one
2115 * to replace and will complain and fail.
2117 if ((foundUuidEntry && (willReplaceCnt > 0))
2118 || (!foundUuidEntry && (count > 1))) {
2120 ("The following fileserver is being registered in the VLDB:\n"));
2122 for (k = 0; k < cnt; k++) {
2129 if (foundUuidEntry) {
2131 (" It would have replaced the existing VLDB server entry:\n"));
2132 VLog(0, (" entry %d: [", FoundUuid));
2133 base = (HostAddress[FoundUuid] >> 16) & 0xff;
2134 index = HostAddress[FoundUuid] & 0x0000ffff;
2135 exp = &ex_addr[base][index];
2136 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2137 if (!exp->ex_addrs[mhidx])
2141 PADDR(ntohl(exp->ex_addrs[mhidx]));
2147 VLog(0, (" Yet another VLDB server entry exists:\n"));
2149 VLog(0, (" Yet other VLDB server entries exist:\n"));
2150 for (j = 0; j < count; j++) {
2151 srvidx = WillChange[j];
2152 VLog(0, (" entry %d: ", srvidx));
2153 if ((HostAddress[srvidx] & 0xff000000) == 0xff000000) {
2155 base = (HostAddress[srvidx] >> 16) & 0xff;
2156 index = HostAddress[srvidx] & 0x0000ffff;
2157 exp = &ex_addr[base][index];
2158 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2159 if (!exp->ex_addrs[mhidx])
2163 PADDR(ntohl(exp->ex_addrs[mhidx]));
2167 PADDR(HostAddress[srvidx]);
2173 VLog(0, (" You must 'vos changeaddr' this other server entry\n"));
2176 (" You must 'vos changeaddr' these other server entries\n"));
2179 (" and/or remove the sysid file from the registering fileserver\n"));
2180 VLog(0, (" before the fileserver can be registered in the VLDB.\n"));
2182 ubik_AbortTrans(trans);
2183 return VL_MULTIPADDR;
2186 /* Passed the checks. Now find and update the existing mh entry, or create
2189 if (foundUuidEntry) {
2190 /* Found the entry with same uuid. See if we need to change it */
2193 fbase = (HostAddress[FoundUuid] >> 16) & 0xff;
2194 index = HostAddress[FoundUuid] & 0x0000ffff;
2195 exp = &ex_addr[fbase][index];
2197 /* Determine if the entry has changed */
2198 for (k = 0; ((k < cnt) && !change); k++) {
2199 if (ntohl(exp->ex_addrs[k]) != addrs[k])
2202 for (; ((k < VL_MAXIPADDRS_PERMH) && !change); k++) {
2203 if (exp->ex_addrs[k] != 0)
2207 return (ubik_EndTrans(trans));
2211 VLog(0, ("The following fileserver is being registered in the VLDB:\n"));
2213 for (k = 0; k < cnt; k++) {
2220 if (foundUuidEntry) {
2222 (" It will replace the following existing entry in the VLDB (same uuid):\n"));
2223 VLog(0, (" entry %d: [", FoundUuid));
2224 for (k = 0; k < VL_MAXIPADDRS_PERMH; k++) {
2225 if (exp->ex_addrs[k] == 0)
2229 PADDR(ntohl(exp->ex_addrs[k]));
2232 } else if (willReplaceCnt || (count == 1)) {
2233 /* If we are not replacing an entry and there is only one entry to change,
2234 * then we will replace that entry.
2236 if (!willReplaceCnt) {
2237 ReplaceEntry = WillChange[0];
2241 /* Have an entry that needs to be replaced */
2242 if ((HostAddress[ReplaceEntry] & 0xff000000) == 0xff000000) {
2243 fbase = (HostAddress[ReplaceEntry] >> 16) & 0xff;
2244 index = HostAddress[ReplaceEntry] & 0x0000ffff;
2245 exp = &ex_addr[fbase][index];
2248 (" It will replace the following existing entry in the VLDB (new uuid):\n"));
2249 VLog(0, (" entry %d: [", ReplaceEntry));
2250 for (k = 0; k < VL_MAXIPADDRS_PERMH; k++) {
2251 if (exp->ex_addrs[k] == 0)
2255 PADDR(ntohl(exp->ex_addrs[k]));
2259 /* Not a mh entry. So we have to create a new mh entry and
2260 * put it on the ReplaceEntry slot of the HostAddress array.
2262 VLog(0, (" It will replace existing entry %d, ", ReplaceEntry));
2263 PADDR(HostAddress[ReplaceEntry]);
2264 VLog(0,(", in the VLDB (new uuid):\n"));
2267 FindExtentBlock(trans, uuidp, 1, ReplaceEntry, &exp, &fbase);
2269 ubik_AbortTrans(trans);
2270 return (code ? code : VL_IO);
2274 /* There is no entry for this server, must create a new mh entry as
2275 * well as use a new slot of the HostAddress array.
2277 VLog(0, (" It will create a new entry in the VLDB.\n"));
2278 code = FindExtentBlock(trans, uuidp, 1, -1, &exp, &fbase);
2280 ubik_AbortTrans(trans);
2281 return (code ? code : VL_IO);
2285 /* Now we have a mh entry to fill in. Update the uuid, bump the
2286 * uniquifier, and fill in its IP addresses.
2289 afs_htonuuid(&tuuid);
2290 exp->ex_hostuuid = tuuid;
2291 exp->ex_uniquifier = htonl(ntohl(exp->ex_uniquifier) + 1);
2292 for (k = 0; k < cnt; k++) {
2293 exp->ex_addrs[k] = htonl(addrs[k]);
2295 for (; k < VL_MAXIPADDRS_PERMH; k++) {
2296 exp->ex_addrs[k] = 0;
2299 /* Write the new mh entry out */
2302 DOFFSET(ntohl(ex_addr[0]->ex_contaddrs[fbase]),
2303 (char *)ex_addr[fbase], (char *)exp), (char *)exp,
2305 ubik_AbortTrans(trans);
2309 /* Remove any common addresses from other mh entres. We know these entries
2310 * are being changed and not replaced so they are mh entries.
2313 for (i = 0; i < count; i++) {
2316 /* Skip the entry we replaced */
2317 if (willReplaceCnt && (WillChange[i] == ReplaceEntry))
2320 base = (HostAddress[WillChange[i]] >> 16) & 0xff;
2321 index = HostAddress[WillChange[i]] & 0x0000ffff;
2322 tex = &ex_addr[fbase][index];
2326 (" The following existing entries in the VLDB will be updated:\n"));
2328 VLog(0, (" entry %d: [", WillChange[i]));
2329 for (h = j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2330 if (tex->ex_addrs[j]) {
2333 PADDR(ntohl(tex->ex_addrs[j]));
2336 for (k = 0; k < cnt; k++) {
2337 if (ntohl(tex->ex_addrs[j]) == addrs[k])
2341 /* Not found, so we keep it */
2342 tex->ex_addrs[h] = tex->ex_addrs[j];
2346 for (j = h; j < VL_MAXIPADDRS_PERMH; j++) {
2347 tex->ex_addrs[j] = 0; /* zero rest of mh entry */
2351 /* Write out the modified mh entry */
2352 tex->ex_uniquifier = htonl(ntohl(tex->ex_uniquifier) + 1);
2354 DOFFSET(ntohl(ex_addr[0]->ex_contaddrs[base]),
2355 (char *)ex_addr[base], (char *)tex);
2356 if (vlwrite(trans, doff, (char *)tex, sizeof(*tex))) {
2357 ubik_AbortTrans(trans);
2362 return (ubik_EndTrans(trans));
2366 SVL_GetAddrsU(struct rx_call *rxcall,
2367 struct ListAddrByAttributes *attributes,
2369 afs_int32 *uniquifier,
2370 afs_int32 *nentries,
2373 register afs_int32 errorcode, index = -1, offset;
2374 struct ubik_trans *trans;
2375 int nservers, i, j, base = 0;
2376 struct extentaddr *exp = 0;
2378 afs_uint32 *taddrp, taddr;
2380 COUNT_REQ(VLGETADDRSU);
2381 addrsp->bulkaddrs_len = *nentries = 0;
2382 addrsp->bulkaddrs_val = 0;
2383 VLog(5, ("GetAddrsU %s\n", rxinfo(rxcall)));
2384 if ((errorcode = Init_VLdbase(&trans, LOCKREAD, this_op)))
2387 if (attributes->Mask & VLADDR_IPADDR) {
2388 if (attributes->Mask & (VLADDR_INDEX | VLADDR_UUID)) {
2389 ubik_AbortTrans(trans);
2392 for (base = 0; base < VL_MAX_ADDREXTBLKS; base++) {
2395 for (i = 1; i < VL_MHSRV_PERBLK; i++) {
2396 exp = &ex_addr[base][i];
2397 tuuid = exp->ex_hostuuid;
2398 afs_ntohuuid(&tuuid);
2399 if (afs_uuid_is_nil(&tuuid))
2401 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2402 if (exp->ex_addrs[j]
2403 && (ntohl(exp->ex_addrs[j]) == attributes->ipaddr)) {
2407 if (j < VL_MAXIPADDRS_PERMH)
2410 if (i < VL_MHSRV_PERBLK)
2413 if (base >= VL_MAX_ADDREXTBLKS) {
2414 ubik_AbortTrans(trans);
2417 } else if (attributes->Mask & VLADDR_INDEX) {
2418 if (attributes->Mask & (VLADDR_IPADDR | VLADDR_UUID)) {
2419 ubik_AbortTrans(trans);
2422 index = attributes->index;
2423 if (index < 1 || index >= (VL_MAX_ADDREXTBLKS * VL_MHSRV_PERBLK)) {
2424 ubik_AbortTrans(trans);
2425 return VL_INDEXERANGE;
2427 base = index / VL_MHSRV_PERBLK;
2428 offset = index % VL_MHSRV_PERBLK;
2430 ubik_AbortTrans(trans);
2433 if (!ex_addr[base]) {
2434 ubik_AbortTrans(trans);
2435 return VL_INDEXERANGE;
2437 exp = &ex_addr[base][offset];
2438 } else if (attributes->Mask & VLADDR_UUID) {
2439 if (attributes->Mask & (VLADDR_IPADDR | VLADDR_INDEX)) {
2440 ubik_AbortTrans(trans);
2443 if (!ex_addr[0]) { /* mh servers probably aren't setup on this vldb */
2444 ubik_AbortTrans(trans);
2448 FindExtentBlock(trans, &attributes->uuid, 0, -1, &exp, &base))) {
2449 ubik_AbortTrans(trans);
2453 ubik_AbortTrans(trans);
2458 ubik_AbortTrans(trans);
2461 addrsp->bulkaddrs_val = taddrp =
2462 (afs_uint32 *) malloc(sizeof(afs_int32) * (MAXSERVERID + 1));
2463 nservers = *nentries = addrsp->bulkaddrs_len = 0;
2466 ubik_AbortTrans(trans);
2469 tuuid = exp->ex_hostuuid;
2470 afs_ntohuuid(&tuuid);
2471 if (afs_uuid_is_nil(&tuuid)) {
2472 ubik_AbortTrans(trans);
2478 *uniquifier = ntohl(exp->ex_uniquifier);
2479 for (i = 0; i < VL_MAXIPADDRS_PERMH; i++) {
2480 if (exp->ex_addrs[i]) {
2481 taddr = ntohl(exp->ex_addrs[i]);
2482 /* Weed out duplicates */
2483 for (j = 0; j < nservers; j++) {
2484 if (taddrp[j] == taddr)
2487 if ((j == nservers) && (j <= MAXSERVERID)) {
2488 taddrp[nservers] = taddr;
2493 addrsp->bulkaddrs_len = *nentries = nservers;
2494 return (ubik_EndTrans(trans));
2497 /* ============> End of Exported vldb RPC functions <============= */
2500 /* Routine that copies the given vldb entry to the output buffer, vldbentries. */
2502 put_attributeentry(struct vldbentry **Vldbentry,
2503 struct vldbentry **VldbentryFirst,
2504 struct vldbentry **VldbentryLast,
2505 bulkentries *vldbentries,
2506 struct nvlentry *entry,
2507 afs_int32 *nentries,
2508 afs_int32 *alloccnt)
2513 if (*Vldbentry == *VldbentryLast) {
2515 return VL_SIZEEXCEEDED; /* no growing if smallMem defined */
2517 /* Allocate another set of memory; each time allocate twice as
2518 * many blocks as the last time. When we reach VLDBALLOCLIMIT,
2519 * then grow in increments of VLDBALLOCINCR.
2521 allo = (*alloccnt > VLDBALLOCLIMIT) ? VLDBALLOCINCR : *alloccnt;
2523 (vldbentry *) realloc(*VldbentryFirst,
2524 (*alloccnt + allo) * sizeof(vldbentry));
2528 *VldbentryFirst = vldbentries->bulkentries_val = reall;
2529 *Vldbentry = *VldbentryFirst + *alloccnt;
2530 *VldbentryLast = *Vldbentry + allo;
2533 vlentry_to_vldbentry(entry, *Vldbentry);
2536 vldbentries->bulkentries_len++;
2541 put_nattributeentry(struct nvldbentry **Vldbentry,
2542 struct nvldbentry **VldbentryFirst,
2543 struct nvldbentry **VldbentryLast,
2544 nbulkentries *vldbentries,
2545 struct nvlentry *entry,
2546 afs_int32 matchtype,
2547 afs_int32 matchindex,
2548 afs_int32 *nentries,
2549 afs_int32 *alloccnt)
2554 if (*Vldbentry == *VldbentryLast) {
2556 return VL_SIZEEXCEEDED; /* no growing if smallMem defined */
2558 /* Allocate another set of memory; each time allocate twice as
2559 * many blocks as the last time. When we reach VLDBALLOCLIMIT,
2560 * then grow in increments of VLDBALLOCINCR.
2562 allo = (*alloccnt > VLDBALLOCLIMIT) ? VLDBALLOCINCR : *alloccnt;
2564 (nvldbentry *) realloc(*VldbentryFirst,
2565 (*alloccnt + allo) * sizeof(nvldbentry));
2569 *VldbentryFirst = vldbentries->nbulkentries_val = reall;
2570 *Vldbentry = *VldbentryFirst + *alloccnt;
2571 *VldbentryLast = *Vldbentry + allo;
2574 vlentry_to_nvldbentry(entry, *Vldbentry);
2575 (*Vldbentry)->matchindex = (matchtype << 16) + matchindex;
2578 vldbentries->nbulkentries_len++;
2583 /* Common code to actually remove a vldb entry from the database. */
2585 RemoveEntry(struct ubik_trans *trans, afs_int32 entryptr,
2586 struct nvlentry *tentry)
2588 register int errorcode;
2590 if ((errorcode = UnthreadVLentry(trans, entryptr, tentry)))
2592 if ((errorcode = FreeBlock(trans, entryptr)))
2598 ReleaseEntry(struct nvlentry *tentry, afs_int32 releasetype)
2600 if (releasetype & LOCKREL_TIMESTAMP)
2601 tentry->LockTimestamp = 0;
2602 if (releasetype & LOCKREL_OPCODE)
2603 tentry->flags &= ~VLOP_ALLOPERS;
2604 if (releasetype & LOCKREL_AFSID)
2605 tentry->LockAfsId = 0;
2609 /* Verify that the incoming vldb entry is valid; multi type of error codes
2612 check_vldbentry(struct vldbentry *aentry)
2616 if (InvalidVolname(aentry->name))
2618 if (aentry->nServers <= 0 || aentry->nServers > OMAXNSERVERS)
2619 return VL_BADSERVER;
2620 for (i = 0; i < aentry->nServers; i++) {
2621 /* if (aentry->serverNumber[i] < 0 || aentry->serverNumber[i] > MAXSERVERID)
2622 return VL_BADSERVER; */
2623 if (aentry->serverPartition[i] < 0
2624 || aentry->serverPartition[i] > MAXPARTITIONID)
2625 return VL_BADPARTITION;
2626 if (aentry->serverFlags[i] < 0
2627 || aentry->serverFlags[i] > MAXSERVERFLAG)
2628 return VL_BADSERVERFLAG;
2634 check_nvldbentry(struct nvldbentry *aentry)
2638 if (InvalidVolname(aentry->name))
2640 if (aentry->nServers <= 0 || aentry->nServers > NMAXNSERVERS)
2641 return VL_BADSERVER;
2642 for (i = 0; i < aentry->nServers; i++) {
2643 /* if (aentry->serverNumber[i] < 0 || aentry->serverNumber[i] > MAXSERVERID)
2644 return VL_BADSERVER; */
2645 if (aentry->serverPartition[i] < 0
2646 || aentry->serverPartition[i] > MAXPARTITIONID)
2647 return VL_BADPARTITION;
2648 if (aentry->serverFlags[i] < 0
2649 || aentry->serverFlags[i] > MAXSERVERFLAG)
2650 return VL_BADSERVERFLAG;
2656 /* Convert from the external vldb entry representation to its internal
2657 (more compact) form. This call should not change the hash chains! */
2659 vldbentry_to_vlentry(struct ubik_trans *atrans,
2660 struct vldbentry *VldbEntry,
2661 struct nvlentry *VlEntry)
2665 if (strcmp(VlEntry->name, VldbEntry->name))
2666 strncpy(VlEntry->name, VldbEntry->name, sizeof(VlEntry->name));
2667 for (i = 0; i < VldbEntry->nServers; i++) {
2668 serverindex = IpAddrToRelAddr(VldbEntry->serverNumber[i], atrans);
2669 if (serverindex == -1)
2670 return VL_BADSERVER;
2671 VlEntry->serverNumber[i] = serverindex;
2672 VlEntry->serverPartition[i] = VldbEntry->serverPartition[i];
2673 VlEntry->serverFlags[i] = VldbEntry->serverFlags[i];
2675 for (; i < OMAXNSERVERS; i++)
2676 VlEntry->serverNumber[i] = VlEntry->serverPartition[i] =
2677 VlEntry->serverFlags[i] = BADSERVERID;
2678 for (i = 0; i < MAXTYPES; i++)
2679 VlEntry->volumeId[i] = VldbEntry->volumeId[i];
2680 VlEntry->cloneId = VldbEntry->cloneId;
2681 VlEntry->flags = VldbEntry->flags;
2686 nvldbentry_to_vlentry(struct ubik_trans *atrans,
2687 struct nvldbentry *VldbEntry,
2688 struct nvlentry *VlEntry)
2692 if (strcmp(VlEntry->name, VldbEntry->name))
2693 strncpy(VlEntry->name, VldbEntry->name, sizeof(VlEntry->name));
2694 for (i = 0; i < VldbEntry->nServers; i++) {
2695 serverindex = IpAddrToRelAddr(VldbEntry->serverNumber[i], atrans);
2696 if (serverindex == -1)
2697 return VL_BADSERVER;
2698 VlEntry->serverNumber[i] = serverindex;
2699 VlEntry->serverPartition[i] = VldbEntry->serverPartition[i];
2700 VlEntry->serverFlags[i] = VldbEntry->serverFlags[i];
2702 for (; i < NMAXNSERVERS; i++)
2703 VlEntry->serverNumber[i] = VlEntry->serverPartition[i] =
2704 VlEntry->serverFlags[i] = BADSERVERID;
2705 for (i = 0; i < MAXTYPES; i++)
2706 VlEntry->volumeId[i] = VldbEntry->volumeId[i];
2707 VlEntry->cloneId = VldbEntry->cloneId;
2708 VlEntry->flags = VldbEntry->flags;
2713 /* Update the vldb entry with the new fields as indicated by the value of
2714 * the Mask entry in the updateentry structure. All necessary validation
2715 * checks are performed.
2718 get_vldbupdateentry(struct ubik_trans *trans,
2719 afs_int32 blockindex,
2720 struct VldbUpdateEntry *updateentry,
2721 struct nvlentry *VlEntry)
2723 int i, j, errorcode, serverindex;
2724 afs_uint32 checkids[MAXTYPES];
2726 /* check if any specified new IDs are already present in the db. Do
2727 * this check before doing anything else, so we don't get a half-
2729 memset(&checkids, 0, sizeof(checkids));
2730 if (updateentry->Mask & VLUPDATE_RWID) {
2731 checkids[RWVOL] = updateentry->spares3; /* rw id */
2733 if (updateentry->Mask & VLUPDATE_READONLYID) {
2734 checkids[ROVOL] = updateentry->ReadOnlyId;
2736 if (updateentry->Mask & VLUPDATE_BACKUPID) {
2737 checkids[BACKVOL] = updateentry->BackupId;
2740 if (EntryIDExists(trans, checkids, MAXTYPES, &errorcode)) {
2742 } else if (errorcode) {
2746 if (updateentry->Mask & VLUPDATE_VOLUMENAME) {
2747 struct nvlentry tentry;
2749 if (InvalidVolname(updateentry->name))
2752 if (FindByName(trans, updateentry->name, &tentry, &errorcode)) {
2753 return VL_NAMEEXIST;
2754 } else if (errorcode) {
2758 if ((errorcode = UnhashVolname(trans, blockindex, VlEntry)))
2760 strncpy(VlEntry->name, updateentry->name, sizeof(VlEntry->name));
2761 HashVolname(trans, blockindex, VlEntry);
2764 if (updateentry->Mask & VLUPDATE_VOLNAMEHASH) {
2765 if ((errorcode = UnhashVolname(trans, blockindex, VlEntry))) {
2766 if (errorcode != VL_NOENT)
2769 HashVolname(trans, blockindex, VlEntry);
2772 if (updateentry->Mask & VLUPDATE_FLAGS) {
2773 VlEntry->flags = updateentry->flags;
2775 if (updateentry->Mask & VLUPDATE_CLONEID) {
2776 VlEntry->cloneId = updateentry->cloneId;
2778 if (updateentry->Mask & VLUPDATE_RWID) {
2779 if ((errorcode = UnhashVolid(trans, RWVOL, blockindex, VlEntry))) {
2780 if (errorcode != VL_NOENT)
2783 VlEntry->volumeId[RWVOL] = updateentry->spares3; /* rw id */
2784 if ((errorcode = HashVolid(trans, RWVOL, blockindex, VlEntry)))
2787 if (updateentry->Mask & VLUPDATE_READONLYID) {
2788 if ((errorcode = UnhashVolid(trans, ROVOL, blockindex, VlEntry))) {
2789 if (errorcode != VL_NOENT)
2792 VlEntry->volumeId[ROVOL] = updateentry->ReadOnlyId;
2793 if ((errorcode = HashVolid(trans, ROVOL, blockindex, VlEntry)))
2796 if (updateentry->Mask & VLUPDATE_BACKUPID) {
2797 if ((errorcode = UnhashVolid(trans, BACKVOL, blockindex, VlEntry))) {
2798 if (errorcode != VL_NOENT)
2801 VlEntry->volumeId[BACKVOL] = updateentry->BackupId;
2802 if ((errorcode = HashVolid(trans, BACKVOL, blockindex, VlEntry)))
2805 if (updateentry->Mask & VLUPDATE_REPSITES) {
2806 if (updateentry->nModifiedRepsites <= 0
2807 || updateentry->nModifiedRepsites > OMAXNSERVERS)
2808 return VL_BADSERVER;
2809 for (i = 0; i < updateentry->nModifiedRepsites; i++) {
2810 /* if (updateentry->RepsitesTargetServer[i] < 0 || updateentry->RepsitesTargetServer[i] > MAXSERVERID)
2811 return VL_BADSERVER; */
2812 if (updateentry->RepsitesTargetPart[i] < 0
2813 || updateentry->RepsitesTargetPart[i] > MAXPARTITIONID)
2814 return VL_BADPARTITION;
2815 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_DELETE) {
2817 repsite_exists(VlEntry,
2818 IpAddrToRelAddr(updateentry->
2819 RepsitesTargetServer[i],
2821 updateentry->RepsitesTargetPart[i])) !=
2823 repsite_compress(VlEntry, j);
2825 return VL_NOREPSERVER;
2827 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_ADD) {
2828 /* if (updateentry->RepsitesNewServer[i] < 0 || updateentry->RepsitesNewServer[i] > MAXSERVERID)
2829 return VL_BADSERVER; */
2830 if (updateentry->RepsitesNewPart[i] < 0
2831 || updateentry->RepsitesNewPart[i] > MAXPARTITIONID)
2832 return VL_BADPARTITION;
2835 IpAddrToRelAddr(updateentry->RepsitesNewServer[i],
2837 updateentry->RepsitesNewPart[i]) != -1)
2838 return VL_DUPREPSERVER;
2840 VlEntry->serverNumber[j] != BADSERVERID
2841 && j < OMAXNSERVERS; j++);
2842 if (j >= OMAXNSERVERS)
2845 IpAddrToRelAddr(updateentry->RepsitesNewServer[i],
2847 return VL_BADSERVER;
2848 VlEntry->serverNumber[j] = serverindex;
2849 VlEntry->serverPartition[j] = updateentry->RepsitesNewPart[i];
2850 if (updateentry->RepsitesNewFlags[i] < 0
2851 || updateentry->RepsitesNewFlags[i] > MAXSERVERFLAG)
2852 return VL_BADSERVERFLAG;
2853 VlEntry->serverFlags[j] = updateentry->RepsitesNewFlags[i];
2855 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODSERV) {
2856 /*n if (updateentry->RepsitesNewServer[i] < 0 || updateentry->RepsitesNewServer[i] > MAXSERVERID)
2857 return VL_BADSERVER; */
2859 repsite_exists(VlEntry,
2860 IpAddrToRelAddr(updateentry->
2861 RepsitesTargetServer[i],
2863 updateentry->RepsitesTargetPart[i])) !=
2865 VlEntry->serverNumber[j] =
2866 IpAddrToRelAddr(updateentry->RepsitesNewServer[i],
2869 return VL_NOREPSERVER;
2871 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODPART) {
2872 if (updateentry->RepsitesNewPart[i] < 0
2873 || updateentry->RepsitesNewPart[i] > MAXPARTITIONID)
2874 return VL_BADPARTITION;
2876 repsite_exists(VlEntry,
2877 IpAddrToRelAddr(updateentry->
2878 RepsitesTargetServer[i],
2880 updateentry->RepsitesTargetPart[i])) !=
2882 VlEntry->serverPartition[j] =
2883 updateentry->RepsitesNewPart[i];
2885 return VL_NOREPSERVER;
2887 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODFLAG) {
2889 repsite_exists(VlEntry,
2890 IpAddrToRelAddr(updateentry->
2891 RepsitesTargetServer[i],
2893 updateentry->RepsitesTargetPart[i])) !=
2895 if (updateentry->RepsitesNewFlags[i] < 0
2896 || updateentry->RepsitesNewFlags[i] > MAXSERVERFLAG)
2897 return VL_BADSERVERFLAG;
2898 VlEntry->serverFlags[j] =
2899 updateentry->RepsitesNewFlags[i];
2901 return VL_NOREPSERVER;
2909 /* Check if the specified [server,partition] entry is found in the vldb
2910 * entry's repsite table; it's offset in the table is returned, if it's
2913 repsite_exists(struct nvlentry *VlEntry, int server, int partition)
2917 for (i = 0; VlEntry->serverNumber[i] != BADSERVERID && i < OMAXNSERVERS;
2919 if ((VlEntry->serverNumber[i] == server)
2920 && (VlEntry->serverPartition[i] == partition))
2928 /* Repsite table compression: used when deleting a repsite entry so that
2929 * all active repsite entries are on the top of the table. */
2931 repsite_compress(struct nvlentry *VlEntry, int offset)
2933 int repsite_offset = offset;
2935 VlEntry->serverNumber[repsite_offset] != BADSERVERID
2936 && repsite_offset < OMAXNSERVERS - 1; repsite_offset++) {
2937 VlEntry->serverNumber[repsite_offset] =
2938 VlEntry->serverNumber[repsite_offset + 1];
2939 VlEntry->serverPartition[repsite_offset] =
2940 VlEntry->serverPartition[repsite_offset + 1];
2941 VlEntry->serverFlags[repsite_offset] =
2942 VlEntry->serverFlags[repsite_offset + 1];
2944 VlEntry->serverNumber[repsite_offset] = BADSERVERID;
2948 /* Convert from the internal (compacted) vldb entry to the external
2949 * representation used by the interface. */
2951 vlentry_to_vldbentry(struct nvlentry *VlEntry, struct vldbentry *VldbEntry)
2955 memset(VldbEntry, 0, sizeof(struct vldbentry));
2956 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
2957 for (i = 0; i < OMAXNSERVERS; i++) {
2958 if (VlEntry->serverNumber[i] == BADSERVERID)
2960 if ((HostAddress[j = VlEntry->serverNumber[i]] & 0xff000000) ==
2962 struct extentaddr *exp;
2965 base = (HostAddress[j] >> 16) & 0xff;
2966 index = HostAddress[j] & 0x0000ffff;
2967 exp = &ex_addr[base][index];
2968 /* For now return the first ip address back */
2969 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2970 if (exp->ex_addrs[j]) {
2971 VldbEntry->serverNumber[i] = ntohl(exp->ex_addrs[j]);
2976 VldbEntry->serverNumber[i] =
2977 HostAddress[VlEntry->serverNumber[i]];
2978 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
2979 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
2981 VldbEntry->nServers = i;
2982 for (i = 0; i < MAXTYPES; i++)
2983 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
2984 VldbEntry->cloneId = VlEntry->cloneId;
2985 VldbEntry->flags = VlEntry->flags;
2989 /* Convert from the internal (compacted) vldb entry to the external
2990 * representation used by the interface. */
2992 vlentry_to_nvldbentry(struct nvlentry *VlEntry, struct nvldbentry *VldbEntry)
2996 memset(VldbEntry, 0, sizeof(struct vldbentry));
2997 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
2998 for (i = 0; i < NMAXNSERVERS; i++) {
2999 if (VlEntry->serverNumber[i] == BADSERVERID)
3001 if ((HostAddress[j = VlEntry->serverNumber[i]] & 0xff000000) ==
3003 struct extentaddr *exp;
3006 base = (HostAddress[j] >> 16) & 0xff;
3007 index = HostAddress[j] & 0x0000ffff;
3008 exp = &ex_addr[base][index];
3009 /* For now return the first ip address back */
3010 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
3011 if (exp->ex_addrs[j]) {
3012 VldbEntry->serverNumber[i] = ntohl(exp->ex_addrs[j]);
3017 VldbEntry->serverNumber[i] =
3018 HostAddress[VlEntry->serverNumber[i]];
3019 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
3020 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
3022 VldbEntry->nServers = i;
3023 for (i = 0; i < MAXTYPES; i++)
3024 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
3025 VldbEntry->cloneId = VlEntry->cloneId;
3026 VldbEntry->flags = VlEntry->flags;
3030 vlentry_to_uvldbentry(struct nvlentry *VlEntry, struct uvldbentry *VldbEntry)
3034 memset(VldbEntry, 0, sizeof(struct vldbentry));
3035 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
3036 for (i = 0; i < NMAXNSERVERS; i++) {
3037 if (VlEntry->serverNumber[i] == BADSERVERID)
3039 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
3040 VldbEntry->serverUnique[i] = 0;
3041 if ((HostAddress[j = VlEntry->serverNumber[i]] & 0xff000000) ==
3043 struct extentaddr *exp;
3047 base = (HostAddress[j] >> 16) & 0xff;
3048 index = HostAddress[j] & 0x0000ffff;
3049 exp = &ex_addr[base][index];
3050 tuuid = exp->ex_hostuuid;
3051 afs_ntohuuid(&tuuid);
3052 VldbEntry->serverFlags[i] |= VLSERVER_FLAG_UUID;
3053 VldbEntry->serverNumber[i] = tuuid;
3054 VldbEntry->serverUnique[i] = ntohl(exp->ex_uniquifier);
3056 VldbEntry->serverNumber[i].time_low =
3057 HostAddress[VlEntry->serverNumber[i]];
3059 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
3062 VldbEntry->nServers = i;
3063 for (i = 0; i < MAXTYPES; i++)
3064 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
3065 VldbEntry->cloneId = VlEntry->cloneId;
3066 VldbEntry->flags = VlEntry->flags;
3069 #define LEGALCHARS ".ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
3072 /* Verify that the volname is a valid volume name. */
3074 InvalidVolname(char *volname)
3080 slen = strlen(volname);
3081 if (slen >= VL_MAXNAMELEN)
3083 return (slen != strspn(volname, map));
3087 /* Verify that the given volume type is valid. */
3089 InvalidVoltype(afs_int32 voltype)
3091 if (voltype != RWVOL && voltype != ROVOL && voltype != BACKVOL)
3098 InvalidOperation(afs_int32 voloper)
3100 if (voloper != VLOP_MOVE && voloper != VLOP_RELEASE
3101 && voloper != VLOP_BACKUP && voloper != VLOP_DELETE
3102 && voloper != VLOP_DUMP)
3108 InvalidReleasetype(afs_int32 releasetype)
3110 if ((releasetype & LOCKREL_TIMESTAMP) || (releasetype & LOCKREL_OPCODE)
3111 || (releasetype & LOCKREL_AFSID))
3117 IpAddrToRelAddr(register afs_uint32 ipaddr, struct ubik_trans *atrans)
3120 register afs_int32 code, base, index;
3121 struct extentaddr *exp;
3123 for (i = 0; i <= MAXSERVERID; i++) {
3124 if (HostAddress[i] == ipaddr)
3126 if ((HostAddress[i] & 0xff000000) == 0xff000000) {
3127 base = (HostAddress[i] >> 16) & 0xff;
3128 index = HostAddress[i] & 0x0000ffff;
3129 if (base >= VL_MAX_ADDREXTBLKS) {
3131 ("Internal error: Multihome extent base is too large. Base %d index %d\n",
3133 return -1; /* EINVAL */
3135 if (index >= VL_MHSRV_PERBLK) {
3137 ("Internal error: Multihome extent index is too large. Base %d index %d\n",
3139 return -1; /* EINVAL */
3141 if (!ex_addr[base]) {
3143 ("Internal error: Multihome extent does not exist. Base %d\n",
3145 return -1; /* EINVAL */
3147 exp = &ex_addr[base][index];
3148 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
3149 if (exp->ex_addrs[j] && (ntohl(exp->ex_addrs[j]) == ipaddr)) {
3156 /* allocate the new server a server id pronto */
3158 for (i = 0; i <= MAXSERVERID; i++) {
3159 if (cheader.IpMappedAddr[i] == 0) {
3160 cheader.IpMappedAddr[i] = htonl(ipaddr);
3163 DOFFSET(0, &cheader, &cheader.IpMappedAddr[i]),
3164 (char *)&cheader.IpMappedAddr[i],
3166 HostAddress[i] = ipaddr;
3177 ChangeIPAddr(afs_uint32 ipaddr1, afs_uint32 ipaddr2, struct ubik_trans *atrans)
3181 struct extentaddr *exp = NULL;
3185 afs_int32 blockindex, count;
3187 struct nvlentry tentry;
3190 return VL_CREATEFAIL;
3192 /* Don't let addr change to 256.*.*.* : Causes internal error below */
3193 if ((ipaddr2 & 0xff000000) == 0xff000000)
3194 return (VL_BADSERVER);
3196 /* If we are removing an address, ip1 will be -1 and ip2 will be
3197 * the original address. This prevents an older revision vlserver
3198 * from removing the IP address (won't find server 0xfffffff in
3199 * the VLDB). An older revision vlserver does not have the check
3200 * to see if any volumes exist on the server being removed.
3202 if (ipaddr1 == 0xffffffff) {
3207 for (i = 0; i <= MAXSERVERID; i++) {
3208 if ((HostAddress[i] & 0xff000000) == 0xff000000) {
3209 base = (HostAddress[i] >> 16) & 0xff;
3210 index = HostAddress[i] & 0x0000ffff;
3211 if ((base >= VL_MAX_ADDREXTBLKS) || (index >= VL_MHSRV_PERBLK)) {
3213 ("Internal error: Multihome extent addr is too large. Base %d index %d\n",
3215 return -1; /* EINVAL */
3218 exp = &ex_addr[base][index];
3219 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
3220 if (!exp->ex_addrs[mhidx])
3222 if (ntohl(exp->ex_addrs[mhidx]) == ipaddr1)
3225 if (mhidx < VL_MAXIPADDRS_PERMH) {
3228 } else if (HostAddress[i] == ipaddr1) {
3234 if (i >= MAXSERVERID) {
3235 return VL_NOENT; /* not found */
3238 /* If we are removing a server entry, a volume cannot
3239 * exist on the server. If one does, don't remove the
3240 * server entry: return error "volume entry exists".
3243 for (blockindex = NextEntry(atrans, 0, &tentry, &count); blockindex;
3244 blockindex = NextEntry(atrans, blockindex, &tentry, &count)) {
3245 if (++pollcount > 50) {
3246 #ifndef AFS_PTHREAD_ENV
3251 for (j = 0; j < NMAXNSERVERS; j++) {
3252 if (tentry.serverNumber[j] == BADSERVERID)
3254 if (tentry.serverNumber[j] == i) {
3261 /* Log a message saying we are changing/removing an IP address */
3263 ("The following IP address is being %s:\n",
3264 (ipaddr2 ? "changed" : "removed")));
3265 VLog(0, (" entry %d: ", i));
3268 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
3269 if (!exp->ex_addrs[mhidx])
3273 PADDR(ntohl(exp->ex_addrs[mhidx]));
3285 /* Change the registered uuuid addresses */
3287 memset(&tuuid, 0, sizeof(afsUUID));
3288 afs_htonuuid(&tuuid);
3289 exp->ex_hostuuid = tuuid;
3292 DOFFSET(ntohl(ex_addr[0]->ex_contaddrs[base]),
3293 (char *)ex_addr[base], (char *)exp),
3294 (char *)&tuuid, sizeof(tuuid));
3299 /* Now change the host address entry */
3300 cheader.IpMappedAddr[i] = htonl(ipaddr2);
3302 vlwrite(atrans, DOFFSET(0, &cheader, &cheader.IpMappedAddr[i]),
3304 &cheader.IpMappedAddr[i], sizeof(afs_int32));
3305 HostAddress[i] = ipaddr2;
3312 /* see if the vlserver is back yet */
3314 SVL_ProbeServer(struct rx_call *rxcall)