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>
17 #include <sys/types.h>
30 #include "cnvldb.h" /* CHANGEME! */
31 #include <netinet/in.h>
32 #include <afs/venus.h>
34 #include <afs/afsutil.h>
35 #include <afs/fileutil.h>
39 #define MAXSIZE 2048 /* most I'll get back from PIOCTL */
40 #define BADSERVERID 255 /* XXX */
43 extern struct cmd_syndesc *cmd_CreateSyntax();
44 static char pn[] = "cnvldb";
45 static char tempname[] = "XXnewvldb";
46 static char space[MAXSIZE];
47 static int MaxServers[3] = { 30, 254, 254 }; /* max server # permitted in this version */
49 static afs_int32 Conv4to3();
51 static int convert_vlentry();
52 static int rewrite_header();
54 static char tspace[1024]; /* chdir can't handle anything bigger, anyway */
55 /* return a static pointer to a buffer */
61 strcpy(tspace, apath);
62 tp = strrchr(tspace, '/');
71 int fromvers = 0, tovers = 0, showversion = 0;
74 char *pathname = NULL;
79 struct cmd_syndesc *as;
81 register struct cmd_item *ti;
82 register afs_int32 code;
83 int w, old, new, rc, dump = 0, fromv = 0;
85 char ubik[80]; /* space for some ubik header */
87 struct vlheader_1 header1;
88 struct vlheader_2 header2;
89 struct vlheader_3 header3;
90 } oldheader, oldheader1, newheader; /* large enough for either */
93 struct vlentry_1 entry1;
94 struct vlentry_2 entry2;
95 struct vlentry_3 entry3;
96 char mhinfo_block[VL_ADDREXTBLK_SIZE];
99 pathname = (as->parms[2].items ? as->parms[2].items->data : dbPath); /* -name */
100 showversion = (as->parms[3].items ? 1 : 0); /* -showversion */
101 dump = (as->parms[4].items ? 1 : 0); /* -dumpvldb */
102 fromvers = (as->parms[1].items ? atoi(as->parms[1].items->data) : 0); /* -fromversion */
103 tovers = (as->parms[0].items ? atoi(as->parms[0].items->data) : 0); /* -toversion */
105 /* should stat() the old vldb, get its size, and see if there's */
106 /* room for another. It might be in AFS, so check the quota, too */
107 old = open(pathname, O_RDONLY);
113 /* Read the version */
114 lseek(old, 64, L_SET);
115 read(old, &fromv, sizeof(int));
116 fromv = ntohl(fromv);
117 if ((fromv < 1) || (fromv > 4)) {
119 fprintf(stderr, ": Unrecognized VLDB version %d.\n", fromv);
123 /* Sequentially read the database converting the entries as we go */
124 lseek(old, 0, L_SET);
126 readheader(old, fromv, &oldheader);
128 dbsize = ntohl(oldheader.header1.vital_header.eofPtr);
129 fromv = ntohl(oldheader.header1.vital_header.vldbversion);
131 } else if (fromv == 2) {
132 dbsize = ntohl(oldheader.header2.vital_header.eofPtr);
133 fromv = ntohl(oldheader.header2.vital_header.vldbversion);
138 dbsize = ntohl(oldheader.header3.vital_header.eofPtr);
139 fromv = ntohl(oldheader.header3.vital_header.vldbversion);
140 mhaddr = ntohl(oldheader.header3.SIT);
142 /* Read the multihomed extent blocks in */
144 read_mhentries(mhaddr, old);
146 /* Position back to this after header */
147 lseek(old, pos + 64, L_SET);
151 if (showversion || dump) {
153 fprintf(stdout, "%s has a version of %d\n", pathname, fromv);
155 while (oldpos < dbsize) {
156 rc = readentry(old, fromv, &xvlentry);
157 if ((rc == 0) || (rc == EOF))
159 printentry(fromv, &xvlentry);
165 if (!fromvers) { /* not set */
167 } else if (fromvers != fromv) {
169 "%s has a version of %d while the -fromversion specified was %d - aborting\n",
170 pathname, fromv, fromvers);
174 if ((fromvers < 1) || (fromvers > 4)) {
176 fprintf(stderr, ": VLDB version %d is not supported.\n", fromvers);
178 fprintf(stderr, ": Only versions 1-4 are currently supported.\n");
183 tovers = fromvers + 1;
185 if (tovers < 1 || tovers > 4) {
187 fprintf(stderr, ": VLDB version %d is not supported.\n", tovers);
189 fprintf(stderr, ": Only versions 1 - 4 are currently supported.\n");
193 if (mhaddr && (tovers < 3)) {
195 fprintf(stderr, ": Cannot convert. VLDB contains multihome info.\n");
199 /* OK! let's get down to business... */
201 if (chdir(Parent(pathname))) {
206 new = open(tempname, O_WRONLY | O_CREAT | O_TRUNC, 0600);
212 /* Write the UBIK data */
213 w = write(new, ubik, 64);
215 printf("Write of ubik header failed %d; error %u\n", w, errno);
219 /* Because we know that all the vldb entries are the same size and type we
220 * can just read them sequentially, fiddle with the fields, and write
221 * them out again. If we invent a vldb format that has different
222 * types of entries, then we're going to have to invent new logic for
223 * converting the vldb-- we'll probably have to chase down the various
224 * linked lists in turn, doing lseeks and the like.
227 convert_header(old, new, fromvers, tovers, &oldheader, &newheader);
228 while (oldpos < dbsize) {
229 rc = readentry(old, fromvers, &xvlentry);
230 if ((rc == 0) || (rc == EOF))
232 convert_vlentry(new, fromvers, tovers, &oldheader, &newheader,
236 /* We have now finished sequentially reading and writing the database.
237 * Now randomly offset into database and update multihome entries.
239 convert_mhentries(old, new, &newheader, fromvers, tovers);
240 rewrite_header(new, tovers, &newheader);
249 renamefile(tempname, pathname);
255 readheader(fd, version, addr)
260 int hdrsize, size = 0;
264 hdrsize = sizeof(struct vlheader_1);
266 hdrsize = sizeof(struct vlheader_2);
268 size = read(fd, addr, hdrsize);
275 readentry(fd, version, addr)
281 struct vlentry_3 *vl3p = (struct vlentry_3 *)addr;
286 1) ? sizeof(struct vlentry_1) : sizeof(struct vlentry_2));
287 rc = read(fd, addr, toread);
289 printf("Partial read of vlentry at pos %u: %d\n", oldpos, rc);
293 /* Read a mhblock entry if there is one */
294 if ((rc > 0) && (vl3p->flags == VLCONTBLOCK)) {
295 if (!mhaddr) /* Remember first mh block */
296 mhaddr = oldpos - rc;
298 rc1 = read(fd, &addr[rc], VL_ADDREXTBLK_SIZE - rc);
299 if (rc1 != VL_ADDREXTBLK_SIZE - rc)
300 printf("Partial read of mhblock at pos %u: %d\n", oldpos + rc,
311 printentry(version, addr)
315 struct vlentry_2 *vl2p = (struct vlentry_2 *)addr;
316 struct vlentry_3 *vl3p = (struct vlentry_3 *)addr;
319 /* Don't print anything if the entry is a mh info block */
320 if (vl3p->flags == VLCONTBLOCK) {
324 if (version == 1 || version == 2) {
325 printf("%s\t%5d [%10d:%10d:%10d]%8X%8d\n", vl2p->name, vl2p->spares3,
326 vl2p->volumeId[0], vl2p->volumeId[1], vl2p->volumeId[2],
327 vl2p->flags, vl2p->LockAfsId);
328 printf("\t%8d%8d%8d [%7d%7d%7d]%7d% [%4d%4d%4d%4d][%4d%4d%4d%4d]\n",
329 vl2p->LockTimestamp, vl2p->cloneId, vl2p->spares0,
330 vl2p->nextIdHash[0], vl2p->nextIdHash[1], vl2p->nextIdHash[2],
331 vl2p->nextNameHash, vl2p->serverNumber[0],
332 vl2p->serverNumber[1], vl2p->serverNumber[2],
333 vl2p->serverNumber[3], vl2p->serverPartition[0],
334 vl2p->serverPartition[1], vl2p->serverPartition[2],
335 vl2p->serverPartition[3]);
336 printf("\t[%4d%4d%4d%4d]\n", vl2p->serverFlags[0],
337 vl2p->serverFlags[1], vl2p->serverFlags[2],
338 vl2p->serverFlags[3]);
339 } else { /* if (version >= 3) */
341 if (vl3p->flags == VLFREE)
343 printf("%s\tPos=%d NextIdHash=[%d:%d:%d] NextNameHash=%d\n",
344 vl3p->name, (oldpos - sizeof(struct vlentry_3)),
345 vl3p->nextIdHash[0], vl3p->nextIdHash[1], vl3p->nextIdHash[2],
347 printf("\tRW=%u RO=%u BK=%u CL=%u flags=0x%X lockBy=%d lockTime=%u\n",
348 vl3p->volumeId[0], vl3p->volumeId[1], vl3p->volumeId[2],
349 vl3p->cloneId, vl3p->flags, vl3p->LockAfsId,
350 vl3p->LockTimestamp);
351 for (i = 0; i < OMAXNSERVERS; i++) {
352 if ((vl3p->serverNumber[i] & 0xff) != 0xff) {
353 printf("\tServer=%d Partition=%d flags=%X\n",
354 vl3p->serverNumber[i], vl3p->serverPartition[i],
355 vl3p->serverFlags[i]);
362 int readmhentries = 0;
363 struct extentaddr *base[VL_MAX_ADDREXTBLKS];
365 /* Read the multihome extent blocks in. Check if they are good by
366 * verifying their address is not pass the EOF and the flags are good.
367 * If it's not good, then don't read the block in.
369 read_mhentries(mh_addr, oldfd)
381 /* Initialize base pointers */
382 for (j = 0; j < VL_MAX_ADDREXTBLKS; j++)
388 /* Check if the first extent block is beyond eof. If
389 * it is, it's not real.
391 if (mh_addr > dbsize - VL_ADDREXTBLK_SIZE)
394 /* Now read the first mh extent block */
395 code = lseek(oldfd, mh_addr + 64, L_SET);
397 perror("seek MH block");
400 base[0] = (struct extentaddr *)malloc(VL_ADDREXTBLK_SIZE);
405 code = read(oldfd, (char *)base[0], VL_ADDREXTBLK_SIZE);
406 if (code != VL_ADDREXTBLK_SIZE) {
407 perror("read MH block");
413 /* Verify that this block is the right one */
414 if (ntohl(base[0]->ex_flags) != VLCONTBLOCK) { /* check if flag is correct */
420 /* The first block contains pointers to the other extent blocks.
421 * Check to see if the pointers are good and read them in if they are.
424 for (j = 1; j < VL_MAX_ADDREXTBLKS; j++) {
425 if (!base[0]->ex_contaddrs[j])
428 sit = ntohl(base[0]->ex_contaddrs[j]);
430 /* Every time we allocate a new extent block, it is allocated after
431 * the previous ones. But it must be before the EOF.
433 if ((sit < (a + VL_ADDREXTBLK_SIZE))
434 || (sit > dbsize - VL_ADDREXTBLK_SIZE)) {
438 /* Read the extent block in */
440 code = lseek(oldfd, sit, L_SET);
442 perror("seek MH block");
445 base[j] = (struct extentaddr *)malloc(VL_ADDREXTBLK_SIZE);
450 code = read(oldfd, (char *)base[j], VL_ADDREXTBLK_SIZE);
451 if (code != VL_ADDREXTBLK_SIZE) {
452 perror("read MH block");
456 /* Verify that this block knows its an extent block */
457 if (ntohl(base[j]->ex_flags) != VLCONTBLOCK) {
463 /* The extent block passed our tests */
464 a = ntohl(base[0]->ex_contaddrs[j]);
468 /* Follow the SIT pointer in the header (mhaddr) to the multihomed
469 * extent blocks and verify that the pointers are good. And fix.
470 * Then convert the multihomed addresses to single address if we
471 * are converting back from version 4.
473 * Before this can be called, the routine read_mhentries must be called.
475 convert_mhentries(oldfd, newfd, header, fromver, tover)
477 struct vlheader_2 *header;
482 int i, j, modified = 0, w;
483 afs_uint32 raddr, addr;
484 struct extentaddr *exp;
487 /* Check if the header says the extent block exists. If
488 * it does, then read_mhentries should have read it in.
490 if (mhaddr && !base[0]) {
491 printf("Fix Bad base extent block pointer\n");
492 header->SIT = mhaddr = 0;
493 } else if (mhaddr && base[0]) {
495 if ((ntohl(header->SIT) != mhaddr) && (tover == 4)) {
497 ("Fix pointer to first base extent block. Was 0x%x, now 0x%x\n",
498 ntohl(header->SIT), mhaddr);
499 header->SIT = htonl(mhaddr);
502 /* Check if the first block points to itself. If not, then fix it */
503 if (ntohl(base[0]->ex_contaddrs[0]) != mhaddr) {
504 printf("Fix bad pointer in base extent block: Base 0\n");
505 base[0]->ex_contaddrs[0] = htonl(mhaddr);
509 /* The first block contains pointers to the other extent blocks.
510 * Check to see if the pointers are good.
512 for (j = 1; j < VL_MAX_ADDREXTBLKS; j++) {
513 /* Check if the base extent block says the extent blocks exist.
514 * If it does, then read_mhentries should have read it in.
516 if (base[0]->ex_contaddrs[j] && !base[j]) {
517 printf("Fix bad pointer in base extent block: Base %d\n", j);
518 base[0]->ex_contaddrs[j] = 0;
523 /* Now write out the base extent blocks if it changed */
525 code = lseek(newfd, mhaddr + 64, L_SET);
527 perror("seek MH Block");
530 w = write(newfd, (char *)base[0], VL_ADDREXTBLK_SIZE);
531 if (w != VL_ADDREXTBLK_SIZE) {
532 perror("write MH Block");
538 /* If we are converting from version 4 to version 3, then
539 * translate any multihome ptrs in the IpMappedAddr array
540 * to true IP addresses.
542 if ((fromver == 4) && (tover == 3)) {
543 /* Step through the fileserver addresses in the VLDB header
544 * and convert the pointers back to IP addresses.
546 for (i = 0; i < 254; i++) {
547 addr = ntohl(header->IpMappedAddr[i]);
548 if (addr && ((addr & 0xff000000) == 0xff000000)) {
549 basei = (addr >> 16) & 0xff;
550 index = addr & 0xffff;
552 if ((basei >= VL_ADDREXTBLK_SIZE) || !base[basei]) {
554 "Warning: mh entry %d has no IP address; ignored!!\n",
556 header->IpMappedAddr[i] = 0;
559 exp = &base[basei][index];
561 /* For now return the first ip address back */
562 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
563 if (exp->ex_addrs[j]) {
564 raddr = ntohl(exp->ex_addrs[j]);
568 if (j >= VL_MAXIPADDRS_PERMH) {
570 "Warning: mh entry %d has no ip address; ignored!!\n",
575 ("Multi-homed addr: converting to single ip address %d.%d.%d.%d\n",
576 (raddr >> 24 & 0xff), (raddr >> 16 & 0xff),
577 (raddr >> 8 & 0xff), (raddr & 0xff));
579 header->IpMappedAddr[i] = htonl(raddr);
582 header->SIT = mhaddr = 0; /* mhinfo block has been removed */
584 /* Now step through the hash tables in header updating them.
585 * Because we removed the mh info blocks and some entries they
586 * point to may have changed position.
589 for (i = 0; i < 8191; i++) {
590 header->VolnameHash[i] = Conv4to3(header->VolnameHash[i]);
593 for (i = 0; i < 3; i++) {
594 for (j = 0; j < 8191; j++) {
595 header->VolidHash[i][j] = Conv4to3(header->VolidHash[i][j]);
599 /* Update eofptr to take into account the removal of the mhinfo blocks */
600 header->vital_header.eofPtr = htonl(Conv4to3(dbsize));
605 convert_header(ofd, fd, fromv, tov, fromaddr, toaddr)
606 int ofd, fd, fromv, tov;
607 char *fromaddr, *toaddr;
609 struct vlheader_1 *tvp1;
610 struct vlheader_2 *tvp2;
615 memcpy(toaddr, fromaddr, sizeof(struct vlheader_1));
616 tvp1 = (struct vlheader_1 *)toaddr;
618 w = write(fd, tvp1, sizeof(struct vlheader_1));
619 if (w != sizeof(struct vlheader_1)) {
620 printf("Write of header failed %d; error %u\n", w, errno);
624 /* for garbage-collecting... */
625 for (i = 0; i < 31; i++)
626 tvp1->IpMappedAddr[i] = 0;
628 } else if (tov == 2 || tov == 3) {
629 tvp1 = (struct vlheader_1 *)fromaddr;
630 tvp2 = (struct vlheader_2 *)toaddr;
631 memset(tvp2, 0, sizeof(struct vlheader_2));
632 tvp2->vital_header.vldbversion = htonl(tov);
633 tvp2->vital_header.headersize = htonl(sizeof(struct vlheader_2));
635 ntohl(tvp2->vital_header.headersize) -
636 ntohl(tvp1->vital_header.headersize);
637 if (ntohl(tvp1->vital_header.freePtr))
638 tvp2->vital_header.freePtr =
639 htonl(ntohl(tvp1->vital_header.freePtr) + diff);
640 if (ntohl(tvp1->vital_header.eofPtr))
641 tvp2->vital_header.eofPtr =
642 htonl(ntohl(tvp1->vital_header.eofPtr) + diff);
643 tvp2->vital_header.allocs = tvp1->vital_header.allocs;
644 tvp2->vital_header.frees = tvp1->vital_header.frees;
645 tvp2->vital_header.MaxVolumeId = tvp1->vital_header.MaxVolumeId;
646 for (i = 0; i < 3; i++)
647 tvp2->vital_header.totalEntries[i] =
648 tvp1->vital_header.totalEntries[i];
650 for (i = 0; i < 31; i++)
651 tvp2->IpMappedAddr[i] = tvp1->IpMappedAddr[i];
653 for (i = 0; i < 8191; i++) {
654 if (ntohl(tvp1->VolnameHash[i]))
655 tvp2->VolnameHash[i] =
656 htonl(ntohl(tvp1->VolnameHash[i]) + diff);
659 for (i = 0; i < 3; i++) {
660 for (j = 0; j < 8191; j++) {
661 if (ntohl(tvp1->VolidHash[i][j]))
662 tvp2->VolidHash[i][j] =
663 htonl(ntohl(tvp1->VolidHash[i][j]) + diff);
667 w = write(fd, tvp2, sizeof(struct vlheader_2));
668 if (w != sizeof(struct vlheader_2)) {
669 printf("Write of header failed %d; error %u\n", w, errno);
673 /* for garbage-collecting... */
674 for (i = 0; i < 31; i++)
675 tvp2->IpMappedAddr[i] = 0;
678 } else if (fromv == 2 || fromv == 3 || fromv == 4) {
679 if (tov == 2 || tov == 3 || tov == 4) {
680 memcpy(toaddr, fromaddr, sizeof(struct vlheader_2));
681 tvp2 = (struct vlheader_2 *)toaddr;
682 tvp2->vital_header.vldbversion = htonl(tov);
683 w = write(fd, tvp2, sizeof(struct vlheader_2));
684 if (w != sizeof(struct vlheader_2)) {
685 printf("Write of header failed %d; error %u\n", w, errno);
689 } else if (tov == 1) {
690 tvp2 = (struct vlheader_2 *)fromaddr;
691 tvp1 = (struct vlheader_1 *)toaddr;
692 memset(tvp1, 0, sizeof(struct vlheader_1));
693 tvp1->vital_header.vldbversion = htonl(1);
694 tvp1->vital_header.headersize = htonl(sizeof(struct vlheader_1));
696 ntohl(tvp1->vital_header.headersize) -
697 ntohl(tvp2->vital_header.headersize);
698 if (ntohl(tvp2->vital_header.freePtr))
699 tvp1->vital_header.freePtr =
700 htonl(ntohl(tvp2->vital_header.freePtr) + diff);
701 if (ntohl(tvp2->vital_header.eofPtr))
702 tvp1->vital_header.eofPtr =
703 htonl(ntohl(tvp2->vital_header.eofPtr) + diff);
704 tvp1->vital_header.allocs = tvp2->vital_header.allocs;
705 tvp1->vital_header.frees = tvp2->vital_header.frees;
706 tvp1->vital_header.MaxVolumeId = tvp2->vital_header.MaxVolumeId;
707 for (i = 0; i < 3; i++)
708 tvp1->vital_header.totalEntries[i] =
709 tvp2->vital_header.totalEntries[i];
711 for (i = 0; i < 31; i++)
712 tvp1->IpMappedAddr[i] = tvp2->IpMappedAddr[i];
714 for (i = 0; i < 8191; i++) {
715 if (ntohl(tvp2->VolnameHash[i]))
716 tvp1->VolnameHash[i] =
717 htonl(ntohl(tvp2->VolnameHash[i]) + diff);
720 for (i = 0; i < 3; i++) {
721 for (j = 0; j < 8191; j++) {
722 if (ntohl(tvp2->VolidHash[i][j]))
723 tvp1->VolidHash[i][j] =
724 htonl(ntohl(tvp2->VolidHash[i][j]) + diff);
728 w = write(fd, tvp1, sizeof(struct vlheader_1));
729 if (w != sizeof(struct vlheader_2)) {
730 printf("Write of header failed %d; error %u\n", w, errno);
734 /* for garbage-collecting... */
735 for (i = 0; i < 31; i++)
736 tvp1->IpMappedAddr[i] = 0;
745 /* Convert an address pointer to a vlentry from version 4 to version 3.
746 * This involves checking if the address is after any of the four
747 * MH block and if it is, subtract the size of the MH block.
749 * In going from version 4 to 3, the mh blocks go away and all entries
750 * move up in their place. The adresses then need to be updated.
752 * Before this can be called, the routine read_mhentries must be called.
761 if (!base[0] || !addr)
765 for (i = 0; i < VL_MAX_ADDREXTBLKS; i++) {
766 if (base[i] && base[0]->ex_contaddrs[i]
767 && (addr > base[0]->ex_contaddrs[i]))
768 raddr -= VL_ADDREXTBLK_SIZE;
774 /* this only works because the vlheader struct is essentially the same
775 * from version 1 to version 2 -- that is, the first bunch of fields
776 * aren't any more or any larger, so they match up pretty well.
780 convert_vlentry(new, fromvers, tovers, oldheader, newheader, vlentryp)
781 int new, fromvers, tovers;
782 struct vlheader_1 *oldheader, *newheader; /* close enough */
783 struct vlentry_1 *vlentryp; /* 1 and 2 are identical */
786 struct vlentry_3 *vl3p = (struct vlentry_3 *)vlentryp;
788 /* For mh information blocks,
789 * If going to version 4 or greater, keep the mh info block.
790 * Otherwise, don't keep it (version 3 and earlier don't have them).
792 if (vl3p->flags == VLCONTBLOCK) {
794 w = write(new, vlentryp, VL_ADDREXTBLK_SIZE);
795 if (w != VL_ADDREXTBLK_SIZE) {
796 printf("Write of mh info block failed %d; error %u\n", w,
804 if (fromvers == 2 && tovers == 3) {
807 vl.volumeId[0] = vlentryp->volumeId[0];
808 vl.volumeId[1] = vlentryp->volumeId[1];
809 vl.volumeId[2] = vlentryp->volumeId[2];
810 vl.flags = vlentryp->flags;
811 vl.LockAfsId = vlentryp->LockAfsId;
812 vl.LockTimestamp = vlentryp->LockTimestamp;
813 vl.cloneId = vlentryp->cloneId;
814 vl.nextIdHash[0] = vlentryp->nextIdHash[0];
815 vl.nextIdHash[1] = vlentryp->nextIdHash[1];
816 vl.nextIdHash[2] = vlentryp->nextIdHash[2];
817 vl.nextNameHash = vlentryp->nextNameHash;
818 memcpy(vl.name, vlentryp->name, 65);
819 for (i = 0; i < 8; i++) {
820 vl.serverNumber[i] = vlentryp->serverNumber[i];
821 vl.serverPartition[i] = vlentryp->serverPartition[i];
822 vl.serverFlags[i] = vlentryp->serverFlags[i];
825 vl.serverNumber[i] = vl.serverPartition[i] = vl.serverFlags[i] =
827 w = write(new, &vl, sizeof(struct vlentry_3));
828 if (w != sizeof(struct vlentry_3)) {
829 printf("Write of entry failed %d; error %u\n", w, errno);
834 } else if (fromvers == 3 && tovers == 2) {
836 struct vlentry_3 *xnvlentry = (struct vlentry_3 *)vlentryp;
838 memset((char *)&vl, 0, sizeof(struct vlentry_2));
839 vl.volumeId[0] = xnvlentry->volumeId[0];
840 vl.volumeId[1] = xnvlentry->volumeId[1];
841 vl.volumeId[2] = xnvlentry->volumeId[2];
842 vl.flags = xnvlentry->flags;
843 vl.LockAfsId = xnvlentry->LockAfsId;
844 vl.LockTimestamp = xnvlentry->LockTimestamp;
845 vl.cloneId = xnvlentry->cloneId;
846 for (i = 0; i < 3; i++) {
847 if (ntohl(xnvlentry->nextIdHash[i]))
848 vl.nextIdHash[i] = xnvlentry->nextIdHash[i];
850 if (ntohl(xnvlentry->nextNameHash))
851 vl.nextNameHash = xnvlentry->nextNameHash;
852 memcpy(vl.name, xnvlentry->name, 65);
853 for (i = 0; i < 8; i++) {
854 vl.serverNumber[i] = xnvlentry->serverNumber[i];
855 vl.serverPartition[i] = xnvlentry->serverPartition[i];
856 vl.serverFlags[i] = xnvlentry->serverFlags[i];
858 w = write(new, &vl, sizeof(struct vlentry_2));
859 if (w != sizeof(struct vlentry_2)) {
860 printf("Write of entry failed %d; error %u\n", w, errno);
864 } else if (fromvers == 3 && tovers == 1) {
866 struct vlentry_3 *xnvlentry = (struct vlentry_3 *)vlentryp;
870 1 ? sizeof(struct vlheader_1) : sizeof(struct vlheader_2))
872 1 ? sizeof(struct vlheader_1) : sizeof(struct vlheader_2));
873 memset((char *)&vl, 0, sizeof(struct vlentry_1));
874 vl.volumeId[0] = xnvlentry->volumeId[0];
875 vl.volumeId[1] = xnvlentry->volumeId[1];
876 vl.volumeId[2] = xnvlentry->volumeId[2];
877 vl.flags = xnvlentry->flags;
878 vl.LockAfsId = xnvlentry->LockAfsId;
879 vl.LockTimestamp = xnvlentry->LockTimestamp;
880 vl.cloneId = xnvlentry->cloneId;
881 for (i = 0; i < 3; i++) {
882 if (ntohl(xnvlentry->nextIdHash[i]))
884 htonl(ntohl(xnvlentry->nextIdHash[i]) + diff);
886 if (ntohl(xnvlentry->nextNameHash))
887 vl.nextNameHash = htonl(ntohl(xnvlentry->nextNameHash) + diff);
889 memcpy(vl.name, xnvlentry->name, 65);
890 for (i = 0; i < 8; i++) {
891 vl.serverNumber[i] = xnvlentry->serverNumber[i];
892 vl.serverPartition[i] = xnvlentry->serverPartition[i];
893 vl.serverFlags[i] = xnvlentry->serverFlags[i];
895 for (i = 0; i < 8; i++) {
896 s = xnvlentry->serverNumber[i];
898 if (s > MaxServers[tovers - 1]) {
900 "%s: Too Many Servers (%d) for this version!\n",
904 newheader->IpMappedAddr[s] = oldheader->IpMappedAddr[s];
907 w = write(new, &vl, sizeof(struct vlentry_1));
908 if (w != sizeof(struct vlentry_1)) {
909 printf("Write of entry failed %d; error %u\n", w, errno);
913 } else if (fromvers == 4 && tovers == 3) {
915 /* We are converting from version 4 to 3. In this conversion, mh info
916 * blocks go away and all vlentries after them move up in the vldb file.
917 * When this happens, the linked list pointers need to be updated.
919 memcpy(&vl, vlentryp, sizeof(vl));
920 for (i = 0; i < 3; i++) {
921 vl.nextIdHash[i] = Conv4to3(vl.nextIdHash[i]);
923 vl.nextNameHash = Conv4to3(vl.nextNameHash);
925 w = write(new, &vl, sizeof(vl));
926 if (w != sizeof(vl)) {
927 printf("Write of entry failed %d; error %u\n", w, errno);
934 w = write(new, vlentryp, sizeof(struct vlentry_1));
935 if (w != sizeof(struct vlentry_1)) {
936 printf("Write of entry failed %d; error %u\n", w, errno);
939 } else if (tovers == 2) {
940 w = write(new, vlentryp, sizeof(struct vlentry_2));
941 if (w != sizeof(struct vlentry_2)) {
942 printf("Write of entry failed %d; error %u\n", w, errno);
945 } else if (tovers == 3 || tovers == 4) {
946 w = write(new, vlentryp, sizeof(struct vlentry_3));
947 if (w != sizeof(struct vlentry_3)) {
948 printf("Write of entry failed %d; error %u\n", w, errno);
954 "Skipping vlentry write - db corrupted - bad toversion %d\n",
962 rewrite_header(new, tovers, newheader)
968 pos = lseek(new, 64, L_SET); /* leave room for ubik */
971 fprintf(stderr, "%s: no garbage colection\n", pn);
973 } else if (pos != 64) {
974 fprintf(stderr, "%s: Can't rewind: no garbage collection\n", pn);
980 1) ? sizeof(struct vlheader_1) : sizeof(struct vlheader_2));
981 w = write(new, newheader, towrite);
983 printf("Write of entry failed %d; error %u\n", w, errno);
991 #include "AFS_component_version_number.c"
997 register struct cmd_syndesc *ts;
1000 ts = cmd_CreateSyntax("initcmd", handleit, 0, "optional");
1001 cmd_AddParm(ts, "-to", CMD_SINGLE, CMD_OPTIONAL, "goal version");
1002 cmd_AddParm(ts, "-from", CMD_SINGLE, CMD_OPTIONAL, "current version");
1003 cmd_AddParm(ts, "-path", CMD_SINGLE, CMD_OPTIONAL, "pathname");
1004 cmd_AddParm(ts, "-showversion", CMD_FLAG, CMD_OPTIONAL,
1005 "Just display version of current vldb");
1006 cmd_AddParm(ts, "-dumpvldb", CMD_FLAG, CMD_OPTIONAL,
1007 "display all vldb entries");
1010 cmd_AddParm(ts, "-noGC", CMD_FLAG, CMD_OPTIONAL,
1011 "Don't do garbage collection");
1014 dbPath = AFSDIR_SERVER_VLDB_FILEPATH;
1016 code = cmd_Dispatch(argc, argv);