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>
15 #include <sys/types.h>
18 #include <afs/afsutil.h>
25 #include <netinet/in.h>
36 #include "afs/audit.h"
43 extern struct afsconf_dir *vldb_confdir;
44 extern struct ubik_dbase *VL_dbase;
45 struct vlheader cheader; /* kept in network byte order */
46 extern afs_uint32 HostAddress[]; /* host addresses kept in host byte order */
48 struct extentaddr *ex_addr[VL_MAX_ADDREXTBLKS] = { 0, 0, 0, 0};
49 static char rxinfo_str[128]; /* Need rxinfo string to be non-local */
50 #define ABORT(c) { errorcode = (c); goto abort; }
52 #define END(c) { errorcode = (c); goto end; }
54 #define VLDBALLOCLIMIT 10000
55 #define VLDBALLOCINCR 2048
57 static int put_attributeentry();
58 static int put_nattributeentry();
59 static int RemoveEntry();
60 static ReleaseEntry();
61 static int check_vldbentry();
62 static int check_nvldbentry();
63 static int vldbentry_to_vlentry();
64 static int nvldbentry_to_vlentry();
65 static get_vldbupdateentry();
66 static int repsite_exists();
67 static repsite_compress();
68 static vlentry_to_vldbentry();
69 static vlentry_to_nvldbentry();
70 static vlentry_to_uvldbentry();
71 static int InvalidVolname();
72 static int InvalidVoltype();
73 static int InvalidOperation();
74 static int InvalidReleasetype();
75 static int IpAddrToRelAddr();
76 static int ChangeIPAddr();
79 struct rx_call *rxcall;
82 register struct rx_connection *tconn;
87 struct in_addr hostAddr;
89 tconn = rx_ConnectionOf(rxcall);
90 hostAddr.s_addr = rx_HostOf(rx_PeerOf(tconn));
91 code = rxkad_GetServerInfo(rxcall->conn, NULL, &exp, tname, tinst, tcell, NULL);
93 sprintf(rxinfo_str,"%s %s", inet_ntoa(hostAddr), tname);
95 sprintf(rxinfo_str,"%s noauth",inet_ntoa(hostAddr));
99 /* This is called to initialize the database, set the appropriate locks and make sure that the vldb header is valid */
100 int Init_VLdbase (trans, locktype, this_op)
101 struct ubik_trans **trans;
102 int locktype; /* indicate read or write transaction */
105 int errorcode=0, pass, wl;
107 for (pass=1; pass<=3; pass++) {
108 if (pass == 2) { /* take write lock to rebuild the db */
109 errorcode = ubik_BeginTrans (VL_dbase, UBIK_WRITETRANS, trans);
112 else if (locktype == LOCKREAD) {
113 errorcode = ubik_BeginTransReadAny (VL_dbase, UBIK_READTRANS, trans);
117 errorcode = ubik_BeginTrans (VL_dbase, UBIK_WRITETRANS, trans);
123 errorcode = ubik_SetLock (*trans, 1, 1, locktype);
126 ubik_AbortTrans (*trans);
130 /* check that dbase is initialized and setup cheader */
131 /* 2nd pass we try to rebuild the header */
132 errorcode = CheckInit(*trans, ((pass==2)?1:0));
133 if (!errorcode && wl && extent_mod)
134 errorcode = readExtents(*trans); /* Fix the mh extent blocks */
137 ubik_AbortTrans(*trans);
138 /* Only rebuld if the database is empty */
139 /* Exit if can't rebuild */
140 if ((pass == 1) && (errorcode != VL_EMPTY)) return errorcode;
141 if (pass == 2) return errorcode;
143 else { /* No errorcode */
145 ubik_EndTrans(*trans); /* Rebuilt db. End trans, then retake original lock */
148 break; /* didn't rebuild and successful - exit */
156 /* Create a new vldb entry; both new volume id and name must be unique (non-existant in vldb). */
158 afs_int32 SVL_CreateEntry(rxcall, newentry)
159 struct rx_call *rxcall;
160 struct vldbentry *newentry;
161 { struct ubik_trans *trans;
162 afs_int32 errorcode, blockindex;
163 struct nvlentry tentry;
165 COUNT_REQ (VLCREATEENTRY);
166 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) {
171 /* Do some validity tests on new entry */
172 if ( (errorcode = check_vldbentry(newentry))
173 || (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
176 VLog(1, ("OCreate Volume %d %s\n", newentry->volumeId[RWVOL], rxinfo(rxcall)));
177 /* XXX shouldn't we check to see if the r/o volume is duplicated? */
178 if (newentry->volumeId[RWVOL]
179 && FindByID(trans, newentry->volumeId[RWVOL], RWVOL, &tentry,
180 &errorcode)) { /* entry already exists, we fail */
181 errorcode = VL_IDEXIST;
183 } else if (errorcode) {
187 /* Is this following check (by volume name) necessary?? */
188 /* If entry already exists, we fail */
189 if (FindByName(trans, newentry->name, &tentry, &errorcode)) {
190 errorcode = VL_NAMEEXIST;
192 } else if (errorcode) {
196 blockindex = AllocBlock(trans, &tentry);
197 if (blockindex == 0) {
198 errorcode = VL_CREATEFAIL;
202 memset(&tentry, 0, sizeof(struct nvlentry));
203 /* Convert to its internal representation; both in host byte order */
204 if (errorcode = vldbentry_to_vlentry(trans, newentry, &tentry)) {
205 FreeBlock(trans, blockindex);
209 /* Actually insert the entry in vldb */
210 errorcode = ThreadVLentry(trans, blockindex, &tentry);
212 FreeBlock(trans, blockindex);
216 errorcode = ubik_EndTrans(trans);
222 ubik_AbortTrans(trans);
225 osi_auditU (rxcall, VLCreateEntryEvent, errorcode,
226 AUD_STR, (newentry ? newentry->name : NULL), AUD_END);
231 afs_int32 SVL_CreateEntryN(rxcall, newentry)
232 struct rx_call *rxcall;
233 struct nvldbentry *newentry;
234 { struct ubik_trans *trans;
235 afs_int32 errorcode, blockindex;
236 struct nvlentry tentry;
238 COUNT_REQ (VLCREATEENTRYN);
239 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) {
244 /* Do some validity tests on new entry */
245 if ( (errorcode = check_nvldbentry(newentry))
246 || (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op)))
249 VLog(1, ("Create Volume %d %s\n", newentry->volumeId[RWVOL], rxinfo(rxcall)));
250 /* XXX shouldn't we check to see if the r/o volume is duplicated? */
251 if (newentry->volumeId[RWVOL]
252 && FindByID(trans, newentry->volumeId[RWVOL], RWVOL, &tentry,
253 &errorcode)) { /* entry already exists, we fail */
254 errorcode = VL_IDEXIST;
256 } else if (errorcode) {
260 /* Is this following check (by volume name) necessary?? */
261 /* If entry already exists, we fail */
262 if (FindByName(trans, newentry->name, &tentry, &errorcode)) {
263 errorcode = VL_NAMEEXIST;
265 } else if (errorcode) {
269 blockindex = AllocBlock(trans, &tentry);
270 if (blockindex == 0) {
271 errorcode = VL_CREATEFAIL;
275 memset(&tentry, 0, sizeof(struct nvlentry));
276 /* Convert to its internal representation; both in host byte order */
277 if (errorcode = nvldbentry_to_vlentry(trans, newentry, &tentry)) {
278 FreeBlock(trans, blockindex);
282 /* Actually insert the entry in vldb */
283 errorcode = ThreadVLentry(trans, blockindex, &tentry);
285 FreeBlock(trans, blockindex);
289 errorcode = ubik_EndTrans(trans);
295 ubik_AbortTrans(trans);
298 osi_auditU (rxcall, VLCreateEntryEvent, errorcode,
299 AUD_STR, (newentry ? newentry->name : NULL), AUD_END);
304 afs_int32 SVL_ChangeAddr(rxcall, ip1, ip2)
305 struct rx_call *rxcall;
307 { struct ubik_trans *trans;
310 COUNT_REQ (VLCHANGEADDR);
311 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) {
316 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
319 VLog(1, ("Change Addr %d -> %d %s\n", ip1, ip2, rxinfo(rxcall)));
320 if (errorcode = ChangeIPAddr(ip1, ip2, trans))
323 errorcode = ubik_EndTrans(trans);
329 ubik_AbortTrans(trans);
332 osi_auditU (rxcall, VLChangeAddrEvent, errorcode, AUD_LONG, ip1,
333 AUD_LONG, ip2, AUD_END);
337 /* Delete a vldb entry given the volume id. */
338 afs_int32 SVL_DeleteEntry(rxcall, volid, voltype)
339 struct rx_call *rxcall;
342 { struct ubik_trans *trans;
343 afs_int32 blockindex, errorcode;
344 struct nvlentry tentry;
346 COUNT_REQ (VLDELETEENTRY);
347 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
350 if ((voltype != -1 ) && (InvalidVoltype(voltype)))
351 END( VL_BADVOLTYPE );
353 if (errorcode = Init_VLdbase (&trans, LOCKWRITE, this_op))
356 VLog(1, ("Delete Volume %d %s\n", volid, rxinfo(rxcall)));
357 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
358 if (blockindex == 0) { /* volid not found */
359 if (!errorcode) errorcode = VL_NOENT;
363 if (tentry.flags & VLDELETED) { /* Already deleted; return */
364 ABORT( VL_ENTDELETED );
366 if (errorcode = RemoveEntry(trans, blockindex, &tentry)) {
369 errorcode = (ubik_EndTrans(trans));
374 ubik_AbortTrans(trans);
377 osi_auditU (rxcall, VLDeleteEntryEvent, errorcode, AUD_LONG, volid, AUD_END);
382 /* Get a vldb entry given its volume id; make sure it's not a deleted entry. */
383 GetEntryByID (rxcall, volid, voltype, aentry, new, this_op)
384 struct rx_call *rxcall;
386 afs_int32 voltype, new, this_op;
387 char *aentry; /* entry data copied here */
388 { struct ubik_trans *trans;
389 afs_int32 blockindex, errorcode;
390 struct nvlentry tentry;
392 if ((voltype != -1 ) && (InvalidVoltype(voltype)))
393 return VL_BADVOLTYPE;
394 if (errorcode = Init_VLdbase (&trans, LOCKREAD, this_op))
397 VLog(5, ("GetVolumeByID %d (%d) %s\n", volid, new, rxinfo(rxcall)));
398 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
399 if (blockindex == 0) { /* entry not found */
400 if (!errorcode) errorcode = VL_NOENT;
402 ubik_AbortTrans (trans);
405 if (tentry.flags & VLDELETED) { /* Entry is deleted! */
407 ubik_AbortTrans (trans);
408 return VL_ENTDELETED;
410 /* Convert from the internal to external form */
412 vlentry_to_nvldbentry(&tentry, (struct nvldbentry *)aentry);
414 vlentry_to_uvldbentry(&tentry, (struct uvldbentry *)aentry);
416 vlentry_to_vldbentry(&tentry, (struct vldbentry *)aentry);
417 return(ubik_EndTrans(trans));
420 afs_int32 SVL_GetEntryByID (rxcall, volid, voltype, aentry)
421 struct rx_call *rxcall;
422 afs_int32 volid, voltype;
423 vldbentry *aentry; /* entry data copied here */
425 COUNT_REQ (VLGETENTRYBYID);
426 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 0, this_op));
429 afs_int32 SVL_GetEntryByIDN (rxcall, volid, voltype, aentry)
430 struct rx_call *rxcall;
431 afs_int32 volid, voltype;
432 nvldbentry *aentry; /* entry data copied here */
434 COUNT_REQ (VLGETENTRYBYIDN);
435 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 1, this_op));
438 afs_int32 SVL_GetEntryByIDU (rxcall, volid, voltype, aentry)
439 struct rx_call *rxcall;
440 afs_int32 volid, voltype;
441 uvldbentry *aentry; /* entry data copied here */
443 COUNT_REQ (VLGETENTRYBYIDU);
444 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 2, this_op));
449 /* returns true if the id is a decimal integer, in which case we interpret it
450 as an id. make the cache manager much simpler */
451 static int NameIsId(aname)
452 register char *aname; {
454 while (tc = *aname++) {
455 if (tc > '9' || tc < '0') return 0;
460 /* Get a vldb entry given the volume's name; of course, very similar to VLGetEntryByID() above. */
461 GetEntryByName (rxcall, volname, aentry, new, this_op)
462 struct rx_call *rxcall;
464 char *aentry; /* entry data copied here */
466 { struct ubik_trans *trans;
467 afs_int32 blockindex, errorcode;
468 struct nvlentry tentry;
470 if (NameIsId(volname)) {
471 return GetEntryByID(rxcall, atoi(volname), -1, aentry, new, this_op);
473 if (InvalidVolname(volname))
475 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
477 VLog(5, ("GetVolumeByName %s (%d) %s\n", volname, new, rxinfo(rxcall)));
478 blockindex = FindByName(trans, volname, &tentry, &errorcode);
479 if (blockindex == 0) { /* entry not found */
480 if (!errorcode) errorcode = VL_NOENT;
482 ubik_AbortTrans(trans);
485 if (tentry.flags & VLDELETED) { /* Entry is deleted */
487 ubik_AbortTrans(trans);
488 return VL_ENTDELETED;
490 /* Convert to external entry representation */
492 vlentry_to_nvldbentry(&tentry, (struct nvldbentry *)aentry);
494 vlentry_to_uvldbentry(&tentry, (struct uvldbentry *)aentry);
496 vlentry_to_vldbentry(&tentry, (struct vldbentry *)aentry);
497 return(ubik_EndTrans(trans));
500 afs_int32 SVL_GetEntryByNameO (rxcall, volname, aentry)
501 struct rx_call *rxcall;
503 struct vldbentry *aentry; /* entry data copied here */
505 COUNT_REQ (VLGETENTRYBYNAME);
506 return (GetEntryByName(rxcall, volname, (char *)aentry, 0, this_op));
510 afs_int32 SVL_GetEntryByNameN (rxcall, volname, aentry)
511 struct rx_call *rxcall;
513 struct nvldbentry *aentry; /* entry data copied here */
515 COUNT_REQ (VLGETENTRYBYNAMEN);
516 return (GetEntryByName(rxcall, volname, (char *)aentry, 1, this_op));
519 afs_int32 SVL_GetEntryByNameU (rxcall, volname, aentry)
520 struct rx_call *rxcall;
522 struct uvldbentry *aentry; /* entry data copied here */
524 COUNT_REQ (VLGETENTRYBYNAMEU);
525 return (GetEntryByName(rxcall, volname, (char *)aentry, 2, this_op));
530 /* Get the current value of the maximum volume id and bump the volume id counter by Maxvolidbump. */
531 afs_int32 SVL_GetNewVolumeId (rxcall, Maxvolidbump, newvolumeid)
532 struct rx_call *rxcall;
533 afs_int32 Maxvolidbump;
534 afs_int32 *newvolumeid;
535 { register afs_int32 errorcode, maxvolumeid;
536 struct ubik_trans *trans;
538 COUNT_REQ (VLGETNEWVOLUMEID);
539 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
542 if (Maxvolidbump < 0 || Maxvolidbump > MAXBUMPCOUNT)
543 END ( VL_BADVOLIDBUMP );
545 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
548 *newvolumeid = maxvolumeid = ntohl(cheader.vital_header.MaxVolumeId);
549 maxvolumeid += Maxvolidbump;
550 VLog(1, ("GetNewVolid newmax=%d %s\n", maxvolumeid, rxinfo(rxcall)));
551 cheader.vital_header.MaxVolumeId = htonl(maxvolumeid);
552 if (write_vital_vlheader(trans)) {
555 errorcode = (ubik_EndTrans(trans));
560 ubik_AbortTrans(trans);
563 osi_auditU (rxcall, VLGetNewVolumeIdEvent, errorcode, AUD_END);
568 /* Simple replace the contents of the vldb entry, volid, with
569 * newentry. No individual checking/updating per field (alike
570 * VLUpdateEntry) is done. */
572 afs_int32 SVL_ReplaceEntry (rxcall, volid, voltype, newentry, releasetype)
573 struct rx_call *rxcall;
576 struct vldbentry *newentry;
577 afs_int32 releasetype;
578 { struct ubik_trans *trans;
579 afs_int32 blockindex, errorcode, typeindex;
581 int hashVol[MAXTYPES];
582 struct nvlentry tentry;
584 COUNT_REQ (VLREPLACEENTRY);
585 for(typeindex = 0; typeindex < MAXTYPES; typeindex++)
586 hashVol[typeindex] = 0;
588 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
591 if (errorcode = check_vldbentry(newentry))
594 if (voltype != -1 && InvalidVoltype(voltype))
595 END ( VL_BADVOLTYPE );
597 if (releasetype && InvalidReleasetype(releasetype))
598 END( VL_BADRELLOCKTYPE );
599 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
602 VLog(1, ("OReplace Volume %d %s\n", volid, rxinfo(rxcall)));
603 /* find vlentry we're changing */
604 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
605 if (blockindex == 0) { /* entry not found */
606 if (!errorcode) errorcode = VL_NOENT;
610 /* check that we're not trying to change the RW vol ID */
611 if (newentry->volumeId[RWVOL] != tentry.volumeId[RWVOL]) {
612 ABORT( VL_BADENTRY );
615 /* unhash volid entries if they're disappearing or changing.
616 * Remember if we need to hash in the new value (we don't have to
617 * rehash if volid stays same */
618 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
619 if (tentry.volumeId[typeindex] != newentry->volumeId[typeindex]) {
620 if (tentry.volumeId[typeindex])
621 if (errorcode = UnhashVolid(trans, typeindex, blockindex,
625 /* we must rehash new id if the id is different and the ID is nonzero */
626 hashVol[typeindex] = 1; /* must rehash this guy if he exists */
630 /* Rehash volname if it changes */
631 if (strcmp(newentry->name, tentry.name)) { /* Name changes; redo hashing */
632 if (errorcode = UnhashVolname(trans, blockindex, &tentry)) {
638 /* after this, tentry is new entry, not old one. vldbentry_to_vlentry
639 doesn't touch hash chains */
640 if (errorcode = vldbentry_to_vlentry(trans, newentry, &tentry)) {
644 for(typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
645 if (hashVol[typeindex] && tentry.volumeId[typeindex]) {
646 if (errorcode = HashVolid(trans, typeindex, blockindex, &tentry)) {
653 HashVolname(trans, blockindex, &tentry);
656 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
657 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
661 END (ubik_EndTrans(trans));
665 ubik_AbortTrans(trans);
668 osi_auditU (rxcall, VLReplaceVLEntryEvent, errorcode, AUD_LONG, volid, AUD_END);
672 afs_int32 SVL_ReplaceEntryN (rxcall, volid, voltype, newentry, releasetype)
673 struct rx_call *rxcall;
676 struct nvldbentry *newentry;
677 afs_int32 releasetype;
678 { struct ubik_trans *trans;
679 afs_int32 blockindex, errorcode, typeindex;
681 int hashVol[MAXTYPES];
682 struct nvlentry tentry;
684 COUNT_REQ (VLREPLACEENTRYN);
685 for(typeindex = 0; typeindex < MAXTYPES; typeindex++)
686 hashVol[typeindex] = 0;
688 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
691 if (errorcode = check_nvldbentry(newentry))
694 if (voltype != -1 && InvalidVoltype(voltype))
695 END ( VL_BADVOLTYPE );
697 if (releasetype && InvalidReleasetype(releasetype))
698 END( VL_BADRELLOCKTYPE );
699 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
702 VLog(1, ("Replace Volume %d %s\n", volid, rxinfo(rxcall)));
703 /* find vlentry we're changing */
704 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
705 if (blockindex == 0) { /* entry not found */
706 if (!errorcode) errorcode = VL_NOENT;
710 /* check that we're not trying to change the RW vol ID */
711 if (newentry->volumeId[RWVOL] != tentry.volumeId[RWVOL]) {
712 ABORT( VL_BADENTRY );
715 /* unhash volid entries if they're disappearing or changing.
716 * Remember if we need to hash in the new value (we don't have to
717 * rehash if volid stays same */
718 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
719 if (tentry.volumeId[typeindex] != newentry->volumeId[typeindex]) {
720 if (tentry.volumeId[typeindex])
721 if (errorcode = UnhashVolid(trans, typeindex, blockindex,
725 /* we must rehash new id if the id is different and the ID is nonzero */
726 hashVol[typeindex] = 1; /* must rehash this guy if he exists */
730 /* Rehash volname if it changes */
731 if (strcmp(newentry->name, tentry.name)) { /* Name changes; redo hashing */
732 if (errorcode = UnhashVolname(trans, blockindex, &tentry)) {
738 /* after this, tentry is new entry, not old one. vldbentry_to_vlentry
739 doesn't touch hash chains */
740 if (errorcode = nvldbentry_to_vlentry(trans, newentry, &tentry)) {
744 for(typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
745 if (hashVol[typeindex] && tentry.volumeId[typeindex]) {
746 if (errorcode = HashVolid(trans, typeindex, blockindex, &tentry)) {
753 HashVolname(trans, blockindex, &tentry);
756 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
757 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
761 END (ubik_EndTrans(trans));
765 ubik_AbortTrans(trans);
768 osi_auditU (rxcall, VLReplaceVLEntryEvent, errorcode, AUD_LONG, volid, AUD_END);
773 /* Update a vldb entry (accessed thru its volume id). Almost all of the entry's fields can be modified in a single call by setting the appropriate bits in the Mask field in VldbUpdateentry. */
774 /* this routine may never have been tested; use replace entry instead unless you're brave */
775 afs_int32 SVL_UpdateEntry (rxcall, volid, voltype, updateentry, releasetype)
776 struct rx_call *rxcall;
779 afs_int32 releasetype;
780 struct VldbUpdateEntry *updateentry; /* Update entry copied here */
781 { struct ubik_trans *trans;
782 afs_int32 blockindex, errorcode;
783 struct nvlentry tentry;
785 COUNT_REQ (VLUPDATEENTRY);
786 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
788 if ((voltype != -1 ) && (InvalidVoltype(voltype)))
789 END( VL_BADVOLTYPE );
790 if (releasetype && InvalidReleasetype(releasetype))
791 END( VL_BADRELLOCKTYPE );
792 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
795 VLog(1, ("Update Volume %d %s\n", volid, rxinfo(rxcall)));
796 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
797 if (blockindex == 0) { /* entry not found */
798 if (!errorcode) errorcode = VL_NOENT;
802 /* Do the actual updating of the entry, tentry. */
803 if (errorcode = get_vldbupdateentry(trans, blockindex, updateentry, &tentry)) {
807 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
808 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
811 END(ubik_EndTrans(trans));
815 ubik_AbortTrans(trans);
818 osi_auditU (rxcall, VLUpdateEntryEvent, errorcode, AUD_LONG, volid, AUD_END);
823 afs_int32 SVL_UpdateEntryByName (rxcall, volname, updateentry, releasetype)
824 struct rx_call *rxcall;
826 afs_int32 releasetype;
827 struct VldbUpdateEntry *updateentry; /* Update entry copied here */
828 { struct ubik_trans *trans;
829 afs_int32 blockindex, errorcode;
830 struct nvlentry tentry;
832 COUNT_REQ (VLUPDATEENTRYBYNAME);
833 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
835 if (releasetype && InvalidReleasetype(releasetype))
836 END( VL_BADRELLOCKTYPE );
837 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
840 blockindex = FindByName(trans, volname, &tentry, &errorcode);
841 if (blockindex == 0) { /* entry not found */
842 if (!errorcode) errorcode = VL_NOENT;
846 /* Do the actual updating of the entry, tentry. */
847 if (errorcode = get_vldbupdateentry(trans, blockindex, updateentry, &tentry)) {
851 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
852 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
855 END(ubik_EndTrans(trans));
859 ubik_AbortTrans(trans);
862 osi_auditU (rxcall, VLUpdateEntryEvent, errorcode, AUD_LONG, -1, AUD_END);
867 /* Set a lock to the vldb entry for volid (of type voltype if not -1). */
868 afs_int32 SVL_SetLock (rxcall, volid, voltype, voloper)
869 struct rx_call *rxcall;
873 { afs_int32 timestamp, blockindex, errorcode;
874 struct ubik_trans *trans;
875 struct nvlentry tentry;
877 COUNT_REQ(VLSETLOCK);
878 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
880 if ((voltype != -1 ) && (InvalidVoltype(voltype)))
881 END( VL_BADVOLTYPE );
882 if (InvalidOperation(voloper))
883 END( VL_BADVOLOPER );
884 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
887 VLog(1, ("SetLock Volume %d %s\n", volid, rxinfo(rxcall)));
888 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
889 if (blockindex == NULLO) {
890 if (!errorcode) errorcode = VL_NOENT;
893 if (tentry.flags & VLDELETED) {
894 ABORT( VL_ENTDELETED );
896 timestamp = FT_ApproxTime();
898 /* Check if entry is already locked; note that we unlock any entry
899 * locked more than MAXLOCKTIME seconds */
900 if ((tentry.LockTimestamp)
901 && ((timestamp - tentry.LockTimestamp) < MAXLOCKTIME)) {
902 ABORT( VL_ENTRYLOCKED );
905 /* Consider it an unlocked entry: set current timestamp, caller
906 * and active vol operation */
907 tentry.LockTimestamp = timestamp;
908 tentry.LockAfsId = 0; /* Not implemented yet */
909 if (tentry.flags & VLOP_RELEASE) {
910 ABORT( VL_RERELEASE );
912 tentry.flags &= ~VLOP_ALLOPERS; /* Clear any possible older operation bit */
913 tentry.flags |= voloper;
915 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
918 END(ubik_EndTrans(trans));
922 ubik_AbortTrans(trans);
925 osi_auditU (rxcall, VLSetLockEvent, errorcode, AUD_LONG, volid, AUD_END);
930 /* Release an already locked vldb entry. Releasetype determines what
931 * fields (afsid and/or volume operation) will be cleared along with
932 * the lock time stamp. */
934 afs_int32 SVL_ReleaseLock (rxcall, volid, voltype, releasetype)
935 struct rx_call *rxcall;
938 afs_int32 releasetype;
939 { afs_int32 blockindex, errorcode;
940 struct ubik_trans *trans;
941 struct nvlentry tentry;
943 COUNT_REQ(VLRELEASELOCK);
944 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
946 if ((voltype != -1 ) && (InvalidVoltype(voltype)))
947 END( VL_BADVOLTYPE );
948 if (releasetype && InvalidReleasetype(releasetype))
949 END( VL_BADRELLOCKTYPE );
950 if (errorcode = Init_VLdbase(&trans, LOCKWRITE, this_op))
953 VLog(1, ("ReleaseLock Volume %d %s\n", volid, rxinfo(rxcall)));
954 blockindex = FindByID(trans, volid, voltype, &tentry, &errorcode);
955 if (blockindex == NULLO) {
956 if (!errorcode) errorcode = VL_NOENT;
959 if (tentry.flags & VLDELETED) {
960 ABORT( VL_ENTDELETED );
963 ReleaseEntry(&tentry, releasetype); /* Unlock the appropriate fields */
964 if (vlentrywrite(trans, blockindex, &tentry, sizeof(tentry))) {
967 END(ubik_EndTrans(trans));
971 ubik_AbortTrans(trans);
974 osi_auditU (rxcall, VLReleaseLockEvent, errorcode, AUD_LONG, volid, AUD_END);
979 /* ListEntry returns a single vldb entry, aentry, with offset previous_index; the remaining parameters (i.e. next_index) are used so that sequential calls to this routine will get the next (all) vldb entries. */
980 afs_int32 SVL_ListEntry (rxcall, previous_index, count, next_index, aentry)
981 struct rx_call *rxcall;
982 afs_int32 previous_index;
984 afs_int32 *next_index;
985 struct vldbentry *aentry;
987 struct ubik_trans *trans;
988 struct nvlentry tentry;
990 COUNT_REQ(VLLISTENTRY);
991 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
993 VLog(25, ("OListEntry index=%d %s\n", previous_index, rxinfo(rxcall)));
994 *next_index = NextEntry(trans, previous_index, &tentry, count);
996 vlentry_to_vldbentry(&tentry, aentry);
997 return(ubik_EndTrans(trans));
1000 /* ListEntry returns a single vldb entry, aentry, with offset previous_index; the remaining parameters (i.e. next_index) are used so that sequential calls to this routine will get the next (all) vldb entries. */
1001 afs_int32 SVL_ListEntryN (rxcall, previous_index, count, next_index, aentry)
1002 struct rx_call *rxcall;
1003 afs_int32 previous_index;
1005 afs_int32 *next_index;
1006 struct nvldbentry *aentry;
1008 struct ubik_trans *trans;
1009 struct nvlentry tentry;
1011 COUNT_REQ(VLLISTENTRYN);
1012 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1014 VLog(25, ("ListEntry index=%d %s\n", previous_index, rxinfo(rxcall)));
1015 *next_index = NextEntry(trans, previous_index, &tentry, count);
1017 vlentry_to_nvldbentry(&tentry, aentry);
1018 return(ubik_EndTrans(trans));
1022 /* Retrieves in vldbentries all vldb entries that match the specified attributes (by server number, partition, volume type, and flag); if volume id is specified then the associated list for that entry is returned. CAUTION: This could be a very expensive call since in most cases sequential search of all vldb entries is performed. */
1023 afs_int32 SVL_ListAttributes(rxcall, attributes, nentries, vldbentries)
1024 struct rx_call *rxcall;
1025 struct VldbListByAttributes *attributes;
1026 afs_int32 *nentries;
1027 bulkentries *vldbentries;
1028 { int errorcode, allocCount = 0;
1029 struct ubik_trans *trans;
1030 struct nvlentry tentry;
1031 struct vldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1034 COUNT_REQ (VLLISTATTRIBUTES);
1035 vldbentries->bulkentries_val = 0;
1036 vldbentries->bulkentries_len = *nentries = 0;
1037 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1039 allocCount = VLDBALLOCCOUNT;
1040 Vldbentry = VldbentryFirst = vldbentries->bulkentries_val = (vldbentry *)malloc(allocCount * sizeof(vldbentry));
1041 if (Vldbentry == NULL) {
1043 ubik_AbortTrans(trans);
1046 VldbentryLast = VldbentryFirst + allocCount;
1047 /* Handle the attribute by volume id totally separate of the rest (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!) */
1048 if (attributes->Mask & VLLIST_VOLUMEID) {
1049 afs_int32 blockindex;
1051 blockindex = FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1052 if (blockindex == 0) {
1053 if (!errorcode) errorcode = VL_NOENT;
1055 ubik_AbortTrans(trans);
1056 if(vldbentries->bulkentries_val)free((char *)vldbentries->bulkentries_val);
1057 vldbentries->bulkentries_val = 0;
1058 vldbentries->bulkentries_len = 0;
1061 if (errorcode = put_attributeentry(&Vldbentry, &VldbentryFirst, &VldbentryLast, vldbentries, &tentry, nentries, &allocCount)) {
1063 ubik_AbortTrans(trans);
1064 if(vldbentries->bulkentries_val)free((char *)vldbentries->bulkentries_val);
1065 vldbentries->bulkentries_val = 0;
1066 vldbentries->bulkentries_len = 0;
1067 return VL_SIZEEXCEEDED;
1070 afs_int32 nextblockindex=0, count=0, k, match=0;
1071 while (nextblockindex = NextEntry(trans, nextblockindex, &tentry, &count)) {
1072 if (++pollcount > 50) {
1077 if (attributes->Mask & VLLIST_SERVER) {
1079 if ((serverindex = IpAddrToRelAddr(attributes->server, (struct ubik_trans *) 0)) == -1) continue;
1080 for (k=0; k<OMAXNSERVERS;k++) {
1081 if (tentry.serverNumber[k] == BADSERVERID) break;
1082 if (tentry.serverNumber[k] == serverindex) {
1087 if (!match) continue;
1089 if (attributes->Mask & VLLIST_PARTITION) {
1091 if (tentry.serverPartition[k] != attributes->partition) continue;
1093 for (k=0; k<OMAXNSERVERS;k++) {
1094 if (tentry.serverNumber[k] == BADSERVERID) break;
1095 if (tentry.serverPartition[k] == attributes->partition) {
1100 if (!match) continue;
1104 if (attributes->Mask & VLLIST_FLAG) {
1105 if (!(tentry.flags & attributes->flag)) continue;
1107 if (errorcode = put_attributeentry(&Vldbentry, &VldbentryFirst, &VldbentryLast, vldbentries, &tentry, nentries, &allocCount)) {
1109 ubik_AbortTrans(trans);
1110 if(vldbentries->bulkentries_val)free((char *)vldbentries->bulkentries_val);
1111 vldbentries->bulkentries_val = 0;
1112 vldbentries->bulkentries_len = 0;
1117 if (vldbentries->bulkentries_len && (allocCount > vldbentries->bulkentries_len)) {
1119 vldbentries->bulkentries_val = (vldbentry *) realloc(vldbentries->bulkentries_val, vldbentries->bulkentries_len * sizeof(vldbentry));
1120 if (vldbentries->bulkentries_val == NULL) {
1122 ubik_AbortTrans(trans);
1126 VLog(5, ("ListAttrs nentries=%d %s\n", vldbentries->bulkentries_len, rxinfo(rxcall)));
1127 return(ubik_EndTrans(trans));
1130 afs_int32 SVL_ListAttributesN(rxcall, attributes, nentries, vldbentries)
1131 struct rx_call *rxcall;
1132 struct VldbListByAttributes *attributes;
1133 afs_int32 *nentries;
1134 nbulkentries *vldbentries;
1135 { int errorcode, allocCount = 0;
1136 struct ubik_trans *trans;
1137 struct nvlentry tentry;
1138 struct nvldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1141 COUNT_REQ (VLLISTATTRIBUTESN);
1142 vldbentries->nbulkentries_val = 0;
1143 vldbentries->nbulkentries_len = *nentries = 0;
1144 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1146 allocCount = VLDBALLOCCOUNT;
1147 Vldbentry = VldbentryFirst = vldbentries->nbulkentries_val = (nvldbentry *)malloc(allocCount * sizeof(nvldbentry));
1148 if (Vldbentry == NULL) {
1150 ubik_AbortTrans(trans);
1153 VldbentryLast = VldbentryFirst + allocCount;
1154 /* Handle the attribute by volume id totally separate of the rest (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!) */
1155 if (attributes->Mask & VLLIST_VOLUMEID) {
1156 afs_int32 blockindex;
1158 blockindex = FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1159 if (blockindex == 0) {
1160 if (!errorcode) errorcode = VL_NOENT;
1162 ubik_AbortTrans(trans);
1163 if(vldbentries->nbulkentries_val)free((char *)vldbentries->nbulkentries_val);
1164 vldbentries->nbulkentries_val = 0;
1165 vldbentries->nbulkentries_len = 0;
1168 if (errorcode = put_nattributeentry(&Vldbentry, &VldbentryFirst, &VldbentryLast, vldbentries,
1169 &tentry, 0, 0, nentries, &allocCount)) {
1171 ubik_AbortTrans(trans);
1172 if(vldbentries->nbulkentries_val)free((char *)vldbentries->nbulkentries_val);
1173 vldbentries->nbulkentries_val = 0;
1174 vldbentries->nbulkentries_len = 0;
1175 return VL_SIZEEXCEEDED;
1178 afs_int32 nextblockindex=0, count=0, k, match=0;
1179 while (nextblockindex = NextEntry(trans, nextblockindex, &tentry, &count)) {
1180 if (++pollcount > 50) {
1186 if (attributes->Mask & VLLIST_SERVER) {
1188 if ((serverindex = IpAddrToRelAddr(attributes->server, (struct ubik_trans *) 0)) == -1) continue;
1189 for (k=0; k<NMAXNSERVERS;k++) {
1190 if (tentry.serverNumber[k] == BADSERVERID) break;
1191 if (tentry.serverNumber[k] == serverindex) {
1196 if (!match) continue;
1198 if (attributes->Mask & VLLIST_PARTITION) {
1200 if (tentry.serverPartition[k] != attributes->partition) continue;
1202 for (k=0; k<NMAXNSERVERS;k++) {
1203 if (tentry.serverNumber[k] == BADSERVERID) break;
1204 if (tentry.serverPartition[k] == attributes->partition) {
1209 if (!match) continue;
1213 if (attributes->Mask & VLLIST_FLAG) {
1214 if (!(tentry.flags & attributes->flag)) continue;
1216 if (errorcode = put_nattributeentry(&Vldbentry, &VldbentryFirst, &VldbentryLast,
1217 vldbentries, &tentry, 0, 0, nentries, &allocCount)) {
1219 ubik_AbortTrans(trans);
1220 if(vldbentries->nbulkentries_val)free((char *)vldbentries->nbulkentries_val);
1221 vldbentries->nbulkentries_val = 0;
1222 vldbentries->nbulkentries_len = 0;
1227 if (vldbentries->nbulkentries_len && (allocCount > vldbentries->nbulkentries_len)) {
1229 vldbentries->nbulkentries_val = (nvldbentry *) realloc(vldbentries->nbulkentries_val,
1230 vldbentries->nbulkentries_len * sizeof(nvldbentry));
1231 if (vldbentries->nbulkentries_val == NULL) {
1233 ubik_AbortTrans(trans);
1237 VLog(5, ("NListAttrs nentries=%d %s\n", vldbentries->nbulkentries_len, rxinfo(rxcall)));
1238 return(ubik_EndTrans(trans));
1242 afs_int32 SVL_ListAttributesN2(rxcall, attributes, name, startindex, nentries, vldbentries, nextstartindex)
1243 struct rx_call *rxcall;
1244 struct VldbListByAttributes *attributes;
1245 char * name; /* Wildcarded volume name */
1246 afs_int32 startindex;
1247 afs_int32 *nentries;
1248 nbulkentries *vldbentries;
1249 afs_int32 *nextstartindex;
1251 int errorcode=0, maxCount=VLDBALLOCCOUNT;
1252 struct ubik_trans *trans;
1253 struct nvlentry tentry;
1254 struct nvldbentry *Vldbentry=0, *VldbentryFirst=0, *VldbentryLast=0;
1255 afs_int32 blockindex=0, count=0, k, match, matchindex;
1256 int serverindex=-1; /* no server found */
1257 int findserver=0, findpartition=0, findflag=0, findname=0;
1260 int namematchRWBK, namematchRO, thismatch, matchtype;
1261 char volumename[VL_MAXNAMELEN];
1263 COUNT_REQ (VLLISTATTRIBUTESN2);
1264 vldbentries->nbulkentries_val = 0;
1265 vldbentries->nbulkentries_len = 0;
1267 *nextstartindex = -1;
1269 errorcode = Init_VLdbase(&trans, LOCKREAD, this_op);
1270 if (errorcode) return errorcode;
1272 Vldbentry = VldbentryFirst = vldbentries->nbulkentries_val = (nvldbentry *)malloc(maxCount * sizeof(nvldbentry));
1273 if (Vldbentry == NULL) {
1275 ubik_AbortTrans(trans);
1279 VldbentryLast = VldbentryFirst + maxCount;
1281 /* Handle the attribute by volume id totally separate of the rest
1282 * (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!)
1284 if (attributes->Mask & VLLIST_VOLUMEID) {
1285 blockindex = FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1286 if (blockindex == 0) {
1287 if (!errorcode) errorcode = VL_NOENT;
1289 errorcode = put_nattributeentry(&Vldbentry, &VldbentryFirst, &VldbentryLast,
1290 vldbentries, &tentry, 0, 0, nentries, &maxCount);
1291 if (errorcode) goto done;
1295 /* Search each entry in the database and return all entries
1296 * that match the request. It checks volumename (with
1297 * wildcarding), entry flags, server, and partition.
1300 /* Get the server index for matching server address */
1301 if (attributes->Mask & VLLIST_SERVER) {
1302 serverindex = IpAddrToRelAddr(attributes->server, (struct ubik_trans *)0);
1303 if (serverindex == -1) goto done;
1306 findpartition = ((attributes->Mask & VLLIST_PARTITION) ? 1 : 0);
1307 findflag = ((attributes->Mask & VLLIST_FLAG) ? 1 : 0);
1308 if (name && (strcmp(name,".*") != 0) && (strcmp(name,"") != 0)) {
1309 sprintf(volumename, "^%s$", name);
1310 t = (char *)re_comp(volumename);
1312 errorcode = VL_BADNAME;
1318 /* Read each entry and see if it is the one we want */
1319 blockindex = startindex;
1320 while (blockindex = NextEntry(trans, blockindex, &tentry, &count)) {
1321 if (++pollcount > 50) {
1326 /* Step through each server index searching for a match.
1327 * Match to an existing RW, BK, or RO volume name (preference
1328 * is in this order). Remember which index we matched against.
1330 namematchRWBK = namematchRO = 0; /* 0->notTried; 1->match; 2->noMatch */
1332 for (k=0; (k<NMAXNSERVERS && (tentry.serverNumber[k]!=BADSERVERID)); k++) {
1333 thismatch = 0; /* does this index match */
1335 /* Match against the RW or BK volume name. Remember
1336 * results in namematchRWBK. Prefer RW over BK.
1338 if (tentry.serverFlags[k] & VLSF_RWVOL) {
1339 /* Does the name match the RW name */
1340 if (tentry.flags & VLF_RWEXISTS) {
1342 sprintf(volumename, "%s", tentry.name);
1343 if (re_exec(volumename)) {
1344 thismatch = VLSF_RWVOL;
1347 thismatch = VLSF_RWVOL;
1351 /* Does the name match the BK name */
1352 if (!thismatch && (tentry.flags & VLF_BACKEXISTS)) {
1354 sprintf(volumename, "%s.backup", tentry.name);
1355 if (re_exec(volumename)) {
1356 thismatch = VLSF_BACKVOL;
1359 thismatch = VLSF_BACKVOL;
1363 namematchRWBK = (thismatch?1:2);
1366 /* Match with the RO volume name. Compare once and
1367 * remember results in namematchRO. Note that this will
1368 * pick up entries marked NEWREPSITEs and DONTUSE.
1371 if (tentry.flags & VLF_ROEXISTS) {
1374 thismatch = ((namematchRO == 1)?VLSF_ROVOL:0);
1376 sprintf(volumename, "%s.readonly", tentry.name);
1377 if (re_exec(volumename))
1378 thismatch = VLSF_ROVOL;
1381 thismatch = VLSF_ROVOL;
1384 namematchRO = (thismatch?1:2);
1387 /* Is there a server match */
1388 if (thismatch && findserver &&
1389 (tentry.serverNumber[k] != serverindex))
1392 /* Is there a partition match */
1393 if (thismatch && findpartition &&
1394 (tentry.serverPartition[k] != attributes->partition))
1397 /* Is there a flag match */
1398 if (thismatch && findflag && !(tentry.flags & attributes->flag))
1401 /* We found a match. Remember the index, and type */
1405 matchtype = thismatch;
1408 /* Since we prefer RW and BK volume matches over RO matches,
1409 * if we have already checked the RWBK name, then we already
1410 * found the best match and so end the search.
1412 * If we tried matching against the RW, BK, and RO volume names
1413 * and both failed, then we end the search (none will match).
1415 if ( (match && namematchRWBK) ||
1416 ((namematchRWBK==2) && (namematchRO==2)) )
1420 /* Passed all the tests. Take it */
1422 errorcode = put_nattributeentry(&Vldbentry,
1423 &VldbentryFirst, &VldbentryLast,
1424 vldbentries, &tentry, matchtype, matchindex,
1425 nentries, &maxCount);
1426 if (errorcode) goto done;
1428 if (*nentries >= maxCount) break; /* collected the max */
1431 *nextstartindex = (blockindex ? blockindex : -1);
1437 ubik_AbortTrans(trans);
1438 if (vldbentries->nbulkentries_val)
1439 free((char *)vldbentries->nbulkentries_val);
1440 vldbentries->nbulkentries_val = 0;
1441 vldbentries->nbulkentries_len = 0;
1442 *nextstartindex = -1;
1445 VLog(5, ("N2ListAttrs nentries=%d %s\n", vldbentries->nbulkentries_len, rxinfo(rxcall)));
1446 return(ubik_EndTrans(trans));
1451 /* Retrieves in vldbentries all vldb entries that match the specified
1452 * attributes (by server number, partition, volume type, and flag); if
1453 * volume id is specified then the associated list for that entry is
1454 * returned. CAUTION: This could be a very expensive call since in most
1455 * cases sequential search of all vldb entries is performed.
1457 afs_int32 SVL_LinkedList(rxcall, attributes, nentries, vldbentries)
1458 struct rx_call *rxcall;
1459 struct VldbListByAttributes *attributes;
1460 afs_int32 *nentries;
1461 vldb_list *vldbentries;
1464 struct ubik_trans *trans;
1465 struct nvlentry tentry;
1466 vldblist vllist, *vllistptr;
1467 afs_int32 blockindex, count, k, match;
1471 COUNT_REQ (VLLINKEDLIST);
1472 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1476 vldbentries->node = NULL;
1477 vllistptr = &vldbentries->node;
1479 /* List by volumeid */
1480 if (attributes->Mask & VLLIST_VOLUMEID) {
1481 blockindex = FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1484 ubik_AbortTrans(trans);
1485 return (errorcode ? errorcode : VL_NOENT);
1488 vllist = (single_vldbentry *) malloc(sizeof(single_vldbentry));
1489 if (vllist == NULL) {
1491 ubik_AbortTrans(trans);
1494 vlentry_to_vldbentry(&tentry, &vllist->VldbEntry);
1495 vllist->next_vldb = NULL;
1497 *vllistptr = vllist; /* Thread onto list */
1498 vllistptr = &vllist->next_vldb;
1502 /* Search by server, partition, and flags */
1504 for (blockindex = NextEntry(trans, 0, &tentry, &count);
1506 blockindex = NextEntry(trans, blockindex, &tentry, &count)) {
1509 if (++pollcount > 50) {
1514 /* Does this volume exist on the desired server */
1515 if (attributes->Mask & VLLIST_SERVER) {
1516 serverindex = IpAddrToRelAddr(attributes->server, (struct ubik_trans *)0);
1517 if (serverindex == -1) continue;
1518 for (k=0; k < OMAXNSERVERS; k++) {
1519 if (tentry.serverNumber[k] == BADSERVERID) break;
1520 if (tentry.serverNumber[k] == serverindex) {
1525 if (!match) continue;
1528 /* Does this volume exist on the desired partition */
1529 if (attributes->Mask & VLLIST_PARTITION) {
1531 if (tentry.serverPartition[k] != attributes->partition)
1534 for (k=0; k < OMAXNSERVERS; k++) {
1535 if (tentry.serverNumber[k] == BADSERVERID) break;
1536 if (tentry.serverPartition[k] == attributes->partition) {
1542 if (!match) continue;
1545 /* Does this volume have the desired flags */
1546 if (attributes->Mask & VLLIST_FLAG) {
1547 if (!(tentry.flags & attributes->flag))
1551 vllist = (single_vldbentry *) malloc(sizeof(single_vldbentry));
1552 if (vllist == NULL) {
1554 ubik_AbortTrans(trans);
1557 vlentry_to_vldbentry(&tentry, &vllist->VldbEntry);
1558 vllist->next_vldb = NULL;
1560 *vllistptr = vllist; /* Thread onto list */
1561 vllistptr = &vllist->next_vldb;
1563 if (smallMem && (*nentries >= VLDBALLOCCOUNT)) {
1565 ubik_AbortTrans(trans);
1566 return VL_SIZEEXCEEDED;
1571 return(ubik_EndTrans(trans));
1574 afs_int32 SVL_LinkedListN(rxcall, attributes, nentries, vldbentries)
1575 struct rx_call *rxcall;
1576 struct VldbListByAttributes *attributes;
1577 afs_int32 *nentries;
1578 nvldb_list *vldbentries;
1581 struct ubik_trans *trans;
1582 struct nvlentry tentry;
1583 nvldblist vllist, *vllistptr;
1584 afs_int32 blockindex, count, k, match;
1588 COUNT_REQ (VLLINKEDLISTN);
1589 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1593 vldbentries->node = NULL;
1594 vllistptr = &vldbentries->node;
1596 /* List by volumeid */
1597 if (attributes->Mask & VLLIST_VOLUMEID) {
1598 blockindex = FindByID(trans, attributes->volumeid, -1, &tentry, &errorcode);
1601 ubik_AbortTrans(trans);
1602 return (errorcode ? errorcode : VL_NOENT);
1605 vllist = (single_nvldbentry *) malloc(sizeof(single_nvldbentry));
1606 if (vllist == NULL) {
1608 ubik_AbortTrans(trans);
1611 vlentry_to_nvldbentry(&tentry, &vllist->VldbEntry);
1612 vllist->next_vldb = NULL;
1614 *vllistptr = vllist; /* Thread onto list */
1615 vllistptr = &vllist->next_vldb;
1619 /* Search by server, partition, and flags */
1621 for (blockindex = NextEntry(trans, 0, &tentry, &count);
1623 blockindex = NextEntry(trans, blockindex, &tentry, &count)) {
1626 if (++pollcount > 50) {
1631 /* Does this volume exist on the desired server */
1632 if (attributes->Mask & VLLIST_SERVER) {
1633 serverindex = IpAddrToRelAddr(attributes->server, (struct ubik_trans *)0);
1634 if (serverindex == -1) continue;
1635 for (k=0; k < NMAXNSERVERS; k++) {
1636 if (tentry.serverNumber[k] == BADSERVERID) break;
1637 if (tentry.serverNumber[k] == serverindex) {
1642 if (!match) continue;
1645 /* Does this volume exist on the desired partition */
1646 if (attributes->Mask & VLLIST_PARTITION) {
1648 if (tentry.serverPartition[k] != attributes->partition)
1651 for (k=0; k < NMAXNSERVERS; k++) {
1652 if (tentry.serverNumber[k] == BADSERVERID) break;
1653 if (tentry.serverPartition[k] == attributes->partition) {
1659 if (!match) continue;
1662 /* Does this volume have the desired flags */
1663 if (attributes->Mask & VLLIST_FLAG) {
1664 if (!(tentry.flags & attributes->flag))
1668 vllist = (single_nvldbentry *) malloc(sizeof(single_nvldbentry));
1669 if (vllist == NULL) {
1671 ubik_AbortTrans(trans);
1674 vlentry_to_nvldbentry(&tentry, &vllist->VldbEntry);
1675 vllist->next_vldb = NULL;
1677 *vllistptr = vllist; /* Thread onto list */
1678 vllistptr = &vllist->next_vldb;
1680 if (smallMem && (*nentries >= VLDBALLOCCOUNT)) {
1682 ubik_AbortTrans(trans);
1683 return VL_SIZEEXCEEDED;
1688 return(ubik_EndTrans(trans));
1691 /* Get back vldb header statistics (allocs, frees, maxvolumeid, totalentries, etc) and dynamic statistics (number of requests and/or aborts per remote procedure call, etc) */
1692 afs_int32 SVL_GetStats(rxcall, stats, vital_header)
1693 struct rx_call *rxcall;
1695 vital_vlheader *vital_header;
1696 { register afs_int32 errorcode;
1697 struct ubik_trans *trans;
1699 COUNT_REQ(VLGETSTATS);
1701 /* Allow users to get statistics freely */
1702 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) /* Must be in 'UserList' to use */
1705 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1707 VLog(5, ("GetStats %\n", rxinfo(rxcall)));
1708 memcpy((char *) vital_header, (char *)&cheader.vital_header, sizeof(vital_vlheader));
1709 memcpy((char *) stats, (char *)&dynamic_statistics, sizeof(vldstats));
1710 return(ubik_EndTrans(trans));
1713 /* Get the list of file server addresses from the VLDB. Currently it's pretty
1714 * easy to do. In the future, it might require a little bit of grunging
1715 * through the VLDB, but that's life.
1717 afs_int32 SVL_GetAddrs(rxcall, Handle, spare2, spare3, nentries, addrsp)
1718 struct rx_call *rxcall;
1719 afs_int32 Handle, spare2;
1720 struct VLCallBack *spare3;
1721 afs_int32 *nentries;
1723 { register afs_int32 errorcode;
1724 struct ubik_trans *trans;
1728 COUNT_REQ(VLGETADDRS);
1729 addrsp->bulkaddrs_len = *nentries = 0;
1730 addrsp->bulkaddrs_val = 0;
1731 memset(spare3, 0, sizeof (struct VLCallBack));
1733 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
1736 VLog(5, ("GetAddrs\n"));
1737 addrsp->bulkaddrs_val = taddrp = (afs_uint32 *)malloc(sizeof(afs_int32)*(MAXSERVERID+1));
1738 nservers= *nentries = addrsp->bulkaddrs_len = 0;
1742 ubik_AbortTrans(trans);
1746 for (i=0; i <= MAXSERVERID; i++) {
1747 if (*taddrp = ntohl(cheader.IpMappedAddr[i])) {
1753 addrsp->bulkaddrs_len = *nentries = nservers;
1754 return(ubik_EndTrans(trans));
1757 #define PADDR(addr) printf("%d.%d.%d.%d", (addr>>24)&0xff, (addr>>16)&0xff, (addr>>8) &0xff, addr&0xff);
1759 afs_int32 SVL_RegisterAddrs(rxcall, uuidp, spare1, addrsp)
1760 struct rx_call *rxcall;
1766 struct ubik_trans *trans;
1767 int cnt, h, i, j, k, m, base, index;
1768 struct extentaddr *exp = 0, *tex;
1770 afs_uint32 addrs[VL_MAXIPADDRS_PERMH];
1772 int count, willChangeEntry, foundUuidEntry, willReplaceCnt;
1773 int WillReplaceEntry, WillChange[MAXSERVERID+1], FoundUuid, ReplaceEntry;
1776 COUNT_REQ(VLREGADDR);
1777 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
1779 if (code = Init_VLdbase(&trans, LOCKWRITE, this_op))
1782 /* Eliminate duplicates from IP address list */
1783 for (k=0, cnt=0; k<addrsp->bulkaddrs_len; k++) {
1784 if (addrsp->bulkaddrs_val[k] == 0)
1786 for (m=0; m < cnt; m++) {
1787 if (addrs[m] == addrsp->bulkaddrs_val[k])
1791 if (m == VL_MAXIPADDRS_PERMH) {
1792 VLog(0, ("Number of addresses exceeds %d. Cannot register IP addr 0x%x in VLDB\n",
1793 VL_MAXIPADDRS_PERMH, addrsp->bulkaddrs_val[k]));
1795 addrs[m] = addrsp->bulkaddrs_val[k];
1801 ubik_AbortTrans(trans);
1802 return VL_INDEXERANGE;
1808 /* For each server registered within the VLDB */
1809 for (srvidx=0; srvidx <= MAXSERVERID;srvidx++) {
1810 willChangeEntry = 0;
1811 WillReplaceEntry = 1;
1812 if ((HostAddress[srvidx] & 0xff000000) == 0xff000000) {
1813 /* The server is registered as a multihomed */
1814 base = (HostAddress[srvidx] >> 16) & 0xff;
1815 index = HostAddress[srvidx] & 0x0000ffff;
1816 if (base >= VL_MAX_ADDREXTBLKS) {
1817 VLog(0, ("Internal error: Multihome extent base is too large. Base %d index %d\n",
1821 if (index >= VL_MHSRV_PERBLK) {
1822 VLog(0, ("Internal error: Multihome extent index is too large. Base %d index %d\n",
1826 if (!ex_addr[base]) {
1827 VLog(0, ("Internal error: Multihome extent does not exist. Base %d\n", base));
1831 /* See if the addresses to register will change this server entry */
1832 exp = &ex_addr[base][index];
1833 tuuid = exp->ex_hostuuid;
1834 afs_ntohuuid(&tuuid);
1835 if (afs_uuid_equal(uuidp, &tuuid)) {
1839 for (mhidx=0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
1840 if (!exp->ex_addrs[mhidx]) continue;
1841 for (k=0; k<cnt; k++) {
1842 if (ntohl(exp->ex_addrs[mhidx]) == addrs[k]) {
1843 willChangeEntry = 1;
1844 WillChange[count] = srvidx;
1848 if (k >= cnt) WillReplaceEntry = 0;
1852 /* The server is not registered as a multihomed.
1853 * See if the addresses to register will replace this server entry.
1855 for (k=0; k<cnt; k++) {
1856 if (HostAddress[srvidx] == addrs[k]) {
1857 willChangeEntry = 1;
1858 WillChange[count] = srvidx;
1859 WillReplaceEntry = 1;
1864 if (willChangeEntry) {
1865 if (WillReplaceEntry) {
1867 ReplaceEntry = srvidx;
1873 /* If we found the uuid in the VLDB and if we are replacing another
1874 * entire entry, then complain and fail. Also, if we did not find
1875 * the uuid in the VLDB and the IP addresses being registered was
1876 * found in more than one other entry, then we don't know which one
1877 * to replace and will complain and fail.
1879 if ( ( foundUuidEntry && (willReplaceCnt > 0)) ||
1880 (!foundUuidEntry && (count > 1)) ) {
1881 VLog(0, ("The following fileserver is being registered in the VLDB:\n"));
1883 for (k=0; k<cnt; k++) {
1884 if (k>0) printf(" ");
1889 if (foundUuidEntry) {
1890 printf(" It would have replaced the existing VLDB server entry:\n");
1891 printf(" entry %d: [", FoundUuid);
1892 base = (HostAddress[FoundUuid] >> 16) & 0xff;
1893 index = HostAddress[FoundUuid] & 0x0000ffff;
1894 exp = &ex_addr[base][index];
1895 for (mhidx=0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
1896 if (!exp->ex_addrs[mhidx]) continue;
1897 if (mhidx > 0) printf(" ");
1898 PADDR(ntohl(exp->ex_addrs[mhidx]));
1903 if (count == 1) printf(" Yet another VLDB server entry exists:\n");
1904 else printf(" Yet other VLDB server entries exist:\n");
1905 for (j=0; j<count; j++) {
1906 srvidx = WillChange[j];
1907 printf(" entry %d: ", srvidx);
1908 if ((HostAddress[srvidx] & 0xff000000) == 0xff000000) {
1910 base = (HostAddress[srvidx] >> 16) & 0xff;
1911 index = HostAddress[srvidx] & 0x0000ffff;
1912 exp = &ex_addr[base][index];
1913 for (mhidx=0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
1914 if (!exp->ex_addrs[mhidx]) continue;
1915 if (mhidx > 0) printf(" ");
1916 PADDR(ntohl(exp->ex_addrs[mhidx]));
1920 PADDR(HostAddress[srvidx]);
1926 printf(" You must 'vos changeaddr' this other server entry\n");
1928 printf(" You must 'vos changeaddr' these other server entries\n");
1930 printf(" and/or remove the sysid file from the registering fileserver\n");
1931 printf(" before the fileserver can be registered in the VLDB.\n");
1933 ubik_AbortTrans(trans);
1934 return VL_MULTIPADDR;
1937 /* Passed the checks. Now find and update the existing mh entry, or create
1940 if (foundUuidEntry) {
1941 /* Found the entry with same uuid. See if we need to change it */
1944 fbase = (HostAddress[FoundUuid] >> 16) & 0xff;
1945 index = HostAddress[FoundUuid] & 0x0000ffff;
1946 exp = &ex_addr[fbase][index];
1948 /* Determine if the entry has changed */
1949 for (k=0; ((k < cnt) && !change); k++) {
1950 if (ntohl(exp->ex_addrs[k]) != addrs[k])
1953 for (; ((k < VL_MAXIPADDRS_PERMH) && !change); k++) {
1954 if (exp->ex_addrs[k] != 0)
1958 return(ubik_EndTrans(trans));
1962 VLog(0, ("The following fileserver is being registered in the VLDB:\n"));
1964 for (k=0; k<cnt; k++) {
1965 if (k>0) printf(" ");
1970 if (foundUuidEntry) {
1971 printf(" It will replace the following existing entry in the VLDB (same uuid):\n");
1972 printf(" entry %d: [", FoundUuid);
1973 for (k=0; k < VL_MAXIPADDRS_PERMH; k++) {
1974 if (exp->ex_addrs[k] == 0) continue;
1975 if (k>0) printf(" ");
1976 PADDR(ntohl(exp->ex_addrs[k]));
1980 else if (willReplaceCnt || (count == 1)) {
1981 /* If we are not replacing an entry and there is only one entry to change,
1982 * then we will replace that entry.
1984 if (!willReplaceCnt) {
1985 ReplaceEntry = WillChange[0];
1989 /* Have an entry that needs to be replaced */
1990 if ((HostAddress[ReplaceEntry] & 0xff000000) == 0xff000000) {
1991 fbase = (HostAddress[ReplaceEntry] >> 16) & 0xff;
1992 index = HostAddress[ReplaceEntry] & 0x0000ffff;
1993 exp = &ex_addr[fbase][index];
1995 printf(" It will replace the following existing entry in the VLDB (new uuid):\n");
1996 printf(" entry %d: [", ReplaceEntry);
1997 for (k=0; k < VL_MAXIPADDRS_PERMH; k++) {
1998 if (exp->ex_addrs[k] == 0) continue;
1999 if (k>0) printf(" ");
2000 PADDR(ntohl(exp->ex_addrs[k]));
2004 /* Not a mh entry. So we have to create a new mh entry and
2005 * put it on the ReplaceEntry slot of the HostAddress array.
2007 printf(" It will replace existing entry %d, ", ReplaceEntry);
2008 PADDR(HostAddress[ReplaceEntry]);
2009 printf(", in the VLDB (new uuid):\n");
2011 code = FindExtentBlock(trans, uuidp, 1, ReplaceEntry, &exp, &fbase);
2013 ubik_AbortTrans(trans);
2014 return (code ? code : VL_IO);
2018 /* There is no entry for this server, must create a new mh entry as
2019 * well as use a new slot of the HostAddress array.
2021 printf(" It will create a new entry in the VLDB.\n");
2022 code = FindExtentBlock(trans, uuidp, 1, -1, &exp, &fbase);
2024 ubik_AbortTrans(trans);
2025 return (code ? code : VL_IO);
2029 /* Now we have a mh entry to fill in. Update the uuid, bump the
2030 * uniquifier, and fill in its IP addresses.
2033 afs_htonuuid(&tuuid);
2034 exp->ex_hostuuid = tuuid;
2035 exp->ex_uniquifier = htonl(ntohl(exp->ex_uniquifier)+1);
2036 for (k=0; k < cnt; k++) {
2037 exp->ex_addrs[k] = htonl(addrs[k]);
2039 for (; k < VL_MAXIPADDRS_PERMH; k++) {
2040 exp->ex_addrs[k] = 0;
2043 /* Write the new mh entry out */
2044 if (vlwrite(trans, DOFFSET(ntohl(ex_addr[0]->ex_contaddrs[fbase]),
2045 (char *)ex_addr[fbase], (char *)exp),
2046 (char *)exp, sizeof(*exp))) {
2047 ubik_AbortTrans(trans);
2051 /* Remove any common addresses from other mh entres. We know these entries
2052 * are being changed and not replaced so they are mh entries.
2055 for (i=0; i<count; i++) {
2058 /* Skip the entry we replaced */
2059 if (willReplaceCnt && (WillChange[i] == ReplaceEntry))
2062 base = (HostAddress[WillChange[i]] >> 16) & 0xff;
2063 index = HostAddress[WillChange[i]] & 0x0000ffff;
2064 tex = &ex_addr[fbase][index];
2067 printf(" The following existing entries in the VLDB will be updated:\n");
2069 printf(" entry %d: [", WillChange[i]);
2070 for (h=j=0; j < VL_MAXIPADDRS_PERMH; j++) {
2071 if (tex->ex_addrs[j]) {
2072 if (j>0) printf(" ");
2073 PADDR(ntohl(tex->ex_addrs[j]));
2076 for (k=0; k<cnt; k++) {
2077 if (ntohl(tex->ex_addrs[j]) == addrs[k]) break;
2080 /* Not found, so we keep it */
2081 tex->ex_addrs[h] = tex->ex_addrs[j];
2085 for (j=h; j < VL_MAXIPADDRS_PERMH; j++) {
2086 tex->ex_addrs[j] = 0; /* zero rest of mh entry */
2090 /* Write out the modified mh entry */
2091 tex->ex_uniquifier = htonl(ntohl(tex->ex_uniquifier)+1);
2092 doff=DOFFSET(ntohl(ex_addr[0]->ex_contaddrs[base]),
2093 (char *)ex_addr[base], (char *)tex);
2094 if (vlwrite(trans, doff, (char*)tex, sizeof(*tex))) {
2095 ubik_AbortTrans(trans);
2100 return(ubik_EndTrans(trans));
2103 afs_int32 SVL_GetAddrsU(rxcall, attributes, uuidpo, uniquifier, nentries, addrsp)
2104 struct rx_call *rxcall;
2105 struct ListAddrByAttributes *attributes;
2107 afs_int32 *uniquifier, *nentries;
2109 { register afs_int32 errorcode, index=-1, offset;
2110 struct ubik_trans *trans;
2111 int nservers, i, j, base=0;
2112 struct extentaddr *exp=0;
2114 afs_uint32 *taddrp, taddr;
2116 COUNT_REQ(VLGETADDRSU);
2117 addrsp->bulkaddrs_len = *nentries = 0;
2118 addrsp->bulkaddrs_val = 0;
2119 VLog(5, ("GetAddrsU %s\n", rxinfo(rxcall)));
2120 if (errorcode = Init_VLdbase(&trans, LOCKREAD, this_op))
2123 if (attributes->Mask & VLADDR_IPADDR) {
2124 if (attributes->Mask & (VLADDR_INDEX|VLADDR_UUID)) {
2125 ubik_AbortTrans(trans);
2128 for (base = 0; base < VL_MAX_ADDREXTBLKS; base++) {
2131 for (i = 1; i < VL_MHSRV_PERBLK; i++) {
2132 exp = &ex_addr[base][i];
2133 tuuid = exp->ex_hostuuid;
2134 afs_ntohuuid(&tuuid);
2135 if (afs_uuid_is_nil(&tuuid)) continue;
2136 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2137 if (exp->ex_addrs[j] && (ntohl(exp->ex_addrs[j]) == attributes->ipaddr)) {
2141 if (j < VL_MAXIPADDRS_PERMH) break;
2143 if (i < VL_MHSRV_PERBLK) break;
2145 if (base >= VL_MAX_ADDREXTBLKS) {
2146 ubik_AbortTrans(trans);
2149 } else if (attributes->Mask & VLADDR_INDEX) {
2150 if (attributes->Mask & (VLADDR_IPADDR|VLADDR_UUID)) {
2151 ubik_AbortTrans(trans);
2154 index = attributes->index;
2155 if (index < 1 || index >= (VL_MAX_ADDREXTBLKS*VL_MHSRV_PERBLK)) {
2156 ubik_AbortTrans(trans);
2157 return VL_INDEXERANGE;
2159 base = index / VL_MHSRV_PERBLK;
2160 offset = index % VL_MHSRV_PERBLK;
2162 ubik_AbortTrans(trans);
2165 if (!ex_addr[base]) {
2166 ubik_AbortTrans(trans);
2167 return VL_INDEXERANGE;
2169 exp = &ex_addr[base][offset];
2170 } else if (attributes->Mask & VLADDR_UUID) {
2171 if (attributes->Mask & (VLADDR_IPADDR|VLADDR_INDEX)) {
2172 ubik_AbortTrans(trans);
2175 if (!ex_addr[0]) { /* mh servers probably aren't setup on this vldb */
2176 ubik_AbortTrans(trans);
2179 if (errorcode = FindExtentBlock(trans, &attributes->uuid, 0, -1, &exp, &base)) {
2180 ubik_AbortTrans(trans);
2184 ubik_AbortTrans(trans);
2189 ubik_AbortTrans(trans);
2192 addrsp->bulkaddrs_val = taddrp = (afs_uint32 *)malloc(sizeof(afs_int32)*(MAXSERVERID+1));
2193 nservers= *nentries = addrsp->bulkaddrs_len = 0;
2196 ubik_AbortTrans(trans);
2199 tuuid = exp->ex_hostuuid;
2200 afs_ntohuuid(&tuuid);
2201 if (afs_uuid_is_nil(&tuuid)) {
2202 ubik_AbortTrans(trans);
2205 if (uuidpo) *uuidpo = tuuid;
2206 if (uniquifier) *uniquifier = ntohl(exp->ex_uniquifier);
2207 for (i = 0; i < VL_MAXIPADDRS_PERMH; i++) {
2208 if (exp->ex_addrs[i]) {
2209 taddr = ntohl(exp->ex_addrs[i]);
2210 /* Weed out duplicates */
2211 for (j = 0; j < nservers; j++) {
2212 if (taddrp[j] == taddr)
2215 if ((j == nservers) && (j <= MAXSERVERID)) {
2216 taddrp[nservers] = taddr;
2221 addrsp->bulkaddrs_len = *nentries = nservers;
2222 return(ubik_EndTrans(trans));
2225 /* ============> End of Exported vldb RPC functions <============= */
2228 /* Routine that copies the given vldb entry to the output buffer, vldbentries. */
2230 put_attributeentry(Vldbentry, VldbentryFirst, VldbentryLast, vldbentries, entry, nentries, alloccnt)
2231 struct vldbentry **Vldbentry, **VldbentryFirst, **VldbentryLast;
2232 bulkentries *vldbentries;
2233 struct nvlentry *entry;
2234 afs_int32 *nentries, *alloccnt;
2239 if (*Vldbentry == *VldbentryLast) {
2240 if (smallMem) return VL_SIZEEXCEEDED; /* no growing if smallMem defined */
2242 /* Allocate another set of memory; each time allocate twice as
2243 * many blocks as the last time. When we reach VLDBALLOCLIMIT,
2244 * then grow in increments of VLDBALLOCINCR.
2246 allo = (*alloccnt > VLDBALLOCLIMIT) ? VLDBALLOCINCR : *alloccnt;
2247 reall = (vldbentry *) realloc(*VldbentryFirst, (*alloccnt+allo)*sizeof(vldbentry));
2248 if (reall == NULL) return VL_NOMEM;
2250 *VldbentryFirst = vldbentries->bulkentries_val = reall;
2251 *Vldbentry = *VldbentryFirst + *alloccnt;
2252 *VldbentryLast = *Vldbentry + allo;
2255 vlentry_to_vldbentry(entry, *Vldbentry);
2258 vldbentries->bulkentries_len++;
2263 put_nattributeentry(Vldbentry, VldbentryFirst, VldbentryLast, vldbentries, entry,
2264 matchtype, matchindex, nentries, alloccnt)
2265 struct nvldbentry **Vldbentry, **VldbentryFirst, **VldbentryLast;
2266 nbulkentries *vldbentries;
2267 struct nvlentry *entry;
2268 afs_int32 matchtype, matchindex, *nentries, *alloccnt;
2273 if (*Vldbentry == *VldbentryLast) {
2274 if (smallMem) return VL_SIZEEXCEEDED; /* no growing if smallMem defined */
2276 /* Allocate another set of memory; each time allocate twice as
2277 * many blocks as the last time. When we reach VLDBALLOCLIMIT,
2278 * then grow in increments of VLDBALLOCINCR.
2280 allo = (*alloccnt > VLDBALLOCLIMIT) ? VLDBALLOCINCR : *alloccnt;
2281 reall = (nvldbentry *)realloc(*VldbentryFirst, (*alloccnt+allo)*sizeof(nvldbentry));
2282 if (reall == NULL) return VL_NOMEM;
2284 *VldbentryFirst = vldbentries->nbulkentries_val = reall;
2285 *Vldbentry = *VldbentryFirst + *alloccnt;
2286 *VldbentryLast = *Vldbentry + allo;
2289 vlentry_to_nvldbentry(entry, *Vldbentry);
2290 (*Vldbentry)->matchindex = (matchtype << 16) + matchindex;
2293 vldbentries->nbulkentries_len++;
2298 /* Common code to actually remove a vldb entry from the database. */
2300 RemoveEntry(trans, entryptr, tentry)
2301 struct ubik_trans *trans;
2303 struct nvlentry *tentry;
2305 register int errorcode;
2307 if (errorcode = UnthreadVLentry(trans, entryptr, tentry))
2309 if (errorcode = FreeBlock(trans, entryptr))
2315 ReleaseEntry(tentry, releasetype)
2316 struct nvlentry *tentry;
2317 afs_int32 releasetype;
2319 if (releasetype & LOCKREL_TIMESTAMP)
2320 tentry->LockTimestamp = 0;
2321 if (releasetype & LOCKREL_OPCODE)
2322 tentry->flags &= ~VLOP_ALLOPERS;
2323 if (releasetype & LOCKREL_AFSID)
2324 tentry->LockAfsId = 0;
2328 /* Verify that the incoming vldb entry is valid; multi type of error codes are returned. */
2330 check_vldbentry(aentry)
2331 struct vldbentry *aentry;
2335 if (InvalidVolname(aentry->name))
2337 if (aentry->nServers <= 0 || aentry->nServers > OMAXNSERVERS)
2338 return VL_BADSERVER;
2339 for (i=0; i < aentry->nServers; i++) {
2340 /* if (aentry->serverNumber[i] < 0 || aentry->serverNumber[i] > MAXSERVERID)
2341 return VL_BADSERVER; */
2342 if (aentry->serverPartition[i] < 0 || aentry->serverPartition[i] > MAXPARTITIONID)
2343 return VL_BADPARTITION;
2344 if (aentry->serverFlags[i] < 0 || aentry->serverFlags[i] > MAXSERVERFLAG)
2345 return VL_BADSERVERFLAG;
2351 check_nvldbentry(aentry)
2352 struct nvldbentry *aentry;
2356 if (InvalidVolname(aentry->name))
2358 if (aentry->nServers <= 0 || aentry->nServers > NMAXNSERVERS)
2359 return VL_BADSERVER;
2360 for (i=0; i < aentry->nServers; i++) {
2361 /* if (aentry->serverNumber[i] < 0 || aentry->serverNumber[i] > MAXSERVERID)
2362 return VL_BADSERVER; */
2363 if (aentry->serverPartition[i] < 0 || aentry->serverPartition[i] > MAXPARTITIONID)
2364 return VL_BADPARTITION;
2365 if (aentry->serverFlags[i] < 0 || aentry->serverFlags[i] > MAXSERVERFLAG)
2366 return VL_BADSERVERFLAG;
2372 /* Convert from the external vldb entry representation to its internal
2373 (more compact) form. This call should not change the hash chains! */
2375 vldbentry_to_vlentry(atrans, VldbEntry, VlEntry)
2376 struct ubik_trans *atrans;
2377 struct vldbentry *VldbEntry;
2378 struct nvlentry *VlEntry;
2382 if (strcmp(VlEntry->name, VldbEntry->name))
2383 strncpy(VlEntry->name, VldbEntry->name, sizeof(VlEntry->name));
2384 for (i=0; i<VldbEntry->nServers; i++) {
2385 serverindex = IpAddrToRelAddr(VldbEntry->serverNumber[i], atrans);
2386 if (serverindex == -1) return VL_BADSERVER;
2387 VlEntry->serverNumber[i] = serverindex;
2388 VlEntry->serverPartition[i] = VldbEntry->serverPartition[i];
2389 VlEntry->serverFlags[i] = VldbEntry->serverFlags[i];
2391 for (;i < OMAXNSERVERS; i++)
2392 VlEntry->serverNumber[i] = VlEntry->serverPartition[i] = VlEntry->serverFlags[i] = BADSERVERID;
2393 for (i=0; i < MAXTYPES; i++)
2394 VlEntry->volumeId[i] = VldbEntry->volumeId[i];
2395 VlEntry->cloneId = VldbEntry->cloneId;
2396 VlEntry->flags = VldbEntry->flags;
2401 nvldbentry_to_vlentry(atrans, VldbEntry, VlEntry)
2402 struct ubik_trans *atrans;
2403 struct nvldbentry *VldbEntry;
2404 struct nvlentry *VlEntry;
2408 if (strcmp(VlEntry->name, VldbEntry->name))
2409 strncpy(VlEntry->name, VldbEntry->name, sizeof(VlEntry->name));
2410 for (i=0; i<VldbEntry->nServers; i++) {
2411 serverindex = IpAddrToRelAddr(VldbEntry->serverNumber[i], atrans);
2412 if (serverindex == -1) return VL_BADSERVER;
2413 VlEntry->serverNumber[i] = serverindex;
2414 VlEntry->serverPartition[i] = VldbEntry->serverPartition[i];
2415 VlEntry->serverFlags[i] = VldbEntry->serverFlags[i];
2417 for (;i < NMAXNSERVERS; i++)
2418 VlEntry->serverNumber[i] = VlEntry->serverPartition[i] = VlEntry->serverFlags[i] = BADSERVERID;
2419 for (i=0; i < MAXTYPES; i++)
2420 VlEntry->volumeId[i] = VldbEntry->volumeId[i];
2421 VlEntry->cloneId = VldbEntry->cloneId;
2422 VlEntry->flags = VldbEntry->flags;
2427 /* Update the vldb entry with the new fields as indicated by the value of the Mask entry in the updateentry structure. All necessary validation checks are performed. */
2429 get_vldbupdateentry(trans, blockindex, updateentry, VlEntry)
2430 struct ubik_trans *trans;
2431 afs_int32 blockindex;
2432 struct VldbUpdateEntry *updateentry;
2433 struct nvlentry *VlEntry;
2435 int i, j, errorcode, serverindex;
2437 if (updateentry->Mask & VLUPDATE_VOLUMENAME) {
2438 if (InvalidVolname(updateentry->name))
2440 if (errorcode = UnhashVolname(trans, blockindex, VlEntry))
2442 strncpy(VlEntry->name, updateentry->name, sizeof(VlEntry->name));
2443 HashVolname(trans, blockindex, VlEntry);
2446 if (updateentry->Mask & VLUPDATE_VOLNAMEHASH) {
2447 if (errorcode = UnhashVolname(trans, blockindex, VlEntry)) {
2448 if (errorcode != VL_NOENT)
2451 HashVolname(trans, blockindex, VlEntry);
2454 if (updateentry->Mask & VLUPDATE_FLAGS) {
2455 VlEntry->flags = updateentry->flags;
2457 if (updateentry->Mask & VLUPDATE_CLONEID) {
2458 VlEntry->cloneId = updateentry->cloneId;
2460 if (updateentry->Mask & VLUPDATE_RWID) {
2461 if (errorcode = UnhashVolid(trans, RWVOL, blockindex, VlEntry)) {
2462 if (errorcode != VL_NOENT)
2465 VlEntry->volumeId[RWVOL] = updateentry->spares3; /* rw id */
2466 if (errorcode = HashVolid(trans, RWVOL, blockindex, VlEntry))
2469 if (updateentry->Mask & VLUPDATE_READONLYID) {
2470 if (errorcode = UnhashVolid(trans, ROVOL, blockindex, VlEntry)) {
2471 if (errorcode != VL_NOENT)
2474 VlEntry->volumeId[ROVOL] = updateentry->ReadOnlyId;
2475 if (errorcode = HashVolid(trans, ROVOL, blockindex, VlEntry))
2478 if (updateentry->Mask & VLUPDATE_BACKUPID) {
2479 if (errorcode = UnhashVolid(trans, BACKVOL, blockindex, VlEntry)) {
2480 if (errorcode != VL_NOENT)
2483 VlEntry->volumeId[BACKVOL] = updateentry->BackupId;
2484 if (errorcode = HashVolid(trans, BACKVOL, blockindex, VlEntry))
2487 if (updateentry->Mask & VLUPDATE_REPSITES) {
2488 if (updateentry->nModifiedRepsites <= 0 || updateentry->nModifiedRepsites > OMAXNSERVERS)
2489 return VL_BADSERVER;
2490 for (i=0; i < updateentry->nModifiedRepsites; i++) {
2491 /* if (updateentry->RepsitesTargetServer[i] < 0 || updateentry->RepsitesTargetServer[i] > MAXSERVERID)
2492 return VL_BADSERVER; */
2493 if (updateentry->RepsitesTargetPart[i] < 0 || updateentry->RepsitesTargetPart[i] > MAXPARTITIONID)
2494 return VL_BADPARTITION;
2495 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_DELETE) {
2496 if ((j = repsite_exists(VlEntry, IpAddrToRelAddr(updateentry->RepsitesTargetServer[i], trans), updateentry->RepsitesTargetPart[i])) != -1)
2497 repsite_compress(VlEntry, j);
2498 else return VL_NOREPSERVER;
2500 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_ADD) {
2501 /* if (updateentry->RepsitesNewServer[i] < 0 || updateentry->RepsitesNewServer[i] > MAXSERVERID)
2502 return VL_BADSERVER; */
2503 if (updateentry->RepsitesNewPart[i] < 0 || updateentry->RepsitesNewPart[i] > MAXPARTITIONID)
2504 return VL_BADPARTITION;
2505 if (repsite_exists(VlEntry, IpAddrToRelAddr(updateentry->RepsitesNewServer[i], trans), updateentry->RepsitesNewPart[i]) != -1)
2506 return VL_DUPREPSERVER;
2507 for (j=0; VlEntry->serverNumber[j] != BADSERVERID && j < OMAXNSERVERS; j++);
2508 if (j >= OMAXNSERVERS) return VL_REPSFULL;
2509 if ((serverindex = IpAddrToRelAddr(updateentry->RepsitesNewServer[i], trans)) == -1)
2510 return VL_BADSERVER;
2511 VlEntry->serverNumber[j] = serverindex;
2512 VlEntry->serverPartition[j] = updateentry->RepsitesNewPart[i];
2513 if (updateentry->RepsitesNewFlags[i] < 0 || updateentry->RepsitesNewFlags[i] > MAXSERVERFLAG)
2514 return VL_BADSERVERFLAG;
2515 VlEntry->serverFlags[j] = updateentry->RepsitesNewFlags[i];
2517 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODSERV) {
2518 /*n if (updateentry->RepsitesNewServer[i] < 0 || updateentry->RepsitesNewServer[i] > MAXSERVERID)
2519 return VL_BADSERVER; */
2520 if ((j = repsite_exists(VlEntry, IpAddrToRelAddr(updateentry->RepsitesTargetServer[i], trans), updateentry->RepsitesTargetPart[i])) != -1) {
2521 VlEntry->serverNumber[j] = IpAddrToRelAddr(updateentry->RepsitesNewServer[i], trans);
2523 else return VL_NOREPSERVER;
2525 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODPART) {
2526 if (updateentry->RepsitesNewPart[i] < 0 || updateentry->RepsitesNewPart[i] > MAXPARTITIONID)
2527 return VL_BADPARTITION;
2528 if ((j = repsite_exists(VlEntry, IpAddrToRelAddr(updateentry->RepsitesTargetServer[i], trans), updateentry->RepsitesTargetPart[i])) != -1)
2529 VlEntry->serverPartition[j] = updateentry->RepsitesNewPart[i];
2530 else return VL_NOREPSERVER;
2532 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODFLAG) {
2533 if ((j = repsite_exists(VlEntry, IpAddrToRelAddr(updateentry->RepsitesTargetServer[i], trans), updateentry->RepsitesTargetPart[i])) != -1) {
2534 if (updateentry->RepsitesNewFlags[i] < 0 || updateentry->RepsitesNewFlags[i] > MAXSERVERFLAG)
2535 return VL_BADSERVERFLAG;
2536 VlEntry->serverFlags[j] = updateentry->RepsitesNewFlags[i];
2537 } else return VL_NOREPSERVER;
2545 /* Check if the specified [server,partition] entry is found in the vldb entry's repsite table; it's offset in the table is returned, if it's present there. */
2547 repsite_exists(VlEntry, server, partition)
2548 struct nvlentry *VlEntry;
2549 int server, partition;
2553 for (i=0; VlEntry->serverNumber[i] != BADSERVERID && i < OMAXNSERVERS; i++) {
2554 if ((VlEntry->serverNumber[i] == server) && (VlEntry->serverPartition[i] == partition))
2562 /* Repsite table compression: used when deleting a repsite entry so that all active repsite entries are on the top of the table. */
2564 repsite_compress(VlEntry, offset)
2565 struct nvlentry *VlEntry;
2568 int repsite_offset = offset;
2569 for (; VlEntry->serverNumber[repsite_offset] != BADSERVERID && repsite_offset < OMAXNSERVERS-1; repsite_offset++) {
2570 VlEntry->serverNumber[repsite_offset] = VlEntry->serverNumber[repsite_offset+1];
2571 VlEntry->serverPartition[repsite_offset] = VlEntry->serverPartition[repsite_offset+1];
2572 VlEntry->serverFlags[repsite_offset] = VlEntry->serverFlags[repsite_offset+1];
2574 VlEntry->serverNumber[repsite_offset] = BADSERVERID;
2578 /* Convert from the internal (compacted) vldb entry to the external representation used by the interface. */
2580 vlentry_to_vldbentry(VlEntry, VldbEntry)
2581 struct nvlentry *VlEntry;
2582 struct vldbentry *VldbEntry;
2586 memset(VldbEntry, 0, sizeof(struct vldbentry));
2587 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
2588 for (i=0; i < OMAXNSERVERS; i++) {
2589 if (VlEntry->serverNumber[i] == BADSERVERID) break;
2590 if ((HostAddress[j = VlEntry->serverNumber[i]] & 0xff000000) == 0xff000000) {
2591 struct extentaddr *exp;
2594 base = (HostAddress[j] >> 16) & 0xff;
2595 index = HostAddress[j] & 0x0000ffff;
2596 exp = &ex_addr[base][index];
2597 /* For now return the first ip address back */
2598 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2599 if (exp->ex_addrs[j]) {
2600 VldbEntry->serverNumber[i] = ntohl(exp->ex_addrs[j]);
2605 VldbEntry->serverNumber[i] = HostAddress[VlEntry->serverNumber[i]];
2606 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
2607 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
2609 VldbEntry->nServers = i;
2610 for (i=0; i<MAXTYPES; i++)
2611 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
2612 VldbEntry->cloneId = VlEntry->cloneId;
2613 VldbEntry->flags = VlEntry->flags;
2617 /* Convert from the internal (compacted) vldb entry to the external representation used by the interface. */
2618 static vlentry_to_nvldbentry(VlEntry, VldbEntry)
2619 struct nvlentry *VlEntry;
2620 struct nvldbentry *VldbEntry;
2624 memset(VldbEntry, 0, sizeof(struct vldbentry));
2625 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
2626 for (i=0; i < NMAXNSERVERS; i++) {
2627 if (VlEntry->serverNumber[i] == BADSERVERID) break;
2628 if ((HostAddress[j = VlEntry->serverNumber[i]] & 0xff000000) == 0xff000000) {
2629 struct extentaddr *exp;
2632 base = (HostAddress[j] >> 16) & 0xff;
2633 index = HostAddress[j] & 0x0000ffff;
2634 exp = &ex_addr[base][index];
2635 /* For now return the first ip address back */
2636 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2637 if (exp->ex_addrs[j]) {
2638 VldbEntry->serverNumber[i] = ntohl(exp->ex_addrs[j]);
2643 VldbEntry->serverNumber[i] = HostAddress[VlEntry->serverNumber[i]];
2644 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
2645 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
2647 VldbEntry->nServers = i;
2648 for (i=0; i<MAXTYPES; i++)
2649 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
2650 VldbEntry->cloneId = VlEntry->cloneId;
2651 VldbEntry->flags = VlEntry->flags;
2654 static vlentry_to_uvldbentry(VlEntry, VldbEntry)
2655 struct nvlentry *VlEntry;
2656 struct uvldbentry *VldbEntry;
2660 memset(VldbEntry, 0, sizeof(struct vldbentry));
2661 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
2662 for (i=0; i < NMAXNSERVERS; i++) {
2663 if (VlEntry->serverNumber[i] == BADSERVERID) break;
2664 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
2665 VldbEntry->serverUnique[i] = 0;
2666 if ((HostAddress[j = VlEntry->serverNumber[i]] & 0xff000000) == 0xff000000) {
2667 struct extentaddr *exp;
2671 base = (HostAddress[j] >> 16) & 0xff;
2672 index = HostAddress[j] & 0x0000ffff;
2673 exp = &ex_addr[base][index];
2674 tuuid = exp->ex_hostuuid;
2675 afs_ntohuuid(&tuuid);
2676 VldbEntry->serverFlags[i] |= VLSERVER_FLAG_UUID;
2677 VldbEntry->serverNumber[i] = tuuid;
2678 VldbEntry->serverUnique[i] = ntohl(exp->ex_uniquifier);
2680 VldbEntry->serverNumber[i].time_low = HostAddress[VlEntry->serverNumber[i]];
2682 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
2685 VldbEntry->nServers = i;
2686 for (i=0; i<MAXTYPES; i++)
2687 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
2688 VldbEntry->cloneId = VlEntry->cloneId;
2689 VldbEntry->flags = VlEntry->flags;
2692 #define LEGALCHARS ".ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
2695 /* Verify that the volname is a valid volume name. */
2697 InvalidVolname(volname)
2704 slen = strlen(volname);
2705 if (slen >= VL_MAXNAMELEN) return 1;
2706 return(slen != strspn(volname, map));
2710 /* Verify that the given volume type is valid. */
2712 InvalidVoltype(voltype)
2715 if (voltype != RWVOL && voltype != ROVOL && voltype != BACKVOL)
2722 InvalidOperation(voloper)
2725 if (voloper != VLOP_MOVE && voloper != VLOP_RELEASE && voloper != VLOP_BACKUP && voloper != VLOP_DELETE && voloper != VLOP_DUMP)
2731 InvalidReleasetype(releasetype)
2732 afs_int32 releasetype;
2734 if ((releasetype & LOCKREL_TIMESTAMP) || (releasetype & LOCKREL_OPCODE) || (releasetype & LOCKREL_AFSID))
2740 IpAddrToRelAddr(ipaddr, atrans)
2741 struct ubik_trans *atrans;
2742 register afs_uint32 ipaddr;
2745 register afs_int32 code, base, index;
2746 struct extentaddr *exp;
2748 for (i = 0; i <= MAXSERVERID; i++) {
2749 if (HostAddress[i] == ipaddr)
2751 if ((HostAddress[i] & 0xff000000) == 0xff000000) {
2752 base = (HostAddress[i] >> 16) & 0xff;
2753 index = HostAddress[i] & 0x0000ffff;
2754 if (base >= VL_MAX_ADDREXTBLKS) {
2755 VLog(0, ("Internal error: Multihome extent base is too large. Base %d index %d\n", base, index));
2756 return -1; /* EINVAL */
2758 if (index >= VL_MHSRV_PERBLK) {
2759 VLog(0, ("Internal error: Multihome extent index is too large. Base %d index %d\n", base, index));
2760 return -1; /* EINVAL */
2762 if (!ex_addr[base]) {
2763 VLog(0, ("Internal error: Multihome extent does not exist. Base %d\n", base));
2764 return -1; /* EINVAL */
2766 exp = &ex_addr[base][index];
2767 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2768 if (exp->ex_addrs[j] && (ntohl(exp->ex_addrs[j]) == ipaddr)) {
2775 /* allocate the new server a server id pronto */
2777 for(i=0;i <= MAXSERVERID;i++) {
2778 if (cheader.IpMappedAddr[i] == 0) {
2779 cheader.IpMappedAddr[i] = htonl(ipaddr);
2780 code = vlwrite(atrans, DOFFSET(0, &cheader, &cheader.IpMappedAddr[i]), (char *) &cheader.IpMappedAddr[i], sizeof(afs_int32));
2781 HostAddress[i] = ipaddr;
2782 if (code) return -1;
2791 ChangeIPAddr(ipaddr1, ipaddr2, atrans)
2792 struct ubik_trans *atrans;
2793 register afs_uint32 ipaddr1, ipaddr2;
2797 struct extentaddr *exp;
2798 int base, index, mhidx;
2800 afs_int32 blockindex, count;
2802 struct nvlentry tentry;
2805 return VL_CREATEFAIL;
2807 /* Don't let addr change to 256.*.*.* : Causes internal error below */
2808 if ((ipaddr2 & 0xff000000) == 0xff000000)
2809 return(VL_BADSERVER);
2811 /* If we are removing an address, ip1 will be -1 and ip2 will be
2812 * the original address. This prevents an older revision vlserver
2813 * from removing the IP address (won't find server 0xfffffff in
2814 * the VLDB). An older revision vlserver does not have the check
2815 * to see if any volumes exist on the server being removed.
2817 if (ipaddr1 == 0xffffffff) {
2822 for (i = 0; i <= MAXSERVERID; i++) {
2823 if ((HostAddress[i] & 0xff000000) == 0xff000000) {
2824 base = (HostAddress[i] >> 16) & 0xff;
2825 index = HostAddress[i] & 0x0000ffff;
2826 if ((base >= VL_MAX_ADDREXTBLKS) || (index >= VL_MHSRV_PERBLK)) {
2827 VLog(0, ("Internal error: Multihome extent addr is too large. Base %d index %d\n",
2829 return -1; /* EINVAL */
2832 exp = &ex_addr[base][index];
2833 for (mhidx=0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2834 if (!exp->ex_addrs[mhidx]) continue;
2835 if (ntohl(exp->ex_addrs[mhidx]) == ipaddr1)
2838 if (mhidx < VL_MAXIPADDRS_PERMH) {
2842 else if (HostAddress[i] == ipaddr1) {
2848 if (i >= MAXSERVERID) {
2849 return VL_NOENT; /* not found */
2852 /* If we are removing a server entry, a volume cannot
2853 * exist on the server. If one does, don't remove the
2854 * server entry: return error "volume entry exists".
2857 for (blockindex = NextEntry(atrans, 0, &tentry, &count);
2859 blockindex = NextEntry(atrans, blockindex, &tentry, &count)) {
2860 if (++pollcount > 50) {
2864 for (j=0; j<NMAXNSERVERS; j++) {
2865 if (tentry.serverNumber[j] == BADSERVERID) break;
2866 if (tentry.serverNumber[j] == i) {
2873 /* Log a message saying we are changing/removing an IP address */
2874 VLog(0, ("The following IP address is being %s:\n",
2875 (ipaddr2?"changed":"removed")));
2876 printf(" entry %d: ", i);
2879 for (mhidx=0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2880 if (!exp->ex_addrs[mhidx]) continue;
2881 if (mhidx>0) printf(" ");
2882 PADDR(ntohl(exp->ex_addrs[mhidx]));
2894 /* Change the registered uuuid addresses */
2896 memset(&tuuid, 0, sizeof(afsUUID));
2897 afs_htonuuid(&tuuid);
2898 exp->ex_hostuuid = tuuid;
2899 code = vlwrite(atrans, DOFFSET(ntohl(ex_addr[0]->ex_contaddrs[base]),
2900 (char *)ex_addr[base], (char *)exp),
2901 (char *)&tuuid, sizeof(tuuid));
2906 /* Now change the host address entry */
2907 cheader.IpMappedAddr[i] = htonl(ipaddr2);
2908 code = vlwrite(atrans, DOFFSET(0, &cheader, &cheader.IpMappedAddr[i]), (char *)
2909 &cheader.IpMappedAddr[i], sizeof(afs_int32));
2910 HostAddress[i] = ipaddr2;
2917 /* see if the vlserver is back yet */
2918 afs_int32 SVL_ProbeServer(rxcall)
2919 struct rx_call *rxcall; {