2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include <afs/param.h>
14 #include <sys/types.h>
18 #include <afs/afsutil.h>
26 #include <netinet/in.h>
29 #include <afs/cellconfig.h>
31 #include "vlserver_internal.h"
32 #include "afs/audit.h"
36 #ifdef HAVE_POSIX_REGEX /* use POSIX regexp library */
41 extern int extent_mod;
42 extern struct afsconf_dir *vldb_confdir;
43 extern struct ubik_dbase *VL_dbase;
45 #define ABORT(c) { errorcode = (c); goto abort; }
47 #define END(c) { errorcode = (c); goto end; }
49 #define VLDBALLOCLIMIT 10000
50 #define VLDBALLOCINCR 2048
52 static int put_attributeentry(struct vl_ctx *ctx,
53 struct vldbentry **, struct vldbentry **,
54 struct vldbentry **, bulkentries *,
55 struct nvlentry *, afs_int32 *, afs_int32 *);
56 static int put_nattributeentry(struct vl_ctx *ctx,
57 struct nvldbentry **, struct nvldbentry **,
58 struct nvldbentry **, nbulkentries *,
59 struct nvlentry *, afs_int32, afs_int32,
60 afs_int32 *, afs_int32 *);
61 static int RemoveEntry(struct vl_ctx *ctx, afs_int32 entryptr,
62 struct nvlentry *tentry);
63 static void ReleaseEntry(struct nvlentry *tentry, afs_int32 releasetype);
64 static int check_vldbentry(struct vldbentry *aentry);
65 static int check_nvldbentry(struct nvldbentry *aentry);
66 static int vldbentry_to_vlentry(struct vl_ctx *ctx,
67 struct vldbentry *VldbEntry,
68 struct nvlentry *VlEntry);
69 static int nvldbentry_to_vlentry(struct vl_ctx *ctx,
70 struct nvldbentry *VldbEntry,
71 struct nvlentry *VlEntry);
72 static int get_vldbupdateentry(struct vl_ctx *ctx, afs_int32 blockindex,
73 struct VldbUpdateEntry *updateentry,
74 struct nvlentry *VlEntry);
75 static int repsite_exists(struct nvlentry *VlEntry, int server, int partition);
76 static void repsite_compress(struct nvlentry *VlEntry, int offset);
77 static void vlentry_to_vldbentry(struct vl_ctx *ctx,
78 struct nvlentry *VlEntry,
79 struct vldbentry *VldbEntry);
80 static void vlentry_to_nvldbentry(struct vl_ctx *ctx,
81 struct nvlentry *VlEntry,
82 struct nvldbentry *VldbEntry);
83 static void vlentry_to_uvldbentry(struct vl_ctx *ctx,
84 struct nvlentry *VlEntry,
85 struct uvldbentry *VldbEntry);
86 static int InvalidVolname(char *volname);
87 static int InvalidVoltype(afs_int32 voltype);
88 static int InvalidOperation(afs_int32 voloper);
89 static int InvalidReleasetype(afs_int32 releasetype);
90 static int IpAddrToRelAddr(struct vl_ctx *ctx, afs_uint32 ipaddr, int create);
91 static int ChangeIPAddr(struct vl_ctx *ctx, afs_uint32 ipaddr1,
94 #define AFS_RXINFO_LEN 128
96 rxinfo(char * str, struct rx_call *rxcall)
99 struct rx_connection *tconn;
104 struct in_addr hostAddr;
106 tconn = rx_ConnectionOf(rxcall);
107 hostAddr.s_addr = rx_HostOf(rx_PeerOf(tconn));
109 rxkad_GetServerInfo(rxcall->conn, NULL, &exp, tname, tinst, tcell,
112 sprintf(str, "%s %s%s%s%s%s", inet_ntoa(hostAddr), tname,
113 (tinst[0] == '\0') ? "" : ".",
114 (tinst[0] == '\0') ? "" : tinst,
115 (tcell[0] == '\0') ? "" : "@",
116 (tcell[0] == '\0') ? "" : tcell);
118 sprintf(str, "%s noauth", inet_ntoa(hostAddr));
122 /* This is called to initialize the database, set the appropriate locks and make sure that the vldb header is valid */
124 Init_VLdbase(struct vl_ctx *ctx,
125 int locktype, /* indicate read or write transaction */
128 int errorcode = 0, pass, wl;
130 for (pass = 1; pass <= 3; pass++) {
131 if (pass == 2) { /* take write lock to rebuild the db */
132 errorcode = ubik_BeginTrans(VL_dbase, UBIK_WRITETRANS, &ctx->trans);
134 } else if (locktype == LOCKREAD) {
136 ubik_BeginTransReadAnyWrite(VL_dbase, UBIK_READTRANS, &ctx->trans);
139 errorcode = ubik_BeginTrans(VL_dbase, UBIK_WRITETRANS, &ctx->trans);
145 errorcode = ubik_SetLock(ctx->trans, 1, 1, locktype);
148 ubik_AbortTrans(ctx->trans);
152 /* check that dbase is initialized and setup cheader */
153 /* 2nd pass we try to rebuild the header */
154 errorcode = CheckInit(ctx->trans, ((pass == 2) ? 1 : 0));
155 if (!errorcode && wl && extent_mod)
156 errorcode = readExtents(ctx->trans); /* Fix the mh extent blocks */
159 ubik_AbortTrans(ctx->trans);
160 /* Only rebuld if the database is empty */
161 /* Exit if can't rebuild */
162 if ((pass == 1) && (errorcode != VL_EMPTY))
166 } else { /* No errorcode */
168 ubik_EndTrans(ctx->trans); /* Rebuilt db. End trans, then retake original lock */
170 break; /* didn't rebuild and successful - exit */
174 if (errorcode == 0) {
175 errorcode = vlsetcache(ctx, locktype);
181 /* Create a new vldb entry; both new volume id and name must be unique
182 * (non-existant in vldb).
186 SVL_CreateEntry(struct rx_call *rxcall, struct vldbentry *newentry)
189 afs_int32 errorcode, blockindex;
190 struct nvlentry tentry;
191 char rxstr[AFS_RXINFO_LEN];
193 COUNT_REQ(VLCREATEENTRY);
194 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) {
199 /* Do some validity tests on new entry */
200 if ((errorcode = check_vldbentry(newentry))
201 || (errorcode = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
205 ("OCreate Volume %d %s\n", newentry->volumeId[RWVOL],
206 rxinfo(rxstr, rxcall)));
207 if (EntryIDExists(&ctx, newentry->volumeId, MAXTYPES, &errorcode)) {
208 /* at least one of the specified IDs already exists; we fail */
209 errorcode = VL_IDEXIST;
211 } else if (errorcode) {
215 /* Is this following check (by volume name) necessary?? */
216 /* If entry already exists, we fail */
217 if (FindByName(&ctx, newentry->name, &tentry, &errorcode)) {
218 errorcode = VL_NAMEEXIST;
220 } else if (errorcode) {
224 blockindex = AllocBlock(&ctx, &tentry);
225 if (blockindex == 0) {
226 errorcode = VL_CREATEFAIL;
230 memset(&tentry, 0, sizeof(struct nvlentry));
231 /* Convert to its internal representation; both in host byte order */
232 if ((errorcode = vldbentry_to_vlentry(&ctx, newentry, &tentry))) {
233 FreeBlock(&ctx, blockindex);
237 /* Actually insert the entry in vldb */
238 errorcode = ThreadVLentry(&ctx, blockindex, &tentry);
240 FreeBlock(&ctx, blockindex);
243 errorcode = ubik_EndTrans(ctx.trans);
249 ubik_AbortTrans(ctx.trans);
252 osi_auditU(rxcall, VLCreateEntryEvent, errorcode, AUD_STR,
253 (newentry ? newentry->name : NULL), AUD_END);
259 SVL_CreateEntryN(struct rx_call *rxcall, struct nvldbentry *newentry)
262 afs_int32 errorcode, blockindex;
263 struct nvlentry tentry;
264 char rxstr[AFS_RXINFO_LEN];
266 COUNT_REQ(VLCREATEENTRYN);
267 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) {
272 /* Do some validity tests on new entry */
273 if ((errorcode = check_nvldbentry(newentry))
274 || (errorcode = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
278 ("Create Volume %d %s\n", newentry->volumeId[RWVOL],
279 rxinfo(rxstr, rxcall)));
280 if (EntryIDExists(&ctx, newentry->volumeId, MAXTYPES, &errorcode)) {
281 /* at least one of the specified IDs already exists; we fail */
282 errorcode = VL_IDEXIST;
284 } else if (errorcode) {
288 /* Is this following check (by volume name) necessary?? */
289 /* If entry already exists, we fail */
290 if (FindByName(&ctx, newentry->name, &tentry, &errorcode)) {
291 errorcode = VL_NAMEEXIST;
293 } else if (errorcode) {
297 blockindex = AllocBlock(&ctx, &tentry);
298 if (blockindex == 0) {
299 errorcode = VL_CREATEFAIL;
303 memset(&tentry, 0, sizeof(struct nvlentry));
304 /* Convert to its internal representation; both in host byte order */
305 if ((errorcode = nvldbentry_to_vlentry(&ctx, newentry, &tentry))) {
306 FreeBlock(&ctx, blockindex);
310 /* Actually insert the entry in vldb */
311 errorcode = ThreadVLentry(&ctx, blockindex, &tentry);
313 FreeBlock(&ctx, blockindex);
316 errorcode = ubik_EndTrans(ctx.trans);
322 ubik_AbortTrans(ctx.trans);
325 osi_auditU(rxcall, VLCreateEntryEvent, errorcode, AUD_STR,
326 (newentry ? newentry->name : NULL), AUD_END);
332 SVL_ChangeAddr(struct rx_call *rxcall, afs_uint32 ip1, afs_uint32 ip2)
336 char rxstr[AFS_RXINFO_LEN];
338 COUNT_REQ(VLCHANGEADDR);
339 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) {
344 if ((errorcode = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
347 VLog(1, ("Change Addr %u -> %u %s\n", ip1, ip2, rxinfo(rxstr, rxcall)));
348 if ((errorcode = ChangeIPAddr(&ctx, ip1, ip2)))
351 errorcode = ubik_EndTrans(ctx.trans);
357 ubik_AbortTrans(ctx.trans);
360 osi_auditU(rxcall, VLChangeAddrEvent, errorcode, AUD_LONG, ip1, AUD_LONG,
365 /* Delete a vldb entry given the volume id. */
367 SVL_DeleteEntry(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype)
370 afs_int32 blockindex, errorcode;
371 struct nvlentry tentry;
372 char rxstr[AFS_RXINFO_LEN];
374 COUNT_REQ(VLDELETEENTRY);
375 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
378 if ((voltype != -1) && (InvalidVoltype(voltype)))
381 if ((errorcode = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
384 VLog(1, ("Delete Volume %u %s\n", volid, rxinfo(rxstr, rxcall)));
385 blockindex = FindByID(&ctx, volid, voltype, &tentry, &errorcode);
386 if (blockindex == 0) { /* volid not found */
388 errorcode = VL_NOENT;
392 if (tentry.flags & VLDELETED) { /* Already deleted; return */
393 ABORT(VL_ENTDELETED);
395 if ((errorcode = RemoveEntry(&ctx, blockindex, &tentry))) {
398 errorcode = (ubik_EndTrans(ctx.trans));
403 ubik_AbortTrans(ctx.trans);
406 osi_auditU(rxcall, VLDeleteEntryEvent, errorcode, AUD_LONG, volid,
412 /* Get a vldb entry given its volume id; make sure it's not a deleted entry. */
414 GetEntryByID(struct rx_call *rxcall,
417 char *aentry, /* entry data copied here */
422 afs_int32 blockindex, errorcode;
423 struct nvlentry tentry;
424 char rxstr[AFS_RXINFO_LEN];
426 if ((voltype != -1) && (InvalidVoltype(voltype)))
427 return VL_BADVOLTYPE;
428 if ((errorcode = Init_VLdbase(&ctx, LOCKREAD, this_op)))
431 VLog(5, ("GetVolumeByID %u (%d) %s\n", volid, new,
432 rxinfo(rxstr, rxcall)));
433 blockindex = FindByID(&ctx, volid, voltype, &tentry, &errorcode);
434 if (blockindex == 0) { /* entry not found */
436 errorcode = VL_NOENT;
438 ubik_AbortTrans(ctx.trans);
441 if (tentry.flags & VLDELETED) { /* Entry is deleted! */
443 ubik_AbortTrans(ctx.trans);
444 return VL_ENTDELETED;
446 /* Convert from the internal to external form */
448 vlentry_to_nvldbentry(&ctx, &tentry, (struct nvldbentry *)aentry);
450 vlentry_to_uvldbentry(&ctx, &tentry, (struct uvldbentry *)aentry);
452 vlentry_to_vldbentry(&ctx, &tentry, (struct vldbentry *)aentry);
453 return (ubik_EndTrans(ctx.trans));
457 SVL_GetEntryByID(struct rx_call *rxcall,
460 vldbentry *aentry) /* entry data copied here */
462 COUNT_REQ(VLGETENTRYBYID);
463 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 0, this_op));
467 SVL_GetEntryByIDN(struct rx_call *rxcall,
470 nvldbentry *aentry) /* entry data copied here */
472 COUNT_REQ(VLGETENTRYBYIDN);
473 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 1, this_op));
477 SVL_GetEntryByIDU(struct rx_call *rxcall,
480 uvldbentry *aentry) /* entry data copied here */
482 COUNT_REQ(VLGETENTRYBYIDU);
483 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 2, this_op));
488 /* returns true if the id is a decimal integer, in which case we interpret
489 * it as an id. make the cache manager much simpler */
491 NameIsId(char *aname)
494 while ((tc = *aname++)) {
495 if (tc > '9' || tc < '0')
501 /* Get a vldb entry given the volume's name; of course, very similar to
502 * VLGetEntryByID() above. */
504 GetEntryByName(struct rx_call *rxcall,
506 char *aentry, /* entry data copied here */
511 afs_int32 blockindex, errorcode;
512 struct nvlentry tentry;
513 char rxstr[AFS_RXINFO_LEN];
515 if (NameIsId(volname)) {
516 return GetEntryByID(rxcall, atoi(volname), -1, aentry, new, this_op);
518 if (InvalidVolname(volname))
520 if ((errorcode = Init_VLdbase(&ctx, LOCKREAD, this_op)))
522 VLog(5, ("GetVolumeByName %s (%d) %s\n", volname, new, rxinfo(rxstr, rxcall)));
523 blockindex = FindByName(&ctx, volname, &tentry, &errorcode);
524 if (blockindex == 0) { /* entry not found */
526 errorcode = VL_NOENT;
528 ubik_AbortTrans(ctx.trans);
531 if (tentry.flags & VLDELETED) { /* Entry is deleted */
533 ubik_AbortTrans(ctx.trans);
534 return VL_ENTDELETED;
536 /* Convert to external entry representation */
538 vlentry_to_nvldbentry(&ctx, &tentry, (struct nvldbentry *)aentry);
540 vlentry_to_uvldbentry(&ctx, &tentry, (struct uvldbentry *)aentry);
542 vlentry_to_vldbentry(&ctx, &tentry, (struct vldbentry *)aentry);
543 return (ubik_EndTrans(ctx.trans));
547 SVL_GetEntryByNameO(struct rx_call *rxcall,
549 struct vldbentry *aentry) /* entry data copied here */
551 COUNT_REQ(VLGETENTRYBYNAME);
552 return (GetEntryByName(rxcall, volname, (char *)aentry, 0, this_op));
557 SVL_GetEntryByNameN(struct rx_call *rxcall,
559 struct nvldbentry *aentry) /* entry data copied here */
561 COUNT_REQ(VLGETENTRYBYNAMEN);
562 return (GetEntryByName(rxcall, volname, (char *)aentry, 1, this_op));
566 SVL_GetEntryByNameU(struct rx_call *rxcall,
568 struct uvldbentry *aentry) /* entry data copied here */
570 COUNT_REQ(VLGETENTRYBYNAMEU);
571 return (GetEntryByName(rxcall, volname, (char *)aentry, 2, this_op));
576 /* Get the current value of the maximum volume id and bump the volume id counter by Maxvolidbump. */
578 SVL_GetNewVolumeId(struct rx_call *rxcall, afs_uint32 Maxvolidbump,
579 afs_uint32 *newvolumeid)
582 afs_uint32 maxvolumeid;
584 char rxstr[AFS_RXINFO_LEN];
586 COUNT_REQ(VLGETNEWVOLUMEID);
587 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
590 if (Maxvolidbump < 0 || Maxvolidbump > MAXBUMPCOUNT)
591 END(VL_BADVOLIDBUMP);
593 if ((errorcode = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
596 *newvolumeid = maxvolumeid = NextUnusedID(&ctx,
597 ntohl(ctx.cheader->vital_header.MaxVolumeId), Maxvolidbump, &errorcode);
602 maxvolumeid += Maxvolidbump;
603 VLog(1, ("GetNewVolid newmax=%u %s\n", maxvolumeid, rxinfo(rxstr, rxcall)));
604 ctx.cheader->vital_header.MaxVolumeId = htonl(maxvolumeid);
605 if (write_vital_vlheader(&ctx)) {
608 errorcode = (ubik_EndTrans(ctx.trans));
613 ubik_AbortTrans(ctx.trans);
616 osi_auditU(rxcall, VLGetNewVolumeIdEvent, errorcode, AUD_END);
621 /* Simple replace the contents of the vldb entry, volid, with
622 * newentry. No individual checking/updating per field (alike
623 * VLUpdateEntry) is done. */
626 SVL_ReplaceEntry(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype,
627 struct vldbentry *newentry, afs_int32 releasetype)
630 afs_int32 blockindex, errorcode, typeindex;
632 int hashVol[MAXTYPES];
633 struct nvlentry tentry;
634 afs_uint32 checkids[MAXTYPES];
635 char rxstr[AFS_RXINFO_LEN];
637 COUNT_REQ(VLREPLACEENTRY);
638 for (typeindex = 0; typeindex < MAXTYPES; typeindex++)
639 hashVol[typeindex] = 0;
641 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
644 if ((errorcode = check_vldbentry(newentry)))
647 if (voltype != -1 && InvalidVoltype(voltype))
650 if (releasetype && InvalidReleasetype(releasetype))
651 END(VL_BADRELLOCKTYPE);
652 if ((errorcode = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
655 VLog(1, ("OReplace Volume %u %s\n", volid, rxinfo(rxstr, rxcall)));
656 /* find vlentry we're changing */
657 blockindex = FindByID(&ctx, volid, voltype, &tentry, &errorcode);
658 if (blockindex == 0) { /* entry not found */
660 errorcode = VL_NOENT;
664 /* check that we're not trying to change the RW vol ID */
665 if (newentry->volumeId[RWVOL] != tentry.volumeId[RWVOL]) {
669 /* make sure none of the IDs we are changing to are already in use */
670 memset(&checkids, 0, sizeof(checkids));
671 for (typeindex = ROVOL; typeindex < MAXTYPES; typeindex++) {
672 if (tentry.volumeId[typeindex] != newentry->volumeId[typeindex]) {
673 checkids[typeindex] = newentry->volumeId[typeindex];
676 if (EntryIDExists(&ctx, checkids, MAXTYPES, &errorcode)) {
678 } else if (errorcode) {
682 /* make sure the name we're changing to doesn't already exist */
683 if (strcmp(newentry->name, tentry.name)) {
684 struct nvlentry tmp_entry;
685 if (FindByName(&ctx, newentry->name, &tmp_entry, &errorcode)) {
687 } else if (errorcode) {
692 /* unhash volid entries if they're disappearing or changing.
693 * Remember if we need to hash in the new value (we don't have to
694 * rehash if volid stays same */
695 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
696 if (tentry.volumeId[typeindex] != newentry->volumeId[typeindex]) {
697 if (tentry.volumeId[typeindex])
699 UnhashVolid(&ctx, typeindex, blockindex, &tentry))) {
702 /* we must rehash new id if the id is different and the ID is nonzero */
703 hashVol[typeindex] = 1; /* must rehash this guy if he exists */
707 /* Rehash volname if it changes */
708 if (strcmp(newentry->name, tentry.name)) { /* Name changes; redo hashing */
709 if ((errorcode = UnhashVolname(&ctx, blockindex, &tentry))) {
715 /* after this, tentry is new entry, not old one. vldbentry_to_vlentry
716 * doesn't touch hash chains */
717 if ((errorcode = vldbentry_to_vlentry(&ctx, newentry, &tentry))) {
721 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
722 if (hashVol[typeindex] && tentry.volumeId[typeindex]) {
723 if ((errorcode = HashVolid(&ctx, typeindex, blockindex, &tentry))) {
730 HashVolname(&ctx, blockindex, &tentry);
733 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
734 if (vlentrywrite(ctx.trans, blockindex, &tentry, sizeof(tentry))) {
738 END(ubik_EndTrans(ctx.trans));
742 ubik_AbortTrans(ctx.trans);
745 osi_auditU(rxcall, VLReplaceVLEntryEvent, errorcode, AUD_LONG, volid,
751 SVL_ReplaceEntryN(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype,
752 struct nvldbentry *newentry, afs_int32 releasetype)
755 afs_int32 blockindex, errorcode, typeindex;
757 int hashVol[MAXTYPES];
758 struct nvlentry tentry;
759 char rxstr[AFS_RXINFO_LEN];
761 COUNT_REQ(VLREPLACEENTRYN);
762 for (typeindex = 0; typeindex < MAXTYPES; typeindex++)
763 hashVol[typeindex] = 0;
765 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
768 if ((errorcode = check_nvldbentry(newentry)))
771 if (voltype != -1 && InvalidVoltype(voltype))
774 if (releasetype && InvalidReleasetype(releasetype))
775 END(VL_BADRELLOCKTYPE);
776 if ((errorcode = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
779 VLog(1, ("Replace Volume %u %s\n", volid, rxinfo(rxstr, rxcall)));
780 /* find vlentry we're changing */
781 blockindex = FindByID(&ctx, volid, voltype, &tentry, &errorcode);
782 if (blockindex == 0) { /* entry not found */
784 errorcode = VL_NOENT;
788 /* check that we're not trying to change the RW vol ID */
789 if (newentry->volumeId[RWVOL] != tentry.volumeId[RWVOL]) {
793 /* unhash volid entries if they're disappearing or changing.
794 * Remember if we need to hash in the new value (we don't have to
795 * rehash if volid stays same */
796 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
797 if (tentry.volumeId[typeindex] != newentry->volumeId[typeindex]) {
798 if (tentry.volumeId[typeindex])
800 UnhashVolid(&ctx, typeindex, blockindex, &tentry))) {
803 /* we must rehash new id if the id is different and the ID is nonzero */
804 hashVol[typeindex] = 1; /* must rehash this guy if he exists */
808 /* Rehash volname if it changes */
809 if (strcmp(newentry->name, tentry.name)) { /* Name changes; redo hashing */
810 if ((errorcode = UnhashVolname(&ctx, blockindex, &tentry))) {
816 /* after this, tentry is new entry, not old one. vldbentry_to_vlentry
817 * doesn't touch hash chains */
818 if ((errorcode = nvldbentry_to_vlentry(&ctx, newentry, &tentry))) {
822 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
823 if (hashVol[typeindex] && tentry.volumeId[typeindex]) {
824 if ((errorcode = HashVolid(&ctx, typeindex, blockindex, &tentry))) {
831 HashVolname(&ctx, blockindex, &tentry);
834 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
835 if (vlentrywrite(ctx.trans, blockindex, &tentry, sizeof(tentry))) {
839 END(ubik_EndTrans(ctx.trans));
843 ubik_AbortTrans(ctx.trans);
846 osi_auditU(rxcall, VLReplaceVLEntryEvent, errorcode, AUD_LONG, volid,
852 /* Update a vldb entry (accessed thru its volume id). Almost all of the
853 * entry's fields can be modified in a single call by setting the
854 * appropriate bits in the Mask field in VldbUpdateentry. */
855 /* this routine may never have been tested; use replace entry instead
856 * unless you're brave */
858 SVL_UpdateEntry(struct rx_call *rxcall,
861 struct VldbUpdateEntry *updateentry, /* Update entry copied here */
862 afs_int32 releasetype)
865 afs_int32 blockindex, errorcode;
866 struct nvlentry tentry;
867 char rxstr[AFS_RXINFO_LEN];
869 COUNT_REQ(VLUPDATEENTRY);
870 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
872 if ((voltype != -1) && (InvalidVoltype(voltype)))
874 if (releasetype && InvalidReleasetype(releasetype))
875 END(VL_BADRELLOCKTYPE);
876 if ((errorcode = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
879 VLog(1, ("Update Volume %u %s\n", volid, rxinfo(rxstr, rxcall)));
880 blockindex = FindByID(&ctx, volid, voltype, &tentry, &errorcode);
881 if (blockindex == 0) { /* entry not found */
883 errorcode = VL_NOENT;
887 /* Do the actual updating of the entry, tentry. */
889 get_vldbupdateentry(&ctx, blockindex, updateentry, &tentry))) {
893 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
894 if (vlentrywrite(ctx.trans, blockindex, &tentry, sizeof(tentry))) {
897 END(ubik_EndTrans(ctx.trans));
901 ubik_AbortTrans(ctx.trans);
904 osi_auditU(rxcall, VLUpdateEntryEvent, errorcode, AUD_LONG, volid,
911 SVL_UpdateEntryByName(struct rx_call *rxcall,
913 struct VldbUpdateEntry *updateentry, /* Update entry copied here */
914 afs_int32 releasetype)
917 afs_int32 blockindex, errorcode;
918 struct nvlentry tentry;
920 COUNT_REQ(VLUPDATEENTRYBYNAME);
921 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
923 if (releasetype && InvalidReleasetype(releasetype))
924 END(VL_BADRELLOCKTYPE);
925 if ((errorcode = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
928 blockindex = FindByName(&ctx, volname, &tentry, &errorcode);
929 if (blockindex == 0) { /* entry not found */
931 errorcode = VL_NOENT;
935 /* Do the actual updating of the entry, tentry. */
937 get_vldbupdateentry(&ctx, blockindex, updateentry, &tentry))) {
941 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
942 if (vlentrywrite(ctx.trans, blockindex, &tentry, sizeof(tentry))) {
945 END(ubik_EndTrans(ctx.trans));
949 ubik_AbortTrans(ctx.trans);
952 osi_auditU(rxcall, VLUpdateEntryEvent, errorcode, AUD_LONG, -1, AUD_END);
957 /* Set a lock to the vldb entry for volid (of type voltype if not -1). */
959 SVL_SetLock(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype,
962 afs_int32 timestamp, blockindex, errorcode;
964 struct nvlentry tentry;
965 char rxstr[AFS_RXINFO_LEN];
967 COUNT_REQ(VLSETLOCK);
968 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
970 if ((voltype != -1) && (InvalidVoltype(voltype)))
972 if (InvalidOperation(voloper))
974 if ((errorcode = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
977 VLog(1, ("SetLock Volume %u %s\n", volid, rxinfo(rxstr, rxcall)));
978 blockindex = FindByID(&ctx, volid, voltype, &tentry, &errorcode);
979 if (blockindex == NULLO) {
981 errorcode = VL_NOENT;
984 if (tentry.flags & VLDELETED) {
985 ABORT(VL_ENTDELETED);
987 timestamp = FT_ApproxTime();
989 /* Check if entry is already locked; note that we unlock any entry
990 * locked more than MAXLOCKTIME seconds */
991 if ((tentry.LockTimestamp)
992 && ((timestamp - tentry.LockTimestamp) < MAXLOCKTIME)) {
993 ABORT(VL_ENTRYLOCKED);
996 /* Consider it an unlocked entry: set current timestamp, caller
997 * and active vol operation */
998 tentry.LockTimestamp = timestamp;
999 tentry.LockAfsId = 0; /* Not implemented yet */
1000 if (tentry.flags & VLOP_RELEASE) {
1001 ABORT(VL_RERELEASE);
1003 tentry.flags &= ~VLOP_ALLOPERS; /* Clear any possible older operation bit */
1004 tentry.flags |= voloper;
1006 if (vlentrywrite(ctx.trans, blockindex, &tentry, sizeof(tentry))) {
1009 END(ubik_EndTrans(ctx.trans));
1013 ubik_AbortTrans(ctx.trans);
1016 osi_auditU(rxcall, VLSetLockEvent, errorcode, AUD_LONG, volid, AUD_END);
1021 /* Release an already locked vldb entry. Releasetype determines what
1022 * fields (afsid and/or volume operation) will be cleared along with
1023 * the lock time stamp. */
1026 SVL_ReleaseLock(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype,
1027 afs_int32 releasetype)
1029 afs_int32 blockindex, errorcode;
1031 struct nvlentry tentry;
1032 char rxstr[AFS_RXINFO_LEN];
1034 COUNT_REQ(VLRELEASELOCK);
1035 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
1037 if ((voltype != -1) && (InvalidVoltype(voltype)))
1039 if (releasetype && InvalidReleasetype(releasetype))
1040 END(VL_BADRELLOCKTYPE);
1041 if ((errorcode = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
1044 VLog(1, ("ReleaseLock Volume %u %s\n", volid, rxinfo(rxstr, rxcall)));
1045 blockindex = FindByID(&ctx, volid, voltype, &tentry, &errorcode);
1046 if (blockindex == NULLO) {
1048 errorcode = VL_NOENT;
1051 if (tentry.flags & VLDELETED) {
1052 ABORT(VL_ENTDELETED);
1055 ReleaseEntry(&tentry, releasetype); /* Unlock the appropriate fields */
1056 if (vlentrywrite(ctx.trans, blockindex, &tentry, sizeof(tentry))) {
1059 END(ubik_EndTrans(ctx.trans));
1063 ubik_AbortTrans(ctx.trans);
1066 osi_auditU(rxcall, VLReleaseLockEvent, errorcode, AUD_LONG, volid,
1072 /* ListEntry returns a single vldb entry, aentry, with offset previous_index;
1073 * the remaining parameters (i.e. next_index) are used so that sequential
1074 * calls to this routine will get the next (all) vldb entries.
1077 SVL_ListEntry(struct rx_call *rxcall, afs_int32 previous_index,
1078 afs_int32 *count, afs_int32 *next_index,
1079 struct vldbentry *aentry)
1083 struct nvlentry tentry;
1084 char rxstr[AFS_RXINFO_LEN];
1086 COUNT_REQ(VLLISTENTRY);
1087 if ((errorcode = Init_VLdbase(&ctx, LOCKREAD, this_op)))
1089 VLog(25, ("OListEntry index=%d %s\n", previous_index,
1090 rxinfo(rxstr, rxcall)));
1091 *next_index = NextEntry(&ctx, previous_index, &tentry, count);
1093 vlentry_to_vldbentry(&ctx, &tentry, aentry);
1094 return (ubik_EndTrans(ctx.trans));
1097 /* ListEntry returns a single vldb entry, aentry, with offset previous_index;
1098 * the remaining parameters (i.e. next_index) are used so that sequential
1099 * calls to this routine will get the next (all) vldb entries.
1102 SVL_ListEntryN(struct rx_call *rxcall, afs_int32 previous_index,
1103 afs_int32 *count, afs_int32 *next_index,
1104 struct nvldbentry *aentry)
1108 struct nvlentry tentry;
1109 char rxstr[AFS_RXINFO_LEN];
1111 COUNT_REQ(VLLISTENTRYN);
1112 if ((errorcode = Init_VLdbase(&ctx, LOCKREAD, this_op)))
1114 VLog(25, ("ListEntry index=%d %s\n", previous_index, rxinfo(rxstr, rxcall)));
1115 *next_index = NextEntry(&ctx, previous_index, &tentry, count);
1117 vlentry_to_nvldbentry(&ctx, &tentry, aentry);
1118 return (ubik_EndTrans(ctx.trans));
1122 /* Retrieves in vldbentries all vldb entries that match the specified
1123 * attributes (by server number, partition, volume type, and flag); if volume
1124 * id is specified then the associated list for that entry is returned.
1125 * CAUTION: This could be a very expensive call since in most cases
1126 * sequential search of all vldb entries is performed.
1129 SVL_ListAttributes(struct rx_call *rxcall,
1130 struct VldbListByAttributes *attributes,
1131 afs_int32 *nentries,
1132 bulkentries *vldbentries)
1134 int errorcode, allocCount = 0;
1136 struct nvlentry tentry;
1137 struct vldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1139 char rxstr[AFS_RXINFO_LEN];
1141 COUNT_REQ(VLLISTATTRIBUTES);
1142 vldbentries->bulkentries_val = 0;
1143 vldbentries->bulkentries_len = *nentries = 0;
1144 if ((errorcode = Init_VLdbase(&ctx, LOCKREAD, this_op)))
1146 allocCount = VLDBALLOCCOUNT;
1147 Vldbentry = VldbentryFirst = vldbentries->bulkentries_val =
1148 (vldbentry *) malloc(allocCount * sizeof(vldbentry));
1149 if (Vldbentry == NULL) {
1151 ubik_AbortTrans(ctx.trans);
1154 VldbentryLast = VldbentryFirst + allocCount;
1155 /* Handle the attribute by volume id totally separate of the rest
1156 * (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!) */
1157 if (attributes->Mask & VLLIST_VOLUMEID) {
1158 afs_int32 blockindex;
1161 FindByID(&ctx, attributes->volumeid, -1, &tentry, &errorcode);
1162 if (blockindex == 0) {
1164 errorcode = VL_NOENT;
1166 ubik_AbortTrans(ctx.trans);
1167 if (vldbentries->bulkentries_val)
1168 free((char *)vldbentries->bulkentries_val);
1169 vldbentries->bulkentries_val = 0;
1170 vldbentries->bulkentries_len = 0;
1174 put_attributeentry(&ctx, &Vldbentry, &VldbentryFirst, &VldbentryLast,
1175 vldbentries, &tentry, nentries, &allocCount))) {
1177 ubik_AbortTrans(ctx.trans);
1178 if (vldbentries->bulkentries_val)
1179 free((char *)vldbentries->bulkentries_val);
1180 vldbentries->bulkentries_val = 0;
1181 vldbentries->bulkentries_len = 0;
1182 return VL_SIZEEXCEEDED;
1185 afs_int32 nextblockindex = 0, count = 0, k = 0, match = 0;
1186 while ((nextblockindex =
1187 NextEntry(&ctx, nextblockindex, &tentry, &count))) {
1188 if (++pollcount > 50) {
1189 #ifndef AFS_PTHREAD_ENV
1195 if (attributes->Mask & VLLIST_SERVER) {
1198 IpAddrToRelAddr(&ctx, attributes->server, 0)) == -1)
1200 for (k = 0; k < OMAXNSERVERS; k++) {
1201 if (tentry.serverNumber[k] == BADSERVERID)
1203 if (tentry.serverNumber[k] == serverindex) {
1211 if (attributes->Mask & VLLIST_PARTITION) {
1213 if (tentry.serverPartition[k] != attributes->partition)
1216 for (k = 0; k < OMAXNSERVERS; k++) {
1217 if (tentry.serverNumber[k] == BADSERVERID)
1219 if (tentry.serverPartition[k] ==
1220 attributes->partition) {
1230 if (attributes->Mask & VLLIST_FLAG) {
1231 if (!(tentry.flags & attributes->flag))
1235 put_attributeentry(&ctx, &Vldbentry, &VldbentryFirst,
1236 &VldbentryLast, vldbentries, &tentry,
1237 nentries, &allocCount))) {
1239 ubik_AbortTrans(ctx.trans);
1240 if (vldbentries->bulkentries_val)
1241 free((char *)vldbentries->bulkentries_val);
1242 vldbentries->bulkentries_val = 0;
1243 vldbentries->bulkentries_len = 0;
1248 if (vldbentries->bulkentries_len
1249 && (allocCount > vldbentries->bulkentries_len)) {
1251 vldbentries->bulkentries_val =
1252 (vldbentry *) realloc(vldbentries->bulkentries_val,
1253 vldbentries->bulkentries_len *
1255 if (vldbentries->bulkentries_val == NULL) {
1257 ubik_AbortTrans(ctx.trans);
1262 ("ListAttrs nentries=%d %s\n", vldbentries->bulkentries_len,
1263 rxinfo(rxstr, rxcall)));
1264 return (ubik_EndTrans(ctx.trans));
1268 SVL_ListAttributesN(struct rx_call *rxcall,
1269 struct VldbListByAttributes *attributes,
1270 afs_int32 *nentries,
1271 nbulkentries *vldbentries)
1273 int errorcode, allocCount = 0;
1275 struct nvlentry tentry;
1276 struct nvldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1278 char rxstr[AFS_RXINFO_LEN];
1280 COUNT_REQ(VLLISTATTRIBUTESN);
1281 vldbentries->nbulkentries_val = 0;
1282 vldbentries->nbulkentries_len = *nentries = 0;
1283 if ((errorcode = Init_VLdbase(&ctx, LOCKREAD, this_op)))
1285 allocCount = VLDBALLOCCOUNT;
1286 Vldbentry = VldbentryFirst = vldbentries->nbulkentries_val =
1287 (nvldbentry *) malloc(allocCount * sizeof(nvldbentry));
1288 if (Vldbentry == NULL) {
1290 ubik_AbortTrans(ctx.trans);
1293 VldbentryLast = VldbentryFirst + allocCount;
1294 /* Handle the attribute by volume id totally separate of the rest
1295 * (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!) */
1296 if (attributes->Mask & VLLIST_VOLUMEID) {
1297 afs_int32 blockindex;
1300 FindByID(&ctx, attributes->volumeid, -1, &tentry, &errorcode);
1301 if (blockindex == 0) {
1303 errorcode = VL_NOENT;
1305 ubik_AbortTrans(ctx.trans);
1306 if (vldbentries->nbulkentries_val)
1307 free((char *)vldbentries->nbulkentries_val);
1308 vldbentries->nbulkentries_val = 0;
1309 vldbentries->nbulkentries_len = 0;
1313 put_nattributeentry(&ctx, &Vldbentry, &VldbentryFirst, &VldbentryLast,
1314 vldbentries, &tentry, 0, 0, nentries,
1317 ubik_AbortTrans(ctx.trans);
1318 if (vldbentries->nbulkentries_val)
1319 free((char *)vldbentries->nbulkentries_val);
1320 vldbentries->nbulkentries_val = 0;
1321 vldbentries->nbulkentries_len = 0;
1322 return VL_SIZEEXCEEDED;
1325 afs_int32 nextblockindex = 0, count = 0, k = 0, match = 0;
1326 while ((nextblockindex =
1327 NextEntry(&ctx, nextblockindex, &tentry, &count))) {
1328 if (++pollcount > 50) {
1329 #ifndef AFS_PTHREAD_ENV
1336 if (attributes->Mask & VLLIST_SERVER) {
1339 IpAddrToRelAddr(&ctx, attributes->server, 0)) == -1)
1341 for (k = 0; k < NMAXNSERVERS; k++) {
1342 if (tentry.serverNumber[k] == BADSERVERID)
1344 if (tentry.serverNumber[k] == serverindex) {
1352 if (attributes->Mask & VLLIST_PARTITION) {
1354 if (tentry.serverPartition[k] != attributes->partition)
1357 for (k = 0; k < NMAXNSERVERS; k++) {
1358 if (tentry.serverNumber[k] == BADSERVERID)
1360 if (tentry.serverPartition[k] ==
1361 attributes->partition) {
1371 if (attributes->Mask & VLLIST_FLAG) {
1372 if (!(tentry.flags & attributes->flag))
1376 put_nattributeentry(&ctx, &Vldbentry, &VldbentryFirst,
1377 &VldbentryLast, vldbentries, &tentry, 0,
1378 0, nentries, &allocCount))) {
1380 ubik_AbortTrans(ctx.trans);
1381 if (vldbentries->nbulkentries_val)
1382 free((char *)vldbentries->nbulkentries_val);
1383 vldbentries->nbulkentries_val = 0;
1384 vldbentries->nbulkentries_len = 0;
1389 if (vldbentries->nbulkentries_len
1390 && (allocCount > vldbentries->nbulkentries_len)) {
1392 vldbentries->nbulkentries_val =
1393 (nvldbentry *) realloc(vldbentries->nbulkentries_val,
1394 vldbentries->nbulkentries_len *
1395 sizeof(nvldbentry));
1396 if (vldbentries->nbulkentries_val == NULL) {
1398 ubik_AbortTrans(ctx.trans);
1403 ("NListAttrs nentries=%d %s\n", vldbentries->nbulkentries_len,
1404 rxinfo(rxstr, rxcall)));
1405 return (ubik_EndTrans(ctx.trans));
1410 SVL_ListAttributesN2(struct rx_call *rxcall,
1411 struct VldbListByAttributes *attributes,
1412 char *name, /* Wildcarded volume name */
1413 afs_int32 startindex,
1414 afs_int32 *nentries,
1415 nbulkentries *vldbentries,
1416 afs_int32 *nextstartindex)
1418 int errorcode = 0, maxCount = VLDBALLOCCOUNT;
1420 struct nvlentry tentry;
1421 struct nvldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1422 afs_int32 blockindex = 0, count = 0, k, match;
1423 afs_int32 matchindex = 0;
1424 int serverindex = -1; /* no server found */
1425 int findserver = 0, findpartition = 0, findflag = 0, findname = 0;
1427 int namematchRWBK, namematchRO, thismatch;
1429 char volumename[VL_MAXNAMELEN+2]; /* regex anchors */
1430 char rxstr[AFS_RXINFO_LEN];
1431 #ifdef HAVE_POSIX_REGEX
1433 int need_regfree = 0;
1438 COUNT_REQ(VLLISTATTRIBUTESN2);
1439 vldbentries->nbulkentries_val = 0;
1440 vldbentries->nbulkentries_len = 0;
1442 *nextstartindex = -1;
1444 errorcode = Init_VLdbase(&ctx, LOCKREAD, this_op);
1448 Vldbentry = VldbentryFirst = vldbentries->nbulkentries_val =
1449 (nvldbentry *) malloc(maxCount * sizeof(nvldbentry));
1450 if (Vldbentry == NULL) {
1452 ubik_AbortTrans(ctx.trans);
1456 VldbentryLast = VldbentryFirst + maxCount;
1458 /* Handle the attribute by volume id totally separate of the rest
1459 * (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!)
1461 if (attributes->Mask & VLLIST_VOLUMEID) {
1463 FindByID(&ctx, attributes->volumeid, -1, &tentry, &errorcode);
1464 if (blockindex == 0) {
1466 errorcode = VL_NOENT;
1469 put_nattributeentry(&ctx, &Vldbentry, &VldbentryFirst,
1470 &VldbentryLast, vldbentries, &tentry, 0,
1471 0, nentries, &maxCount);
1477 /* Search each entry in the database and return all entries
1478 * that match the request. It checks volumename (with
1479 * wildcarding), entry flags, server, and partition.
1482 /* Get the server index for matching server address */
1483 if (attributes->Mask & VLLIST_SERVER) {
1485 IpAddrToRelAddr(&ctx, attributes->server, 0);
1486 if (serverindex == -1)
1490 findpartition = ((attributes->Mask & VLLIST_PARTITION) ? 1 : 0);
1491 findflag = ((attributes->Mask & VLLIST_FLAG) ? 1 : 0);
1492 if (name && (strcmp(name, ".*") != 0) && (strcmp(name, "") != 0)) {
1493 sprintf(volumename, "^%s$", name);
1494 #ifdef HAVE_POSIX_REGEX
1495 if (regcomp(&re, volumename, REG_NOSUB) != 0) {
1496 errorcode = VL_BADNAME;
1501 t = (char *)re_comp(volumename);
1503 errorcode = VL_BADNAME;
1510 /* Read each entry and see if it is the one we want */
1511 blockindex = startindex;
1512 while ((blockindex = NextEntry(&ctx, blockindex, &tentry, &count))) {
1513 if (++pollcount > 50) {
1514 #ifndef AFS_PTHREAD_ENV
1520 /* Step through each server index searching for a match.
1521 * Match to an existing RW, BK, or RO volume name (preference
1522 * is in this order). Remember which index we matched against.
1524 namematchRWBK = namematchRO = 0; /* 0->notTried; 1->match; 2->noMatch */
1528 && (tentry.serverNumber[k] != BADSERVERID)); k++) {
1529 thismatch = 0; /* does this index match */
1531 /* Match against the RW or BK volume name. Remember
1532 * results in namematchRWBK. Prefer RW over BK.
1534 if (tentry.serverFlags[k] & VLSF_RWVOL) {
1535 /* Does the name match the RW name */
1536 if (tentry.flags & VLF_RWEXISTS) {
1538 sprintf(volumename, "%s", tentry.name);
1539 #ifdef HAVE_POSIX_REGEX
1540 if (regexec(&re, volumename, 0, NULL, 0) == 0) {
1541 thismatch = VLSF_RWVOL;
1544 if (re_exec(volumename)) {
1545 thismatch = VLSF_RWVOL;
1549 thismatch = VLSF_RWVOL;
1553 /* Does the name match the BK name */
1554 if (!thismatch && (tentry.flags & VLF_BACKEXISTS)) {
1556 sprintf(volumename, "%s.backup", tentry.name);
1557 #ifdef HAVE_POSIX_REGEX
1558 if (regexec(&re, volumename, 0, NULL, 0) == 0) {
1559 thismatch = VLSF_BACKVOL;
1562 if (re_exec(volumename)) {
1563 thismatch = VLSF_BACKVOL;
1567 thismatch = VLSF_BACKVOL;
1571 namematchRWBK = (thismatch ? 1 : 2);
1574 /* Match with the RO volume name. Compare once and
1575 * remember results in namematchRO. Note that this will
1576 * pick up entries marked NEWREPSITEs and DONTUSE.
1579 if (tentry.flags & VLF_ROEXISTS) {
1583 ((namematchRO == 1) ? VLSF_ROVOL : 0);
1585 sprintf(volumename, "%s.readonly",
1587 #ifdef HAVE_POSIX_REGEX
1588 if (regexec(&re, volumename, 0, NULL, 0) == 0) {
1589 thismatch = VLSF_ROVOL;
1592 if (re_exec(volumename))
1593 thismatch = VLSF_ROVOL;
1597 thismatch = VLSF_ROVOL;
1600 namematchRO = (thismatch ? 1 : 2);
1603 /* Is there a server match */
1604 if (thismatch && findserver
1605 && (tentry.serverNumber[k] != serverindex))
1608 /* Is there a partition match */
1609 if (thismatch && findpartition
1610 && (tentry.serverPartition[k] != attributes->partition))
1613 /* Is there a flag match */
1614 if (thismatch && findflag
1615 && !(tentry.flags & attributes->flag))
1618 /* We found a match. Remember the index, and type */
1622 matchtype = thismatch;
1625 /* Since we prefer RW and BK volume matches over RO matches,
1626 * if we have already checked the RWBK name, then we already
1627 * found the best match and so end the search.
1629 * If we tried matching against the RW, BK, and RO volume names
1630 * and both failed, then we end the search (none will match).
1632 if ((match && namematchRWBK)
1633 || ((namematchRWBK == 2) && (namematchRO == 2)))
1637 /* Passed all the tests. Take it */
1640 put_nattributeentry(&ctx, &Vldbentry, &VldbentryFirst,
1641 &VldbentryLast, vldbentries, &tentry,
1642 matchtype, matchindex, nentries,
1647 if (*nentries >= maxCount)
1648 break; /* collected the max */
1651 *nextstartindex = (blockindex ? blockindex : -1);
1655 #ifdef HAVE_POSIX_REGEX
1662 ubik_AbortTrans(ctx.trans);
1663 if (vldbentries->nbulkentries_val)
1664 free((char *)vldbentries->nbulkentries_val);
1665 vldbentries->nbulkentries_val = 0;
1666 vldbentries->nbulkentries_len = 0;
1667 *nextstartindex = -1;
1671 ("N2ListAttrs nentries=%d %s\n", vldbentries->nbulkentries_len,
1672 rxinfo(rxstr, rxcall)));
1673 return (ubik_EndTrans(ctx.trans));
1678 /* Retrieves in vldbentries all vldb entries that match the specified
1679 * attributes (by server number, partition, volume type, and flag); if
1680 * volume id is specified then the associated list for that entry is
1681 * returned. CAUTION: This could be a very expensive call since in most
1682 * cases sequential search of all vldb entries is performed.
1685 SVL_LinkedList(struct rx_call *rxcall,
1686 struct VldbListByAttributes *attributes,
1687 afs_int32 *nentries,
1688 vldb_list *vldbentries)
1692 struct nvlentry tentry;
1693 vldblist vllist, *vllistptr;
1694 afs_int32 blockindex, count, match;
1699 COUNT_REQ(VLLINKEDLIST);
1700 if ((errorcode = Init_VLdbase(&ctx, LOCKREAD, this_op)))
1704 vldbentries->node = NULL;
1705 vllistptr = &vldbentries->node;
1707 /* List by volumeid */
1708 if (attributes->Mask & VLLIST_VOLUMEID) {
1710 FindByID(&ctx, attributes->volumeid, -1, &tentry, &errorcode);
1713 ubik_AbortTrans(ctx.trans);
1714 return (errorcode ? errorcode : VL_NOENT);
1717 vllist = (single_vldbentry *) malloc(sizeof(single_vldbentry));
1718 if (vllist == NULL) {
1720 ubik_AbortTrans(ctx.trans);
1723 vlentry_to_vldbentry(&ctx, &tentry, &vllist->VldbEntry);
1724 vllist->next_vldb = NULL;
1726 *vllistptr = vllist; /* Thread onto list */
1727 vllistptr = &vllist->next_vldb;
1731 /* Search by server, partition, and flags */
1733 for (blockindex = NextEntry(&ctx, 0, &tentry, &count); blockindex;
1734 blockindex = NextEntry(&ctx, blockindex, &tentry, &count)) {
1737 if (++pollcount > 50) {
1738 #ifndef AFS_PTHREAD_ENV
1744 /* Does this volume exist on the desired server */
1745 if (attributes->Mask & VLLIST_SERVER) {
1747 IpAddrToRelAddr(&ctx, attributes->server, 0);
1748 if (serverindex == -1)
1750 for (k = 0; k < OMAXNSERVERS; k++) {
1751 if (tentry.serverNumber[k] == BADSERVERID)
1753 if (tentry.serverNumber[k] == serverindex) {
1762 /* Does this volume exist on the desired partition */
1763 if (attributes->Mask & VLLIST_PARTITION) {
1765 if (tentry.serverPartition[k] != attributes->partition)
1768 for (k = 0; k < OMAXNSERVERS; k++) {
1769 if (tentry.serverNumber[k] == BADSERVERID)
1771 if (tentry.serverPartition[k] ==
1772 attributes->partition) {
1782 /* Does this volume have the desired flags */
1783 if (attributes->Mask & VLLIST_FLAG) {
1784 if (!(tentry.flags & attributes->flag))
1788 vllist = (single_vldbentry *) malloc(sizeof(single_vldbentry));
1789 if (vllist == NULL) {
1791 ubik_AbortTrans(ctx.trans);
1794 vlentry_to_vldbentry(&ctx, &tentry, &vllist->VldbEntry);
1795 vllist->next_vldb = NULL;
1797 *vllistptr = vllist; /* Thread onto list */
1798 vllistptr = &vllist->next_vldb;
1800 if (smallMem && (*nentries >= VLDBALLOCCOUNT)) {
1802 ubik_AbortTrans(ctx.trans);
1803 return VL_SIZEEXCEEDED;
1808 return (ubik_EndTrans(ctx.trans));
1812 SVL_LinkedListN(struct rx_call *rxcall,
1813 struct VldbListByAttributes *attributes,
1814 afs_int32 *nentries,
1815 nvldb_list *vldbentries)
1819 struct nvlentry tentry;
1820 nvldblist vllist, *vllistptr;
1821 afs_int32 blockindex, count, match;
1826 COUNT_REQ(VLLINKEDLISTN);
1827 if ((errorcode = Init_VLdbase(&ctx, LOCKREAD, this_op)))
1831 vldbentries->node = NULL;
1832 vllistptr = &vldbentries->node;
1834 /* List by volumeid */
1835 if (attributes->Mask & VLLIST_VOLUMEID) {
1837 FindByID(&ctx, attributes->volumeid, -1, &tentry, &errorcode);
1840 ubik_AbortTrans(ctx.trans);
1841 return (errorcode ? errorcode : VL_NOENT);
1844 vllist = (single_nvldbentry *) malloc(sizeof(single_nvldbentry));
1845 if (vllist == NULL) {
1847 ubik_AbortTrans(ctx.trans);
1850 vlentry_to_nvldbentry(&ctx, &tentry, &vllist->VldbEntry);
1851 vllist->next_vldb = NULL;
1853 *vllistptr = vllist; /* Thread onto list */
1854 vllistptr = &vllist->next_vldb;
1858 /* Search by server, partition, and flags */
1860 for (blockindex = NextEntry(&ctx, 0, &tentry, &count); blockindex;
1861 blockindex = NextEntry(&ctx, blockindex, &tentry, &count)) {
1864 if (++pollcount > 50) {
1865 #ifndef AFS_PTHREAD_ENV
1871 /* Does this volume exist on the desired server */
1872 if (attributes->Mask & VLLIST_SERVER) {
1874 IpAddrToRelAddr(&ctx, attributes->server, 0);
1875 if (serverindex == -1)
1877 for (k = 0; k < NMAXNSERVERS; k++) {
1878 if (tentry.serverNumber[k] == BADSERVERID)
1880 if (tentry.serverNumber[k] == serverindex) {
1889 /* Does this volume exist on the desired partition */
1890 if (attributes->Mask & VLLIST_PARTITION) {
1892 if (tentry.serverPartition[k] != attributes->partition)
1895 for (k = 0; k < NMAXNSERVERS; k++) {
1896 if (tentry.serverNumber[k] == BADSERVERID)
1898 if (tentry.serverPartition[k] ==
1899 attributes->partition) {
1909 /* Does this volume have the desired flags */
1910 if (attributes->Mask & VLLIST_FLAG) {
1911 if (!(tentry.flags & attributes->flag))
1915 vllist = (single_nvldbentry *) malloc(sizeof(single_nvldbentry));
1916 if (vllist == NULL) {
1918 ubik_AbortTrans(ctx.trans);
1921 vlentry_to_nvldbentry(&ctx, &tentry, &vllist->VldbEntry);
1922 vllist->next_vldb = NULL;
1924 *vllistptr = vllist; /* Thread onto list */
1925 vllistptr = &vllist->next_vldb;
1927 if (smallMem && (*nentries >= VLDBALLOCCOUNT)) {
1929 ubik_AbortTrans(ctx.trans);
1930 return VL_SIZEEXCEEDED;
1935 return (ubik_EndTrans(ctx.trans));
1938 /* Get back vldb header statistics (allocs, frees, maxvolumeid,
1939 * totalentries, etc) and dynamic statistics (number of requests and/or
1940 * aborts per remote procedure call, etc)
1943 SVL_GetStats(struct rx_call *rxcall,
1945 vital_vlheader *vital_header)
1947 afs_int32 errorcode;
1949 char rxstr[AFS_RXINFO_LEN];
1951 COUNT_REQ(VLGETSTATS);
1953 /* Allow users to get statistics freely */
1954 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) /* Must be in 'UserList' to use */
1957 if ((errorcode = Init_VLdbase(&ctx, LOCKREAD, this_op)))
1959 VLog(5, ("GetStats %s\n", rxinfo(rxstr, rxcall)));
1960 memcpy((char *)vital_header, (char *)&ctx.cheader->vital_header,
1961 sizeof(vital_vlheader));
1962 memcpy((char *)stats, (char *)&dynamic_statistics, sizeof(vldstats));
1963 return (ubik_EndTrans(ctx.trans));
1966 /* Get the list of file server addresses from the VLDB. Currently it's pretty
1967 * easy to do. In the future, it might require a little bit of grunging
1968 * through the VLDB, but that's life.
1971 SVL_GetAddrs(struct rx_call *rxcall,
1974 struct VLCallBack *spare3,
1975 afs_int32 *nentries,
1978 afs_int32 errorcode;
1983 COUNT_REQ(VLGETADDRS);
1984 addrsp->bulkaddrs_len = *nentries = 0;
1985 addrsp->bulkaddrs_val = 0;
1986 memset(spare3, 0, sizeof(struct VLCallBack));
1988 if ((errorcode = Init_VLdbase(&ctx, LOCKREAD, this_op)))
1991 VLog(5, ("GetAddrs\n"));
1992 addrsp->bulkaddrs_val = taddrp =
1993 (afs_uint32 *) malloc(sizeof(afs_int32) * (MAXSERVERID + 1));
1994 nservers = *nentries = addrsp->bulkaddrs_len = 0;
1998 ubik_AbortTrans(ctx.trans);
2002 for (i = 0; i <= MAXSERVERID; i++) {
2003 if ((*taddrp = ntohl(ctx.cheader->IpMappedAddr[i]))) {
2009 addrsp->bulkaddrs_len = *nentries = nservers;
2010 return (ubik_EndTrans(ctx.trans));
2013 #define PADDR(addr) VLog(0,("%d.%d.%d.%d", (addr>>24)&0xff, (addr>>16)&0xff, (addr>>8) &0xff, addr&0xff));
2016 SVL_RegisterAddrs(struct rx_call *rxcall, afsUUID *uuidp, afs_int32 spare1,
2021 int cnt, h, i, j, k, m, base, index;
2022 struct extentaddr *exp = 0, *tex;
2024 afs_uint32 addrs[VL_MAXIPADDRS_PERMH];
2026 int count, willChangeEntry, foundUuidEntry, willReplaceCnt;
2027 int WillReplaceEntry, WillChange[MAXSERVERID + 1];
2029 int ReplaceEntry = 0;
2032 COUNT_REQ(VLREGADDR);
2033 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
2035 if ((code = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
2038 /* Eliminate duplicates from IP address list */
2039 for (k = 0, cnt = 0; k < addrsp->bulkaddrs_len; k++) {
2040 if (addrsp->bulkaddrs_val[k] == 0)
2042 for (m = 0; m < cnt; m++) {
2043 if (addrs[m] == addrsp->bulkaddrs_val[k])
2047 if (m == VL_MAXIPADDRS_PERMH) {
2049 ("Number of addresses exceeds %d. Cannot register IP addr 0x%x in VLDB\n",
2050 VL_MAXIPADDRS_PERMH, addrsp->bulkaddrs_val[k]));
2052 addrs[m] = addrsp->bulkaddrs_val[k];
2058 ubik_AbortTrans(ctx.trans);
2059 return VL_INDEXERANGE;
2065 /* For each server registered within the VLDB */
2066 for (srvidx = 0; srvidx <= MAXSERVERID; srvidx++) {
2067 willChangeEntry = 0;
2068 WillReplaceEntry = 1;
2069 if ((ctx.hostaddress[srvidx] & 0xff000000) == 0xff000000) {
2070 /* The server is registered as a multihomed */
2071 base = (ctx.hostaddress[srvidx] >> 16) & 0xff;
2072 index = ctx.hostaddress[srvidx] & 0x0000ffff;
2073 if (base >= VL_MAX_ADDREXTBLKS) {
2075 ("Internal error: Multihome extent base is too large. Base %d index %d\n",
2079 if (index >= VL_MHSRV_PERBLK) {
2081 ("Internal error: Multihome extent index is too large. Base %d index %d\n",
2085 if (!ctx.ex_addr[base]) {
2087 ("Internal error: Multihome extent does not exist. Base %d\n",
2092 /* See if the addresses to register will change this server entry */
2093 exp = &ctx.ex_addr[base][index];
2094 tuuid = exp->ex_hostuuid;
2095 afs_ntohuuid(&tuuid);
2096 if (afs_uuid_equal(uuidp, &tuuid)) {
2100 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2101 if (!exp->ex_addrs[mhidx])
2103 for (k = 0; k < cnt; k++) {
2104 if (ntohl(exp->ex_addrs[mhidx]) == addrs[k]) {
2105 willChangeEntry = 1;
2106 WillChange[count] = srvidx;
2111 WillReplaceEntry = 0;
2115 /* The server is not registered as a multihomed.
2116 * See if the addresses to register will replace this server entry.
2118 for (k = 0; k < cnt; k++) {
2119 if (ctx.hostaddress[srvidx] == addrs[k]) {
2120 willChangeEntry = 1;
2121 WillChange[count] = srvidx;
2122 WillReplaceEntry = 1;
2127 if (willChangeEntry) {
2128 if (WillReplaceEntry) {
2130 ReplaceEntry = srvidx;
2136 /* If we found the uuid in the VLDB and if we are replacing another
2137 * entire entry, then complain and fail. Also, if we did not find
2138 * the uuid in the VLDB and the IP addresses being registered was
2139 * found in more than one other entry, then we don't know which one
2140 * to replace and will complain and fail.
2142 if ((foundUuidEntry && (willReplaceCnt > 0))
2143 || (!foundUuidEntry && (count > 1))) {
2145 ("The following fileserver is being registered in the VLDB:\n"));
2147 for (k = 0; k < cnt; k++) {
2154 if (foundUuidEntry) {
2156 (" It would have replaced the existing VLDB server entry:\n"));
2157 VLog(0, (" entry %d: [", FoundUuid));
2158 base = (ctx.hostaddress[FoundUuid] >> 16) & 0xff;
2159 index = ctx.hostaddress[FoundUuid] & 0x0000ffff;
2160 exp = &ctx.ex_addr[base][index];
2161 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2162 if (!exp->ex_addrs[mhidx])
2166 PADDR(ntohl(exp->ex_addrs[mhidx]));
2172 VLog(0, (" Yet another VLDB server entry exists:\n"));
2174 VLog(0, (" Yet other VLDB server entries exist:\n"));
2175 for (j = 0; j < count; j++) {
2176 srvidx = WillChange[j];
2177 VLog(0, (" entry %d: ", srvidx));
2178 if ((ctx.hostaddress[srvidx] & 0xff000000) == 0xff000000) {
2180 base = (ctx.hostaddress[srvidx] >> 16) & 0xff;
2181 index = ctx.hostaddress[srvidx] & 0x0000ffff;
2182 exp = &ctx.ex_addr[base][index];
2183 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2184 if (!exp->ex_addrs[mhidx])
2188 PADDR(ntohl(exp->ex_addrs[mhidx]));
2192 PADDR(ctx.hostaddress[srvidx]);
2198 VLog(0, (" You must 'vos changeaddr' this other server entry\n"));
2201 (" You must 'vos changeaddr' these other server entries\n"));
2204 (" and/or remove the sysid file from the registering fileserver\n"));
2205 VLog(0, (" before the fileserver can be registered in the VLDB.\n"));
2207 ubik_AbortTrans(ctx.trans);
2208 return VL_MULTIPADDR;
2211 /* Passed the checks. Now find and update the existing mh entry, or create
2214 if (foundUuidEntry) {
2215 /* Found the entry with same uuid. See if we need to change it */
2218 fbase = (ctx.hostaddress[FoundUuid] >> 16) & 0xff;
2219 index = ctx.hostaddress[FoundUuid] & 0x0000ffff;
2220 exp = &ctx.ex_addr[fbase][index];
2222 /* Determine if the entry has changed */
2223 for (k = 0; ((k < cnt) && !change); k++) {
2224 if (ntohl(exp->ex_addrs[k]) != addrs[k])
2227 for (; ((k < VL_MAXIPADDRS_PERMH) && !change); k++) {
2228 if (exp->ex_addrs[k] != 0)
2232 return (ubik_EndTrans(ctx.trans));
2236 VLog(0, ("The following fileserver is being registered in the VLDB:\n"));
2238 for (k = 0; k < cnt; k++) {
2245 if (foundUuidEntry) {
2247 (" It will replace the following existing entry in the VLDB (same uuid):\n"));
2248 VLog(0, (" entry %d: [", FoundUuid));
2249 for (k = 0; k < VL_MAXIPADDRS_PERMH; k++) {
2250 if (exp->ex_addrs[k] == 0)
2254 PADDR(ntohl(exp->ex_addrs[k]));
2257 } else if (willReplaceCnt || (count == 1)) {
2258 /* If we are not replacing an entry and there is only one entry to change,
2259 * then we will replace that entry.
2261 if (!willReplaceCnt) {
2262 ReplaceEntry = WillChange[0];
2266 /* Have an entry that needs to be replaced */
2267 if ((ctx.hostaddress[ReplaceEntry] & 0xff000000) == 0xff000000) {
2268 fbase = (ctx.hostaddress[ReplaceEntry] >> 16) & 0xff;
2269 index = ctx.hostaddress[ReplaceEntry] & 0x0000ffff;
2270 exp = &ctx.ex_addr[fbase][index];
2273 (" It will replace the following existing entry in the VLDB (new uuid):\n"));
2274 VLog(0, (" entry %d: [", ReplaceEntry));
2275 for (k = 0; k < VL_MAXIPADDRS_PERMH; k++) {
2276 if (exp->ex_addrs[k] == 0)
2280 PADDR(ntohl(exp->ex_addrs[k]));
2284 /* Not a mh entry. So we have to create a new mh entry and
2285 * put it on the ReplaceEntry slot of the ctx.hostaddress array.
2287 VLog(0, (" It will replace existing entry %d, ", ReplaceEntry));
2288 PADDR(ctx.hostaddress[ReplaceEntry]);
2289 VLog(0,(", in the VLDB (new uuid):\n"));
2292 FindExtentBlock(&ctx, uuidp, 1, ReplaceEntry, &exp, &fbase);
2294 ubik_AbortTrans(ctx.trans);
2295 return (code ? code : VL_IO);
2299 /* There is no entry for this server, must create a new mh entry as
2300 * well as use a new slot of the ctx.hostaddress array.
2302 VLog(0, (" It will create a new entry in the VLDB.\n"));
2303 code = FindExtentBlock(&ctx, uuidp, 1, -1, &exp, &fbase);
2305 ubik_AbortTrans(ctx.trans);
2306 return (code ? code : VL_IO);
2310 /* Now we have a mh entry to fill in. Update the uuid, bump the
2311 * uniquifier, and fill in its IP addresses.
2314 afs_htonuuid(&tuuid);
2315 exp->ex_hostuuid = tuuid;
2316 exp->ex_uniquifier = htonl(ntohl(exp->ex_uniquifier) + 1);
2317 for (k = 0; k < cnt; k++) {
2318 exp->ex_addrs[k] = htonl(addrs[k]);
2320 for (; k < VL_MAXIPADDRS_PERMH; k++) {
2321 exp->ex_addrs[k] = 0;
2324 /* Write the new mh entry out */
2327 DOFFSET(ntohl(ctx.ex_addr[0]->ex_contaddrs[fbase]),
2328 (char *)ctx.ex_addr[fbase], (char *)exp), (char *)exp,
2330 ubik_AbortTrans(ctx.trans);
2334 /* Remove any common addresses from other mh entres. We know these entries
2335 * are being changed and not replaced so they are mh entries.
2338 for (i = 0; i < count; i++) {
2341 /* Skip the entry we replaced */
2342 if (willReplaceCnt && (WillChange[i] == ReplaceEntry))
2345 base = (ctx.hostaddress[WillChange[i]] >> 16) & 0xff;
2346 index = ctx.hostaddress[WillChange[i]] & 0x0000ffff;
2347 tex = &ctx.ex_addr[fbase][index];
2351 (" The following existing entries in the VLDB will be updated:\n"));
2353 VLog(0, (" entry %d: [", WillChange[i]));
2354 for (h = j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2355 if (tex->ex_addrs[j]) {
2358 PADDR(ntohl(tex->ex_addrs[j]));
2361 for (k = 0; k < cnt; k++) {
2362 if (ntohl(tex->ex_addrs[j]) == addrs[k])
2366 /* Not found, so we keep it */
2367 tex->ex_addrs[h] = tex->ex_addrs[j];
2371 for (j = h; j < VL_MAXIPADDRS_PERMH; j++) {
2372 tex->ex_addrs[j] = 0; /* zero rest of mh entry */
2376 /* Write out the modified mh entry */
2377 tex->ex_uniquifier = htonl(ntohl(tex->ex_uniquifier) + 1);
2379 DOFFSET(ntohl(ctx.ex_addr[0]->ex_contaddrs[base]),
2380 (char *)ctx.ex_addr[base], (char *)tex);
2381 if (vlwrite(ctx.trans, doff, (char *)tex, sizeof(*tex))) {
2382 ubik_AbortTrans(ctx.trans);
2387 return (ubik_EndTrans(ctx.trans));
2391 SVL_GetAddrsU(struct rx_call *rxcall,
2392 struct ListAddrByAttributes *attributes,
2394 afs_int32 *uniquifier,
2395 afs_int32 *nentries,
2398 afs_int32 errorcode, index = -1, offset;
2400 int nservers, i, j, base = 0;
2401 struct extentaddr *exp = 0;
2403 afs_uint32 *taddrp, taddr;
2404 char rxstr[AFS_RXINFO_LEN];
2406 COUNT_REQ(VLGETADDRSU);
2407 addrsp->bulkaddrs_len = *nentries = 0;
2408 addrsp->bulkaddrs_val = 0;
2409 VLog(5, ("GetAddrsU %s\n", rxinfo(rxstr, rxcall)));
2410 if ((errorcode = Init_VLdbase(&ctx, LOCKREAD, this_op)))
2413 if (attributes->Mask & VLADDR_IPADDR) {
2414 if (attributes->Mask & (VLADDR_INDEX | VLADDR_UUID)) {
2415 ubik_AbortTrans(ctx.trans);
2418 for (base = 0; base < VL_MAX_ADDREXTBLKS; base++) {
2419 if (!ctx.ex_addr[base])
2421 for (i = 1; i < VL_MHSRV_PERBLK; i++) {
2422 exp = &ctx.ex_addr[base][i];
2423 tuuid = exp->ex_hostuuid;
2424 afs_ntohuuid(&tuuid);
2425 if (afs_uuid_is_nil(&tuuid))
2427 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2428 if (exp->ex_addrs[j]
2429 && (ntohl(exp->ex_addrs[j]) == attributes->ipaddr)) {
2433 if (j < VL_MAXIPADDRS_PERMH)
2436 if (i < VL_MHSRV_PERBLK)
2439 if (base >= VL_MAX_ADDREXTBLKS) {
2440 ubik_AbortTrans(ctx.trans);
2443 } else if (attributes->Mask & VLADDR_INDEX) {
2444 if (attributes->Mask & (VLADDR_IPADDR | VLADDR_UUID)) {
2445 ubik_AbortTrans(ctx.trans);
2448 index = attributes->index;
2449 if (index < 1 || index >= (VL_MAX_ADDREXTBLKS * VL_MHSRV_PERBLK)) {
2450 ubik_AbortTrans(ctx.trans);
2451 return VL_INDEXERANGE;
2453 base = index / VL_MHSRV_PERBLK;
2454 offset = index % VL_MHSRV_PERBLK;
2456 ubik_AbortTrans(ctx.trans);
2459 if (!ctx.ex_addr[base]) {
2460 ubik_AbortTrans(ctx.trans);
2461 return VL_INDEXERANGE;
2463 exp = &ctx.ex_addr[base][offset];
2464 } else if (attributes->Mask & VLADDR_UUID) {
2465 if (attributes->Mask & (VLADDR_IPADDR | VLADDR_INDEX)) {
2466 ubik_AbortTrans(ctx.trans);
2469 if (!ctx.ex_addr[0]) { /* mh servers probably aren't setup on this vldb */
2470 ubik_AbortTrans(ctx.trans);
2474 FindExtentBlock(&ctx, &attributes->uuid, 0, -1, &exp, &base))) {
2475 ubik_AbortTrans(ctx.trans);
2479 ubik_AbortTrans(ctx.trans);
2484 ubik_AbortTrans(ctx.trans);
2487 addrsp->bulkaddrs_val = taddrp =
2488 (afs_uint32 *) malloc(sizeof(afs_int32) * (MAXSERVERID + 1));
2489 nservers = *nentries = addrsp->bulkaddrs_len = 0;
2492 ubik_AbortTrans(ctx.trans);
2495 tuuid = exp->ex_hostuuid;
2496 afs_ntohuuid(&tuuid);
2497 if (afs_uuid_is_nil(&tuuid)) {
2498 ubik_AbortTrans(ctx.trans);
2504 *uniquifier = ntohl(exp->ex_uniquifier);
2505 for (i = 0; i < VL_MAXIPADDRS_PERMH; i++) {
2506 if (exp->ex_addrs[i]) {
2507 taddr = ntohl(exp->ex_addrs[i]);
2508 /* Weed out duplicates */
2509 for (j = 0; j < nservers; j++) {
2510 if (taddrp[j] == taddr)
2513 if ((j == nservers) && (j <= MAXSERVERID)) {
2514 taddrp[nservers] = taddr;
2519 addrsp->bulkaddrs_len = *nentries = nservers;
2520 return (ubik_EndTrans(ctx.trans));
2523 /* ============> End of Exported vldb RPC functions <============= */
2526 /* Routine that copies the given vldb entry to the output buffer, vldbentries. */
2528 put_attributeentry(struct vl_ctx *ctx,
2529 struct vldbentry **Vldbentry,
2530 struct vldbentry **VldbentryFirst,
2531 struct vldbentry **VldbentryLast,
2532 bulkentries *vldbentries,
2533 struct nvlentry *entry,
2534 afs_int32 *nentries,
2535 afs_int32 *alloccnt)
2540 if (*Vldbentry == *VldbentryLast) {
2542 return VL_SIZEEXCEEDED; /* no growing if smallMem defined */
2544 /* Allocate another set of memory; each time allocate twice as
2545 * many blocks as the last time. When we reach VLDBALLOCLIMIT,
2546 * then grow in increments of VLDBALLOCINCR.
2548 allo = (*alloccnt > VLDBALLOCLIMIT) ? VLDBALLOCINCR : *alloccnt;
2550 (vldbentry *) realloc(*VldbentryFirst,
2551 (*alloccnt + allo) * sizeof(vldbentry));
2555 *VldbentryFirst = vldbentries->bulkentries_val = reall;
2556 *Vldbentry = *VldbentryFirst + *alloccnt;
2557 *VldbentryLast = *Vldbentry + allo;
2560 vlentry_to_vldbentry(ctx, entry, *Vldbentry);
2563 vldbentries->bulkentries_len++;
2568 put_nattributeentry(struct vl_ctx *ctx,
2569 struct nvldbentry **Vldbentry,
2570 struct nvldbentry **VldbentryFirst,
2571 struct nvldbentry **VldbentryLast,
2572 nbulkentries *vldbentries,
2573 struct nvlentry *entry,
2574 afs_int32 matchtype,
2575 afs_int32 matchindex,
2576 afs_int32 *nentries,
2577 afs_int32 *alloccnt)
2582 if (*Vldbentry == *VldbentryLast) {
2584 return VL_SIZEEXCEEDED; /* no growing if smallMem defined */
2586 /* Allocate another set of memory; each time allocate twice as
2587 * many blocks as the last time. When we reach VLDBALLOCLIMIT,
2588 * then grow in increments of VLDBALLOCINCR.
2590 allo = (*alloccnt > VLDBALLOCLIMIT) ? VLDBALLOCINCR : *alloccnt;
2592 (nvldbentry *) realloc(*VldbentryFirst,
2593 (*alloccnt + allo) * sizeof(nvldbentry));
2597 *VldbentryFirst = vldbentries->nbulkentries_val = reall;
2598 *Vldbentry = *VldbentryFirst + *alloccnt;
2599 *VldbentryLast = *Vldbentry + allo;
2602 vlentry_to_nvldbentry(ctx, entry, *Vldbentry);
2603 (*Vldbentry)->matchindex = (matchtype << 16) + matchindex;
2606 vldbentries->nbulkentries_len++;
2611 /* Common code to actually remove a vldb entry from the database. */
2613 RemoveEntry(struct vl_ctx *ctx, afs_int32 entryptr,
2614 struct nvlentry *tentry)
2618 if ((errorcode = UnthreadVLentry(ctx, entryptr, tentry)))
2620 if ((errorcode = FreeBlock(ctx, entryptr)))
2626 ReleaseEntry(struct nvlentry *tentry, afs_int32 releasetype)
2628 if (releasetype & LOCKREL_TIMESTAMP)
2629 tentry->LockTimestamp = 0;
2630 if (releasetype & LOCKREL_OPCODE)
2631 tentry->flags &= ~VLOP_ALLOPERS;
2632 if (releasetype & LOCKREL_AFSID)
2633 tentry->LockAfsId = 0;
2637 /* Verify that the incoming vldb entry is valid; multi type of error codes
2640 check_vldbentry(struct vldbentry *aentry)
2644 if (InvalidVolname(aentry->name))
2646 if (aentry->nServers <= 0 || aentry->nServers > OMAXNSERVERS)
2647 return VL_BADSERVER;
2648 for (i = 0; i < aentry->nServers; i++) {
2649 /* if (aentry->serverNumber[i] < 0 || aentry->serverNumber[i] > MAXSERVERID)
2650 return VL_BADSERVER; */
2651 if (aentry->serverPartition[i] < 0
2652 || aentry->serverPartition[i] > MAXPARTITIONID)
2653 return VL_BADPARTITION;
2654 if (aentry->serverFlags[i] < 0
2655 || aentry->serverFlags[i] > MAXSERVERFLAG)
2656 return VL_BADSERVERFLAG;
2662 check_nvldbentry(struct nvldbentry *aentry)
2666 if (InvalidVolname(aentry->name))
2668 if (aentry->nServers <= 0 || aentry->nServers > NMAXNSERVERS)
2669 return VL_BADSERVER;
2670 for (i = 0; i < aentry->nServers; i++) {
2671 /* if (aentry->serverNumber[i] < 0 || aentry->serverNumber[i] > MAXSERVERID)
2672 return VL_BADSERVER; */
2673 if (aentry->serverPartition[i] < 0
2674 || aentry->serverPartition[i] > MAXPARTITIONID)
2675 return VL_BADPARTITION;
2676 if (aentry->serverFlags[i] < 0
2677 || aentry->serverFlags[i] > MAXSERVERFLAG)
2678 return VL_BADSERVERFLAG;
2684 /* Convert from the external vldb entry representation to its internal
2685 (more compact) form. This call should not change the hash chains! */
2687 vldbentry_to_vlentry(struct vl_ctx *ctx,
2688 struct vldbentry *VldbEntry,
2689 struct nvlentry *VlEntry)
2693 if (strcmp(VlEntry->name, VldbEntry->name))
2694 strncpy(VlEntry->name, VldbEntry->name, sizeof(VlEntry->name));
2695 for (i = 0; i < VldbEntry->nServers; i++) {
2696 serverindex = IpAddrToRelAddr(ctx, VldbEntry->serverNumber[i], 1);
2697 if (serverindex == -1)
2698 return VL_BADSERVER;
2699 VlEntry->serverNumber[i] = serverindex;
2700 VlEntry->serverPartition[i] = VldbEntry->serverPartition[i];
2701 VlEntry->serverFlags[i] = VldbEntry->serverFlags[i];
2703 for (; i < OMAXNSERVERS; i++)
2704 VlEntry->serverNumber[i] = VlEntry->serverPartition[i] =
2705 VlEntry->serverFlags[i] = BADSERVERID;
2706 for (i = 0; i < MAXTYPES; i++)
2707 VlEntry->volumeId[i] = VldbEntry->volumeId[i];
2708 VlEntry->cloneId = VldbEntry->cloneId;
2709 VlEntry->flags = VldbEntry->flags;
2714 nvldbentry_to_vlentry(struct vl_ctx *ctx,
2715 struct nvldbentry *VldbEntry,
2716 struct nvlentry *VlEntry)
2720 if (strcmp(VlEntry->name, VldbEntry->name))
2721 strncpy(VlEntry->name, VldbEntry->name, sizeof(VlEntry->name));
2722 for (i = 0; i < VldbEntry->nServers; i++) {
2723 serverindex = IpAddrToRelAddr(ctx, VldbEntry->serverNumber[i], 1);
2724 if (serverindex == -1)
2725 return VL_BADSERVER;
2726 VlEntry->serverNumber[i] = serverindex;
2727 VlEntry->serverPartition[i] = VldbEntry->serverPartition[i];
2728 VlEntry->serverFlags[i] = VldbEntry->serverFlags[i];
2730 for (; i < NMAXNSERVERS; i++)
2731 VlEntry->serverNumber[i] = VlEntry->serverPartition[i] =
2732 VlEntry->serverFlags[i] = BADSERVERID;
2733 for (i = 0; i < MAXTYPES; i++)
2734 VlEntry->volumeId[i] = VldbEntry->volumeId[i];
2735 VlEntry->cloneId = VldbEntry->cloneId;
2736 VlEntry->flags = VldbEntry->flags;
2741 /* Update the vldb entry with the new fields as indicated by the value of
2742 * the Mask entry in the updateentry structure. All necessary validation
2743 * checks are performed.
2746 get_vldbupdateentry(struct vl_ctx *ctx,
2747 afs_int32 blockindex,
2748 struct VldbUpdateEntry *updateentry,
2749 struct nvlentry *VlEntry)
2751 int i, j, errorcode, serverindex;
2752 afs_uint32 checkids[MAXTYPES];
2754 /* check if any specified new IDs are already present in the db. Do
2755 * this check before doing anything else, so we don't get a half-
2757 memset(&checkids, 0, sizeof(checkids));
2758 if (updateentry->Mask & VLUPDATE_RWID) {
2759 checkids[RWVOL] = updateentry->spares3; /* rw id */
2761 if (updateentry->Mask & VLUPDATE_READONLYID) {
2762 checkids[ROVOL] = updateentry->ReadOnlyId;
2764 if (updateentry->Mask & VLUPDATE_BACKUPID) {
2765 checkids[BACKVOL] = updateentry->BackupId;
2768 if (EntryIDExists(ctx, checkids, MAXTYPES, &errorcode)) {
2770 } else if (errorcode) {
2774 if (updateentry->Mask & VLUPDATE_VOLUMENAME) {
2775 struct nvlentry tentry;
2777 if (InvalidVolname(updateentry->name))
2780 if (FindByName(ctx, updateentry->name, &tentry, &errorcode)) {
2781 return VL_NAMEEXIST;
2782 } else if (errorcode) {
2786 if ((errorcode = UnhashVolname(ctx, blockindex, VlEntry)))
2788 strncpy(VlEntry->name, updateentry->name, sizeof(VlEntry->name));
2789 HashVolname(ctx, blockindex, VlEntry);
2792 if (updateentry->Mask & VLUPDATE_VOLNAMEHASH) {
2793 if ((errorcode = UnhashVolname(ctx, blockindex, VlEntry))) {
2794 if (errorcode != VL_NOENT)
2797 HashVolname(ctx, blockindex, VlEntry);
2800 if (updateentry->Mask & VLUPDATE_FLAGS) {
2801 VlEntry->flags = updateentry->flags;
2803 if (updateentry->Mask & VLUPDATE_CLONEID) {
2804 VlEntry->cloneId = updateentry->cloneId;
2806 if (updateentry->Mask & VLUPDATE_RWID) {
2807 if ((errorcode = UnhashVolid(ctx, RWVOL, blockindex, VlEntry))) {
2808 if (errorcode != VL_NOENT)
2811 VlEntry->volumeId[RWVOL] = updateentry->spares3; /* rw id */
2812 if ((errorcode = HashVolid(ctx, RWVOL, blockindex, VlEntry)))
2815 if (updateentry->Mask & VLUPDATE_READONLYID) {
2816 if ((errorcode = UnhashVolid(ctx, ROVOL, blockindex, VlEntry))) {
2817 if (errorcode != VL_NOENT)
2820 VlEntry->volumeId[ROVOL] = updateentry->ReadOnlyId;
2821 if ((errorcode = HashVolid(ctx, ROVOL, blockindex, VlEntry)))
2824 if (updateentry->Mask & VLUPDATE_BACKUPID) {
2825 if ((errorcode = UnhashVolid(ctx, BACKVOL, blockindex, VlEntry))) {
2826 if (errorcode != VL_NOENT)
2829 VlEntry->volumeId[BACKVOL] = updateentry->BackupId;
2830 if ((errorcode = HashVolid(ctx, BACKVOL, blockindex, VlEntry)))
2833 if (updateentry->Mask & VLUPDATE_REPSITES) {
2834 if (updateentry->nModifiedRepsites <= 0
2835 || updateentry->nModifiedRepsites > OMAXNSERVERS)
2836 return VL_BADSERVER;
2837 for (i = 0; i < updateentry->nModifiedRepsites; i++) {
2838 /* if (updateentry->RepsitesTargetServer[i] < 0 || updateentry->RepsitesTargetServer[i] > MAXSERVERID)
2839 return VL_BADSERVER; */
2840 if (updateentry->RepsitesTargetPart[i] < 0
2841 || updateentry->RepsitesTargetPart[i] > MAXPARTITIONID)
2842 return VL_BADPARTITION;
2843 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_DELETE) {
2845 repsite_exists(VlEntry,
2846 IpAddrToRelAddr(ctx, updateentry->
2847 RepsitesTargetServer[i],
2849 updateentry->RepsitesTargetPart[i])) !=
2851 repsite_compress(VlEntry, j);
2853 return VL_NOREPSERVER;
2855 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_ADD) {
2856 /* if (updateentry->RepsitesNewServer[i] < 0 || updateentry->RepsitesNewServer[i] > MAXSERVERID)
2857 return VL_BADSERVER; */
2858 if (updateentry->RepsitesNewPart[i] < 0
2859 || updateentry->RepsitesNewPart[i] > MAXPARTITIONID)
2860 return VL_BADPARTITION;
2863 IpAddrToRelAddr(ctx, updateentry->RepsitesNewServer[i], 1),
2864 updateentry->RepsitesNewPart[i]) != -1)
2865 return VL_DUPREPSERVER;
2867 VlEntry->serverNumber[j] != BADSERVERID
2868 && j < OMAXNSERVERS; j++);
2869 if (j >= OMAXNSERVERS)
2872 IpAddrToRelAddr(ctx, updateentry->RepsitesNewServer[i],
2874 return VL_BADSERVER;
2875 VlEntry->serverNumber[j] = serverindex;
2876 VlEntry->serverPartition[j] = updateentry->RepsitesNewPart[i];
2877 if (updateentry->RepsitesNewFlags[i] < 0
2878 || updateentry->RepsitesNewFlags[i] > MAXSERVERFLAG)
2879 return VL_BADSERVERFLAG;
2880 VlEntry->serverFlags[j] = updateentry->RepsitesNewFlags[i];
2882 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODSERV) {
2883 /*n if (updateentry->RepsitesNewServer[i] < 0 || updateentry->RepsitesNewServer[i] > MAXSERVERID)
2884 return VL_BADSERVER; */
2886 repsite_exists(VlEntry,
2887 IpAddrToRelAddr(ctx, updateentry->
2888 RepsitesTargetServer[i],
2890 updateentry->RepsitesTargetPart[i])) !=
2892 VlEntry->serverNumber[j] =
2893 IpAddrToRelAddr(ctx, updateentry->RepsitesNewServer[i],
2896 return VL_NOREPSERVER;
2898 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODPART) {
2899 if (updateentry->RepsitesNewPart[i] < 0
2900 || updateentry->RepsitesNewPart[i] > MAXPARTITIONID)
2901 return VL_BADPARTITION;
2903 repsite_exists(VlEntry,
2904 IpAddrToRelAddr(ctx, updateentry->
2905 RepsitesTargetServer[i],
2907 updateentry->RepsitesTargetPart[i])) !=
2909 VlEntry->serverPartition[j] =
2910 updateentry->RepsitesNewPart[i];
2912 return VL_NOREPSERVER;
2914 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODFLAG) {
2916 repsite_exists(VlEntry,
2917 IpAddrToRelAddr(ctx, updateentry->
2918 RepsitesTargetServer[i],
2920 updateentry->RepsitesTargetPart[i])) !=
2922 if (updateentry->RepsitesNewFlags[i] < 0
2923 || updateentry->RepsitesNewFlags[i] > MAXSERVERFLAG)
2924 return VL_BADSERVERFLAG;
2925 VlEntry->serverFlags[j] =
2926 updateentry->RepsitesNewFlags[i];
2928 return VL_NOREPSERVER;
2936 /* Check if the specified [server,partition] entry is found in the vldb
2937 * entry's repsite table; it's offset in the table is returned, if it's
2940 repsite_exists(struct nvlentry *VlEntry, int server, int partition)
2944 for (i = 0; VlEntry->serverNumber[i] != BADSERVERID && i < OMAXNSERVERS;
2946 if ((VlEntry->serverNumber[i] == server)
2947 && (VlEntry->serverPartition[i] == partition))
2955 /* Repsite table compression: used when deleting a repsite entry so that
2956 * all active repsite entries are on the top of the table. */
2958 repsite_compress(struct nvlentry *VlEntry, int offset)
2960 int repsite_offset = offset;
2962 VlEntry->serverNumber[repsite_offset] != BADSERVERID
2963 && repsite_offset < OMAXNSERVERS - 1; repsite_offset++) {
2964 VlEntry->serverNumber[repsite_offset] =
2965 VlEntry->serverNumber[repsite_offset + 1];
2966 VlEntry->serverPartition[repsite_offset] =
2967 VlEntry->serverPartition[repsite_offset + 1];
2968 VlEntry->serverFlags[repsite_offset] =
2969 VlEntry->serverFlags[repsite_offset + 1];
2971 VlEntry->serverNumber[repsite_offset] = BADSERVERID;
2975 /* Convert from the internal (compacted) vldb entry to the external
2976 * representation used by the interface. */
2978 vlentry_to_vldbentry(struct vl_ctx *ctx, struct nvlentry *VlEntry,
2979 struct vldbentry *VldbEntry)
2983 memset(VldbEntry, 0, sizeof(struct vldbentry));
2984 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
2985 for (i = 0; i < OMAXNSERVERS; i++) {
2986 if (VlEntry->serverNumber[i] == BADSERVERID)
2988 if ((ctx->hostaddress[j = VlEntry->serverNumber[i]] & 0xff000000) ==
2990 struct extentaddr *exp;
2993 base = (ctx->hostaddress[j] >> 16) & 0xff;
2994 index = ctx->hostaddress[j] & 0x0000ffff;
2995 exp = &ctx->ex_addr[base][index];
2996 /* For now return the first ip address back */
2997 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2998 if (exp->ex_addrs[j]) {
2999 VldbEntry->serverNumber[i] = ntohl(exp->ex_addrs[j]);
3004 VldbEntry->serverNumber[i] =
3005 ctx->hostaddress[VlEntry->serverNumber[i]];
3006 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
3007 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
3009 VldbEntry->nServers = i;
3010 for (i = 0; i < MAXTYPES; i++)
3011 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
3012 VldbEntry->cloneId = VlEntry->cloneId;
3013 VldbEntry->flags = VlEntry->flags;
3017 /* Convert from the internal (compacted) vldb entry to the external
3018 * representation used by the interface. */
3020 vlentry_to_nvldbentry(struct vl_ctx *ctx, struct nvlentry *VlEntry,
3021 struct nvldbentry *VldbEntry)
3025 memset(VldbEntry, 0, sizeof(struct vldbentry));
3026 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
3027 for (i = 0; i < NMAXNSERVERS; i++) {
3028 if (VlEntry->serverNumber[i] == BADSERVERID)
3030 if ((ctx->hostaddress[j = VlEntry->serverNumber[i]] & 0xff000000) ==
3032 struct extentaddr *exp;
3035 base = (ctx->hostaddress[j] >> 16) & 0xff;
3036 index = ctx->hostaddress[j] & 0x0000ffff;
3037 exp = &ctx->ex_addr[base][index];
3038 /* For now return the first ip address back */
3039 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
3040 if (exp->ex_addrs[j]) {
3041 VldbEntry->serverNumber[i] = ntohl(exp->ex_addrs[j]);
3046 VldbEntry->serverNumber[i] =
3047 ctx->hostaddress[VlEntry->serverNumber[i]];
3048 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
3049 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
3051 VldbEntry->nServers = i;
3052 for (i = 0; i < MAXTYPES; i++)
3053 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
3054 VldbEntry->cloneId = VlEntry->cloneId;
3055 VldbEntry->flags = VlEntry->flags;
3059 vlentry_to_uvldbentry(struct vl_ctx *ctx, struct nvlentry *VlEntry,
3060 struct uvldbentry *VldbEntry)
3064 memset(VldbEntry, 0, sizeof(struct vldbentry));
3065 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
3066 for (i = 0; i < NMAXNSERVERS; i++) {
3067 if (VlEntry->serverNumber[i] == BADSERVERID)
3069 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
3070 VldbEntry->serverUnique[i] = 0;
3071 if ((ctx->hostaddress[j = VlEntry->serverNumber[i]] & 0xff000000) ==
3073 struct extentaddr *exp;
3077 base = (ctx->hostaddress[j] >> 16) & 0xff;
3078 index = ctx->hostaddress[j] & 0x0000ffff;
3079 exp = &ctx->ex_addr[base][index];
3080 tuuid = exp->ex_hostuuid;
3081 afs_ntohuuid(&tuuid);
3082 VldbEntry->serverFlags[i] |= VLSERVER_FLAG_UUID;
3083 VldbEntry->serverNumber[i] = tuuid;
3084 VldbEntry->serverUnique[i] = ntohl(exp->ex_uniquifier);
3086 VldbEntry->serverNumber[i].time_low =
3087 ctx->hostaddress[VlEntry->serverNumber[i]];
3089 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
3092 VldbEntry->nServers = i;
3093 for (i = 0; i < MAXTYPES; i++)
3094 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
3095 VldbEntry->cloneId = VlEntry->cloneId;
3096 VldbEntry->flags = VlEntry->flags;
3099 #define LEGALCHARS ".ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
3102 /* Verify that the volname is a valid volume name. */
3104 InvalidVolname(char *volname)
3110 slen = strlen(volname);
3111 if (slen >= VL_MAXNAMELEN)
3113 return (slen != strspn(volname, map));
3117 /* Verify that the given volume type is valid. */
3119 InvalidVoltype(afs_int32 voltype)
3121 if (voltype != RWVOL && voltype != ROVOL && voltype != BACKVOL)
3128 InvalidOperation(afs_int32 voloper)
3130 if (voloper != VLOP_MOVE && voloper != VLOP_RELEASE
3131 && voloper != VLOP_BACKUP && voloper != VLOP_DELETE
3132 && voloper != VLOP_DUMP)
3138 InvalidReleasetype(afs_int32 releasetype)
3140 if ((releasetype & LOCKREL_TIMESTAMP) || (releasetype & LOCKREL_OPCODE)
3141 || (releasetype & LOCKREL_AFSID))
3147 IpAddrToRelAddr(struct vl_ctx *ctx, afs_uint32 ipaddr, int create)
3150 afs_int32 code, base, index;
3151 struct extentaddr *exp;
3153 for (i = 0; i <= MAXSERVERID; i++) {
3154 if (ctx->hostaddress[i] == ipaddr)
3156 if ((ctx->hostaddress[i] & 0xff000000) == 0xff000000) {
3157 base = (ctx->hostaddress[i] >> 16) & 0xff;
3158 index = ctx->hostaddress[i] & 0x0000ffff;
3159 if (base >= VL_MAX_ADDREXTBLKS) {
3161 ("Internal error: Multihome extent base is too large. Base %d index %d\n",
3163 return -1; /* EINVAL */
3165 if (index >= VL_MHSRV_PERBLK) {
3167 ("Internal error: Multihome extent index is too large. Base %d index %d\n",
3169 return -1; /* EINVAL */
3171 if (!ctx->ex_addr[base]) {
3173 ("Internal error: Multihome extent does not exist. Base %d\n",
3175 return -1; /* EINVAL */
3177 exp = &ctx->ex_addr[base][index];
3178 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
3179 if (exp->ex_addrs[j] && (ntohl(exp->ex_addrs[j]) == ipaddr)) {
3186 /* allocate the new server a server id pronto */
3188 for (i = 0; i <= MAXSERVERID; i++) {
3189 if (ctx->cheader->IpMappedAddr[i] == 0) {
3190 ctx->cheader->IpMappedAddr[i] = htonl(ipaddr);
3193 DOFFSET(0, ctx->cheader, &ctx->cheader->IpMappedAddr[i]),
3194 (char *)&ctx->cheader->IpMappedAddr[i],
3196 ctx->hostaddress[i] = ipaddr;
3207 ChangeIPAddr(struct vl_ctx *ctx, afs_uint32 ipaddr1, afs_uint32 ipaddr2)
3211 struct extentaddr *exp = NULL;
3215 afs_int32 blockindex, count;
3217 struct nvlentry tentry;
3218 int ipaddr1_id = -1, ipaddr2_id = -1;
3220 /* Don't let addr change to 256.*.*.* : Causes internal error below */
3221 if ((ipaddr2 & 0xff000000) == 0xff000000)
3222 return (VL_BADSERVER);
3224 /* If we are removing an address, ip1 will be -1 and ip2 will be
3225 * the original address. This prevents an older revision vlserver
3226 * from removing the IP address (won't find server 0xfffffff in
3227 * the VLDB). An older revision vlserver does not have the check
3228 * to see if any volumes exist on the server being removed.
3230 if (ipaddr1 == 0xffffffff) {
3235 for (i = 0; i <= MAXSERVERID; i++) {
3236 if ((ctx->hostaddress[i] & 0xff000000) == 0xff000000) {
3237 base = (ctx->hostaddress[i] >> 16) & 0xff;
3238 index = ctx->hostaddress[i] & 0x0000ffff;
3239 if ((base >= VL_MAX_ADDREXTBLKS) || (index >= VL_MHSRV_PERBLK)) {
3241 ("Internal error: Multihome extent addr is too large. Base %d index %d\n",
3243 return -1; /* EINVAL */
3246 exp = &ctx->ex_addr[base][index];
3247 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
3248 if (!exp->ex_addrs[mhidx])
3250 if (ntohl(exp->ex_addrs[mhidx]) == ipaddr1) {
3253 if (ipaddr2 != 0 && ntohl(exp->ex_addrs[mhidx]) == ipaddr2) {
3258 if (ctx->hostaddress[i] == ipaddr1) {
3262 if (ipaddr2 != 0 && ctx->hostaddress[i] == ipaddr2) {
3267 if (ipaddr1_id >= 0 && (ipaddr2 == 0 || ipaddr2_id >= 0)) {
3268 /* we've either found both IPs already in the VLDB, or we found
3269 * ipaddr1, and we're not going to find ipaddr2 because it's 0 */
3274 if (ipaddr1_id < 0) {
3275 return VL_NOENT; /* not found */
3278 if (ipaddr2_id >= 0 && ipaddr2_id != ipaddr1_id) {
3279 char buf1[16], buf2[16];
3280 VLog(0, ("Cannot change IP address from %s to %s because the latter "
3281 "is in use by server id %d\n",
3282 afs_inet_ntoa_r(htonl(ipaddr1), buf1),
3283 afs_inet_ntoa_r(htonl(ipaddr2), buf2),
3285 return VL_MULTIPADDR;
3288 /* If we are removing a server entry, a volume cannot
3289 * exist on the server. If one does, don't remove the
3290 * server entry: return error "volume entry exists".
3293 for (blockindex = NextEntry(ctx, 0, &tentry, &count); blockindex;
3294 blockindex = NextEntry(ctx, blockindex, &tentry, &count)) {
3295 if (++pollcount > 50) {
3296 #ifndef AFS_PTHREAD_ENV
3301 for (j = 0; j < NMAXNSERVERS; j++) {
3302 if (tentry.serverNumber[j] == BADSERVERID)
3304 if (tentry.serverNumber[j] == ipaddr1_id) {
3311 /* Log a message saying we are changing/removing an IP address */
3313 ("The following IP address is being %s:\n",
3314 (ipaddr2 ? "changed" : "removed")));
3315 VLog(0, (" entry %d: ", i));
3318 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
3319 if (!exp->ex_addrs[mhidx])
3323 PADDR(ntohl(exp->ex_addrs[mhidx]));
3335 /* Change the registered uuuid addresses */
3337 memset(&tuuid, 0, sizeof(afsUUID));
3338 afs_htonuuid(&tuuid);
3339 exp->ex_hostuuid = tuuid;
3342 DOFFSET(ntohl(ctx->ex_addr[0]->ex_contaddrs[base]),
3343 (char *)ctx->ex_addr[base], (char *)exp),
3344 (char *)&tuuid, sizeof(tuuid));
3349 /* Now change the host address entry */
3350 ctx->cheader->IpMappedAddr[ipaddr1_id] = htonl(ipaddr2);
3352 vlwrite(ctx->trans, DOFFSET(0, ctx->cheader, &ctx->cheader->IpMappedAddr[ipaddr1_id]),
3354 &ctx->cheader->IpMappedAddr[ipaddr1_id], sizeof(afs_int32));
3355 ctx->hostaddress[ipaddr1_id] = ipaddr2;
3362 /* see if the vlserver is back yet */
3364 SVL_ProbeServer(struct rx_call *rxcall)