2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include <afs/param.h>
16 #include <afs/afsutil.h>
22 #include <afs/cellconfig.h>
25 #include "vlserver_internal.h"
26 #include "afs/audit.h"
28 #ifdef HAVE_POSIX_REGEX /* use POSIX regexp library */
33 extern int extent_mod;
34 extern struct afsconf_dir *vldb_confdir;
35 extern struct ubik_dbase *VL_dbase;
37 #define ABORT(c) do { \
47 #define VLDBALLOCLIMIT 10000
48 #define VLDBALLOCINCR 2048
50 static int put_attributeentry(struct vl_ctx *ctx,
51 struct vldbentry **, struct vldbentry **,
52 struct vldbentry **, bulkentries *,
53 struct nvlentry *, afs_int32 *, afs_int32 *);
54 static int put_nattributeentry(struct vl_ctx *ctx,
55 struct nvldbentry **, struct nvldbentry **,
56 struct nvldbentry **, nbulkentries *,
57 struct nvlentry *, afs_int32, afs_int32,
58 afs_int32 *, afs_int32 *);
59 static int RemoveEntry(struct vl_ctx *ctx, afs_int32 entryptr,
60 struct nvlentry *tentry);
61 static void ReleaseEntry(struct nvlentry *tentry, afs_int32 releasetype);
62 static int check_vldbentry(struct vldbentry *aentry);
63 static int check_nvldbentry(struct nvldbentry *aentry);
64 static int vldbentry_to_vlentry(struct vl_ctx *ctx,
65 struct vldbentry *VldbEntry,
66 struct nvlentry *VlEntry);
67 static int nvldbentry_to_vlentry(struct vl_ctx *ctx,
68 struct nvldbentry *VldbEntry,
69 struct nvlentry *VlEntry);
70 static int get_vldbupdateentry(struct vl_ctx *ctx, afs_int32 blockindex,
71 struct VldbUpdateEntry *updateentry,
72 struct nvlentry *VlEntry);
73 static int repsite_exists(struct nvlentry *VlEntry, int server, int partition);
74 static void repsite_compress(struct nvlentry *VlEntry, int offset);
75 static void vlentry_to_vldbentry(struct vl_ctx *ctx,
76 struct nvlentry *VlEntry,
77 struct vldbentry *VldbEntry);
78 static void vlentry_to_nvldbentry(struct vl_ctx *ctx,
79 struct nvlentry *VlEntry,
80 struct nvldbentry *VldbEntry);
81 static void vlentry_to_uvldbentry(struct vl_ctx *ctx,
82 struct nvlentry *VlEntry,
83 struct uvldbentry *VldbEntry);
84 static int InvalidVolname(char *volname);
85 static int InvalidVoltype(afs_int32 voltype);
86 static int InvalidOperation(afs_int32 voloper);
87 static int InvalidReleasetype(afs_int32 releasetype);
88 static int IpAddrToRelAddr(struct vl_ctx *ctx, afs_uint32 ipaddr, int create);
89 static int ChangeIPAddr(struct vl_ctx *ctx, afs_uint32 ipaddr1,
93 countRequest(int opcode)
96 dynamic_statistics.requests[opcode - VL_LOWEST_OPCODE]++;
101 countAbort(int opcode)
104 dynamic_statistics.aborts[opcode - VL_LOWEST_OPCODE]++;
108 #define AFS_RXINFO_LEN 128
110 rxinfo(char * str, struct rx_call *rxcall)
113 struct rx_connection *tconn;
118 struct in_addr hostAddr;
120 tconn = rx_ConnectionOf(rxcall);
121 hostAddr.s_addr = rx_HostOf(rx_PeerOf(tconn));
123 rxkad_GetServerInfo(rxcall->conn, NULL, &exp, tname, tinst, tcell,
126 sprintf(str, "%s %s%s%s%s%s", inet_ntoa(hostAddr), tname,
127 (tinst[0] == '\0') ? "" : ".",
128 (tinst[0] == '\0') ? "" : tinst,
129 (tcell[0] == '\0') ? "" : "@",
130 (tcell[0] == '\0') ? "" : tcell);
132 sprintf(str, "%s noauth", inet_ntoa(hostAddr));
136 /* This is called to initialize the database, set the appropriate locks and make sure that the vldb header is valid */
138 Init_VLdbase(struct vl_ctx *ctx,
139 int locktype, /* indicate read or write transaction */
142 int errorcode = 0, pass, wl;
144 for (pass = 1; pass <= 3; pass++) {
145 if (pass == 2) { /* take write lock to rebuild the db */
146 errorcode = ubik_BeginTrans(VL_dbase, UBIK_WRITETRANS, &ctx->trans);
148 } else if (locktype == LOCKREAD) {
150 ubik_BeginTransReadAnyWrite(VL_dbase, UBIK_READTRANS, &ctx->trans);
153 errorcode = ubik_BeginTrans(VL_dbase, UBIK_WRITETRANS, &ctx->trans);
159 errorcode = ubik_SetLock(ctx->trans, 1, 1, locktype);
162 ubik_AbortTrans(ctx->trans);
166 /* check that dbase is initialized and setup cheader */
167 /* 2nd pass we try to rebuild the header */
168 errorcode = CheckInit(ctx->trans, ((pass == 2) ? 1 : 0));
169 if (!errorcode && wl && extent_mod)
170 errorcode = readExtents(ctx->trans); /* Fix the mh extent blocks */
173 ubik_AbortTrans(ctx->trans);
174 /* Only rebuld if the database is empty */
175 /* Exit if can't rebuild */
176 if ((pass == 1) && (errorcode != VL_EMPTY))
180 } else { /* No errorcode */
182 ubik_EndTrans(ctx->trans); /* Rebuilt db. End trans, then retake original lock */
184 break; /* didn't rebuild and successful - exit */
188 if (errorcode == 0) {
189 errorcode = vlsetcache(ctx, locktype);
195 /* Create a new vldb entry; both new volume id and name must be unique
196 * (non-existant in vldb).
200 SVL_CreateEntry(struct rx_call *rxcall, struct vldbentry *newentry)
202 int this_op = VLCREATEENTRY;
204 afs_int32 errorcode, blockindex;
205 struct nvlentry tentry;
206 char rxstr[AFS_RXINFO_LEN];
208 countRequest(this_op);
209 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) {
214 /* Do some validity tests on new entry */
215 if ((errorcode = check_vldbentry(newentry))
216 || (errorcode = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
220 ("OCreate Volume %d %s\n", newentry->volumeId[RWVOL],
221 rxinfo(rxstr, rxcall)));
222 if (EntryIDExists(&ctx, newentry->volumeId, MAXTYPES, &errorcode)) {
223 /* at least one of the specified IDs already exists; we fail */
224 errorcode = VL_IDEXIST;
226 } else if (errorcode) {
230 /* Is this following check (by volume name) necessary?? */
231 /* If entry already exists, we fail */
232 if (FindByName(&ctx, newentry->name, &tentry, &errorcode)) {
233 errorcode = VL_NAMEEXIST;
235 } else if (errorcode) {
239 blockindex = AllocBlock(&ctx, &tentry);
240 if (blockindex == 0) {
241 errorcode = VL_CREATEFAIL;
245 memset(&tentry, 0, sizeof(struct nvlentry));
246 /* Convert to its internal representation; both in host byte order */
247 if ((errorcode = vldbentry_to_vlentry(&ctx, newentry, &tentry))) {
248 FreeBlock(&ctx, blockindex);
252 /* Actually insert the entry in vldb */
253 errorcode = ThreadVLentry(&ctx, blockindex, &tentry);
255 FreeBlock(&ctx, blockindex);
258 errorcode = ubik_EndTrans(ctx.trans);
264 ubik_AbortTrans(ctx.trans);
267 osi_auditU(rxcall, VLCreateEntryEvent, errorcode, AUD_STR,
268 (newentry ? newentry->name : NULL), AUD_END);
274 SVL_CreateEntryN(struct rx_call *rxcall, struct nvldbentry *newentry)
276 int this_op = VLCREATEENTRYN;
278 afs_int32 errorcode, blockindex;
279 struct nvlentry tentry;
280 char rxstr[AFS_RXINFO_LEN];
282 countRequest(this_op);
283 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) {
288 /* Do some validity tests on new entry */
289 if ((errorcode = check_nvldbentry(newentry))
290 || (errorcode = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
294 ("Create Volume %d %s\n", newentry->volumeId[RWVOL],
295 rxinfo(rxstr, rxcall)));
296 if (EntryIDExists(&ctx, newentry->volumeId, MAXTYPES, &errorcode)) {
297 /* at least one of the specified IDs already exists; we fail */
298 errorcode = VL_IDEXIST;
300 } else if (errorcode) {
304 /* Is this following check (by volume name) necessary?? */
305 /* If entry already exists, we fail */
306 if (FindByName(&ctx, newentry->name, &tentry, &errorcode)) {
307 errorcode = VL_NAMEEXIST;
309 } else if (errorcode) {
313 blockindex = AllocBlock(&ctx, &tentry);
314 if (blockindex == 0) {
315 errorcode = VL_CREATEFAIL;
319 memset(&tentry, 0, sizeof(struct nvlentry));
320 /* Convert to its internal representation; both in host byte order */
321 if ((errorcode = nvldbentry_to_vlentry(&ctx, newentry, &tentry))) {
322 FreeBlock(&ctx, blockindex);
326 /* Actually insert the entry in vldb */
327 errorcode = ThreadVLentry(&ctx, blockindex, &tentry);
329 FreeBlock(&ctx, blockindex);
332 errorcode = ubik_EndTrans(ctx.trans);
338 ubik_AbortTrans(ctx.trans);
341 osi_auditU(rxcall, VLCreateEntryEvent, errorcode, AUD_STR,
342 (newentry ? newentry->name : NULL), AUD_END);
348 SVL_ChangeAddr(struct rx_call *rxcall, afs_uint32 ip1, afs_uint32 ip2)
350 int this_op = VLCHANGEADDR;
353 char rxstr[AFS_RXINFO_LEN];
355 countRequest(this_op);
356 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) {
361 if ((errorcode = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
364 VLog(1, ("Change Addr %u -> %u %s\n", ip1, ip2, rxinfo(rxstr, rxcall)));
365 if ((errorcode = ChangeIPAddr(&ctx, ip1, ip2)))
368 errorcode = ubik_EndTrans(ctx.trans);
374 ubik_AbortTrans(ctx.trans);
377 osi_auditU(rxcall, VLChangeAddrEvent, errorcode, AUD_LONG, ip1, AUD_LONG,
382 /* Delete a vldb entry given the volume id. */
384 SVL_DeleteEntry(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype)
386 int this_op = VLDELETEENTRY;
388 afs_int32 blockindex, errorcode;
389 struct nvlentry tentry;
390 char rxstr[AFS_RXINFO_LEN];
392 countRequest(this_op);
393 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
396 if ((voltype != -1) && (InvalidVoltype(voltype)))
399 if ((errorcode = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
402 VLog(1, ("Delete Volume %u %s\n", volid, rxinfo(rxstr, rxcall)));
403 blockindex = FindByID(&ctx, volid, voltype, &tentry, &errorcode);
404 if (blockindex == 0) { /* volid not found */
406 errorcode = VL_NOENT;
410 if (tentry.flags & VLDELETED) { /* Already deleted; return */
411 ABORT(VL_ENTDELETED);
413 if ((errorcode = RemoveEntry(&ctx, blockindex, &tentry))) {
416 errorcode = (ubik_EndTrans(ctx.trans));
421 ubik_AbortTrans(ctx.trans);
424 osi_auditU(rxcall, VLDeleteEntryEvent, errorcode, AUD_LONG, volid,
430 /* Get a vldb entry given its volume id; make sure it's not a deleted entry. */
432 GetEntryByID(struct rx_call *rxcall,
435 char *aentry, /* entry data copied here */
440 afs_int32 blockindex, errorcode;
441 struct nvlentry tentry;
442 char rxstr[AFS_RXINFO_LEN];
444 countRequest(this_op);
446 if ((voltype != -1) && (InvalidVoltype(voltype)))
447 return VL_BADVOLTYPE;
448 if ((errorcode = Init_VLdbase(&ctx, LOCKREAD, this_op)))
451 VLog(5, ("GetVolumeByID %u (%d) %s\n", volid, new,
452 rxinfo(rxstr, rxcall)));
453 blockindex = FindByID(&ctx, volid, voltype, &tentry, &errorcode);
454 if (blockindex == 0) { /* entry not found */
456 errorcode = VL_NOENT;
458 ubik_AbortTrans(ctx.trans);
461 if (tentry.flags & VLDELETED) { /* Entry is deleted! */
463 ubik_AbortTrans(ctx.trans);
464 return VL_ENTDELETED;
466 /* Convert from the internal to external form */
468 vlentry_to_nvldbentry(&ctx, &tentry, (struct nvldbentry *)aentry);
470 vlentry_to_uvldbentry(&ctx, &tentry, (struct uvldbentry *)aentry);
472 vlentry_to_vldbentry(&ctx, &tentry, (struct vldbentry *)aentry);
473 return (ubik_EndTrans(ctx.trans));
477 SVL_GetEntryByID(struct rx_call *rxcall,
480 vldbentry *aentry) /* entry data copied here */
482 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 0,
487 SVL_GetEntryByIDN(struct rx_call *rxcall,
490 nvldbentry *aentry) /* entry data copied here */
492 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 1,
497 SVL_GetEntryByIDU(struct rx_call *rxcall,
500 uvldbentry *aentry) /* entry data copied here */
502 return (GetEntryByID(rxcall, volid, voltype, (char *)aentry, 2,
506 /* returns true if the id is a decimal integer, in which case we interpret
507 * it as an id. make the cache manager much simpler */
509 NameIsId(char *aname)
512 while ((tc = *aname++)) {
513 if (tc > '9' || tc < '0')
519 /* Get a vldb entry given the volume's name; of course, very similar to
520 * VLGetEntryByID() above. */
522 GetEntryByName(struct rx_call *rxcall,
524 char *aentry, /* entry data copied here */
529 afs_int32 blockindex, errorcode;
530 struct nvlentry tentry;
531 char rxstr[AFS_RXINFO_LEN];
533 if (NameIsId(volname)) {
534 return GetEntryByID(rxcall, atoi(volname), -1, aentry, new, this_op);
536 if (InvalidVolname(volname))
538 if ((errorcode = Init_VLdbase(&ctx, LOCKREAD, this_op)))
540 VLog(5, ("GetVolumeByName %s (%d) %s\n", volname, new, rxinfo(rxstr, rxcall)));
541 blockindex = FindByName(&ctx, volname, &tentry, &errorcode);
542 if (blockindex == 0) { /* entry not found */
544 errorcode = VL_NOENT;
546 ubik_AbortTrans(ctx.trans);
549 if (tentry.flags & VLDELETED) { /* Entry is deleted */
551 ubik_AbortTrans(ctx.trans);
552 return VL_ENTDELETED;
554 /* Convert to external entry representation */
556 vlentry_to_nvldbentry(&ctx, &tentry, (struct nvldbentry *)aentry);
558 vlentry_to_uvldbentry(&ctx, &tentry, (struct uvldbentry *)aentry);
560 vlentry_to_vldbentry(&ctx, &tentry, (struct vldbentry *)aentry);
561 return (ubik_EndTrans(ctx.trans));
565 SVL_GetEntryByNameO(struct rx_call *rxcall,
567 struct vldbentry *aentry) /* entry data copied here */
569 return (GetEntryByName(rxcall, volname, (char *)aentry, 0,
575 SVL_GetEntryByNameN(struct rx_call *rxcall,
577 struct nvldbentry *aentry) /* entry data copied here */
579 return (GetEntryByName(rxcall, volname, (char *)aentry, 1,
584 SVL_GetEntryByNameU(struct rx_call *rxcall,
586 struct uvldbentry *aentry) /* entry data copied here */
588 return (GetEntryByName(rxcall, volname, (char *)aentry, 2,
594 /* Get the current value of the maximum volume id and bump the volume id counter by Maxvolidbump. */
596 SVL_GetNewVolumeId(struct rx_call *rxcall, afs_uint32 Maxvolidbump,
597 afs_uint32 *newvolumeid)
599 int this_op = VLGETNEWVOLUMEID;
601 afs_uint32 maxvolumeid;
603 char rxstr[AFS_RXINFO_LEN];
605 countRequest(this_op);
606 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
609 if (Maxvolidbump < 0 || Maxvolidbump > MAXBUMPCOUNT)
610 END(VL_BADVOLIDBUMP);
612 if ((errorcode = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
615 *newvolumeid = maxvolumeid = NextUnusedID(&ctx,
616 ntohl(ctx.cheader->vital_header.MaxVolumeId), Maxvolidbump, &errorcode);
621 maxvolumeid += Maxvolidbump;
622 VLog(1, ("GetNewVolid newmax=%u %s\n", maxvolumeid, rxinfo(rxstr, rxcall)));
623 ctx.cheader->vital_header.MaxVolumeId = htonl(maxvolumeid);
624 if (write_vital_vlheader(&ctx)) {
627 errorcode = (ubik_EndTrans(ctx.trans));
632 ubik_AbortTrans(ctx.trans);
635 osi_auditU(rxcall, VLGetNewVolumeIdEvent, errorcode, AUD_END);
640 /* Simple replace the contents of the vldb entry, volid, with
641 * newentry. No individual checking/updating per field (alike
642 * VLUpdateEntry) is done. */
645 SVL_ReplaceEntry(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype,
646 struct vldbentry *newentry, afs_int32 releasetype)
648 int this_op = VLREPLACEENTRY;
650 afs_int32 blockindex, errorcode, typeindex;
652 int hashVol[MAXTYPES];
653 struct nvlentry tentry;
654 afs_uint32 checkids[MAXTYPES];
655 char rxstr[AFS_RXINFO_LEN];
657 countRequest(this_op);
658 for (typeindex = 0; typeindex < MAXTYPES; typeindex++)
659 hashVol[typeindex] = 0;
661 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
664 if ((errorcode = check_vldbentry(newentry)))
667 if (voltype != -1 && InvalidVoltype(voltype))
670 if (releasetype && InvalidReleasetype(releasetype))
671 END(VL_BADRELLOCKTYPE);
672 if ((errorcode = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
675 VLog(1, ("OReplace Volume %u %s\n", volid, rxinfo(rxstr, rxcall)));
676 /* find vlentry we're changing */
677 blockindex = FindByID(&ctx, volid, voltype, &tentry, &errorcode);
678 if (blockindex == 0) { /* entry not found */
680 errorcode = VL_NOENT;
684 /* check that we're not trying to change the RW vol ID */
685 if (newentry->volumeId[RWVOL] != tentry.volumeId[RWVOL]) {
689 /* make sure none of the IDs we are changing to are already in use */
690 memset(&checkids, 0, sizeof(checkids));
691 for (typeindex = ROVOL; typeindex < MAXTYPES; typeindex++) {
692 if (tentry.volumeId[typeindex] != newentry->volumeId[typeindex]) {
693 checkids[typeindex] = newentry->volumeId[typeindex];
696 if (EntryIDExists(&ctx, checkids, MAXTYPES, &errorcode)) {
698 } else if (errorcode) {
702 /* make sure the name we're changing to doesn't already exist */
703 if (strcmp(newentry->name, tentry.name)) {
704 struct nvlentry tmp_entry;
705 if (FindByName(&ctx, newentry->name, &tmp_entry, &errorcode)) {
707 } else if (errorcode) {
712 /* unhash volid entries if they're disappearing or changing.
713 * Remember if we need to hash in the new value (we don't have to
714 * rehash if volid stays same */
715 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
716 if (tentry.volumeId[typeindex] != newentry->volumeId[typeindex]) {
717 if (tentry.volumeId[typeindex])
719 UnhashVolid(&ctx, typeindex, blockindex, &tentry))) {
722 /* we must rehash new id if the id is different and the ID is nonzero */
723 hashVol[typeindex] = 1; /* must rehash this guy if he exists */
727 /* Rehash volname if it changes */
728 if (strcmp(newentry->name, tentry.name)) { /* Name changes; redo hashing */
729 if ((errorcode = UnhashVolname(&ctx, blockindex, &tentry))) {
735 /* after this, tentry is new entry, not old one. vldbentry_to_vlentry
736 * doesn't touch hash chains */
737 if ((errorcode = vldbentry_to_vlentry(&ctx, newentry, &tentry))) {
741 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
742 if (hashVol[typeindex] && tentry.volumeId[typeindex]) {
743 if ((errorcode = HashVolid(&ctx, typeindex, blockindex, &tentry))) {
750 HashVolname(&ctx, blockindex, &tentry);
753 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
754 if (vlentrywrite(ctx.trans, blockindex, &tentry, sizeof(tentry))) {
758 END(ubik_EndTrans(ctx.trans));
762 ubik_AbortTrans(ctx.trans);
765 osi_auditU(rxcall, VLReplaceVLEntryEvent, errorcode, AUD_LONG, volid,
771 SVL_ReplaceEntryN(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype,
772 struct nvldbentry *newentry, afs_int32 releasetype)
774 int this_op = VLREPLACEENTRYN;
776 afs_int32 blockindex, errorcode, typeindex;
778 int hashVol[MAXTYPES];
779 struct nvlentry tentry;
780 char rxstr[AFS_RXINFO_LEN];
782 countRequest(this_op);
783 for (typeindex = 0; typeindex < MAXTYPES; typeindex++)
784 hashVol[typeindex] = 0;
786 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
789 if ((errorcode = check_nvldbentry(newentry)))
792 if (voltype != -1 && InvalidVoltype(voltype))
795 if (releasetype && InvalidReleasetype(releasetype))
796 END(VL_BADRELLOCKTYPE);
797 if ((errorcode = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
800 VLog(1, ("Replace Volume %u %s\n", volid, rxinfo(rxstr, rxcall)));
801 /* find vlentry we're changing */
802 blockindex = FindByID(&ctx, volid, voltype, &tentry, &errorcode);
803 if (blockindex == 0) { /* entry not found */
805 errorcode = VL_NOENT;
809 /* check that we're not trying to change the RW vol ID */
810 if (newentry->volumeId[RWVOL] != tentry.volumeId[RWVOL]) {
814 /* unhash volid entries if they're disappearing or changing.
815 * Remember if we need to hash in the new value (we don't have to
816 * rehash if volid stays same */
817 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
818 if (tentry.volumeId[typeindex] != newentry->volumeId[typeindex]) {
819 if (tentry.volumeId[typeindex])
821 UnhashVolid(&ctx, typeindex, blockindex, &tentry))) {
824 /* we must rehash new id if the id is different and the ID is nonzero */
825 hashVol[typeindex] = 1; /* must rehash this guy if he exists */
829 /* Rehash volname if it changes */
830 if (strcmp(newentry->name, tentry.name)) { /* Name changes; redo hashing */
831 if ((errorcode = UnhashVolname(&ctx, blockindex, &tentry))) {
837 /* after this, tentry is new entry, not old one. vldbentry_to_vlentry
838 * doesn't touch hash chains */
839 if ((errorcode = nvldbentry_to_vlentry(&ctx, newentry, &tentry))) {
843 for (typeindex = ROVOL; typeindex <= BACKVOL; typeindex++) {
844 if (hashVol[typeindex] && tentry.volumeId[typeindex]) {
845 if ((errorcode = HashVolid(&ctx, typeindex, blockindex, &tentry))) {
852 HashVolname(&ctx, blockindex, &tentry);
855 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
856 if (vlentrywrite(ctx.trans, blockindex, &tentry, sizeof(tentry))) {
860 END(ubik_EndTrans(ctx.trans));
864 ubik_AbortTrans(ctx.trans);
867 osi_auditU(rxcall, VLReplaceVLEntryEvent, errorcode, AUD_LONG, volid,
873 /* Update a vldb entry (accessed thru its volume id). Almost all of the
874 * entry's fields can be modified in a single call by setting the
875 * appropriate bits in the Mask field in VldbUpdateentry. */
876 /* this routine may never have been tested; use replace entry instead
877 * unless you're brave */
879 SVL_UpdateEntry(struct rx_call *rxcall,
882 struct VldbUpdateEntry *updateentry, /* Update entry copied here */
883 afs_int32 releasetype)
885 int this_op = VLUPDATEENTRY;
887 afs_int32 blockindex, errorcode;
888 struct nvlentry tentry;
889 char rxstr[AFS_RXINFO_LEN];
891 countRequest(this_op);
892 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
894 if ((voltype != -1) && (InvalidVoltype(voltype)))
896 if (releasetype && InvalidReleasetype(releasetype))
897 END(VL_BADRELLOCKTYPE);
898 if ((errorcode = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
901 VLog(1, ("Update Volume %u %s\n", volid, rxinfo(rxstr, rxcall)));
902 blockindex = FindByID(&ctx, volid, voltype, &tentry, &errorcode);
903 if (blockindex == 0) { /* entry not found */
905 errorcode = VL_NOENT;
909 /* Do the actual updating of the entry, tentry. */
911 get_vldbupdateentry(&ctx, blockindex, updateentry, &tentry))) {
915 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
916 if (vlentrywrite(ctx.trans, blockindex, &tentry, sizeof(tentry))) {
919 END(ubik_EndTrans(ctx.trans));
923 ubik_AbortTrans(ctx.trans);
926 osi_auditU(rxcall, VLUpdateEntryEvent, errorcode, AUD_LONG, volid,
933 SVL_UpdateEntryByName(struct rx_call *rxcall,
935 struct VldbUpdateEntry *updateentry, /* Update entry copied here */
936 afs_int32 releasetype)
938 int this_op = VLUPDATEENTRYBYNAME;
940 afs_int32 blockindex, errorcode;
941 struct nvlentry tentry;
943 countRequest(this_op);
944 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
946 if (releasetype && InvalidReleasetype(releasetype))
947 END(VL_BADRELLOCKTYPE);
948 if ((errorcode = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
951 blockindex = FindByName(&ctx, volname, &tentry, &errorcode);
952 if (blockindex == 0) { /* entry not found */
954 errorcode = VL_NOENT;
958 /* Do the actual updating of the entry, tentry. */
960 get_vldbupdateentry(&ctx, blockindex, updateentry, &tentry))) {
964 ReleaseEntry(&tentry, releasetype); /* Unlock entry if necessary */
965 if (vlentrywrite(ctx.trans, blockindex, &tentry, sizeof(tentry))) {
968 END(ubik_EndTrans(ctx.trans));
972 ubik_AbortTrans(ctx.trans);
975 osi_auditU(rxcall, VLUpdateEntryEvent, errorcode, AUD_LONG, -1, AUD_END);
980 /* Set a lock to the vldb entry for volid (of type voltype if not -1). */
982 SVL_SetLock(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype,
985 int this_op = VLSETLOCK;
986 afs_int32 timestamp, blockindex, errorcode;
988 struct nvlentry tentry;
989 char rxstr[AFS_RXINFO_LEN];
991 countRequest(this_op);
992 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
994 if ((voltype != -1) && (InvalidVoltype(voltype)))
996 if (InvalidOperation(voloper))
998 if ((errorcode = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
1001 VLog(1, ("SetLock Volume %u %s\n", volid, rxinfo(rxstr, rxcall)));
1002 blockindex = FindByID(&ctx, volid, voltype, &tentry, &errorcode);
1003 if (blockindex == NULLO) {
1005 errorcode = VL_NOENT;
1008 if (tentry.flags & VLDELETED) {
1009 ABORT(VL_ENTDELETED);
1011 timestamp = FT_ApproxTime();
1013 /* Check if entry is already locked; note that we unlock any entry
1014 * locked more than MAXLOCKTIME seconds */
1015 if ((tentry.LockTimestamp)
1016 && ((timestamp - tentry.LockTimestamp) < MAXLOCKTIME)) {
1017 ABORT(VL_ENTRYLOCKED);
1020 /* Consider it an unlocked entry: set current timestamp, caller
1021 * and active vol operation */
1022 tentry.LockTimestamp = timestamp;
1023 tentry.LockAfsId = 0; /* Not implemented yet */
1024 if (tentry.flags & VLOP_RELEASE) {
1025 ABORT(VL_RERELEASE);
1027 tentry.flags &= ~VLOP_ALLOPERS; /* Clear any possible older operation bit */
1028 tentry.flags |= voloper;
1030 if (vlentrywrite(ctx.trans, blockindex, &tentry, sizeof(tentry))) {
1033 END(ubik_EndTrans(ctx.trans));
1036 countAbort(this_op);
1037 ubik_AbortTrans(ctx.trans);
1040 osi_auditU(rxcall, VLSetLockEvent, errorcode, AUD_LONG, volid, AUD_END);
1045 /* Release an already locked vldb entry. Releasetype determines what
1046 * fields (afsid and/or volume operation) will be cleared along with
1047 * the lock time stamp. */
1050 SVL_ReleaseLock(struct rx_call *rxcall, afs_uint32 volid, afs_int32 voltype,
1051 afs_int32 releasetype)
1053 int this_op = VLRELEASELOCK;
1054 afs_int32 blockindex, errorcode;
1056 struct nvlentry tentry;
1057 char rxstr[AFS_RXINFO_LEN];
1059 countRequest(this_op);
1060 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
1062 if ((voltype != -1) && (InvalidVoltype(voltype)))
1064 if (releasetype && InvalidReleasetype(releasetype))
1065 END(VL_BADRELLOCKTYPE);
1066 if ((errorcode = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
1069 VLog(1, ("ReleaseLock Volume %u %s\n", volid, rxinfo(rxstr, rxcall)));
1070 blockindex = FindByID(&ctx, volid, voltype, &tentry, &errorcode);
1071 if (blockindex == NULLO) {
1073 errorcode = VL_NOENT;
1076 if (tentry.flags & VLDELETED) {
1077 ABORT(VL_ENTDELETED);
1080 ReleaseEntry(&tentry, releasetype); /* Unlock the appropriate fields */
1081 if (vlentrywrite(ctx.trans, blockindex, &tentry, sizeof(tentry))) {
1084 END(ubik_EndTrans(ctx.trans));
1087 countAbort(this_op);
1088 ubik_AbortTrans(ctx.trans);
1091 osi_auditU(rxcall, VLReleaseLockEvent, errorcode, AUD_LONG, volid,
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_ListEntry(struct rx_call *rxcall, afs_int32 previous_index,
1103 afs_int32 *count, afs_int32 *next_index,
1104 struct vldbentry *aentry)
1106 int this_op = VLLISTENTRY;
1109 struct nvlentry tentry;
1110 char rxstr[AFS_RXINFO_LEN];
1112 countRequest(this_op);
1113 if ((errorcode = Init_VLdbase(&ctx, LOCKREAD, this_op)))
1115 VLog(25, ("OListEntry index=%d %s\n", previous_index,
1116 rxinfo(rxstr, rxcall)));
1117 *next_index = NextEntry(&ctx, previous_index, &tentry, count);
1119 vlentry_to_vldbentry(&ctx, &tentry, aentry);
1120 return (ubik_EndTrans(ctx.trans));
1123 /* ListEntry returns a single vldb entry, aentry, with offset previous_index;
1124 * the remaining parameters (i.e. next_index) are used so that sequential
1125 * calls to this routine will get the next (all) vldb entries.
1128 SVL_ListEntryN(struct rx_call *rxcall, afs_int32 previous_index,
1129 afs_int32 *count, afs_int32 *next_index,
1130 struct nvldbentry *aentry)
1132 int this_op = VLLISTENTRYN;
1135 struct nvlentry tentry;
1136 char rxstr[AFS_RXINFO_LEN];
1138 countRequest(this_op);
1139 if ((errorcode = Init_VLdbase(&ctx, LOCKREAD, this_op)))
1141 VLog(25, ("ListEntry index=%d %s\n", previous_index, rxinfo(rxstr, rxcall)));
1142 *next_index = NextEntry(&ctx, previous_index, &tentry, count);
1144 vlentry_to_nvldbentry(&ctx, &tentry, aentry);
1145 return (ubik_EndTrans(ctx.trans));
1149 /* Retrieves in vldbentries all vldb entries that match the specified
1150 * attributes (by server number, partition, volume type, and flag); if volume
1151 * id is specified then the associated list for that entry is returned.
1152 * CAUTION: This could be a very expensive call since in most cases
1153 * sequential search of all vldb entries is performed.
1156 SVL_ListAttributes(struct rx_call *rxcall,
1157 struct VldbListByAttributes *attributes,
1158 afs_int32 *nentries,
1159 bulkentries *vldbentries)
1161 int this_op = VLLISTATTRIBUTES;
1162 int errorcode, allocCount = 0;
1164 struct nvlentry tentry;
1165 struct vldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1167 char rxstr[AFS_RXINFO_LEN];
1169 countRequest(this_op);
1170 vldbentries->bulkentries_val = 0;
1171 vldbentries->bulkentries_len = *nentries = 0;
1172 if ((errorcode = Init_VLdbase(&ctx, LOCKREAD, this_op)))
1174 allocCount = VLDBALLOCCOUNT;
1175 Vldbentry = VldbentryFirst = vldbentries->bulkentries_val =
1176 (vldbentry *) malloc(allocCount * sizeof(vldbentry));
1177 if (Vldbentry == NULL) {
1178 countAbort(this_op);
1179 ubik_AbortTrans(ctx.trans);
1182 VldbentryLast = VldbentryFirst + allocCount;
1183 /* Handle the attribute by volume id totally separate of the rest
1184 * (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!) */
1185 if (attributes->Mask & VLLIST_VOLUMEID) {
1186 afs_int32 blockindex;
1189 FindByID(&ctx, attributes->volumeid, -1, &tentry, &errorcode);
1190 if (blockindex == 0) {
1192 errorcode = VL_NOENT;
1193 countAbort(this_op);
1194 ubik_AbortTrans(ctx.trans);
1195 if (vldbentries->bulkentries_val)
1196 free((char *)vldbentries->bulkentries_val);
1197 vldbentries->bulkentries_val = 0;
1198 vldbentries->bulkentries_len = 0;
1202 put_attributeentry(&ctx, &Vldbentry, &VldbentryFirst, &VldbentryLast,
1203 vldbentries, &tentry, nentries, &allocCount))) {
1204 countAbort(this_op);
1205 ubik_AbortTrans(ctx.trans);
1206 if (vldbentries->bulkentries_val)
1207 free((char *)vldbentries->bulkentries_val);
1208 vldbentries->bulkentries_val = 0;
1209 vldbentries->bulkentries_len = 0;
1210 return VL_SIZEEXCEEDED;
1213 afs_int32 nextblockindex = 0, count = 0, k = 0, match = 0;
1214 while ((nextblockindex =
1215 NextEntry(&ctx, nextblockindex, &tentry, &count))) {
1216 if (++pollcount > 50) {
1217 #ifndef AFS_PTHREAD_ENV
1223 if (attributes->Mask & VLLIST_SERVER) {
1226 IpAddrToRelAddr(&ctx, attributes->server, 0)) == -1)
1228 for (k = 0; k < OMAXNSERVERS; k++) {
1229 if (tentry.serverNumber[k] == BADSERVERID)
1231 if (tentry.serverNumber[k] == serverindex) {
1239 if (attributes->Mask & VLLIST_PARTITION) {
1241 if (tentry.serverPartition[k] != attributes->partition)
1244 for (k = 0; k < OMAXNSERVERS; k++) {
1245 if (tentry.serverNumber[k] == BADSERVERID)
1247 if (tentry.serverPartition[k] ==
1248 attributes->partition) {
1258 if (attributes->Mask & VLLIST_FLAG) {
1259 if (!(tentry.flags & attributes->flag))
1263 put_attributeentry(&ctx, &Vldbentry, &VldbentryFirst,
1264 &VldbentryLast, vldbentries, &tentry,
1265 nentries, &allocCount))) {
1266 countAbort(this_op);
1267 ubik_AbortTrans(ctx.trans);
1268 if (vldbentries->bulkentries_val)
1269 free((char *)vldbentries->bulkentries_val);
1270 vldbentries->bulkentries_val = 0;
1271 vldbentries->bulkentries_len = 0;
1276 if (vldbentries->bulkentries_len
1277 && (allocCount > vldbentries->bulkentries_len)) {
1279 vldbentries->bulkentries_val =
1280 (vldbentry *) realloc(vldbentries->bulkentries_val,
1281 vldbentries->bulkentries_len *
1283 if (vldbentries->bulkentries_val == NULL) {
1284 countAbort(this_op);
1285 ubik_AbortTrans(ctx.trans);
1290 ("ListAttrs nentries=%d %s\n", vldbentries->bulkentries_len,
1291 rxinfo(rxstr, rxcall)));
1292 return (ubik_EndTrans(ctx.trans));
1296 SVL_ListAttributesN(struct rx_call *rxcall,
1297 struct VldbListByAttributes *attributes,
1298 afs_int32 *nentries,
1299 nbulkentries *vldbentries)
1301 int this_op = VLLISTATTRIBUTESN;
1302 int errorcode, allocCount = 0;
1304 struct nvlentry tentry;
1305 struct nvldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1307 char rxstr[AFS_RXINFO_LEN];
1309 countRequest(this_op);
1310 vldbentries->nbulkentries_val = 0;
1311 vldbentries->nbulkentries_len = *nentries = 0;
1312 if ((errorcode = Init_VLdbase(&ctx, LOCKREAD, this_op)))
1314 allocCount = VLDBALLOCCOUNT;
1315 Vldbentry = VldbentryFirst = vldbentries->nbulkentries_val =
1316 (nvldbentry *) malloc(allocCount * sizeof(nvldbentry));
1317 if (Vldbentry == NULL) {
1318 countAbort(this_op);
1319 ubik_AbortTrans(ctx.trans);
1322 VldbentryLast = VldbentryFirst + allocCount;
1323 /* Handle the attribute by volume id totally separate of the rest
1324 * (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!) */
1325 if (attributes->Mask & VLLIST_VOLUMEID) {
1326 afs_int32 blockindex;
1329 FindByID(&ctx, attributes->volumeid, -1, &tentry, &errorcode);
1330 if (blockindex == 0) {
1332 errorcode = VL_NOENT;
1333 countAbort(this_op);
1334 ubik_AbortTrans(ctx.trans);
1335 if (vldbentries->nbulkentries_val)
1336 free((char *)vldbentries->nbulkentries_val);
1337 vldbentries->nbulkentries_val = 0;
1338 vldbentries->nbulkentries_len = 0;
1342 put_nattributeentry(&ctx, &Vldbentry, &VldbentryFirst, &VldbentryLast,
1343 vldbentries, &tentry, 0, 0, nentries,
1345 countAbort(this_op);
1346 ubik_AbortTrans(ctx.trans);
1347 if (vldbentries->nbulkentries_val)
1348 free((char *)vldbentries->nbulkentries_val);
1349 vldbentries->nbulkentries_val = 0;
1350 vldbentries->nbulkentries_len = 0;
1351 return VL_SIZEEXCEEDED;
1354 afs_int32 nextblockindex = 0, count = 0, k = 0, match = 0;
1355 while ((nextblockindex =
1356 NextEntry(&ctx, nextblockindex, &tentry, &count))) {
1357 if (++pollcount > 50) {
1358 #ifndef AFS_PTHREAD_ENV
1365 if (attributes->Mask & VLLIST_SERVER) {
1368 IpAddrToRelAddr(&ctx, attributes->server, 0)) == -1)
1370 for (k = 0; k < NMAXNSERVERS; k++) {
1371 if (tentry.serverNumber[k] == BADSERVERID)
1373 if (tentry.serverNumber[k] == serverindex) {
1381 if (attributes->Mask & VLLIST_PARTITION) {
1383 if (tentry.serverPartition[k] != attributes->partition)
1386 for (k = 0; k < NMAXNSERVERS; k++) {
1387 if (tentry.serverNumber[k] == BADSERVERID)
1389 if (tentry.serverPartition[k] ==
1390 attributes->partition) {
1400 if (attributes->Mask & VLLIST_FLAG) {
1401 if (!(tentry.flags & attributes->flag))
1405 put_nattributeentry(&ctx, &Vldbentry, &VldbentryFirst,
1406 &VldbentryLast, vldbentries, &tentry, 0,
1407 0, nentries, &allocCount))) {
1408 countAbort(this_op);
1409 ubik_AbortTrans(ctx.trans);
1410 if (vldbentries->nbulkentries_val)
1411 free((char *)vldbentries->nbulkentries_val);
1412 vldbentries->nbulkentries_val = 0;
1413 vldbentries->nbulkentries_len = 0;
1418 if (vldbentries->nbulkentries_len
1419 && (allocCount > vldbentries->nbulkentries_len)) {
1421 vldbentries->nbulkentries_val =
1422 (nvldbentry *) realloc(vldbentries->nbulkentries_val,
1423 vldbentries->nbulkentries_len *
1424 sizeof(nvldbentry));
1425 if (vldbentries->nbulkentries_val == NULL) {
1426 countAbort(this_op);
1427 ubik_AbortTrans(ctx.trans);
1432 ("NListAttrs nentries=%d %s\n", vldbentries->nbulkentries_len,
1433 rxinfo(rxstr, rxcall)));
1434 return (ubik_EndTrans(ctx.trans));
1439 SVL_ListAttributesN2(struct rx_call *rxcall,
1440 struct VldbListByAttributes *attributes,
1441 char *name, /* Wildcarded volume name */
1442 afs_int32 startindex,
1443 afs_int32 *nentries,
1444 nbulkentries *vldbentries,
1445 afs_int32 *nextstartindex)
1447 int this_op = VLLISTATTRIBUTESN2;
1448 int errorcode = 0, maxCount = VLDBALLOCCOUNT;
1450 struct nvlentry tentry;
1451 struct nvldbentry *Vldbentry = 0, *VldbentryFirst = 0, *VldbentryLast = 0;
1452 afs_int32 blockindex = 0, count = 0, k, match;
1453 afs_int32 matchindex = 0;
1454 int serverindex = -1; /* no server found */
1455 int findserver = 0, findpartition = 0, findflag = 0, findname = 0;
1457 int namematchRWBK, namematchRO, thismatch;
1459 char volumename[VL_MAXNAMELEN+2]; /* regex anchors */
1460 char rxstr[AFS_RXINFO_LEN];
1461 #ifdef HAVE_POSIX_REGEX
1463 int need_regfree = 0;
1468 countRequest(this_op);
1469 vldbentries->nbulkentries_val = 0;
1470 vldbentries->nbulkentries_len = 0;
1472 *nextstartindex = -1;
1474 errorcode = Init_VLdbase(&ctx, LOCKREAD, this_op);
1478 Vldbentry = VldbentryFirst = vldbentries->nbulkentries_val =
1479 (nvldbentry *) malloc(maxCount * sizeof(nvldbentry));
1480 if (Vldbentry == NULL) {
1481 countAbort(this_op);
1482 ubik_AbortTrans(ctx.trans);
1486 VldbentryLast = VldbentryFirst + maxCount;
1488 /* Handle the attribute by volume id totally separate of the rest
1489 * (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!)
1491 if (attributes->Mask & VLLIST_VOLUMEID) {
1493 FindByID(&ctx, attributes->volumeid, -1, &tentry, &errorcode);
1494 if (blockindex == 0) {
1496 errorcode = VL_NOENT;
1499 put_nattributeentry(&ctx, &Vldbentry, &VldbentryFirst,
1500 &VldbentryLast, vldbentries, &tentry, 0,
1501 0, nentries, &maxCount);
1507 /* Search each entry in the database and return all entries
1508 * that match the request. It checks volumename (with
1509 * wildcarding), entry flags, server, and partition.
1512 /* Get the server index for matching server address */
1513 if (attributes->Mask & VLLIST_SERVER) {
1515 IpAddrToRelAddr(&ctx, attributes->server, 0);
1516 if (serverindex == -1)
1520 findpartition = ((attributes->Mask & VLLIST_PARTITION) ? 1 : 0);
1521 findflag = ((attributes->Mask & VLLIST_FLAG) ? 1 : 0);
1522 if (name && (strcmp(name, ".*") != 0) && (strcmp(name, "") != 0)) {
1523 sprintf(volumename, "^%s$", name);
1524 #ifdef HAVE_POSIX_REGEX
1525 if (regcomp(&re, volumename, REG_NOSUB) != 0) {
1526 errorcode = VL_BADNAME;
1531 t = (char *)re_comp(volumename);
1533 errorcode = VL_BADNAME;
1540 /* Read each entry and see if it is the one we want */
1541 blockindex = startindex;
1542 while ((blockindex = NextEntry(&ctx, blockindex, &tentry, &count))) {
1543 if (++pollcount > 50) {
1544 #ifndef AFS_PTHREAD_ENV
1550 /* Step through each server index searching for a match.
1551 * Match to an existing RW, BK, or RO volume name (preference
1552 * is in this order). Remember which index we matched against.
1554 namematchRWBK = namematchRO = 0; /* 0->notTried; 1->match; 2->noMatch */
1558 && (tentry.serverNumber[k] != BADSERVERID)); k++) {
1559 thismatch = 0; /* does this index match */
1561 /* Match against the RW or BK volume name. Remember
1562 * results in namematchRWBK. Prefer RW over BK.
1564 if (tentry.serverFlags[k] & VLSF_RWVOL) {
1565 /* Does the name match the RW name */
1566 if (tentry.flags & VLF_RWEXISTS) {
1568 sprintf(volumename, "%s", tentry.name);
1569 #ifdef HAVE_POSIX_REGEX
1570 if (regexec(&re, volumename, 0, NULL, 0) == 0) {
1571 thismatch = VLSF_RWVOL;
1574 if (re_exec(volumename)) {
1575 thismatch = VLSF_RWVOL;
1579 thismatch = VLSF_RWVOL;
1583 /* Does the name match the BK name */
1584 if (!thismatch && (tentry.flags & VLF_BACKEXISTS)) {
1586 sprintf(volumename, "%s.backup", tentry.name);
1587 #ifdef HAVE_POSIX_REGEX
1588 if (regexec(&re, volumename, 0, NULL, 0) == 0) {
1589 thismatch = VLSF_BACKVOL;
1592 if (re_exec(volumename)) {
1593 thismatch = VLSF_BACKVOL;
1597 thismatch = VLSF_BACKVOL;
1601 namematchRWBK = (thismatch ? 1 : 2);
1604 /* Match with the RO volume name. Compare once and
1605 * remember results in namematchRO. Note that this will
1606 * pick up entries marked NEWREPSITEs and DONTUSE.
1609 if (tentry.flags & VLF_ROEXISTS) {
1613 ((namematchRO == 1) ? VLSF_ROVOL : 0);
1615 sprintf(volumename, "%s.readonly",
1617 #ifdef HAVE_POSIX_REGEX
1618 if (regexec(&re, volumename, 0, NULL, 0) == 0) {
1619 thismatch = VLSF_ROVOL;
1622 if (re_exec(volumename))
1623 thismatch = VLSF_ROVOL;
1627 thismatch = VLSF_ROVOL;
1630 namematchRO = (thismatch ? 1 : 2);
1633 /* Is there a server match */
1634 if (thismatch && findserver
1635 && (tentry.serverNumber[k] != serverindex))
1638 /* Is there a partition match */
1639 if (thismatch && findpartition
1640 && (tentry.serverPartition[k] != attributes->partition))
1643 /* Is there a flag match */
1644 if (thismatch && findflag
1645 && !(tentry.flags & attributes->flag))
1648 /* We found a match. Remember the index, and type */
1652 matchtype = thismatch;
1655 /* Since we prefer RW and BK volume matches over RO matches,
1656 * if we have already checked the RWBK name, then we already
1657 * found the best match and so end the search.
1659 * If we tried matching against the RW, BK, and RO volume names
1660 * and both failed, then we end the search (none will match).
1662 if ((match && namematchRWBK)
1663 || ((namematchRWBK == 2) && (namematchRO == 2)))
1667 /* Passed all the tests. Take it */
1670 put_nattributeentry(&ctx, &Vldbentry, &VldbentryFirst,
1671 &VldbentryLast, vldbentries, &tentry,
1672 matchtype, matchindex, nentries,
1677 if (*nentries >= maxCount)
1678 break; /* collected the max */
1681 *nextstartindex = (blockindex ? blockindex : -1);
1685 #ifdef HAVE_POSIX_REGEX
1691 countAbort(this_op);
1692 ubik_AbortTrans(ctx.trans);
1693 if (vldbentries->nbulkentries_val)
1694 free((char *)vldbentries->nbulkentries_val);
1695 vldbentries->nbulkentries_val = 0;
1696 vldbentries->nbulkentries_len = 0;
1697 *nextstartindex = -1;
1701 ("N2ListAttrs nentries=%d %s\n", vldbentries->nbulkentries_len,
1702 rxinfo(rxstr, rxcall)));
1703 return (ubik_EndTrans(ctx.trans));
1708 /* Retrieves in vldbentries all vldb entries that match the specified
1709 * attributes (by server number, partition, volume type, and flag); if
1710 * volume id is specified then the associated list for that entry is
1711 * returned. CAUTION: This could be a very expensive call since in most
1712 * cases sequential search of all vldb entries is performed.
1715 SVL_LinkedList(struct rx_call *rxcall,
1716 struct VldbListByAttributes *attributes,
1717 afs_int32 *nentries,
1718 vldb_list *vldbentries)
1720 int this_op = VLLINKEDLIST;
1723 struct nvlentry tentry;
1724 vldblist vllist, *vllistptr;
1725 afs_int32 blockindex, count, match;
1730 countRequest(this_op);
1731 if ((errorcode = Init_VLdbase(&ctx, LOCKREAD, this_op)))
1735 vldbentries->node = NULL;
1736 vllistptr = &vldbentries->node;
1738 /* List by volumeid */
1739 if (attributes->Mask & VLLIST_VOLUMEID) {
1741 FindByID(&ctx, attributes->volumeid, -1, &tentry, &errorcode);
1743 countAbort(this_op);
1744 ubik_AbortTrans(ctx.trans);
1745 return (errorcode ? errorcode : VL_NOENT);
1748 vllist = (single_vldbentry *) malloc(sizeof(single_vldbentry));
1749 if (vllist == NULL) {
1750 countAbort(this_op);
1751 ubik_AbortTrans(ctx.trans);
1754 vlentry_to_vldbentry(&ctx, &tentry, &vllist->VldbEntry);
1755 vllist->next_vldb = NULL;
1757 *vllistptr = vllist; /* Thread onto list */
1758 vllistptr = &vllist->next_vldb;
1762 /* Search by server, partition, and flags */
1764 for (blockindex = NextEntry(&ctx, 0, &tentry, &count); blockindex;
1765 blockindex = NextEntry(&ctx, blockindex, &tentry, &count)) {
1768 if (++pollcount > 50) {
1769 #ifndef AFS_PTHREAD_ENV
1775 /* Does this volume exist on the desired server */
1776 if (attributes->Mask & VLLIST_SERVER) {
1778 IpAddrToRelAddr(&ctx, attributes->server, 0);
1779 if (serverindex == -1)
1781 for (k = 0; k < OMAXNSERVERS; k++) {
1782 if (tentry.serverNumber[k] == BADSERVERID)
1784 if (tentry.serverNumber[k] == serverindex) {
1793 /* Does this volume exist on the desired partition */
1794 if (attributes->Mask & VLLIST_PARTITION) {
1796 if (tentry.serverPartition[k] != attributes->partition)
1799 for (k = 0; k < OMAXNSERVERS; k++) {
1800 if (tentry.serverNumber[k] == BADSERVERID)
1802 if (tentry.serverPartition[k] ==
1803 attributes->partition) {
1813 /* Does this volume have the desired flags */
1814 if (attributes->Mask & VLLIST_FLAG) {
1815 if (!(tentry.flags & attributes->flag))
1819 vllist = (single_vldbentry *) malloc(sizeof(single_vldbentry));
1820 if (vllist == NULL) {
1821 countAbort(this_op);
1822 ubik_AbortTrans(ctx.trans);
1825 vlentry_to_vldbentry(&ctx, &tentry, &vllist->VldbEntry);
1826 vllist->next_vldb = NULL;
1828 *vllistptr = vllist; /* Thread onto list */
1829 vllistptr = &vllist->next_vldb;
1831 if (smallMem && (*nentries >= VLDBALLOCCOUNT)) {
1832 countAbort(this_op);
1833 ubik_AbortTrans(ctx.trans);
1834 return VL_SIZEEXCEEDED;
1839 return (ubik_EndTrans(ctx.trans));
1843 SVL_LinkedListN(struct rx_call *rxcall,
1844 struct VldbListByAttributes *attributes,
1845 afs_int32 *nentries,
1846 nvldb_list *vldbentries)
1848 int this_op = VLLINKEDLISTN;
1851 struct nvlentry tentry;
1852 nvldblist vllist, *vllistptr;
1853 afs_int32 blockindex, count, match;
1858 countRequest(this_op);
1859 if ((errorcode = Init_VLdbase(&ctx, LOCKREAD, this_op)))
1863 vldbentries->node = NULL;
1864 vllistptr = &vldbentries->node;
1866 /* List by volumeid */
1867 if (attributes->Mask & VLLIST_VOLUMEID) {
1869 FindByID(&ctx, attributes->volumeid, -1, &tentry, &errorcode);
1871 countAbort(this_op);
1872 ubik_AbortTrans(ctx.trans);
1873 return (errorcode ? errorcode : VL_NOENT);
1876 vllist = (single_nvldbentry *) malloc(sizeof(single_nvldbentry));
1877 if (vllist == NULL) {
1878 countAbort(this_op);
1879 ubik_AbortTrans(ctx.trans);
1882 vlentry_to_nvldbentry(&ctx, &tentry, &vllist->VldbEntry);
1883 vllist->next_vldb = NULL;
1885 *vllistptr = vllist; /* Thread onto list */
1886 vllistptr = &vllist->next_vldb;
1890 /* Search by server, partition, and flags */
1892 for (blockindex = NextEntry(&ctx, 0, &tentry, &count); blockindex;
1893 blockindex = NextEntry(&ctx, blockindex, &tentry, &count)) {
1896 if (++pollcount > 50) {
1897 #ifndef AFS_PTHREAD_ENV
1903 /* Does this volume exist on the desired server */
1904 if (attributes->Mask & VLLIST_SERVER) {
1906 IpAddrToRelAddr(&ctx, attributes->server, 0);
1907 if (serverindex == -1)
1909 for (k = 0; k < NMAXNSERVERS; k++) {
1910 if (tentry.serverNumber[k] == BADSERVERID)
1912 if (tentry.serverNumber[k] == serverindex) {
1921 /* Does this volume exist on the desired partition */
1922 if (attributes->Mask & VLLIST_PARTITION) {
1924 if (tentry.serverPartition[k] != attributes->partition)
1927 for (k = 0; k < NMAXNSERVERS; k++) {
1928 if (tentry.serverNumber[k] == BADSERVERID)
1930 if (tentry.serverPartition[k] ==
1931 attributes->partition) {
1941 /* Does this volume have the desired flags */
1942 if (attributes->Mask & VLLIST_FLAG) {
1943 if (!(tentry.flags & attributes->flag))
1947 vllist = (single_nvldbentry *) malloc(sizeof(single_nvldbentry));
1948 if (vllist == NULL) {
1949 countAbort(this_op);
1950 ubik_AbortTrans(ctx.trans);
1953 vlentry_to_nvldbentry(&ctx, &tentry, &vllist->VldbEntry);
1954 vllist->next_vldb = NULL;
1956 *vllistptr = vllist; /* Thread onto list */
1957 vllistptr = &vllist->next_vldb;
1959 if (smallMem && (*nentries >= VLDBALLOCCOUNT)) {
1960 countAbort(this_op);
1961 ubik_AbortTrans(ctx.trans);
1962 return VL_SIZEEXCEEDED;
1967 return (ubik_EndTrans(ctx.trans));
1970 /* Get back vldb header statistics (allocs, frees, maxvolumeid,
1971 * totalentries, etc) and dynamic statistics (number of requests and/or
1972 * aborts per remote procedure call, etc)
1975 SVL_GetStats(struct rx_call *rxcall,
1977 vital_vlheader *vital_header)
1979 int this_op = VLGETSTATS;
1980 afs_int32 errorcode;
1982 char rxstr[AFS_RXINFO_LEN];
1984 countRequest(this_op);
1986 /* Allow users to get statistics freely */
1987 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) /* Must be in 'UserList' to use */
1990 if ((errorcode = Init_VLdbase(&ctx, LOCKREAD, this_op)))
1992 VLog(5, ("GetStats %s\n", rxinfo(rxstr, rxcall)));
1993 memcpy((char *)vital_header, (char *)&ctx.cheader->vital_header,
1994 sizeof(vital_vlheader));
1995 memcpy((char *)stats, (char *)&dynamic_statistics, sizeof(vldstats));
1996 return (ubik_EndTrans(ctx.trans));
1999 /* Get the list of file server addresses from the VLDB. Currently it's pretty
2000 * easy to do. In the future, it might require a little bit of grunging
2001 * through the VLDB, but that's life.
2004 SVL_GetAddrs(struct rx_call *rxcall,
2007 struct VLCallBack *spare3,
2008 afs_int32 *nentries,
2011 int this_op = VLGETADDRS;
2012 afs_int32 errorcode;
2017 countRequest(this_op);
2018 addrsp->bulkaddrs_len = *nentries = 0;
2019 addrsp->bulkaddrs_val = 0;
2020 memset(spare3, 0, sizeof(struct VLCallBack));
2022 if ((errorcode = Init_VLdbase(&ctx, LOCKREAD, this_op)))
2025 VLog(5, ("GetAddrs\n"));
2026 addrsp->bulkaddrs_val = taddrp =
2027 (afs_uint32 *) malloc(sizeof(afs_int32) * (MAXSERVERID + 1));
2028 nservers = *nentries = addrsp->bulkaddrs_len = 0;
2031 countAbort(this_op);
2032 ubik_AbortTrans(ctx.trans);
2036 for (i = 0; i <= MAXSERVERID; i++) {
2037 if ((*taddrp = ntohl(ctx.cheader->IpMappedAddr[i]))) {
2043 addrsp->bulkaddrs_len = *nentries = nservers;
2044 return (ubik_EndTrans(ctx.trans));
2047 #define PADDR(addr) VLog(0,("%d.%d.%d.%d", (addr>>24)&0xff, (addr>>16)&0xff, (addr>>8) &0xff, addr&0xff));
2050 SVL_RegisterAddrs(struct rx_call *rxcall, afsUUID *uuidp, afs_int32 spare1,
2053 int this_op = VLREGADDR;
2056 int cnt, h, i, j, k, m, base, index;
2057 struct extentaddr *exp = 0, *tex;
2059 afs_uint32 addrs[VL_MAXIPADDRS_PERMH];
2061 int count, willChangeEntry, foundUuidEntry, willReplaceCnt;
2062 int WillReplaceEntry, WillChange[MAXSERVERID + 1];
2064 int ReplaceEntry = 0;
2067 countRequest(this_op);
2068 if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL))
2070 if ((code = Init_VLdbase(&ctx, LOCKWRITE, this_op)))
2073 /* Eliminate duplicates from IP address list */
2074 for (k = 0, cnt = 0; k < addrsp->bulkaddrs_len; k++) {
2075 if (addrsp->bulkaddrs_val[k] == 0)
2077 for (m = 0; m < cnt; m++) {
2078 if (addrs[m] == addrsp->bulkaddrs_val[k])
2082 if (m == VL_MAXIPADDRS_PERMH) {
2084 ("Number of addresses exceeds %d. Cannot register IP addr 0x%x in VLDB\n",
2085 VL_MAXIPADDRS_PERMH, addrsp->bulkaddrs_val[k]));
2087 addrs[m] = addrsp->bulkaddrs_val[k];
2093 ubik_AbortTrans(ctx.trans);
2094 return VL_INDEXERANGE;
2100 /* For each server registered within the VLDB */
2101 for (srvidx = 0; srvidx <= MAXSERVERID; srvidx++) {
2102 willChangeEntry = 0;
2103 WillReplaceEntry = 1;
2104 if ((ctx.hostaddress[srvidx] & 0xff000000) == 0xff000000) {
2105 /* The server is registered as a multihomed */
2106 base = (ctx.hostaddress[srvidx] >> 16) & 0xff;
2107 index = ctx.hostaddress[srvidx] & 0x0000ffff;
2108 if (base >= VL_MAX_ADDREXTBLKS) {
2110 ("Internal error: Multihome extent base is too large. Base %d index %d\n",
2114 if (index >= VL_MHSRV_PERBLK) {
2116 ("Internal error: Multihome extent index is too large. Base %d index %d\n",
2120 if (!ctx.ex_addr[base]) {
2122 ("Internal error: Multihome extent does not exist. Base %d\n",
2127 /* See if the addresses to register will change this server entry */
2128 exp = &ctx.ex_addr[base][index];
2129 tuuid = exp->ex_hostuuid;
2130 afs_ntohuuid(&tuuid);
2131 if (afs_uuid_equal(uuidp, &tuuid)) {
2135 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2136 if (!exp->ex_addrs[mhidx])
2138 for (k = 0; k < cnt; k++) {
2139 if (ntohl(exp->ex_addrs[mhidx]) == addrs[k]) {
2140 willChangeEntry = 1;
2141 WillChange[count] = srvidx;
2146 WillReplaceEntry = 0;
2150 /* The server is not registered as a multihomed.
2151 * See if the addresses to register will replace this server entry.
2153 for (k = 0; k < cnt; k++) {
2154 if (ctx.hostaddress[srvidx] == addrs[k]) {
2155 willChangeEntry = 1;
2156 WillChange[count] = srvidx;
2157 WillReplaceEntry = 1;
2162 if (willChangeEntry) {
2163 if (WillReplaceEntry) {
2165 ReplaceEntry = srvidx;
2171 /* If we found the uuid in the VLDB and if we are replacing another
2172 * entire entry, then complain and fail. Also, if we did not find
2173 * the uuid in the VLDB and the IP addresses being registered was
2174 * found in more than one other entry, then we don't know which one
2175 * to replace and will complain and fail.
2177 if ((foundUuidEntry && (willReplaceCnt > 0))
2178 || (!foundUuidEntry && (count > 1))) {
2180 ("The following fileserver is being registered in the VLDB:\n"));
2182 for (k = 0; k < cnt; k++) {
2189 if (foundUuidEntry) {
2191 (" It would have replaced the existing VLDB server entry:\n"));
2192 VLog(0, (" entry %d: [", FoundUuid));
2193 base = (ctx.hostaddress[FoundUuid] >> 16) & 0xff;
2194 index = ctx.hostaddress[FoundUuid] & 0x0000ffff;
2195 exp = &ctx.ex_addr[base][index];
2196 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2197 if (!exp->ex_addrs[mhidx])
2201 PADDR(ntohl(exp->ex_addrs[mhidx]));
2207 VLog(0, (" Yet another VLDB server entry exists:\n"));
2209 VLog(0, (" Yet other VLDB server entries exist:\n"));
2210 for (j = 0; j < count; j++) {
2211 srvidx = WillChange[j];
2212 VLog(0, (" entry %d: ", srvidx));
2213 if ((ctx.hostaddress[srvidx] & 0xff000000) == 0xff000000) {
2215 base = (ctx.hostaddress[srvidx] >> 16) & 0xff;
2216 index = ctx.hostaddress[srvidx] & 0x0000ffff;
2217 exp = &ctx.ex_addr[base][index];
2218 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
2219 if (!exp->ex_addrs[mhidx])
2223 PADDR(ntohl(exp->ex_addrs[mhidx]));
2227 PADDR(ctx.hostaddress[srvidx]);
2233 VLog(0, (" You must 'vos changeaddr' this other server entry\n"));
2236 (" You must 'vos changeaddr' these other server entries\n"));
2239 (" and/or remove the sysid file from the registering fileserver\n"));
2240 VLog(0, (" before the fileserver can be registered in the VLDB.\n"));
2242 ubik_AbortTrans(ctx.trans);
2243 return VL_MULTIPADDR;
2246 /* Passed the checks. Now find and update the existing mh entry, or create
2249 if (foundUuidEntry) {
2250 /* Found the entry with same uuid. See if we need to change it */
2253 fbase = (ctx.hostaddress[FoundUuid] >> 16) & 0xff;
2254 index = ctx.hostaddress[FoundUuid] & 0x0000ffff;
2255 exp = &ctx.ex_addr[fbase][index];
2257 /* Determine if the entry has changed */
2258 for (k = 0; ((k < cnt) && !change); k++) {
2259 if (ntohl(exp->ex_addrs[k]) != addrs[k])
2262 for (; ((k < VL_MAXIPADDRS_PERMH) && !change); k++) {
2263 if (exp->ex_addrs[k] != 0)
2267 return (ubik_EndTrans(ctx.trans));
2271 VLog(0, ("The following fileserver is being registered in the VLDB:\n"));
2273 for (k = 0; k < cnt; k++) {
2280 if (foundUuidEntry) {
2282 (" It will replace the following existing entry in the VLDB (same uuid):\n"));
2283 VLog(0, (" entry %d: [", FoundUuid));
2284 for (k = 0; k < VL_MAXIPADDRS_PERMH; k++) {
2285 if (exp->ex_addrs[k] == 0)
2289 PADDR(ntohl(exp->ex_addrs[k]));
2292 } else if (willReplaceCnt || (count == 1)) {
2293 /* If we are not replacing an entry and there is only one entry to change,
2294 * then we will replace that entry.
2296 if (!willReplaceCnt) {
2297 ReplaceEntry = WillChange[0];
2301 /* Have an entry that needs to be replaced */
2302 if ((ctx.hostaddress[ReplaceEntry] & 0xff000000) == 0xff000000) {
2303 fbase = (ctx.hostaddress[ReplaceEntry] >> 16) & 0xff;
2304 index = ctx.hostaddress[ReplaceEntry] & 0x0000ffff;
2305 exp = &ctx.ex_addr[fbase][index];
2308 (" It will replace the following existing entry in the VLDB (new uuid):\n"));
2309 VLog(0, (" entry %d: [", ReplaceEntry));
2310 for (k = 0; k < VL_MAXIPADDRS_PERMH; k++) {
2311 if (exp->ex_addrs[k] == 0)
2315 PADDR(ntohl(exp->ex_addrs[k]));
2319 /* Not a mh entry. So we have to create a new mh entry and
2320 * put it on the ReplaceEntry slot of the ctx.hostaddress array.
2322 VLog(0, (" It will replace existing entry %d, ", ReplaceEntry));
2323 PADDR(ctx.hostaddress[ReplaceEntry]);
2324 VLog(0,(", in the VLDB (new uuid):\n"));
2327 FindExtentBlock(&ctx, uuidp, 1, ReplaceEntry, &exp, &fbase);
2329 ubik_AbortTrans(ctx.trans);
2330 return (code ? code : VL_IO);
2334 /* There is no entry for this server, must create a new mh entry as
2335 * well as use a new slot of the ctx.hostaddress array.
2337 VLog(0, (" It will create a new entry in the VLDB.\n"));
2338 code = FindExtentBlock(&ctx, uuidp, 1, -1, &exp, &fbase);
2340 ubik_AbortTrans(ctx.trans);
2341 return (code ? code : VL_IO);
2345 /* Now we have a mh entry to fill in. Update the uuid, bump the
2346 * uniquifier, and fill in its IP addresses.
2349 afs_htonuuid(&tuuid);
2350 exp->ex_hostuuid = tuuid;
2351 exp->ex_uniquifier = htonl(ntohl(exp->ex_uniquifier) + 1);
2352 for (k = 0; k < cnt; k++) {
2353 exp->ex_addrs[k] = htonl(addrs[k]);
2355 for (; k < VL_MAXIPADDRS_PERMH; k++) {
2356 exp->ex_addrs[k] = 0;
2359 /* Write the new mh entry out */
2362 DOFFSET(ntohl(ctx.ex_addr[0]->ex_contaddrs[fbase]),
2363 (char *)ctx.ex_addr[fbase], (char *)exp), (char *)exp,
2365 ubik_AbortTrans(ctx.trans);
2369 /* Remove any common addresses from other mh entres. We know these entries
2370 * are being changed and not replaced so they are mh entries.
2373 for (i = 0; i < count; i++) {
2376 /* Skip the entry we replaced */
2377 if (willReplaceCnt && (WillChange[i] == ReplaceEntry))
2380 base = (ctx.hostaddress[WillChange[i]] >> 16) & 0xff;
2381 index = ctx.hostaddress[WillChange[i]] & 0x0000ffff;
2382 tex = &ctx.ex_addr[fbase][index];
2386 (" The following existing entries in the VLDB will be updated:\n"));
2388 VLog(0, (" entry %d: [", WillChange[i]));
2389 for (h = j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2390 if (tex->ex_addrs[j]) {
2393 PADDR(ntohl(tex->ex_addrs[j]));
2396 for (k = 0; k < cnt; k++) {
2397 if (ntohl(tex->ex_addrs[j]) == addrs[k])
2401 /* Not found, so we keep it */
2402 tex->ex_addrs[h] = tex->ex_addrs[j];
2406 for (j = h; j < VL_MAXIPADDRS_PERMH; j++) {
2407 tex->ex_addrs[j] = 0; /* zero rest of mh entry */
2411 /* Write out the modified mh entry */
2412 tex->ex_uniquifier = htonl(ntohl(tex->ex_uniquifier) + 1);
2414 DOFFSET(ntohl(ctx.ex_addr[0]->ex_contaddrs[base]),
2415 (char *)ctx.ex_addr[base], (char *)tex);
2416 if (vlwrite(ctx.trans, doff, (char *)tex, sizeof(*tex))) {
2417 ubik_AbortTrans(ctx.trans);
2422 return (ubik_EndTrans(ctx.trans));
2426 SVL_GetAddrsU(struct rx_call *rxcall,
2427 struct ListAddrByAttributes *attributes,
2429 afs_int32 *uniquifier,
2430 afs_int32 *nentries,
2433 int this_op = VLGETADDRSU;
2434 afs_int32 errorcode, index = -1, offset;
2436 int nservers, i, j, base = 0;
2437 struct extentaddr *exp = 0;
2439 afs_uint32 *taddrp, taddr;
2440 char rxstr[AFS_RXINFO_LEN];
2442 countRequest(this_op);
2443 addrsp->bulkaddrs_len = *nentries = 0;
2444 addrsp->bulkaddrs_val = 0;
2445 VLog(5, ("GetAddrsU %s\n", rxinfo(rxstr, rxcall)));
2446 if ((errorcode = Init_VLdbase(&ctx, LOCKREAD, this_op)))
2449 if (attributes->Mask & VLADDR_IPADDR) {
2450 if (attributes->Mask & (VLADDR_INDEX | VLADDR_UUID)) {
2451 ubik_AbortTrans(ctx.trans);
2454 for (base = 0; base < VL_MAX_ADDREXTBLKS; base++) {
2455 if (!ctx.ex_addr[base])
2457 for (i = 1; i < VL_MHSRV_PERBLK; i++) {
2458 exp = &ctx.ex_addr[base][i];
2459 tuuid = exp->ex_hostuuid;
2460 afs_ntohuuid(&tuuid);
2461 if (afs_uuid_is_nil(&tuuid))
2463 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
2464 if (exp->ex_addrs[j]
2465 && (ntohl(exp->ex_addrs[j]) == attributes->ipaddr)) {
2469 if (j < VL_MAXIPADDRS_PERMH)
2472 if (i < VL_MHSRV_PERBLK)
2475 if (base >= VL_MAX_ADDREXTBLKS) {
2476 ubik_AbortTrans(ctx.trans);
2479 } else if (attributes->Mask & VLADDR_INDEX) {
2480 if (attributes->Mask & (VLADDR_IPADDR | VLADDR_UUID)) {
2481 ubik_AbortTrans(ctx.trans);
2484 index = attributes->index;
2485 if (index < 1 || index >= (VL_MAX_ADDREXTBLKS * VL_MHSRV_PERBLK)) {
2486 ubik_AbortTrans(ctx.trans);
2487 return VL_INDEXERANGE;
2489 base = index / VL_MHSRV_PERBLK;
2490 offset = index % VL_MHSRV_PERBLK;
2492 ubik_AbortTrans(ctx.trans);
2495 if (!ctx.ex_addr[base]) {
2496 ubik_AbortTrans(ctx.trans);
2497 return VL_INDEXERANGE;
2499 exp = &ctx.ex_addr[base][offset];
2500 } else if (attributes->Mask & VLADDR_UUID) {
2501 if (attributes->Mask & (VLADDR_IPADDR | VLADDR_INDEX)) {
2502 ubik_AbortTrans(ctx.trans);
2505 if (!ctx.ex_addr[0]) { /* mh servers probably aren't setup on this vldb */
2506 ubik_AbortTrans(ctx.trans);
2510 FindExtentBlock(&ctx, &attributes->uuid, 0, -1, &exp, &base))) {
2511 ubik_AbortTrans(ctx.trans);
2515 ubik_AbortTrans(ctx.trans);
2520 ubik_AbortTrans(ctx.trans);
2523 addrsp->bulkaddrs_val = taddrp =
2524 (afs_uint32 *) malloc(sizeof(afs_int32) * (MAXSERVERID + 1));
2525 nservers = *nentries = addrsp->bulkaddrs_len = 0;
2527 countAbort(this_op);
2528 ubik_AbortTrans(ctx.trans);
2531 tuuid = exp->ex_hostuuid;
2532 afs_ntohuuid(&tuuid);
2533 if (afs_uuid_is_nil(&tuuid)) {
2534 ubik_AbortTrans(ctx.trans);
2540 *uniquifier = ntohl(exp->ex_uniquifier);
2541 for (i = 0; i < VL_MAXIPADDRS_PERMH; i++) {
2542 if (exp->ex_addrs[i]) {
2543 taddr = ntohl(exp->ex_addrs[i]);
2544 /* Weed out duplicates */
2545 for (j = 0; j < nservers; j++) {
2546 if (taddrp[j] == taddr)
2549 if ((j == nservers) && (j <= MAXSERVERID)) {
2550 taddrp[nservers] = taddr;
2555 addrsp->bulkaddrs_len = *nentries = nservers;
2556 return (ubik_EndTrans(ctx.trans));
2559 /* ============> End of Exported vldb RPC functions <============= */
2562 /* Routine that copies the given vldb entry to the output buffer, vldbentries. */
2564 put_attributeentry(struct vl_ctx *ctx,
2565 struct vldbentry **Vldbentry,
2566 struct vldbentry **VldbentryFirst,
2567 struct vldbentry **VldbentryLast,
2568 bulkentries *vldbentries,
2569 struct nvlentry *entry,
2570 afs_int32 *nentries,
2571 afs_int32 *alloccnt)
2576 if (*Vldbentry == *VldbentryLast) {
2578 return VL_SIZEEXCEEDED; /* no growing if smallMem defined */
2580 /* Allocate another set of memory; each time allocate twice as
2581 * many blocks as the last time. When we reach VLDBALLOCLIMIT,
2582 * then grow in increments of VLDBALLOCINCR.
2584 allo = (*alloccnt > VLDBALLOCLIMIT) ? VLDBALLOCINCR : *alloccnt;
2586 (vldbentry *) realloc(*VldbentryFirst,
2587 (*alloccnt + allo) * sizeof(vldbentry));
2591 *VldbentryFirst = vldbentries->bulkentries_val = reall;
2592 *Vldbentry = *VldbentryFirst + *alloccnt;
2593 *VldbentryLast = *Vldbentry + allo;
2596 vlentry_to_vldbentry(ctx, entry, *Vldbentry);
2599 vldbentries->bulkentries_len++;
2604 put_nattributeentry(struct vl_ctx *ctx,
2605 struct nvldbentry **Vldbentry,
2606 struct nvldbentry **VldbentryFirst,
2607 struct nvldbentry **VldbentryLast,
2608 nbulkentries *vldbentries,
2609 struct nvlentry *entry,
2610 afs_int32 matchtype,
2611 afs_int32 matchindex,
2612 afs_int32 *nentries,
2613 afs_int32 *alloccnt)
2618 if (*Vldbentry == *VldbentryLast) {
2620 return VL_SIZEEXCEEDED; /* no growing if smallMem defined */
2622 /* Allocate another set of memory; each time allocate twice as
2623 * many blocks as the last time. When we reach VLDBALLOCLIMIT,
2624 * then grow in increments of VLDBALLOCINCR.
2626 allo = (*alloccnt > VLDBALLOCLIMIT) ? VLDBALLOCINCR : *alloccnt;
2628 (nvldbentry *) realloc(*VldbentryFirst,
2629 (*alloccnt + allo) * sizeof(nvldbentry));
2633 *VldbentryFirst = vldbentries->nbulkentries_val = reall;
2634 *Vldbentry = *VldbentryFirst + *alloccnt;
2635 *VldbentryLast = *Vldbentry + allo;
2638 vlentry_to_nvldbentry(ctx, entry, *Vldbentry);
2639 (*Vldbentry)->matchindex = (matchtype << 16) + matchindex;
2642 vldbentries->nbulkentries_len++;
2647 /* Common code to actually remove a vldb entry from the database. */
2649 RemoveEntry(struct vl_ctx *ctx, afs_int32 entryptr,
2650 struct nvlentry *tentry)
2654 if ((errorcode = UnthreadVLentry(ctx, entryptr, tentry)))
2656 if ((errorcode = FreeBlock(ctx, entryptr)))
2662 ReleaseEntry(struct nvlentry *tentry, afs_int32 releasetype)
2664 if (releasetype & LOCKREL_TIMESTAMP)
2665 tentry->LockTimestamp = 0;
2666 if (releasetype & LOCKREL_OPCODE)
2667 tentry->flags &= ~VLOP_ALLOPERS;
2668 if (releasetype & LOCKREL_AFSID)
2669 tentry->LockAfsId = 0;
2673 /* Verify that the incoming vldb entry is valid; multi type of error codes
2676 check_vldbentry(struct vldbentry *aentry)
2680 if (InvalidVolname(aentry->name))
2682 if (aentry->nServers <= 0 || aentry->nServers > OMAXNSERVERS)
2683 return VL_BADSERVER;
2684 for (i = 0; i < aentry->nServers; i++) {
2685 /* if (aentry->serverNumber[i] < 0 || aentry->serverNumber[i] > MAXSERVERID)
2686 return VL_BADSERVER; */
2687 if (aentry->serverPartition[i] < 0
2688 || aentry->serverPartition[i] > MAXPARTITIONID)
2689 return VL_BADPARTITION;
2690 if (aentry->serverFlags[i] < 0
2691 || aentry->serverFlags[i] > MAXSERVERFLAG)
2692 return VL_BADSERVERFLAG;
2698 check_nvldbentry(struct nvldbentry *aentry)
2702 if (InvalidVolname(aentry->name))
2704 if (aentry->nServers <= 0 || aentry->nServers > NMAXNSERVERS)
2705 return VL_BADSERVER;
2706 for (i = 0; i < aentry->nServers; i++) {
2707 /* if (aentry->serverNumber[i] < 0 || aentry->serverNumber[i] > MAXSERVERID)
2708 return VL_BADSERVER; */
2709 if (aentry->serverPartition[i] < 0
2710 || aentry->serverPartition[i] > MAXPARTITIONID)
2711 return VL_BADPARTITION;
2712 if (aentry->serverFlags[i] < 0
2713 || aentry->serverFlags[i] > MAXSERVERFLAG)
2714 return VL_BADSERVERFLAG;
2720 /* Convert from the external vldb entry representation to its internal
2721 (more compact) form. This call should not change the hash chains! */
2723 vldbentry_to_vlentry(struct vl_ctx *ctx,
2724 struct vldbentry *VldbEntry,
2725 struct nvlentry *VlEntry)
2729 if (strcmp(VlEntry->name, VldbEntry->name))
2730 strncpy(VlEntry->name, VldbEntry->name, sizeof(VlEntry->name));
2731 for (i = 0; i < VldbEntry->nServers; i++) {
2732 serverindex = IpAddrToRelAddr(ctx, VldbEntry->serverNumber[i], 1);
2733 if (serverindex == -1)
2734 return VL_BADSERVER;
2735 VlEntry->serverNumber[i] = serverindex;
2736 VlEntry->serverPartition[i] = VldbEntry->serverPartition[i];
2737 VlEntry->serverFlags[i] = VldbEntry->serverFlags[i];
2739 for (; i < OMAXNSERVERS; i++)
2740 VlEntry->serverNumber[i] = VlEntry->serverPartition[i] =
2741 VlEntry->serverFlags[i] = BADSERVERID;
2742 for (i = 0; i < MAXTYPES; i++)
2743 VlEntry->volumeId[i] = VldbEntry->volumeId[i];
2744 VlEntry->cloneId = VldbEntry->cloneId;
2745 VlEntry->flags = VldbEntry->flags;
2750 nvldbentry_to_vlentry(struct vl_ctx *ctx,
2751 struct nvldbentry *VldbEntry,
2752 struct nvlentry *VlEntry)
2756 if (strcmp(VlEntry->name, VldbEntry->name))
2757 strncpy(VlEntry->name, VldbEntry->name, sizeof(VlEntry->name));
2758 for (i = 0; i < VldbEntry->nServers; i++) {
2759 serverindex = IpAddrToRelAddr(ctx, VldbEntry->serverNumber[i], 1);
2760 if (serverindex == -1)
2761 return VL_BADSERVER;
2762 VlEntry->serverNumber[i] = serverindex;
2763 VlEntry->serverPartition[i] = VldbEntry->serverPartition[i];
2764 VlEntry->serverFlags[i] = VldbEntry->serverFlags[i];
2766 for (; i < NMAXNSERVERS; i++)
2767 VlEntry->serverNumber[i] = VlEntry->serverPartition[i] =
2768 VlEntry->serverFlags[i] = BADSERVERID;
2769 for (i = 0; i < MAXTYPES; i++)
2770 VlEntry->volumeId[i] = VldbEntry->volumeId[i];
2771 VlEntry->cloneId = VldbEntry->cloneId;
2772 VlEntry->flags = VldbEntry->flags;
2777 /* Update the vldb entry with the new fields as indicated by the value of
2778 * the Mask entry in the updateentry structure. All necessary validation
2779 * checks are performed.
2782 get_vldbupdateentry(struct vl_ctx *ctx,
2783 afs_int32 blockindex,
2784 struct VldbUpdateEntry *updateentry,
2785 struct nvlentry *VlEntry)
2787 int i, j, errorcode, serverindex;
2788 afs_uint32 checkids[MAXTYPES];
2790 /* check if any specified new IDs are already present in the db. Do
2791 * this check before doing anything else, so we don't get a half-
2793 memset(&checkids, 0, sizeof(checkids));
2794 if (updateentry->Mask & VLUPDATE_RWID) {
2795 checkids[RWVOL] = updateentry->spares3; /* rw id */
2797 if (updateentry->Mask & VLUPDATE_READONLYID) {
2798 checkids[ROVOL] = updateentry->ReadOnlyId;
2800 if (updateentry->Mask & VLUPDATE_BACKUPID) {
2801 checkids[BACKVOL] = updateentry->BackupId;
2804 if (EntryIDExists(ctx, checkids, MAXTYPES, &errorcode)) {
2806 } else if (errorcode) {
2810 if (updateentry->Mask & VLUPDATE_VOLUMENAME) {
2811 struct nvlentry tentry;
2813 if (InvalidVolname(updateentry->name))
2816 if (FindByName(ctx, updateentry->name, &tentry, &errorcode)) {
2817 return VL_NAMEEXIST;
2818 } else if (errorcode) {
2822 if ((errorcode = UnhashVolname(ctx, blockindex, VlEntry)))
2824 strncpy(VlEntry->name, updateentry->name, sizeof(VlEntry->name));
2825 HashVolname(ctx, blockindex, VlEntry);
2828 if (updateentry->Mask & VLUPDATE_VOLNAMEHASH) {
2829 if ((errorcode = UnhashVolname(ctx, blockindex, VlEntry))) {
2830 if (errorcode != VL_NOENT)
2833 HashVolname(ctx, blockindex, VlEntry);
2836 if (updateentry->Mask & VLUPDATE_FLAGS) {
2837 VlEntry->flags = updateentry->flags;
2839 if (updateentry->Mask & VLUPDATE_CLONEID) {
2840 VlEntry->cloneId = updateentry->cloneId;
2842 if (updateentry->Mask & VLUPDATE_RWID) {
2843 if ((errorcode = UnhashVolid(ctx, RWVOL, blockindex, VlEntry))) {
2844 if (errorcode != VL_NOENT)
2847 VlEntry->volumeId[RWVOL] = updateentry->spares3; /* rw id */
2848 if ((errorcode = HashVolid(ctx, RWVOL, blockindex, VlEntry)))
2851 if (updateentry->Mask & VLUPDATE_READONLYID) {
2852 if ((errorcode = UnhashVolid(ctx, ROVOL, blockindex, VlEntry))) {
2853 if (errorcode != VL_NOENT)
2856 VlEntry->volumeId[ROVOL] = updateentry->ReadOnlyId;
2857 if ((errorcode = HashVolid(ctx, ROVOL, blockindex, VlEntry)))
2860 if (updateentry->Mask & VLUPDATE_BACKUPID) {
2861 if ((errorcode = UnhashVolid(ctx, BACKVOL, blockindex, VlEntry))) {
2862 if (errorcode != VL_NOENT)
2865 VlEntry->volumeId[BACKVOL] = updateentry->BackupId;
2866 if ((errorcode = HashVolid(ctx, BACKVOL, blockindex, VlEntry)))
2869 if (updateentry->Mask & VLUPDATE_REPSITES) {
2870 if (updateentry->nModifiedRepsites <= 0
2871 || updateentry->nModifiedRepsites > OMAXNSERVERS)
2872 return VL_BADSERVER;
2873 for (i = 0; i < updateentry->nModifiedRepsites; i++) {
2874 /* if (updateentry->RepsitesTargetServer[i] < 0 || updateentry->RepsitesTargetServer[i] > MAXSERVERID)
2875 return VL_BADSERVER; */
2876 if (updateentry->RepsitesTargetPart[i] < 0
2877 || updateentry->RepsitesTargetPart[i] > MAXPARTITIONID)
2878 return VL_BADPARTITION;
2879 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_DELETE) {
2881 repsite_exists(VlEntry,
2882 IpAddrToRelAddr(ctx, updateentry->
2883 RepsitesTargetServer[i],
2885 updateentry->RepsitesTargetPart[i])) !=
2887 repsite_compress(VlEntry, j);
2889 return VL_NOREPSERVER;
2891 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_ADD) {
2892 /* if (updateentry->RepsitesNewServer[i] < 0 || updateentry->RepsitesNewServer[i] > MAXSERVERID)
2893 return VL_BADSERVER; */
2894 if (updateentry->RepsitesNewPart[i] < 0
2895 || updateentry->RepsitesNewPart[i] > MAXPARTITIONID)
2896 return VL_BADPARTITION;
2899 IpAddrToRelAddr(ctx, updateentry->RepsitesNewServer[i], 1),
2900 updateentry->RepsitesNewPart[i]) != -1)
2901 return VL_DUPREPSERVER;
2903 VlEntry->serverNumber[j] != BADSERVERID
2904 && j < OMAXNSERVERS; j++);
2905 if (j >= OMAXNSERVERS)
2908 IpAddrToRelAddr(ctx, updateentry->RepsitesNewServer[i],
2910 return VL_BADSERVER;
2911 VlEntry->serverNumber[j] = serverindex;
2912 VlEntry->serverPartition[j] = updateentry->RepsitesNewPart[i];
2913 if (updateentry->RepsitesNewFlags[i] < 0
2914 || updateentry->RepsitesNewFlags[i] > MAXSERVERFLAG)
2915 return VL_BADSERVERFLAG;
2916 VlEntry->serverFlags[j] = updateentry->RepsitesNewFlags[i];
2918 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODSERV) {
2919 /*n if (updateentry->RepsitesNewServer[i] < 0 || updateentry->RepsitesNewServer[i] > MAXSERVERID)
2920 return VL_BADSERVER; */
2922 repsite_exists(VlEntry,
2923 IpAddrToRelAddr(ctx, updateentry->
2924 RepsitesTargetServer[i],
2926 updateentry->RepsitesTargetPart[i])) !=
2928 VlEntry->serverNumber[j] =
2929 IpAddrToRelAddr(ctx, updateentry->RepsitesNewServer[i],
2932 return VL_NOREPSERVER;
2934 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODPART) {
2935 if (updateentry->RepsitesNewPart[i] < 0
2936 || updateentry->RepsitesNewPart[i] > MAXPARTITIONID)
2937 return VL_BADPARTITION;
2939 repsite_exists(VlEntry,
2940 IpAddrToRelAddr(ctx, updateentry->
2941 RepsitesTargetServer[i],
2943 updateentry->RepsitesTargetPart[i])) !=
2945 VlEntry->serverPartition[j] =
2946 updateentry->RepsitesNewPart[i];
2948 return VL_NOREPSERVER;
2950 if (updateentry->RepsitesMask[i] & VLUPDATE_REPS_MODFLAG) {
2952 repsite_exists(VlEntry,
2953 IpAddrToRelAddr(ctx, updateentry->
2954 RepsitesTargetServer[i],
2956 updateentry->RepsitesTargetPart[i])) !=
2958 if (updateentry->RepsitesNewFlags[i] < 0
2959 || updateentry->RepsitesNewFlags[i] > MAXSERVERFLAG)
2960 return VL_BADSERVERFLAG;
2961 VlEntry->serverFlags[j] =
2962 updateentry->RepsitesNewFlags[i];
2964 return VL_NOREPSERVER;
2972 /* Check if the specified [server,partition] entry is found in the vldb
2973 * entry's repsite table; it's offset in the table is returned, if it's
2976 repsite_exists(struct nvlentry *VlEntry, int server, int partition)
2980 for (i = 0; VlEntry->serverNumber[i] != BADSERVERID && i < OMAXNSERVERS;
2982 if ((VlEntry->serverNumber[i] == server)
2983 && (VlEntry->serverPartition[i] == partition))
2991 /* Repsite table compression: used when deleting a repsite entry so that
2992 * all active repsite entries are on the top of the table. */
2994 repsite_compress(struct nvlentry *VlEntry, int offset)
2996 int repsite_offset = offset;
2998 VlEntry->serverNumber[repsite_offset] != BADSERVERID
2999 && repsite_offset < OMAXNSERVERS - 1; repsite_offset++) {
3000 VlEntry->serverNumber[repsite_offset] =
3001 VlEntry->serverNumber[repsite_offset + 1];
3002 VlEntry->serverPartition[repsite_offset] =
3003 VlEntry->serverPartition[repsite_offset + 1];
3004 VlEntry->serverFlags[repsite_offset] =
3005 VlEntry->serverFlags[repsite_offset + 1];
3007 VlEntry->serverNumber[repsite_offset] = BADSERVERID;
3011 /* Convert from the internal (compacted) vldb entry to the external
3012 * representation used by the interface. */
3014 vlentry_to_vldbentry(struct vl_ctx *ctx, struct nvlentry *VlEntry,
3015 struct vldbentry *VldbEntry)
3019 memset(VldbEntry, 0, sizeof(struct vldbentry));
3020 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
3021 for (i = 0; i < OMAXNSERVERS; i++) {
3022 if (VlEntry->serverNumber[i] == BADSERVERID)
3024 if ((ctx->hostaddress[j = VlEntry->serverNumber[i]] & 0xff000000) ==
3026 struct extentaddr *exp;
3029 base = (ctx->hostaddress[j] >> 16) & 0xff;
3030 index = ctx->hostaddress[j] & 0x0000ffff;
3031 exp = &ctx->ex_addr[base][index];
3032 /* For now return the first ip address back */
3033 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
3034 if (exp->ex_addrs[j]) {
3035 VldbEntry->serverNumber[i] = ntohl(exp->ex_addrs[j]);
3040 VldbEntry->serverNumber[i] =
3041 ctx->hostaddress[VlEntry->serverNumber[i]];
3042 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
3043 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
3045 VldbEntry->nServers = i;
3046 for (i = 0; i < MAXTYPES; i++)
3047 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
3048 VldbEntry->cloneId = VlEntry->cloneId;
3049 VldbEntry->flags = VlEntry->flags;
3053 /* Convert from the internal (compacted) vldb entry to the external
3054 * representation used by the interface. */
3056 vlentry_to_nvldbentry(struct vl_ctx *ctx, struct nvlentry *VlEntry,
3057 struct nvldbentry *VldbEntry)
3061 memset(VldbEntry, 0, sizeof(struct vldbentry));
3062 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
3063 for (i = 0; i < NMAXNSERVERS; i++) {
3064 if (VlEntry->serverNumber[i] == BADSERVERID)
3066 if ((ctx->hostaddress[j = VlEntry->serverNumber[i]] & 0xff000000) ==
3068 struct extentaddr *exp;
3071 base = (ctx->hostaddress[j] >> 16) & 0xff;
3072 index = ctx->hostaddress[j] & 0x0000ffff;
3073 exp = &ctx->ex_addr[base][index];
3074 /* For now return the first ip address back */
3075 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
3076 if (exp->ex_addrs[j]) {
3077 VldbEntry->serverNumber[i] = ntohl(exp->ex_addrs[j]);
3082 VldbEntry->serverNumber[i] =
3083 ctx->hostaddress[VlEntry->serverNumber[i]];
3084 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
3085 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
3087 VldbEntry->nServers = i;
3088 for (i = 0; i < MAXTYPES; i++)
3089 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
3090 VldbEntry->cloneId = VlEntry->cloneId;
3091 VldbEntry->flags = VlEntry->flags;
3095 vlentry_to_uvldbentry(struct vl_ctx *ctx, struct nvlentry *VlEntry,
3096 struct uvldbentry *VldbEntry)
3100 memset(VldbEntry, 0, sizeof(struct vldbentry));
3101 strncpy(VldbEntry->name, VlEntry->name, sizeof(VldbEntry->name));
3102 for (i = 0; i < NMAXNSERVERS; i++) {
3103 if (VlEntry->serverNumber[i] == BADSERVERID)
3105 VldbEntry->serverFlags[i] = VlEntry->serverFlags[i];
3106 VldbEntry->serverUnique[i] = 0;
3107 if ((ctx->hostaddress[j = VlEntry->serverNumber[i]] & 0xff000000) ==
3109 struct extentaddr *exp;
3113 base = (ctx->hostaddress[j] >> 16) & 0xff;
3114 index = ctx->hostaddress[j] & 0x0000ffff;
3115 exp = &ctx->ex_addr[base][index];
3116 tuuid = exp->ex_hostuuid;
3117 afs_ntohuuid(&tuuid);
3118 VldbEntry->serverFlags[i] |= VLSERVER_FLAG_UUID;
3119 VldbEntry->serverNumber[i] = tuuid;
3120 VldbEntry->serverUnique[i] = ntohl(exp->ex_uniquifier);
3122 VldbEntry->serverNumber[i].time_low =
3123 ctx->hostaddress[VlEntry->serverNumber[i]];
3125 VldbEntry->serverPartition[i] = VlEntry->serverPartition[i];
3128 VldbEntry->nServers = i;
3129 for (i = 0; i < MAXTYPES; i++)
3130 VldbEntry->volumeId[i] = VlEntry->volumeId[i];
3131 VldbEntry->cloneId = VlEntry->cloneId;
3132 VldbEntry->flags = VlEntry->flags;
3135 #define LEGALCHARS ".ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
3138 /* Verify that the volname is a valid volume name. */
3140 InvalidVolname(char *volname)
3146 slen = strlen(volname);
3147 if (slen >= VL_MAXNAMELEN)
3149 return (slen != strspn(volname, map));
3153 /* Verify that the given volume type is valid. */
3155 InvalidVoltype(afs_int32 voltype)
3157 if (voltype != RWVOL && voltype != ROVOL && voltype != BACKVOL)
3164 InvalidOperation(afs_int32 voloper)
3166 if (voloper != VLOP_MOVE && voloper != VLOP_RELEASE
3167 && voloper != VLOP_BACKUP && voloper != VLOP_DELETE
3168 && voloper != VLOP_DUMP)
3174 InvalidReleasetype(afs_int32 releasetype)
3176 if ((releasetype & LOCKREL_TIMESTAMP) || (releasetype & LOCKREL_OPCODE)
3177 || (releasetype & LOCKREL_AFSID))
3183 IpAddrToRelAddr(struct vl_ctx *ctx, afs_uint32 ipaddr, int create)
3186 afs_int32 code, base, index;
3187 struct extentaddr *exp;
3189 for (i = 0; i <= MAXSERVERID; i++) {
3190 if (ctx->hostaddress[i] == ipaddr)
3192 if ((ctx->hostaddress[i] & 0xff000000) == 0xff000000) {
3193 base = (ctx->hostaddress[i] >> 16) & 0xff;
3194 index = ctx->hostaddress[i] & 0x0000ffff;
3195 if (base >= VL_MAX_ADDREXTBLKS) {
3197 ("Internal error: Multihome extent base is too large. Base %d index %d\n",
3199 return -1; /* EINVAL */
3201 if (index >= VL_MHSRV_PERBLK) {
3203 ("Internal error: Multihome extent index is too large. Base %d index %d\n",
3205 return -1; /* EINVAL */
3207 if (!ctx->ex_addr[base]) {
3209 ("Internal error: Multihome extent does not exist. Base %d\n",
3211 return -1; /* EINVAL */
3213 exp = &ctx->ex_addr[base][index];
3214 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
3215 if (exp->ex_addrs[j] && (ntohl(exp->ex_addrs[j]) == ipaddr)) {
3222 /* allocate the new server a server id pronto */
3224 for (i = 0; i <= MAXSERVERID; i++) {
3225 if (ctx->cheader->IpMappedAddr[i] == 0) {
3226 ctx->cheader->IpMappedAddr[i] = htonl(ipaddr);
3229 DOFFSET(0, ctx->cheader, &ctx->cheader->IpMappedAddr[i]),
3230 (char *)&ctx->cheader->IpMappedAddr[i],
3232 ctx->hostaddress[i] = ipaddr;
3243 ChangeIPAddr(struct vl_ctx *ctx, afs_uint32 ipaddr1, afs_uint32 ipaddr2)
3247 struct extentaddr *exp = NULL;
3251 afs_int32 blockindex, count;
3253 struct nvlentry tentry;
3254 int ipaddr1_id = -1, ipaddr2_id = -1;
3256 /* Don't let addr change to 256.*.*.* : Causes internal error below */
3257 if ((ipaddr2 & 0xff000000) == 0xff000000)
3258 return (VL_BADSERVER);
3260 /* If we are removing an address, ip1 will be -1 and ip2 will be
3261 * the original address. This prevents an older revision vlserver
3262 * from removing the IP address (won't find server 0xfffffff in
3263 * the VLDB). An older revision vlserver does not have the check
3264 * to see if any volumes exist on the server being removed.
3266 if (ipaddr1 == 0xffffffff) {
3271 for (i = 0; i <= MAXSERVERID; i++) {
3272 if ((ctx->hostaddress[i] & 0xff000000) == 0xff000000) {
3273 base = (ctx->hostaddress[i] >> 16) & 0xff;
3274 index = ctx->hostaddress[i] & 0x0000ffff;
3275 if ((base >= VL_MAX_ADDREXTBLKS) || (index >= VL_MHSRV_PERBLK)) {
3277 ("Internal error: Multihome extent addr is too large. Base %d index %d\n",
3279 return -1; /* EINVAL */
3282 exp = &ctx->ex_addr[base][index];
3283 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
3284 if (!exp->ex_addrs[mhidx])
3286 if (ntohl(exp->ex_addrs[mhidx]) == ipaddr1) {
3289 if (ipaddr2 != 0 && ntohl(exp->ex_addrs[mhidx]) == ipaddr2) {
3294 if (ctx->hostaddress[i] == ipaddr1) {
3298 if (ipaddr2 != 0 && ctx->hostaddress[i] == ipaddr2) {
3303 if (ipaddr1_id >= 0 && (ipaddr2 == 0 || ipaddr2_id >= 0)) {
3304 /* we've either found both IPs already in the VLDB, or we found
3305 * ipaddr1, and we're not going to find ipaddr2 because it's 0 */
3310 if (ipaddr1_id < 0) {
3311 return VL_NOENT; /* not found */
3314 if (ipaddr2_id >= 0 && ipaddr2_id != ipaddr1_id) {
3315 char buf1[16], buf2[16];
3316 VLog(0, ("Cannot change IP address from %s to %s because the latter "
3317 "is in use by server id %d\n",
3318 afs_inet_ntoa_r(htonl(ipaddr1), buf1),
3319 afs_inet_ntoa_r(htonl(ipaddr2), buf2),
3321 return VL_MULTIPADDR;
3324 /* If we are removing a server entry, a volume cannot
3325 * exist on the server. If one does, don't remove the
3326 * server entry: return error "volume entry exists".
3329 for (blockindex = NextEntry(ctx, 0, &tentry, &count); blockindex;
3330 blockindex = NextEntry(ctx, blockindex, &tentry, &count)) {
3331 if (++pollcount > 50) {
3332 #ifndef AFS_PTHREAD_ENV
3337 for (j = 0; j < NMAXNSERVERS; j++) {
3338 if (tentry.serverNumber[j] == BADSERVERID)
3340 if (tentry.serverNumber[j] == ipaddr1_id) {
3347 /* Log a message saying we are changing/removing an IP address */
3349 ("The following IP address is being %s:\n",
3350 (ipaddr2 ? "changed" : "removed")));
3351 VLog(0, (" entry %d: ", i));
3354 for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) {
3355 if (!exp->ex_addrs[mhidx])
3359 PADDR(ntohl(exp->ex_addrs[mhidx]));
3371 /* Change the registered uuuid addresses */
3373 memset(&tuuid, 0, sizeof(afsUUID));
3374 afs_htonuuid(&tuuid);
3375 exp->ex_hostuuid = tuuid;
3378 DOFFSET(ntohl(ctx->ex_addr[0]->ex_contaddrs[base]),
3379 (char *)ctx->ex_addr[base], (char *)exp),
3380 (char *)&tuuid, sizeof(tuuid));
3385 /* Now change the host address entry */
3386 ctx->cheader->IpMappedAddr[ipaddr1_id] = htonl(ipaddr2);
3388 vlwrite(ctx->trans, DOFFSET(0, ctx->cheader, &ctx->cheader->IpMappedAddr[ipaddr1_id]),
3390 &ctx->cheader->IpMappedAddr[ipaddr1_id], sizeof(afs_int32));
3391 ctx->hostaddress[ipaddr1_id] = ipaddr2;
3398 /* see if the vlserver is back yet */
3400 SVL_ProbeServer(struct rx_call *rxcall)