2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include <afs/param.h>
15 #include <sys/types.h>
19 #include <afs/afsutil.h>
27 #include <netinet/in.h>
30 #include <afs/cellconfig.h>
32 #include "vlserver_internal.h"
33 #include "afs/audit.h"
37 #ifdef HAVE_POSIX_REGEX /* use POSIX regexp library */
42 extern int extent_mod;
43 extern struct afsconf_dir *vldb_confdir;
44 extern struct ubik_dbase *VL_dbase;
46 #define ABORT(c) { errorcode = (c); goto abort; }
48 #define END(c) { errorcode = (c); goto end; }
50 #define VLDBALLOCLIMIT 10000
51 #define VLDBALLOCINCR 2048
53 static int put_attributeentry(struct vl_ctx *ctx,
54 struct vldbentry **, struct vldbentry **,
55 struct vldbentry **, bulkentries *,
56 struct nvlentry *, afs_int32 *, afs_int32 *);
57 static int put_nattributeentry(struct vl_ctx *ctx,
58 struct nvldbentry **, struct nvldbentry **,
59 struct nvldbentry **, nbulkentries *,
60 struct nvlentry *, afs_int32, afs_int32,
61 afs_int32 *, afs_int32 *);
62 static int RemoveEntry(struct vl_ctx *ctx, afs_int32 entryptr,
63 struct nvlentry *tentry);
64 static void ReleaseEntry(struct nvlentry *tentry, afs_int32 releasetype);
65 static int check_vldbentry(struct vldbentry *aentry);
66 static int check_nvldbentry(struct nvldbentry *aentry);
67 static int vldbentry_to_vlentry(struct vl_ctx *ctx,
68 struct vldbentry *VldbEntry,
69 struct nvlentry *VlEntry);
70 static int nvldbentry_to_vlentry(struct vl_ctx *ctx,
71 struct nvldbentry *VldbEntry,
72 struct nvlentry *VlEntry);
73 static int get_vldbupdateentry(struct vl_ctx *ctx, afs_int32 blockindex,
74 struct VldbUpdateEntry *updateentry,
75 struct nvlentry *VlEntry);
76 static int repsite_exists(struct nvlentry *VlEntry, int server, int partition);
77 static void repsite_compress(struct nvlentry *VlEntry, int offset);
78 static void vlentry_to_vldbentry(struct vl_ctx *ctx,
79 struct nvlentry *VlEntry,
80 struct vldbentry *VldbEntry);
81 static void vlentry_to_nvldbentry(struct vl_ctx *ctx,
82 struct nvlentry *VlEntry,
83 struct nvldbentry *VldbEntry);
84 static void vlentry_to_uvldbentry(struct vl_ctx *ctx,
85 struct nvlentry *VlEntry,
86 struct uvldbentry *VldbEntry);
87 static int InvalidVolname(char *volname);
88 static int InvalidVoltype(afs_int32 voltype);
89 static int InvalidOperation(afs_int32 voloper);
90 static int InvalidReleasetype(afs_int32 releasetype);
91 static int IpAddrToRelAddr(struct vl_ctx *ctx, afs_uint32 ipaddr, int create);
92 static int ChangeIPAddr(struct vl_ctx *ctx, afs_uint32 ipaddr1,
95 #define AFS_RXINFO_LEN 128
97 rxinfo(char * str, struct rx_call *rxcall)
100 struct rx_connection *tconn;
105 struct in_addr hostAddr;
107 tconn = rx_ConnectionOf(rxcall);
108 hostAddr.s_addr = rx_HostOf(rx_PeerOf(tconn));
110 rxkad_GetServerInfo(rxcall->conn, NULL, &exp, tname, tinst, tcell,
113 sprintf(str, "%s %s%s%s%s%s", inet_ntoa(hostAddr), tname,
114 (tinst[0] == '\0') ? "" : ".",
115 (tinst[0] == '\0') ? "" : tinst,
116 (tcell[0] == '\0') ? "" : "@",
117 (tcell[0] == '\0') ? "" : tcell);
119 sprintf(str, "%s noauth", inet_ntoa(hostAddr));
123 /* This is called to initialize the database, set the appropriate locks and make sure that the vldb header is valid */
125 Init_VLdbase(struct vl_ctx *ctx,
126 int locktype, /* indicate read or write transaction */
129 int errorcode = 0, pass, wl;
131 for (pass = 1; pass <= 3; pass++) {
132 if (pass == 2) { /* take write lock to rebuild the db */
133 errorcode = ubik_BeginTrans(VL_dbase, UBIK_WRITETRANS, &ctx->trans);
135 } else if (locktype == LOCKREAD) {
137 ubik_BeginTransReadAnyWrite(VL_dbase, UBIK_READTRANS, &ctx->trans);
140 errorcode = ubik_BeginTrans(VL_dbase, UBIK_WRITETRANS, &ctx->trans);
146 errorcode = ubik_SetLock(ctx->trans, 1, 1, locktype);
149 ubik_AbortTrans(ctx->trans);
153 /* check that dbase is initialized and setup cheader */
154 /* 2nd pass we try to rebuild the header */
155 errorcode = CheckInit(ctx->trans, ((pass == 2) ? 1 : 0));
156 if (!errorcode && wl && extent_mod)
157 errorcode = readExtents(ctx->trans); /* Fix the mh extent blocks */
160 ubik_AbortTrans(ctx->trans);
161 /* Only rebuld if the database is empty */
162 /* Exit if can't rebuild */
163 if ((pass == 1) && (errorcode != VL_EMPTY))
167 } else { /* No errorcode */
169 ubik_EndTrans(ctx->trans); /* Rebuilt db. End trans, then retake original lock */
171 break; /* didn't rebuild and successful - exit */
175 if (errorcode == 0) {
176 errorcode = vlsetcache(ctx, locktype);
182 /* Create a new vldb entry; both new volume id and name must be unique
183 * (non-existant in vldb).
187 SVL_CreateEntry(struct rx_call *rxcall, struct vldbentry *newentry)
190 afs_int32 errorcode, blockindex;
191 struct nvlentry tentry;
192 char rxstr[AFS_RXINFO_LEN];
194 COUNT_REQ(VLCREATEENTRY);
195 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) {
200 /* Do some validity tests on new entry */
201 if ((errorcode = check_vldbentry(newentry))
202 || (errorcode = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
206 ("OCreate Volume %d %s\n", newentry->volumeId[RWVOL],
207 rxinfo(rxstr, rxcall)));
208 if (EntryIDExists(&ctx, newentry->volumeId, MAXTYPES, &errorcode)) {
209 /* at least one of the specified IDs already exists; we fail */
210 errorcode = VL_IDEXIST;
212 } else if (errorcode) {
216 /* Is this following check (by volume name) necessary?? */
217 /* If entry already exists, we fail */
218 if (FindByName(&ctx, newentry->name, &tentry, &errorcode)) {
219 errorcode = VL_NAMEEXIST;
221 } else if (errorcode) {
225 blockindex = AllocBlock(&ctx, &tentry);
226 if (blockindex == 0) {
227 errorcode = VL_CREATEFAIL;
231 memset(&tentry, 0, sizeof(struct nvlentry));
232 /* Convert to its internal representation; both in host byte order */
233 if ((errorcode = vldbentry_to_vlentry(&ctx, newentry, &tentry))) {
234 FreeBlock(&ctx, blockindex);
238 /* Actually insert the entry in vldb */
239 errorcode = ThreadVLentry(&ctx, blockindex, &tentry);
241 FreeBlock(&ctx, blockindex);
244 errorcode = ubik_EndTrans(ctx.trans);
250 ubik_AbortTrans(ctx.trans);
253 osi_auditU(rxcall, VLCreateEntryEvent, errorcode, AUD_STR,
254 (newentry ? newentry->name : NULL), AUD_END);
260 SVL_CreateEntryN(struct rx_call *rxcall, struct nvldbentry *newentry)
263 afs_int32 errorcode, blockindex;
264 struct nvlentry tentry;
265 char rxstr[AFS_RXINFO_LEN];
267 COUNT_REQ(VLCREATEENTRYN);
268 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) {
273 /* Do some validity tests on new entry */
274 if ((errorcode = check_nvldbentry(newentry))
275 || (errorcode = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
279 ("Create Volume %d %s\n", newentry->volumeId[RWVOL],
280 rxinfo(rxstr, rxcall)));
281 if (EntryIDExists(&ctx, newentry->volumeId, MAXTYPES, &errorcode)) {
282 /* at least one of the specified IDs already exists; we fail */
283 errorcode = VL_IDEXIST;
285 } else if (errorcode) {
289 /* Is this following check (by volume name) necessary?? */
290 /* If entry already exists, we fail */
291 if (FindByName(&ctx, newentry->name, &tentry, &errorcode)) {
292 errorcode = VL_NAMEEXIST;
294 } else if (errorcode) {
298 blockindex = AllocBlock(&ctx, &tentry);
299 if (blockindex == 0) {
300 errorcode = VL_CREATEFAIL;
304 memset(&tentry, 0, sizeof(struct nvlentry));
305 /* Convert to its internal representation; both in host byte order */
306 if ((errorcode = nvldbentry_to_vlentry(&ctx, newentry, &tentry))) {
307 FreeBlock(&ctx, blockindex);
311 /* Actually insert the entry in vldb */
312 errorcode = ThreadVLentry(&ctx, blockindex, &tentry);
314 FreeBlock(&ctx, blockindex);
317 errorcode = ubik_EndTrans(ctx.trans);
323 ubik_AbortTrans(ctx.trans);
326 osi_auditU(rxcall, VLCreateEntryEvent, errorcode, AUD_STR,
327 (newentry ? newentry->name : NULL), AUD_END);
333 SVL_ChangeAddr(struct rx_call *rxcall, afs_uint32 ip1, afs_uint32 ip2)
337 char rxstr[AFS_RXINFO_LEN];
339 COUNT_REQ(VLCHANGEADDR);
340 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) {
345 if ((errorcode = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
348 VLog(1, ("Change Addr %u -> %u %s\n", ip1, ip2, rxinfo(rxstr, rxcall)));
349 if ((errorcode = ChangeIPAddr(&ctx, ip1, ip2)))
352 errorcode = ubik_EndTrans(ctx.trans);
358 ubik_AbortTrans(ctx.trans);
361 osi_auditU(rxcall, VLChangeAddrEvent, errorcode, AUD_LONG, ip1, AUD_LONG,
366 /* Delete a vldb entry given the volume id. */
368 SVL_DeleteEntry(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype)
371 afs_int32 blockindex, errorcode;
372 struct nvlentry tentry;
373 char rxstr[AFS_RXINFO_LEN];
375 COUNT_REQ(VLDELETEENTRY);
376 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
379 if ((voltype != -1) && (InvalidVoltype(voltype)))
382 if ((errorcode = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
385 VLog(1, ("Delete Volume %u %s\n", volid, rxinfo(rxstr, rxcall)));
386 blockindex = FindByID(&ctx, volid, voltype, &tentry, &errorcode);
387 if (blockindex == 0) { /* volid not found */
389 errorcode = VL_NOENT;
393 if (tentry.flags & VLDELETED) { /* Already deleted; return */
394 ABORT(VL_ENTDELETED);
396 if ((errorcode = RemoveEntry(&ctx, blockindex, &tentry))) {
399 errorcode = (ubik_EndTrans(ctx.trans));
404 ubik_AbortTrans(ctx.trans);
407 osi_auditU(rxcall, VLDeleteEntryEvent, errorcode, AUD_LONG, volid,
413 /* Get a vldb entry given its volume id; make sure it's not a deleted entry. */
415 GetEntryByID(struct rx_call *rxcall,
418 char *aentry, /* entry data copied here */
423 afs_int32 blockindex, errorcode;
424 struct nvlentry tentry;
425 char rxstr[AFS_RXINFO_LEN];
427 if ((voltype != -1) && (InvalidVoltype(voltype)))
428 return VL_BADVOLTYPE;
429 if ((errorcode = Init_VLdbase(&ctx, LOCKREAD, this_op)))
432 VLog(5, ("GetVolumeByID %u (%d) %s\n", volid, new,
433 rxinfo(rxstr, rxcall)));
434 blockindex = FindByID(&ctx, volid, voltype, &tentry, &errorcode);
435 if (blockindex == 0) { /* entry not found */
437 errorcode = VL_NOENT;
439 ubik_AbortTrans(ctx.trans);
442 if (tentry.flags & VLDELETED) { /* Entry is deleted! */
444 ubik_AbortTrans(ctx.trans);
445 return VL_ENTDELETED;
447 /* Convert from the internal to external form */
449 vlentry_to_nvldbentry(&ctx, &tentry, (struct nvldbentry *)aentry);
451 vlentry_to_uvldbentry(&ctx, &tentry, (struct uvldbentry *)aentry);
453 vlentry_to_vldbentry(&ctx, &tentry, (struct vldbentry *)aentry);
454 return (ubik_EndTrans(ctx.trans));
458 SVL_GetEntryByID(struct rx_call *rxcall,
461 vldbentry *aentry) /* entry data copied here */
463 COUNT_REQ(VLGETENTRYBYID);
464 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 0, this_op));
468 SVL_GetEntryByIDN(struct rx_call *rxcall,
471 nvldbentry *aentry) /* entry data copied here */
473 COUNT_REQ(VLGETENTRYBYIDN);
474 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 1, this_op));
478 SVL_GetEntryByIDU(struct rx_call *rxcall,
481 uvldbentry *aentry) /* entry data copied here */
483 COUNT_REQ(VLGETENTRYBYIDU);
484 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 2, this_op));
489 /* returns true if the id is a decimal integer, in which case we interpret
490 * it as an id. make the cache manager much simpler */
492 NameIsId(char *aname)
495 while ((tc = *aname++)) {
496 if (tc > '9' || tc < '0')
502 /* Get a vldb entry given the volume's name; of course, very similar to
503 * VLGetEntryByID() above. */
505 GetEntryByName(struct rx_call *rxcall,
507 char *aentry, /* entry data copied here */
512 afs_int32 blockindex, errorcode;
513 struct nvlentry tentry;
514 char rxstr[AFS_RXINFO_LEN];
516 if (NameIsId(volname)) {
517 return GetEntryByID(rxcall, atoi(volname), -1, aentry, new, this_op);
519 if (InvalidVolname(volname))
521 if ((errorcode = Init_VLdbase(&ctx, LOCKREAD, this_op)))
523 VLog(5, ("GetVolumeByName %s (%d) %s\n", volname, new, rxinfo(rxstr, rxcall)));
524 blockindex = FindByName(&ctx, volname, &tentry, &errorcode);
525 if (blockindex == 0) { /* entry not found */
527 errorcode = VL_NOENT;
529 ubik_AbortTrans(ctx.trans);
532 if (tentry.flags & VLDELETED) { /* Entry is deleted */
534 ubik_AbortTrans(ctx.trans);
535 return VL_ENTDELETED;
537 /* Convert to external entry representation */
539 vlentry_to_nvldbentry(&ctx, &tentry, (struct nvldbentry *)aentry);
541 vlentry_to_uvldbentry(&ctx, &tentry, (struct uvldbentry *)aentry);
543 vlentry_to_vldbentry(&ctx, &tentry, (struct vldbentry *)aentry);
544 return (ubik_EndTrans(ctx.trans));
548 SVL_GetEntryByNameO(struct rx_call *rxcall,
550 struct vldbentry *aentry) /* entry data copied here */
552 COUNT_REQ(VLGETENTRYBYNAME);
553 return (GetEntryByName(rxcall, volname, (char *)aentry, 0, this_op));
558 SVL_GetEntryByNameN(struct rx_call *rxcall,
560 struct nvldbentry *aentry) /* entry data copied here */
562 COUNT_REQ(VLGETENTRYBYNAMEN);
563 return (GetEntryByName(rxcall, volname, (char *)aentry, 1, this_op));
567 SVL_GetEntryByNameU(struct rx_call *rxcall,
569 struct uvldbentry *aentry) /* entry data copied here */
571 COUNT_REQ(VLGETENTRYBYNAMEU);
572 return (GetEntryByName(rxcall, volname, (char *)aentry, 2, this_op));
577 /* Get the current value of the maximum volume id and bump the volume id counter by Maxvolidbump. */
579 SVL_GetNewVolumeId(struct rx_call *rxcall, afs_uint32 Maxvolidbump,
580 afs_uint32 *newvolumeid)
583 afs_uint32 maxvolumeid;
585 char rxstr[AFS_RXINFO_LEN];
587 COUNT_REQ(VLGETNEWVOLUMEID);
588 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
591 if (Maxvolidbump < 0 || Maxvolidbump > MAXBUMPCOUNT)
592 END(VL_BADVOLIDBUMP);
594 if ((errorcode = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
597 *newvolumeid = maxvolumeid = NextUnusedID(&ctx,
598 ntohl(ctx.cheader->vital_header.MaxVolumeId), Maxvolidbump, &errorcode);
603 maxvolumeid += Maxvolidbump;
604 VLog(1, ("GetNewVolid newmax=%u %s\n", maxvolumeid, rxinfo(rxstr, rxcall)));
605 ctx.cheader->vital_header.MaxVolumeId = htonl(maxvolumeid);
606 if (write_vital_vlheader(&ctx)) {
609 errorcode = (ubik_EndTrans(ctx.trans));
614 ubik_AbortTrans(ctx.trans);
617 osi_auditU(rxcall, VLGetNewVolumeIdEvent, errorcode, AUD_END);
622 /* Simple replace the contents of the vldb entry, volid, with
623 * newentry. No individual checking/updating per field (alike
624 * VLUpdateEntry) is done. */
627 SVL_ReplaceEntry(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype,
628 struct vldbentry *newentry, afs_int32 releasetype)
631 afs_int32 blockindex, errorcode, typeindex;
633 int hashVol[MAXTYPES];
634 struct nvlentry tentry;
635 afs_uint32 checkids[MAXTYPES];
636 char rxstr[AFS_RXINFO_LEN];
638 COUNT_REQ(VLREPLACEENTRY);
639 for (typeindex = 0; typeindex < MAXTYPES; typeindex++)
640 hashVol[typeindex] = 0;
642 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
645 if ((errorcode = check_vldbentry(newentry)))
648 if (voltype != -1 && InvalidVoltype(voltype))
651 if (releasetype && InvalidReleasetype(releasetype))
652 END(VL_BADRELLOCKTYPE);
653 if ((errorcode = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
656 VLog(1, ("OReplace Volume %u %s\n", volid, rxinfo(rxstr, rxcall)));
657 /* find vlentry we're changing */
658 blockindex = FindByID(&ctx, volid, voltype, &tentry, &errorcode);
659 if (blockindex == 0) { /* entry not found */
661 errorcode = VL_NOENT;
665 /* check that we're not trying to change the RW vol ID */
666 if (newentry->volumeId[RWVOL] != tentry.volumeId[RWVOL]) {
670 /* make sure none of the IDs we are changing to are already in use */
671 memset(&checkids, 0, sizeof(checkids));
672 for (typeindex = ROVOL; typeindex < MAXTYPES; typeindex++) {
673 if (tentry.volumeId[typeindex] != newentry->volumeId[typeindex]) {
674 checkids[typeindex] = newentry->volumeId[typeindex];
677 if (EntryIDExists(&ctx, checkids, MAXTYPES, &errorcode)) {
679 } else if (errorcode) {
683 /* make sure the name we're changing to doesn't already exist */
684 if (strcmp(newentry->name, tentry.name)) {
685 struct nvlentry tmp_entry;
686 if (FindByName(&ctx, newentry->name, &tmp_entry, &errorcode)) {
688 } else if (errorcode) {
693 /* unhash volid entries if they're disappearing or changing.
694 * Remember if we need to hash in the new value (we don't have to
695 * rehash if volid stays same */
696 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
697 if (tentry.volumeId[typeindex] != newentry->volumeId[typeindex]) {
698 if (tentry.volumeId[typeindex])
700 UnhashVolid(&ctx, typeindex, blockindex, &tentry))) {
703 /* we must rehash new id if the id is different and the ID is nonzero */
704 hashVol[typeindex] = 1; /* must rehash this guy if he exists */
708 /* Rehash volname if it changes */
709 if (strcmp(newentry->name, tentry.name)) { /* Name changes; redo hashing */
710 if ((errorcode = UnhashVolname(&ctx, blockindex, &tentry))) {
716 /* after this, tentry is new entry, not old one. vldbentry_to_vlentry
717 * doesn't touch hash chains */
718 if ((errorcode = vldbentry_to_vlentry(&ctx, newentry, &tentry))) {
722 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
723 if (hashVol[typeindex] && tentry.volumeId[typeindex]) {
724 if ((errorcode = HashVolid(&ctx, typeindex, blockindex, &tentry))) {
731 HashVolname(&ctx, blockindex, &tentry);
734 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
735 if (vlentrywrite(ctx.trans, blockindex, &tentry, sizeof(tentry))) {
739 END(ubik_EndTrans(ctx.trans));
743 ubik_AbortTrans(ctx.trans);
746 osi_auditU(rxcall, VLReplaceVLEntryEvent, errorcode, AUD_LONG, volid,
752 SVL_ReplaceEntryN(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype,
753 struct nvldbentry *newentry, afs_int32 releasetype)
756 afs_int32 blockindex, errorcode, typeindex;
758 int hashVol[MAXTYPES];
759 struct nvlentry tentry;
760 char rxstr[AFS_RXINFO_LEN];
762 COUNT_REQ(VLREPLACEENTRYN);
763 for (typeindex = 0; typeindex < MAXTYPES; typeindex++)
764 hashVol[typeindex] = 0;
766 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
769 if ((errorcode = check_nvldbentry(newentry)))
772 if (voltype != -1 && InvalidVoltype(voltype))
775 if (releasetype && InvalidReleasetype(releasetype))
776 END(VL_BADRELLOCKTYPE);
777 if ((errorcode = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
780 VLog(1, ("Replace Volume %u %s\n", volid, rxinfo(rxstr, rxcall)));
781 /* find vlentry we're changing */
782 blockindex = FindByID(&ctx, volid, voltype, &tentry, &errorcode);
783 if (blockindex == 0) { /* entry not found */
785 errorcode = VL_NOENT;
789 /* check that we're not trying to change the RW vol ID */
790 if (newentry->volumeId[RWVOL] != tentry.volumeId[RWVOL]) {
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 ((errorcode = 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 ((errorcode = nvldbentry_to_vlentry(&ctx, newentry, &tentry))) {
823 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
824 if (hashVol[typeindex] && tentry.volumeId[typeindex]) {
825 if ((errorcode = 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, errorcode, AUD_LONG, volid,
853 /* Update a vldb entry (accessed thru its volume id). Almost all of the
854 * entry's fields can be modified in a single call by setting the
855 * appropriate bits in the Mask field in VldbUpdateentry. */
856 /* this routine may never have been tested; use replace entry instead
857 * unless you're brave */
859 SVL_UpdateEntry(struct rx_call *rxcall,
862 struct VldbUpdateEntry *updateentry, /* Update entry copied here */
863 afs_int32 releasetype)
866 afs_int32 blockindex, errorcode;
867 struct nvlentry tentry;
868 char rxstr[AFS_RXINFO_LEN];
870 COUNT_REQ(VLUPDATEENTRY);
871 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
873 if ((voltype != -1) && (InvalidVoltype(voltype)))
875 if (releasetype && InvalidReleasetype(releasetype))
876 END(VL_BADRELLOCKTYPE);
877 if ((errorcode = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
880 VLog(1, ("Update Volume %u %s\n", volid, rxinfo(rxstr, rxcall)));
881 blockindex = FindByID(&ctx, volid, voltype, &tentry, &errorcode);
882 if (blockindex == 0) { /* entry not found */
884 errorcode = VL_NOENT;
888 /* Do the actual updating of the entry, tentry. */
890 get_vldbupdateentry(&ctx, blockindex, updateentry, &tentry))) {
894 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
895 if (vlentrywrite(ctx.trans, blockindex, &tentry, sizeof(tentry))) {
898 END(ubik_EndTrans(ctx.trans));
902 ubik_AbortTrans(ctx.trans);
905 osi_auditU(rxcall, VLUpdateEntryEvent, errorcode, AUD_LONG, volid,
912 SVL_UpdateEntryByName(struct rx_call *rxcall,
914 struct VldbUpdateEntry *updateentry, /* Update entry copied here */
915 afs_int32 releasetype)
918 afs_int32 blockindex, errorcode;
919 struct nvlentry tentry;
921 COUNT_REQ(VLUPDATEENTRYBYNAME);
922 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
924 if (releasetype && InvalidReleasetype(releasetype))
925 END(VL_BADRELLOCKTYPE);
926 if ((errorcode = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
929 blockindex = FindByName(&ctx, volname, &tentry, &errorcode);
930 if (blockindex == 0) { /* entry not found */
932 errorcode = VL_NOENT;
936 /* Do the actual updating of the entry, tentry. */
938 get_vldbupdateentry(&ctx, blockindex, updateentry, &tentry))) {
942 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
943 if (vlentrywrite(ctx.trans, blockindex, &tentry, sizeof(tentry))) {
946 END(ubik_EndTrans(ctx.trans));
950 ubik_AbortTrans(ctx.trans);
953 osi_auditU(rxcall, VLUpdateEntryEvent, errorcode, AUD_LONG, -1, AUD_END);
958 /* Set a lock to the vldb entry for volid (of type voltype if not -1). */
960 SVL_SetLock(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype,
963 afs_int32 timestamp, blockindex, errorcode;
965 struct nvlentry tentry;
966 char rxstr[AFS_RXINFO_LEN];
968 COUNT_REQ(VLSETLOCK);
969 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
971 if ((voltype != -1) && (InvalidVoltype(voltype)))
973 if (InvalidOperation(voloper))
975 if ((errorcode = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
978 VLog(1, ("SetLock Volume %u %s\n", volid, rxinfo(rxstr, rxcall)));
979 blockindex = FindByID(&ctx, volid, voltype, &tentry, &errorcode);
980 if (blockindex == NULLO) {
982 errorcode = VL_NOENT;
985 if (tentry.flags & VLDELETED) {
986 ABORT(VL_ENTDELETED);
988 timestamp = FT_ApproxTime();
990 /* Check if entry is already locked; note that we unlock any entry
991 * locked more than MAXLOCKTIME seconds */
992 if ((tentry.LockTimestamp)
993 && ((timestamp - tentry.LockTimestamp) < MAXLOCKTIME)) {
994 ABORT(VL_ENTRYLOCKED);
997 /* Consider it an unlocked entry: set current timestamp, caller
998 * and active vol operation */
999 tentry.LockTimestamp = timestamp;
1000 tentry.LockAfsId = 0; /* Not implemented yet */
1001 if (tentry.flags & VLOP_RELEASE) {
1002 ABORT(VL_RERELEASE);
1004 tentry.flags &= ~VLOP_ALLOPERS; /* Clear any possible older operation bit */
1005 tentry.flags |= voloper;
1007 if (vlentrywrite(ctx.trans, blockindex, &tentry, sizeof(tentry))) {
1010 END(ubik_EndTrans(ctx.trans));
1014 ubik_AbortTrans(ctx.trans);
1017 osi_auditU(rxcall, VLSetLockEvent, errorcode, AUD_LONG, volid, AUD_END);
1022 /* Release an already locked vldb entry. Releasetype determines what
1023 * fields (afsid and/or volume operation) will be cleared along with
1024 * the lock time stamp. */
1027 SVL_ReleaseLock(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype,
1028 afs_int32 releasetype)
1030 afs_int32 blockindex, errorcode;
1032 struct nvlentry tentry;
1033 char rxstr[AFS_RXINFO_LEN];
1035 COUNT_REQ(VLRELEASELOCK);
1036 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
1038 if ((voltype != -1) && (InvalidVoltype(voltype)))
1040 if (releasetype && InvalidReleasetype(releasetype))
1041 END(VL_BADRELLOCKTYPE);
1042 if ((errorcode = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
1045 VLog(1, ("ReleaseLock Volume %u %s\n", volid, rxinfo(rxstr, rxcall)));
1046 blockindex = FindByID(&ctx, volid, voltype, &tentry, &errorcode);
1047 if (blockindex == NULLO) {
1049 errorcode = VL_NOENT;
1052 if (tentry.flags & VLDELETED) {
1053 ABORT(VL_ENTDELETED);
1056 ReleaseEntry(&tentry, releasetype); /* Unlock the appropriate fields */
1057 if (vlentrywrite(ctx.trans, blockindex, &tentry, sizeof(tentry))) {
1060 END(ubik_EndTrans(ctx.trans));
1064 ubik_AbortTrans(ctx.trans);
1067 osi_auditU(rxcall, VLReleaseLockEvent, errorcode, AUD_LONG, volid,
1073 /* ListEntry returns a single vldb entry, aentry, with offset previous_index;
1074 * the remaining parameters (i.e. next_index) are used so that sequential
1075 * calls to this routine will get the next (all) vldb entries.
1078 SVL_ListEntry(struct rx_call *rxcall, afs_int32 previous_index,
1079 afs_int32 *count, afs_int32 *next_index,
1080 struct vldbentry *aentry)
1084 struct nvlentry tentry;
1085 char rxstr[AFS_RXINFO_LEN];
1087 COUNT_REQ(VLLISTENTRY);
1088 if ((errorcode = Init_VLdbase(&ctx, LOCKREAD, this_op)))
1090 VLog(25, ("OListEntry index=%d %s\n", previous_index,
1091 rxinfo(rxstr, rxcall)));
1092 *next_index = NextEntry(&ctx, previous_index, &tentry, count);
1094 vlentry_to_vldbentry(&ctx, &tentry, aentry);
1095 return (ubik_EndTrans(ctx.trans));
1098 /* ListEntry returns a single vldb entry, aentry, with offset previous_index;
1099 * the remaining parameters (i.e. next_index) are used so that sequential
1100 * calls to this routine will get the next (all) vldb entries.
1103 SVL_ListEntryN(struct rx_call *rxcall, afs_int32 previous_index,
1104 afs_int32 *count, afs_int32 *next_index,
1105 struct nvldbentry *aentry)
1109 struct nvlentry tentry;
1110 char rxstr[AFS_RXINFO_LEN];
1112 COUNT_REQ(VLLISTENTRYN);
1113 if ((errorcode = Init_VLdbase(&ctx, LOCKREAD, this_op)))
1115 VLog(25, ("ListEntry index=%d %s\n", previous_index, rxinfo(rxstr, rxcall)));
1116 *next_index = NextEntry(&ctx, previous_index, &tentry, count);
1118 vlentry_to_nvldbentry(&ctx, &tentry, aentry);
1119 return (ubik_EndTrans(ctx.trans));
1123 /* Retrieves in vldbentries all vldb entries that match the specified
1124 * attributes (by server number, partition, volume type, and flag); if volume
1125 * id is specified then the associated list for that entry is returned.
1126 * CAUTION: This could be a very expensive call since in most cases
1127 * sequential search of all vldb entries is performed.
1130 SVL_ListAttributes(struct rx_call *rxcall,
1131 struct VldbListByAttributes *attributes,
1132 afs_int32 *nentries,
1133 bulkentries *vldbentries)
1135 int errorcode, allocCount = 0;
1137 struct nvlentry tentry;
1138 struct vldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1140 char rxstr[AFS_RXINFO_LEN];
1142 COUNT_REQ(VLLISTATTRIBUTES);
1143 vldbentries->bulkentries_val = 0;
1144 vldbentries->bulkentries_len = *nentries = 0;
1145 if ((errorcode = Init_VLdbase(&ctx, LOCKREAD, this_op)))
1147 allocCount = VLDBALLOCCOUNT;
1148 Vldbentry = VldbentryFirst = vldbentries->bulkentries_val =
1149 (vldbentry *) malloc(allocCount * sizeof(vldbentry));
1150 if (Vldbentry == NULL) {
1152 ubik_AbortTrans(ctx.trans);
1155 VldbentryLast = VldbentryFirst + allocCount;
1156 /* Handle the attribute by volume id totally separate of the rest
1157 * (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!) */
1158 if (attributes->Mask & VLLIST_VOLUMEID) {
1159 afs_int32 blockindex;
1162 FindByID(&ctx, attributes->volumeid, -1, &tentry, &errorcode);
1163 if (blockindex == 0) {
1165 errorcode = VL_NOENT;
1167 ubik_AbortTrans(ctx.trans);
1168 if (vldbentries->bulkentries_val)
1169 free((char *)vldbentries->bulkentries_val);
1170 vldbentries->bulkentries_val = 0;
1171 vldbentries->bulkentries_len = 0;
1175 put_attributeentry(&ctx, &Vldbentry, &VldbentryFirst, &VldbentryLast,
1176 vldbentries, &tentry, nentries, &allocCount))) {
1178 ubik_AbortTrans(ctx.trans);
1179 if (vldbentries->bulkentries_val)
1180 free((char *)vldbentries->bulkentries_val);
1181 vldbentries->bulkentries_val = 0;
1182 vldbentries->bulkentries_len = 0;
1183 return VL_SIZEEXCEEDED;
1186 afs_int32 nextblockindex = 0, count = 0, k = 0, match = 0;
1187 while ((nextblockindex =
1188 NextEntry(&ctx, nextblockindex, &tentry, &count))) {
1189 if (++pollcount > 50) {
1190 #ifndef AFS_PTHREAD_ENV
1196 if (attributes->Mask & VLLIST_SERVER) {
1199 IpAddrToRelAddr(&ctx, attributes->server, 0)) == -1)
1201 for (k = 0; k < OMAXNSERVERS; k++) {
1202 if (tentry.serverNumber[k] == BADSERVERID)
1204 if (tentry.serverNumber[k] == serverindex) {
1212 if (attributes->Mask & VLLIST_PARTITION) {
1214 if (tentry.serverPartition[k] != attributes->partition)
1217 for (k = 0; k < OMAXNSERVERS; k++) {
1218 if (tentry.serverNumber[k] == BADSERVERID)
1220 if (tentry.serverPartition[k] ==
1221 attributes->partition) {
1231 if (attributes->Mask & VLLIST_FLAG) {
1232 if (!(tentry.flags & attributes->flag))
1236 put_attributeentry(&ctx, &Vldbentry, &VldbentryFirst,
1237 &VldbentryLast, vldbentries, &tentry,
1238 nentries, &allocCount))) {
1240 ubik_AbortTrans(ctx.trans);
1241 if (vldbentries->bulkentries_val)
1242 free((char *)vldbentries->bulkentries_val);
1243 vldbentries->bulkentries_val = 0;
1244 vldbentries->bulkentries_len = 0;
1249 if (vldbentries->bulkentries_len
1250 && (allocCount > vldbentries->bulkentries_len)) {
1252 vldbentries->bulkentries_val =
1253 (vldbentry *) realloc(vldbentries->bulkentries_val,
1254 vldbentries->bulkentries_len *
1256 if (vldbentries->bulkentries_val == NULL) {
1258 ubik_AbortTrans(ctx.trans);
1263 ("ListAttrs nentries=%d %s\n", vldbentries->bulkentries_len,
1264 rxinfo(rxstr, rxcall)));
1265 return (ubik_EndTrans(ctx.trans));
1269 SVL_ListAttributesN(struct rx_call *rxcall,
1270 struct VldbListByAttributes *attributes,
1271 afs_int32 *nentries,
1272 nbulkentries *vldbentries)
1274 int errorcode, allocCount = 0;
1276 struct nvlentry tentry;
1277 struct nvldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1279 char rxstr[AFS_RXINFO_LEN];
1281 COUNT_REQ(VLLISTATTRIBUTESN);
1282 vldbentries->nbulkentries_val = 0;
1283 vldbentries->nbulkentries_len = *nentries = 0;
1284 if ((errorcode = Init_VLdbase(&ctx, LOCKREAD, this_op)))
1286 allocCount = VLDBALLOCCOUNT;
1287 Vldbentry = VldbentryFirst = vldbentries->nbulkentries_val =
1288 (nvldbentry *) malloc(allocCount * sizeof(nvldbentry));
1289 if (Vldbentry == NULL) {
1291 ubik_AbortTrans(ctx.trans);
1294 VldbentryLast = VldbentryFirst + allocCount;
1295 /* Handle the attribute by volume id totally separate of the rest
1296 * (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!) */
1297 if (attributes->Mask & VLLIST_VOLUMEID) {
1298 afs_int32 blockindex;
1301 FindByID(&ctx, attributes->volumeid, -1, &tentry, &errorcode);
1302 if (blockindex == 0) {
1304 errorcode = VL_NOENT;
1306 ubik_AbortTrans(ctx.trans);
1307 if (vldbentries->nbulkentries_val)
1308 free((char *)vldbentries->nbulkentries_val);
1309 vldbentries->nbulkentries_val = 0;
1310 vldbentries->nbulkentries_len = 0;
1314 put_nattributeentry(&ctx, &Vldbentry, &VldbentryFirst, &VldbentryLast,
1315 vldbentries, &tentry, 0, 0, nentries,
1318 ubik_AbortTrans(ctx.trans);
1319 if (vldbentries->nbulkentries_val)
1320 free((char *)vldbentries->nbulkentries_val);
1321 vldbentries->nbulkentries_val = 0;
1322 vldbentries->nbulkentries_len = 0;
1323 return VL_SIZEEXCEEDED;
1326 afs_int32 nextblockindex = 0, count = 0, k = 0, match = 0;
1327 while ((nextblockindex =
1328 NextEntry(&ctx, nextblockindex, &tentry, &count))) {
1329 if (++pollcount > 50) {
1330 #ifndef AFS_PTHREAD_ENV
1337 if (attributes->Mask & VLLIST_SERVER) {
1340 IpAddrToRelAddr(&ctx, attributes->server, 0)) == -1)
1342 for (k = 0; k < NMAXNSERVERS; k++) {
1343 if (tentry.serverNumber[k] == BADSERVERID)
1345 if (tentry.serverNumber[k] == serverindex) {
1353 if (attributes->Mask & VLLIST_PARTITION) {
1355 if (tentry.serverPartition[k] != attributes->partition)
1358 for (k = 0; k < NMAXNSERVERS; k++) {
1359 if (tentry.serverNumber[k] == BADSERVERID)
1361 if (tentry.serverPartition[k] ==
1362 attributes->partition) {
1372 if (attributes->Mask & VLLIST_FLAG) {
1373 if (!(tentry.flags & attributes->flag))
1377 put_nattributeentry(&ctx, &Vldbentry, &VldbentryFirst,
1378 &VldbentryLast, vldbentries, &tentry, 0,
1379 0, nentries, &allocCount))) {
1381 ubik_AbortTrans(ctx.trans);
1382 if (vldbentries->nbulkentries_val)
1383 free((char *)vldbentries->nbulkentries_val);
1384 vldbentries->nbulkentries_val = 0;
1385 vldbentries->nbulkentries_len = 0;
1390 if (vldbentries->nbulkentries_len
1391 && (allocCount > vldbentries->nbulkentries_len)) {
1393 vldbentries->nbulkentries_val =
1394 (nvldbentry *) realloc(vldbentries->nbulkentries_val,
1395 vldbentries->nbulkentries_len *
1396 sizeof(nvldbentry));
1397 if (vldbentries->nbulkentries_val == NULL) {
1399 ubik_AbortTrans(ctx.trans);
1404 ("NListAttrs nentries=%d %s\n", vldbentries->nbulkentries_len,
1405 rxinfo(rxstr, rxcall)));
1406 return (ubik_EndTrans(ctx.trans));
1411 SVL_ListAttributesN2(struct rx_call *rxcall,
1412 struct VldbListByAttributes *attributes,
1413 char *name, /* Wildcarded volume name */
1414 afs_int32 startindex,
1415 afs_int32 *nentries,
1416 nbulkentries *vldbentries,
1417 afs_int32 *nextstartindex)
1419 int errorcode = 0, maxCount = VLDBALLOCCOUNT;
1421 struct nvlentry tentry;
1422 struct nvldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1423 afs_int32 blockindex = 0, count = 0, k, match;
1424 afs_int32 matchindex = 0;
1425 int serverindex = -1; /* no server found */
1426 int findserver = 0, findpartition = 0, findflag = 0, findname = 0;
1428 int namematchRWBK, namematchRO, thismatch;
1430 char volumename[VL_MAXNAMELEN+2]; /* regex anchors */
1431 char rxstr[AFS_RXINFO_LEN];
1432 #ifdef HAVE_POSIX_REGEX
1434 int need_regfree = 0;
1439 COUNT_REQ(VLLISTATTRIBUTESN2);
1440 vldbentries->nbulkentries_val = 0;
1441 vldbentries->nbulkentries_len = 0;
1443 *nextstartindex = -1;
1445 errorcode = Init_VLdbase(&ctx, LOCKREAD, this_op);
1449 Vldbentry = VldbentryFirst = vldbentries->nbulkentries_val =
1450 (nvldbentry *) malloc(maxCount * sizeof(nvldbentry));
1451 if (Vldbentry == NULL) {
1453 ubik_AbortTrans(ctx.trans);
1457 VldbentryLast = VldbentryFirst + maxCount;
1459 /* Handle the attribute by volume id totally separate of the rest
1460 * (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!)
1462 if (attributes->Mask & VLLIST_VOLUMEID) {
1464 FindByID(&ctx, attributes->volumeid, -1, &tentry, &errorcode);
1465 if (blockindex == 0) {
1467 errorcode = VL_NOENT;
1470 put_nattributeentry(&ctx, &Vldbentry, &VldbentryFirst,
1471 &VldbentryLast, vldbentries, &tentry, 0,
1472 0, nentries, &maxCount);
1478 /* Search each entry in the database and return all entries
1479 * that match the request. It checks volumename (with
1480 * wildcarding), entry flags, server, and partition.
1483 /* Get the server index for matching server address */
1484 if (attributes->Mask & VLLIST_SERVER) {
1486 IpAddrToRelAddr(&ctx, attributes->server, 0);
1487 if (serverindex == -1)
1491 findpartition = ((attributes->Mask & VLLIST_PARTITION) ? 1 : 0);
1492 findflag = ((attributes->Mask & VLLIST_FLAG) ? 1 : 0);
1493 if (name && (strcmp(name, ".*") != 0) && (strcmp(name, "") != 0)) {
1494 sprintf(volumename, "^%s$", name);
1495 #ifdef HAVE_POSIX_REGEX
1496 if (regcomp(&re, volumename, REG_NOSUB) != 0) {
1497 errorcode = VL_BADNAME;
1502 t = (char *)re_comp(volumename);
1504 errorcode = VL_BADNAME;
1511 /* Read each entry and see if it is the one we want */
1512 blockindex = startindex;
1513 while ((blockindex = NextEntry(&ctx, blockindex, &tentry, &count))) {
1514 if (++pollcount > 50) {
1515 #ifndef AFS_PTHREAD_ENV
1521 /* Step through each server index searching for a match.
1522 * Match to an existing RW, BK, or RO volume name (preference
1523 * is in this order). Remember which index we matched against.
1525 namematchRWBK = namematchRO = 0; /* 0->notTried; 1->match; 2->noMatch */
1529 && (tentry.serverNumber[k] != BADSERVERID)); k++) {
1530 thismatch = 0; /* does this index match */
1532 /* Match against the RW or BK volume name. Remember
1533 * results in namematchRWBK. Prefer RW over BK.
1535 if (tentry.serverFlags[k] & VLSF_RWVOL) {
1536 /* Does the name match the RW name */
1537 if (tentry.flags & VLF_RWEXISTS) {
1539 sprintf(volumename, "%s", tentry.name);
1540 #ifdef HAVE_POSIX_REGEX
1541 if (regexec(&re, volumename, 0, NULL, 0) == 0) {
1542 thismatch = VLSF_RWVOL;
1545 if (re_exec(volumename)) {
1546 thismatch = VLSF_RWVOL;
1550 thismatch = VLSF_RWVOL;
1554 /* Does the name match the BK name */
1555 if (!thismatch && (tentry.flags & VLF_BACKEXISTS)) {
1557 sprintf(volumename, "%s.backup", tentry.name);
1558 #ifdef HAVE_POSIX_REGEX
1559 if (regexec(&re, volumename, 0, NULL, 0) == 0) {
1560 thismatch = VLSF_BACKVOL;
1563 if (re_exec(volumename)) {
1564 thismatch = VLSF_BACKVOL;
1568 thismatch = VLSF_BACKVOL;
1572 namematchRWBK = (thismatch ? 1 : 2);
1575 /* Match with the RO volume name. Compare once and
1576 * remember results in namematchRO. Note that this will
1577 * pick up entries marked NEWREPSITEs and DONTUSE.
1580 if (tentry.flags & VLF_ROEXISTS) {
1584 ((namematchRO == 1) ? VLSF_ROVOL : 0);
1586 sprintf(volumename, "%s.readonly",
1588 #ifdef HAVE_POSIX_REGEX
1589 if (regexec(&re, volumename, 0, NULL, 0) == 0) {
1590 thismatch = VLSF_ROVOL;
1593 if (re_exec(volumename))
1594 thismatch = VLSF_ROVOL;
1598 thismatch = VLSF_ROVOL;
1601 namematchRO = (thismatch ? 1 : 2);
1604 /* Is there a server match */
1605 if (thismatch && findserver
1606 && (tentry.serverNumber[k] != serverindex))
1609 /* Is there a partition match */
1610 if (thismatch && findpartition
1611 && (tentry.serverPartition[k] != attributes->partition))
1614 /* Is there a flag match */
1615 if (thismatch && findflag
1616 && !(tentry.flags & attributes->flag))
1619 /* We found a match. Remember the index, and type */
1623 matchtype = thismatch;
1626 /* Since we prefer RW and BK volume matches over RO matches,
1627 * if we have already checked the RWBK name, then we already
1628 * found the best match and so end the search.
1630 * If we tried matching against the RW, BK, and RO volume names
1631 * and both failed, then we end the search (none will match).
1633 if ((match && namematchRWBK)
1634 || ((namematchRWBK == 2) && (namematchRO == 2)))
1638 /* Passed all the tests. Take it */
1641 put_nattributeentry(&ctx, &Vldbentry, &VldbentryFirst,
1642 &VldbentryLast, vldbentries, &tentry,
1643 matchtype, matchindex, nentries,
1648 if (*nentries >= maxCount)
1649 break; /* collected the max */
1652 *nextstartindex = (blockindex ? blockindex : -1);
1656 #ifdef HAVE_POSIX_REGEX
1663 ubik_AbortTrans(ctx.trans);
1664 if (vldbentries->nbulkentries_val)
1665 free((char *)vldbentries->nbulkentries_val);
1666 vldbentries->nbulkentries_val = 0;
1667 vldbentries->nbulkentries_len = 0;
1668 *nextstartindex = -1;
1672 ("N2ListAttrs nentries=%d %s\n", vldbentries->nbulkentries_len,
1673 rxinfo(rxstr, rxcall)));
1674 return (ubik_EndTrans(ctx.trans));
1679 /* Retrieves in vldbentries all vldb entries that match the specified
1680 * attributes (by server number, partition, volume type, and flag); if
1681 * volume id is specified then the associated list for that entry is
1682 * returned. CAUTION: This could be a very expensive call since in most
1683 * cases sequential search of all vldb entries is performed.
1686 SVL_LinkedList(struct rx_call *rxcall,
1687 struct VldbListByAttributes *attributes,
1688 afs_int32 *nentries,
1689 vldb_list *vldbentries)
1693 struct nvlentry tentry;
1694 vldblist vllist, *vllistptr;
1695 afs_int32 blockindex, count, match;
1700 COUNT_REQ(VLLINKEDLIST);
1701 if ((errorcode = Init_VLdbase(&ctx, LOCKREAD, this_op)))
1705 vldbentries->node = NULL;
1706 vllistptr = &vldbentries->node;
1708 /* List by volumeid */
1709 if (attributes->Mask & VLLIST_VOLUMEID) {
1711 FindByID(&ctx, attributes->volumeid, -1, &tentry, &errorcode);
1714 ubik_AbortTrans(ctx.trans);
1715 return (errorcode ? errorcode : VL_NOENT);
1718 vllist = (single_vldbentry *) malloc(sizeof(single_vldbentry));
1719 if (vllist == NULL) {
1721 ubik_AbortTrans(ctx.trans);
1724 vlentry_to_vldbentry(&ctx, &tentry, &vllist->VldbEntry);
1725 vllist->next_vldb = NULL;
1727 *vllistptr = vllist; /* Thread onto list */
1728 vllistptr = &vllist->next_vldb;
1732 /* Search by server, partition, and flags */
1734 for (blockindex = NextEntry(&ctx, 0, &tentry, &count); blockindex;
1735 blockindex = NextEntry(&ctx, blockindex, &tentry, &count)) {
1738 if (++pollcount > 50) {
1739 #ifndef AFS_PTHREAD_ENV
1745 /* Does this volume exist on the desired server */
1746 if (attributes->Mask & VLLIST_SERVER) {
1748 IpAddrToRelAddr(&ctx, attributes->server, 0);
1749 if (serverindex == -1)
1751 for (k = 0; k < OMAXNSERVERS; k++) {
1752 if (tentry.serverNumber[k] == BADSERVERID)
1754 if (tentry.serverNumber[k] == serverindex) {
1763 /* Does this volume exist on the desired partition */
1764 if (attributes->Mask & VLLIST_PARTITION) {
1766 if (tentry.serverPartition[k] != attributes->partition)
1769 for (k = 0; k < OMAXNSERVERS; k++) {
1770 if (tentry.serverNumber[k] == BADSERVERID)
1772 if (tentry.serverPartition[k] ==
1773 attributes->partition) {
1783 /* Does this volume have the desired flags */
1784 if (attributes->Mask & VLLIST_FLAG) {
1785 if (!(tentry.flags & attributes->flag))
1789 vllist = (single_vldbentry *) malloc(sizeof(single_vldbentry));
1790 if (vllist == NULL) {
1792 ubik_AbortTrans(ctx.trans);
1795 vlentry_to_vldbentry(&ctx, &tentry, &vllist->VldbEntry);
1796 vllist->next_vldb = NULL;
1798 *vllistptr = vllist; /* Thread onto list */
1799 vllistptr = &vllist->next_vldb;
1801 if (smallMem && (*nentries >= VLDBALLOCCOUNT)) {
1803 ubik_AbortTrans(ctx.trans);
1804 return VL_SIZEEXCEEDED;
1809 return (ubik_EndTrans(ctx.trans));
1813 SVL_LinkedListN(struct rx_call *rxcall,
1814 struct VldbListByAttributes *attributes,
1815 afs_int32 *nentries,
1816 nvldb_list *vldbentries)
1820 struct nvlentry tentry;
1821 nvldblist vllist, *vllistptr;
1822 afs_int32 blockindex, count, match;
1827 COUNT_REQ(VLLINKEDLISTN);
1828 if ((errorcode = Init_VLdbase(&ctx, LOCKREAD, this_op)))
1832 vldbentries->node = NULL;
1833 vllistptr = &vldbentries->node;
1835 /* List by volumeid */
1836 if (attributes->Mask & VLLIST_VOLUMEID) {
1838 FindByID(&ctx, attributes->volumeid, -1, &tentry, &errorcode);
1841 ubik_AbortTrans(ctx.trans);
1842 return (errorcode ? errorcode : VL_NOENT);
1845 vllist = (single_nvldbentry *) malloc(sizeof(single_nvldbentry));
1846 if (vllist == NULL) {
1848 ubik_AbortTrans(ctx.trans);
1851 vlentry_to_nvldbentry(&ctx, &tentry, &vllist->VldbEntry);
1852 vllist->next_vldb = NULL;
1854 *vllistptr = vllist; /* Thread onto list */
1855 vllistptr = &vllist->next_vldb;
1859 /* Search by server, partition, and flags */
1861 for (blockindex = NextEntry(&ctx, 0, &tentry, &count); blockindex;
1862 blockindex = NextEntry(&ctx, blockindex, &tentry, &count)) {
1865 if (++pollcount > 50) {
1866 #ifndef AFS_PTHREAD_ENV
1872 /* Does this volume exist on the desired server */
1873 if (attributes->Mask & VLLIST_SERVER) {
1875 IpAddrToRelAddr(&ctx, attributes->server, 0);
1876 if (serverindex == -1)
1878 for (k = 0; k < NMAXNSERVERS; k++) {
1879 if (tentry.serverNumber[k] == BADSERVERID)
1881 if (tentry.serverNumber[k] == serverindex) {
1890 /* Does this volume exist on the desired partition */
1891 if (attributes->Mask & VLLIST_PARTITION) {
1893 if (tentry.serverPartition[k] != attributes->partition)
1896 for (k = 0; k < NMAXNSERVERS; k++) {
1897 if (tentry.serverNumber[k] == BADSERVERID)
1899 if (tentry.serverPartition[k] ==
1900 attributes->partition) {
1910 /* Does this volume have the desired flags */
1911 if (attributes->Mask & VLLIST_FLAG) {
1912 if (!(tentry.flags & attributes->flag))
1916 vllist = (single_nvldbentry *) malloc(sizeof(single_nvldbentry));
1917 if (vllist == NULL) {
1919 ubik_AbortTrans(ctx.trans);
1922 vlentry_to_nvldbentry(&ctx, &tentry, &vllist->VldbEntry);
1923 vllist->next_vldb = NULL;
1925 *vllistptr = vllist; /* Thread onto list */
1926 vllistptr = &vllist->next_vldb;
1928 if (smallMem && (*nentries >= VLDBALLOCCOUNT)) {
1930 ubik_AbortTrans(ctx.trans);
1931 return VL_SIZEEXCEEDED;
1936 return (ubik_EndTrans(ctx.trans));
1939 /* Get back vldb header statistics (allocs, frees, maxvolumeid,
1940 * totalentries, etc) and dynamic statistics (number of requests and/or
1941 * aborts per remote procedure call, etc)
1944 SVL_GetStats(struct rx_call *rxcall,
1946 vital_vlheader *vital_header)
1948 afs_int32 errorcode;
1950 char rxstr[AFS_RXINFO_LEN];
1952 COUNT_REQ(VLGETSTATS);
1954 /* Allow users to get statistics freely */
1955 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) /* Must be in 'UserList' to use */
1958 if ((errorcode = Init_VLdbase(&ctx, LOCKREAD, this_op)))
1960 VLog(5, ("GetStats %s\n", rxinfo(rxstr, rxcall)));
1961 memcpy((char *)vital_header, (char *)&ctx.cheader->vital_header,
1962 sizeof(vital_vlheader));
1963 memcpy((char *)stats, (char *)&dynamic_statistics, sizeof(vldstats));
1964 return (ubik_EndTrans(ctx.trans));
1967 /* Get the list of file server addresses from the VLDB. Currently it's pretty
1968 * easy to do. In the future, it might require a little bit of grunging
1969 * through the VLDB, but that's life.
1972 SVL_GetAddrs(struct rx_call *rxcall,
1975 struct VLCallBack *spare3,
1976 afs_int32 *nentries,
1979 afs_int32 errorcode;
1984 COUNT_REQ(VLGETADDRS);
1985 addrsp->bulkaddrs_len = *nentries = 0;
1986 addrsp->bulkaddrs_val = 0;
1987 memset(spare3, 0, sizeof(struct VLCallBack));
1989 if ((errorcode = Init_VLdbase(&ctx, LOCKREAD, this_op)))
1992 VLog(5, ("GetAddrs\n"));
1993 addrsp->bulkaddrs_val = taddrp =
1994 (afs_uint32 *) malloc(sizeof(afs_int32) * (MAXSERVERID + 1));
1995 nservers = *nentries = addrsp->bulkaddrs_len = 0;
1999 ubik_AbortTrans(ctx.trans);
2003 for (i = 0; i <= MAXSERVERID; i++) {
2004 if ((*taddrp = ntohl(ctx.cheader->IpMappedAddr[i]))) {
2010 addrsp->bulkaddrs_len = *nentries = nservers;
2011 return (ubik_EndTrans(ctx.trans));
2014 #define PADDR(addr) VLog(0,("%d.%d.%d.%d", (addr>>24)&0xff, (addr>>16)&0xff, (addr>>8) &0xff, addr&0xff));
2017 SVL_RegisterAddrs(struct rx_call *rxcall, afsUUID *uuidp, afs_int32 spare1,
2022 int cnt, h, i, j, k, m, base, index;
2023 struct extentaddr *exp = 0, *tex;
2025 afs_uint32 addrs[VL_MAXIPADDRS_PERMH];
2027 int count, willChangeEntry, foundUuidEntry, willReplaceCnt;
2028 int WillReplaceEntry, WillChange[MAXSERVERID + 1];
2030 int ReplaceEntry = 0;
2033 COUNT_REQ(VLREGADDR);
2034 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
2036 if ((code = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
2039 /* Eliminate duplicates from IP address list */
2040 for (k = 0, cnt = 0; k < addrsp->bulkaddrs_len; k++) {
2041 if (addrsp->bulkaddrs_val[k] == 0)
2043 for (m = 0; m < cnt; m++) {
2044 if (addrs[m] == addrsp->bulkaddrs_val[k])
2048 if (m == VL_MAXIPADDRS_PERMH) {
2050 ("Number of addresses exceeds %d. Cannot register IP addr 0x%x in VLDB\n",
2051 VL_MAXIPADDRS_PERMH, addrsp->bulkaddrs_val[k]));
2053 addrs[m] = addrsp->bulkaddrs_val[k];
2059 ubik_AbortTrans(ctx.trans);
2060 return VL_INDEXERANGE;
2066 /* For each server registered within the VLDB */
2067 for (srvidx = 0; srvidx <= MAXSERVERID; srvidx++) {
2068 willChangeEntry = 0;
2069 WillReplaceEntry = 1;
2070 if ((ctx.hostaddress[srvidx] & 0xff000000) == 0xff000000) {
2071 /* The server is registered as a multihomed */
2072 base = (ctx.hostaddress[srvidx] >> 16) & 0xff;
2073 index = ctx.hostaddress[srvidx] & 0x0000ffff;
2074 if (base >= VL_MAX_ADDREXTBLKS) {
2076 ("Internal error: Multihome extent base is too large. Base %d index %d\n",
2080 if (index >= VL_MHSRV_PERBLK) {
2082 ("Internal error: Multihome extent index is too large. Base %d index %d\n",
2086 if (!ctx.ex_addr[base]) {
2088 ("Internal error: Multihome extent does not exist. Base %d\n",
2093 /* See if the addresses to register will change this server entry */
2094 exp = &ctx.ex_addr[base][index];
2095 tuuid = exp->ex_hostuuid;
2096 afs_ntohuuid(&tuuid);
2097 if (afs_uuid_equal(uuidp, &tuuid)) {
2101 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2102 if (!exp->ex_addrs[mhidx])
2104 for (k = 0; k < cnt; k++) {
2105 if (ntohl(exp->ex_addrs[mhidx]) == addrs[k]) {
2106 willChangeEntry = 1;
2107 WillChange[count] = srvidx;
2112 WillReplaceEntry = 0;
2116 /* The server is not registered as a multihomed.
2117 * See if the addresses to register will replace this server entry.
2119 for (k = 0; k < cnt; k++) {
2120 if (ctx.hostaddress[srvidx] == addrs[k]) {
2121 willChangeEntry = 1;
2122 WillChange[count] = srvidx;
2123 WillReplaceEntry = 1;
2128 if (willChangeEntry) {
2129 if (WillReplaceEntry) {
2131 ReplaceEntry = srvidx;
2137 /* If we found the uuid in the VLDB and if we are replacing another
2138 * entire entry, then complain and fail. Also, if we did not find
2139 * the uuid in the VLDB and the IP addresses being registered was
2140 * found in more than one other entry, then we don't know which one
2141 * to replace and will complain and fail.
2143 if ((foundUuidEntry && (willReplaceCnt > 0))
2144 || (!foundUuidEntry && (count > 1))) {
2146 ("The following fileserver is being registered in the VLDB:\n"));
2148 for (k = 0; k < cnt; k++) {
2155 if (foundUuidEntry) {
2157 (" It would have replaced the existing VLDB server entry:\n"));
2158 VLog(0, (" entry %d: [", FoundUuid));
2159 base = (ctx.hostaddress[FoundUuid] >> 16) & 0xff;
2160 index = ctx.hostaddress[FoundUuid] & 0x0000ffff;
2161 exp = &ctx.ex_addr[base][index];
2162 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2163 if (!exp->ex_addrs[mhidx])
2167 PADDR(ntohl(exp->ex_addrs[mhidx]));
2173 VLog(0, (" Yet another VLDB server entry exists:\n"));
2175 VLog(0, (" Yet other VLDB server entries exist:\n"));
2176 for (j = 0; j < count; j++) {
2177 srvidx = WillChange[j];
2178 VLog(0, (" entry %d: ", srvidx));
2179 if ((ctx.hostaddress[srvidx] & 0xff000000) == 0xff000000) {
2181 base = (ctx.hostaddress[srvidx] >> 16) & 0xff;
2182 index = ctx.hostaddress[srvidx] & 0x0000ffff;
2183 exp = &ctx.ex_addr[base][index];
2184 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2185 if (!exp->ex_addrs[mhidx])
2189 PADDR(ntohl(exp->ex_addrs[mhidx]));
2193 PADDR(ctx.hostaddress[srvidx]);
2199 VLog(0, (" You must 'vos changeaddr' this other server entry\n"));
2202 (" You must 'vos changeaddr' these other server entries\n"));
2205 (" and/or remove the sysid file from the registering fileserver\n"));
2206 VLog(0, (" before the fileserver can be registered in the VLDB.\n"));
2208 ubik_AbortTrans(ctx.trans);
2209 return VL_MULTIPADDR;
2212 /* Passed the checks. Now find and update the existing mh entry, or create
2215 if (foundUuidEntry) {
2216 /* Found the entry with same uuid. See if we need to change it */
2219 fbase = (ctx.hostaddress[FoundUuid] >> 16) & 0xff;
2220 index = ctx.hostaddress[FoundUuid] & 0x0000ffff;
2221 exp = &ctx.ex_addr[fbase][index];
2223 /* Determine if the entry has changed */
2224 for (k = 0; ((k < cnt) && !change); k++) {
2225 if (ntohl(exp->ex_addrs[k]) != addrs[k])
2228 for (; ((k < VL_MAXIPADDRS_PERMH) && !change); k++) {
2229 if (exp->ex_addrs[k] != 0)
2233 return (ubik_EndTrans(ctx.trans));
2237 VLog(0, ("The following fileserver is being registered in the VLDB:\n"));
2239 for (k = 0; k < cnt; k++) {
2246 if (foundUuidEntry) {
2248 (" It will replace the following existing entry in the VLDB (same uuid):\n"));
2249 VLog(0, (" entry %d: [", FoundUuid));
2250 for (k = 0; k < VL_MAXIPADDRS_PERMH; k++) {
2251 if (exp->ex_addrs[k] == 0)
2255 PADDR(ntohl(exp->ex_addrs[k]));
2258 } else if (willReplaceCnt || (count == 1)) {
2259 /* If we are not replacing an entry and there is only one entry to change,
2260 * then we will replace that entry.
2262 if (!willReplaceCnt) {
2263 ReplaceEntry = WillChange[0];
2267 /* Have an entry that needs to be replaced */
2268 if ((ctx.hostaddress[ReplaceEntry] & 0xff000000) == 0xff000000) {
2269 fbase = (ctx.hostaddress[ReplaceEntry] >> 16) & 0xff;
2270 index = ctx.hostaddress[ReplaceEntry] & 0x0000ffff;
2271 exp = &ctx.ex_addr[fbase][index];
2274 (" It will replace the following existing entry in the VLDB (new uuid):\n"));
2275 VLog(0, (" entry %d: [", ReplaceEntry));
2276 for (k = 0; k < VL_MAXIPADDRS_PERMH; k++) {
2277 if (exp->ex_addrs[k] == 0)
2281 PADDR(ntohl(exp->ex_addrs[k]));
2285 /* Not a mh entry. So we have to create a new mh entry and
2286 * put it on the ReplaceEntry slot of the ctx.hostaddress array.
2288 VLog(0, (" It will replace existing entry %d, ", ReplaceEntry));
2289 PADDR(ctx.hostaddress[ReplaceEntry]);
2290 VLog(0,(", in the VLDB (new uuid):\n"));
2293 FindExtentBlock(&ctx, uuidp, 1, ReplaceEntry, &exp, &fbase);
2295 ubik_AbortTrans(ctx.trans);
2296 return (code ? code : VL_IO);
2300 /* There is no entry for this server, must create a new mh entry as
2301 * well as use a new slot of the ctx.hostaddress array.
2303 VLog(0, (" It will create a new entry in the VLDB.\n"));
2304 code = FindExtentBlock(&ctx, uuidp, 1, -1, &exp, &fbase);
2306 ubik_AbortTrans(ctx.trans);
2307 return (code ? code : VL_IO);
2311 /* Now we have a mh entry to fill in. Update the uuid, bump the
2312 * uniquifier, and fill in its IP addresses.
2315 afs_htonuuid(&tuuid);
2316 exp->ex_hostuuid = tuuid;
2317 exp->ex_uniquifier = htonl(ntohl(exp->ex_uniquifier) + 1);
2318 for (k = 0; k < cnt; k++) {
2319 exp->ex_addrs[k] = htonl(addrs[k]);
2321 for (; k < VL_MAXIPADDRS_PERMH; k++) {
2322 exp->ex_addrs[k] = 0;
2325 /* Write the new mh entry out */
2328 DOFFSET(ntohl(ctx.ex_addr[0]->ex_contaddrs[fbase]),
2329 (char *)ctx.ex_addr[fbase], (char *)exp), (char *)exp,
2331 ubik_AbortTrans(ctx.trans);
2335 /* Remove any common addresses from other mh entres. We know these entries
2336 * are being changed and not replaced so they are mh entries.
2339 for (i = 0; i < count; i++) {
2342 /* Skip the entry we replaced */
2343 if (willReplaceCnt && (WillChange[i] == ReplaceEntry))
2346 base = (ctx.hostaddress[WillChange[i]] >> 16) & 0xff;
2347 index = ctx.hostaddress[WillChange[i]] & 0x0000ffff;
2348 tex = &ctx.ex_addr[fbase][index];
2352 (" The following existing entries in the VLDB will be updated:\n"));
2354 VLog(0, (" entry %d: [", WillChange[i]));
2355 for (h = j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2356 if (tex->ex_addrs[j]) {
2359 PADDR(ntohl(tex->ex_addrs[j]));
2362 for (k = 0; k < cnt; k++) {
2363 if (ntohl(tex->ex_addrs[j]) == addrs[k])
2367 /* Not found, so we keep it */
2368 tex->ex_addrs[h] = tex->ex_addrs[j];
2372 for (j = h; j < VL_MAXIPADDRS_PERMH; j++) {
2373 tex->ex_addrs[j] = 0; /* zero rest of mh entry */
2377 /* Write out the modified mh entry */
2378 tex->ex_uniquifier = htonl(ntohl(tex->ex_uniquifier) + 1);
2380 DOFFSET(ntohl(ctx.ex_addr[0]->ex_contaddrs[base]),
2381 (char *)ctx.ex_addr[base], (char *)tex);
2382 if (vlwrite(ctx.trans, doff, (char *)tex, sizeof(*tex))) {
2383 ubik_AbortTrans(ctx.trans);
2388 return (ubik_EndTrans(ctx.trans));
2392 SVL_GetAddrsU(struct rx_call *rxcall,
2393 struct ListAddrByAttributes *attributes,
2395 afs_int32 *uniquifier,
2396 afs_int32 *nentries,
2399 afs_int32 errorcode, index = -1, offset;
2401 int nservers, i, j, base = 0;
2402 struct extentaddr *exp = 0;
2404 afs_uint32 *taddrp, taddr;
2405 char rxstr[AFS_RXINFO_LEN];
2407 COUNT_REQ(VLGETADDRSU);
2408 addrsp->bulkaddrs_len = *nentries = 0;
2409 addrsp->bulkaddrs_val = 0;
2410 VLog(5, ("GetAddrsU %s\n", rxinfo(rxstr, rxcall)));
2411 if ((errorcode = Init_VLdbase(&ctx, LOCKREAD, this_op)))
2414 if (attributes->Mask & VLADDR_IPADDR) {
2415 if (attributes->Mask & (VLADDR_INDEX | VLADDR_UUID)) {
2416 ubik_AbortTrans(ctx.trans);
2419 for (base = 0; base < VL_MAX_ADDREXTBLKS; base++) {
2420 if (!ctx.ex_addr[base])
2422 for (i = 1; i < VL_MHSRV_PERBLK; i++) {
2423 exp = &ctx.ex_addr[base][i];
2424 tuuid = exp->ex_hostuuid;
2425 afs_ntohuuid(&tuuid);
2426 if (afs_uuid_is_nil(&tuuid))
2428 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2429 if (exp->ex_addrs[j]
2430 && (ntohl(exp->ex_addrs[j]) == attributes->ipaddr)) {
2434 if (j < VL_MAXIPADDRS_PERMH)
2437 if (i < VL_MHSRV_PERBLK)
2440 if (base >= VL_MAX_ADDREXTBLKS) {
2441 ubik_AbortTrans(ctx.trans);
2444 } else if (attributes->Mask & VLADDR_INDEX) {
2445 if (attributes->Mask & (VLADDR_IPADDR | VLADDR_UUID)) {
2446 ubik_AbortTrans(ctx.trans);
2449 index = attributes->index;
2450 if (index < 1 || index >= (VL_MAX_ADDREXTBLKS * VL_MHSRV_PERBLK)) {
2451 ubik_AbortTrans(ctx.trans);
2452 return VL_INDEXERANGE;
2454 base = index / VL_MHSRV_PERBLK;
2455 offset = index % VL_MHSRV_PERBLK;
2457 ubik_AbortTrans(ctx.trans);
2460 if (!ctx.ex_addr[base]) {
2461 ubik_AbortTrans(ctx.trans);
2462 return VL_INDEXERANGE;
2464 exp = &ctx.ex_addr[base][offset];
2465 } else if (attributes->Mask & VLADDR_UUID) {
2466 if (attributes->Mask & (VLADDR_IPADDR | VLADDR_INDEX)) {
2467 ubik_AbortTrans(ctx.trans);
2470 if (!ctx.ex_addr[0]) { /* mh servers probably aren't setup on this vldb */
2471 ubik_AbortTrans(ctx.trans);
2475 FindExtentBlock(&ctx, &attributes->uuid, 0, -1, &exp, &base))) {
2476 ubik_AbortTrans(ctx.trans);
2480 ubik_AbortTrans(ctx.trans);
2485 ubik_AbortTrans(ctx.trans);
2488 addrsp->bulkaddrs_val = taddrp =
2489 (afs_uint32 *) malloc(sizeof(afs_int32) * (MAXSERVERID + 1));
2490 nservers = *nentries = addrsp->bulkaddrs_len = 0;
2493 ubik_AbortTrans(ctx.trans);
2496 tuuid = exp->ex_hostuuid;
2497 afs_ntohuuid(&tuuid);
2498 if (afs_uuid_is_nil(&tuuid)) {
2499 ubik_AbortTrans(ctx.trans);
2505 *uniquifier = ntohl(exp->ex_uniquifier);
2506 for (i = 0; i < VL_MAXIPADDRS_PERMH; i++) {
2507 if (exp->ex_addrs[i]) {
2508 taddr = ntohl(exp->ex_addrs[i]);
2509 /* Weed out duplicates */
2510 for (j = 0; j < nservers; j++) {
2511 if (taddrp[j] == taddr)
2514 if ((j == nservers) && (j <= MAXSERVERID)) {
2515 taddrp[nservers] = taddr;
2520 addrsp->bulkaddrs_len = *nentries = nservers;
2521 return (ubik_EndTrans(ctx.trans));
2524 /* ============> End of Exported vldb RPC functions <============= */
2527 /* Routine that copies the given vldb entry to the output buffer, vldbentries. */
2529 put_attributeentry(struct vl_ctx *ctx,
2530 struct vldbentry **Vldbentry,
2531 struct vldbentry **VldbentryFirst,
2532 struct vldbentry **VldbentryLast,
2533 bulkentries *vldbentries,
2534 struct nvlentry *entry,
2535 afs_int32 *nentries,
2536 afs_int32 *alloccnt)
2541 if (*Vldbentry == *VldbentryLast) {
2543 return VL_SIZEEXCEEDED; /* no growing if smallMem defined */
2545 /* Allocate another set of memory; each time allocate twice as
2546 * many blocks as the last time. When we reach VLDBALLOCLIMIT,
2547 * then grow in increments of VLDBALLOCINCR.
2549 allo = (*alloccnt > VLDBALLOCLIMIT) ? VLDBALLOCINCR : *alloccnt;
2551 (vldbentry *) realloc(*VldbentryFirst,
2552 (*alloccnt + allo) * sizeof(vldbentry));
2556 *VldbentryFirst = vldbentries->bulkentries_val = reall;
2557 *Vldbentry = *VldbentryFirst + *alloccnt;
2558 *VldbentryLast = *Vldbentry + allo;
2561 vlentry_to_vldbentry(ctx, entry, *Vldbentry);
2564 vldbentries->bulkentries_len++;
2569 put_nattributeentry(struct vl_ctx *ctx,
2570 struct nvldbentry **Vldbentry,
2571 struct nvldbentry **VldbentryFirst,
2572 struct nvldbentry **VldbentryLast,
2573 nbulkentries *vldbentries,
2574 struct nvlentry *entry,
2575 afs_int32 matchtype,
2576 afs_int32 matchindex,
2577 afs_int32 *nentries,
2578 afs_int32 *alloccnt)
2583 if (*Vldbentry == *VldbentryLast) {
2585 return VL_SIZEEXCEEDED; /* no growing if smallMem defined */
2587 /* Allocate another set of memory; each time allocate twice as
2588 * many blocks as the last time. When we reach VLDBALLOCLIMIT,
2589 * then grow in increments of VLDBALLOCINCR.
2591 allo = (*alloccnt > VLDBALLOCLIMIT) ? VLDBALLOCINCR : *alloccnt;
2593 (nvldbentry *) realloc(*VldbentryFirst,
2594 (*alloccnt + allo) * sizeof(nvldbentry));
2598 *VldbentryFirst = vldbentries->nbulkentries_val = reall;
2599 *Vldbentry = *VldbentryFirst + *alloccnt;
2600 *VldbentryLast = *Vldbentry + allo;
2603 vlentry_to_nvldbentry(ctx, entry, *Vldbentry);
2604 (*Vldbentry)->matchindex = (matchtype << 16) + matchindex;
2607 vldbentries->nbulkentries_len++;
2612 /* Common code to actually remove a vldb entry from the database. */
2614 RemoveEntry(struct vl_ctx *ctx, afs_int32 entryptr,
2615 struct nvlentry *tentry)
2619 if ((errorcode = UnthreadVLentry(ctx, entryptr, tentry)))
2621 if ((errorcode = FreeBlock(ctx, entryptr)))
2627 ReleaseEntry(struct nvlentry *tentry, afs_int32 releasetype)
2629 if (releasetype & LOCKREL_TIMESTAMP)
2630 tentry->LockTimestamp = 0;
2631 if (releasetype & LOCKREL_OPCODE)
2632 tentry->flags &= ~VLOP_ALLOPERS;
2633 if (releasetype & LOCKREL_AFSID)
2634 tentry->LockAfsId = 0;
2638 /* Verify that the incoming vldb entry is valid; multi type of error codes
2641 check_vldbentry(struct vldbentry *aentry)
2645 if (InvalidVolname(aentry->name))
2647 if (aentry->nServers <= 0 || aentry->nServers > OMAXNSERVERS)
2648 return VL_BADSERVER;
2649 for (i = 0; i < aentry->nServers; i++) {
2650 /* if (aentry->serverNumber[i] < 0 || aentry->serverNumber[i] > MAXSERVERID)
2651 return VL_BADSERVER; */
2652 if (aentry->serverPartition[i] < 0
2653 || aentry->serverPartition[i] > MAXPARTITIONID)
2654 return VL_BADPARTITION;
2655 if (aentry->serverFlags[i] < 0
2656 || aentry->serverFlags[i] > MAXSERVERFLAG)
2657 return VL_BADSERVERFLAG;
2663 check_nvldbentry(struct nvldbentry *aentry)
2667 if (InvalidVolname(aentry->name))
2669 if (aentry->nServers <= 0 || aentry->nServers > NMAXNSERVERS)
2670 return VL_BADSERVER;
2671 for (i = 0; i < aentry->nServers; i++) {
2672 /* if (aentry->serverNumber[i] < 0 || aentry->serverNumber[i] > MAXSERVERID)
2673 return VL_BADSERVER; */
2674 if (aentry->serverPartition[i] < 0
2675 || aentry->serverPartition[i] > MAXPARTITIONID)
2676 return VL_BADPARTITION;
2677 if (aentry->serverFlags[i] < 0
2678 || aentry->serverFlags[i] > MAXSERVERFLAG)
2679 return VL_BADSERVERFLAG;
2685 /* Convert from the external vldb entry representation to its internal
2686 (more compact) form. This call should not change the hash chains! */
2688 vldbentry_to_vlentry(struct vl_ctx *ctx,
2689 struct vldbentry *VldbEntry,
2690 struct nvlentry *VlEntry)
2694 if (strcmp(VlEntry->name, VldbEntry->name))
2695 strncpy(VlEntry->name, VldbEntry->name, sizeof(VlEntry->name));
2696 for (i = 0; i < VldbEntry->nServers; i++) {
2697 serverindex = IpAddrToRelAddr(ctx, VldbEntry->serverNumber[i], 1);
2698 if (serverindex == -1)
2699 return VL_BADSERVER;
2700 VlEntry->serverNumber[i] = serverindex;
2701 VlEntry->serverPartition[i] = VldbEntry->serverPartition[i];
2702 VlEntry->serverFlags[i] = VldbEntry->serverFlags[i];
2704 for (; i < OMAXNSERVERS; i++)
2705 VlEntry->serverNumber[i] = VlEntry->serverPartition[i] =
2706 VlEntry->serverFlags[i] = BADSERVERID;
2707 for (i = 0; i < MAXTYPES; i++)
2708 VlEntry->volumeId[i] = VldbEntry->volumeId[i];
2709 VlEntry->cloneId = VldbEntry->cloneId;
2710 VlEntry->flags = VldbEntry->flags;
2715 nvldbentry_to_vlentry(struct vl_ctx *ctx,
2716 struct nvldbentry *VldbEntry,
2717 struct nvlentry *VlEntry)
2721 if (strcmp(VlEntry->name, VldbEntry->name))
2722 strncpy(VlEntry->name, VldbEntry->name, sizeof(VlEntry->name));
2723 for (i = 0; i < VldbEntry->nServers; i++) {
2724 serverindex = IpAddrToRelAddr(ctx, VldbEntry->serverNumber[i], 1);
2725 if (serverindex == -1)
2726 return VL_BADSERVER;
2727 VlEntry->serverNumber[i] = serverindex;
2728 VlEntry->serverPartition[i] = VldbEntry->serverPartition[i];
2729 VlEntry->serverFlags[i] = VldbEntry->serverFlags[i];
2731 for (; i < NMAXNSERVERS; i++)
2732 VlEntry->serverNumber[i] = VlEntry->serverPartition[i] =
2733 VlEntry->serverFlags[i] = BADSERVERID;
2734 for (i = 0; i < MAXTYPES; i++)
2735 VlEntry->volumeId[i] = VldbEntry->volumeId[i];
2736 VlEntry->cloneId = VldbEntry->cloneId;
2737 VlEntry->flags = VldbEntry->flags;
2742 /* Update the vldb entry with the new fields as indicated by the value of
2743 * the Mask entry in the updateentry structure. All necessary validation
2744 * checks are performed.
2747 get_vldbupdateentry(struct vl_ctx *ctx,
2748 afs_int32 blockindex,
2749 struct VldbUpdateEntry *updateentry,
2750 struct nvlentry *VlEntry)
2752 int i, j, errorcode, serverindex;
2753 afs_uint32 checkids[MAXTYPES];
2755 /* check if any specified new IDs are already present in the db. Do
2756 * this check before doing anything else, so we don't get a half-
2758 memset(&checkids, 0, sizeof(checkids));
2759 if (updateentry->Mask & VLUPDATE_RWID) {
2760 checkids[RWVOL] = updateentry->spares3; /* rw id */
2762 if (updateentry->Mask & VLUPDATE_READONLYID) {
2763 checkids[ROVOL] = updateentry->ReadOnlyId;
2765 if (updateentry->Mask & VLUPDATE_BACKUPID) {
2766 checkids[BACKVOL] = updateentry->BackupId;
2769 if (EntryIDExists(ctx, checkids, MAXTYPES, &errorcode)) {
2771 } else if (errorcode) {
2775 if (updateentry->Mask & VLUPDATE_VOLUMENAME) {
2776 struct nvlentry tentry;
2778 if (InvalidVolname(updateentry->name))
2781 if (FindByName(ctx, updateentry->name, &tentry, &errorcode)) {
2782 return VL_NAMEEXIST;
2783 } else if (errorcode) {
2787 if ((errorcode = UnhashVolname(ctx, blockindex, VlEntry)))
2789 strncpy(VlEntry->name, updateentry->name, sizeof(VlEntry->name));
2790 HashVolname(ctx, blockindex, VlEntry);
2793 if (updateentry->Mask & VLUPDATE_VOLNAMEHASH) {
2794 if ((errorcode = UnhashVolname(ctx, blockindex, VlEntry))) {
2795 if (errorcode != VL_NOENT)
2798 HashVolname(ctx, blockindex, VlEntry);
2801 if (updateentry->Mask & VLUPDATE_FLAGS) {
2802 VlEntry->flags = updateentry->flags;
2804 if (updateentry->Mask & VLUPDATE_CLONEID) {
2805 VlEntry->cloneId = updateentry->cloneId;
2807 if (updateentry->Mask & VLUPDATE_RWID) {
2808 if ((errorcode = UnhashVolid(ctx, RWVOL, blockindex, VlEntry))) {
2809 if (errorcode != VL_NOENT)
2812 VlEntry->volumeId[RWVOL] = updateentry->spares3; /* rw id */
2813 if ((errorcode = HashVolid(ctx, RWVOL, blockindex, VlEntry)))
2816 if (updateentry->Mask & VLUPDATE_READONLYID) {
2817 if ((errorcode = UnhashVolid(ctx, ROVOL, blockindex, VlEntry))) {
2818 if (errorcode != VL_NOENT)
2821 VlEntry->volumeId[ROVOL] = updateentry->ReadOnlyId;
2822 if ((errorcode = HashVolid(ctx, ROVOL, blockindex, VlEntry)))
2825 if (updateentry->Mask & VLUPDATE_BACKUPID) {
2826 if ((errorcode = UnhashVolid(ctx, BACKVOL, blockindex, VlEntry))) {
2827 if (errorcode != VL_NOENT)
2830 VlEntry->volumeId[BACKVOL] = updateentry->BackupId;
2831 if ((errorcode = HashVolid(ctx, BACKVOL, blockindex, VlEntry)))
2834 if (updateentry->Mask & VLUPDATE_REPSITES) {
2835 if (updateentry->nModifiedRepsites <= 0
2836 || updateentry->nModifiedRepsites > OMAXNSERVERS)
2837 return VL_BADSERVER;
2838 for (i = 0; i < updateentry->nModifiedRepsites; i++) {
2839 /* if (updateentry->RepsitesTargetServer[i] < 0 || updateentry->RepsitesTargetServer[i] > MAXSERVERID)
2840 return VL_BADSERVER; */
2841 if (updateentry->RepsitesTargetPart[i] < 0
2842 || updateentry->RepsitesTargetPart[i] > MAXPARTITIONID)
2843 return VL_BADPARTITION;
2844 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_DELETE) {
2846 repsite_exists(VlEntry,
2847 IpAddrToRelAddr(ctx, updateentry->
2848 RepsitesTargetServer[i],
2850 updateentry->RepsitesTargetPart[i])) !=
2852 repsite_compress(VlEntry, j);
2854 return VL_NOREPSERVER;
2856 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_ADD) {
2857 /* if (updateentry->RepsitesNewServer[i] < 0 || updateentry->RepsitesNewServer[i] > MAXSERVERID)
2858 return VL_BADSERVER; */
2859 if (updateentry->RepsitesNewPart[i] < 0
2860 || updateentry->RepsitesNewPart[i] > MAXPARTITIONID)
2861 return VL_BADPARTITION;
2864 IpAddrToRelAddr(ctx, updateentry->RepsitesNewServer[i], 1),
2865 updateentry->RepsitesNewPart[i]) != -1)
2866 return VL_DUPREPSERVER;
2868 VlEntry->serverNumber[j] != BADSERVERID
2869 && j < OMAXNSERVERS; j++);
2870 if (j >= OMAXNSERVERS)
2873 IpAddrToRelAddr(ctx, updateentry->RepsitesNewServer[i],
2875 return VL_BADSERVER;
2876 VlEntry->serverNumber[j] = serverindex;
2877 VlEntry->serverPartition[j] = updateentry->RepsitesNewPart[i];
2878 if (updateentry->RepsitesNewFlags[i] < 0
2879 || updateentry->RepsitesNewFlags[i] > MAXSERVERFLAG)
2880 return VL_BADSERVERFLAG;
2881 VlEntry->serverFlags[j] = updateentry->RepsitesNewFlags[i];
2883 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODSERV) {
2884 /*n if (updateentry->RepsitesNewServer[i] < 0 || updateentry->RepsitesNewServer[i] > MAXSERVERID)
2885 return VL_BADSERVER; */
2887 repsite_exists(VlEntry,
2888 IpAddrToRelAddr(ctx, updateentry->
2889 RepsitesTargetServer[i],
2891 updateentry->RepsitesTargetPart[i])) !=
2893 VlEntry->serverNumber[j] =
2894 IpAddrToRelAddr(ctx, updateentry->RepsitesNewServer[i],
2897 return VL_NOREPSERVER;
2899 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODPART) {
2900 if (updateentry->RepsitesNewPart[i] < 0
2901 || updateentry->RepsitesNewPart[i] > MAXPARTITIONID)
2902 return VL_BADPARTITION;
2904 repsite_exists(VlEntry,
2905 IpAddrToRelAddr(ctx, updateentry->
2906 RepsitesTargetServer[i],
2908 updateentry->RepsitesTargetPart[i])) !=
2910 VlEntry->serverPartition[j] =
2911 updateentry->RepsitesNewPart[i];
2913 return VL_NOREPSERVER;
2915 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODFLAG) {
2917 repsite_exists(VlEntry,
2918 IpAddrToRelAddr(ctx, updateentry->
2919 RepsitesTargetServer[i],
2921 updateentry->RepsitesTargetPart[i])) !=
2923 if (updateentry->RepsitesNewFlags[i] < 0
2924 || updateentry->RepsitesNewFlags[i] > MAXSERVERFLAG)
2925 return VL_BADSERVERFLAG;
2926 VlEntry->serverFlags[j] =
2927 updateentry->RepsitesNewFlags[i];
2929 return VL_NOREPSERVER;
2937 /* Check if the specified [server,partition] entry is found in the vldb
2938 * entry's repsite table; it's offset in the table is returned, if it's
2941 repsite_exists(struct nvlentry *VlEntry, int server, int partition)
2945 for (i = 0; VlEntry->serverNumber[i] != BADSERVERID && i < OMAXNSERVERS;
2947 if ((VlEntry->serverNumber[i] == server)
2948 && (VlEntry->serverPartition[i] == partition))
2956 /* Repsite table compression: used when deleting a repsite entry so that
2957 * all active repsite entries are on the top of the table. */
2959 repsite_compress(struct nvlentry *VlEntry, int offset)
2961 int repsite_offset = offset;
2963 VlEntry->serverNumber[repsite_offset] != BADSERVERID
2964 && repsite_offset < OMAXNSERVERS - 1; repsite_offset++) {
2965 VlEntry->serverNumber[repsite_offset] =
2966 VlEntry->serverNumber[repsite_offset + 1];
2967 VlEntry->serverPartition[repsite_offset] =
2968 VlEntry->serverPartition[repsite_offset + 1];
2969 VlEntry->serverFlags[repsite_offset] =
2970 VlEntry->serverFlags[repsite_offset + 1];
2972 VlEntry->serverNumber[repsite_offset] = BADSERVERID;
2976 /* Convert from the internal (compacted) vldb entry to the external
2977 * representation used by the interface. */
2979 vlentry_to_vldbentry(struct vl_ctx *ctx, struct nvlentry *VlEntry,
2980 struct vldbentry *VldbEntry)
2984 memset(VldbEntry, 0, sizeof(struct vldbentry));
2985 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
2986 for (i = 0; i < OMAXNSERVERS; i++) {
2987 if (VlEntry->serverNumber[i] == BADSERVERID)
2989 if ((ctx->hostaddress[j = VlEntry->serverNumber[i]] & 0xff000000) ==
2991 struct extentaddr *exp;
2994 base = (ctx->hostaddress[j] >> 16) & 0xff;
2995 index = ctx->hostaddress[j] & 0x0000ffff;
2996 exp = &ctx->ex_addr[base][index];
2997 /* For now return the first ip address back */
2998 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2999 if (exp->ex_addrs[j]) {
3000 VldbEntry->serverNumber[i] = ntohl(exp->ex_addrs[j]);
3005 VldbEntry->serverNumber[i] =
3006 ctx->hostaddress[VlEntry->serverNumber[i]];
3007 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
3008 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
3010 VldbEntry->nServers = i;
3011 for (i = 0; i < MAXTYPES; i++)
3012 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
3013 VldbEntry->cloneId = VlEntry->cloneId;
3014 VldbEntry->flags = VlEntry->flags;
3018 /* Convert from the internal (compacted) vldb entry to the external
3019 * representation used by the interface. */
3021 vlentry_to_nvldbentry(struct vl_ctx *ctx, struct nvlentry *VlEntry,
3022 struct nvldbentry *VldbEntry)
3026 memset(VldbEntry, 0, sizeof(struct vldbentry));
3027 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
3028 for (i = 0; i < NMAXNSERVERS; i++) {
3029 if (VlEntry->serverNumber[i] == BADSERVERID)
3031 if ((ctx->hostaddress[j = VlEntry->serverNumber[i]] & 0xff000000) ==
3033 struct extentaddr *exp;
3036 base = (ctx->hostaddress[j] >> 16) & 0xff;
3037 index = ctx->hostaddress[j] & 0x0000ffff;
3038 exp = &ctx->ex_addr[base][index];
3039 /* For now return the first ip address back */
3040 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
3041 if (exp->ex_addrs[j]) {
3042 VldbEntry->serverNumber[i] = ntohl(exp->ex_addrs[j]);
3047 VldbEntry->serverNumber[i] =
3048 ctx->hostaddress[VlEntry->serverNumber[i]];
3049 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
3050 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
3052 VldbEntry->nServers = i;
3053 for (i = 0; i < MAXTYPES; i++)
3054 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
3055 VldbEntry->cloneId = VlEntry->cloneId;
3056 VldbEntry->flags = VlEntry->flags;
3060 vlentry_to_uvldbentry(struct vl_ctx *ctx, struct nvlentry *VlEntry,
3061 struct uvldbentry *VldbEntry)
3065 memset(VldbEntry, 0, sizeof(struct vldbentry));
3066 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
3067 for (i = 0; i < NMAXNSERVERS; i++) {
3068 if (VlEntry->serverNumber[i] == BADSERVERID)
3070 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
3071 VldbEntry->serverUnique[i] = 0;
3072 if ((ctx->hostaddress[j = VlEntry->serverNumber[i]] & 0xff000000) ==
3074 struct extentaddr *exp;
3078 base = (ctx->hostaddress[j] >> 16) & 0xff;
3079 index = ctx->hostaddress[j] & 0x0000ffff;
3080 exp = &ctx->ex_addr[base][index];
3081 tuuid = exp->ex_hostuuid;
3082 afs_ntohuuid(&tuuid);
3083 VldbEntry->serverFlags[i] |= VLSERVER_FLAG_UUID;
3084 VldbEntry->serverNumber[i] = tuuid;
3085 VldbEntry->serverUnique[i] = ntohl(exp->ex_uniquifier);
3087 VldbEntry->serverNumber[i].time_low =
3088 ctx->hostaddress[VlEntry->serverNumber[i]];
3090 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
3093 VldbEntry->nServers = i;
3094 for (i = 0; i < MAXTYPES; i++)
3095 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
3096 VldbEntry->cloneId = VlEntry->cloneId;
3097 VldbEntry->flags = VlEntry->flags;
3100 #define LEGALCHARS ".ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
3103 /* Verify that the volname is a valid volume name. */
3105 InvalidVolname(char *volname)
3111 slen = strlen(volname);
3112 if (slen >= VL_MAXNAMELEN)
3114 return (slen != strspn(volname, map));
3118 /* Verify that the given volume type is valid. */
3120 InvalidVoltype(afs_int32 voltype)
3122 if (voltype != RWVOL && voltype != ROVOL && voltype != BACKVOL)
3129 InvalidOperation(afs_int32 voloper)
3131 if (voloper != VLOP_MOVE && voloper != VLOP_RELEASE
3132 && voloper != VLOP_BACKUP && voloper != VLOP_DELETE
3133 && voloper != VLOP_DUMP)
3139 InvalidReleasetype(afs_int32 releasetype)
3141 if ((releasetype & LOCKREL_TIMESTAMP) || (releasetype & LOCKREL_OPCODE)
3142 || (releasetype & LOCKREL_AFSID))
3148 IpAddrToRelAddr(struct vl_ctx *ctx, afs_uint32 ipaddr, int create)
3151 afs_int32 code, base, index;
3152 struct extentaddr *exp;
3154 for (i = 0; i <= MAXSERVERID; i++) {
3155 if (ctx->hostaddress[i] == ipaddr)
3157 if ((ctx->hostaddress[i] & 0xff000000) == 0xff000000) {
3158 base = (ctx->hostaddress[i] >> 16) & 0xff;
3159 index = ctx->hostaddress[i] & 0x0000ffff;
3160 if (base >= VL_MAX_ADDREXTBLKS) {
3162 ("Internal error: Multihome extent base is too large. Base %d index %d\n",
3164 return -1; /* EINVAL */
3166 if (index >= VL_MHSRV_PERBLK) {
3168 ("Internal error: Multihome extent index is too large. Base %d index %d\n",
3170 return -1; /* EINVAL */
3172 if (!ctx->ex_addr[base]) {
3174 ("Internal error: Multihome extent does not exist. Base %d\n",
3176 return -1; /* EINVAL */
3178 exp = &ctx->ex_addr[base][index];
3179 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
3180 if (exp->ex_addrs[j] && (ntohl(exp->ex_addrs[j]) == ipaddr)) {
3187 /* allocate the new server a server id pronto */
3189 for (i = 0; i <= MAXSERVERID; i++) {
3190 if (ctx->cheader->IpMappedAddr[i] == 0) {
3191 ctx->cheader->IpMappedAddr[i] = htonl(ipaddr);
3194 DOFFSET(0, ctx->cheader, &ctx->cheader->IpMappedAddr[i]),
3195 (char *)&ctx->cheader->IpMappedAddr[i],
3197 ctx->hostaddress[i] = ipaddr;
3208 ChangeIPAddr(struct vl_ctx *ctx, afs_uint32 ipaddr1, afs_uint32 ipaddr2)
3212 struct extentaddr *exp = NULL;
3216 afs_int32 blockindex, count;
3218 struct nvlentry tentry;
3219 int ipaddr1_id = -1, ipaddr2_id = -1;
3221 /* Don't let addr change to 256.*.*.* : Causes internal error below */
3222 if ((ipaddr2 & 0xff000000) == 0xff000000)
3223 return (VL_BADSERVER);
3225 /* If we are removing an address, ip1 will be -1 and ip2 will be
3226 * the original address. This prevents an older revision vlserver
3227 * from removing the IP address (won't find server 0xfffffff in
3228 * the VLDB). An older revision vlserver does not have the check
3229 * to see if any volumes exist on the server being removed.
3231 if (ipaddr1 == 0xffffffff) {
3236 for (i = 0; i <= MAXSERVERID; i++) {
3237 if ((ctx->hostaddress[i] & 0xff000000) == 0xff000000) {
3238 base = (ctx->hostaddress[i] >> 16) & 0xff;
3239 index = ctx->hostaddress[i] & 0x0000ffff;
3240 if ((base >= VL_MAX_ADDREXTBLKS) || (index >= VL_MHSRV_PERBLK)) {
3242 ("Internal error: Multihome extent addr is too large. Base %d index %d\n",
3244 return -1; /* EINVAL */
3247 exp = &ctx->ex_addr[base][index];
3248 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
3249 if (!exp->ex_addrs[mhidx])
3251 if (ntohl(exp->ex_addrs[mhidx]) == ipaddr1) {
3254 if (ipaddr2 != 0 && ntohl(exp->ex_addrs[mhidx]) == ipaddr2) {
3259 if (ctx->hostaddress[i] == ipaddr1) {
3263 if (ipaddr2 != 0 && ctx->hostaddress[i] == ipaddr2) {
3268 if (ipaddr1_id >= 0 && (ipaddr2 == 0 || ipaddr2_id >= 0)) {
3269 /* we've either found both IPs already in the VLDB, or we found
3270 * ipaddr1, and we're not going to find ipaddr2 because it's 0 */
3275 if (ipaddr1_id < 0) {
3276 return VL_NOENT; /* not found */
3279 if (ipaddr2_id >= 0 && ipaddr2_id != ipaddr1_id) {
3280 char buf1[16], buf2[16];
3281 VLog(0, ("Cannot change IP address from %s to %s because the latter "
3282 "is in use by server id %d\n",
3283 afs_inet_ntoa_r(htonl(ipaddr1), buf1),
3284 afs_inet_ntoa_r(htonl(ipaddr2), buf2),
3286 return VL_MULTIPADDR;
3289 /* If we are removing a server entry, a volume cannot
3290 * exist on the server. If one does, don't remove the
3291 * server entry: return error "volume entry exists".
3294 for (blockindex = NextEntry(ctx, 0, &tentry, &count); blockindex;
3295 blockindex = NextEntry(ctx, blockindex, &tentry, &count)) {
3296 if (++pollcount > 50) {
3297 #ifndef AFS_PTHREAD_ENV
3302 for (j = 0; j < NMAXNSERVERS; j++) {
3303 if (tentry.serverNumber[j] == BADSERVERID)
3305 if (tentry.serverNumber[j] == ipaddr1_id) {
3312 /* Log a message saying we are changing/removing an IP address */
3314 ("The following IP address is being %s:\n",
3315 (ipaddr2 ? "changed" : "removed")));
3316 VLog(0, (" entry %d: ", i));
3319 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
3320 if (!exp->ex_addrs[mhidx])
3324 PADDR(ntohl(exp->ex_addrs[mhidx]));
3336 /* Change the registered uuuid addresses */
3338 memset(&tuuid, 0, sizeof(afsUUID));
3339 afs_htonuuid(&tuuid);
3340 exp->ex_hostuuid = tuuid;
3343 DOFFSET(ntohl(ctx->ex_addr[0]->ex_contaddrs[base]),
3344 (char *)ctx->ex_addr[base], (char *)exp),
3345 (char *)&tuuid, sizeof(tuuid));
3350 /* Now change the host address entry */
3351 ctx->cheader->IpMappedAddr[ipaddr1_id] = htonl(ipaddr2);
3353 vlwrite(ctx->trans, DOFFSET(0, ctx->cheader, &ctx->cheader->IpMappedAddr[ipaddr1_id]),
3355 &ctx->cheader->IpMappedAddr[ipaddr1_id], sizeof(afs_int32));
3356 ctx->hostaddress[ipaddr1_id] = ipaddr2;
3363 /* see if the vlserver is back yet */
3365 SVL_ProbeServer(struct rx_call *rxcall)