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 #define ABORT(c) { errorcode = (c); goto abort; }
50 #define END(c) { errorcode = (c); goto end; }
52 #define VLDBALLOCLIMIT 10000
53 #define VLDBALLOCINCR 2048
55 static int put_attributeentry(struct vldbentry **, struct vldbentry **,
56 struct vldbentry **, bulkentries *,
57 struct nvlentry *, afs_int32 *, afs_int32 *);
58 static int put_nattributeentry(struct nvldbentry **, struct nvldbentry **,
59 struct nvldbentry **, nbulkentries *,
60 struct nvlentry *, afs_int32, afs_int32,
61 afs_int32 *, afs_int32 *);
62 static int RemoveEntry(struct ubik_trans *trans, afs_int32 entryptr,
63 struct nvlentry *tentry);
64 static void ReleaseEntry(struct nvlentry *tentry, afs_int32 releasetype);
65 static int check_vldbentry(struct vldbentry *aentry);
66 static int check_nvldbentry(struct nvldbentry *aentry);
67 static int vldbentry_to_vlentry(struct ubik_trans *atrans,
68 struct vldbentry *VldbEntry,
69 struct nvlentry *VlEntry);
70 static int nvldbentry_to_vlentry(struct ubik_trans *atrans,
71 struct nvldbentry *VldbEntry,
72 struct nvlentry *VlEntry);
73 static int get_vldbupdateentry(struct ubik_trans *trans, afs_int32 blockindex,
74 struct VldbUpdateEntry *updateentry,
75 struct nvlentry *VlEntry);
76 static int repsite_exists(struct nvlentry *VlEntry, int server, int partition);
77 static void repsite_compress(struct nvlentry *VlEntry, int offset);
78 static void vlentry_to_vldbentry(struct nvlentry *VlEntry,
79 struct vldbentry *VldbEntry);
80 static void vlentry_to_nvldbentry(struct nvlentry *VlEntry,
81 struct nvldbentry *VldbEntry);
82 static void vlentry_to_uvldbentry(struct nvlentry *VlEntry,
83 struct uvldbentry *VldbEntry);
84 static int InvalidVolname(char *volname);
85 static int InvalidVoltype(afs_int32 voltype);
86 static int InvalidOperation(afs_int32 voloper);
87 static int InvalidReleasetype(afs_int32 releasetype);
88 static int IpAddrToRelAddr(afs_uint32 ipaddr, struct ubik_trans *atrans);
89 static int ChangeIPAddr(afs_uint32 ipaddr1, afs_uint32 ipaddr2,
90 struct ubik_trans *atrans);
92 #define AFS_RXINFO_LEN 128
94 rxinfo(char * str, struct rx_call *rxcall)
97 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(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(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;
186 char rxstr[AFS_RXINFO_LEN];
188 COUNT_REQ(VLCREATEENTRY);
189 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) {
194 /* Do some validity tests on new entry */
195 if ((errorcode = check_vldbentry(newentry))
196 || (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
200 ("OCreate Volume %d %s\n", newentry->volumeId[RWVOL],
201 rxinfo(rxstr, rxcall)));
202 if (EntryIDExists(trans, newentry->volumeId, MAXTYPES, &errorcode)) {
203 /* at least one of the specified IDs already exists; we fail */
204 errorcode = VL_IDEXIST;
206 } else if (errorcode) {
210 /* Is this following check (by volume name) necessary?? */
211 /* If entry already exists, we fail */
212 if (FindByName(trans, newentry->name, &tentry, &errorcode)) {
213 errorcode = VL_NAMEEXIST;
215 } else if (errorcode) {
219 blockindex = AllocBlock(trans, &tentry);
220 if (blockindex == 0) {
221 errorcode = VL_CREATEFAIL;
225 memset(&tentry, 0, sizeof(struct nvlentry));
226 /* Convert to its internal representation; both in host byte order */
227 if ((errorcode = vldbentry_to_vlentry(trans, newentry, &tentry))) {
228 FreeBlock(trans, blockindex);
232 /* Actually insert the entry in vldb */
233 errorcode = ThreadVLentry(trans, blockindex, &tentry);
235 FreeBlock(trans, blockindex);
238 errorcode = ubik_EndTrans(trans);
244 ubik_AbortTrans(trans);
247 osi_auditU(rxcall, VLCreateEntryEvent, errorcode, AUD_STR,
248 (newentry ? newentry->name : NULL), AUD_END);
254 SVL_CreateEntryN(struct rx_call *rxcall, struct nvldbentry *newentry)
256 struct ubik_trans *trans;
257 afs_int32 errorcode, blockindex;
258 struct nvlentry tentry;
259 char rxstr[AFS_RXINFO_LEN];
261 COUNT_REQ(VLCREATEENTRYN);
262 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) {
267 /* Do some validity tests on new entry */
268 if ((errorcode = check_nvldbentry(newentry))
269 || (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
273 ("Create Volume %d %s\n", newentry->volumeId[RWVOL],
274 rxinfo(rxstr, rxcall)));
275 if (EntryIDExists(trans, newentry->volumeId, MAXTYPES, &errorcode)) {
276 /* at least one of the specified IDs already exists; we fail */
277 errorcode = VL_IDEXIST;
279 } else if (errorcode) {
283 /* Is this following check (by volume name) necessary?? */
284 /* If entry already exists, we fail */
285 if (FindByName(trans, newentry->name, &tentry, &errorcode)) {
286 errorcode = VL_NAMEEXIST;
288 } else if (errorcode) {
292 blockindex = AllocBlock(trans, &tentry);
293 if (blockindex == 0) {
294 errorcode = VL_CREATEFAIL;
298 memset(&tentry, 0, sizeof(struct nvlentry));
299 /* Convert to its internal representation; both in host byte order */
300 if ((errorcode = nvldbentry_to_vlentry(trans, newentry, &tentry))) {
301 FreeBlock(trans, blockindex);
305 /* Actually insert the entry in vldb */
306 errorcode = ThreadVLentry(trans, blockindex, &tentry);
308 FreeBlock(trans, blockindex);
311 errorcode = ubik_EndTrans(trans);
317 ubik_AbortTrans(trans);
320 osi_auditU(rxcall, VLCreateEntryEvent, errorcode, AUD_STR,
321 (newentry ? newentry->name : NULL), AUD_END);
327 SVL_ChangeAddr(struct rx_call *rxcall, afs_uint32 ip1, afs_uint32 ip2)
329 struct ubik_trans *trans;
331 char rxstr[AFS_RXINFO_LEN];
333 COUNT_REQ(VLCHANGEADDR);
334 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) {
339 if ((errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
342 VLog(1, ("Change Addr %u -> %u %s\n", ip1, ip2, rxinfo(rxstr, rxcall)));
343 if ((errorcode = ChangeIPAddr(ip1, ip2, trans)))
346 errorcode = ubik_EndTrans(trans);
352 ubik_AbortTrans(trans);
355 osi_auditU(rxcall, VLChangeAddrEvent, errorcode, AUD_LONG, ip1, AUD_LONG,
360 /* Delete a vldb entry given the volume id. */
362 SVL_DeleteEntry(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype)
364 struct ubik_trans *trans;
365 afs_int32 blockindex, errorcode;
366 struct nvlentry tentry;
367 char rxstr[AFS_RXINFO_LEN];
369 COUNT_REQ(VLDELETEENTRY);
370 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
373 if ((voltype != -1) && (InvalidVoltype(voltype)))
376 if ((errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
379 VLog(1, ("Delete Volume %u %s\n", volid, rxinfo(rxstr, rxcall)));
380 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
381 if (blockindex == 0) { /* volid not found */
383 errorcode = VL_NOENT;
387 if (tentry.flags & VLDELETED) { /* Already deleted; return */
388 ABORT(VL_ENTDELETED);
390 if ((errorcode = RemoveEntry(trans, blockindex, &tentry))) {
393 errorcode = (ubik_EndTrans(trans));
398 ubik_AbortTrans(trans);
401 osi_auditU(rxcall, VLDeleteEntryEvent, errorcode, AUD_LONG, volid,
407 /* Get a vldb entry given its volume id; make sure it's not a deleted entry. */
409 GetEntryByID(struct rx_call *rxcall,
412 char *aentry, /* entry data copied here */
416 struct ubik_trans *trans;
417 afs_int32 blockindex, errorcode;
418 struct nvlentry tentry;
419 char rxstr[AFS_RXINFO_LEN];
421 if ((voltype != -1) && (InvalidVoltype(voltype)))
422 return VL_BADVOLTYPE;
423 if ((errorcode = Init_VLdbase(&trans, LOCKREAD, this_op)))
426 VLog(5, ("GetVolumeByID %u (%d) %s\n", volid, new,
427 rxinfo(rxstr, rxcall)));
428 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
429 if (blockindex == 0) { /* entry not found */
431 errorcode = VL_NOENT;
433 ubik_AbortTrans(trans);
436 if (tentry.flags & VLDELETED) { /* Entry is deleted! */
438 ubik_AbortTrans(trans);
439 return VL_ENTDELETED;
441 /* Convert from the internal to external form */
443 vlentry_to_nvldbentry(&tentry, (struct nvldbentry *)aentry);
445 vlentry_to_uvldbentry(&tentry, (struct uvldbentry *)aentry);
447 vlentry_to_vldbentry(&tentry, (struct vldbentry *)aentry);
448 return (ubik_EndTrans(trans));
452 SVL_GetEntryByID(struct rx_call *rxcall,
455 vldbentry *aentry) /* entry data copied here */
457 COUNT_REQ(VLGETENTRYBYID);
458 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 0, this_op));
462 SVL_GetEntryByIDN(struct rx_call *rxcall,
465 nvldbentry *aentry) /* entry data copied here */
467 COUNT_REQ(VLGETENTRYBYIDN);
468 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 1, this_op));
472 SVL_GetEntryByIDU(struct rx_call *rxcall,
475 uvldbentry *aentry) /* entry data copied here */
477 COUNT_REQ(VLGETENTRYBYIDU);
478 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 2, this_op));
483 /* returns true if the id is a decimal integer, in which case we interpret
484 * it as an id. make the cache manager much simpler */
486 NameIsId(char *aname)
489 while ((tc = *aname++)) {
490 if (tc > '9' || tc < '0')
496 /* Get a vldb entry given the volume's name; of course, very similar to
497 * VLGetEntryByID() above. */
499 GetEntryByName(struct rx_call *rxcall,
501 char *aentry, /* entry data copied here */
505 struct ubik_trans *trans;
506 afs_int32 blockindex, errorcode;
507 struct nvlentry tentry;
508 char rxstr[AFS_RXINFO_LEN];
510 if (NameIsId(volname)) {
511 return GetEntryByID(rxcall, atoi(volname), -1, aentry, new, this_op);
513 if (InvalidVolname(volname))
515 if ((errorcode = Init_VLdbase(&trans, LOCKREAD, this_op)))
517 VLog(5, ("GetVolumeByName %s (%d) %s\n", volname, new, rxinfo(rxstr, rxcall)));
518 blockindex = FindByName(trans, volname, &tentry, &errorcode);
519 if (blockindex == 0) { /* entry not found */
521 errorcode = VL_NOENT;
523 ubik_AbortTrans(trans);
526 if (tentry.flags & VLDELETED) { /* Entry is deleted */
528 ubik_AbortTrans(trans);
529 return VL_ENTDELETED;
531 /* Convert to external entry representation */
533 vlentry_to_nvldbentry(&tentry, (struct nvldbentry *)aentry);
535 vlentry_to_uvldbentry(&tentry, (struct uvldbentry *)aentry);
537 vlentry_to_vldbentry(&tentry, (struct vldbentry *)aentry);
538 return (ubik_EndTrans(trans));
542 SVL_GetEntryByNameO(struct rx_call *rxcall,
544 struct vldbentry *aentry) /* entry data copied here */
546 COUNT_REQ(VLGETENTRYBYNAME);
547 return (GetEntryByName(rxcall, volname, (char *)aentry, 0, this_op));
552 SVL_GetEntryByNameN(struct rx_call *rxcall,
554 struct nvldbentry *aentry) /* entry data copied here */
556 COUNT_REQ(VLGETENTRYBYNAMEN);
557 return (GetEntryByName(rxcall, volname, (char *)aentry, 1, this_op));
561 SVL_GetEntryByNameU(struct rx_call *rxcall,
563 struct uvldbentry *aentry) /* entry data copied here */
565 COUNT_REQ(VLGETENTRYBYNAMEU);
566 return (GetEntryByName(rxcall, volname, (char *)aentry, 2, this_op));
571 /* Get the current value of the maximum volume id and bump the volume id counter by Maxvolidbump. */
573 SVL_GetNewVolumeId(struct rx_call *rxcall, afs_uint32 Maxvolidbump,
574 afs_uint32 *newvolumeid)
577 afs_uint32 maxvolumeid;
578 struct ubik_trans *trans;
579 char rxstr[AFS_RXINFO_LEN];
581 COUNT_REQ(VLGETNEWVOLUMEID);
582 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
585 if (Maxvolidbump < 0 || Maxvolidbump > MAXBUMPCOUNT)
586 END(VL_BADVOLIDBUMP);
588 if ((errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
591 *newvolumeid = maxvolumeid = NextUnusedID(trans,
592 ntohl(cheader.vital_header.MaxVolumeId), Maxvolidbump, &errorcode);
597 maxvolumeid += Maxvolidbump;
598 VLog(1, ("GetNewVolid newmax=%u %s\n", maxvolumeid, rxinfo(rxstr, rxcall)));
599 cheader.vital_header.MaxVolumeId = htonl(maxvolumeid);
600 if (write_vital_vlheader(trans)) {
603 errorcode = (ubik_EndTrans(trans));
608 ubik_AbortTrans(trans);
611 osi_auditU(rxcall, VLGetNewVolumeIdEvent, errorcode, AUD_END);
616 /* Simple replace the contents of the vldb entry, volid, with
617 * newentry. No individual checking/updating per field (alike
618 * VLUpdateEntry) is done. */
621 SVL_ReplaceEntry(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype,
622 struct vldbentry *newentry, afs_int32 releasetype)
624 struct ubik_trans *trans;
625 afs_int32 blockindex, errorcode, typeindex;
627 int hashVol[MAXTYPES];
628 struct nvlentry tentry;
629 afs_uint32 checkids[MAXTYPES];
630 char rxstr[AFS_RXINFO_LEN];
632 COUNT_REQ(VLREPLACEENTRY);
633 for (typeindex = 0; typeindex < MAXTYPES; typeindex++)
634 hashVol[typeindex] = 0;
636 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
639 if ((errorcode = check_vldbentry(newentry)))
642 if (voltype != -1 && InvalidVoltype(voltype))
645 if (releasetype && InvalidReleasetype(releasetype))
646 END(VL_BADRELLOCKTYPE);
647 if ((errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
650 VLog(1, ("OReplace Volume %u %s\n", volid, rxinfo(rxstr, rxcall)));
651 /* find vlentry we're changing */
652 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
653 if (blockindex == 0) { /* entry not found */
655 errorcode = VL_NOENT;
659 /* check that we're not trying to change the RW vol ID */
660 if (newentry->volumeId[RWVOL] != tentry.volumeId[RWVOL]) {
664 /* make sure none of the IDs we are changing to are already in use */
665 memset(&checkids, 0, sizeof(checkids));
666 for (typeindex = ROVOL; typeindex < MAXTYPES; typeindex++) {
667 if (tentry.volumeId[typeindex] != newentry->volumeId[typeindex]) {
668 checkids[typeindex] = newentry->volumeId[typeindex];
671 if (EntryIDExists(trans, checkids, MAXTYPES, &errorcode)) {
673 } else if (errorcode) {
677 /* make sure the name we're changing to doesn't already exist */
678 if (strcmp(newentry->name, tentry.name)) {
679 struct nvlentry tmp_entry;
680 if (FindByName(trans, newentry->name, &tmp_entry, &errorcode)) {
682 } else if (errorcode) {
687 /* unhash volid entries if they're disappearing or changing.
688 * Remember if we need to hash in the new value (we don't have to
689 * rehash if volid stays same */
690 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
691 if (tentry.volumeId[typeindex] != newentry->volumeId[typeindex]) {
692 if (tentry.volumeId[typeindex])
694 UnhashVolid(trans, typeindex, blockindex, &tentry))) {
697 /* we must rehash new id if the id is different and the ID is nonzero */
698 hashVol[typeindex] = 1; /* must rehash this guy if he exists */
702 /* Rehash volname if it changes */
703 if (strcmp(newentry->name, tentry.name)) { /* Name changes; redo hashing */
704 if ((errorcode = UnhashVolname(trans, blockindex, &tentry))) {
710 /* after this, tentry is new entry, not old one. vldbentry_to_vlentry
711 * doesn't touch hash chains */
712 if ((errorcode = vldbentry_to_vlentry(trans, newentry, &tentry))) {
716 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
717 if (hashVol[typeindex] && tentry.volumeId[typeindex]) {
718 if ((errorcode = HashVolid(trans, typeindex, blockindex, &tentry))) {
725 HashVolname(trans, blockindex, &tentry);
728 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
729 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
733 END(ubik_EndTrans(trans));
737 ubik_AbortTrans(trans);
740 osi_auditU(rxcall, VLReplaceVLEntryEvent, errorcode, AUD_LONG, volid,
746 SVL_ReplaceEntryN(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype,
747 struct nvldbentry *newentry, afs_int32 releasetype)
749 struct ubik_trans *trans;
750 afs_int32 blockindex, errorcode, typeindex;
752 int hashVol[MAXTYPES];
753 struct nvlentry tentry;
754 char rxstr[AFS_RXINFO_LEN];
756 COUNT_REQ(VLREPLACEENTRYN);
757 for (typeindex = 0; typeindex < MAXTYPES; typeindex++)
758 hashVol[typeindex] = 0;
760 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
763 if ((errorcode = check_nvldbentry(newentry)))
766 if (voltype != -1 && InvalidVoltype(voltype))
769 if (releasetype && InvalidReleasetype(releasetype))
770 END(VL_BADRELLOCKTYPE);
771 if ((errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
774 VLog(1, ("Replace Volume %u %s\n", volid, rxinfo(rxstr, rxcall)));
775 /* find vlentry we're changing */
776 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
777 if (blockindex == 0) { /* entry not found */
779 errorcode = VL_NOENT;
783 /* check that we're not trying to change the RW vol ID */
784 if (newentry->volumeId[RWVOL] != tentry.volumeId[RWVOL]) {
788 /* unhash volid entries if they're disappearing or changing.
789 * Remember if we need to hash in the new value (we don't have to
790 * rehash if volid stays same */
791 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
792 if (tentry.volumeId[typeindex] != newentry->volumeId[typeindex]) {
793 if (tentry.volumeId[typeindex])
795 UnhashVolid(trans, typeindex, blockindex, &tentry))) {
798 /* we must rehash new id if the id is different and the ID is nonzero */
799 hashVol[typeindex] = 1; /* must rehash this guy if he exists */
803 /* Rehash volname if it changes */
804 if (strcmp(newentry->name, tentry.name)) { /* Name changes; redo hashing */
805 if ((errorcode = UnhashVolname(trans, blockindex, &tentry))) {
811 /* after this, tentry is new entry, not old one. vldbentry_to_vlentry
812 * doesn't touch hash chains */
813 if ((errorcode = nvldbentry_to_vlentry(trans, newentry, &tentry))) {
817 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
818 if (hashVol[typeindex] && tentry.volumeId[typeindex]) {
819 if ((errorcode = HashVolid(trans, typeindex, blockindex, &tentry))) {
826 HashVolname(trans, blockindex, &tentry);
829 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
830 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
834 END(ubik_EndTrans(trans));
838 ubik_AbortTrans(trans);
841 osi_auditU(rxcall, VLReplaceVLEntryEvent, errorcode, AUD_LONG, volid,
847 /* Update a vldb entry (accessed thru its volume id). Almost all of the
848 * entry's fields can be modified in a single call by setting the
849 * appropriate bits in the Mask field in VldbUpdateentry. */
850 /* this routine may never have been tested; use replace entry instead
851 * unless you're brave */
853 SVL_UpdateEntry(struct rx_call *rxcall,
856 struct VldbUpdateEntry *updateentry, /* Update entry copied here */
857 afs_int32 releasetype)
859 struct ubik_trans *trans;
860 afs_int32 blockindex, errorcode;
861 struct nvlentry tentry;
862 char rxstr[AFS_RXINFO_LEN];
864 COUNT_REQ(VLUPDATEENTRY);
865 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
867 if ((voltype != -1) && (InvalidVoltype(voltype)))
869 if (releasetype && InvalidReleasetype(releasetype))
870 END(VL_BADRELLOCKTYPE);
871 if ((errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
874 VLog(1, ("Update Volume %u %s\n", volid, rxinfo(rxstr, rxcall)));
875 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
876 if (blockindex == 0) { /* entry not found */
878 errorcode = VL_NOENT;
882 /* Do the actual updating of the entry, tentry. */
884 get_vldbupdateentry(trans, blockindex, updateentry, &tentry))) {
888 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
889 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
892 END(ubik_EndTrans(trans));
896 ubik_AbortTrans(trans);
899 osi_auditU(rxcall, VLUpdateEntryEvent, errorcode, AUD_LONG, volid,
906 SVL_UpdateEntryByName(struct rx_call *rxcall,
908 struct VldbUpdateEntry *updateentry, /* Update entry copied here */
909 afs_int32 releasetype)
911 struct ubik_trans *trans;
912 afs_int32 blockindex, errorcode;
913 struct nvlentry tentry;
915 COUNT_REQ(VLUPDATEENTRYBYNAME);
916 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
918 if (releasetype && InvalidReleasetype(releasetype))
919 END(VL_BADRELLOCKTYPE);
920 if ((errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
923 blockindex = FindByName(trans, volname, &tentry, &errorcode);
924 if (blockindex == 0) { /* entry not found */
926 errorcode = VL_NOENT;
930 /* Do the actual updating of the entry, tentry. */
932 get_vldbupdateentry(trans, blockindex, updateentry, &tentry))) {
936 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
937 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
940 END(ubik_EndTrans(trans));
944 ubik_AbortTrans(trans);
947 osi_auditU(rxcall, VLUpdateEntryEvent, errorcode, AUD_LONG, -1, AUD_END);
952 /* Set a lock to the vldb entry for volid (of type voltype if not -1). */
954 SVL_SetLock(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype,
957 afs_int32 timestamp, blockindex, errorcode;
958 struct ubik_trans *trans;
959 struct nvlentry tentry;
960 char rxstr[AFS_RXINFO_LEN];
962 COUNT_REQ(VLSETLOCK);
963 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
965 if ((voltype != -1) && (InvalidVoltype(voltype)))
967 if (InvalidOperation(voloper))
969 if ((errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
972 VLog(1, ("SetLock Volume %u %s\n", volid, rxinfo(rxstr, rxcall)));
973 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
974 if (blockindex == NULLO) {
976 errorcode = VL_NOENT;
979 if (tentry.flags & VLDELETED) {
980 ABORT(VL_ENTDELETED);
982 timestamp = FT_ApproxTime();
984 /* Check if entry is already locked; note that we unlock any entry
985 * locked more than MAXLOCKTIME seconds */
986 if ((tentry.LockTimestamp)
987 && ((timestamp - tentry.LockTimestamp) < MAXLOCKTIME)) {
988 ABORT(VL_ENTRYLOCKED);
991 /* Consider it an unlocked entry: set current timestamp, caller
992 * and active vol operation */
993 tentry.LockTimestamp = timestamp;
994 tentry.LockAfsId = 0; /* Not implemented yet */
995 if (tentry.flags & VLOP_RELEASE) {
998 tentry.flags &= ~VLOP_ALLOPERS; /* Clear any possible older operation bit */
999 tentry.flags |= voloper;
1001 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
1004 END(ubik_EndTrans(trans));
1008 ubik_AbortTrans(trans);
1011 osi_auditU(rxcall, VLSetLockEvent, errorcode, AUD_LONG, volid, AUD_END);
1016 /* Release an already locked vldb entry. Releasetype determines what
1017 * fields (afsid and/or volume operation) will be cleared along with
1018 * the lock time stamp. */
1021 SVL_ReleaseLock(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype,
1022 afs_int32 releasetype)
1024 afs_int32 blockindex, errorcode;
1025 struct ubik_trans *trans;
1026 struct nvlentry tentry;
1027 char rxstr[AFS_RXINFO_LEN];
1029 COUNT_REQ(VLRELEASELOCK);
1030 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
1032 if ((voltype != -1) && (InvalidVoltype(voltype)))
1034 if (releasetype && InvalidReleasetype(releasetype))
1035 END(VL_BADRELLOCKTYPE);
1036 if ((errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
1039 VLog(1, ("ReleaseLock Volume %u %s\n", volid, rxinfo(rxstr, rxcall)));
1040 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
1041 if (blockindex == NULLO) {
1043 errorcode = VL_NOENT;
1046 if (tentry.flags & VLDELETED) {
1047 ABORT(VL_ENTDELETED);
1050 ReleaseEntry(&tentry, releasetype); /* Unlock the appropriate fields */
1051 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
1054 END(ubik_EndTrans(trans));
1058 ubik_AbortTrans(trans);
1061 osi_auditU(rxcall, VLReleaseLockEvent, errorcode, AUD_LONG, volid,
1067 /* ListEntry returns a single vldb entry, aentry, with offset previous_index;
1068 * the remaining parameters (i.e. next_index) are used so that sequential
1069 * calls to this routine will get the next (all) vldb entries.
1072 SVL_ListEntry(struct rx_call *rxcall, afs_int32 previous_index,
1073 afs_int32 *count, afs_int32 *next_index,
1074 struct vldbentry *aentry)
1077 struct ubik_trans *trans;
1078 struct nvlentry tentry;
1079 char rxstr[AFS_RXINFO_LEN];
1081 COUNT_REQ(VLLISTENTRY);
1082 if ((errorcode = Init_VLdbase(&trans, LOCKREAD, this_op)))
1084 VLog(25, ("OListEntry index=%d %s\n", previous_index,
1085 rxinfo(rxstr, rxcall)));
1086 *next_index = NextEntry(trans, previous_index, &tentry, count);
1088 vlentry_to_vldbentry(&tentry, aentry);
1089 return (ubik_EndTrans(trans));
1092 /* ListEntry returns a single vldb entry, aentry, with offset previous_index;
1093 * the remaining parameters (i.e. next_index) are used so that sequential
1094 * calls to this routine will get the next (all) vldb entries.
1097 SVL_ListEntryN(struct rx_call *rxcall, afs_int32 previous_index,
1098 afs_int32 *count, afs_int32 *next_index,
1099 struct nvldbentry *aentry)
1102 struct ubik_trans *trans;
1103 struct nvlentry tentry;
1104 char rxstr[AFS_RXINFO_LEN];
1106 COUNT_REQ(VLLISTENTRYN);
1107 if ((errorcode = Init_VLdbase(&trans, LOCKREAD, this_op)))
1109 VLog(25, ("ListEntry index=%d %s\n", previous_index, rxinfo(rxstr, rxcall)));
1110 *next_index = NextEntry(trans, previous_index, &tentry, count);
1112 vlentry_to_nvldbentry(&tentry, aentry);
1113 return (ubik_EndTrans(trans));
1117 /* Retrieves in vldbentries all vldb entries that match the specified
1118 * attributes (by server number, partition, volume type, and flag); if volume
1119 * id is specified then the associated list for that entry is returned.
1120 * CAUTION: This could be a very expensive call since in most cases
1121 * sequential search of all vldb entries is performed.
1124 SVL_ListAttributes(struct rx_call *rxcall,
1125 struct VldbListByAttributes *attributes,
1126 afs_int32 *nentries,
1127 bulkentries *vldbentries)
1129 int errorcode, allocCount = 0;
1130 struct ubik_trans *trans;
1131 struct nvlentry tentry;
1132 struct vldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1134 char rxstr[AFS_RXINFO_LEN];
1136 COUNT_REQ(VLLISTATTRIBUTES);
1137 vldbentries->bulkentries_val = 0;
1138 vldbentries->bulkentries_len = *nentries = 0;
1139 if ((errorcode = Init_VLdbase(&trans, LOCKREAD, this_op)))
1141 allocCount = VLDBALLOCCOUNT;
1142 Vldbentry = VldbentryFirst = vldbentries->bulkentries_val =
1143 (vldbentry *) malloc(allocCount * sizeof(vldbentry));
1144 if (Vldbentry == NULL) {
1146 ubik_AbortTrans(trans);
1149 VldbentryLast = VldbentryFirst + allocCount;
1150 /* Handle the attribute by volume id totally separate of the rest
1151 * (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!) */
1152 if (attributes->Mask & VLLIST_VOLUMEID) {
1153 afs_int32 blockindex;
1156 FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1157 if (blockindex == 0) {
1159 errorcode = VL_NOENT;
1161 ubik_AbortTrans(trans);
1162 if (vldbentries->bulkentries_val)
1163 free((char *)vldbentries->bulkentries_val);
1164 vldbentries->bulkentries_val = 0;
1165 vldbentries->bulkentries_len = 0;
1169 put_attributeentry(&Vldbentry, &VldbentryFirst, &VldbentryLast,
1170 vldbentries, &tentry, nentries, &allocCount))) {
1172 ubik_AbortTrans(trans);
1173 if (vldbentries->bulkentries_val)
1174 free((char *)vldbentries->bulkentries_val);
1175 vldbentries->bulkentries_val = 0;
1176 vldbentries->bulkentries_len = 0;
1177 return VL_SIZEEXCEEDED;
1180 afs_int32 nextblockindex = 0, count = 0, k = 0, match = 0;
1181 while ((nextblockindex =
1182 NextEntry(trans, nextblockindex, &tentry, &count))) {
1183 if (++pollcount > 50) {
1184 #ifndef AFS_PTHREAD_ENV
1190 if (attributes->Mask & VLLIST_SERVER) {
1193 IpAddrToRelAddr(attributes->server, NULL)) == -1)
1195 for (k = 0; k < OMAXNSERVERS; k++) {
1196 if (tentry.serverNumber[k] == BADSERVERID)
1198 if (tentry.serverNumber[k] == serverindex) {
1206 if (attributes->Mask & VLLIST_PARTITION) {
1208 if (tentry.serverPartition[k] != attributes->partition)
1211 for (k = 0; k < OMAXNSERVERS; k++) {
1212 if (tentry.serverNumber[k] == BADSERVERID)
1214 if (tentry.serverPartition[k] ==
1215 attributes->partition) {
1225 if (attributes->Mask & VLLIST_FLAG) {
1226 if (!(tentry.flags & attributes->flag))
1230 put_attributeentry(&Vldbentry, &VldbentryFirst,
1231 &VldbentryLast, vldbentries, &tentry,
1232 nentries, &allocCount))) {
1234 ubik_AbortTrans(trans);
1235 if (vldbentries->bulkentries_val)
1236 free((char *)vldbentries->bulkentries_val);
1237 vldbentries->bulkentries_val = 0;
1238 vldbentries->bulkentries_len = 0;
1243 if (vldbentries->bulkentries_len
1244 && (allocCount > vldbentries->bulkentries_len)) {
1246 vldbentries->bulkentries_val =
1247 (vldbentry *) realloc(vldbentries->bulkentries_val,
1248 vldbentries->bulkentries_len *
1250 if (vldbentries->bulkentries_val == NULL) {
1252 ubik_AbortTrans(trans);
1257 ("ListAttrs nentries=%d %s\n", vldbentries->bulkentries_len,
1258 rxinfo(rxstr, rxcall)));
1259 return (ubik_EndTrans(trans));
1263 SVL_ListAttributesN(struct rx_call *rxcall,
1264 struct VldbListByAttributes *attributes,
1265 afs_int32 *nentries,
1266 nbulkentries *vldbentries)
1268 int errorcode, allocCount = 0;
1269 struct ubik_trans *trans;
1270 struct nvlentry tentry;
1271 struct nvldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1273 char rxstr[AFS_RXINFO_LEN];
1275 COUNT_REQ(VLLISTATTRIBUTESN);
1276 vldbentries->nbulkentries_val = 0;
1277 vldbentries->nbulkentries_len = *nentries = 0;
1278 if ((errorcode = Init_VLdbase(&trans, LOCKREAD, this_op)))
1280 allocCount = VLDBALLOCCOUNT;
1281 Vldbentry = VldbentryFirst = vldbentries->nbulkentries_val =
1282 (nvldbentry *) malloc(allocCount * sizeof(nvldbentry));
1283 if (Vldbentry == NULL) {
1285 ubik_AbortTrans(trans);
1288 VldbentryLast = VldbentryFirst + allocCount;
1289 /* Handle the attribute by volume id totally separate of the rest
1290 * (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!) */
1291 if (attributes->Mask & VLLIST_VOLUMEID) {
1292 afs_int32 blockindex;
1295 FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1296 if (blockindex == 0) {
1298 errorcode = VL_NOENT;
1300 ubik_AbortTrans(trans);
1301 if (vldbentries->nbulkentries_val)
1302 free((char *)vldbentries->nbulkentries_val);
1303 vldbentries->nbulkentries_val = 0;
1304 vldbentries->nbulkentries_len = 0;
1308 put_nattributeentry(&Vldbentry, &VldbentryFirst, &VldbentryLast,
1309 vldbentries, &tentry, 0, 0, nentries,
1312 ubik_AbortTrans(trans);
1313 if (vldbentries->nbulkentries_val)
1314 free((char *)vldbentries->nbulkentries_val);
1315 vldbentries->nbulkentries_val = 0;
1316 vldbentries->nbulkentries_len = 0;
1317 return VL_SIZEEXCEEDED;
1320 afs_int32 nextblockindex = 0, count = 0, k = 0, match = 0;
1321 while ((nextblockindex =
1322 NextEntry(trans, nextblockindex, &tentry, &count))) {
1323 if (++pollcount > 50) {
1324 #ifndef AFS_PTHREAD_ENV
1331 if (attributes->Mask & VLLIST_SERVER) {
1334 IpAddrToRelAddr(attributes->server, NULL)) == -1)
1336 for (k = 0; k < NMAXNSERVERS; k++) {
1337 if (tentry.serverNumber[k] == BADSERVERID)
1339 if (tentry.serverNumber[k] == serverindex) {
1347 if (attributes->Mask & VLLIST_PARTITION) {
1349 if (tentry.serverPartition[k] != attributes->partition)
1352 for (k = 0; k < NMAXNSERVERS; k++) {
1353 if (tentry.serverNumber[k] == BADSERVERID)
1355 if (tentry.serverPartition[k] ==
1356 attributes->partition) {
1366 if (attributes->Mask & VLLIST_FLAG) {
1367 if (!(tentry.flags & attributes->flag))
1371 put_nattributeentry(&Vldbentry, &VldbentryFirst,
1372 &VldbentryLast, vldbentries, &tentry, 0,
1373 0, nentries, &allocCount))) {
1375 ubik_AbortTrans(trans);
1376 if (vldbentries->nbulkentries_val)
1377 free((char *)vldbentries->nbulkentries_val);
1378 vldbentries->nbulkentries_val = 0;
1379 vldbentries->nbulkentries_len = 0;
1384 if (vldbentries->nbulkentries_len
1385 && (allocCount > vldbentries->nbulkentries_len)) {
1387 vldbentries->nbulkentries_val =
1388 (nvldbentry *) realloc(vldbentries->nbulkentries_val,
1389 vldbentries->nbulkentries_len *
1390 sizeof(nvldbentry));
1391 if (vldbentries->nbulkentries_val == NULL) {
1393 ubik_AbortTrans(trans);
1398 ("NListAttrs nentries=%d %s\n", vldbentries->nbulkentries_len,
1399 rxinfo(rxstr, rxcall)));
1400 return (ubik_EndTrans(trans));
1405 SVL_ListAttributesN2(struct rx_call *rxcall,
1406 struct VldbListByAttributes *attributes,
1407 char *name, /* Wildcarded volume name */
1408 afs_int32 startindex,
1409 afs_int32 *nentries,
1410 nbulkentries *vldbentries,
1411 afs_int32 *nextstartindex)
1413 int errorcode = 0, maxCount = VLDBALLOCCOUNT;
1414 struct ubik_trans *trans;
1415 struct nvlentry tentry;
1416 struct nvldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1417 afs_int32 blockindex = 0, count = 0, k, match;
1418 afs_int32 matchindex = 0;
1419 int serverindex = -1; /* no server found */
1420 int findserver = 0, findpartition = 0, findflag = 0, findname = 0;
1422 int namematchRWBK, namematchRO, thismatch;
1424 char volumename[VL_MAXNAMELEN+2]; /* regex anchors */
1425 char rxstr[AFS_RXINFO_LEN];
1426 #ifdef HAVE_POSIX_REGEX
1428 int need_regfree = 0;
1433 COUNT_REQ(VLLISTATTRIBUTESN2);
1434 vldbentries->nbulkentries_val = 0;
1435 vldbentries->nbulkentries_len = 0;
1437 *nextstartindex = -1;
1439 errorcode = Init_VLdbase(&trans, LOCKREAD, this_op);
1443 Vldbentry = VldbentryFirst = vldbentries->nbulkentries_val =
1444 (nvldbentry *) malloc(maxCount * sizeof(nvldbentry));
1445 if (Vldbentry == NULL) {
1447 ubik_AbortTrans(trans);
1451 VldbentryLast = VldbentryFirst + maxCount;
1453 /* Handle the attribute by volume id totally separate of the rest
1454 * (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!)
1456 if (attributes->Mask & VLLIST_VOLUMEID) {
1458 FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1459 if (blockindex == 0) {
1461 errorcode = VL_NOENT;
1464 put_nattributeentry(&Vldbentry, &VldbentryFirst,
1465 &VldbentryLast, vldbentries, &tentry, 0,
1466 0, nentries, &maxCount);
1472 /* Search each entry in the database and return all entries
1473 * that match the request. It checks volumename (with
1474 * wildcarding), entry flags, server, and partition.
1477 /* Get the server index for matching server address */
1478 if (attributes->Mask & VLLIST_SERVER) {
1480 IpAddrToRelAddr(attributes->server, NULL);
1481 if (serverindex == -1)
1485 findpartition = ((attributes->Mask & VLLIST_PARTITION) ? 1 : 0);
1486 findflag = ((attributes->Mask & VLLIST_FLAG) ? 1 : 0);
1487 if (name && (strcmp(name, ".*") != 0) && (strcmp(name, "") != 0)) {
1488 sprintf(volumename, "^%s$", name);
1489 #ifdef HAVE_POSIX_REGEX
1490 if (regcomp(&re, volumename, REG_NOSUB) != 0) {
1491 errorcode = VL_BADNAME;
1496 t = (char *)re_comp(volumename);
1498 errorcode = VL_BADNAME;
1505 /* Read each entry and see if it is the one we want */
1506 blockindex = startindex;
1507 while ((blockindex = NextEntry(trans, blockindex, &tentry, &count))) {
1508 if (++pollcount > 50) {
1509 #ifndef AFS_PTHREAD_ENV
1515 /* Step through each server index searching for a match.
1516 * Match to an existing RW, BK, or RO volume name (preference
1517 * is in this order). Remember which index we matched against.
1519 namematchRWBK = namematchRO = 0; /* 0->notTried; 1->match; 2->noMatch */
1523 && (tentry.serverNumber[k] != BADSERVERID)); k++) {
1524 thismatch = 0; /* does this index match */
1526 /* Match against the RW or BK volume name. Remember
1527 * results in namematchRWBK. Prefer RW over BK.
1529 if (tentry.serverFlags[k] & VLSF_RWVOL) {
1530 /* Does the name match the RW name */
1531 if (tentry.flags & VLF_RWEXISTS) {
1533 sprintf(volumename, "%s", tentry.name);
1534 #ifdef HAVE_POSIX_REGEX
1535 if (regexec(&re, volumename, 0, NULL, 0) == 0) {
1536 thismatch = VLSF_RWVOL;
1539 if (re_exec(volumename)) {
1540 thismatch = VLSF_RWVOL;
1544 thismatch = VLSF_RWVOL;
1548 /* Does the name match the BK name */
1549 if (!thismatch && (tentry.flags & VLF_BACKEXISTS)) {
1551 sprintf(volumename, "%s.backup", tentry.name);
1552 #ifdef HAVE_POSIX_REGEX
1553 if (regexec(&re, volumename, 0, NULL, 0) == 0) {
1554 thismatch = VLSF_BACKVOL;
1557 if (re_exec(volumename)) {
1558 thismatch = VLSF_BACKVOL;
1562 thismatch = VLSF_BACKVOL;
1566 namematchRWBK = (thismatch ? 1 : 2);
1569 /* Match with the RO volume name. Compare once and
1570 * remember results in namematchRO. Note that this will
1571 * pick up entries marked NEWREPSITEs and DONTUSE.
1574 if (tentry.flags & VLF_ROEXISTS) {
1578 ((namematchRO == 1) ? VLSF_ROVOL : 0);
1580 sprintf(volumename, "%s.readonly",
1582 #ifdef HAVE_POSIX_REGEX
1583 if (regexec(&re, volumename, 0, NULL, 0) == 0) {
1584 thismatch = VLSF_ROVOL;
1587 if (re_exec(volumename))
1588 thismatch = VLSF_ROVOL;
1592 thismatch = VLSF_ROVOL;
1595 namematchRO = (thismatch ? 1 : 2);
1598 /* Is there a server match */
1599 if (thismatch && findserver
1600 && (tentry.serverNumber[k] != serverindex))
1603 /* Is there a partition match */
1604 if (thismatch && findpartition
1605 && (tentry.serverPartition[k] != attributes->partition))
1608 /* Is there a flag match */
1609 if (thismatch && findflag
1610 && !(tentry.flags & attributes->flag))
1613 /* We found a match. Remember the index, and type */
1617 matchtype = thismatch;
1620 /* Since we prefer RW and BK volume matches over RO matches,
1621 * if we have already checked the RWBK name, then we already
1622 * found the best match and so end the search.
1624 * If we tried matching against the RW, BK, and RO volume names
1625 * and both failed, then we end the search (none will match).
1627 if ((match && namematchRWBK)
1628 || ((namematchRWBK == 2) && (namematchRO == 2)))
1632 /* Passed all the tests. Take it */
1635 put_nattributeentry(&Vldbentry, &VldbentryFirst,
1636 &VldbentryLast, vldbentries, &tentry,
1637 matchtype, matchindex, nentries,
1642 if (*nentries >= maxCount)
1643 break; /* collected the max */
1646 *nextstartindex = (blockindex ? blockindex : -1);
1650 #ifdef HAVE_POSIX_REGEX
1657 ubik_AbortTrans(trans);
1658 if (vldbentries->nbulkentries_val)
1659 free((char *)vldbentries->nbulkentries_val);
1660 vldbentries->nbulkentries_val = 0;
1661 vldbentries->nbulkentries_len = 0;
1662 *nextstartindex = -1;
1666 ("N2ListAttrs nentries=%d %s\n", vldbentries->nbulkentries_len,
1667 rxinfo(rxstr, rxcall)));
1668 return (ubik_EndTrans(trans));
1673 /* Retrieves in vldbentries all vldb entries that match the specified
1674 * attributes (by server number, partition, volume type, and flag); if
1675 * volume id is specified then the associated list for that entry is
1676 * returned. CAUTION: This could be a very expensive call since in most
1677 * cases sequential search of all vldb entries is performed.
1680 SVL_LinkedList(struct rx_call *rxcall,
1681 struct VldbListByAttributes *attributes,
1682 afs_int32 *nentries,
1683 vldb_list *vldbentries)
1686 struct ubik_trans *trans;
1687 struct nvlentry tentry;
1688 vldblist vllist, *vllistptr;
1689 afs_int32 blockindex, count, match;
1694 COUNT_REQ(VLLINKEDLIST);
1695 if ((errorcode = Init_VLdbase(&trans, LOCKREAD, this_op)))
1699 vldbentries->node = NULL;
1700 vllistptr = &vldbentries->node;
1702 /* List by volumeid */
1703 if (attributes->Mask & VLLIST_VOLUMEID) {
1705 FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1708 ubik_AbortTrans(trans);
1709 return (errorcode ? errorcode : VL_NOENT);
1712 vllist = (single_vldbentry *) malloc(sizeof(single_vldbentry));
1713 if (vllist == NULL) {
1715 ubik_AbortTrans(trans);
1718 vlentry_to_vldbentry(&tentry, &vllist->VldbEntry);
1719 vllist->next_vldb = NULL;
1721 *vllistptr = vllist; /* Thread onto list */
1722 vllistptr = &vllist->next_vldb;
1726 /* Search by server, partition, and flags */
1728 for (blockindex = NextEntry(trans, 0, &tentry, &count); blockindex;
1729 blockindex = NextEntry(trans, blockindex, &tentry, &count)) {
1732 if (++pollcount > 50) {
1733 #ifndef AFS_PTHREAD_ENV
1739 /* Does this volume exist on the desired server */
1740 if (attributes->Mask & VLLIST_SERVER) {
1742 IpAddrToRelAddr(attributes->server, NULL);
1743 if (serverindex == -1)
1745 for (k = 0; k < OMAXNSERVERS; k++) {
1746 if (tentry.serverNumber[k] == BADSERVERID)
1748 if (tentry.serverNumber[k] == serverindex) {
1757 /* Does this volume exist on the desired partition */
1758 if (attributes->Mask & VLLIST_PARTITION) {
1760 if (tentry.serverPartition[k] != attributes->partition)
1763 for (k = 0; k < OMAXNSERVERS; k++) {
1764 if (tentry.serverNumber[k] == BADSERVERID)
1766 if (tentry.serverPartition[k] ==
1767 attributes->partition) {
1777 /* Does this volume have the desired flags */
1778 if (attributes->Mask & VLLIST_FLAG) {
1779 if (!(tentry.flags & attributes->flag))
1783 vllist = (single_vldbentry *) malloc(sizeof(single_vldbentry));
1784 if (vllist == NULL) {
1786 ubik_AbortTrans(trans);
1789 vlentry_to_vldbentry(&tentry, &vllist->VldbEntry);
1790 vllist->next_vldb = NULL;
1792 *vllistptr = vllist; /* Thread onto list */
1793 vllistptr = &vllist->next_vldb;
1795 if (smallMem && (*nentries >= VLDBALLOCCOUNT)) {
1797 ubik_AbortTrans(trans);
1798 return VL_SIZEEXCEEDED;
1803 return (ubik_EndTrans(trans));
1807 SVL_LinkedListN(struct rx_call *rxcall,
1808 struct VldbListByAttributes *attributes,
1809 afs_int32 *nentries,
1810 nvldb_list *vldbentries)
1813 struct ubik_trans *trans;
1814 struct nvlentry tentry;
1815 nvldblist vllist, *vllistptr;
1816 afs_int32 blockindex, count, match;
1821 COUNT_REQ(VLLINKEDLISTN);
1822 if ((errorcode = Init_VLdbase(&trans, LOCKREAD, this_op)))
1826 vldbentries->node = NULL;
1827 vllistptr = &vldbentries->node;
1829 /* List by volumeid */
1830 if (attributes->Mask & VLLIST_VOLUMEID) {
1832 FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1835 ubik_AbortTrans(trans);
1836 return (errorcode ? errorcode : VL_NOENT);
1839 vllist = (single_nvldbentry *) malloc(sizeof(single_nvldbentry));
1840 if (vllist == NULL) {
1842 ubik_AbortTrans(trans);
1845 vlentry_to_nvldbentry(&tentry, &vllist->VldbEntry);
1846 vllist->next_vldb = NULL;
1848 *vllistptr = vllist; /* Thread onto list */
1849 vllistptr = &vllist->next_vldb;
1853 /* Search by server, partition, and flags */
1855 for (blockindex = NextEntry(trans, 0, &tentry, &count); blockindex;
1856 blockindex = NextEntry(trans, blockindex, &tentry, &count)) {
1859 if (++pollcount > 50) {
1860 #ifndef AFS_PTHREAD_ENV
1866 /* Does this volume exist on the desired server */
1867 if (attributes->Mask & VLLIST_SERVER) {
1869 IpAddrToRelAddr(attributes->server, NULL);
1870 if (serverindex == -1)
1872 for (k = 0; k < NMAXNSERVERS; k++) {
1873 if (tentry.serverNumber[k] == BADSERVERID)
1875 if (tentry.serverNumber[k] == serverindex) {
1884 /* Does this volume exist on the desired partition */
1885 if (attributes->Mask & VLLIST_PARTITION) {
1887 if (tentry.serverPartition[k] != attributes->partition)
1890 for (k = 0; k < NMAXNSERVERS; k++) {
1891 if (tentry.serverNumber[k] == BADSERVERID)
1893 if (tentry.serverPartition[k] ==
1894 attributes->partition) {
1904 /* Does this volume have the desired flags */
1905 if (attributes->Mask & VLLIST_FLAG) {
1906 if (!(tentry.flags & attributes->flag))
1910 vllist = (single_nvldbentry *) malloc(sizeof(single_nvldbentry));
1911 if (vllist == NULL) {
1913 ubik_AbortTrans(trans);
1916 vlentry_to_nvldbentry(&tentry, &vllist->VldbEntry);
1917 vllist->next_vldb = NULL;
1919 *vllistptr = vllist; /* Thread onto list */
1920 vllistptr = &vllist->next_vldb;
1922 if (smallMem && (*nentries >= VLDBALLOCCOUNT)) {
1924 ubik_AbortTrans(trans);
1925 return VL_SIZEEXCEEDED;
1930 return (ubik_EndTrans(trans));
1933 /* Get back vldb header statistics (allocs, frees, maxvolumeid,
1934 * totalentries, etc) and dynamic statistics (number of requests and/or
1935 * aborts per remote procedure call, etc)
1938 SVL_GetStats(struct rx_call *rxcall,
1940 vital_vlheader *vital_header)
1942 afs_int32 errorcode;
1943 struct ubik_trans *trans;
1944 char rxstr[AFS_RXINFO_LEN];
1946 COUNT_REQ(VLGETSTATS);
1948 /* Allow users to get statistics freely */
1949 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) /* Must be in 'UserList' to use */
1952 if ((errorcode = Init_VLdbase(&trans, LOCKREAD, this_op)))
1954 VLog(5, ("GetStats %s\n", rxinfo(rxstr, rxcall)));
1955 memcpy((char *)vital_header, (char *)&cheader.vital_header,
1956 sizeof(vital_vlheader));
1957 memcpy((char *)stats, (char *)&dynamic_statistics, sizeof(vldstats));
1958 return (ubik_EndTrans(trans));
1961 /* Get the list of file server addresses from the VLDB. Currently it's pretty
1962 * easy to do. In the future, it might require a little bit of grunging
1963 * through the VLDB, but that's life.
1966 SVL_GetAddrs(struct rx_call *rxcall,
1969 struct VLCallBack *spare3,
1970 afs_int32 *nentries,
1973 afs_int32 errorcode;
1974 struct ubik_trans *trans;
1978 COUNT_REQ(VLGETADDRS);
1979 addrsp->bulkaddrs_len = *nentries = 0;
1980 addrsp->bulkaddrs_val = 0;
1981 memset(spare3, 0, sizeof(struct VLCallBack));
1983 if ((errorcode = Init_VLdbase(&trans, LOCKREAD, this_op)))
1986 VLog(5, ("GetAddrs\n"));
1987 addrsp->bulkaddrs_val = taddrp =
1988 (afs_uint32 *) malloc(sizeof(afs_int32) * (MAXSERVERID + 1));
1989 nservers = *nentries = addrsp->bulkaddrs_len = 0;
1993 ubik_AbortTrans(trans);
1997 for (i = 0; i <= MAXSERVERID; i++) {
1998 if ((*taddrp = ntohl(cheader.IpMappedAddr[i]))) {
2004 addrsp->bulkaddrs_len = *nentries = nservers;
2005 return (ubik_EndTrans(trans));
2008 #define PADDR(addr) VLog(0,("%d.%d.%d.%d", (addr>>24)&0xff, (addr>>16)&0xff, (addr>>8) &0xff, addr&0xff));
2011 SVL_RegisterAddrs(struct rx_call *rxcall, afsUUID *uuidp, afs_int32 spare1,
2015 struct ubik_trans *trans;
2016 int cnt, h, i, j, k, m, base, index;
2017 struct extentaddr *exp = 0, *tex;
2019 afs_uint32 addrs[VL_MAXIPADDRS_PERMH];
2021 int count, willChangeEntry, foundUuidEntry, willReplaceCnt;
2022 int WillReplaceEntry, WillChange[MAXSERVERID + 1];
2024 int ReplaceEntry = 0;
2027 COUNT_REQ(VLREGADDR);
2028 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
2030 if ((code = Init_VLdbase(&trans, LOCKWRITE, this_op)))
2033 /* Eliminate duplicates from IP address list */
2034 for (k = 0, cnt = 0; k < addrsp->bulkaddrs_len; k++) {
2035 if (addrsp->bulkaddrs_val[k] == 0)
2037 for (m = 0; m < cnt; m++) {
2038 if (addrs[m] == addrsp->bulkaddrs_val[k])
2042 if (m == VL_MAXIPADDRS_PERMH) {
2044 ("Number of addresses exceeds %d. Cannot register IP addr 0x%x in VLDB\n",
2045 VL_MAXIPADDRS_PERMH, addrsp->bulkaddrs_val[k]));
2047 addrs[m] = addrsp->bulkaddrs_val[k];
2053 ubik_AbortTrans(trans);
2054 return VL_INDEXERANGE;
2060 /* For each server registered within the VLDB */
2061 for (srvidx = 0; srvidx <= MAXSERVERID; srvidx++) {
2062 willChangeEntry = 0;
2063 WillReplaceEntry = 1;
2064 if ((HostAddress[srvidx] & 0xff000000) == 0xff000000) {
2065 /* The server is registered as a multihomed */
2066 base = (HostAddress[srvidx] >> 16) & 0xff;
2067 index = HostAddress[srvidx] & 0x0000ffff;
2068 if (base >= VL_MAX_ADDREXTBLKS) {
2070 ("Internal error: Multihome extent base is too large. Base %d index %d\n",
2074 if (index >= VL_MHSRV_PERBLK) {
2076 ("Internal error: Multihome extent index is too large. Base %d index %d\n",
2080 if (!ex_addr[base]) {
2082 ("Internal error: Multihome extent does not exist. Base %d\n",
2087 /* See if the addresses to register will change this server entry */
2088 exp = &ex_addr[base][index];
2089 tuuid = exp->ex_hostuuid;
2090 afs_ntohuuid(&tuuid);
2091 if (afs_uuid_equal(uuidp, &tuuid)) {
2095 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2096 if (!exp->ex_addrs[mhidx])
2098 for (k = 0; k < cnt; k++) {
2099 if (ntohl(exp->ex_addrs[mhidx]) == addrs[k]) {
2100 willChangeEntry = 1;
2101 WillChange[count] = srvidx;
2106 WillReplaceEntry = 0;
2110 /* The server is not registered as a multihomed.
2111 * See if the addresses to register will replace this server entry.
2113 for (k = 0; k < cnt; k++) {
2114 if (HostAddress[srvidx] == addrs[k]) {
2115 willChangeEntry = 1;
2116 WillChange[count] = srvidx;
2117 WillReplaceEntry = 1;
2122 if (willChangeEntry) {
2123 if (WillReplaceEntry) {
2125 ReplaceEntry = srvidx;
2131 /* If we found the uuid in the VLDB and if we are replacing another
2132 * entire entry, then complain and fail. Also, if we did not find
2133 * the uuid in the VLDB and the IP addresses being registered was
2134 * found in more than one other entry, then we don't know which one
2135 * to replace and will complain and fail.
2137 if ((foundUuidEntry && (willReplaceCnt > 0))
2138 || (!foundUuidEntry && (count > 1))) {
2140 ("The following fileserver is being registered in the VLDB:\n"));
2142 for (k = 0; k < cnt; k++) {
2149 if (foundUuidEntry) {
2151 (" It would have replaced the existing VLDB server entry:\n"));
2152 VLog(0, (" entry %d: [", FoundUuid));
2153 base = (HostAddress[FoundUuid] >> 16) & 0xff;
2154 index = HostAddress[FoundUuid] & 0x0000ffff;
2155 exp = &ex_addr[base][index];
2156 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2157 if (!exp->ex_addrs[mhidx])
2161 PADDR(ntohl(exp->ex_addrs[mhidx]));
2167 VLog(0, (" Yet another VLDB server entry exists:\n"));
2169 VLog(0, (" Yet other VLDB server entries exist:\n"));
2170 for (j = 0; j < count; j++) {
2171 srvidx = WillChange[j];
2172 VLog(0, (" entry %d: ", srvidx));
2173 if ((HostAddress[srvidx] & 0xff000000) == 0xff000000) {
2175 base = (HostAddress[srvidx] >> 16) & 0xff;
2176 index = HostAddress[srvidx] & 0x0000ffff;
2177 exp = &ex_addr[base][index];
2178 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2179 if (!exp->ex_addrs[mhidx])
2183 PADDR(ntohl(exp->ex_addrs[mhidx]));
2187 PADDR(HostAddress[srvidx]);
2193 VLog(0, (" You must 'vos changeaddr' this other server entry\n"));
2196 (" You must 'vos changeaddr' these other server entries\n"));
2199 (" and/or remove the sysid file from the registering fileserver\n"));
2200 VLog(0, (" before the fileserver can be registered in the VLDB.\n"));
2202 ubik_AbortTrans(trans);
2203 return VL_MULTIPADDR;
2206 /* Passed the checks. Now find and update the existing mh entry, or create
2209 if (foundUuidEntry) {
2210 /* Found the entry with same uuid. See if we need to change it */
2213 fbase = (HostAddress[FoundUuid] >> 16) & 0xff;
2214 index = HostAddress[FoundUuid] & 0x0000ffff;
2215 exp = &ex_addr[fbase][index];
2217 /* Determine if the entry has changed */
2218 for (k = 0; ((k < cnt) && !change); k++) {
2219 if (ntohl(exp->ex_addrs[k]) != addrs[k])
2222 for (; ((k < VL_MAXIPADDRS_PERMH) && !change); k++) {
2223 if (exp->ex_addrs[k] != 0)
2227 return (ubik_EndTrans(trans));
2231 VLog(0, ("The following fileserver is being registered in the VLDB:\n"));
2233 for (k = 0; k < cnt; k++) {
2240 if (foundUuidEntry) {
2242 (" It will replace the following existing entry in the VLDB (same uuid):\n"));
2243 VLog(0, (" entry %d: [", FoundUuid));
2244 for (k = 0; k < VL_MAXIPADDRS_PERMH; k++) {
2245 if (exp->ex_addrs[k] == 0)
2249 PADDR(ntohl(exp->ex_addrs[k]));
2252 } else if (willReplaceCnt || (count == 1)) {
2253 /* If we are not replacing an entry and there is only one entry to change,
2254 * then we will replace that entry.
2256 if (!willReplaceCnt) {
2257 ReplaceEntry = WillChange[0];
2261 /* Have an entry that needs to be replaced */
2262 if ((HostAddress[ReplaceEntry] & 0xff000000) == 0xff000000) {
2263 fbase = (HostAddress[ReplaceEntry] >> 16) & 0xff;
2264 index = HostAddress[ReplaceEntry] & 0x0000ffff;
2265 exp = &ex_addr[fbase][index];
2268 (" It will replace the following existing entry in the VLDB (new uuid):\n"));
2269 VLog(0, (" entry %d: [", ReplaceEntry));
2270 for (k = 0; k < VL_MAXIPADDRS_PERMH; k++) {
2271 if (exp->ex_addrs[k] == 0)
2275 PADDR(ntohl(exp->ex_addrs[k]));
2279 /* Not a mh entry. So we have to create a new mh entry and
2280 * put it on the ReplaceEntry slot of the HostAddress array.
2282 VLog(0, (" It will replace existing entry %d, ", ReplaceEntry));
2283 PADDR(HostAddress[ReplaceEntry]);
2284 VLog(0,(", in the VLDB (new uuid):\n"));
2287 FindExtentBlock(trans, uuidp, 1, ReplaceEntry, &exp, &fbase);
2289 ubik_AbortTrans(trans);
2290 return (code ? code : VL_IO);
2294 /* There is no entry for this server, must create a new mh entry as
2295 * well as use a new slot of the HostAddress array.
2297 VLog(0, (" It will create a new entry in the VLDB.\n"));
2298 code = FindExtentBlock(trans, uuidp, 1, -1, &exp, &fbase);
2300 ubik_AbortTrans(trans);
2301 return (code ? code : VL_IO);
2305 /* Now we have a mh entry to fill in. Update the uuid, bump the
2306 * uniquifier, and fill in its IP addresses.
2309 afs_htonuuid(&tuuid);
2310 exp->ex_hostuuid = tuuid;
2311 exp->ex_uniquifier = htonl(ntohl(exp->ex_uniquifier) + 1);
2312 for (k = 0; k < cnt; k++) {
2313 exp->ex_addrs[k] = htonl(addrs[k]);
2315 for (; k < VL_MAXIPADDRS_PERMH; k++) {
2316 exp->ex_addrs[k] = 0;
2319 /* Write the new mh entry out */
2322 DOFFSET(ntohl(ex_addr[0]->ex_contaddrs[fbase]),
2323 (char *)ex_addr[fbase], (char *)exp), (char *)exp,
2325 ubik_AbortTrans(trans);
2329 /* Remove any common addresses from other mh entres. We know these entries
2330 * are being changed and not replaced so they are mh entries.
2333 for (i = 0; i < count; i++) {
2336 /* Skip the entry we replaced */
2337 if (willReplaceCnt && (WillChange[i] == ReplaceEntry))
2340 base = (HostAddress[WillChange[i]] >> 16) & 0xff;
2341 index = HostAddress[WillChange[i]] & 0x0000ffff;
2342 tex = &ex_addr[fbase][index];
2346 (" The following existing entries in the VLDB will be updated:\n"));
2348 VLog(0, (" entry %d: [", WillChange[i]));
2349 for (h = j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2350 if (tex->ex_addrs[j]) {
2353 PADDR(ntohl(tex->ex_addrs[j]));
2356 for (k = 0; k < cnt; k++) {
2357 if (ntohl(tex->ex_addrs[j]) == addrs[k])
2361 /* Not found, so we keep it */
2362 tex->ex_addrs[h] = tex->ex_addrs[j];
2366 for (j = h; j < VL_MAXIPADDRS_PERMH; j++) {
2367 tex->ex_addrs[j] = 0; /* zero rest of mh entry */
2371 /* Write out the modified mh entry */
2372 tex->ex_uniquifier = htonl(ntohl(tex->ex_uniquifier) + 1);
2374 DOFFSET(ntohl(ex_addr[0]->ex_contaddrs[base]),
2375 (char *)ex_addr[base], (char *)tex);
2376 if (vlwrite(trans, doff, (char *)tex, sizeof(*tex))) {
2377 ubik_AbortTrans(trans);
2382 return (ubik_EndTrans(trans));
2386 SVL_GetAddrsU(struct rx_call *rxcall,
2387 struct ListAddrByAttributes *attributes,
2389 afs_int32 *uniquifier,
2390 afs_int32 *nentries,
2393 afs_int32 errorcode, index = -1, offset;
2394 struct ubik_trans *trans;
2395 int nservers, i, j, base = 0;
2396 struct extentaddr *exp = 0;
2398 afs_uint32 *taddrp, taddr;
2399 char rxstr[AFS_RXINFO_LEN];
2401 COUNT_REQ(VLGETADDRSU);
2402 addrsp->bulkaddrs_len = *nentries = 0;
2403 addrsp->bulkaddrs_val = 0;
2404 VLog(5, ("GetAddrsU %s\n", rxinfo(rxstr, rxcall)));
2405 if ((errorcode = Init_VLdbase(&trans, LOCKREAD, this_op)))
2408 if (attributes->Mask & VLADDR_IPADDR) {
2409 if (attributes->Mask & (VLADDR_INDEX | VLADDR_UUID)) {
2410 ubik_AbortTrans(trans);
2413 for (base = 0; base < VL_MAX_ADDREXTBLKS; base++) {
2416 for (i = 1; i < VL_MHSRV_PERBLK; i++) {
2417 exp = &ex_addr[base][i];
2418 tuuid = exp->ex_hostuuid;
2419 afs_ntohuuid(&tuuid);
2420 if (afs_uuid_is_nil(&tuuid))
2422 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2423 if (exp->ex_addrs[j]
2424 && (ntohl(exp->ex_addrs[j]) == attributes->ipaddr)) {
2428 if (j < VL_MAXIPADDRS_PERMH)
2431 if (i < VL_MHSRV_PERBLK)
2434 if (base >= VL_MAX_ADDREXTBLKS) {
2435 ubik_AbortTrans(trans);
2438 } else if (attributes->Mask & VLADDR_INDEX) {
2439 if (attributes->Mask & (VLADDR_IPADDR | VLADDR_UUID)) {
2440 ubik_AbortTrans(trans);
2443 index = attributes->index;
2444 if (index < 1 || index >= (VL_MAX_ADDREXTBLKS * VL_MHSRV_PERBLK)) {
2445 ubik_AbortTrans(trans);
2446 return VL_INDEXERANGE;
2448 base = index / VL_MHSRV_PERBLK;
2449 offset = index % VL_MHSRV_PERBLK;
2451 ubik_AbortTrans(trans);
2454 if (!ex_addr[base]) {
2455 ubik_AbortTrans(trans);
2456 return VL_INDEXERANGE;
2458 exp = &ex_addr[base][offset];
2459 } else if (attributes->Mask & VLADDR_UUID) {
2460 if (attributes->Mask & (VLADDR_IPADDR | VLADDR_INDEX)) {
2461 ubik_AbortTrans(trans);
2464 if (!ex_addr[0]) { /* mh servers probably aren't setup on this vldb */
2465 ubik_AbortTrans(trans);
2469 FindExtentBlock(trans, &attributes->uuid, 0, -1, &exp, &base))) {
2470 ubik_AbortTrans(trans);
2474 ubik_AbortTrans(trans);
2479 ubik_AbortTrans(trans);
2482 addrsp->bulkaddrs_val = taddrp =
2483 (afs_uint32 *) malloc(sizeof(afs_int32) * (MAXSERVERID + 1));
2484 nservers = *nentries = addrsp->bulkaddrs_len = 0;
2487 ubik_AbortTrans(trans);
2490 tuuid = exp->ex_hostuuid;
2491 afs_ntohuuid(&tuuid);
2492 if (afs_uuid_is_nil(&tuuid)) {
2493 ubik_AbortTrans(trans);
2499 *uniquifier = ntohl(exp->ex_uniquifier);
2500 for (i = 0; i < VL_MAXIPADDRS_PERMH; i++) {
2501 if (exp->ex_addrs[i]) {
2502 taddr = ntohl(exp->ex_addrs[i]);
2503 /* Weed out duplicates */
2504 for (j = 0; j < nservers; j++) {
2505 if (taddrp[j] == taddr)
2508 if ((j == nservers) && (j <= MAXSERVERID)) {
2509 taddrp[nservers] = taddr;
2514 addrsp->bulkaddrs_len = *nentries = nservers;
2515 return (ubik_EndTrans(trans));
2518 /* ============> End of Exported vldb RPC functions <============= */
2521 /* Routine that copies the given vldb entry to the output buffer, vldbentries. */
2523 put_attributeentry(struct vldbentry **Vldbentry,
2524 struct vldbentry **VldbentryFirst,
2525 struct vldbentry **VldbentryLast,
2526 bulkentries *vldbentries,
2527 struct nvlentry *entry,
2528 afs_int32 *nentries,
2529 afs_int32 *alloccnt)
2534 if (*Vldbentry == *VldbentryLast) {
2536 return VL_SIZEEXCEEDED; /* no growing if smallMem defined */
2538 /* Allocate another set of memory; each time allocate twice as
2539 * many blocks as the last time. When we reach VLDBALLOCLIMIT,
2540 * then grow in increments of VLDBALLOCINCR.
2542 allo = (*alloccnt > VLDBALLOCLIMIT) ? VLDBALLOCINCR : *alloccnt;
2544 (vldbentry *) realloc(*VldbentryFirst,
2545 (*alloccnt + allo) * sizeof(vldbentry));
2549 *VldbentryFirst = vldbentries->bulkentries_val = reall;
2550 *Vldbentry = *VldbentryFirst + *alloccnt;
2551 *VldbentryLast = *Vldbentry + allo;
2554 vlentry_to_vldbentry(entry, *Vldbentry);
2557 vldbentries->bulkentries_len++;
2562 put_nattributeentry(struct nvldbentry **Vldbentry,
2563 struct nvldbentry **VldbentryFirst,
2564 struct nvldbentry **VldbentryLast,
2565 nbulkentries *vldbentries,
2566 struct nvlentry *entry,
2567 afs_int32 matchtype,
2568 afs_int32 matchindex,
2569 afs_int32 *nentries,
2570 afs_int32 *alloccnt)
2575 if (*Vldbentry == *VldbentryLast) {
2577 return VL_SIZEEXCEEDED; /* no growing if smallMem defined */
2579 /* Allocate another set of memory; each time allocate twice as
2580 * many blocks as the last time. When we reach VLDBALLOCLIMIT,
2581 * then grow in increments of VLDBALLOCINCR.
2583 allo = (*alloccnt > VLDBALLOCLIMIT) ? VLDBALLOCINCR : *alloccnt;
2585 (nvldbentry *) realloc(*VldbentryFirst,
2586 (*alloccnt + allo) * sizeof(nvldbentry));
2590 *VldbentryFirst = vldbentries->nbulkentries_val = reall;
2591 *Vldbentry = *VldbentryFirst + *alloccnt;
2592 *VldbentryLast = *Vldbentry + allo;
2595 vlentry_to_nvldbentry(entry, *Vldbentry);
2596 (*Vldbentry)->matchindex = (matchtype << 16) + matchindex;
2599 vldbentries->nbulkentries_len++;
2604 /* Common code to actually remove a vldb entry from the database. */
2606 RemoveEntry(struct ubik_trans *trans, afs_int32 entryptr,
2607 struct nvlentry *tentry)
2611 if ((errorcode = UnthreadVLentry(trans, entryptr, tentry)))
2613 if ((errorcode = FreeBlock(trans, entryptr)))
2619 ReleaseEntry(struct nvlentry *tentry, afs_int32 releasetype)
2621 if (releasetype & LOCKREL_TIMESTAMP)
2622 tentry->LockTimestamp = 0;
2623 if (releasetype & LOCKREL_OPCODE)
2624 tentry->flags &= ~VLOP_ALLOPERS;
2625 if (releasetype & LOCKREL_AFSID)
2626 tentry->LockAfsId = 0;
2630 /* Verify that the incoming vldb entry is valid; multi type of error codes
2633 check_vldbentry(struct vldbentry *aentry)
2637 if (InvalidVolname(aentry->name))
2639 if (aentry->nServers <= 0 || aentry->nServers > OMAXNSERVERS)
2640 return VL_BADSERVER;
2641 for (i = 0; i < aentry->nServers; i++) {
2642 /* if (aentry->serverNumber[i] < 0 || aentry->serverNumber[i] > MAXSERVERID)
2643 return VL_BADSERVER; */
2644 if (aentry->serverPartition[i] < 0
2645 || aentry->serverPartition[i] > MAXPARTITIONID)
2646 return VL_BADPARTITION;
2647 if (aentry->serverFlags[i] < 0
2648 || aentry->serverFlags[i] > MAXSERVERFLAG)
2649 return VL_BADSERVERFLAG;
2655 check_nvldbentry(struct nvldbentry *aentry)
2659 if (InvalidVolname(aentry->name))
2661 if (aentry->nServers <= 0 || aentry->nServers > NMAXNSERVERS)
2662 return VL_BADSERVER;
2663 for (i = 0; i < aentry->nServers; i++) {
2664 /* if (aentry->serverNumber[i] < 0 || aentry->serverNumber[i] > MAXSERVERID)
2665 return VL_BADSERVER; */
2666 if (aentry->serverPartition[i] < 0
2667 || aentry->serverPartition[i] > MAXPARTITIONID)
2668 return VL_BADPARTITION;
2669 if (aentry->serverFlags[i] < 0
2670 || aentry->serverFlags[i] > MAXSERVERFLAG)
2671 return VL_BADSERVERFLAG;
2677 /* Convert from the external vldb entry representation to its internal
2678 (more compact) form. This call should not change the hash chains! */
2680 vldbentry_to_vlentry(struct ubik_trans *atrans,
2681 struct vldbentry *VldbEntry,
2682 struct nvlentry *VlEntry)
2686 if (strcmp(VlEntry->name, VldbEntry->name))
2687 strncpy(VlEntry->name, VldbEntry->name, sizeof(VlEntry->name));
2688 for (i = 0; i < VldbEntry->nServers; i++) {
2689 serverindex = IpAddrToRelAddr(VldbEntry->serverNumber[i], atrans);
2690 if (serverindex == -1)
2691 return VL_BADSERVER;
2692 VlEntry->serverNumber[i] = serverindex;
2693 VlEntry->serverPartition[i] = VldbEntry->serverPartition[i];
2694 VlEntry->serverFlags[i] = VldbEntry->serverFlags[i];
2696 for (; i < OMAXNSERVERS; i++)
2697 VlEntry->serverNumber[i] = VlEntry->serverPartition[i] =
2698 VlEntry->serverFlags[i] = BADSERVERID;
2699 for (i = 0; i < MAXTYPES; i++)
2700 VlEntry->volumeId[i] = VldbEntry->volumeId[i];
2701 VlEntry->cloneId = VldbEntry->cloneId;
2702 VlEntry->flags = VldbEntry->flags;
2707 nvldbentry_to_vlentry(struct ubik_trans *atrans,
2708 struct nvldbentry *VldbEntry,
2709 struct nvlentry *VlEntry)
2713 if (strcmp(VlEntry->name, VldbEntry->name))
2714 strncpy(VlEntry->name, VldbEntry->name, sizeof(VlEntry->name));
2715 for (i = 0; i < VldbEntry->nServers; i++) {
2716 serverindex = IpAddrToRelAddr(VldbEntry->serverNumber[i], atrans);
2717 if (serverindex == -1)
2718 return VL_BADSERVER;
2719 VlEntry->serverNumber[i] = serverindex;
2720 VlEntry->serverPartition[i] = VldbEntry->serverPartition[i];
2721 VlEntry->serverFlags[i] = VldbEntry->serverFlags[i];
2723 for (; i < NMAXNSERVERS; i++)
2724 VlEntry->serverNumber[i] = VlEntry->serverPartition[i] =
2725 VlEntry->serverFlags[i] = BADSERVERID;
2726 for (i = 0; i < MAXTYPES; i++)
2727 VlEntry->volumeId[i] = VldbEntry->volumeId[i];
2728 VlEntry->cloneId = VldbEntry->cloneId;
2729 VlEntry->flags = VldbEntry->flags;
2734 /* Update the vldb entry with the new fields as indicated by the value of
2735 * the Mask entry in the updateentry structure. All necessary validation
2736 * checks are performed.
2739 get_vldbupdateentry(struct ubik_trans *trans,
2740 afs_int32 blockindex,
2741 struct VldbUpdateEntry *updateentry,
2742 struct nvlentry *VlEntry)
2744 int i, j, errorcode, serverindex;
2745 afs_uint32 checkids[MAXTYPES];
2747 /* check if any specified new IDs are already present in the db. Do
2748 * this check before doing anything else, so we don't get a half-
2750 memset(&checkids, 0, sizeof(checkids));
2751 if (updateentry->Mask & VLUPDATE_RWID) {
2752 checkids[RWVOL] = updateentry->spares3; /* rw id */
2754 if (updateentry->Mask & VLUPDATE_READONLYID) {
2755 checkids[ROVOL] = updateentry->ReadOnlyId;
2757 if (updateentry->Mask & VLUPDATE_BACKUPID) {
2758 checkids[BACKVOL] = updateentry->BackupId;
2761 if (EntryIDExists(trans, checkids, MAXTYPES, &errorcode)) {
2763 } else if (errorcode) {
2767 if (updateentry->Mask & VLUPDATE_VOLUMENAME) {
2768 struct nvlentry tentry;
2770 if (InvalidVolname(updateentry->name))
2773 if (FindByName(trans, updateentry->name, &tentry, &errorcode)) {
2774 return VL_NAMEEXIST;
2775 } else if (errorcode) {
2779 if ((errorcode = UnhashVolname(trans, blockindex, VlEntry)))
2781 strncpy(VlEntry->name, updateentry->name, sizeof(VlEntry->name));
2782 HashVolname(trans, blockindex, VlEntry);
2785 if (updateentry->Mask & VLUPDATE_VOLNAMEHASH) {
2786 if ((errorcode = UnhashVolname(trans, blockindex, VlEntry))) {
2787 if (errorcode != VL_NOENT)
2790 HashVolname(trans, blockindex, VlEntry);
2793 if (updateentry->Mask & VLUPDATE_FLAGS) {
2794 VlEntry->flags = updateentry->flags;
2796 if (updateentry->Mask & VLUPDATE_CLONEID) {
2797 VlEntry->cloneId = updateentry->cloneId;
2799 if (updateentry->Mask & VLUPDATE_RWID) {
2800 if ((errorcode = UnhashVolid(trans, RWVOL, blockindex, VlEntry))) {
2801 if (errorcode != VL_NOENT)
2804 VlEntry->volumeId[RWVOL] = updateentry->spares3; /* rw id */
2805 if ((errorcode = HashVolid(trans, RWVOL, blockindex, VlEntry)))
2808 if (updateentry->Mask & VLUPDATE_READONLYID) {
2809 if ((errorcode = UnhashVolid(trans, ROVOL, blockindex, VlEntry))) {
2810 if (errorcode != VL_NOENT)
2813 VlEntry->volumeId[ROVOL] = updateentry->ReadOnlyId;
2814 if ((errorcode = HashVolid(trans, ROVOL, blockindex, VlEntry)))
2817 if (updateentry->Mask & VLUPDATE_BACKUPID) {
2818 if ((errorcode = UnhashVolid(trans, BACKVOL, blockindex, VlEntry))) {
2819 if (errorcode != VL_NOENT)
2822 VlEntry->volumeId[BACKVOL] = updateentry->BackupId;
2823 if ((errorcode = HashVolid(trans, BACKVOL, blockindex, VlEntry)))
2826 if (updateentry->Mask & VLUPDATE_REPSITES) {
2827 if (updateentry->nModifiedRepsites <= 0
2828 || updateentry->nModifiedRepsites > OMAXNSERVERS)
2829 return VL_BADSERVER;
2830 for (i = 0; i < updateentry->nModifiedRepsites; i++) {
2831 /* if (updateentry->RepsitesTargetServer[i] < 0 || updateentry->RepsitesTargetServer[i] > MAXSERVERID)
2832 return VL_BADSERVER; */
2833 if (updateentry->RepsitesTargetPart[i] < 0
2834 || updateentry->RepsitesTargetPart[i] > MAXPARTITIONID)
2835 return VL_BADPARTITION;
2836 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_DELETE) {
2838 repsite_exists(VlEntry,
2839 IpAddrToRelAddr(updateentry->
2840 RepsitesTargetServer[i],
2842 updateentry->RepsitesTargetPart[i])) !=
2844 repsite_compress(VlEntry, j);
2846 return VL_NOREPSERVER;
2848 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_ADD) {
2849 /* if (updateentry->RepsitesNewServer[i] < 0 || updateentry->RepsitesNewServer[i] > MAXSERVERID)
2850 return VL_BADSERVER; */
2851 if (updateentry->RepsitesNewPart[i] < 0
2852 || updateentry->RepsitesNewPart[i] > MAXPARTITIONID)
2853 return VL_BADPARTITION;
2856 IpAddrToRelAddr(updateentry->RepsitesNewServer[i],
2858 updateentry->RepsitesNewPart[i]) != -1)
2859 return VL_DUPREPSERVER;
2861 VlEntry->serverNumber[j] != BADSERVERID
2862 && j < OMAXNSERVERS; j++);
2863 if (j >= OMAXNSERVERS)
2866 IpAddrToRelAddr(updateentry->RepsitesNewServer[i],
2868 return VL_BADSERVER;
2869 VlEntry->serverNumber[j] = serverindex;
2870 VlEntry->serverPartition[j] = updateentry->RepsitesNewPart[i];
2871 if (updateentry->RepsitesNewFlags[i] < 0
2872 || updateentry->RepsitesNewFlags[i] > MAXSERVERFLAG)
2873 return VL_BADSERVERFLAG;
2874 VlEntry->serverFlags[j] = updateentry->RepsitesNewFlags[i];
2876 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODSERV) {
2877 /*n if (updateentry->RepsitesNewServer[i] < 0 || updateentry->RepsitesNewServer[i] > MAXSERVERID)
2878 return VL_BADSERVER; */
2880 repsite_exists(VlEntry,
2881 IpAddrToRelAddr(updateentry->
2882 RepsitesTargetServer[i],
2884 updateentry->RepsitesTargetPart[i])) !=
2886 VlEntry->serverNumber[j] =
2887 IpAddrToRelAddr(updateentry->RepsitesNewServer[i],
2890 return VL_NOREPSERVER;
2892 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODPART) {
2893 if (updateentry->RepsitesNewPart[i] < 0
2894 || updateentry->RepsitesNewPart[i] > MAXPARTITIONID)
2895 return VL_BADPARTITION;
2897 repsite_exists(VlEntry,
2898 IpAddrToRelAddr(updateentry->
2899 RepsitesTargetServer[i],
2901 updateentry->RepsitesTargetPart[i])) !=
2903 VlEntry->serverPartition[j] =
2904 updateentry->RepsitesNewPart[i];
2906 return VL_NOREPSERVER;
2908 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODFLAG) {
2910 repsite_exists(VlEntry,
2911 IpAddrToRelAddr(updateentry->
2912 RepsitesTargetServer[i],
2914 updateentry->RepsitesTargetPart[i])) !=
2916 if (updateentry->RepsitesNewFlags[i] < 0
2917 || updateentry->RepsitesNewFlags[i] > MAXSERVERFLAG)
2918 return VL_BADSERVERFLAG;
2919 VlEntry->serverFlags[j] =
2920 updateentry->RepsitesNewFlags[i];
2922 return VL_NOREPSERVER;
2930 /* Check if the specified [server,partition] entry is found in the vldb
2931 * entry's repsite table; it's offset in the table is returned, if it's
2934 repsite_exists(struct nvlentry *VlEntry, int server, int partition)
2938 for (i = 0; VlEntry->serverNumber[i] != BADSERVERID && i < OMAXNSERVERS;
2940 if ((VlEntry->serverNumber[i] == server)
2941 && (VlEntry->serverPartition[i] == partition))
2949 /* Repsite table compression: used when deleting a repsite entry so that
2950 * all active repsite entries are on the top of the table. */
2952 repsite_compress(struct nvlentry *VlEntry, int offset)
2954 int repsite_offset = offset;
2956 VlEntry->serverNumber[repsite_offset] != BADSERVERID
2957 && repsite_offset < OMAXNSERVERS - 1; repsite_offset++) {
2958 VlEntry->serverNumber[repsite_offset] =
2959 VlEntry->serverNumber[repsite_offset + 1];
2960 VlEntry->serverPartition[repsite_offset] =
2961 VlEntry->serverPartition[repsite_offset + 1];
2962 VlEntry->serverFlags[repsite_offset] =
2963 VlEntry->serverFlags[repsite_offset + 1];
2965 VlEntry->serverNumber[repsite_offset] = BADSERVERID;
2969 /* Convert from the internal (compacted) vldb entry to the external
2970 * representation used by the interface. */
2972 vlentry_to_vldbentry(struct nvlentry *VlEntry, struct vldbentry *VldbEntry)
2976 memset(VldbEntry, 0, sizeof(struct vldbentry));
2977 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
2978 for (i = 0; i < OMAXNSERVERS; i++) {
2979 if (VlEntry->serverNumber[i] == BADSERVERID)
2981 if ((HostAddress[j = VlEntry->serverNumber[i]] & 0xff000000) ==
2983 struct extentaddr *exp;
2986 base = (HostAddress[j] >> 16) & 0xff;
2987 index = HostAddress[j] & 0x0000ffff;
2988 exp = &ex_addr[base][index];
2989 /* For now return the first ip address back */
2990 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2991 if (exp->ex_addrs[j]) {
2992 VldbEntry->serverNumber[i] = ntohl(exp->ex_addrs[j]);
2997 VldbEntry->serverNumber[i] =
2998 HostAddress[VlEntry->serverNumber[i]];
2999 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
3000 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
3002 VldbEntry->nServers = i;
3003 for (i = 0; i < MAXTYPES; i++)
3004 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
3005 VldbEntry->cloneId = VlEntry->cloneId;
3006 VldbEntry->flags = VlEntry->flags;
3010 /* Convert from the internal (compacted) vldb entry to the external
3011 * representation used by the interface. */
3013 vlentry_to_nvldbentry(struct nvlentry *VlEntry, struct nvldbentry *VldbEntry)
3017 memset(VldbEntry, 0, sizeof(struct vldbentry));
3018 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
3019 for (i = 0; i < NMAXNSERVERS; i++) {
3020 if (VlEntry->serverNumber[i] == BADSERVERID)
3022 if ((HostAddress[j = VlEntry->serverNumber[i]] & 0xff000000) ==
3024 struct extentaddr *exp;
3027 base = (HostAddress[j] >> 16) & 0xff;
3028 index = HostAddress[j] & 0x0000ffff;
3029 exp = &ex_addr[base][index];
3030 /* For now return the first ip address back */
3031 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
3032 if (exp->ex_addrs[j]) {
3033 VldbEntry->serverNumber[i] = ntohl(exp->ex_addrs[j]);
3038 VldbEntry->serverNumber[i] =
3039 HostAddress[VlEntry->serverNumber[i]];
3040 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
3041 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
3043 VldbEntry->nServers = i;
3044 for (i = 0; i < MAXTYPES; i++)
3045 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
3046 VldbEntry->cloneId = VlEntry->cloneId;
3047 VldbEntry->flags = VlEntry->flags;
3051 vlentry_to_uvldbentry(struct nvlentry *VlEntry, struct uvldbentry *VldbEntry)
3055 memset(VldbEntry, 0, sizeof(struct vldbentry));
3056 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
3057 for (i = 0; i < NMAXNSERVERS; i++) {
3058 if (VlEntry->serverNumber[i] == BADSERVERID)
3060 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
3061 VldbEntry->serverUnique[i] = 0;
3062 if ((HostAddress[j = VlEntry->serverNumber[i]] & 0xff000000) ==
3064 struct extentaddr *exp;
3068 base = (HostAddress[j] >> 16) & 0xff;
3069 index = HostAddress[j] & 0x0000ffff;
3070 exp = &ex_addr[base][index];
3071 tuuid = exp->ex_hostuuid;
3072 afs_ntohuuid(&tuuid);
3073 VldbEntry->serverFlags[i] |= VLSERVER_FLAG_UUID;
3074 VldbEntry->serverNumber[i] = tuuid;
3075 VldbEntry->serverUnique[i] = ntohl(exp->ex_uniquifier);
3077 VldbEntry->serverNumber[i].time_low =
3078 HostAddress[VlEntry->serverNumber[i]];
3080 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
3083 VldbEntry->nServers = i;
3084 for (i = 0; i < MAXTYPES; i++)
3085 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
3086 VldbEntry->cloneId = VlEntry->cloneId;
3087 VldbEntry->flags = VlEntry->flags;
3090 #define LEGALCHARS ".ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
3093 /* Verify that the volname is a valid volume name. */
3095 InvalidVolname(char *volname)
3101 slen = strlen(volname);
3102 if (slen >= VL_MAXNAMELEN)
3104 return (slen != strspn(volname, map));
3108 /* Verify that the given volume type is valid. */
3110 InvalidVoltype(afs_int32 voltype)
3112 if (voltype != RWVOL && voltype != ROVOL && voltype != BACKVOL)
3119 InvalidOperation(afs_int32 voloper)
3121 if (voloper != VLOP_MOVE && voloper != VLOP_RELEASE
3122 && voloper != VLOP_BACKUP && voloper != VLOP_DELETE
3123 && voloper != VLOP_DUMP)
3129 InvalidReleasetype(afs_int32 releasetype)
3131 if ((releasetype & LOCKREL_TIMESTAMP) || (releasetype & LOCKREL_OPCODE)
3132 || (releasetype & LOCKREL_AFSID))
3138 IpAddrToRelAddr(afs_uint32 ipaddr, struct ubik_trans *atrans)
3141 afs_int32 code, base, index;
3142 struct extentaddr *exp;
3144 for (i = 0; i <= MAXSERVERID; i++) {
3145 if (HostAddress[i] == ipaddr)
3147 if ((HostAddress[i] & 0xff000000) == 0xff000000) {
3148 base = (HostAddress[i] >> 16) & 0xff;
3149 index = HostAddress[i] & 0x0000ffff;
3150 if (base >= VL_MAX_ADDREXTBLKS) {
3152 ("Internal error: Multihome extent base is too large. Base %d index %d\n",
3154 return -1; /* EINVAL */
3156 if (index >= VL_MHSRV_PERBLK) {
3158 ("Internal error: Multihome extent index is too large. Base %d index %d\n",
3160 return -1; /* EINVAL */
3162 if (!ex_addr[base]) {
3164 ("Internal error: Multihome extent does not exist. Base %d\n",
3166 return -1; /* EINVAL */
3168 exp = &ex_addr[base][index];
3169 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
3170 if (exp->ex_addrs[j] && (ntohl(exp->ex_addrs[j]) == ipaddr)) {
3177 /* allocate the new server a server id pronto */
3179 for (i = 0; i <= MAXSERVERID; i++) {
3180 if (cheader.IpMappedAddr[i] == 0) {
3181 cheader.IpMappedAddr[i] = htonl(ipaddr);
3184 DOFFSET(0, &cheader, &cheader.IpMappedAddr[i]),
3185 (char *)&cheader.IpMappedAddr[i],
3187 HostAddress[i] = ipaddr;
3198 ChangeIPAddr(afs_uint32 ipaddr1, afs_uint32 ipaddr2, struct ubik_trans *atrans)
3202 struct extentaddr *exp = NULL;
3206 afs_int32 blockindex, count;
3208 struct nvlentry tentry;
3209 int ipaddr1_id = -1, ipaddr2_id = -1;
3212 return VL_CREATEFAIL;
3214 /* Don't let addr change to 256.*.*.* : Causes internal error below */
3215 if ((ipaddr2 & 0xff000000) == 0xff000000)
3216 return (VL_BADSERVER);
3218 /* If we are removing an address, ip1 will be -1 and ip2 will be
3219 * the original address. This prevents an older revision vlserver
3220 * from removing the IP address (won't find server 0xfffffff in
3221 * the VLDB). An older revision vlserver does not have the check
3222 * to see if any volumes exist on the server being removed.
3224 if (ipaddr1 == 0xffffffff) {
3229 for (i = 0; i <= MAXSERVERID; i++) {
3230 if ((HostAddress[i] & 0xff000000) == 0xff000000) {
3231 base = (HostAddress[i] >> 16) & 0xff;
3232 index = HostAddress[i] & 0x0000ffff;
3233 if ((base >= VL_MAX_ADDREXTBLKS) || (index >= VL_MHSRV_PERBLK)) {
3235 ("Internal error: Multihome extent addr is too large. Base %d index %d\n",
3237 return -1; /* EINVAL */
3240 exp = &ex_addr[base][index];
3241 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
3242 if (!exp->ex_addrs[mhidx])
3244 if (ntohl(exp->ex_addrs[mhidx]) == ipaddr1) {
3247 if (ipaddr2 != 0 && ntohl(exp->ex_addrs[mhidx]) == ipaddr2) {
3252 if (HostAddress[i] == ipaddr1) {
3256 if (ipaddr2 != 0 && HostAddress[i] == ipaddr2) {
3261 if (ipaddr1_id >= 0 && (ipaddr2 == 0 || ipaddr2_id >= 0)) {
3262 /* we've either found both IPs already in the VLDB, or we found
3263 * ipaddr1, and we're not going to find ipaddr2 because it's 0 */
3268 if (ipaddr1_id < 0) {
3269 return VL_NOENT; /* not found */
3272 if (ipaddr2_id >= 0 && ipaddr2_id != ipaddr1_id) {
3273 char buf1[16], buf2[16];
3274 VLog(0, ("Cannot change IP address from %s to %s because the latter "
3275 "is in use by server id %d\n",
3276 afs_inet_ntoa_r(htonl(ipaddr1), buf1),
3277 afs_inet_ntoa_r(htonl(ipaddr2), buf2),
3279 return VL_MULTIPADDR;
3282 /* If we are removing a server entry, a volume cannot
3283 * exist on the server. If one does, don't remove the
3284 * server entry: return error "volume entry exists".
3287 for (blockindex = NextEntry(atrans, 0, &tentry, &count); blockindex;
3288 blockindex = NextEntry(atrans, blockindex, &tentry, &count)) {
3289 if (++pollcount > 50) {
3290 #ifndef AFS_PTHREAD_ENV
3295 for (j = 0; j < NMAXNSERVERS; j++) {
3296 if (tentry.serverNumber[j] == BADSERVERID)
3298 if (tentry.serverNumber[j] == ipaddr1_id) {
3305 /* Log a message saying we are changing/removing an IP address */
3307 ("The following IP address is being %s:\n",
3308 (ipaddr2 ? "changed" : "removed")));
3309 VLog(0, (" entry %d: ", i));
3312 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
3313 if (!exp->ex_addrs[mhidx])
3317 PADDR(ntohl(exp->ex_addrs[mhidx]));
3329 /* Change the registered uuuid addresses */
3331 memset(&tuuid, 0, sizeof(afsUUID));
3332 afs_htonuuid(&tuuid);
3333 exp->ex_hostuuid = tuuid;
3336 DOFFSET(ntohl(ex_addr[0]->ex_contaddrs[base]),
3337 (char *)ex_addr[base], (char *)exp),
3338 (char *)&tuuid, sizeof(tuuid));
3343 /* Now change the host address entry */
3344 cheader.IpMappedAddr[ipaddr1_id] = htonl(ipaddr2);
3346 vlwrite(atrans, DOFFSET(0, &cheader, &cheader.IpMappedAddr[ipaddr1_id]),
3348 &cheader.IpMappedAddr[ipaddr1_id], sizeof(afs_int32));
3349 HostAddress[ipaddr1_id] = ipaddr2;
3356 /* see if the vlserver is back yet */
3358 SVL_ProbeServer(struct rx_call *rxcall)