2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include <afs/param.h>
16 #include <afs/afsutil.h>
22 #include <afs/cellconfig.h>
25 #include "vlserver_internal.h"
26 #include "afs/audit.h"
28 #ifdef HAVE_POSIX_REGEX /* use POSIX regexp library */
33 extern int extent_mod;
34 extern struct afsconf_dir *vldb_confdir;
35 extern struct ubik_dbase *VL_dbase;
37 #define ABORT(c) do { \
47 #define VLDBALLOCLIMIT 10000
48 #define VLDBALLOCINCR 2048
50 static int put_attributeentry(struct vl_ctx *ctx,
51 struct vldbentry **, struct vldbentry **,
52 struct vldbentry **, bulkentries *,
53 struct nvlentry *, afs_int32 *, afs_int32 *);
54 static int put_nattributeentry(struct vl_ctx *ctx,
55 struct nvldbentry **, struct nvldbentry **,
56 struct nvldbentry **, nbulkentries *,
57 struct nvlentry *, afs_int32, afs_int32,
58 afs_int32 *, afs_int32 *);
59 static int RemoveEntry(struct vl_ctx *ctx, afs_int32 entryptr,
60 struct nvlentry *tentry);
61 static void ReleaseEntry(struct nvlentry *tentry, afs_int32 releasetype);
62 static int check_vldbentry(struct vldbentry *aentry);
63 static int check_nvldbentry(struct nvldbentry *aentry);
64 static int vldbentry_to_vlentry(struct vl_ctx *ctx,
65 struct vldbentry *VldbEntry,
66 struct nvlentry *VlEntry);
67 static int nvldbentry_to_vlentry(struct vl_ctx *ctx,
68 struct nvldbentry *VldbEntry,
69 struct nvlentry *VlEntry);
70 static int get_vldbupdateentry(struct vl_ctx *ctx, afs_int32 blockindex,
71 struct VldbUpdateEntry *updateentry,
72 struct nvlentry *VlEntry);
73 static int repsite_exists(struct nvlentry *VlEntry, int server, int partition);
74 static void repsite_compress(struct nvlentry *VlEntry, int offset);
75 static void vlentry_to_vldbentry(struct vl_ctx *ctx,
76 struct nvlentry *VlEntry,
77 struct vldbentry *VldbEntry);
78 static void vlentry_to_nvldbentry(struct vl_ctx *ctx,
79 struct nvlentry *VlEntry,
80 struct nvldbentry *VldbEntry);
81 static void vlentry_to_uvldbentry(struct vl_ctx *ctx,
82 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(struct vl_ctx *ctx, afs_uint32 ipaddr, int create);
89 static int ChangeIPAddr(struct vl_ctx *ctx, afs_uint32 ipaddr1,
93 countRequest(int opcode)
96 dynamic_statistics.requests[opcode - VL_LOWEST_OPCODE]++;
101 countAbort(int opcode)
104 dynamic_statistics.aborts[opcode - VL_LOWEST_OPCODE]++;
108 #define AFS_RXINFO_LEN 128
110 rxinfo(char * str, struct rx_call *rxcall)
113 struct rx_connection *tconn;
118 struct in_addr hostAddr;
120 tconn = rx_ConnectionOf(rxcall);
121 hostAddr.s_addr = rx_HostOf(rx_PeerOf(tconn));
123 rxkad_GetServerInfo(rxcall->conn, NULL, &exp, tname, tinst, tcell,
126 sprintf(str, "%s %s%s%s%s%s", inet_ntoa(hostAddr), tname,
127 (tinst[0] == '\0') ? "" : ".",
128 (tinst[0] == '\0') ? "" : tinst,
129 (tcell[0] == '\0') ? "" : "@",
130 (tcell[0] == '\0') ? "" : tcell);
132 sprintf(str, "%s noauth", inet_ntoa(hostAddr));
136 /* This is called to initialize the database, set the appropriate locks and make sure that the vldb header is valid */
138 Init_VLdbase(struct vl_ctx *ctx,
139 int locktype, /* indicate read or write transaction */
142 int code = 0, pass, wl;
144 for (pass = 1; pass <= 3; pass++) {
145 if (pass == 2) { /* take write lock to rebuild the db */
146 code = ubik_BeginTrans(VL_dbase, UBIK_WRITETRANS, &ctx->trans);
148 } else if (locktype == LOCKREAD) {
150 ubik_BeginTransReadAnyWrite(VL_dbase, UBIK_READTRANS, &ctx->trans);
153 code = ubik_BeginTrans(VL_dbase, UBIK_WRITETRANS, &ctx->trans);
159 code = ubik_SetLock(ctx->trans, 1, 1, locktype);
162 ubik_AbortTrans(ctx->trans);
166 /* check that dbase is initialized and setup cheader */
167 /* 2nd pass we try to rebuild the header */
168 code = CheckInit(ctx->trans, ((pass == 2) ? 1 : 0));
169 if (!code && wl && extent_mod)
170 code = readExtents(ctx->trans); /* Fix the mh extent blocks */
173 ubik_AbortTrans(ctx->trans);
174 /* Only rebuld if the database is empty */
175 /* Exit if can't rebuild */
176 if ((pass == 1) && (code != VL_EMPTY))
180 } else { /* No code */
182 ubik_EndTrans(ctx->trans); /* Rebuilt db. End trans, then retake original lock */
184 break; /* didn't rebuild and successful - exit */
189 code = vlsetcache(ctx, locktype);
195 /* Create a new vldb entry; both new volume id and name must be unique
196 * (non-existant in vldb).
200 SVL_CreateEntry(struct rx_call *rxcall, struct vldbentry *newentry)
202 int this_op = VLCREATEENTRY;
204 afs_int32 code, blockindex;
205 struct nvlentry tentry;
206 char rxstr[AFS_RXINFO_LEN];
208 countRequest(this_op);
209 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) {
214 /* Do some validity tests on new entry */
215 if ((code = check_vldbentry(newentry))
216 || (code = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
220 ("OCreate Volume %d %s\n", newentry->volumeId[RWVOL],
221 rxinfo(rxstr, rxcall)));
222 if (EntryIDExists(&ctx, newentry->volumeId, MAXTYPES, &code)) {
223 /* at least one of the specified IDs already exists; we fail */
230 /* Is this following check (by volume name) necessary?? */
231 /* If entry already exists, we fail */
232 if (FindByName(&ctx, newentry->name, &tentry, &code)) {
239 blockindex = AllocBlock(&ctx, &tentry);
240 if (blockindex == 0) {
241 code = VL_CREATEFAIL;
245 memset(&tentry, 0, sizeof(struct nvlentry));
246 /* Convert to its internal representation; both in host byte order */
247 if ((code = vldbentry_to_vlentry(&ctx, newentry, &tentry))) {
248 FreeBlock(&ctx, blockindex);
252 /* Actually insert the entry in vldb */
253 code = ThreadVLentry(&ctx, blockindex, &tentry);
255 FreeBlock(&ctx, blockindex);
258 code = ubik_EndTrans(ctx.trans);
264 ubik_AbortTrans(ctx.trans);
267 osi_auditU(rxcall, VLCreateEntryEvent, code, AUD_STR,
268 (newentry ? newentry->name : NULL), AUD_END);
274 SVL_CreateEntryN(struct rx_call *rxcall, struct nvldbentry *newentry)
276 int this_op = VLCREATEENTRYN;
278 afs_int32 code, blockindex;
279 struct nvlentry tentry;
280 char rxstr[AFS_RXINFO_LEN];
282 countRequest(this_op);
283 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) {
288 /* Do some validity tests on new entry */
289 if ((code = check_nvldbentry(newentry))
290 || (code = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
294 ("Create Volume %d %s\n", newentry->volumeId[RWVOL],
295 rxinfo(rxstr, rxcall)));
296 if (EntryIDExists(&ctx, newentry->volumeId, MAXTYPES, &code)) {
297 /* at least one of the specified IDs already exists; we fail */
304 /* Is this following check (by volume name) necessary?? */
305 /* If entry already exists, we fail */
306 if (FindByName(&ctx, newentry->name, &tentry, &code)) {
313 blockindex = AllocBlock(&ctx, &tentry);
314 if (blockindex == 0) {
315 code = VL_CREATEFAIL;
319 memset(&tentry, 0, sizeof(struct nvlentry));
320 /* Convert to its internal representation; both in host byte order */
321 if ((code = nvldbentry_to_vlentry(&ctx, newentry, &tentry))) {
322 FreeBlock(&ctx, blockindex);
326 /* Actually insert the entry in vldb */
327 code = ThreadVLentry(&ctx, blockindex, &tentry);
329 FreeBlock(&ctx, blockindex);
332 code = ubik_EndTrans(ctx.trans);
338 ubik_AbortTrans(ctx.trans);
341 osi_auditU(rxcall, VLCreateEntryEvent, code, AUD_STR,
342 (newentry ? newentry->name : NULL), AUD_END);
348 SVL_ChangeAddr(struct rx_call *rxcall, afs_uint32 ip1, afs_uint32 ip2)
350 int this_op = VLCHANGEADDR;
353 char rxstr[AFS_RXINFO_LEN];
355 countRequest(this_op);
356 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) {
361 if ((code = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
364 VLog(1, ("Change Addr %u -> %u %s\n", ip1, ip2, rxinfo(rxstr, rxcall)));
365 if ((code = ChangeIPAddr(&ctx, ip1, ip2)))
368 code = ubik_EndTrans(ctx.trans);
374 ubik_AbortTrans(ctx.trans);
377 osi_auditU(rxcall, VLChangeAddrEvent, code, AUD_LONG, ip1, AUD_LONG,
382 /* Delete a vldb entry given the volume id. */
384 SVL_DeleteEntry(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype)
386 int this_op = VLDELETEENTRY;
388 afs_int32 blockindex, code;
389 struct nvlentry tentry;
390 char rxstr[AFS_RXINFO_LEN];
392 countRequest(this_op);
393 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
396 if ((voltype != -1) && (InvalidVoltype(voltype)))
399 if ((code = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
402 VLog(1, ("Delete Volume %u %s\n", volid, rxinfo(rxstr, rxcall)));
403 blockindex = FindByID(&ctx, volid, voltype, &tentry, &code);
404 if (blockindex == 0) { /* volid not found */
410 if (tentry.flags & VLDELETED) { /* Already deleted; return */
411 ABORT(VL_ENTDELETED);
413 if ((code = RemoveEntry(&ctx, blockindex, &tentry))) {
416 code = (ubik_EndTrans(ctx.trans));
421 ubik_AbortTrans(ctx.trans);
424 osi_auditU(rxcall, VLDeleteEntryEvent, code, AUD_LONG, volid,
430 /* Get a vldb entry given its volume id; make sure it's not a deleted entry. */
432 GetEntryByID(struct rx_call *rxcall,
435 char *aentry, /* entry data copied here */
440 afs_int32 blockindex, code;
441 struct nvlentry tentry;
442 char rxstr[AFS_RXINFO_LEN];
444 countRequest(this_op);
446 if ((voltype != -1) && (InvalidVoltype(voltype)))
447 return VL_BADVOLTYPE;
448 if ((code = Init_VLdbase(&ctx, LOCKREAD, this_op)))
451 VLog(5, ("GetVolumeByID %u (%d) %s\n", volid, new,
452 rxinfo(rxstr, rxcall)));
453 blockindex = FindByID(&ctx, volid, voltype, &tentry, &code);
454 if (blockindex == 0) { /* entry not found */
459 if (tentry.flags & VLDELETED) { /* Entry is deleted! */
460 code = VL_ENTDELETED;
463 /* Convert from the internal to external form */
465 vlentry_to_nvldbentry(&ctx, &tentry, (struct nvldbentry *)aentry);
467 vlentry_to_uvldbentry(&ctx, &tentry, (struct uvldbentry *)aentry);
469 vlentry_to_vldbentry(&ctx, &tentry, (struct vldbentry *)aentry);
470 return (ubik_EndTrans(ctx.trans));
474 ubik_AbortTrans(ctx.trans);
479 SVL_GetEntryByID(struct rx_call *rxcall,
482 vldbentry *aentry) /* entry data copied here */
484 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 0,
489 SVL_GetEntryByIDN(struct rx_call *rxcall,
492 nvldbentry *aentry) /* entry data copied here */
494 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 1,
499 SVL_GetEntryByIDU(struct rx_call *rxcall,
502 uvldbentry *aentry) /* entry data copied here */
504 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 2,
508 /* returns true if the id is a decimal integer, in which case we interpret
509 * it as an id. make the cache manager much simpler */
511 NameIsId(char *aname)
514 while ((tc = *aname++)) {
515 if (tc > '9' || tc < '0')
521 /* Get a vldb entry given the volume's name; of course, very similar to
522 * VLGetEntryByID() above. */
524 GetEntryByName(struct rx_call *rxcall,
526 char *aentry, /* entry data copied here */
531 afs_int32 blockindex, code;
532 struct nvlentry tentry;
533 char rxstr[AFS_RXINFO_LEN];
535 if (NameIsId(volname)) {
536 return GetEntryByID(rxcall, atoi(volname), -1, aentry, new, this_op);
538 if (InvalidVolname(volname))
540 if ((code = Init_VLdbase(&ctx, LOCKREAD, this_op)))
542 VLog(5, ("GetVolumeByName %s (%d) %s\n", volname, new, rxinfo(rxstr, rxcall)));
543 blockindex = FindByName(&ctx, volname, &tentry, &code);
544 if (blockindex == 0) { /* entry not found */
549 if (tentry.flags & VLDELETED) { /* Entry is deleted */
550 code = VL_ENTDELETED;
553 /* Convert to external entry representation */
555 vlentry_to_nvldbentry(&ctx, &tentry, (struct nvldbentry *)aentry);
557 vlentry_to_uvldbentry(&ctx, &tentry, (struct uvldbentry *)aentry);
559 vlentry_to_vldbentry(&ctx, &tentry, (struct vldbentry *)aentry);
560 return (ubik_EndTrans(ctx.trans));
564 ubik_AbortTrans(ctx.trans);
570 SVL_GetEntryByNameO(struct rx_call *rxcall,
572 struct vldbentry *aentry) /* entry data copied here */
574 return (GetEntryByName(rxcall, volname, (char *)aentry, 0,
580 SVL_GetEntryByNameN(struct rx_call *rxcall,
582 struct nvldbentry *aentry) /* entry data copied here */
584 return (GetEntryByName(rxcall, volname, (char *)aentry, 1,
589 SVL_GetEntryByNameU(struct rx_call *rxcall,
591 struct uvldbentry *aentry) /* entry data copied here */
593 return (GetEntryByName(rxcall, volname, (char *)aentry, 2,
599 /* Get the current value of the maximum volume id and bump the volume id counter by Maxvolidbump. */
601 SVL_GetNewVolumeId(struct rx_call *rxcall, afs_uint32 Maxvolidbump,
602 afs_uint32 *newvolumeid)
604 int this_op = VLGETNEWVOLUMEID;
606 afs_uint32 maxvolumeid;
608 char rxstr[AFS_RXINFO_LEN];
610 countRequest(this_op);
611 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
614 if (Maxvolidbump < 0 || Maxvolidbump > MAXBUMPCOUNT)
615 END(VL_BADVOLIDBUMP);
617 if ((code = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
620 *newvolumeid = maxvolumeid = NextUnusedID(&ctx,
621 ntohl(ctx.cheader->vital_header.MaxVolumeId), Maxvolidbump, &code);
626 maxvolumeid += Maxvolidbump;
627 VLog(1, ("GetNewVolid newmax=%u %s\n", maxvolumeid, rxinfo(rxstr, rxcall)));
628 ctx.cheader->vital_header.MaxVolumeId = htonl(maxvolumeid);
629 if (write_vital_vlheader(&ctx)) {
632 code = (ubik_EndTrans(ctx.trans));
637 ubik_AbortTrans(ctx.trans);
640 osi_auditU(rxcall, VLGetNewVolumeIdEvent, code, AUD_END);
645 /* Simple replace the contents of the vldb entry, volid, with
646 * newentry. No individual checking/updating per field (alike
647 * VLUpdateEntry) is done. */
650 SVL_ReplaceEntry(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype,
651 struct vldbentry *newentry, afs_int32 releasetype)
653 int this_op = VLREPLACEENTRY;
655 afs_int32 blockindex, code, typeindex;
657 int hashVol[MAXTYPES];
658 struct nvlentry tentry;
659 afs_uint32 checkids[MAXTYPES];
660 char rxstr[AFS_RXINFO_LEN];
662 countRequest(this_op);
663 for (typeindex = 0; typeindex < MAXTYPES; typeindex++)
664 hashVol[typeindex] = 0;
666 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
669 if ((code = check_vldbentry(newentry)))
672 if (voltype != -1 && InvalidVoltype(voltype))
675 if (releasetype && InvalidReleasetype(releasetype))
676 END(VL_BADRELLOCKTYPE);
677 if ((code = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
680 VLog(1, ("OReplace Volume %u %s\n", volid, rxinfo(rxstr, rxcall)));
681 /* find vlentry we're changing */
682 blockindex = FindByID(&ctx, volid, voltype, &tentry, &code);
683 if (blockindex == 0) { /* entry not found */
689 /* check that we're not trying to change the RW vol ID */
690 if (newentry->volumeId[RWVOL] != tentry.volumeId[RWVOL]) {
694 /* make sure none of the IDs we are changing to are already in use */
695 memset(&checkids, 0, sizeof(checkids));
696 for (typeindex = ROVOL; typeindex < MAXTYPES; typeindex++) {
697 if (tentry.volumeId[typeindex] != newentry->volumeId[typeindex]) {
698 checkids[typeindex] = newentry->volumeId[typeindex];
701 if (EntryIDExists(&ctx, checkids, MAXTYPES, &code)) {
707 /* make sure the name we're changing to doesn't already exist */
708 if (strcmp(newentry->name, tentry.name)) {
709 struct nvlentry tmp_entry;
710 if (FindByName(&ctx, newentry->name, &tmp_entry, &code)) {
717 /* unhash volid entries if they're disappearing or changing.
718 * Remember if we need to hash in the new value (we don't have to
719 * rehash if volid stays same */
720 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
721 if (tentry.volumeId[typeindex] != newentry->volumeId[typeindex]) {
722 if (tentry.volumeId[typeindex])
724 UnhashVolid(&ctx, typeindex, blockindex, &tentry))) {
727 /* we must rehash new id if the id is different and the ID is nonzero */
728 hashVol[typeindex] = 1; /* must rehash this guy if he exists */
732 /* Rehash volname if it changes */
733 if (strcmp(newentry->name, tentry.name)) { /* Name changes; redo hashing */
734 if ((code = UnhashVolname(&ctx, blockindex, &tentry))) {
740 /* after this, tentry is new entry, not old one. vldbentry_to_vlentry
741 * doesn't touch hash chains */
742 if ((code = vldbentry_to_vlentry(&ctx, newentry, &tentry))) {
746 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
747 if (hashVol[typeindex] && tentry.volumeId[typeindex]) {
748 if ((code = HashVolid(&ctx, typeindex, blockindex, &tentry))) {
755 HashVolname(&ctx, blockindex, &tentry);
758 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
759 if (vlentrywrite(ctx.trans, blockindex, &tentry, sizeof(tentry))) {
763 END(ubik_EndTrans(ctx.trans));
767 ubik_AbortTrans(ctx.trans);
770 osi_auditU(rxcall, VLReplaceVLEntryEvent, code, AUD_LONG, volid,
776 SVL_ReplaceEntryN(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype,
777 struct nvldbentry *newentry, afs_int32 releasetype)
779 int this_op = VLREPLACEENTRYN;
781 afs_int32 blockindex, code, typeindex;
783 int hashVol[MAXTYPES];
784 struct nvlentry tentry;
785 char rxstr[AFS_RXINFO_LEN];
787 countRequest(this_op);
788 for (typeindex = 0; typeindex < MAXTYPES; typeindex++)
789 hashVol[typeindex] = 0;
791 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
794 if ((code = check_nvldbentry(newentry)))
797 if (voltype != -1 && InvalidVoltype(voltype))
800 if (releasetype && InvalidReleasetype(releasetype))
801 END(VL_BADRELLOCKTYPE);
802 if ((code = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
805 VLog(1, ("Replace Volume %u %s\n", volid, rxinfo(rxstr, rxcall)));
806 /* find vlentry we're changing */
807 blockindex = FindByID(&ctx, volid, voltype, &tentry, &code);
808 if (blockindex == 0) { /* entry not found */
814 /* check that we're not trying to change the RW vol ID */
815 if (newentry->volumeId[RWVOL] != tentry.volumeId[RWVOL]) {
819 /* unhash volid entries if they're disappearing or changing.
820 * Remember if we need to hash in the new value (we don't have to
821 * rehash if volid stays same */
822 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
823 if (tentry.volumeId[typeindex] != newentry->volumeId[typeindex]) {
824 if (tentry.volumeId[typeindex])
826 UnhashVolid(&ctx, typeindex, blockindex, &tentry))) {
829 /* we must rehash new id if the id is different and the ID is nonzero */
830 hashVol[typeindex] = 1; /* must rehash this guy if he exists */
834 /* Rehash volname if it changes */
835 if (strcmp(newentry->name, tentry.name)) { /* Name changes; redo hashing */
836 if ((code = UnhashVolname(&ctx, blockindex, &tentry))) {
842 /* after this, tentry is new entry, not old one. vldbentry_to_vlentry
843 * doesn't touch hash chains */
844 if ((code = nvldbentry_to_vlentry(&ctx, newentry, &tentry))) {
848 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
849 if (hashVol[typeindex] && tentry.volumeId[typeindex]) {
850 if ((code = HashVolid(&ctx, typeindex, blockindex, &tentry))) {
857 HashVolname(&ctx, blockindex, &tentry);
860 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
861 if (vlentrywrite(ctx.trans, blockindex, &tentry, sizeof(tentry))) {
865 END(ubik_EndTrans(ctx.trans));
869 ubik_AbortTrans(ctx.trans);
872 osi_auditU(rxcall, VLReplaceVLEntryEvent, code, AUD_LONG, volid,
878 /* Update a vldb entry (accessed thru its volume id). Almost all of the
879 * entry's fields can be modified in a single call by setting the
880 * appropriate bits in the Mask field in VldbUpdateentry. */
881 /* this routine may never have been tested; use replace entry instead
882 * unless you're brave */
884 SVL_UpdateEntry(struct rx_call *rxcall,
887 struct VldbUpdateEntry *updateentry, /* Update entry copied here */
888 afs_int32 releasetype)
890 int this_op = VLUPDATEENTRY;
892 afs_int32 blockindex, code;
893 struct nvlentry tentry;
894 char rxstr[AFS_RXINFO_LEN];
896 countRequest(this_op);
897 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
899 if ((voltype != -1) && (InvalidVoltype(voltype)))
901 if (releasetype && InvalidReleasetype(releasetype))
902 END(VL_BADRELLOCKTYPE);
903 if ((code = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
906 VLog(1, ("Update Volume %u %s\n", volid, rxinfo(rxstr, rxcall)));
907 blockindex = FindByID(&ctx, volid, voltype, &tentry, &code);
908 if (blockindex == 0) { /* entry not found */
914 /* Do the actual updating of the entry, tentry. */
916 get_vldbupdateentry(&ctx, blockindex, updateentry, &tentry))) {
920 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
921 if (vlentrywrite(ctx.trans, blockindex, &tentry, sizeof(tentry))) {
924 END(ubik_EndTrans(ctx.trans));
928 ubik_AbortTrans(ctx.trans);
931 osi_auditU(rxcall, VLUpdateEntryEvent, code, AUD_LONG, volid,
938 SVL_UpdateEntryByName(struct rx_call *rxcall,
940 struct VldbUpdateEntry *updateentry, /* Update entry copied here */
941 afs_int32 releasetype)
943 int this_op = VLUPDATEENTRYBYNAME;
945 afs_int32 blockindex, code;
946 struct nvlentry tentry;
948 countRequest(this_op);
949 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
951 if (releasetype && InvalidReleasetype(releasetype))
952 END(VL_BADRELLOCKTYPE);
953 if ((code = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
956 blockindex = FindByName(&ctx, volname, &tentry, &code);
957 if (blockindex == 0) { /* entry not found */
963 /* Do the actual updating of the entry, tentry. */
965 get_vldbupdateentry(&ctx, blockindex, updateentry, &tentry))) {
969 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
970 if (vlentrywrite(ctx.trans, blockindex, &tentry, sizeof(tentry))) {
973 END(ubik_EndTrans(ctx.trans));
977 ubik_AbortTrans(ctx.trans);
980 osi_auditU(rxcall, VLUpdateEntryEvent, code, AUD_LONG, -1, AUD_END);
985 /* Set a lock to the vldb entry for volid (of type voltype if not -1). */
987 SVL_SetLock(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype,
990 int this_op = VLSETLOCK;
991 afs_int32 timestamp, blockindex, code;
993 struct nvlentry tentry;
994 char rxstr[AFS_RXINFO_LEN];
996 countRequest(this_op);
997 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
999 if ((voltype != -1) && (InvalidVoltype(voltype)))
1001 if (InvalidOperation(voloper))
1003 if ((code = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
1006 VLog(1, ("SetLock Volume %u %s\n", volid, rxinfo(rxstr, rxcall)));
1007 blockindex = FindByID(&ctx, volid, voltype, &tentry, &code);
1008 if (blockindex == NULLO) {
1013 if (tentry.flags & VLDELETED) {
1014 ABORT(VL_ENTDELETED);
1016 timestamp = FT_ApproxTime();
1018 /* Check if entry is already locked; note that we unlock any entry
1019 * locked more than MAXLOCKTIME seconds */
1020 if ((tentry.LockTimestamp)
1021 && ((timestamp - tentry.LockTimestamp) < MAXLOCKTIME)) {
1022 ABORT(VL_ENTRYLOCKED);
1025 /* Consider it an unlocked entry: set current timestamp, caller
1026 * and active vol operation */
1027 tentry.LockTimestamp = timestamp;
1028 tentry.LockAfsId = 0; /* Not implemented yet */
1029 if (tentry.flags & VLOP_RELEASE) {
1030 ABORT(VL_RERELEASE);
1032 tentry.flags &= ~VLOP_ALLOPERS; /* Clear any possible older operation bit */
1033 tentry.flags |= voloper;
1035 if (vlentrywrite(ctx.trans, blockindex, &tentry, sizeof(tentry))) {
1038 END(ubik_EndTrans(ctx.trans));
1041 countAbort(this_op);
1042 ubik_AbortTrans(ctx.trans);
1045 osi_auditU(rxcall, VLSetLockEvent, code, AUD_LONG, volid, AUD_END);
1050 /* Release an already locked vldb entry. Releasetype determines what
1051 * fields (afsid and/or volume operation) will be cleared along with
1052 * the lock time stamp. */
1055 SVL_ReleaseLock(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype,
1056 afs_int32 releasetype)
1058 int this_op = VLRELEASELOCK;
1059 afs_int32 blockindex, code;
1061 struct nvlentry tentry;
1062 char rxstr[AFS_RXINFO_LEN];
1064 countRequest(this_op);
1065 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
1067 if ((voltype != -1) && (InvalidVoltype(voltype)))
1069 if (releasetype && InvalidReleasetype(releasetype))
1070 END(VL_BADRELLOCKTYPE);
1071 if ((code = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
1074 VLog(1, ("ReleaseLock Volume %u %s\n", volid, rxinfo(rxstr, rxcall)));
1075 blockindex = FindByID(&ctx, volid, voltype, &tentry, &code);
1076 if (blockindex == NULLO) {
1081 if (tentry.flags & VLDELETED) {
1082 ABORT(VL_ENTDELETED);
1085 ReleaseEntry(&tentry, releasetype); /* Unlock the appropriate fields */
1086 if (vlentrywrite(ctx.trans, blockindex, &tentry, sizeof(tentry))) {
1089 END(ubik_EndTrans(ctx.trans));
1092 countAbort(this_op);
1093 ubik_AbortTrans(ctx.trans);
1096 osi_auditU(rxcall, VLReleaseLockEvent, code, AUD_LONG, volid,
1102 /* ListEntry returns a single vldb entry, aentry, with offset previous_index;
1103 * the remaining parameters (i.e. next_index) are used so that sequential
1104 * calls to this routine will get the next (all) vldb entries.
1107 SVL_ListEntry(struct rx_call *rxcall, afs_int32 previous_index,
1108 afs_int32 *count, afs_int32 *next_index,
1109 struct vldbentry *aentry)
1111 int this_op = VLLISTENTRY;
1114 struct nvlentry tentry;
1115 char rxstr[AFS_RXINFO_LEN];
1117 countRequest(this_op);
1118 if ((code = Init_VLdbase(&ctx, LOCKREAD, this_op)))
1120 VLog(25, ("OListEntry index=%d %s\n", previous_index,
1121 rxinfo(rxstr, rxcall)));
1122 *next_index = NextEntry(&ctx, previous_index, &tentry, count);
1124 vlentry_to_vldbentry(&ctx, &tentry, aentry);
1125 return (ubik_EndTrans(ctx.trans));
1128 /* ListEntry returns a single vldb entry, aentry, with offset previous_index;
1129 * the remaining parameters (i.e. next_index) are used so that sequential
1130 * calls to this routine will get the next (all) vldb entries.
1133 SVL_ListEntryN(struct rx_call *rxcall, afs_int32 previous_index,
1134 afs_int32 *count, afs_int32 *next_index,
1135 struct nvldbentry *aentry)
1137 int this_op = VLLISTENTRYN;
1140 struct nvlentry tentry;
1141 char rxstr[AFS_RXINFO_LEN];
1143 countRequest(this_op);
1144 if ((code = Init_VLdbase(&ctx, LOCKREAD, this_op)))
1146 VLog(25, ("ListEntry index=%d %s\n", previous_index, rxinfo(rxstr, rxcall)));
1147 *next_index = NextEntry(&ctx, previous_index, &tentry, count);
1149 vlentry_to_nvldbentry(&ctx, &tentry, aentry);
1150 return (ubik_EndTrans(ctx.trans));
1154 /* Retrieves in vldbentries all vldb entries that match the specified
1155 * attributes (by server number, partition, volume type, and flag); if volume
1156 * id is specified then the associated list for that entry is returned.
1157 * CAUTION: This could be a very expensive call since in most cases
1158 * sequential search of all vldb entries is performed.
1161 SVL_ListAttributes(struct rx_call *rxcall,
1162 struct VldbListByAttributes *attributes,
1163 afs_int32 *nentries,
1164 bulkentries *vldbentries)
1166 int this_op = VLLISTATTRIBUTES;
1167 int code, allocCount = 0;
1169 struct nvlentry tentry;
1170 struct vldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1172 char rxstr[AFS_RXINFO_LEN];
1174 countRequest(this_op);
1175 vldbentries->bulkentries_val = 0;
1176 vldbentries->bulkentries_len = *nentries = 0;
1177 if ((code = Init_VLdbase(&ctx, LOCKREAD, this_op)))
1179 allocCount = VLDBALLOCCOUNT;
1180 Vldbentry = VldbentryFirst = vldbentries->bulkentries_val =
1181 (vldbentry *) malloc(allocCount * sizeof(vldbentry));
1182 if (Vldbentry == NULL) {
1186 VldbentryLast = VldbentryFirst + allocCount;
1187 /* Handle the attribute by volume id totally separate of the rest
1188 * (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!) */
1189 if (attributes->Mask & VLLIST_VOLUMEID) {
1190 afs_int32 blockindex;
1193 FindByID(&ctx, attributes->volumeid, -1, &tentry, &code);
1194 if (blockindex == 0) {
1200 code = put_attributeentry(&ctx, &Vldbentry, &VldbentryFirst,
1201 &VldbentryLast, vldbentries, &tentry,
1202 nentries, &allocCount);
1206 afs_int32 nextblockindex = 0, count = 0, k = 0, match = 0;
1207 while ((nextblockindex =
1208 NextEntry(&ctx, nextblockindex, &tentry, &count))) {
1209 if (++pollcount > 50) {
1210 #ifndef AFS_PTHREAD_ENV
1216 if (attributes->Mask & VLLIST_SERVER) {
1219 IpAddrToRelAddr(&ctx, attributes->server, 0)) == -1)
1221 for (k = 0; k < OMAXNSERVERS; k++) {
1222 if (tentry.serverNumber[k] == BADSERVERID)
1224 if (tentry.serverNumber[k] == serverindex) {
1232 if (attributes->Mask & VLLIST_PARTITION) {
1234 if (tentry.serverPartition[k] != attributes->partition)
1237 for (k = 0; k < OMAXNSERVERS; k++) {
1238 if (tentry.serverNumber[k] == BADSERVERID)
1240 if (tentry.serverPartition[k] ==
1241 attributes->partition) {
1251 if (attributes->Mask & VLLIST_FLAG) {
1252 if (!(tentry.flags & attributes->flag))
1255 code = put_attributeentry(&ctx, &Vldbentry, &VldbentryFirst,
1256 &VldbentryLast, vldbentries, &tentry,
1257 nentries, &allocCount);
1262 if (vldbentries->bulkentries_len
1263 && (allocCount > vldbentries->bulkentries_len)) {
1265 vldbentries->bulkentries_val =
1266 (vldbentry *) realloc(vldbentries->bulkentries_val,
1267 vldbentries->bulkentries_len *
1269 if (vldbentries->bulkentries_val == NULL) {
1275 ("ListAttrs nentries=%d %s\n", vldbentries->bulkentries_len,
1276 rxinfo(rxstr, rxcall)));
1277 return (ubik_EndTrans(ctx.trans));
1280 if (vldbentries->bulkentries_val)
1281 free(vldbentries->bulkentries_val);
1282 vldbentries->bulkentries_val = 0;
1283 vldbentries->bulkentries_len = 0;
1285 countAbort(this_op);
1286 ubik_AbortTrans(ctx.trans);
1292 SVL_ListAttributesN(struct rx_call *rxcall,
1293 struct VldbListByAttributes *attributes,
1294 afs_int32 *nentries,
1295 nbulkentries *vldbentries)
1297 int this_op = VLLISTATTRIBUTESN;
1298 int code, allocCount = 0;
1300 struct nvlentry tentry;
1301 struct nvldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1303 char rxstr[AFS_RXINFO_LEN];
1305 countRequest(this_op);
1306 vldbentries->nbulkentries_val = 0;
1307 vldbentries->nbulkentries_len = *nentries = 0;
1308 if ((code = Init_VLdbase(&ctx, LOCKREAD, this_op)))
1310 allocCount = VLDBALLOCCOUNT;
1311 Vldbentry = VldbentryFirst = vldbentries->nbulkentries_val =
1312 (nvldbentry *) malloc(allocCount * sizeof(nvldbentry));
1313 if (Vldbentry == NULL) {
1317 VldbentryLast = VldbentryFirst + allocCount;
1318 /* Handle the attribute by volume id totally separate of the rest
1319 * (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!) */
1320 if (attributes->Mask & VLLIST_VOLUMEID) {
1321 afs_int32 blockindex;
1324 FindByID(&ctx, attributes->volumeid, -1, &tentry, &code);
1325 if (blockindex == 0) {
1331 code = put_nattributeentry(&ctx, &Vldbentry, &VldbentryFirst,
1332 &VldbentryLast, vldbentries, &tentry,
1333 0, 0, nentries, &allocCount);
1337 afs_int32 nextblockindex = 0, count = 0, k = 0, match = 0;
1338 while ((nextblockindex =
1339 NextEntry(&ctx, nextblockindex, &tentry, &count))) {
1340 if (++pollcount > 50) {
1341 #ifndef AFS_PTHREAD_ENV
1348 if (attributes->Mask & VLLIST_SERVER) {
1351 IpAddrToRelAddr(&ctx, attributes->server, 0)) == -1)
1353 for (k = 0; k < NMAXNSERVERS; k++) {
1354 if (tentry.serverNumber[k] == BADSERVERID)
1356 if (tentry.serverNumber[k] == serverindex) {
1364 if (attributes->Mask & VLLIST_PARTITION) {
1366 if (tentry.serverPartition[k] != attributes->partition)
1369 for (k = 0; k < NMAXNSERVERS; k++) {
1370 if (tentry.serverNumber[k] == BADSERVERID)
1372 if (tentry.serverPartition[k] ==
1373 attributes->partition) {
1383 if (attributes->Mask & VLLIST_FLAG) {
1384 if (!(tentry.flags & attributes->flag))
1387 code = put_nattributeentry(&ctx, &Vldbentry, &VldbentryFirst,
1388 &VldbentryLast, vldbentries,
1389 &tentry, 0, 0, nentries, &allocCount);
1394 if (vldbentries->nbulkentries_len
1395 && (allocCount > vldbentries->nbulkentries_len)) {
1397 vldbentries->nbulkentries_val =
1398 (nvldbentry *) realloc(vldbentries->nbulkentries_val,
1399 vldbentries->nbulkentries_len *
1400 sizeof(nvldbentry));
1401 if (vldbentries->nbulkentries_val == NULL) {
1407 ("NListAttrs nentries=%d %s\n", vldbentries->nbulkentries_len,
1408 rxinfo(rxstr, rxcall)));
1409 return (ubik_EndTrans(ctx.trans));
1412 countAbort(this_op);
1413 ubik_AbortTrans(ctx.trans);
1414 if (vldbentries->nbulkentries_val)
1415 free(vldbentries->nbulkentries_val);
1416 vldbentries->nbulkentries_val = 0;
1417 vldbentries->nbulkentries_len = 0;
1423 SVL_ListAttributesN2(struct rx_call *rxcall,
1424 struct VldbListByAttributes *attributes,
1425 char *name, /* Wildcarded volume name */
1426 afs_int32 startindex,
1427 afs_int32 *nentries,
1428 nbulkentries *vldbentries,
1429 afs_int32 *nextstartindex)
1431 int this_op = VLLISTATTRIBUTESN2;
1432 int code = 0, maxCount = VLDBALLOCCOUNT;
1434 struct nvlentry tentry;
1435 struct nvldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1436 afs_int32 blockindex = 0, count = 0, k, match;
1437 afs_int32 matchindex = 0;
1438 int serverindex = -1; /* no server found */
1439 int findserver = 0, findpartition = 0, findflag = 0, findname = 0;
1441 int namematchRWBK, namematchRO, thismatch;
1443 char volumename[VL_MAXNAMELEN+2]; /* regex anchors */
1444 char rxstr[AFS_RXINFO_LEN];
1445 #ifdef HAVE_POSIX_REGEX
1447 int need_regfree = 0;
1452 countRequest(this_op);
1453 vldbentries->nbulkentries_val = 0;
1454 vldbentries->nbulkentries_len = 0;
1456 *nextstartindex = -1;
1458 code = Init_VLdbase(&ctx, LOCKREAD, this_op);
1462 Vldbentry = VldbentryFirst = vldbentries->nbulkentries_val =
1463 (nvldbentry *) malloc(maxCount * sizeof(nvldbentry));
1464 if (Vldbentry == NULL) {
1465 countAbort(this_op);
1466 ubik_AbortTrans(ctx.trans);
1470 VldbentryLast = VldbentryFirst + maxCount;
1472 /* Handle the attribute by volume id totally separate of the rest
1473 * (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!)
1475 if (attributes->Mask & VLLIST_VOLUMEID) {
1477 FindByID(&ctx, attributes->volumeid, -1, &tentry, &code);
1478 if (blockindex == 0) {
1483 put_nattributeentry(&ctx, &Vldbentry, &VldbentryFirst,
1484 &VldbentryLast, vldbentries, &tentry, 0,
1485 0, nentries, &maxCount);
1491 /* Search each entry in the database and return all entries
1492 * that match the request. It checks volumename (with
1493 * wildcarding), entry flags, server, and partition.
1496 /* Get the server index for matching server address */
1497 if (attributes->Mask & VLLIST_SERVER) {
1499 IpAddrToRelAddr(&ctx, attributes->server, 0);
1500 if (serverindex == -1)
1504 findpartition = ((attributes->Mask & VLLIST_PARTITION) ? 1 : 0);
1505 findflag = ((attributes->Mask & VLLIST_FLAG) ? 1 : 0);
1506 if (name && (strcmp(name, ".*") != 0) && (strcmp(name, "") != 0)) {
1507 sprintf(volumename, "^%s$", name);
1508 #ifdef HAVE_POSIX_REGEX
1509 if (regcomp(&re, volumename, REG_NOSUB) != 0) {
1515 t = (char *)re_comp(volumename);
1524 /* Read each entry and see if it is the one we want */
1525 blockindex = startindex;
1526 while ((blockindex = NextEntry(&ctx, blockindex, &tentry, &count))) {
1527 if (++pollcount > 50) {
1528 #ifndef AFS_PTHREAD_ENV
1534 /* Step through each server index searching for a match.
1535 * Match to an existing RW, BK, or RO volume name (preference
1536 * is in this order). Remember which index we matched against.
1538 namematchRWBK = namematchRO = 0; /* 0->notTried; 1->match; 2->noMatch */
1542 && (tentry.serverNumber[k] != BADSERVERID)); k++) {
1543 thismatch = 0; /* does this index match */
1545 /* Match against the RW or BK volume name. Remember
1546 * results in namematchRWBK. Prefer RW over BK.
1548 if (tentry.serverFlags[k] & VLSF_RWVOL) {
1549 /* Does the name match the RW name */
1550 if (tentry.flags & VLF_RWEXISTS) {
1552 sprintf(volumename, "%s", tentry.name);
1553 #ifdef HAVE_POSIX_REGEX
1554 if (regexec(&re, volumename, 0, NULL, 0) == 0) {
1555 thismatch = VLSF_RWVOL;
1558 if (re_exec(volumename)) {
1559 thismatch = VLSF_RWVOL;
1563 thismatch = VLSF_RWVOL;
1567 /* Does the name match the BK name */
1568 if (!thismatch && (tentry.flags & VLF_BACKEXISTS)) {
1570 sprintf(volumename, "%s.backup", tentry.name);
1571 #ifdef HAVE_POSIX_REGEX
1572 if (regexec(&re, volumename, 0, NULL, 0) == 0) {
1573 thismatch = VLSF_BACKVOL;
1576 if (re_exec(volumename)) {
1577 thismatch = VLSF_BACKVOL;
1581 thismatch = VLSF_BACKVOL;
1585 namematchRWBK = (thismatch ? 1 : 2);
1588 /* Match with the RO volume name. Compare once and
1589 * remember results in namematchRO. Note that this will
1590 * pick up entries marked NEWREPSITEs and DONTUSE.
1593 if (tentry.flags & VLF_ROEXISTS) {
1597 ((namematchRO == 1) ? VLSF_ROVOL : 0);
1599 sprintf(volumename, "%s.readonly",
1601 #ifdef HAVE_POSIX_REGEX
1602 if (regexec(&re, volumename, 0, NULL, 0) == 0) {
1603 thismatch = VLSF_ROVOL;
1606 if (re_exec(volumename))
1607 thismatch = VLSF_ROVOL;
1611 thismatch = VLSF_ROVOL;
1614 namematchRO = (thismatch ? 1 : 2);
1617 /* Is there a server match */
1618 if (thismatch && findserver
1619 && (tentry.serverNumber[k] != serverindex))
1622 /* Is there a partition match */
1623 if (thismatch && findpartition
1624 && (tentry.serverPartition[k] != attributes->partition))
1627 /* Is there a flag match */
1628 if (thismatch && findflag
1629 && !(tentry.flags & attributes->flag))
1632 /* We found a match. Remember the index, and type */
1636 matchtype = thismatch;
1639 /* Since we prefer RW and BK volume matches over RO matches,
1640 * if we have already checked the RWBK name, then we already
1641 * found the best match and so end the search.
1643 * If we tried matching against the RW, BK, and RO volume names
1644 * and both failed, then we end the search (none will match).
1646 if ((match && namematchRWBK)
1647 || ((namematchRWBK == 2) && (namematchRO == 2)))
1651 /* Passed all the tests. Take it */
1654 put_nattributeentry(&ctx, &Vldbentry, &VldbentryFirst,
1655 &VldbentryLast, vldbentries, &tentry,
1656 matchtype, matchindex, nentries,
1661 if (*nentries >= maxCount)
1662 break; /* collected the max */
1665 *nextstartindex = (blockindex ? blockindex : -1);
1669 #ifdef HAVE_POSIX_REGEX
1675 countAbort(this_op);
1676 ubik_AbortTrans(ctx.trans);
1677 if (vldbentries->nbulkentries_val)
1678 free((char *)vldbentries->nbulkentries_val);
1679 vldbentries->nbulkentries_val = 0;
1680 vldbentries->nbulkentries_len = 0;
1681 *nextstartindex = -1;
1685 ("N2ListAttrs nentries=%d %s\n", vldbentries->nbulkentries_len,
1686 rxinfo(rxstr, rxcall)));
1687 return (ubik_EndTrans(ctx.trans));
1692 /* Retrieves in vldbentries all vldb entries that match the specified
1693 * attributes (by server number, partition, volume type, and flag); if
1694 * volume id is specified then the associated list for that entry is
1695 * returned. CAUTION: This could be a very expensive call since in most
1696 * cases sequential search of all vldb entries is performed.
1699 SVL_LinkedList(struct rx_call *rxcall,
1700 struct VldbListByAttributes *attributes,
1701 afs_int32 *nentries,
1702 vldb_list *vldbentries)
1704 int this_op = VLLINKEDLIST;
1707 struct nvlentry tentry;
1708 vldblist vllist, *vllistptr;
1709 afs_int32 blockindex, count, match;
1714 countRequest(this_op);
1715 if ((code = Init_VLdbase(&ctx, LOCKREAD, this_op)))
1719 vldbentries->node = NULL;
1720 vllistptr = &vldbentries->node;
1722 /* List by volumeid */
1723 if (attributes->Mask & VLLIST_VOLUMEID) {
1725 FindByID(&ctx, attributes->volumeid, -1, &tentry, &code);
1732 vllist = (single_vldbentry *) malloc(sizeof(single_vldbentry));
1733 if (vllist == NULL) {
1737 vlentry_to_vldbentry(&ctx, &tentry, &vllist->VldbEntry);
1738 vllist->next_vldb = NULL;
1740 *vllistptr = vllist; /* Thread onto list */
1741 vllistptr = &vllist->next_vldb;
1745 /* Search by server, partition, and flags */
1747 for (blockindex = NextEntry(&ctx, 0, &tentry, &count); blockindex;
1748 blockindex = NextEntry(&ctx, blockindex, &tentry, &count)) {
1751 if (++pollcount > 50) {
1752 #ifndef AFS_PTHREAD_ENV
1758 /* Does this volume exist on the desired server */
1759 if (attributes->Mask & VLLIST_SERVER) {
1761 IpAddrToRelAddr(&ctx, attributes->server, 0);
1762 if (serverindex == -1)
1764 for (k = 0; k < OMAXNSERVERS; k++) {
1765 if (tentry.serverNumber[k] == BADSERVERID)
1767 if (tentry.serverNumber[k] == serverindex) {
1776 /* Does this volume exist on the desired partition */
1777 if (attributes->Mask & VLLIST_PARTITION) {
1779 if (tentry.serverPartition[k] != attributes->partition)
1782 for (k = 0; k < OMAXNSERVERS; k++) {
1783 if (tentry.serverNumber[k] == BADSERVERID)
1785 if (tentry.serverPartition[k] ==
1786 attributes->partition) {
1796 /* Does this volume have the desired flags */
1797 if (attributes->Mask & VLLIST_FLAG) {
1798 if (!(tentry.flags & attributes->flag))
1802 vllist = (single_vldbentry *) malloc(sizeof(single_vldbentry));
1803 if (vllist == NULL) {
1807 vlentry_to_vldbentry(&ctx, &tentry, &vllist->VldbEntry);
1808 vllist->next_vldb = NULL;
1810 *vllistptr = vllist; /* Thread onto list */
1811 vllistptr = &vllist->next_vldb;
1813 if (smallMem && (*nentries >= VLDBALLOCCOUNT)) {
1814 code = VL_SIZEEXCEEDED;
1820 return (ubik_EndTrans(ctx.trans));
1823 countAbort(this_op);
1824 ubik_AbortTrans(ctx.trans);
1829 SVL_LinkedListN(struct rx_call *rxcall,
1830 struct VldbListByAttributes *attributes,
1831 afs_int32 *nentries,
1832 nvldb_list *vldbentries)
1834 int this_op = VLLINKEDLISTN;
1837 struct nvlentry tentry;
1838 nvldblist vllist, *vllistptr;
1839 afs_int32 blockindex, count, match;
1844 countRequest(this_op);
1845 if ((code = Init_VLdbase(&ctx, LOCKREAD, this_op)))
1849 vldbentries->node = NULL;
1850 vllistptr = &vldbentries->node;
1852 /* List by volumeid */
1853 if (attributes->Mask & VLLIST_VOLUMEID) {
1855 FindByID(&ctx, attributes->volumeid, -1, &tentry, &code);
1862 vllist = (single_nvldbentry *) malloc(sizeof(single_nvldbentry));
1863 if (vllist == NULL) {
1867 vlentry_to_nvldbentry(&ctx, &tentry, &vllist->VldbEntry);
1868 vllist->next_vldb = NULL;
1870 *vllistptr = vllist; /* Thread onto list */
1871 vllistptr = &vllist->next_vldb;
1875 /* Search by server, partition, and flags */
1877 for (blockindex = NextEntry(&ctx, 0, &tentry, &count); blockindex;
1878 blockindex = NextEntry(&ctx, blockindex, &tentry, &count)) {
1881 if (++pollcount > 50) {
1882 #ifndef AFS_PTHREAD_ENV
1888 /* Does this volume exist on the desired server */
1889 if (attributes->Mask & VLLIST_SERVER) {
1891 IpAddrToRelAddr(&ctx, attributes->server, 0);
1892 if (serverindex == -1)
1894 for (k = 0; k < NMAXNSERVERS; k++) {
1895 if (tentry.serverNumber[k] == BADSERVERID)
1897 if (tentry.serverNumber[k] == serverindex) {
1906 /* Does this volume exist on the desired partition */
1907 if (attributes->Mask & VLLIST_PARTITION) {
1909 if (tentry.serverPartition[k] != attributes->partition)
1912 for (k = 0; k < NMAXNSERVERS; k++) {
1913 if (tentry.serverNumber[k] == BADSERVERID)
1915 if (tentry.serverPartition[k] ==
1916 attributes->partition) {
1926 /* Does this volume have the desired flags */
1927 if (attributes->Mask & VLLIST_FLAG) {
1928 if (!(tentry.flags & attributes->flag))
1932 vllist = (single_nvldbentry *) malloc(sizeof(single_nvldbentry));
1933 if (vllist == NULL) {
1937 vlentry_to_nvldbentry(&ctx, &tentry, &vllist->VldbEntry);
1938 vllist->next_vldb = NULL;
1940 *vllistptr = vllist; /* Thread onto list */
1941 vllistptr = &vllist->next_vldb;
1943 if (smallMem && (*nentries >= VLDBALLOCCOUNT)) {
1944 code = VL_SIZEEXCEEDED;
1950 return (ubik_EndTrans(ctx.trans));
1953 countAbort(this_op);
1954 ubik_AbortTrans(ctx.trans);
1958 /* Get back vldb header statistics (allocs, frees, maxvolumeid,
1959 * totalentries, etc) and dynamic statistics (number of requests and/or
1960 * aborts per remote procedure call, etc)
1963 SVL_GetStats(struct rx_call *rxcall,
1965 vital_vlheader *vital_header)
1967 int this_op = VLGETSTATS;
1970 char rxstr[AFS_RXINFO_LEN];
1972 countRequest(this_op);
1974 /* Allow users to get statistics freely */
1975 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) /* Must be in 'UserList' to use */
1978 if ((code = Init_VLdbase(&ctx, LOCKREAD, this_op)))
1980 VLog(5, ("GetStats %s\n", rxinfo(rxstr, rxcall)));
1981 memcpy((char *)vital_header, (char *)&ctx.cheader->vital_header,
1982 sizeof(vital_vlheader));
1983 memcpy((char *)stats, (char *)&dynamic_statistics, sizeof(vldstats));
1984 return (ubik_EndTrans(ctx.trans));
1987 /* Get the list of file server addresses from the VLDB. Currently it's pretty
1988 * easy to do. In the future, it might require a little bit of grunging
1989 * through the VLDB, but that's life.
1992 SVL_GetAddrs(struct rx_call *rxcall,
1995 struct VLCallBack *spare3,
1996 afs_int32 *nentries,
1999 int this_op = VLGETADDRS;
2005 countRequest(this_op);
2006 addrsp->bulkaddrs_len = *nentries = 0;
2007 addrsp->bulkaddrs_val = 0;
2008 memset(spare3, 0, sizeof(struct VLCallBack));
2010 if ((code = Init_VLdbase(&ctx, LOCKREAD, this_op)))
2013 VLog(5, ("GetAddrs\n"));
2014 addrsp->bulkaddrs_val = taddrp =
2015 (afs_uint32 *) malloc(sizeof(afs_int32) * (MAXSERVERID + 1));
2016 nservers = *nentries = addrsp->bulkaddrs_len = 0;
2023 for (i = 0; i <= MAXSERVERID; i++) {
2024 if ((*taddrp = ntohl(ctx.cheader->IpMappedAddr[i]))) {
2030 addrsp->bulkaddrs_len = *nentries = nservers;
2031 return (ubik_EndTrans(ctx.trans));
2034 countAbort(this_op);
2035 ubik_AbortTrans(ctx.trans);
2039 #define PADDR(addr) VLog(0,("%d.%d.%d.%d", (addr>>24)&0xff, (addr>>16)&0xff, (addr>>8) &0xff, addr&0xff));
2042 SVL_RegisterAddrs(struct rx_call *rxcall, afsUUID *uuidp, afs_int32 spare1,
2045 int this_op = VLREGADDR;
2048 int cnt, h, i, j, k, m, base, index;
2049 struct extentaddr *exp = 0, *tex;
2051 afs_uint32 addrs[VL_MAXIPADDRS_PERMH];
2053 int count, willChangeEntry, foundUuidEntry, willReplaceCnt;
2054 int WillReplaceEntry, WillChange[MAXSERVERID + 1];
2056 int ReplaceEntry = 0;
2059 countRequest(this_op);
2060 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
2062 if ((code = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
2065 /* Eliminate duplicates from IP address list */
2066 for (k = 0, cnt = 0; k < addrsp->bulkaddrs_len; k++) {
2067 if (addrsp->bulkaddrs_val[k] == 0)
2069 for (m = 0; m < cnt; m++) {
2070 if (addrs[m] == addrsp->bulkaddrs_val[k])
2074 if (m == VL_MAXIPADDRS_PERMH) {
2076 ("Number of addresses exceeds %d. Cannot register IP addr 0x%x in VLDB\n",
2077 VL_MAXIPADDRS_PERMH, addrsp->bulkaddrs_val[k]));
2079 addrs[m] = addrsp->bulkaddrs_val[k];
2085 code = VL_INDEXERANGE;
2092 /* For each server registered within the VLDB */
2093 for (srvidx = 0; srvidx <= MAXSERVERID; srvidx++) {
2094 willChangeEntry = 0;
2095 WillReplaceEntry = 1;
2096 if ((ctx.hostaddress[srvidx] & 0xff000000) == 0xff000000) {
2097 /* The server is registered as a multihomed */
2098 base = (ctx.hostaddress[srvidx] >> 16) & 0xff;
2099 index = ctx.hostaddress[srvidx] & 0x0000ffff;
2100 if (base >= VL_MAX_ADDREXTBLKS) {
2102 ("Internal error: Multihome extent base is too large. Base %d index %d\n",
2106 if (index >= VL_MHSRV_PERBLK) {
2108 ("Internal error: Multihome extent index is too large. Base %d index %d\n",
2112 if (!ctx.ex_addr[base]) {
2114 ("Internal error: Multihome extent does not exist. Base %d\n",
2119 /* See if the addresses to register will change this server entry */
2120 exp = &ctx.ex_addr[base][index];
2121 tuuid = exp->ex_hostuuid;
2122 afs_ntohuuid(&tuuid);
2123 if (afs_uuid_equal(uuidp, &tuuid)) {
2127 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2128 if (!exp->ex_addrs[mhidx])
2130 for (k = 0; k < cnt; k++) {
2131 if (ntohl(exp->ex_addrs[mhidx]) == addrs[k]) {
2132 willChangeEntry = 1;
2133 WillChange[count] = srvidx;
2138 WillReplaceEntry = 0;
2142 /* The server is not registered as a multihomed.
2143 * See if the addresses to register will replace this server entry.
2145 for (k = 0; k < cnt; k++) {
2146 if (ctx.hostaddress[srvidx] == addrs[k]) {
2147 willChangeEntry = 1;
2148 WillChange[count] = srvidx;
2149 WillReplaceEntry = 1;
2154 if (willChangeEntry) {
2155 if (WillReplaceEntry) {
2157 ReplaceEntry = srvidx;
2163 /* If we found the uuid in the VLDB and if we are replacing another
2164 * entire entry, then complain and fail. Also, if we did not find
2165 * the uuid in the VLDB and the IP addresses being registered was
2166 * found in more than one other entry, then we don't know which one
2167 * to replace and will complain and fail.
2169 if ((foundUuidEntry && (willReplaceCnt > 0))
2170 || (!foundUuidEntry && (count > 1))) {
2172 ("The following fileserver is being registered in the VLDB:\n"));
2174 for (k = 0; k < cnt; k++) {
2181 if (foundUuidEntry) {
2183 (" It would have replaced the existing VLDB server entry:\n"));
2184 VLog(0, (" entry %d: [", FoundUuid));
2185 base = (ctx.hostaddress[FoundUuid] >> 16) & 0xff;
2186 index = ctx.hostaddress[FoundUuid] & 0x0000ffff;
2187 exp = &ctx.ex_addr[base][index];
2188 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2189 if (!exp->ex_addrs[mhidx])
2193 PADDR(ntohl(exp->ex_addrs[mhidx]));
2199 VLog(0, (" Yet another VLDB server entry exists:\n"));
2201 VLog(0, (" Yet other VLDB server entries exist:\n"));
2202 for (j = 0; j < count; j++) {
2203 srvidx = WillChange[j];
2204 VLog(0, (" entry %d: ", srvidx));
2205 if ((ctx.hostaddress[srvidx] & 0xff000000) == 0xff000000) {
2207 base = (ctx.hostaddress[srvidx] >> 16) & 0xff;
2208 index = ctx.hostaddress[srvidx] & 0x0000ffff;
2209 exp = &ctx.ex_addr[base][index];
2210 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2211 if (!exp->ex_addrs[mhidx])
2215 PADDR(ntohl(exp->ex_addrs[mhidx]));
2219 PADDR(ctx.hostaddress[srvidx]);
2225 VLog(0, (" You must 'vos changeaddr' this other server entry\n"));
2228 (" You must 'vos changeaddr' these other server entries\n"));
2231 (" and/or remove the sysid file from the registering fileserver\n"));
2232 VLog(0, (" before the fileserver can be registered in the VLDB.\n"));
2234 code = VL_MULTIPADDR;
2238 /* Passed the checks. Now find and update the existing mh entry, or create
2241 if (foundUuidEntry) {
2242 /* Found the entry with same uuid. See if we need to change it */
2245 fbase = (ctx.hostaddress[FoundUuid] >> 16) & 0xff;
2246 index = ctx.hostaddress[FoundUuid] & 0x0000ffff;
2247 exp = &ctx.ex_addr[fbase][index];
2249 /* Determine if the entry has changed */
2250 for (k = 0; ((k < cnt) && !change); k++) {
2251 if (ntohl(exp->ex_addrs[k]) != addrs[k])
2254 for (; ((k < VL_MAXIPADDRS_PERMH) && !change); k++) {
2255 if (exp->ex_addrs[k] != 0)
2259 return (ubik_EndTrans(ctx.trans));
2263 VLog(0, ("The following fileserver is being registered in the VLDB:\n"));
2265 for (k = 0; k < cnt; k++) {
2272 if (foundUuidEntry) {
2274 (" It will replace the following existing entry in the VLDB (same uuid):\n"));
2275 VLog(0, (" entry %d: [", FoundUuid));
2276 for (k = 0; k < VL_MAXIPADDRS_PERMH; k++) {
2277 if (exp->ex_addrs[k] == 0)
2281 PADDR(ntohl(exp->ex_addrs[k]));
2284 } else if (willReplaceCnt || (count == 1)) {
2285 /* If we are not replacing an entry and there is only one entry to change,
2286 * then we will replace that entry.
2288 if (!willReplaceCnt) {
2289 ReplaceEntry = WillChange[0];
2293 /* Have an entry that needs to be replaced */
2294 if ((ctx.hostaddress[ReplaceEntry] & 0xff000000) == 0xff000000) {
2295 fbase = (ctx.hostaddress[ReplaceEntry] >> 16) & 0xff;
2296 index = ctx.hostaddress[ReplaceEntry] & 0x0000ffff;
2297 exp = &ctx.ex_addr[fbase][index];
2300 (" It will replace the following existing entry in the VLDB (new uuid):\n"));
2301 VLog(0, (" entry %d: [", ReplaceEntry));
2302 for (k = 0; k < VL_MAXIPADDRS_PERMH; k++) {
2303 if (exp->ex_addrs[k] == 0)
2307 PADDR(ntohl(exp->ex_addrs[k]));
2311 /* Not a mh entry. So we have to create a new mh entry and
2312 * put it on the ReplaceEntry slot of the ctx.hostaddress array.
2314 VLog(0, (" It will replace existing entry %d, ", ReplaceEntry));
2315 PADDR(ctx.hostaddress[ReplaceEntry]);
2316 VLog(0,(", in the VLDB (new uuid):\n"));
2319 FindExtentBlock(&ctx, uuidp, 1, ReplaceEntry, &exp, &fbase);
2327 /* There is no entry for this server, must create a new mh entry as
2328 * well as use a new slot of the ctx.hostaddress array.
2330 VLog(0, (" It will create a new entry in the VLDB.\n"));
2331 code = FindExtentBlock(&ctx, uuidp, 1, -1, &exp, &fbase);
2339 /* Now we have a mh entry to fill in. Update the uuid, bump the
2340 * uniquifier, and fill in its IP addresses.
2343 afs_htonuuid(&tuuid);
2344 exp->ex_hostuuid = tuuid;
2345 exp->ex_uniquifier = htonl(ntohl(exp->ex_uniquifier) + 1);
2346 for (k = 0; k < cnt; k++) {
2347 exp->ex_addrs[k] = htonl(addrs[k]);
2349 for (; k < VL_MAXIPADDRS_PERMH; k++) {
2350 exp->ex_addrs[k] = 0;
2353 /* Write the new mh entry out */
2356 DOFFSET(ntohl(ctx.ex_addr[0]->ex_contaddrs[fbase]),
2357 (char *)ctx.ex_addr[fbase], (char *)exp), (char *)exp,
2363 /* Remove any common addresses from other mh entres. We know these entries
2364 * are being changed and not replaced so they are mh entries.
2367 for (i = 0; i < count; i++) {
2370 /* Skip the entry we replaced */
2371 if (willReplaceCnt && (WillChange[i] == ReplaceEntry))
2374 base = (ctx.hostaddress[WillChange[i]] >> 16) & 0xff;
2375 index = ctx.hostaddress[WillChange[i]] & 0x0000ffff;
2376 tex = &ctx.ex_addr[base][index];
2380 (" The following existing entries in the VLDB will be updated:\n"));
2382 VLog(0, (" entry %d: [", WillChange[i]));
2383 for (h = j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2384 if (tex->ex_addrs[j]) {
2387 PADDR(ntohl(tex->ex_addrs[j]));
2390 for (k = 0; k < cnt; k++) {
2391 if (ntohl(tex->ex_addrs[j]) == addrs[k])
2395 /* Not found, so we keep it */
2396 tex->ex_addrs[h] = tex->ex_addrs[j];
2400 for (j = h; j < VL_MAXIPADDRS_PERMH; j++) {
2401 tex->ex_addrs[j] = 0; /* zero rest of mh entry */
2405 /* Write out the modified mh entry */
2406 tex->ex_uniquifier = htonl(ntohl(tex->ex_uniquifier) + 1);
2408 DOFFSET(ntohl(ctx.ex_addr[0]->ex_contaddrs[base]),
2409 (char *)ctx.ex_addr[base], (char *)tex);
2410 if (vlwrite(ctx.trans, doff, (char *)tex, sizeof(*tex))) {
2411 ubik_AbortTrans(ctx.trans);
2416 return (ubik_EndTrans(ctx.trans));
2419 countAbort(this_op);
2420 ubik_AbortTrans(ctx.trans);
2426 SVL_GetAddrsU(struct rx_call *rxcall,
2427 struct ListAddrByAttributes *attributes,
2429 afs_int32 *uniquifier,
2430 afs_int32 *nentries,
2433 int this_op = VLGETADDRSU;
2434 afs_int32 code, index = -1, offset;
2436 int nservers, i, j, base = 0;
2437 struct extentaddr *exp = 0;
2439 afs_uint32 *taddrp, taddr;
2440 char rxstr[AFS_RXINFO_LEN];
2442 countRequest(this_op);
2443 addrsp->bulkaddrs_len = *nentries = 0;
2444 addrsp->bulkaddrs_val = 0;
2445 VLog(5, ("GetAddrsU %s\n", rxinfo(rxstr, rxcall)));
2446 if ((code = Init_VLdbase(&ctx, LOCKREAD, this_op)))
2449 if (attributes->Mask & VLADDR_IPADDR) {
2450 if (attributes->Mask & (VLADDR_INDEX | VLADDR_UUID)) {
2454 for (base = 0; base < VL_MAX_ADDREXTBLKS; base++) {
2455 if (!ctx.ex_addr[base])
2457 for (i = 1; i < VL_MHSRV_PERBLK; i++) {
2458 exp = &ctx.ex_addr[base][i];
2459 tuuid = exp->ex_hostuuid;
2460 afs_ntohuuid(&tuuid);
2461 if (afs_uuid_is_nil(&tuuid))
2463 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2464 if (exp->ex_addrs[j]
2465 && (ntohl(exp->ex_addrs[j]) == attributes->ipaddr)) {
2469 if (j < VL_MAXIPADDRS_PERMH)
2472 if (i < VL_MHSRV_PERBLK)
2475 if (base >= VL_MAX_ADDREXTBLKS) {
2479 } else if (attributes->Mask & VLADDR_INDEX) {
2480 if (attributes->Mask & (VLADDR_IPADDR | VLADDR_UUID)) {
2484 index = attributes->index;
2485 if (index < 1 || index >= (VL_MAX_ADDREXTBLKS * VL_MHSRV_PERBLK)) {
2486 code = VL_INDEXERANGE;
2489 base = index / VL_MHSRV_PERBLK;
2490 offset = index % VL_MHSRV_PERBLK;
2495 if (!ctx.ex_addr[base]) {
2496 code = VL_INDEXERANGE;
2499 exp = &ctx.ex_addr[base][offset];
2500 } else if (attributes->Mask & VLADDR_UUID) {
2501 if (attributes->Mask & (VLADDR_IPADDR | VLADDR_INDEX)) {
2505 if (!ctx.ex_addr[0]) { /* mh servers probably aren't setup on this vldb */
2509 code = FindExtentBlock(&ctx, &attributes->uuid, 0, -1, &exp, &base);
2521 addrsp->bulkaddrs_val = taddrp =
2522 (afs_uint32 *) malloc(sizeof(afs_int32) * (MAXSERVERID + 1));
2523 nservers = *nentries = addrsp->bulkaddrs_len = 0;
2528 tuuid = exp->ex_hostuuid;
2529 afs_ntohuuid(&tuuid);
2530 if (afs_uuid_is_nil(&tuuid)) {
2537 *uniquifier = ntohl(exp->ex_uniquifier);
2538 for (i = 0; i < VL_MAXIPADDRS_PERMH; i++) {
2539 if (exp->ex_addrs[i]) {
2540 taddr = ntohl(exp->ex_addrs[i]);
2541 /* Weed out duplicates */
2542 for (j = 0; j < nservers; j++) {
2543 if (taddrp[j] == taddr)
2546 if ((j == nservers) && (j <= MAXSERVERID)) {
2547 taddrp[nservers] = taddr;
2552 addrsp->bulkaddrs_len = *nentries = nservers;
2553 return (ubik_EndTrans(ctx.trans));
2556 countAbort(this_op);
2557 ubik_AbortTrans(ctx.trans);
2561 /* ============> End of Exported vldb RPC functions <============= */
2564 /* Routine that copies the given vldb entry to the output buffer, vldbentries. */
2566 put_attributeentry(struct vl_ctx *ctx,
2567 struct vldbentry **Vldbentry,
2568 struct vldbentry **VldbentryFirst,
2569 struct vldbentry **VldbentryLast,
2570 bulkentries *vldbentries,
2571 struct nvlentry *entry,
2572 afs_int32 *nentries,
2573 afs_int32 *alloccnt)
2578 if (*Vldbentry == *VldbentryLast) {
2580 return VL_SIZEEXCEEDED; /* no growing if smallMem defined */
2582 /* Allocate another set of memory; each time allocate twice as
2583 * many blocks as the last time. When we reach VLDBALLOCLIMIT,
2584 * then grow in increments of VLDBALLOCINCR.
2586 allo = (*alloccnt > VLDBALLOCLIMIT) ? VLDBALLOCINCR : *alloccnt;
2588 (vldbentry *) realloc(*VldbentryFirst,
2589 (*alloccnt + allo) * sizeof(vldbentry));
2593 *VldbentryFirst = vldbentries->bulkentries_val = reall;
2594 *Vldbentry = *VldbentryFirst + *alloccnt;
2595 *VldbentryLast = *Vldbentry + allo;
2598 vlentry_to_vldbentry(ctx, entry, *Vldbentry);
2601 vldbentries->bulkentries_len++;
2606 put_nattributeentry(struct vl_ctx *ctx,
2607 struct nvldbentry **Vldbentry,
2608 struct nvldbentry **VldbentryFirst,
2609 struct nvldbentry **VldbentryLast,
2610 nbulkentries *vldbentries,
2611 struct nvlentry *entry,
2612 afs_int32 matchtype,
2613 afs_int32 matchindex,
2614 afs_int32 *nentries,
2615 afs_int32 *alloccnt)
2620 if (*Vldbentry == *VldbentryLast) {
2622 return VL_SIZEEXCEEDED; /* no growing if smallMem defined */
2624 /* Allocate another set of memory; each time allocate twice as
2625 * many blocks as the last time. When we reach VLDBALLOCLIMIT,
2626 * then grow in increments of VLDBALLOCINCR.
2628 allo = (*alloccnt > VLDBALLOCLIMIT) ? VLDBALLOCINCR : *alloccnt;
2630 (nvldbentry *) realloc(*VldbentryFirst,
2631 (*alloccnt + allo) * sizeof(nvldbentry));
2635 *VldbentryFirst = vldbentries->nbulkentries_val = reall;
2636 *Vldbentry = *VldbentryFirst + *alloccnt;
2637 *VldbentryLast = *Vldbentry + allo;
2640 vlentry_to_nvldbentry(ctx, entry, *Vldbentry);
2641 (*Vldbentry)->matchindex = (matchtype << 16) + matchindex;
2644 vldbentries->nbulkentries_len++;
2649 /* Common code to actually remove a vldb entry from the database. */
2651 RemoveEntry(struct vl_ctx *ctx, afs_int32 entryptr,
2652 struct nvlentry *tentry)
2656 if ((code = UnthreadVLentry(ctx, entryptr, tentry)))
2658 if ((code = FreeBlock(ctx, entryptr)))
2664 ReleaseEntry(struct nvlentry *tentry, afs_int32 releasetype)
2666 if (releasetype & LOCKREL_TIMESTAMP)
2667 tentry->LockTimestamp = 0;
2668 if (releasetype & LOCKREL_OPCODE)
2669 tentry->flags &= ~VLOP_ALLOPERS;
2670 if (releasetype & LOCKREL_AFSID)
2671 tentry->LockAfsId = 0;
2675 /* Verify that the incoming vldb entry is valid; multi type of error codes
2678 check_vldbentry(struct vldbentry *aentry)
2682 if (InvalidVolname(aentry->name))
2684 if (aentry->nServers <= 0 || aentry->nServers > OMAXNSERVERS)
2685 return VL_BADSERVER;
2686 for (i = 0; i < aentry->nServers; i++) {
2687 /* if (aentry->serverNumber[i] < 0 || aentry->serverNumber[i] > MAXSERVERID)
2688 return VL_BADSERVER; */
2689 if (aentry->serverPartition[i] < 0
2690 || aentry->serverPartition[i] > MAXPARTITIONID)
2691 return VL_BADPARTITION;
2692 if (aentry->serverFlags[i] < 0
2693 || aentry->serverFlags[i] > MAXSERVERFLAG)
2694 return VL_BADSERVERFLAG;
2700 check_nvldbentry(struct nvldbentry *aentry)
2704 if (InvalidVolname(aentry->name))
2706 if (aentry->nServers <= 0 || aentry->nServers > NMAXNSERVERS)
2707 return VL_BADSERVER;
2708 for (i = 0; i < aentry->nServers; i++) {
2709 /* if (aentry->serverNumber[i] < 0 || aentry->serverNumber[i] > MAXSERVERID)
2710 return VL_BADSERVER; */
2711 if (aentry->serverPartition[i] < 0
2712 || aentry->serverPartition[i] > MAXPARTITIONID)
2713 return VL_BADPARTITION;
2714 if (aentry->serverFlags[i] < 0
2715 || aentry->serverFlags[i] > MAXSERVERFLAG)
2716 return VL_BADSERVERFLAG;
2722 /* Convert from the external vldb entry representation to its internal
2723 (more compact) form. This call should not change the hash chains! */
2725 vldbentry_to_vlentry(struct vl_ctx *ctx,
2726 struct vldbentry *VldbEntry,
2727 struct nvlentry *VlEntry)
2731 if (strcmp(VlEntry->name, VldbEntry->name))
2732 strncpy(VlEntry->name, VldbEntry->name, sizeof(VlEntry->name));
2733 for (i = 0; i < VldbEntry->nServers; i++) {
2734 serverindex = IpAddrToRelAddr(ctx, VldbEntry->serverNumber[i], 1);
2735 if (serverindex == -1)
2736 return VL_BADSERVER;
2737 VlEntry->serverNumber[i] = serverindex;
2738 VlEntry->serverPartition[i] = VldbEntry->serverPartition[i];
2739 VlEntry->serverFlags[i] = VldbEntry->serverFlags[i];
2741 for (; i < OMAXNSERVERS; i++)
2742 VlEntry->serverNumber[i] = VlEntry->serverPartition[i] =
2743 VlEntry->serverFlags[i] = BADSERVERID;
2744 for (i = 0; i < MAXTYPES; i++)
2745 VlEntry->volumeId[i] = VldbEntry->volumeId[i];
2746 VlEntry->cloneId = VldbEntry->cloneId;
2747 VlEntry->flags = VldbEntry->flags;
2752 nvldbentry_to_vlentry(struct vl_ctx *ctx,
2753 struct nvldbentry *VldbEntry,
2754 struct nvlentry *VlEntry)
2758 if (strcmp(VlEntry->name, VldbEntry->name))
2759 strncpy(VlEntry->name, VldbEntry->name, sizeof(VlEntry->name));
2760 for (i = 0; i < VldbEntry->nServers; i++) {
2761 serverindex = IpAddrToRelAddr(ctx, VldbEntry->serverNumber[i], 1);
2762 if (serverindex == -1)
2763 return VL_BADSERVER;
2764 VlEntry->serverNumber[i] = serverindex;
2765 VlEntry->serverPartition[i] = VldbEntry->serverPartition[i];
2766 VlEntry->serverFlags[i] = VldbEntry->serverFlags[i];
2768 for (; i < NMAXNSERVERS; i++)
2769 VlEntry->serverNumber[i] = VlEntry->serverPartition[i] =
2770 VlEntry->serverFlags[i] = BADSERVERID;
2771 for (i = 0; i < MAXTYPES; i++)
2772 VlEntry->volumeId[i] = VldbEntry->volumeId[i];
2773 VlEntry->cloneId = VldbEntry->cloneId;
2774 VlEntry->flags = VldbEntry->flags;
2779 /* Update the vldb entry with the new fields as indicated by the value of
2780 * the Mask entry in the updateentry structure. All necessary validation
2781 * checks are performed.
2784 get_vldbupdateentry(struct vl_ctx *ctx,
2785 afs_int32 blockindex,
2786 struct VldbUpdateEntry *updateentry,
2787 struct nvlentry *VlEntry)
2789 int i, j, code, serverindex;
2790 afs_uint32 checkids[MAXTYPES];
2792 /* check if any specified new IDs are already present in the db. Do
2793 * this check before doing anything else, so we don't get a half-
2795 memset(&checkids, 0, sizeof(checkids));
2796 if (updateentry->Mask & VLUPDATE_RWID) {
2797 checkids[RWVOL] = updateentry->spares3; /* rw id */
2799 if (updateentry->Mask & VLUPDATE_READONLYID) {
2800 checkids[ROVOL] = updateentry->ReadOnlyId;
2802 if (updateentry->Mask & VLUPDATE_BACKUPID) {
2803 checkids[BACKVOL] = updateentry->BackupId;
2806 if (EntryIDExists(ctx, checkids, MAXTYPES, &code)) {
2812 if (updateentry->Mask & VLUPDATE_VOLUMENAME) {
2813 struct nvlentry tentry;
2815 if (InvalidVolname(updateentry->name))
2818 if (FindByName(ctx, updateentry->name, &tentry, &code)) {
2819 return VL_NAMEEXIST;
2824 if ((code = UnhashVolname(ctx, blockindex, VlEntry)))
2826 strncpy(VlEntry->name, updateentry->name, sizeof(VlEntry->name));
2827 HashVolname(ctx, blockindex, VlEntry);
2830 if (updateentry->Mask & VLUPDATE_VOLNAMEHASH) {
2831 if ((code = UnhashVolname(ctx, blockindex, VlEntry))) {
2832 if (code != VL_NOENT)
2835 HashVolname(ctx, blockindex, VlEntry);
2838 if (updateentry->Mask & VLUPDATE_FLAGS) {
2839 VlEntry->flags = updateentry->flags;
2841 if (updateentry->Mask & VLUPDATE_CLONEID) {
2842 VlEntry->cloneId = updateentry->cloneId;
2844 if (updateentry->Mask & VLUPDATE_RWID) {
2845 if ((code = UnhashVolid(ctx, RWVOL, blockindex, VlEntry))) {
2846 if (code != VL_NOENT)
2849 VlEntry->volumeId[RWVOL] = updateentry->spares3; /* rw id */
2850 if ((code = HashVolid(ctx, RWVOL, blockindex, VlEntry)))
2853 if (updateentry->Mask & VLUPDATE_READONLYID) {
2854 if ((code = UnhashVolid(ctx, ROVOL, blockindex, VlEntry))) {
2855 if (code != VL_NOENT)
2858 VlEntry->volumeId[ROVOL] = updateentry->ReadOnlyId;
2859 if ((code = HashVolid(ctx, ROVOL, blockindex, VlEntry)))
2862 if (updateentry->Mask & VLUPDATE_BACKUPID) {
2863 if ((code = UnhashVolid(ctx, BACKVOL, blockindex, VlEntry))) {
2864 if (code != VL_NOENT)
2867 VlEntry->volumeId[BACKVOL] = updateentry->BackupId;
2868 if ((code = HashVolid(ctx, BACKVOL, blockindex, VlEntry)))
2871 if (updateentry->Mask & VLUPDATE_REPSITES) {
2872 if (updateentry->nModifiedRepsites <= 0
2873 || updateentry->nModifiedRepsites > OMAXNSERVERS)
2874 return VL_BADSERVER;
2875 for (i = 0; i < updateentry->nModifiedRepsites; i++) {
2876 /* if (updateentry->RepsitesTargetServer[i] < 0 || updateentry->RepsitesTargetServer[i] > MAXSERVERID)
2877 return VL_BADSERVER; */
2878 if (updateentry->RepsitesTargetPart[i] < 0
2879 || updateentry->RepsitesTargetPart[i] > MAXPARTITIONID)
2880 return VL_BADPARTITION;
2881 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_DELETE) {
2883 repsite_exists(VlEntry,
2884 IpAddrToRelAddr(ctx, updateentry->
2885 RepsitesTargetServer[i],
2887 updateentry->RepsitesTargetPart[i])) !=
2889 repsite_compress(VlEntry, j);
2891 return VL_NOREPSERVER;
2893 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_ADD) {
2894 /* if (updateentry->RepsitesNewServer[i] < 0 || updateentry->RepsitesNewServer[i] > MAXSERVERID)
2895 return VL_BADSERVER; */
2896 if (updateentry->RepsitesNewPart[i] < 0
2897 || updateentry->RepsitesNewPart[i] > MAXPARTITIONID)
2898 return VL_BADPARTITION;
2901 IpAddrToRelAddr(ctx, updateentry->RepsitesNewServer[i], 1),
2902 updateentry->RepsitesNewPart[i]) != -1)
2903 return VL_DUPREPSERVER;
2905 VlEntry->serverNumber[j] != BADSERVERID
2906 && j < OMAXNSERVERS; j++);
2907 if (j >= OMAXNSERVERS)
2910 IpAddrToRelAddr(ctx, updateentry->RepsitesNewServer[i],
2912 return VL_BADSERVER;
2913 VlEntry->serverNumber[j] = serverindex;
2914 VlEntry->serverPartition[j] = updateentry->RepsitesNewPart[i];
2915 if (updateentry->RepsitesNewFlags[i] < 0
2916 || updateentry->RepsitesNewFlags[i] > MAXSERVERFLAG)
2917 return VL_BADSERVERFLAG;
2918 VlEntry->serverFlags[j] = updateentry->RepsitesNewFlags[i];
2920 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODSERV) {
2921 /*n if (updateentry->RepsitesNewServer[i] < 0 || updateentry->RepsitesNewServer[i] > MAXSERVERID)
2922 return VL_BADSERVER; */
2924 repsite_exists(VlEntry,
2925 IpAddrToRelAddr(ctx, updateentry->
2926 RepsitesTargetServer[i],
2928 updateentry->RepsitesTargetPart[i])) !=
2930 VlEntry->serverNumber[j] =
2931 IpAddrToRelAddr(ctx, updateentry->RepsitesNewServer[i],
2934 return VL_NOREPSERVER;
2936 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODPART) {
2937 if (updateentry->RepsitesNewPart[i] < 0
2938 || updateentry->RepsitesNewPart[i] > MAXPARTITIONID)
2939 return VL_BADPARTITION;
2941 repsite_exists(VlEntry,
2942 IpAddrToRelAddr(ctx, updateentry->
2943 RepsitesTargetServer[i],
2945 updateentry->RepsitesTargetPart[i])) !=
2947 VlEntry->serverPartition[j] =
2948 updateentry->RepsitesNewPart[i];
2950 return VL_NOREPSERVER;
2952 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODFLAG) {
2954 repsite_exists(VlEntry,
2955 IpAddrToRelAddr(ctx, updateentry->
2956 RepsitesTargetServer[i],
2958 updateentry->RepsitesTargetPart[i])) !=
2960 if (updateentry->RepsitesNewFlags[i] < 0
2961 || updateentry->RepsitesNewFlags[i] > MAXSERVERFLAG)
2962 return VL_BADSERVERFLAG;
2963 VlEntry->serverFlags[j] =
2964 updateentry->RepsitesNewFlags[i];
2966 return VL_NOREPSERVER;
2974 /* Check if the specified [server,partition] entry is found in the vldb
2975 * entry's repsite table; it's offset in the table is returned, if it's
2978 repsite_exists(struct nvlentry *VlEntry, int server, int partition)
2982 for (i = 0; VlEntry->serverNumber[i] != BADSERVERID && i < OMAXNSERVERS;
2984 if ((VlEntry->serverNumber[i] == server)
2985 && (VlEntry->serverPartition[i] == partition))
2993 /* Repsite table compression: used when deleting a repsite entry so that
2994 * all active repsite entries are on the top of the table. */
2996 repsite_compress(struct nvlentry *VlEntry, int offset)
2998 int repsite_offset = offset;
3000 VlEntry->serverNumber[repsite_offset] != BADSERVERID
3001 && repsite_offset < OMAXNSERVERS - 1; repsite_offset++) {
3002 VlEntry->serverNumber[repsite_offset] =
3003 VlEntry->serverNumber[repsite_offset + 1];
3004 VlEntry->serverPartition[repsite_offset] =
3005 VlEntry->serverPartition[repsite_offset + 1];
3006 VlEntry->serverFlags[repsite_offset] =
3007 VlEntry->serverFlags[repsite_offset + 1];
3009 VlEntry->serverNumber[repsite_offset] = BADSERVERID;
3013 /* Convert from the internal (compacted) vldb entry to the external
3014 * representation used by the interface. */
3016 vlentry_to_vldbentry(struct vl_ctx *ctx, struct nvlentry *VlEntry,
3017 struct vldbentry *VldbEntry)
3021 memset(VldbEntry, 0, sizeof(struct vldbentry));
3022 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
3023 for (i = 0; i < OMAXNSERVERS; i++) {
3024 if (VlEntry->serverNumber[i] == BADSERVERID)
3026 if ((ctx->hostaddress[j = VlEntry->serverNumber[i]] & 0xff000000) ==
3028 struct extentaddr *exp;
3031 base = (ctx->hostaddress[j] >> 16) & 0xff;
3032 index = ctx->hostaddress[j] & 0x0000ffff;
3033 exp = &ctx->ex_addr[base][index];
3034 /* For now return the first ip address back */
3035 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
3036 if (exp->ex_addrs[j]) {
3037 VldbEntry->serverNumber[i] = ntohl(exp->ex_addrs[j]);
3042 VldbEntry->serverNumber[i] =
3043 ctx->hostaddress[VlEntry->serverNumber[i]];
3044 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
3045 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
3047 VldbEntry->nServers = i;
3048 for (i = 0; i < MAXTYPES; i++)
3049 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
3050 VldbEntry->cloneId = VlEntry->cloneId;
3051 VldbEntry->flags = VlEntry->flags;
3055 /* Convert from the internal (compacted) vldb entry to the external
3056 * representation used by the interface. */
3058 vlentry_to_nvldbentry(struct vl_ctx *ctx, struct nvlentry *VlEntry,
3059 struct nvldbentry *VldbEntry)
3063 memset(VldbEntry, 0, sizeof(struct nvldbentry));
3064 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
3065 for (i = 0; i < NMAXNSERVERS; i++) {
3066 if (VlEntry->serverNumber[i] == BADSERVERID)
3068 if ((ctx->hostaddress[j = VlEntry->serverNumber[i]] & 0xff000000) ==
3070 struct extentaddr *exp;
3073 base = (ctx->hostaddress[j] >> 16) & 0xff;
3074 index = ctx->hostaddress[j] & 0x0000ffff;
3075 exp = &ctx->ex_addr[base][index];
3076 /* For now return the first ip address back */
3077 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
3078 if (exp->ex_addrs[j]) {
3079 VldbEntry->serverNumber[i] = ntohl(exp->ex_addrs[j]);
3084 VldbEntry->serverNumber[i] =
3085 ctx->hostaddress[VlEntry->serverNumber[i]];
3086 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
3087 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
3089 VldbEntry->nServers = i;
3090 for (i = 0; i < MAXTYPES; i++)
3091 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
3092 VldbEntry->cloneId = VlEntry->cloneId;
3093 VldbEntry->flags = VlEntry->flags;
3097 vlentry_to_uvldbentry(struct vl_ctx *ctx, struct nvlentry *VlEntry,
3098 struct uvldbentry *VldbEntry)
3102 memset(VldbEntry, 0, sizeof(struct uvldbentry));
3103 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
3104 for (i = 0; i < NMAXNSERVERS; i++) {
3105 if (VlEntry->serverNumber[i] == BADSERVERID)
3107 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
3108 VldbEntry->serverUnique[i] = 0;
3109 if ((ctx->hostaddress[j = VlEntry->serverNumber[i]] & 0xff000000) ==
3111 struct extentaddr *exp;
3115 base = (ctx->hostaddress[j] >> 16) & 0xff;
3116 index = ctx->hostaddress[j] & 0x0000ffff;
3117 exp = &ctx->ex_addr[base][index];
3118 tuuid = exp->ex_hostuuid;
3119 afs_ntohuuid(&tuuid);
3120 VldbEntry->serverFlags[i] |= VLSERVER_FLAG_UUID;
3121 VldbEntry->serverNumber[i] = tuuid;
3122 VldbEntry->serverUnique[i] = ntohl(exp->ex_uniquifier);
3124 VldbEntry->serverNumber[i].time_low =
3125 ctx->hostaddress[VlEntry->serverNumber[i]];
3127 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
3130 VldbEntry->nServers = i;
3131 for (i = 0; i < MAXTYPES; i++)
3132 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
3133 VldbEntry->cloneId = VlEntry->cloneId;
3134 VldbEntry->flags = VlEntry->flags;
3137 #define LEGALCHARS ".ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
3140 /* Verify that the volname is a valid volume name. */
3142 InvalidVolname(char *volname)
3148 slen = strlen(volname);
3149 if (slen >= VL_MAXNAMELEN)
3151 return (slen != strspn(volname, map));
3155 /* Verify that the given volume type is valid. */
3157 InvalidVoltype(afs_int32 voltype)
3159 if (voltype != RWVOL && voltype != ROVOL && voltype != BACKVOL)
3166 InvalidOperation(afs_int32 voloper)
3168 if (voloper != VLOP_MOVE && voloper != VLOP_RELEASE
3169 && voloper != VLOP_BACKUP && voloper != VLOP_DELETE
3170 && voloper != VLOP_DUMP)
3176 InvalidReleasetype(afs_int32 releasetype)
3178 if ((releasetype & LOCKREL_TIMESTAMP) || (releasetype & LOCKREL_OPCODE)
3179 || (releasetype & LOCKREL_AFSID))
3185 IpAddrToRelAddr(struct vl_ctx *ctx, afs_uint32 ipaddr, int create)
3188 afs_int32 code, base, index;
3189 struct extentaddr *exp;
3191 for (i = 0; i <= MAXSERVERID; i++) {
3192 if (ctx->hostaddress[i] == ipaddr)
3194 if ((ctx->hostaddress[i] & 0xff000000) == 0xff000000) {
3195 base = (ctx->hostaddress[i] >> 16) & 0xff;
3196 index = ctx->hostaddress[i] & 0x0000ffff;
3197 if (base >= VL_MAX_ADDREXTBLKS) {
3199 ("Internal error: Multihome extent base is too large. Base %d index %d\n",
3201 return -1; /* EINVAL */
3203 if (index >= VL_MHSRV_PERBLK) {
3205 ("Internal error: Multihome extent index is too large. Base %d index %d\n",
3207 return -1; /* EINVAL */
3209 if (!ctx->ex_addr[base]) {
3211 ("Internal error: Multihome extent does not exist. Base %d\n",
3213 return -1; /* EINVAL */
3215 exp = &ctx->ex_addr[base][index];
3216 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
3217 if (exp->ex_addrs[j] && (ntohl(exp->ex_addrs[j]) == ipaddr)) {
3224 /* allocate the new server a server id pronto */
3226 for (i = 0; i <= MAXSERVERID; i++) {
3227 if (ctx->cheader->IpMappedAddr[i] == 0) {
3228 ctx->cheader->IpMappedAddr[i] = htonl(ipaddr);
3231 DOFFSET(0, ctx->cheader, &ctx->cheader->IpMappedAddr[i]),
3232 (char *)&ctx->cheader->IpMappedAddr[i],
3234 ctx->hostaddress[i] = ipaddr;
3245 ChangeIPAddr(struct vl_ctx *ctx, afs_uint32 ipaddr1, afs_uint32 ipaddr2)
3249 struct extentaddr *exp = NULL;
3253 afs_int32 blockindex, count;
3255 struct nvlentry tentry;
3256 int ipaddr1_id = -1, ipaddr2_id = -1;
3258 /* Don't let addr change to 256.*.*.* : Causes internal error below */
3259 if ((ipaddr2 & 0xff000000) == 0xff000000)
3260 return (VL_BADSERVER);
3262 /* If we are removing an address, ip1 will be -1 and ip2 will be
3263 * the original address. This prevents an older revision vlserver
3264 * from removing the IP address (won't find server 0xfffffff in
3265 * the VLDB). An older revision vlserver does not have the check
3266 * to see if any volumes exist on the server being removed.
3268 if (ipaddr1 == 0xffffffff) {
3273 for (i = 0; i <= MAXSERVERID; i++) {
3274 if ((ctx->hostaddress[i] & 0xff000000) == 0xff000000) {
3275 base = (ctx->hostaddress[i] >> 16) & 0xff;
3276 index = ctx->hostaddress[i] & 0x0000ffff;
3277 if ((base >= VL_MAX_ADDREXTBLKS) || (index >= VL_MHSRV_PERBLK)) {
3279 ("Internal error: Multihome extent addr is too large. Base %d index %d\n",
3281 return -1; /* EINVAL */
3284 exp = &ctx->ex_addr[base][index];
3285 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
3286 if (!exp->ex_addrs[mhidx])
3288 if (ntohl(exp->ex_addrs[mhidx]) == ipaddr1) {
3291 if (ipaddr2 != 0 && ntohl(exp->ex_addrs[mhidx]) == ipaddr2) {
3296 if (ctx->hostaddress[i] == ipaddr1) {
3300 if (ipaddr2 != 0 && ctx->hostaddress[i] == ipaddr2) {
3305 if (ipaddr1_id >= 0 && (ipaddr2 == 0 || ipaddr2_id >= 0)) {
3306 /* we've either found both IPs already in the VLDB, or we found
3307 * ipaddr1, and we're not going to find ipaddr2 because it's 0 */
3312 if (ipaddr1_id < 0) {
3313 return VL_NOENT; /* not found */
3316 if (ipaddr2_id >= 0 && ipaddr2_id != ipaddr1_id) {
3317 char buf1[16], buf2[16];
3318 VLog(0, ("Cannot change IP address from %s to %s because the latter "
3319 "is in use by server id %d\n",
3320 afs_inet_ntoa_r(htonl(ipaddr1), buf1),
3321 afs_inet_ntoa_r(htonl(ipaddr2), buf2),
3323 return VL_MULTIPADDR;
3326 /* If we are removing a server entry, a volume cannot
3327 * exist on the server. If one does, don't remove the
3328 * server entry: return error "volume entry exists".
3331 for (blockindex = NextEntry(ctx, 0, &tentry, &count); blockindex;
3332 blockindex = NextEntry(ctx, blockindex, &tentry, &count)) {
3333 if (++pollcount > 50) {
3334 #ifndef AFS_PTHREAD_ENV
3339 for (j = 0; j < NMAXNSERVERS; j++) {
3340 if (tentry.serverNumber[j] == BADSERVERID)
3342 if (tentry.serverNumber[j] == ipaddr1_id) {
3349 /* Log a message saying we are changing/removing an IP address */
3351 ("The following IP address is being %s:\n",
3352 (ipaddr2 ? "changed" : "removed")));
3353 VLog(0, (" entry %d: ", i));
3356 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
3357 if (!exp->ex_addrs[mhidx])
3361 PADDR(ntohl(exp->ex_addrs[mhidx]));
3373 /* Change the registered uuuid addresses */
3375 memset(&tuuid, 0, sizeof(afsUUID));
3376 afs_htonuuid(&tuuid);
3377 exp->ex_hostuuid = tuuid;
3380 DOFFSET(ntohl(ctx->ex_addr[0]->ex_contaddrs[base]),
3381 (char *)ctx->ex_addr[base], (char *)exp),
3382 (char *)&tuuid, sizeof(tuuid));
3387 /* Now change the host address entry */
3388 ctx->cheader->IpMappedAddr[ipaddr1_id] = htonl(ipaddr2);
3390 vlwrite(ctx->trans, DOFFSET(0, ctx->cheader, &ctx->cheader->IpMappedAddr[ipaddr1_id]),
3392 &ctx->cheader->IpMappedAddr[ipaddr1_id], sizeof(afs_int32));
3393 ctx->hostaddress[ipaddr1_id] = ipaddr2;
3400 /* see if the vlserver is back yet */
3402 SVL_ProbeServer(struct rx_call *rxcall)