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 int vlentry_to_vldbentry(struct vl_ctx *ctx,
76 struct nvlentry *VlEntry,
77 struct vldbentry *VldbEntry);
78 static int vlentry_to_nvldbentry(struct vl_ctx *ctx,
79 struct nvlentry *VlEntry,
80 struct nvldbentry *VldbEntry);
81 static int 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]++;
110 multiHomedExtentBase(struct vl_ctx *ctx, int srvidx, struct extentaddr **exp,
119 if ((ctx->hostaddress[srvidx] & 0xff000000) == 0xff000000) {
120 base = (ctx->hostaddress[srvidx] >> 16) & 0xff;
121 index = ctx->hostaddress[srvidx] & 0x0000ffff;
122 if (base >= VL_MAX_ADDREXTBLKS) {
123 VLog(0, ("Internal error: Multihome extent base is too large. "
124 "Base %d index %d\n", base, index));
127 if (index >= VL_MHSRV_PERBLK) {
128 VLog(0, ("Internal error: Multihome extent index is too large. "
129 "Base %d index %d\n", base, index));
132 if (!ctx->ex_addr[base]) {
133 VLog(0, ("Internal error: Multihome extent does not exist. "
139 *exp = &ctx->ex_addr[base][index];
146 multiHomedExtent(struct vl_ctx *ctx, int srvidx, struct extentaddr **exp)
150 return multiHomedExtentBase(ctx, srvidx, exp, &base);
153 #define AFS_RXINFO_LEN 128
155 rxkadInfo(char *str, struct rx_connection *conn, struct in_addr hostAddr)
163 code = rxkad_GetServerInfo(conn, NULL, &exp, tname, tinst, tcell,
166 snprintf(str, AFS_RXINFO_LEN,
167 "%s rxkad:%s%s%s%s%s", inet_ntoa(hostAddr), tname,
168 (tinst[0] == '\0') ? "" : ".",
169 (tinst[0] == '\0') ? "" : tinst,
170 (tcell[0] == '\0') ? "" : "@",
171 (tcell[0] == '\0') ? "" : tcell);
173 snprintf(str, AFS_RXINFO_LEN, "%s noauth", inet_ntoa(hostAddr));
178 rxinfo(char *str, struct rx_call *rxcall)
180 struct rx_connection *conn;
181 struct in_addr hostAddr;
182 rx_securityIndex authClass;
184 conn = rx_ConnectionOf(rxcall);
185 authClass = rx_SecurityClassOf(conn);
186 hostAddr.s_addr = rx_HostOf(rx_PeerOf(conn));
190 return rxkadInfo(str, conn, hostAddr);
195 snprintf(str, AFS_RXINFO_LEN, "%s noauth", inet_ntoa(hostAddr));
200 /* This is called to initialize the database, set the appropriate locks and make sure that the vldb header is valid */
202 Init_VLdbase(struct vl_ctx *ctx,
203 int locktype, /* indicate read or write transaction */
206 int code = 0, pass, wl;
208 for (pass = 1; pass <= 3; pass++) {
209 if (pass == 2) { /* take write lock to rebuild the db */
210 code = ubik_BeginTrans(VL_dbase, UBIK_WRITETRANS, &ctx->trans);
212 } else if (locktype == LOCKREAD) {
214 ubik_BeginTransReadAnyWrite(VL_dbase, UBIK_READTRANS, &ctx->trans);
217 code = ubik_BeginTrans(VL_dbase, UBIK_WRITETRANS, &ctx->trans);
223 code = ubik_SetLock(ctx->trans, 1, 1, locktype);
226 ubik_AbortTrans(ctx->trans);
230 /* check that dbase is initialized and setup cheader */
231 /* 2nd pass we try to rebuild the header */
232 code = CheckInit(ctx->trans, ((pass == 2) ? 1 : 0));
233 if (!code && wl && extent_mod)
234 code = readExtents(ctx->trans); /* Fix the mh extent blocks */
237 ubik_AbortTrans(ctx->trans);
238 /* Only rebuld if the database is empty */
239 /* Exit if can't rebuild */
240 if ((pass == 1) && (code != VL_EMPTY))
244 } else { /* No code */
246 /* The database header was rebuilt; end the write transaction.
247 * This will call vlsynccache() to copy the write header buffers
248 * to the read header buffers, before calling vlsetache().
249 * Do a third pass to re-acquire the original lock, which
250 * may be a read lock. */
251 ubik_EndTrans(ctx->trans);
253 break; /* didn't rebuild and successful - exit */
258 code = vlsetcache(ctx, locktype);
264 /* Create a new vldb entry; both new volume id and name must be unique
265 * (non-existant in vldb).
269 SVL_CreateEntry(struct rx_call *rxcall, struct vldbentry *newentry)
271 int this_op = VLCREATEENTRY;
273 afs_int32 code, blockindex;
274 struct nvlentry tentry;
275 char rxstr[AFS_RXINFO_LEN];
277 countRequest(this_op);
278 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) {
283 /* Do some validity tests on new entry */
284 if ((code = check_vldbentry(newentry))
285 || (code = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
289 ("OCreate Volume %d %s\n", newentry->volumeId[RWVOL],
290 rxinfo(rxstr, rxcall)));
291 if (EntryIDExists(&ctx, newentry->volumeId, MAXTYPES, &code)) {
292 /* at least one of the specified IDs already exists; we fail */
299 /* Is this following check (by volume name) necessary?? */
300 /* If entry already exists, we fail */
301 if (FindByName(&ctx, newentry->name, &tentry, &code)) {
308 blockindex = AllocBlock(&ctx, &tentry);
309 if (blockindex == 0) {
310 code = VL_CREATEFAIL;
314 memset(&tentry, 0, sizeof(struct nvlentry));
315 /* Convert to its internal representation; both in host byte order */
316 if ((code = vldbentry_to_vlentry(&ctx, newentry, &tentry))) {
317 FreeBlock(&ctx, blockindex);
321 /* Actually insert the entry in vldb */
322 code = ThreadVLentry(&ctx, blockindex, &tentry);
324 FreeBlock(&ctx, blockindex);
327 code = ubik_EndTrans(ctx.trans);
333 ubik_AbortTrans(ctx.trans);
336 osi_auditU(rxcall, VLCreateEntryEvent, code, AUD_STR,
337 (newentry ? newentry->name : NULL), AUD_END);
343 SVL_CreateEntryN(struct rx_call *rxcall, struct nvldbentry *newentry)
345 int this_op = VLCREATEENTRYN;
347 afs_int32 code, blockindex;
348 struct nvlentry tentry;
349 char rxstr[AFS_RXINFO_LEN];
351 countRequest(this_op);
352 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) {
357 /* Do some validity tests on new entry */
358 if ((code = check_nvldbentry(newentry))
359 || (code = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
363 ("Create Volume %d %s\n", newentry->volumeId[RWVOL],
364 rxinfo(rxstr, rxcall)));
365 if (EntryIDExists(&ctx, newentry->volumeId, MAXTYPES, &code)) {
366 /* at least one of the specified IDs already exists; we fail */
373 /* Is this following check (by volume name) necessary?? */
374 /* If entry already exists, we fail */
375 if (FindByName(&ctx, newentry->name, &tentry, &code)) {
382 blockindex = AllocBlock(&ctx, &tentry);
383 if (blockindex == 0) {
384 code = VL_CREATEFAIL;
388 memset(&tentry, 0, sizeof(struct nvlentry));
389 /* Convert to its internal representation; both in host byte order */
390 if ((code = nvldbentry_to_vlentry(&ctx, newentry, &tentry))) {
391 FreeBlock(&ctx, blockindex);
395 /* Actually insert the entry in vldb */
396 code = ThreadVLentry(&ctx, blockindex, &tentry);
398 FreeBlock(&ctx, blockindex);
401 code = ubik_EndTrans(ctx.trans);
407 ubik_AbortTrans(ctx.trans);
410 osi_auditU(rxcall, VLCreateEntryEvent, code, AUD_STR,
411 (newentry ? newentry->name : NULL), AUD_END);
417 SVL_ChangeAddr(struct rx_call *rxcall, afs_uint32 ip1, afs_uint32 ip2)
419 int this_op = VLCHANGEADDR;
422 char rxstr[AFS_RXINFO_LEN];
424 countRequest(this_op);
425 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) {
430 if ((code = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
433 VLog(1, ("Change Addr %u -> %u %s\n", ip1, ip2, rxinfo(rxstr, rxcall)));
434 if ((code = ChangeIPAddr(&ctx, ip1, ip2)))
437 code = ubik_EndTrans(ctx.trans);
443 ubik_AbortTrans(ctx.trans);
446 osi_auditU(rxcall, VLChangeAddrEvent, code, AUD_LONG, ip1, AUD_LONG,
451 /* Delete a vldb entry given the volume id. */
453 SVL_DeleteEntry(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype)
455 int this_op = VLDELETEENTRY;
457 afs_int32 blockindex, code;
458 struct nvlentry tentry;
459 char rxstr[AFS_RXINFO_LEN];
461 countRequest(this_op);
462 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
465 if ((voltype != -1) && (InvalidVoltype(voltype)))
468 if ((code = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
471 VLog(1, ("Delete Volume %u %s\n", volid, rxinfo(rxstr, rxcall)));
472 blockindex = FindByID(&ctx, volid, voltype, &tentry, &code);
473 if (blockindex == 0) { /* volid not found */
479 if (tentry.flags & VLDELETED) { /* Already deleted; return */
480 ABORT(VL_ENTDELETED);
482 if ((code = RemoveEntry(&ctx, blockindex, &tentry))) {
485 code = (ubik_EndTrans(ctx.trans));
490 ubik_AbortTrans(ctx.trans);
493 osi_auditU(rxcall, VLDeleteEntryEvent, code, AUD_LONG, volid,
499 /* Get a vldb entry given its volume id; make sure it's not a deleted entry. */
501 GetEntryByID(struct rx_call *rxcall,
504 char *aentry, /* entry data copied here */
509 afs_int32 blockindex, code;
510 struct nvlentry tentry;
511 char rxstr[AFS_RXINFO_LEN];
513 countRequest(this_op);
515 if ((voltype != -1) && (InvalidVoltype(voltype)))
516 return VL_BADVOLTYPE;
517 if ((code = Init_VLdbase(&ctx, LOCKREAD, this_op)))
520 VLog(5, ("GetVolumeByID %u (%d) %s\n", volid, new,
521 rxinfo(rxstr, rxcall)));
522 blockindex = FindByID(&ctx, volid, voltype, &tentry, &code);
523 if (blockindex == 0) { /* entry not found */
528 if (tentry.flags & VLDELETED) { /* Entry is deleted! */
529 code = VL_ENTDELETED;
532 /* Convert from the internal to external form */
534 code = vlentry_to_nvldbentry(&ctx, &tentry, (struct nvldbentry *)aentry);
536 code = vlentry_to_uvldbentry(&ctx, &tentry, (struct uvldbentry *)aentry);
538 code = vlentry_to_vldbentry(&ctx, &tentry, (struct vldbentry *)aentry);
543 return (ubik_EndTrans(ctx.trans));
547 ubik_AbortTrans(ctx.trans);
552 SVL_GetEntryByID(struct rx_call *rxcall,
555 vldbentry *aentry) /* entry data copied here */
557 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 0,
562 SVL_GetEntryByIDN(struct rx_call *rxcall,
565 nvldbentry *aentry) /* entry data copied here */
567 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 1,
572 SVL_GetEntryByIDU(struct rx_call *rxcall,
575 uvldbentry *aentry) /* entry data copied here */
577 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 2,
581 /* returns true if the id is a decimal integer, in which case we interpret
582 * it as an id. make the cache manager much simpler */
584 NameIsId(char *aname)
587 while ((tc = *aname++)) {
588 if (tc > '9' || tc < '0')
594 /* Get a vldb entry given the volume's name; of course, very similar to
595 * VLGetEntryByID() above. */
597 GetEntryByName(struct rx_call *rxcall,
599 char *aentry, /* entry data copied here */
604 afs_int32 blockindex, code;
605 struct nvlentry tentry;
606 char rxstr[AFS_RXINFO_LEN];
608 if (NameIsId(volname)) {
609 return GetEntryByID(rxcall, strtoul(volname, NULL, 10), -1, aentry, new, this_op);
611 if (InvalidVolname(volname))
613 if ((code = Init_VLdbase(&ctx, LOCKREAD, this_op)))
615 VLog(5, ("GetVolumeByName %s (%d) %s\n", volname, new, rxinfo(rxstr, rxcall)));
616 blockindex = FindByName(&ctx, volname, &tentry, &code);
617 if (blockindex == 0) { /* entry not found */
622 if (tentry.flags & VLDELETED) { /* Entry is deleted */
623 code = VL_ENTDELETED;
626 /* Convert to external entry representation */
628 code = vlentry_to_nvldbentry(&ctx, &tentry, (struct nvldbentry *)aentry);
630 code = vlentry_to_uvldbentry(&ctx, &tentry, (struct uvldbentry *)aentry);
632 code = vlentry_to_vldbentry(&ctx, &tentry, (struct vldbentry *)aentry);
637 return (ubik_EndTrans(ctx.trans));
641 ubik_AbortTrans(ctx.trans);
647 SVL_GetEntryByNameO(struct rx_call *rxcall,
649 struct vldbentry *aentry) /* entry data copied here */
651 return (GetEntryByName(rxcall, volname, (char *)aentry, 0,
657 SVL_GetEntryByNameN(struct rx_call *rxcall,
659 struct nvldbentry *aentry) /* entry data copied here */
661 return (GetEntryByName(rxcall, volname, (char *)aentry, 1,
666 SVL_GetEntryByNameU(struct rx_call *rxcall,
668 struct uvldbentry *aentry) /* entry data copied here */
670 return (GetEntryByName(rxcall, volname, (char *)aentry, 2,
676 /* Get the current value of the maximum volume id and bump the volume id counter by Maxvolidbump. */
678 SVL_GetNewVolumeId(struct rx_call *rxcall, afs_uint32 Maxvolidbump,
679 afs_uint32 *newvolumeid)
681 int this_op = VLGETNEWVOLUMEID;
683 afs_uint32 maxvolumeid;
685 char rxstr[AFS_RXINFO_LEN];
687 countRequest(this_op);
688 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
691 if (Maxvolidbump > MAXBUMPCOUNT)
692 END(VL_BADVOLIDBUMP);
694 if ((code = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
697 *newvolumeid = maxvolumeid = NextUnusedID(&ctx,
698 ntohl(ctx.cheader->vital_header.MaxVolumeId), Maxvolidbump, &code);
703 maxvolumeid += Maxvolidbump;
704 VLog(1, ("GetNewVolid newmax=%u %s\n", maxvolumeid, rxinfo(rxstr, rxcall)));
705 ctx.cheader->vital_header.MaxVolumeId = htonl(maxvolumeid);
706 if (write_vital_vlheader(&ctx)) {
709 code = (ubik_EndTrans(ctx.trans));
714 ubik_AbortTrans(ctx.trans);
717 osi_auditU(rxcall, VLGetNewVolumeIdEvent, code, AUD_END);
722 /* Simple replace the contents of the vldb entry, volid, with
723 * newentry. No individual checking/updating per field (alike
724 * VLUpdateEntry) is done. */
727 SVL_ReplaceEntry(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype,
728 struct vldbentry *newentry, afs_int32 releasetype)
730 int this_op = VLREPLACEENTRY;
732 afs_int32 blockindex, code, typeindex;
734 int hashVol[MAXTYPES];
735 struct nvlentry tentry;
736 afs_uint32 checkids[MAXTYPES];
737 char rxstr[AFS_RXINFO_LEN];
739 countRequest(this_op);
740 for (typeindex = 0; typeindex < MAXTYPES; typeindex++)
741 hashVol[typeindex] = 0;
743 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
746 if ((code = check_vldbentry(newentry)))
749 if (voltype != -1 && InvalidVoltype(voltype))
752 if (releasetype && InvalidReleasetype(releasetype))
753 END(VL_BADRELLOCKTYPE);
754 if ((code = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
757 VLog(1, ("OReplace Volume %u %s\n", volid, rxinfo(rxstr, rxcall)));
758 /* find vlentry we're changing */
759 blockindex = FindByID(&ctx, volid, voltype, &tentry, &code);
760 if (blockindex == 0) { /* entry not found */
766 /* check that we're not trying to change the RW vol ID */
767 if (newentry->volumeId[RWVOL] != tentry.volumeId[RWVOL]) {
771 /* make sure none of the IDs we are changing to are already in use */
772 memset(&checkids, 0, sizeof(checkids));
773 for (typeindex = ROVOL; typeindex < MAXTYPES; typeindex++) {
774 if (tentry.volumeId[typeindex] != newentry->volumeId[typeindex]) {
775 checkids[typeindex] = newentry->volumeId[typeindex];
778 if (EntryIDExists(&ctx, checkids, MAXTYPES, &code)) {
784 /* make sure the name we're changing to doesn't already exist */
785 if (strcmp(newentry->name, tentry.name)) {
786 struct nvlentry tmp_entry;
787 if (FindByName(&ctx, newentry->name, &tmp_entry, &code)) {
794 /* unhash volid entries if they're disappearing or changing.
795 * Remember if we need to hash in the new value (we don't have to
796 * rehash if volid stays same */
797 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
798 if (tentry.volumeId[typeindex] != newentry->volumeId[typeindex]) {
799 if (tentry.volumeId[typeindex])
801 UnhashVolid(&ctx, typeindex, blockindex, &tentry))) {
804 /* we must rehash new id if the id is different and the ID is nonzero */
805 hashVol[typeindex] = 1; /* must rehash this guy if he exists */
809 /* Rehash volname if it changes */
810 if (strcmp(newentry->name, tentry.name)) { /* Name changes; redo hashing */
811 if ((code = UnhashVolname(&ctx, blockindex, &tentry))) {
817 /* after this, tentry is new entry, not old one. vldbentry_to_vlentry
818 * doesn't touch hash chains */
819 if ((code = vldbentry_to_vlentry(&ctx, newentry, &tentry))) {
823 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
824 if (hashVol[typeindex] && tentry.volumeId[typeindex]) {
825 if ((code = HashVolid(&ctx, typeindex, blockindex, &tentry))) {
832 HashVolname(&ctx, blockindex, &tentry);
835 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
836 if (vlentrywrite(ctx.trans, blockindex, &tentry, sizeof(tentry))) {
840 END(ubik_EndTrans(ctx.trans));
844 ubik_AbortTrans(ctx.trans);
847 osi_auditU(rxcall, VLReplaceVLEntryEvent, code, AUD_LONG, volid,
853 SVL_ReplaceEntryN(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype,
854 struct nvldbentry *newentry, afs_int32 releasetype)
856 int this_op = VLREPLACEENTRYN;
858 afs_int32 blockindex, code, typeindex;
860 int hashVol[MAXTYPES];
861 struct nvlentry tentry;
862 char rxstr[AFS_RXINFO_LEN];
864 countRequest(this_op);
865 for (typeindex = 0; typeindex < MAXTYPES; typeindex++)
866 hashVol[typeindex] = 0;
868 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
871 if ((code = check_nvldbentry(newentry)))
874 if (voltype != -1 && InvalidVoltype(voltype))
877 if (releasetype && InvalidReleasetype(releasetype))
878 END(VL_BADRELLOCKTYPE);
879 if ((code = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
882 VLog(1, ("Replace Volume %u %s\n", volid, rxinfo(rxstr, rxcall)));
883 /* find vlentry we're changing */
884 blockindex = FindByID(&ctx, volid, voltype, &tentry, &code);
885 if (blockindex == 0) { /* entry not found */
891 /* check that we're not trying to change the RW vol ID */
892 if (newentry->volumeId[RWVOL] != tentry.volumeId[RWVOL]) {
896 /* unhash volid entries if they're disappearing or changing.
897 * Remember if we need to hash in the new value (we don't have to
898 * rehash if volid stays same */
899 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
900 if (tentry.volumeId[typeindex] != newentry->volumeId[typeindex]) {
901 if (tentry.volumeId[typeindex])
903 UnhashVolid(&ctx, typeindex, blockindex, &tentry))) {
906 /* we must rehash new id if the id is different and the ID is nonzero */
907 hashVol[typeindex] = 1; /* must rehash this guy if he exists */
911 /* Rehash volname if it changes */
912 if (strcmp(newentry->name, tentry.name)) { /* Name changes; redo hashing */
913 if ((code = UnhashVolname(&ctx, blockindex, &tentry))) {
919 /* after this, tentry is new entry, not old one. vldbentry_to_vlentry
920 * doesn't touch hash chains */
921 if ((code = nvldbentry_to_vlentry(&ctx, newentry, &tentry))) {
925 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
926 if (hashVol[typeindex] && tentry.volumeId[typeindex]) {
927 if ((code = HashVolid(&ctx, typeindex, blockindex, &tentry))) {
934 HashVolname(&ctx, blockindex, &tentry);
937 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
938 if (vlentrywrite(ctx.trans, blockindex, &tentry, sizeof(tentry))) {
942 END(ubik_EndTrans(ctx.trans));
946 ubik_AbortTrans(ctx.trans);
949 osi_auditU(rxcall, VLReplaceVLEntryEvent, code, AUD_LONG, volid,
955 /* Update a vldb entry (accessed thru its volume id). Almost all of the
956 * entry's fields can be modified in a single call by setting the
957 * appropriate bits in the Mask field in VldbUpdateentry. */
958 /* this routine may never have been tested; use replace entry instead
959 * unless you're brave */
961 SVL_UpdateEntry(struct rx_call *rxcall,
964 struct VldbUpdateEntry *updateentry, /* Update entry copied here */
965 afs_int32 releasetype)
967 int this_op = VLUPDATEENTRY;
969 afs_int32 blockindex, code;
970 struct nvlentry tentry;
971 char rxstr[AFS_RXINFO_LEN];
973 countRequest(this_op);
974 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
976 if ((voltype != -1) && (InvalidVoltype(voltype)))
978 if (releasetype && InvalidReleasetype(releasetype))
979 END(VL_BADRELLOCKTYPE);
980 if ((code = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
983 VLog(1, ("Update Volume %u %s\n", volid, rxinfo(rxstr, rxcall)));
984 blockindex = FindByID(&ctx, volid, voltype, &tentry, &code);
985 if (blockindex == 0) { /* entry not found */
991 /* Do the actual updating of the entry, tentry. */
993 get_vldbupdateentry(&ctx, blockindex, updateentry, &tentry))) {
997 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
998 if (vlentrywrite(ctx.trans, blockindex, &tentry, sizeof(tentry))) {
1001 END(ubik_EndTrans(ctx.trans));
1004 countAbort(this_op);
1005 ubik_AbortTrans(ctx.trans);
1008 osi_auditU(rxcall, VLUpdateEntryEvent, code, AUD_LONG, volid,
1015 SVL_UpdateEntryByName(struct rx_call *rxcall,
1017 struct VldbUpdateEntry *updateentry, /* Update entry copied here */
1018 afs_int32 releasetype)
1020 int this_op = VLUPDATEENTRYBYNAME;
1022 afs_int32 blockindex, code;
1023 struct nvlentry tentry;
1025 countRequest(this_op);
1026 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
1028 if (releasetype && InvalidReleasetype(releasetype))
1029 END(VL_BADRELLOCKTYPE);
1030 if ((code = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
1033 blockindex = FindByName(&ctx, volname, &tentry, &code);
1034 if (blockindex == 0) { /* entry not found */
1040 /* Do the actual updating of the entry, tentry. */
1042 get_vldbupdateentry(&ctx, blockindex, updateentry, &tentry))) {
1046 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
1047 if (vlentrywrite(ctx.trans, blockindex, &tentry, sizeof(tentry))) {
1050 END(ubik_EndTrans(ctx.trans));
1053 countAbort(this_op);
1054 ubik_AbortTrans(ctx.trans);
1057 osi_auditU(rxcall, VLUpdateEntryEvent, code, AUD_LONG, -1, AUD_END);
1062 /* Set a lock to the vldb entry for volid (of type voltype if not -1). */
1064 SVL_SetLock(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype,
1067 int this_op = VLSETLOCK;
1068 afs_int32 timestamp, blockindex, code;
1070 struct nvlentry tentry;
1071 char rxstr[AFS_RXINFO_LEN];
1073 countRequest(this_op);
1074 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
1076 if ((voltype != -1) && (InvalidVoltype(voltype)))
1078 if (InvalidOperation(voloper))
1080 if ((code = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
1083 VLog(1, ("SetLock Volume %u %s\n", volid, rxinfo(rxstr, rxcall)));
1084 blockindex = FindByID(&ctx, volid, voltype, &tentry, &code);
1085 if (blockindex == NULLO) {
1090 if (tentry.flags & VLDELETED) {
1091 ABORT(VL_ENTDELETED);
1093 timestamp = FT_ApproxTime();
1095 /* Check if entry is already locked; note that we unlock any entry
1096 * locked more than MAXLOCKTIME seconds */
1097 if ((tentry.LockTimestamp)
1098 && ((timestamp - tentry.LockTimestamp) < MAXLOCKTIME)) {
1099 ABORT(VL_ENTRYLOCKED);
1102 /* Consider it an unlocked entry: set current timestamp, caller
1103 * and active vol operation */
1104 tentry.LockTimestamp = timestamp;
1105 tentry.LockAfsId = 0; /* Not implemented yet */
1106 if (tentry.flags & VLOP_RELEASE) {
1107 ABORT(VL_RERELEASE);
1109 tentry.flags &= ~VLOP_ALLOPERS; /* Clear any possible older operation bit */
1110 tentry.flags |= voloper;
1112 if (vlentrywrite(ctx.trans, blockindex, &tentry, sizeof(tentry))) {
1115 END(ubik_EndTrans(ctx.trans));
1118 countAbort(this_op);
1119 ubik_AbortTrans(ctx.trans);
1122 osi_auditU(rxcall, VLSetLockEvent, code, AUD_LONG, volid, AUD_END);
1127 /* Release an already locked vldb entry. Releasetype determines what
1128 * fields (afsid and/or volume operation) will be cleared along with
1129 * the lock time stamp. */
1132 SVL_ReleaseLock(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype,
1133 afs_int32 releasetype)
1135 int this_op = VLRELEASELOCK;
1136 afs_int32 blockindex, code;
1138 struct nvlentry tentry;
1139 char rxstr[AFS_RXINFO_LEN];
1141 countRequest(this_op);
1142 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
1144 if ((voltype != -1) && (InvalidVoltype(voltype)))
1146 if (releasetype && InvalidReleasetype(releasetype))
1147 END(VL_BADRELLOCKTYPE);
1148 if ((code = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
1151 VLog(1, ("ReleaseLock Volume %u %s\n", volid, rxinfo(rxstr, rxcall)));
1152 blockindex = FindByID(&ctx, volid, voltype, &tentry, &code);
1153 if (blockindex == NULLO) {
1158 if (tentry.flags & VLDELETED) {
1159 ABORT(VL_ENTDELETED);
1162 ReleaseEntry(&tentry, releasetype); /* Unlock the appropriate fields */
1163 if (vlentrywrite(ctx.trans, blockindex, &tentry, sizeof(tentry))) {
1166 END(ubik_EndTrans(ctx.trans));
1169 countAbort(this_op);
1170 ubik_AbortTrans(ctx.trans);
1173 osi_auditU(rxcall, VLReleaseLockEvent, code, AUD_LONG, volid,
1179 /* ListEntry returns a single vldb entry, aentry, with offset previous_index;
1180 * the remaining parameters (i.e. next_index) are used so that sequential
1181 * calls to this routine will get the next (all) vldb entries.
1184 SVL_ListEntry(struct rx_call *rxcall, afs_int32 previous_index,
1185 afs_int32 *count, afs_int32 *next_index,
1186 struct vldbentry *aentry)
1188 int this_op = VLLISTENTRY;
1191 struct nvlentry tentry;
1192 char rxstr[AFS_RXINFO_LEN];
1194 countRequest(this_op);
1195 if ((code = Init_VLdbase(&ctx, LOCKREAD, this_op)))
1197 VLog(25, ("OListEntry index=%d %s\n", previous_index,
1198 rxinfo(rxstr, rxcall)));
1199 *next_index = NextEntry(&ctx, previous_index, &tentry, count);
1201 code = vlentry_to_vldbentry(&ctx, &tentry, aentry);
1203 countAbort(this_op);
1204 ubik_AbortTrans(ctx.trans);
1208 return (ubik_EndTrans(ctx.trans));
1211 /* ListEntry returns a single vldb entry, aentry, with offset previous_index;
1212 * the remaining parameters (i.e. next_index) are used so that sequential
1213 * calls to this routine will get the next (all) vldb entries.
1216 SVL_ListEntryN(struct rx_call *rxcall, afs_int32 previous_index,
1217 afs_int32 *count, afs_int32 *next_index,
1218 struct nvldbentry *aentry)
1220 int this_op = VLLISTENTRYN;
1223 struct nvlentry tentry;
1224 char rxstr[AFS_RXINFO_LEN];
1226 countRequest(this_op);
1227 if ((code = Init_VLdbase(&ctx, LOCKREAD, this_op)))
1229 VLog(25, ("ListEntry index=%d %s\n", previous_index, rxinfo(rxstr, rxcall)));
1230 *next_index = NextEntry(&ctx, previous_index, &tentry, count);
1232 code = vlentry_to_nvldbentry(&ctx, &tentry, aentry);
1234 countAbort(this_op);
1235 ubik_AbortTrans(ctx.trans);
1240 return (ubik_EndTrans(ctx.trans));
1244 /* Retrieves in vldbentries all vldb entries that match the specified
1245 * attributes (by server number, partition, volume type, and flag); if volume
1246 * id is specified then the associated list for that entry is returned.
1247 * CAUTION: This could be a very expensive call since in most cases
1248 * sequential search of all vldb entries is performed.
1251 SVL_ListAttributes(struct rx_call *rxcall,
1252 struct VldbListByAttributes *attributes,
1253 afs_int32 *nentries,
1254 bulkentries *vldbentries)
1256 int this_op = VLLISTATTRIBUTES;
1257 int code, allocCount = 0;
1259 struct nvlentry tentry;
1260 struct vldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1262 char rxstr[AFS_RXINFO_LEN];
1264 countRequest(this_op);
1265 vldbentries->bulkentries_val = 0;
1266 vldbentries->bulkentries_len = *nentries = 0;
1267 if ((code = Init_VLdbase(&ctx, LOCKREAD, this_op)))
1269 allocCount = VLDBALLOCCOUNT;
1270 Vldbentry = VldbentryFirst = vldbentries->bulkentries_val =
1271 malloc(allocCount * sizeof(vldbentry));
1272 if (Vldbentry == NULL) {
1276 VldbentryLast = VldbentryFirst + allocCount;
1277 /* Handle the attribute by volume id totally separate of the rest
1278 * (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!) */
1279 if (attributes->Mask & VLLIST_VOLUMEID) {
1280 afs_int32 blockindex;
1283 FindByID(&ctx, attributes->volumeid, -1, &tentry, &code);
1284 if (blockindex == 0) {
1290 code = put_attributeentry(&ctx, &Vldbentry, &VldbentryFirst,
1291 &VldbentryLast, vldbentries, &tentry,
1292 nentries, &allocCount);
1296 afs_int32 nextblockindex = 0, count = 0, k = 0, match = 0;
1297 while ((nextblockindex =
1298 NextEntry(&ctx, nextblockindex, &tentry, &count))) {
1299 if (++pollcount > 50) {
1300 #ifndef AFS_PTHREAD_ENV
1306 if (attributes->Mask & VLLIST_SERVER) {
1309 IpAddrToRelAddr(&ctx, attributes->server, 0)) == -1)
1311 for (k = 0; k < OMAXNSERVERS; k++) {
1312 if (tentry.serverNumber[k] == BADSERVERID)
1314 if (tentry.serverNumber[k] == serverindex) {
1322 if (attributes->Mask & VLLIST_PARTITION) {
1324 if (tentry.serverPartition[k] != attributes->partition)
1327 for (k = 0; k < OMAXNSERVERS; k++) {
1328 if (tentry.serverNumber[k] == BADSERVERID)
1330 if (tentry.serverPartition[k] ==
1331 attributes->partition) {
1341 if (attributes->Mask & VLLIST_FLAG) {
1342 if (!(tentry.flags & attributes->flag))
1345 code = put_attributeentry(&ctx, &Vldbentry, &VldbentryFirst,
1346 &VldbentryLast, vldbentries, &tentry,
1347 nentries, &allocCount);
1352 if (vldbentries->bulkentries_len
1353 && (allocCount > vldbentries->bulkentries_len)) {
1355 vldbentries->bulkentries_val =
1356 realloc(vldbentries->bulkentries_val,
1357 vldbentries->bulkentries_len * sizeof(vldbentry));
1358 if (vldbentries->bulkentries_val == NULL) {
1364 ("ListAttrs nentries=%d %s\n", vldbentries->bulkentries_len,
1365 rxinfo(rxstr, rxcall)));
1366 return (ubik_EndTrans(ctx.trans));
1369 if (vldbentries->bulkentries_val)
1370 free(vldbentries->bulkentries_val);
1371 vldbentries->bulkentries_val = 0;
1372 vldbentries->bulkentries_len = 0;
1374 countAbort(this_op);
1375 ubik_AbortTrans(ctx.trans);
1381 SVL_ListAttributesN(struct rx_call *rxcall,
1382 struct VldbListByAttributes *attributes,
1383 afs_int32 *nentries,
1384 nbulkentries *vldbentries)
1386 int this_op = VLLISTATTRIBUTESN;
1387 int code, allocCount = 0;
1389 struct nvlentry tentry;
1390 struct nvldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1392 char rxstr[AFS_RXINFO_LEN];
1394 countRequest(this_op);
1395 vldbentries->nbulkentries_val = 0;
1396 vldbentries->nbulkentries_len = *nentries = 0;
1397 if ((code = Init_VLdbase(&ctx, LOCKREAD, this_op)))
1399 allocCount = VLDBALLOCCOUNT;
1400 Vldbentry = VldbentryFirst = vldbentries->nbulkentries_val =
1401 malloc(allocCount * sizeof(nvldbentry));
1402 if (Vldbentry == NULL) {
1406 VldbentryLast = VldbentryFirst + allocCount;
1407 /* Handle the attribute by volume id totally separate of the rest
1408 * (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!) */
1409 if (attributes->Mask & VLLIST_VOLUMEID) {
1410 afs_int32 blockindex;
1413 FindByID(&ctx, attributes->volumeid, -1, &tentry, &code);
1414 if (blockindex == 0) {
1420 code = put_nattributeentry(&ctx, &Vldbentry, &VldbentryFirst,
1421 &VldbentryLast, vldbentries, &tentry,
1422 0, 0, nentries, &allocCount);
1426 afs_int32 nextblockindex = 0, count = 0, k = 0, match = 0;
1427 while ((nextblockindex =
1428 NextEntry(&ctx, nextblockindex, &tentry, &count))) {
1429 if (++pollcount > 50) {
1430 #ifndef AFS_PTHREAD_ENV
1437 if (attributes->Mask & VLLIST_SERVER) {
1440 IpAddrToRelAddr(&ctx, attributes->server, 0)) == -1)
1442 for (k = 0; k < NMAXNSERVERS; k++) {
1443 if (tentry.serverNumber[k] == BADSERVERID)
1445 if (tentry.serverNumber[k] == serverindex) {
1453 if (attributes->Mask & VLLIST_PARTITION) {
1455 if (tentry.serverPartition[k] != attributes->partition)
1458 for (k = 0; k < NMAXNSERVERS; k++) {
1459 if (tentry.serverNumber[k] == BADSERVERID)
1461 if (tentry.serverPartition[k] ==
1462 attributes->partition) {
1472 if (attributes->Mask & VLLIST_FLAG) {
1473 if (!(tentry.flags & attributes->flag))
1476 code = put_nattributeentry(&ctx, &Vldbentry, &VldbentryFirst,
1477 &VldbentryLast, vldbentries,
1478 &tentry, 0, 0, nentries, &allocCount);
1483 if (vldbentries->nbulkentries_len
1484 && (allocCount > vldbentries->nbulkentries_len)) {
1486 vldbentries->nbulkentries_val =
1487 realloc(vldbentries->nbulkentries_val,
1488 vldbentries->nbulkentries_len * sizeof(nvldbentry));
1489 if (vldbentries->nbulkentries_val == NULL) {
1495 ("NListAttrs nentries=%d %s\n", vldbentries->nbulkentries_len,
1496 rxinfo(rxstr, rxcall)));
1497 return (ubik_EndTrans(ctx.trans));
1500 countAbort(this_op);
1501 ubik_AbortTrans(ctx.trans);
1502 if (vldbentries->nbulkentries_val)
1503 free(vldbentries->nbulkentries_val);
1504 vldbentries->nbulkentries_val = 0;
1505 vldbentries->nbulkentries_len = 0;
1511 SVL_ListAttributesN2(struct rx_call *rxcall,
1512 struct VldbListByAttributes *attributes,
1513 char *name, /* Wildcarded volume name */
1514 afs_int32 startindex,
1515 afs_int32 *nentries,
1516 nbulkentries *vldbentries,
1517 afs_int32 *nextstartindex)
1519 int this_op = VLLISTATTRIBUTESN2;
1520 int code = 0, maxCount = VLDBALLOCCOUNT;
1522 struct nvlentry tentry;
1523 struct nvldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1524 afs_int32 blockindex = 0, count = 0, k, match;
1525 afs_int32 matchindex = 0;
1526 int serverindex = -1; /* no server found */
1527 int findserver = 0, findpartition = 0, findflag = 0, findname = 0;
1529 int namematchRWBK, namematchRO, thismatch;
1531 char volumename[VL_MAXNAMELEN+2]; /* regex anchors */
1532 char rxstr[AFS_RXINFO_LEN];
1533 #ifdef HAVE_POSIX_REGEX
1535 int need_regfree = 0;
1540 countRequest(this_op);
1541 vldbentries->nbulkentries_val = 0;
1542 vldbentries->nbulkentries_len = 0;
1544 *nextstartindex = -1;
1546 code = Init_VLdbase(&ctx, LOCKREAD, this_op);
1550 Vldbentry = VldbentryFirst = vldbentries->nbulkentries_val =
1551 malloc(maxCount * sizeof(nvldbentry));
1552 if (Vldbentry == NULL) {
1553 countAbort(this_op);
1554 ubik_AbortTrans(ctx.trans);
1558 VldbentryLast = VldbentryFirst + maxCount;
1560 /* Handle the attribute by volume id totally separate of the rest
1561 * (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!)
1563 if (attributes->Mask & VLLIST_VOLUMEID) {
1565 FindByID(&ctx, attributes->volumeid, -1, &tentry, &code);
1566 if (blockindex == 0) {
1571 put_nattributeentry(&ctx, &Vldbentry, &VldbentryFirst,
1572 &VldbentryLast, vldbentries, &tentry, 0,
1573 0, nentries, &maxCount);
1579 /* Search each entry in the database and return all entries
1580 * that match the request. It checks volumename (with
1581 * wildcarding), entry flags, server, and partition.
1584 /* Get the server index for matching server address */
1585 if (attributes->Mask & VLLIST_SERVER) {
1587 IpAddrToRelAddr(&ctx, attributes->server, 0);
1588 if (serverindex == -1)
1592 findpartition = ((attributes->Mask & VLLIST_PARTITION) ? 1 : 0);
1593 findflag = ((attributes->Mask & VLLIST_FLAG) ? 1 : 0);
1594 if (name && (strcmp(name, ".*") != 0) && (strcmp(name, "") != 0)) {
1595 sprintf(volumename, "^%s$", name);
1596 #ifdef HAVE_POSIX_REGEX
1597 if (regcomp(&re, volumename, REG_NOSUB) != 0) {
1603 t = (char *)re_comp(volumename);
1612 /* Read each entry and see if it is the one we want */
1613 blockindex = startindex;
1614 while ((blockindex = NextEntry(&ctx, blockindex, &tentry, &count))) {
1615 if (++pollcount > 50) {
1616 #ifndef AFS_PTHREAD_ENV
1622 /* Step through each server index searching for a match.
1623 * Match to an existing RW, BK, or RO volume name (preference
1624 * is in this order). Remember which index we matched against.
1626 namematchRWBK = namematchRO = 0; /* 0->notTried; 1->match; 2->noMatch */
1630 && (tentry.serverNumber[k] != BADSERVERID)); k++) {
1631 thismatch = 0; /* does this index match */
1633 /* Match against the RW or BK volume name. Remember
1634 * results in namematchRWBK. Prefer RW over BK.
1636 if (tentry.serverFlags[k] & VLSF_RWVOL) {
1637 /* Does the name match the RW name */
1638 if (tentry.flags & VLF_RWEXISTS) {
1640 sprintf(volumename, "%s", tentry.name);
1641 #ifdef HAVE_POSIX_REGEX
1642 if (regexec(&re, volumename, 0, NULL, 0) == 0) {
1643 thismatch = VLSF_RWVOL;
1646 if (re_exec(volumename)) {
1647 thismatch = VLSF_RWVOL;
1651 thismatch = VLSF_RWVOL;
1655 /* Does the name match the BK name */
1656 if (!thismatch && (tentry.flags & VLF_BACKEXISTS)) {
1658 sprintf(volumename, "%s.backup", tentry.name);
1659 #ifdef HAVE_POSIX_REGEX
1660 if (regexec(&re, volumename, 0, NULL, 0) == 0) {
1661 thismatch = VLSF_BACKVOL;
1664 if (re_exec(volumename)) {
1665 thismatch = VLSF_BACKVOL;
1669 thismatch = VLSF_BACKVOL;
1673 namematchRWBK = (thismatch ? 1 : 2);
1676 /* Match with the RO volume name. Compare once and
1677 * remember results in namematchRO. Note that this will
1678 * pick up entries marked NEWREPSITEs and DONTUSE.
1681 if (tentry.flags & VLF_ROEXISTS) {
1685 ((namematchRO == 1) ? VLSF_ROVOL : 0);
1687 sprintf(volumename, "%s.readonly",
1689 #ifdef HAVE_POSIX_REGEX
1690 if (regexec(&re, volumename, 0, NULL, 0) == 0) {
1691 thismatch = VLSF_ROVOL;
1694 if (re_exec(volumename))
1695 thismatch = VLSF_ROVOL;
1699 thismatch = VLSF_ROVOL;
1702 namematchRO = (thismatch ? 1 : 2);
1705 /* Is there a server match */
1706 if (thismatch && findserver
1707 && (tentry.serverNumber[k] != serverindex))
1710 /* Is there a partition match */
1711 if (thismatch && findpartition
1712 && (tentry.serverPartition[k] != attributes->partition))
1715 /* Is there a flag match */
1716 if (thismatch && findflag
1717 && !(tentry.flags & attributes->flag))
1720 /* We found a match. Remember the index, and type */
1724 matchtype = thismatch;
1727 /* Since we prefer RW and BK volume matches over RO matches,
1728 * if we have already checked the RWBK name, then we already
1729 * found the best match and so end the search.
1731 * If we tried matching against the RW, BK, and RO volume names
1732 * and both failed, then we end the search (none will match).
1734 if ((match && namematchRWBK)
1735 || ((namematchRWBK == 2) && (namematchRO == 2)))
1739 /* Passed all the tests. Take it */
1742 put_nattributeentry(&ctx, &Vldbentry, &VldbentryFirst,
1743 &VldbentryLast, vldbentries, &tentry,
1744 matchtype, matchindex, nentries,
1749 if (*nentries >= maxCount)
1750 break; /* collected the max */
1753 *nextstartindex = (blockindex ? blockindex : -1);
1757 #ifdef HAVE_POSIX_REGEX
1763 countAbort(this_op);
1764 ubik_AbortTrans(ctx.trans);
1765 if (vldbentries->nbulkentries_val)
1766 free(vldbentries->nbulkentries_val);
1767 vldbentries->nbulkentries_val = 0;
1768 vldbentries->nbulkentries_len = 0;
1769 *nextstartindex = -1;
1773 ("N2ListAttrs nentries=%d %s\n", vldbentries->nbulkentries_len,
1774 rxinfo(rxstr, rxcall)));
1775 return (ubik_EndTrans(ctx.trans));
1780 /* Retrieves in vldbentries all vldb entries that match the specified
1781 * attributes (by server number, partition, volume type, and flag); if
1782 * volume id is specified then the associated list for that entry is
1783 * returned. CAUTION: This could be a very expensive call since in most
1784 * cases sequential search of all vldb entries is performed.
1787 SVL_LinkedList(struct rx_call *rxcall,
1788 struct VldbListByAttributes *attributes,
1789 afs_int32 *nentries,
1790 vldb_list *vldbentries)
1792 int this_op = VLLINKEDLIST;
1795 struct nvlentry tentry;
1796 vldblist vllist, *vllistptr;
1797 afs_int32 blockindex, count, match;
1802 countRequest(this_op);
1803 if ((code = Init_VLdbase(&ctx, LOCKREAD, this_op)))
1807 vldbentries->node = NULL;
1808 vllistptr = &vldbentries->node;
1810 /* List by volumeid */
1811 if (attributes->Mask & VLLIST_VOLUMEID) {
1813 FindByID(&ctx, attributes->volumeid, -1, &tentry, &code);
1820 vllist = malloc(sizeof(single_vldbentry));
1821 if (vllist == NULL) {
1825 code = vlentry_to_vldbentry(&ctx, &tentry, &vllist->VldbEntry);
1829 vllist->next_vldb = NULL;
1831 *vllistptr = vllist; /* Thread onto list */
1832 vllistptr = &vllist->next_vldb;
1836 /* Search by server, partition, and flags */
1838 for (blockindex = NextEntry(&ctx, 0, &tentry, &count); blockindex;
1839 blockindex = NextEntry(&ctx, blockindex, &tentry, &count)) {
1842 if (++pollcount > 50) {
1843 #ifndef AFS_PTHREAD_ENV
1849 /* Does this volume exist on the desired server */
1850 if (attributes->Mask & VLLIST_SERVER) {
1852 IpAddrToRelAddr(&ctx, attributes->server, 0);
1853 if (serverindex == -1)
1855 for (k = 0; k < OMAXNSERVERS; k++) {
1856 if (tentry.serverNumber[k] == BADSERVERID)
1858 if (tentry.serverNumber[k] == serverindex) {
1867 /* Does this volume exist on the desired partition */
1868 if (attributes->Mask & VLLIST_PARTITION) {
1870 if (tentry.serverPartition[k] != attributes->partition)
1873 for (k = 0; k < OMAXNSERVERS; k++) {
1874 if (tentry.serverNumber[k] == BADSERVERID)
1876 if (tentry.serverPartition[k] ==
1877 attributes->partition) {
1887 /* Does this volume have the desired flags */
1888 if (attributes->Mask & VLLIST_FLAG) {
1889 if (!(tentry.flags & attributes->flag))
1893 vllist = malloc(sizeof(single_vldbentry));
1894 if (vllist == NULL) {
1898 code = vlentry_to_vldbentry(&ctx, &tentry, &vllist->VldbEntry);
1902 vllist->next_vldb = NULL;
1904 *vllistptr = vllist; /* Thread onto list */
1905 vllistptr = &vllist->next_vldb;
1907 if (smallMem && (*nentries >= VLDBALLOCCOUNT)) {
1908 code = VL_SIZEEXCEEDED;
1914 return (ubik_EndTrans(ctx.trans));
1917 countAbort(this_op);
1918 ubik_AbortTrans(ctx.trans);
1923 SVL_LinkedListN(struct rx_call *rxcall,
1924 struct VldbListByAttributes *attributes,
1925 afs_int32 *nentries,
1926 nvldb_list *vldbentries)
1928 int this_op = VLLINKEDLISTN;
1931 struct nvlentry tentry;
1932 nvldblist vllist, *vllistptr;
1933 afs_int32 blockindex, count, match;
1938 countRequest(this_op);
1939 if ((code = Init_VLdbase(&ctx, LOCKREAD, this_op)))
1943 vldbentries->node = NULL;
1944 vllistptr = &vldbentries->node;
1946 /* List by volumeid */
1947 if (attributes->Mask & VLLIST_VOLUMEID) {
1949 FindByID(&ctx, attributes->volumeid, -1, &tentry, &code);
1956 vllist = malloc(sizeof(single_nvldbentry));
1957 if (vllist == NULL) {
1961 code = vlentry_to_nvldbentry(&ctx, &tentry, &vllist->VldbEntry);
1965 vllist->next_vldb = NULL;
1967 *vllistptr = vllist; /* Thread onto list */
1968 vllistptr = &vllist->next_vldb;
1972 /* Search by server, partition, and flags */
1974 for (blockindex = NextEntry(&ctx, 0, &tentry, &count); blockindex;
1975 blockindex = NextEntry(&ctx, blockindex, &tentry, &count)) {
1978 if (++pollcount > 50) {
1979 #ifndef AFS_PTHREAD_ENV
1985 /* Does this volume exist on the desired server */
1986 if (attributes->Mask & VLLIST_SERVER) {
1988 IpAddrToRelAddr(&ctx, attributes->server, 0);
1989 if (serverindex == -1)
1991 for (k = 0; k < NMAXNSERVERS; k++) {
1992 if (tentry.serverNumber[k] == BADSERVERID)
1994 if (tentry.serverNumber[k] == serverindex) {
2003 /* Does this volume exist on the desired partition */
2004 if (attributes->Mask & VLLIST_PARTITION) {
2006 if (tentry.serverPartition[k] != attributes->partition)
2009 for (k = 0; k < NMAXNSERVERS; k++) {
2010 if (tentry.serverNumber[k] == BADSERVERID)
2012 if (tentry.serverPartition[k] ==
2013 attributes->partition) {
2023 /* Does this volume have the desired flags */
2024 if (attributes->Mask & VLLIST_FLAG) {
2025 if (!(tentry.flags & attributes->flag))
2029 vllist = malloc(sizeof(single_nvldbentry));
2030 if (vllist == NULL) {
2034 code = vlentry_to_nvldbentry(&ctx, &tentry, &vllist->VldbEntry);
2038 vllist->next_vldb = NULL;
2040 *vllistptr = vllist; /* Thread onto list */
2041 vllistptr = &vllist->next_vldb;
2043 if (smallMem && (*nentries >= VLDBALLOCCOUNT)) {
2044 code = VL_SIZEEXCEEDED;
2050 return (ubik_EndTrans(ctx.trans));
2053 countAbort(this_op);
2054 ubik_AbortTrans(ctx.trans);
2058 /* Get back vldb header statistics (allocs, frees, maxvolumeid,
2059 * totalentries, etc) and dynamic statistics (number of requests and/or
2060 * aborts per remote procedure call, etc)
2063 SVL_GetStats(struct rx_call *rxcall,
2065 vital_vlheader *vital_header)
2067 int this_op = VLGETSTATS;
2070 char rxstr[AFS_RXINFO_LEN];
2072 countRequest(this_op);
2074 /* Allow users to get statistics freely */
2075 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) /* Must be in 'UserList' to use */
2078 if ((code = Init_VLdbase(&ctx, LOCKREAD, this_op)))
2080 VLog(5, ("GetStats %s\n", rxinfo(rxstr, rxcall)));
2081 memcpy((char *)vital_header, (char *)&ctx.cheader->vital_header,
2082 sizeof(vital_vlheader));
2083 memcpy((char *)stats, (char *)&dynamic_statistics, sizeof(vldstats));
2084 return (ubik_EndTrans(ctx.trans));
2087 /* Get the list of file server addresses from the VLDB. Currently it's pretty
2088 * easy to do. In the future, it might require a little bit of grunging
2089 * through the VLDB, but that's life.
2092 SVL_GetAddrs(struct rx_call *rxcall,
2095 struct VLCallBack *spare3,
2096 afs_int32 *nentries,
2099 int this_op = VLGETADDRS;
2105 countRequest(this_op);
2106 addrsp->bulkaddrs_len = *nentries = 0;
2107 addrsp->bulkaddrs_val = 0;
2108 memset(spare3, 0, sizeof(struct VLCallBack));
2110 if ((code = Init_VLdbase(&ctx, LOCKREAD, this_op)))
2113 VLog(5, ("GetAddrs\n"));
2114 addrsp->bulkaddrs_val = taddrp =
2115 malloc(sizeof(afs_int32) * (MAXSERVERID + 1));
2116 nservers = *nentries = addrsp->bulkaddrs_len = 0;
2123 for (i = 0; i <= MAXSERVERID; i++) {
2124 if ((*taddrp = ntohl(ctx.cheader->IpMappedAddr[i]))) {
2130 addrsp->bulkaddrs_len = *nentries = nservers;
2131 return (ubik_EndTrans(ctx.trans));
2134 countAbort(this_op);
2135 ubik_AbortTrans(ctx.trans);
2140 append_addr(char *buffer, afs_uint32 addr, size_t buffer_size)
2142 int n = strlen(buffer);
2143 if (buffer_size > n) {
2144 snprintf(buffer + n, buffer_size - n, "%u.%u.%u.%u",
2145 (addr >> 24) & 0xff, (addr >> 16) & 0xff, (addr >> 8) & 0xff,
2151 SVL_RegisterAddrs(struct rx_call *rxcall, afsUUID *uuidp, afs_int32 spare1,
2154 int this_op = VLREGADDR;
2157 int cnt, h, i, j, k, m;
2158 struct extentaddr *exp = 0, *tex;
2161 afs_uint32 addrs[VL_MAXIPADDRS_PERMH];
2163 int count, willChangeEntry, foundUuidEntry, willReplaceCnt;
2164 int WillReplaceEntry, WillChange[MAXSERVERID + 1];
2166 int ReplaceEntry = 0;
2169 countRequest(this_op);
2170 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
2172 if ((code = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
2175 /* Eliminate duplicates from IP address list */
2176 for (k = 0, cnt = 0; k < addrsp->bulkaddrs_len; k++) {
2177 if (addrsp->bulkaddrs_val[k] == 0)
2179 for (m = 0; m < cnt; m++) {
2180 if (addrs[m] == addrsp->bulkaddrs_val[k])
2184 if (m == VL_MAXIPADDRS_PERMH) {
2186 ("Number of addresses exceeds %d. Cannot register IP addr 0x%x in VLDB\n",
2187 VL_MAXIPADDRS_PERMH, addrsp->bulkaddrs_val[k]));
2189 addrs[m] = addrsp->bulkaddrs_val[k];
2195 code = VL_INDEXERANGE;
2202 /* For each server registered within the VLDB */
2203 for (srvidx = 0; srvidx <= MAXSERVERID; srvidx++) {
2204 willChangeEntry = 0;
2205 WillReplaceEntry = 1;
2206 code = multiHomedExtent(&ctx, srvidx, &exp);
2211 /* See if the addresses to register will change this server entry */
2212 tuuid = exp->ex_hostuuid;
2213 afs_ntohuuid(&tuuid);
2214 if (afs_uuid_equal(uuidp, &tuuid)) {
2218 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2219 if (!exp->ex_addrs[mhidx])
2221 for (k = 0; k < cnt; k++) {
2222 if (ntohl(exp->ex_addrs[mhidx]) == addrs[k]) {
2223 willChangeEntry = 1;
2224 WillChange[count] = srvidx;
2229 WillReplaceEntry = 0;
2233 /* The server is not registered as a multihomed.
2234 * See if the addresses to register will replace this server entry.
2236 for (k = 0; k < cnt; k++) {
2237 if (ctx.hostaddress[srvidx] == addrs[k]) {
2238 willChangeEntry = 1;
2239 WillChange[count] = srvidx;
2240 WillReplaceEntry = 1;
2245 if (willChangeEntry) {
2246 if (WillReplaceEntry) {
2248 ReplaceEntry = srvidx;
2254 /* If we found the uuid in the VLDB and if we are replacing another
2255 * entire entry, then complain and fail. Also, if we did not find
2256 * the uuid in the VLDB and the IP addresses being registered was
2257 * found in more than one other entry, then we don't know which one
2258 * to replace and will complain and fail.
2260 if ((foundUuidEntry && (willReplaceCnt > 0))
2261 || (!foundUuidEntry && (count > 1))) {
2263 ("The following fileserver is being registered in the VLDB:\n"));
2264 for (addrbuf[0] = '\0', k = 0; k < cnt; k++) {
2266 strlcat(addrbuf, " ", sizeof(addrbuf));
2267 append_addr(addrbuf, addrs[k], sizeof(addrbuf));
2269 VLog(0, (" [%s]\n", addrbuf));
2271 if (foundUuidEntry) {
2272 code = multiHomedExtent(&ctx, FoundUuid, &exp);
2274 VLog(0, (" It would have replaced the existing VLDB server "
2276 for (addrbuf[0] = '\0', mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2277 if (!exp->ex_addrs[mhidx])
2280 strlcat(addrbuf, " ", sizeof(addrbuf));
2281 append_addr(addrbuf, ntohl(exp->ex_addrs[mhidx]), sizeof(addrbuf));
2283 VLog(0, (" entry %d: [%s]\n", FoundUuid, addrbuf));
2288 VLog(0, (" Yet another VLDB server entry exists:\n"));
2290 VLog(0, (" Yet other VLDB server entries exist:\n"));
2291 for (j = 0; j < count; j++) {
2292 srvidx = WillChange[j];
2293 VLog(0, (" entry %d: ", srvidx));
2295 code = multiHomedExtent(&ctx, srvidx, &exp);
2301 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2302 if (!exp->ex_addrs[mhidx])
2305 strlcat(addrbuf, " ", sizeof(addrbuf));
2306 append_addr(addrbuf, ntohl(exp->ex_addrs[mhidx]), sizeof(addrbuf));
2309 append_addr(addrbuf, ctx.hostaddress[srvidx], sizeof(addrbuf));
2311 VLog(0, (" entry %d: [%s]\n", srvidx, addrbuf));
2315 VLog(0, (" You must 'vos changeaddr' this other server entry\n"));
2318 (" You must 'vos changeaddr' these other server entries\n"));
2321 (" and/or remove the sysid file from the registering fileserver\n"));
2322 VLog(0, (" before the fileserver can be registered in the VLDB.\n"));
2324 code = VL_MULTIPADDR;
2328 /* Passed the checks. Now find and update the existing mh entry, or create
2331 if (foundUuidEntry) {
2332 /* Found the entry with same uuid. See if we need to change it */
2335 code = multiHomedExtentBase(&ctx, FoundUuid, &exp, &base);
2339 /* Determine if the entry has changed */
2340 for (k = 0; ((k < cnt) && !change); k++) {
2341 if (ntohl(exp->ex_addrs[k]) != addrs[k])
2344 for (; ((k < VL_MAXIPADDRS_PERMH) && !change); k++) {
2345 if (exp->ex_addrs[k] != 0)
2349 return (ubik_EndTrans(ctx.trans));
2353 VLog(0, ("The following fileserver is being registered in the VLDB:\n"));
2354 for (addrbuf[0] = '\0', k = 0; k < cnt; k++) {
2356 strlcat(addrbuf, " ", sizeof(addrbuf));
2357 append_addr(addrbuf, addrs[k], sizeof(addrbuf));
2359 VLog(0, (" [%s]\n", addrbuf));
2361 if (foundUuidEntry) {
2363 (" It will replace the following existing entry in the VLDB (same uuid):\n"));
2364 for (addrbuf[0] = '\0', k = 0; k < VL_MAXIPADDRS_PERMH; k++) {
2365 if (exp->ex_addrs[k] == 0)
2368 strlcat(addrbuf, " ", sizeof(addrbuf));
2369 append_addr(addrbuf, ntohl(exp->ex_addrs[k]), sizeof(addrbuf));
2371 VLog(0, (" entry %d: [%s]\n", FoundUuid, addrbuf));
2372 } else if (willReplaceCnt || (count == 1)) {
2373 /* If we are not replacing an entry and there is only one entry to change,
2374 * then we will replace that entry.
2376 if (!willReplaceCnt) {
2377 ReplaceEntry = WillChange[0];
2381 /* Have an entry that needs to be replaced */
2382 code = multiHomedExtentBase(&ctx, ReplaceEntry, &exp, &base);
2388 (" It will replace the following existing entry in the VLDB (new uuid):\n"));
2389 for (addrbuf[0] = '\0', k = 0; k < VL_MAXIPADDRS_PERMH; k++) {
2390 if (exp->ex_addrs[k] == 0)
2393 strlcat(addrbuf, " ", sizeof(addrbuf));
2394 append_addr(addrbuf, ntohl(exp->ex_addrs[k]), sizeof(addrbuf));
2396 VLog(0, (" entry %d: [%s]\n", ReplaceEntry, addrbuf));
2398 /* Not a mh entry. So we have to create a new mh entry and
2399 * put it on the ReplaceEntry slot of the ctx.hostaddress array.
2402 append_addr(addrbuf, ctx.hostaddress[ReplaceEntry], sizeof(addrbuf));
2403 VLog(0, (" It will replace existing entry %d, %s,"
2404 " in the VLDB (new uuid):\n", ReplaceEntry, addrbuf));
2406 FindExtentBlock(&ctx, uuidp, 1, ReplaceEntry, &exp, &base);
2414 /* There is no entry for this server, must create a new mh entry as
2415 * well as use a new slot of the ctx.hostaddress array.
2417 VLog(0, (" It will create a new entry in the VLDB.\n"));
2418 code = FindExtentBlock(&ctx, uuidp, 1, -1, &exp, &base);
2426 /* Now we have a mh entry to fill in. Update the uuid, bump the
2427 * uniquifier, and fill in its IP addresses.
2430 afs_htonuuid(&tuuid);
2431 exp->ex_hostuuid = tuuid;
2432 exp->ex_uniquifier = htonl(ntohl(exp->ex_uniquifier) + 1);
2433 for (k = 0; k < cnt; k++) {
2434 exp->ex_addrs[k] = htonl(addrs[k]);
2436 for (; k < VL_MAXIPADDRS_PERMH; k++) {
2437 exp->ex_addrs[k] = 0;
2440 /* Write the new mh entry out */
2443 DOFFSET(ntohl(ctx.ex_addr[0]->ex_contaddrs[base]),
2444 (char *)ctx.ex_addr[base], (char *)exp), (char *)exp,
2450 /* Remove any common addresses from other mh entres. We know these entries
2451 * are being changed and not replaced so they are mh entries.
2454 for (i = 0; i < count; i++) {
2457 /* Skip the entry we replaced */
2458 if (willReplaceCnt && (WillChange[i] == ReplaceEntry))
2461 code = multiHomedExtentBase(&ctx, WillChange[i], &tex, &base);
2467 (" The following existing entries in the VLDB will be updated:\n"));
2469 for (addrbuf[0] = '\0', h = j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2470 if (tex->ex_addrs[j]) {
2472 strlcat(addrbuf, " ", sizeof(addrbuf));
2473 append_addr(addrbuf, ntohl(tex->ex_addrs[j]), sizeof(addrbuf));
2476 for (k = 0; k < cnt; k++) {
2477 if (ntohl(tex->ex_addrs[j]) == addrs[k])
2481 /* Not found, so we keep it */
2482 tex->ex_addrs[h] = tex->ex_addrs[j];
2486 for (j = h; j < VL_MAXIPADDRS_PERMH; j++) {
2487 tex->ex_addrs[j] = 0; /* zero rest of mh entry */
2489 VLog(0, (" entry %d: [%s]\n", WillChange[i], addrbuf));
2491 /* Write out the modified mh entry */
2492 tex->ex_uniquifier = htonl(ntohl(tex->ex_uniquifier) + 1);
2494 DOFFSET(ntohl(ctx.ex_addr[0]->ex_contaddrs[base]),
2495 (char *)ctx.ex_addr[base], (char *)tex);
2496 if (vlwrite(ctx.trans, doff, (char *)tex, sizeof(*tex))) {
2502 return (ubik_EndTrans(ctx.trans));
2505 countAbort(this_op);
2506 ubik_AbortTrans(ctx.trans);
2511 SVL_GetAddrsU(struct rx_call *rxcall,
2512 struct ListAddrByAttributes *attributes,
2514 afs_int32 *uniquifier,
2515 afs_int32 *nentries,
2518 int this_op = VLGETADDRSU;
2519 afs_int32 code, index;
2521 int nservers, i, j, base = 0;
2522 struct extentaddr *exp = 0;
2524 afs_uint32 *taddrp, taddr;
2525 char rxstr[AFS_RXINFO_LEN];
2527 countRequest(this_op);
2528 addrsp->bulkaddrs_len = *nentries = 0;
2529 addrsp->bulkaddrs_val = 0;
2530 VLog(5, ("GetAddrsU %s\n", rxinfo(rxstr, rxcall)));
2531 if ((code = Init_VLdbase(&ctx, LOCKREAD, this_op)))
2534 if (attributes->Mask & VLADDR_IPADDR) {
2535 if (attributes->Mask & (VLADDR_INDEX | VLADDR_UUID)) {
2539 /* Search for a server registered with the VLDB with this ip address. */
2540 for (index = 0; index <= MAXSERVERID; index++) {
2541 code = multiHomedExtent(&ctx, index, &exp);
2546 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2547 if (exp->ex_addrs[j]
2548 && (ntohl(exp->ex_addrs[j]) == attributes->ipaddr)) {
2552 if (j < VL_MAXIPADDRS_PERMH)
2556 if (index > MAXSERVERID) {
2560 } else if (attributes->Mask & VLADDR_INDEX) {
2561 if (attributes->Mask & (VLADDR_IPADDR | VLADDR_UUID)) {
2565 /* VLADDR_INDEX index is one based */
2566 if (attributes->index < 1 || attributes->index > MAXSERVERID) {
2567 code = VL_INDEXERANGE;
2570 index = attributes->index - 1;
2571 code = multiHomedExtent(&ctx, index, &exp);
2576 } else if (attributes->Mask & VLADDR_UUID) {
2577 if (attributes->Mask & (VLADDR_IPADDR | VLADDR_INDEX)) {
2581 if (!ctx.ex_addr[0]) { /* mh servers probably aren't setup on this vldb */
2585 code = FindExtentBlock(&ctx, &attributes->uuid, 0, -1, &exp, &base);
2597 addrsp->bulkaddrs_val = taddrp =
2598 malloc(sizeof(afs_int32) * (MAXSERVERID + 1));
2599 nservers = *nentries = addrsp->bulkaddrs_len = 0;
2604 tuuid = exp->ex_hostuuid;
2605 afs_ntohuuid(&tuuid);
2606 if (afs_uuid_is_nil(&tuuid)) {
2613 *uniquifier = ntohl(exp->ex_uniquifier);
2614 for (i = 0; i < VL_MAXIPADDRS_PERMH; i++) {
2615 if (exp->ex_addrs[i]) {
2616 taddr = ntohl(exp->ex_addrs[i]);
2617 /* Weed out duplicates */
2618 for (j = 0; j < nservers; j++) {
2619 if (taddrp[j] == taddr)
2622 if ((j == nservers) && (j <= MAXSERVERID)) {
2623 taddrp[nservers] = taddr;
2628 addrsp->bulkaddrs_len = *nentries = nservers;
2629 return (ubik_EndTrans(ctx.trans));
2632 countAbort(this_op);
2633 ubik_AbortTrans(ctx.trans);
2637 /* ============> End of Exported vldb RPC functions <============= */
2640 /* Routine that copies the given vldb entry to the output buffer, vldbentries. */
2642 put_attributeentry(struct vl_ctx *ctx,
2643 struct vldbentry **Vldbentry,
2644 struct vldbentry **VldbentryFirst,
2645 struct vldbentry **VldbentryLast,
2646 bulkentries *vldbentries,
2647 struct nvlentry *entry,
2648 afs_int32 *nentries,
2649 afs_int32 *alloccnt)
2655 if (*Vldbentry == *VldbentryLast) {
2657 return VL_SIZEEXCEEDED; /* no growing if smallMem defined */
2659 /* Allocate another set of memory; each time allocate twice as
2660 * many blocks as the last time. When we reach VLDBALLOCLIMIT,
2661 * then grow in increments of VLDBALLOCINCR.
2663 allo = (*alloccnt > VLDBALLOCLIMIT) ? VLDBALLOCINCR : *alloccnt;
2664 reall = realloc(*VldbentryFirst,
2665 (*alloccnt + allo) * sizeof(vldbentry));
2669 *VldbentryFirst = vldbentries->bulkentries_val = reall;
2670 *Vldbentry = *VldbentryFirst + *alloccnt;
2671 *VldbentryLast = *Vldbentry + allo;
2675 code = vlentry_to_vldbentry(ctx, entry, *Vldbentry);
2681 vldbentries->bulkentries_len++;
2686 put_nattributeentry(struct vl_ctx *ctx,
2687 struct nvldbentry **Vldbentry,
2688 struct nvldbentry **VldbentryFirst,
2689 struct nvldbentry **VldbentryLast,
2690 nbulkentries *vldbentries,
2691 struct nvlentry *entry,
2692 afs_int32 matchtype,
2693 afs_int32 matchindex,
2694 afs_int32 *nentries,
2695 afs_int32 *alloccnt)
2701 if (*Vldbentry == *VldbentryLast) {
2703 return VL_SIZEEXCEEDED; /* no growing if smallMem defined */
2705 /* Allocate another set of memory; each time allocate twice as
2706 * many blocks as the last time. When we reach VLDBALLOCLIMIT,
2707 * then grow in increments of VLDBALLOCINCR.
2709 allo = (*alloccnt > VLDBALLOCLIMIT) ? VLDBALLOCINCR : *alloccnt;
2710 reall = realloc(*VldbentryFirst,
2711 (*alloccnt + allo) * sizeof(nvldbentry));
2715 *VldbentryFirst = vldbentries->nbulkentries_val = reall;
2716 *Vldbentry = *VldbentryFirst + *alloccnt;
2717 *VldbentryLast = *Vldbentry + allo;
2720 code = vlentry_to_nvldbentry(ctx, entry, *Vldbentry);
2724 (*Vldbentry)->matchindex = (matchtype << 16) + matchindex;
2727 vldbentries->nbulkentries_len++;
2732 /* Common code to actually remove a vldb entry from the database. */
2734 RemoveEntry(struct vl_ctx *ctx, afs_int32 entryptr,
2735 struct nvlentry *tentry)
2739 if ((code = UnthreadVLentry(ctx, entryptr, tentry)))
2741 if ((code = FreeBlock(ctx, entryptr)))
2747 ReleaseEntry(struct nvlentry *tentry, afs_int32 releasetype)
2749 if (releasetype & LOCKREL_TIMESTAMP)
2750 tentry->LockTimestamp = 0;
2751 if (releasetype & LOCKREL_OPCODE)
2752 tentry->flags &= ~VLOP_ALLOPERS;
2753 if (releasetype & LOCKREL_AFSID)
2754 tentry->LockAfsId = 0;
2758 /* Verify that the incoming vldb entry is valid; multi type of error codes
2761 check_vldbentry(struct vldbentry *aentry)
2765 if (InvalidVolname(aentry->name))
2767 if (aentry->nServers <= 0 || aentry->nServers > OMAXNSERVERS)
2768 return VL_BADSERVER;
2769 for (i = 0; i < aentry->nServers; i++) {
2770 /* if (aentry->serverNumber[i] < 0 || aentry->serverNumber[i] > MAXSERVERID)
2771 return VL_BADSERVER; */
2772 if (aentry->serverPartition[i] < 0
2773 || aentry->serverPartition[i] > MAXPARTITIONID)
2774 return VL_BADPARTITION;
2775 if (aentry->serverFlags[i] < 0
2776 || aentry->serverFlags[i] > MAXSERVERFLAG)
2777 return VL_BADSERVERFLAG;
2783 check_nvldbentry(struct nvldbentry *aentry)
2787 if (InvalidVolname(aentry->name))
2789 if (aentry->nServers <= 0 || aentry->nServers > NMAXNSERVERS)
2790 return VL_BADSERVER;
2791 for (i = 0; i < aentry->nServers; i++) {
2792 /* if (aentry->serverNumber[i] < 0 || aentry->serverNumber[i] > MAXSERVERID)
2793 return VL_BADSERVER; */
2794 if (aentry->serverPartition[i] < 0
2795 || aentry->serverPartition[i] > MAXPARTITIONID)
2796 return VL_BADPARTITION;
2797 if (aentry->serverFlags[i] < 0
2798 || aentry->serverFlags[i] > MAXSERVERFLAG)
2799 return VL_BADSERVERFLAG;
2805 /* Convert from the external vldb entry representation to its internal
2806 (more compact) form. This call should not change the hash chains! */
2808 vldbentry_to_vlentry(struct vl_ctx *ctx,
2809 struct vldbentry *VldbEntry,
2810 struct nvlentry *VlEntry)
2814 if (strcmp(VlEntry->name, VldbEntry->name))
2815 strncpy(VlEntry->name, VldbEntry->name, sizeof(VlEntry->name));
2816 for (i = 0; i < VldbEntry->nServers; i++) {
2817 serverindex = IpAddrToRelAddr(ctx, VldbEntry->serverNumber[i], 1);
2818 if (serverindex == -1)
2819 return VL_BADSERVER;
2820 VlEntry->serverNumber[i] = serverindex;
2821 VlEntry->serverPartition[i] = VldbEntry->serverPartition[i];
2822 VlEntry->serverFlags[i] = VldbEntry->serverFlags[i];
2824 for (; i < OMAXNSERVERS; i++)
2825 VlEntry->serverNumber[i] = VlEntry->serverPartition[i] =
2826 VlEntry->serverFlags[i] = BADSERVERID;
2827 for (i = 0; i < MAXTYPES; i++)
2828 VlEntry->volumeId[i] = VldbEntry->volumeId[i];
2829 VlEntry->cloneId = VldbEntry->cloneId;
2830 VlEntry->flags = VldbEntry->flags;
2835 nvldbentry_to_vlentry(struct vl_ctx *ctx,
2836 struct nvldbentry *VldbEntry,
2837 struct nvlentry *VlEntry)
2841 if (strcmp(VlEntry->name, VldbEntry->name))
2842 strncpy(VlEntry->name, VldbEntry->name, sizeof(VlEntry->name));
2843 for (i = 0; i < VldbEntry->nServers; i++) {
2844 serverindex = IpAddrToRelAddr(ctx, VldbEntry->serverNumber[i], 1);
2845 if (serverindex == -1)
2846 return VL_BADSERVER;
2847 VlEntry->serverNumber[i] = serverindex;
2848 VlEntry->serverPartition[i] = VldbEntry->serverPartition[i];
2849 VlEntry->serverFlags[i] = VldbEntry->serverFlags[i];
2851 for (; i < NMAXNSERVERS; i++)
2852 VlEntry->serverNumber[i] = VlEntry->serverPartition[i] =
2853 VlEntry->serverFlags[i] = BADSERVERID;
2854 for (i = 0; i < MAXTYPES; i++)
2855 VlEntry->volumeId[i] = VldbEntry->volumeId[i];
2856 VlEntry->cloneId = VldbEntry->cloneId;
2857 VlEntry->flags = VldbEntry->flags;
2862 /* Update the vldb entry with the new fields as indicated by the value of
2863 * the Mask entry in the updateentry structure. All necessary validation
2864 * checks are performed.
2867 get_vldbupdateentry(struct vl_ctx *ctx,
2868 afs_int32 blockindex,
2869 struct VldbUpdateEntry *updateentry,
2870 struct nvlentry *VlEntry)
2872 int i, j, code, serverindex;
2873 afs_uint32 checkids[MAXTYPES];
2875 /* check if any specified new IDs are already present in the db. Do
2876 * this check before doing anything else, so we don't get a half-
2878 memset(&checkids, 0, sizeof(checkids));
2879 if (updateentry->Mask & VLUPDATE_RWID) {
2880 checkids[RWVOL] = updateentry->spares3; /* rw id */
2882 if (updateentry->Mask & VLUPDATE_READONLYID) {
2883 checkids[ROVOL] = updateentry->ReadOnlyId;
2885 if (updateentry->Mask & VLUPDATE_BACKUPID) {
2886 checkids[BACKVOL] = updateentry->BackupId;
2889 if (EntryIDExists(ctx, checkids, MAXTYPES, &code)) {
2895 if (updateentry->Mask & VLUPDATE_VOLUMENAME) {
2896 struct nvlentry tentry;
2898 if (InvalidVolname(updateentry->name))
2901 if (FindByName(ctx, updateentry->name, &tentry, &code)) {
2902 return VL_NAMEEXIST;
2907 if ((code = UnhashVolname(ctx, blockindex, VlEntry)))
2909 strncpy(VlEntry->name, updateentry->name, sizeof(VlEntry->name));
2910 HashVolname(ctx, blockindex, VlEntry);
2913 if (updateentry->Mask & VLUPDATE_VOLNAMEHASH) {
2914 if ((code = UnhashVolname(ctx, blockindex, VlEntry))) {
2915 if (code != VL_NOENT)
2918 HashVolname(ctx, blockindex, VlEntry);
2921 if (updateentry->Mask & VLUPDATE_FLAGS) {
2922 VlEntry->flags = updateentry->flags;
2924 if (updateentry->Mask & VLUPDATE_CLONEID) {
2925 VlEntry->cloneId = updateentry->cloneId;
2927 if (updateentry->Mask & VLUPDATE_RWID) {
2928 if ((code = UnhashVolid(ctx, RWVOL, blockindex, VlEntry))) {
2929 if (code != VL_NOENT)
2932 VlEntry->volumeId[RWVOL] = updateentry->spares3; /* rw id */
2933 if ((code = HashVolid(ctx, RWVOL, blockindex, VlEntry)))
2936 if (updateentry->Mask & VLUPDATE_READONLYID) {
2937 if ((code = UnhashVolid(ctx, ROVOL, blockindex, VlEntry))) {
2938 if (code != VL_NOENT)
2941 VlEntry->volumeId[ROVOL] = updateentry->ReadOnlyId;
2942 if ((code = HashVolid(ctx, ROVOL, blockindex, VlEntry)))
2945 if (updateentry->Mask & VLUPDATE_BACKUPID) {
2946 if ((code = UnhashVolid(ctx, BACKVOL, blockindex, VlEntry))) {
2947 if (code != VL_NOENT)
2950 VlEntry->volumeId[BACKVOL] = updateentry->BackupId;
2951 if ((code = HashVolid(ctx, BACKVOL, blockindex, VlEntry)))
2954 if (updateentry->Mask & VLUPDATE_REPSITES) {
2955 if (updateentry->nModifiedRepsites <= 0
2956 || updateentry->nModifiedRepsites > OMAXNSERVERS)
2957 return VL_BADSERVER;
2958 for (i = 0; i < updateentry->nModifiedRepsites; i++) {
2959 /* if (updateentry->RepsitesTargetServer[i] < 0 || updateentry->RepsitesTargetServer[i] > MAXSERVERID)
2960 return VL_BADSERVER; */
2961 if (updateentry->RepsitesTargetPart[i] < 0
2962 || updateentry->RepsitesTargetPart[i] > MAXPARTITIONID)
2963 return VL_BADPARTITION;
2964 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_DELETE) {
2966 repsite_exists(VlEntry,
2967 IpAddrToRelAddr(ctx, updateentry->
2968 RepsitesTargetServer[i],
2970 updateentry->RepsitesTargetPart[i])) !=
2972 repsite_compress(VlEntry, j);
2974 return VL_NOREPSERVER;
2976 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_ADD) {
2977 /* if (updateentry->RepsitesNewServer[i] < 0 || updateentry->RepsitesNewServer[i] > MAXSERVERID)
2978 return VL_BADSERVER; */
2979 if (updateentry->RepsitesNewPart[i] < 0
2980 || updateentry->RepsitesNewPart[i] > MAXPARTITIONID)
2981 return VL_BADPARTITION;
2984 IpAddrToRelAddr(ctx, updateentry->RepsitesNewServer[i], 1),
2985 updateentry->RepsitesNewPart[i]) != -1)
2986 return VL_DUPREPSERVER;
2988 VlEntry->serverNumber[j] != BADSERVERID
2989 && j < OMAXNSERVERS; j++);
2990 if (j >= OMAXNSERVERS)
2993 IpAddrToRelAddr(ctx, updateentry->RepsitesNewServer[i],
2995 return VL_BADSERVER;
2996 VlEntry->serverNumber[j] = serverindex;
2997 VlEntry->serverPartition[j] = updateentry->RepsitesNewPart[i];
2998 if (updateentry->RepsitesNewFlags[i] < 0
2999 || updateentry->RepsitesNewFlags[i] > MAXSERVERFLAG)
3000 return VL_BADSERVERFLAG;
3001 VlEntry->serverFlags[j] = updateentry->RepsitesNewFlags[i];
3003 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODSERV) {
3004 /*n if (updateentry->RepsitesNewServer[i] < 0 || updateentry->RepsitesNewServer[i] > MAXSERVERID)
3005 return VL_BADSERVER; */
3007 repsite_exists(VlEntry,
3008 IpAddrToRelAddr(ctx, updateentry->
3009 RepsitesTargetServer[i],
3011 updateentry->RepsitesTargetPart[i])) !=
3013 VlEntry->serverNumber[j] =
3014 IpAddrToRelAddr(ctx, updateentry->RepsitesNewServer[i],
3017 return VL_NOREPSERVER;
3019 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODPART) {
3020 if (updateentry->RepsitesNewPart[i] < 0
3021 || updateentry->RepsitesNewPart[i] > MAXPARTITIONID)
3022 return VL_BADPARTITION;
3024 repsite_exists(VlEntry,
3025 IpAddrToRelAddr(ctx, updateentry->
3026 RepsitesTargetServer[i],
3028 updateentry->RepsitesTargetPart[i])) !=
3030 VlEntry->serverPartition[j] =
3031 updateentry->RepsitesNewPart[i];
3033 return VL_NOREPSERVER;
3035 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODFLAG) {
3037 repsite_exists(VlEntry,
3038 IpAddrToRelAddr(ctx, updateentry->
3039 RepsitesTargetServer[i],
3041 updateentry->RepsitesTargetPart[i])) !=
3043 if (updateentry->RepsitesNewFlags[i] < 0
3044 || updateentry->RepsitesNewFlags[i] > MAXSERVERFLAG)
3045 return VL_BADSERVERFLAG;
3046 VlEntry->serverFlags[j] =
3047 updateentry->RepsitesNewFlags[i];
3049 return VL_NOREPSERVER;
3057 /* Check if the specified [server,partition] entry is found in the vldb
3058 * entry's repsite table; it's offset in the table is returned, if it's
3061 repsite_exists(struct nvlentry *VlEntry, int server, int partition)
3065 for (i = 0; VlEntry->serverNumber[i] != BADSERVERID && i < OMAXNSERVERS;
3067 if ((VlEntry->serverNumber[i] == server)
3068 && (VlEntry->serverPartition[i] == partition))
3076 /* Repsite table compression: used when deleting a repsite entry so that
3077 * all active repsite entries are on the top of the table. */
3079 repsite_compress(struct nvlentry *VlEntry, int offset)
3081 int repsite_offset = offset;
3083 VlEntry->serverNumber[repsite_offset] != BADSERVERID
3084 && repsite_offset < OMAXNSERVERS - 1; repsite_offset++) {
3085 VlEntry->serverNumber[repsite_offset] =
3086 VlEntry->serverNumber[repsite_offset + 1];
3087 VlEntry->serverPartition[repsite_offset] =
3088 VlEntry->serverPartition[repsite_offset + 1];
3089 VlEntry->serverFlags[repsite_offset] =
3090 VlEntry->serverFlags[repsite_offset + 1];
3092 VlEntry->serverNumber[repsite_offset] = BADSERVERID;
3096 /* Convert from the internal (compacted) vldb entry to the external
3097 * representation used by the interface. */
3099 vlentry_to_vldbentry(struct vl_ctx *ctx, struct nvlentry *VlEntry,
3100 struct vldbentry *VldbEntry)
3103 struct extentaddr *exp;
3105 memset(VldbEntry, 0, sizeof(struct vldbentry));
3106 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
3107 for (i = 0; i < OMAXNSERVERS; i++) {
3108 if (VlEntry->serverNumber[i] == BADSERVERID)
3110 j = VlEntry->serverNumber[i];
3111 code = multiHomedExtent(ctx, VlEntry->serverNumber[i], &exp);
3115 /* For now return the first ip address back */
3116 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
3117 if (exp->ex_addrs[j]) {
3118 VldbEntry->serverNumber[i] = ntohl(exp->ex_addrs[j]);
3123 VldbEntry->serverNumber[i] =
3124 ctx->hostaddress[VlEntry->serverNumber[i]];
3125 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
3126 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
3128 VldbEntry->nServers = i;
3129 for (i = 0; i < MAXTYPES; i++)
3130 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
3131 VldbEntry->cloneId = VlEntry->cloneId;
3132 VldbEntry->flags = VlEntry->flags;
3138 /* Convert from the internal (compacted) vldb entry to the external
3139 * representation used by the interface. */
3141 vlentry_to_nvldbentry(struct vl_ctx *ctx, struct nvlentry *VlEntry,
3142 struct nvldbentry *VldbEntry)
3145 struct extentaddr *exp;
3147 memset(VldbEntry, 0, sizeof(struct nvldbentry));
3148 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
3149 for (i = 0; i < NMAXNSERVERS; i++) {
3150 if (VlEntry->serverNumber[i] == BADSERVERID)
3152 code = multiHomedExtent(ctx, VlEntry->serverNumber[i], &exp);
3157 /* For now return the first ip address back */
3158 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
3159 if (exp->ex_addrs[j]) {
3160 VldbEntry->serverNumber[i] = ntohl(exp->ex_addrs[j]);
3165 VldbEntry->serverNumber[i] =
3166 ctx->hostaddress[VlEntry->serverNumber[i]];
3167 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
3168 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
3170 VldbEntry->nServers = i;
3171 for (i = 0; i < MAXTYPES; i++)
3172 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
3173 VldbEntry->cloneId = VlEntry->cloneId;
3174 VldbEntry->flags = VlEntry->flags;
3180 vlentry_to_uvldbentry(struct vl_ctx *ctx, struct nvlentry *VlEntry,
3181 struct uvldbentry *VldbEntry)
3184 struct extentaddr *exp;
3186 memset(VldbEntry, 0, sizeof(struct uvldbentry));
3187 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
3188 for (i = 0; i < NMAXNSERVERS; i++) {
3189 if (VlEntry->serverNumber[i] == BADSERVERID)
3191 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
3192 VldbEntry->serverUnique[i] = 0;
3193 code = multiHomedExtent(ctx, VlEntry->serverNumber[i], &exp);
3200 tuuid = exp->ex_hostuuid;
3201 afs_ntohuuid(&tuuid);
3202 VldbEntry->serverFlags[i] |= VLSF_UUID;
3203 VldbEntry->serverNumber[i] = tuuid;
3204 VldbEntry->serverUnique[i] = ntohl(exp->ex_uniquifier);
3206 VldbEntry->serverNumber[i].time_low =
3207 ctx->hostaddress[VlEntry->serverNumber[i]];
3209 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
3212 VldbEntry->nServers = i;
3213 for (i = 0; i < MAXTYPES; i++)
3214 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
3215 VldbEntry->cloneId = VlEntry->cloneId;
3216 VldbEntry->flags = VlEntry->flags;
3221 #define LEGALCHARS ".ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
3224 /* Verify that the volname is a valid volume name. */
3226 InvalidVolname(char *volname)
3232 slen = strlen(volname);
3233 if (slen >= VL_MAXNAMELEN)
3235 return (slen != strspn(volname, map));
3239 /* Verify that the given volume type is valid. */
3241 InvalidVoltype(afs_int32 voltype)
3243 if (voltype != RWVOL && voltype != ROVOL && voltype != BACKVOL)
3250 InvalidOperation(afs_int32 voloper)
3252 if (voloper != VLOP_MOVE && voloper != VLOP_RELEASE
3253 && voloper != VLOP_BACKUP && voloper != VLOP_DELETE
3254 && voloper != VLOP_DUMP)
3260 InvalidReleasetype(afs_int32 releasetype)
3262 if ((releasetype & LOCKREL_TIMESTAMP) || (releasetype & LOCKREL_OPCODE)
3263 || (releasetype & LOCKREL_AFSID))
3269 IpAddrToRelAddr(struct vl_ctx *ctx, afs_uint32 ipaddr, int create)
3273 struct extentaddr *exp;
3275 for (i = 0; i <= MAXSERVERID; i++) {
3276 if (ctx->hostaddress[i] == ipaddr)
3278 code = multiHomedExtent(ctx, i, &exp);
3282 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
3283 if (exp->ex_addrs[j] && (ntohl(exp->ex_addrs[j]) == ipaddr)) {
3290 /* allocate the new server a server id pronto */
3292 for (i = 0; i <= MAXSERVERID; i++) {
3293 if (ctx->cheader->IpMappedAddr[i] == 0) {
3294 ctx->cheader->IpMappedAddr[i] = htonl(ipaddr);
3297 DOFFSET(0, ctx->cheader, &ctx->cheader->IpMappedAddr[i]),
3298 (char *)&ctx->cheader->IpMappedAddr[i],
3300 ctx->hostaddress[i] = ipaddr;
3311 ChangeIPAddr(struct vl_ctx *ctx, afs_uint32 ipaddr1, afs_uint32 ipaddr2)
3315 struct extentaddr *exp = NULL;
3319 afs_int32 blockindex, count;
3321 struct nvlentry tentry;
3322 int ipaddr1_id = -1, ipaddr2_id = -1;
3326 /* Don't let addr change to 256.*.*.* : Causes internal error below */
3327 if ((ipaddr2 & 0xff000000) == 0xff000000)
3328 return (VL_BADSERVER);
3330 /* If we are removing an address, ip1 will be -1 and ip2 will be
3331 * the original address. This prevents an older revision vlserver
3332 * from removing the IP address (won't find server 0xfffffff in
3333 * the VLDB). An older revision vlserver does not have the check
3334 * to see if any volumes exist on the server being removed.
3336 if (ipaddr1 == 0xffffffff) {
3341 for (i = 0; i <= MAXSERVERID; i++) {
3342 code = multiHomedExtentBase(ctx, i, &exp, &base);
3347 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
3348 if (!exp->ex_addrs[mhidx])
3350 if (ntohl(exp->ex_addrs[mhidx]) == ipaddr1) {
3353 if (ipaddr2 != 0 && ntohl(exp->ex_addrs[mhidx]) == ipaddr2) {
3358 if (ctx->hostaddress[i] == ipaddr1) {
3362 if (ipaddr2 != 0 && ctx->hostaddress[i] == ipaddr2) {
3367 if (ipaddr1_id >= 0 && (ipaddr2 == 0 || ipaddr2_id >= 0)) {
3368 /* we've either found both IPs already in the VLDB, or we found
3369 * ipaddr1, and we're not going to find ipaddr2 because it's 0 */
3374 if (ipaddr1_id < 0) {
3375 return VL_NOENT; /* not found */
3378 if (ipaddr2_id >= 0 && ipaddr2_id != ipaddr1_id) {
3379 char buf1[16], buf2[16];
3380 VLog(0, ("Cannot change IP address from %s to %s because the latter "
3381 "is in use by server id %d\n",
3382 afs_inet_ntoa_r(htonl(ipaddr1), buf1),
3383 afs_inet_ntoa_r(htonl(ipaddr2), buf2),
3385 return VL_MULTIPADDR;
3388 /* If we are removing a server entry, a volume cannot
3389 * exist on the server. If one does, don't remove the
3390 * server entry: return error "volume entry exists".
3393 for (blockindex = NextEntry(ctx, 0, &tentry, &count); blockindex;
3394 blockindex = NextEntry(ctx, blockindex, &tentry, &count)) {
3395 if (++pollcount > 50) {
3396 #ifndef AFS_PTHREAD_ENV
3401 for (j = 0; j < NMAXNSERVERS; j++) {
3402 if (tentry.serverNumber[j] == BADSERVERID)
3404 if (tentry.serverNumber[j] == ipaddr1_id) {
3411 /* Log a message saying we are changing/removing an IP address */
3413 ("The following IP address is being %s:\n",
3414 (ipaddr2 ? "changed" : "removed")));
3415 addrbuf1[0] = addrbuf2[0] = '\0';
3417 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
3418 if (!exp->ex_addrs[mhidx])
3421 strlcat(addrbuf1, " ", sizeof(addrbuf1));
3422 append_addr(addrbuf1, ntohl(exp->ex_addrs[mhidx]), sizeof(addrbuf1));
3425 append_addr(addrbuf1, ipaddr1, sizeof(addrbuf1));
3428 append_addr(addrbuf2, ipaddr2, sizeof(addrbuf2));
3430 VLog(0, (" entry %d: [%s] -> [%s]\n", i, addrbuf1, addrbuf2));
3432 /* Change the registered uuuid addresses */
3434 memset(&tuuid, 0, sizeof(afsUUID));
3435 afs_htonuuid(&tuuid);
3436 exp->ex_hostuuid = tuuid;
3439 DOFFSET(ntohl(ctx->ex_addr[0]->ex_contaddrs[base]),
3440 (char *)ctx->ex_addr[base], (char *)exp),
3441 (char *)&tuuid, sizeof(tuuid));
3446 /* Now change the host address entry */
3447 ctx->cheader->IpMappedAddr[ipaddr1_id] = htonl(ipaddr2);
3449 vlwrite(ctx->trans, DOFFSET(0, ctx->cheader, &ctx->cheader->IpMappedAddr[ipaddr1_id]),
3451 &ctx->cheader->IpMappedAddr[ipaddr1_id], sizeof(afs_int32));
3452 ctx->hostaddress[ipaddr1_id] = ipaddr2;
3459 /* see if the vlserver is back yet */
3461 SVL_ProbeServer(struct rx_call *rxcall)