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>
18 #include <afs/venus.h>
20 #include <afs/afsutil.h>
21 #include <afs/fileutil.h>
24 #include "cnvldb.h" /* CHANGEME! */
26 #define BADSERVERID 255 /* XXX */
29 static char pn[] = "cnvldb";
30 static char tempname[] = "XXnewvldb";
31 static int MaxServers[3] = { 30, 254, 254 }; /* max server # permitted in this version */
33 static afs_int32 Conv4to3(afs_uint32 addr);
35 static void convert_vlentry(int, int, int, struct vlheader_1 *,
36 struct vlheader_1 *, struct vlentry_1 *);
37 static void rewrite_header(int, int, void *);
38 static void readheader(int fd, int version, void *addr);
39 static int readentry(int fd, int version, void *addr);
40 static void printentry(int version, void *addr);
42 static char tspace[1024]; /* chdir can't handle anything bigger, anyway */
44 void read_mhentries(afs_uint32 mh_addr, int oldfd);
45 void convert_mhentries(int oldfd, int newfd, struct vlheader_2 *header, int fromver, int tover);
47 static int convert_header(int ofd, int fd, int fromv, int tov, void *fromaddr,
50 /* return a static pointer to a buffer */
52 Parent(const char *apath)
55 strcpy(tspace, apath);
56 tp = strrchr(tspace, '/');
65 int fromvers = 0, tovers = 0, showversion = 0;
68 const char *pathname = NULL;
72 handleit(struct cmd_syndesc *as, void *arock)
74 int w, old, new, rc, dump = 0, fromv = 0;
75 char ubik[80]; /* space for some ubik header */
77 struct vlheader_1 header1;
78 struct vlheader_2 header2;
79 struct vlheader_3 header3;
80 } oldheader, newheader; /* large enough for either */
83 struct vlentry_1 entry1;
84 struct vlentry_2 entry2;
85 struct vlentry_3 entry3;
86 char mhinfo_block[VL_ADDREXTBLK_SIZE];
89 pathname = (as->parms[2].items ? as->parms[2].items->data : dbPath); /* -name */
90 showversion = (as->parms[3].items ? 1 : 0); /* -showversion */
91 dump = (as->parms[4].items ? 1 : 0); /* -dumpvldb */
92 fromvers = (as->parms[1].items ? atoi(as->parms[1].items->data) : 0); /* -fromversion */
93 tovers = (as->parms[0].items ? atoi(as->parms[0].items->data) : 0); /* -toversion */
95 /* should stat() the old vldb, get its size, and see if there's */
96 /* room for another. It might be in AFS, so check the quota, too */
97 old = open(pathname, O_RDONLY);
103 /* Read the version */
104 lseek(old, 64, L_SET);
105 read(old, &fromv, sizeof(int));
106 fromv = ntohl(fromv);
107 if ((fromv < 1) || (fromv > 4)) {
108 fprintf(stderr, "%s", pn);
109 fprintf(stderr, ": Unrecognized VLDB version %d.\n", fromv);
113 /* Sequentially read the database converting the entries as we go */
114 lseek(old, 0, L_SET);
116 readheader(old, fromv, &oldheader);
118 dbsize = ntohl(oldheader.header1.vital_header.eofPtr);
119 fromv = ntohl(oldheader.header1.vital_header.vldbversion);
121 } else if (fromv == 2) {
122 dbsize = ntohl(oldheader.header2.vital_header.eofPtr);
123 fromv = ntohl(oldheader.header2.vital_header.vldbversion);
128 dbsize = ntohl(oldheader.header3.vital_header.eofPtr);
129 fromv = ntohl(oldheader.header3.vital_header.vldbversion);
130 mhaddr = ntohl(oldheader.header3.SIT);
132 /* Read the multihomed extent blocks in */
134 read_mhentries(mhaddr, old);
136 /* Position back to this after header */
137 lseek(old, pos + 64, L_SET);
141 if (showversion || dump) {
143 fprintf(stdout, "%s has a version of %d\n", pathname, fromv);
145 while (oldpos < dbsize) {
146 rc = readentry(old, fromv, &xvlentry);
147 if ((rc == 0) || (rc == EOF))
149 printentry(fromv, &xvlentry);
155 if (!fromvers) { /* not set */
157 } else if (fromvers != fromv) {
159 "%s has a version of %d while the -fromversion specified was %d - aborting\n",
160 pathname, fromv, fromvers);
164 if ((fromvers < 1) || (fromvers > 4)) {
165 fprintf(stderr, "%s", pn);
166 fprintf(stderr, ": VLDB version %d is not supported.\n", fromvers);
167 fprintf(stderr, "%s", pn);
168 fprintf(stderr, ": Only versions 1-4 are currently supported.\n");
173 tovers = fromvers + 1;
175 if (tovers < 1 || tovers > 4) {
176 fprintf(stderr, "%s", pn);
177 fprintf(stderr, ": VLDB version %d is not supported.\n", tovers);
178 fprintf(stderr, "%s", pn);
179 fprintf(stderr, ": Only versions 1 - 4 are currently supported.\n");
183 if (mhaddr && (tovers < 3)) {
184 fprintf(stderr, "%s", pn);
185 fprintf(stderr, ": Cannot convert. VLDB contains multihome info.\n");
189 /* OK! let's get down to business... */
191 if (chdir(Parent(pathname))) {
196 new = open(tempname, O_WRONLY | O_CREAT | O_TRUNC, 0600);
202 /* Write the UBIK data */
203 w = write(new, ubik, 64);
205 printf("Write of ubik header failed %d; error %u\n", w, errno);
209 /* Because we know that all the vldb entries are the same size and type we
210 * can just read them sequentially, fiddle with the fields, and write
211 * them out again. If we invent a vldb format that has different
212 * types of entries, then we're going to have to invent new logic for
213 * converting the vldb-- we'll probably have to chase down the various
214 * linked lists in turn, doing lseeks and the like.
217 convert_header(old, new, fromvers, tovers, &oldheader, &newheader);
218 while (oldpos < dbsize) {
219 rc = readentry(old, fromvers, &xvlentry);
220 if ((rc == 0) || (rc == EOF))
222 convert_vlentry(new, fromvers, tovers,
223 (struct vlheader_1 *)&oldheader,
224 (struct vlheader_1 *)&newheader,
225 (struct vlentry_1 *)&xvlentry);
228 /* We have now finished sequentially reading and writing the database.
229 * Now randomly offset into database and update multihome entries.
231 convert_mhentries(old, new, (struct vlheader_2 *)&newheader,
233 rewrite_header(new, tovers, &newheader);
242 renamefile(tempname, pathname);
249 readheader(int fd, int version, void *addr)
251 int hdrsize, size = 0;
255 hdrsize = sizeof(struct vlheader_1);
257 hdrsize = sizeof(struct vlheader_2);
259 size = read(fd, addr, hdrsize);
267 readentry(int fd, int version, void *addr)
270 struct vlentry_3 *vl3p = (struct vlentry_3 *)addr;
272 char *caddr = (char *)addr;
276 1) ? sizeof(struct vlentry_1) : sizeof(struct vlentry_2));
277 rc = read(fd, addr, toread);
279 printf("Partial read of vlentry at pos %u: %d\n", oldpos, rc);
283 /* Read a mhblock entry if there is one */
284 if ((rc > 0) && (vl3p->flags == VLCONTBLOCK)) {
285 if (!mhaddr) /* Remember first mh block */
286 mhaddr = oldpos - rc;
288 rc1 = read(fd, &caddr[rc], VL_ADDREXTBLK_SIZE - rc);
289 if (rc1 != VL_ADDREXTBLK_SIZE - rc)
290 printf("Partial read of mhblock at pos %u: %d\n", oldpos + rc,
302 printentry(int version, void *addr)
304 struct vlentry_2 *vl2p = (struct vlentry_2 *)addr;
305 struct vlentry_3 *vl3p = (struct vlentry_3 *)addr;
308 /* Don't print anything if the entry is a mh info block */
309 if (vl3p->flags == VLCONTBLOCK) {
313 if (version == 1 || version == 2) {
314 printf("%s\t%5d [%10d:%10d:%10d]%8X%8d\n", vl2p->name, vl2p->spares3,
315 vl2p->volumeId[0], vl2p->volumeId[1], vl2p->volumeId[2],
316 vl2p->flags, vl2p->LockAfsId);
317 printf("\t%8d%8d%8d [%7d%7d%7d]%7d [%4d%4d%4d%4d][%4d%4d%4d%4d]\n",
318 vl2p->LockTimestamp, vl2p->cloneId, vl2p->spares0,
319 vl2p->nextIdHash[0], vl2p->nextIdHash[1], vl2p->nextIdHash[2],
320 vl2p->nextNameHash, vl2p->serverNumber[0],
321 vl2p->serverNumber[1], vl2p->serverNumber[2],
322 vl2p->serverNumber[3], vl2p->serverPartition[0],
323 vl2p->serverPartition[1], vl2p->serverPartition[2],
324 vl2p->serverPartition[3]);
325 printf("\t[%4d%4d%4d%4d]\n", vl2p->serverFlags[0],
326 vl2p->serverFlags[1], vl2p->serverFlags[2],
327 vl2p->serverFlags[3]);
328 } else { /* if (version >= 3) */
330 if (vl3p->flags == VLFREE)
332 printf("%s\tPos=%" AFS_SIZET_FMT " NextIdHash=[%d:%d:%d] NextNameHash=%d\n",
333 vl3p->name, (oldpos - sizeof(struct vlentry_3)),
334 vl3p->nextIdHash[0], vl3p->nextIdHash[1], vl3p->nextIdHash[2],
336 printf("\tRW=%u RO=%u BK=%u CL=%u flags=0x%X lockBy=%d lockTime=%u\n",
337 vl3p->volumeId[0], vl3p->volumeId[1], vl3p->volumeId[2],
338 vl3p->cloneId, vl3p->flags, vl3p->LockAfsId,
339 vl3p->LockTimestamp);
340 for (i = 0; i < OMAXNSERVERS; i++) {
341 if ((vl3p->serverNumber[i] & 0xff) != 0xff) {
342 printf("\tServer=%d Partition=%d flags=%X\n",
343 vl3p->serverNumber[i], vl3p->serverPartition[i],
344 vl3p->serverFlags[i]);
351 int readmhentries = 0;
352 struct extentaddr *base[VL_MAX_ADDREXTBLKS];
354 /* Read the multihome extent blocks in. Check if they are good by
355 * verifying their address is not pass the EOF and the flags are good.
356 * If it's not good, then don't read the block in.
359 read_mhentries(afs_uint32 mh_addr, int oldfd)
369 /* Initialize base pointers */
370 for (j = 0; j < VL_MAX_ADDREXTBLKS; j++)
376 /* Check if the first extent block is beyond eof. If
377 * it is, it's not real.
379 if (mh_addr > dbsize - VL_ADDREXTBLK_SIZE)
382 /* Now read the first mh extent block */
383 code = lseek(oldfd, mh_addr + 64, L_SET);
385 perror("seek MH block");
388 base[0] = (struct extentaddr *)malloc(VL_ADDREXTBLK_SIZE);
393 code = read(oldfd, (char *)base[0], VL_ADDREXTBLK_SIZE);
394 if (code != VL_ADDREXTBLK_SIZE) {
395 perror("read MH block");
401 /* Verify that this block is the right one */
402 if (ntohl(base[0]->ex_flags) != VLCONTBLOCK) { /* check if flag is correct */
408 /* The first block contains pointers to the other extent blocks.
409 * Check to see if the pointers are good and read them in if they are.
412 for (j = 1; j < VL_MAX_ADDREXTBLKS; j++) {
413 if (!base[0]->ex_contaddrs[j])
416 sit = ntohl(base[0]->ex_contaddrs[j]);
418 /* Every time we allocate a new extent block, it is allocated after
419 * the previous ones. But it must be before the EOF.
421 if ((sit < (a + VL_ADDREXTBLK_SIZE))
422 || (sit > dbsize - VL_ADDREXTBLK_SIZE)) {
426 /* Read the extent block in */
428 code = lseek(oldfd, sit, L_SET);
430 perror("seek MH block");
433 base[j] = (struct extentaddr *)malloc(VL_ADDREXTBLK_SIZE);
438 code = read(oldfd, (char *)base[j], VL_ADDREXTBLK_SIZE);
439 if (code != VL_ADDREXTBLK_SIZE) {
440 perror("read MH block");
444 /* Verify that this block knows its an extent block */
445 if (ntohl(base[j]->ex_flags) != VLCONTBLOCK) {
451 /* The extent block passed our tests */
452 a = ntohl(base[0]->ex_contaddrs[j]);
456 /* Follow the SIT pointer in the header (mhaddr) to the multihomed
457 * extent blocks and verify that the pointers are good. And fix.
458 * Then convert the multihomed addresses to single address if we
459 * are converting back from version 4.
461 * Before this can be called, the routine read_mhentries must be called.
464 convert_mhentries(int oldfd, int newfd, struct vlheader_2 *header,
465 int fromver, int tover)
468 int i, j, modified = 0, w;
469 afs_uint32 raddr, addr;
470 struct extentaddr *exp;
473 /* Check if the header says the extent block exists. If
474 * it does, then read_mhentries should have read it in.
476 if (mhaddr && !base[0]) {
477 printf("Fix Bad base extent block pointer\n");
478 header->SIT = mhaddr = 0;
479 } else if (mhaddr && base[0]) {
481 if ((ntohl(header->SIT) != mhaddr) && (tover == 4)) {
483 ("Fix pointer to first base extent block. Was 0x%x, now 0x%x\n",
484 ntohl(header->SIT), mhaddr);
485 header->SIT = htonl(mhaddr);
488 /* Check if the first block points to itself. If not, then fix it */
489 if (ntohl(base[0]->ex_contaddrs[0]) != mhaddr) {
490 printf("Fix bad pointer in base extent block: Base 0\n");
491 base[0]->ex_contaddrs[0] = htonl(mhaddr);
495 /* The first block contains pointers to the other extent blocks.
496 * Check to see if the pointers are good.
498 for (j = 1; j < VL_MAX_ADDREXTBLKS; j++) {
499 /* Check if the base extent block says the extent blocks exist.
500 * If it does, then read_mhentries should have read it in.
502 if (base[0]->ex_contaddrs[j] && !base[j]) {
503 printf("Fix bad pointer in base extent block: Base %d\n", j);
504 base[0]->ex_contaddrs[j] = 0;
509 /* Now write out the base extent blocks if it changed */
511 code = lseek(newfd, mhaddr + 64, L_SET);
513 perror("seek MH Block");
516 w = write(newfd, (char *)base[0], VL_ADDREXTBLK_SIZE);
517 if (w != VL_ADDREXTBLK_SIZE) {
518 perror("write MH Block");
524 /* If we are converting from version 4 to version 3, then
525 * translate any multihome ptrs in the IpMappedAddr array
526 * to true IP addresses.
528 if ((fromver == 4) && (tover == 3)) {
529 /* Step through the fileserver addresses in the VLDB header
530 * and convert the pointers back to IP addresses.
532 for (i = 0; i < 254; i++) {
533 addr = ntohl(header->IpMappedAddr[i]);
534 if (addr && ((addr & 0xff000000) == 0xff000000)) {
535 basei = (addr >> 16) & 0xff;
536 index = addr & 0xffff;
538 if ((basei >= VL_ADDREXTBLK_SIZE) || !base[basei]) {
540 "Warning: mh entry %d has no IP address; ignored!!\n",
542 header->IpMappedAddr[i] = 0;
545 exp = &base[basei][index];
547 /* For now return the first ip address back */
548 for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
549 if (exp->ex_addrs[j]) {
550 raddr = ntohl(exp->ex_addrs[j]);
554 if (j >= VL_MAXIPADDRS_PERMH) {
556 "Warning: mh entry %d has no ip address; ignored!!\n",
561 ("Multi-homed addr: converting to single ip address %d.%d.%d.%d\n",
562 (raddr >> 24 & 0xff), (raddr >> 16 & 0xff),
563 (raddr >> 8 & 0xff), (raddr & 0xff));
565 header->IpMappedAddr[i] = htonl(raddr);
568 header->SIT = mhaddr = 0; /* mhinfo block has been removed */
570 /* Now step through the hash tables in header updating them.
571 * Because we removed the mh info blocks and some entries they
572 * point to may have changed position.
575 for (i = 0; i < 8191; i++) {
576 header->VolnameHash[i] = Conv4to3(header->VolnameHash[i]);
579 for (i = 0; i < 3; i++) {
580 for (j = 0; j < 8191; j++) {
581 header->VolidHash[i][j] = Conv4to3(header->VolidHash[i][j]);
585 /* Update eofptr to take into account the removal of the mhinfo blocks */
586 header->vital_header.eofPtr = htonl(Conv4to3(dbsize));
592 convert_header(int ofd, int fd, int fromv, int tov, void *fromaddr,
595 struct vlheader_1 *tvp1;
596 struct vlheader_2 *tvp2;
601 memcpy(toaddr, fromaddr, sizeof(struct vlheader_1));
602 tvp1 = (struct vlheader_1 *)toaddr;
604 w = write(fd, tvp1, sizeof(struct vlheader_1));
605 if (w != sizeof(struct vlheader_1)) {
606 printf("Write of header failed %d; error %u\n", w, errno);
610 /* for garbage-collecting... */
611 for (i = 0; i < 31; i++)
612 tvp1->IpMappedAddr[i] = 0;
614 } else if (tov == 2 || tov == 3) {
615 tvp1 = (struct vlheader_1 *)fromaddr;
616 tvp2 = (struct vlheader_2 *)toaddr;
617 memset(tvp2, 0, sizeof(struct vlheader_2));
618 tvp2->vital_header.vldbversion = htonl(tov);
619 tvp2->vital_header.headersize = htonl(sizeof(struct vlheader_2));
621 ntohl(tvp2->vital_header.headersize) -
622 ntohl(tvp1->vital_header.headersize);
623 if (ntohl(tvp1->vital_header.freePtr))
624 tvp2->vital_header.freePtr =
625 htonl(ntohl(tvp1->vital_header.freePtr) + diff);
626 if (ntohl(tvp1->vital_header.eofPtr))
627 tvp2->vital_header.eofPtr =
628 htonl(ntohl(tvp1->vital_header.eofPtr) + diff);
629 tvp2->vital_header.allocs = tvp1->vital_header.allocs;
630 tvp2->vital_header.frees = tvp1->vital_header.frees;
631 tvp2->vital_header.MaxVolumeId = tvp1->vital_header.MaxVolumeId;
632 for (i = 0; i < 3; i++)
633 tvp2->vital_header.totalEntries[i] =
634 tvp1->vital_header.totalEntries[i];
636 for (i = 0; i < 31; i++)
637 tvp2->IpMappedAddr[i] = tvp1->IpMappedAddr[i];
639 for (i = 0; i < 8191; i++) {
640 if (ntohl(tvp1->VolnameHash[i]))
641 tvp2->VolnameHash[i] =
642 htonl(ntohl(tvp1->VolnameHash[i]) + diff);
645 for (i = 0; i < 3; i++) {
646 for (j = 0; j < 8191; j++) {
647 if (ntohl(tvp1->VolidHash[i][j]))
648 tvp2->VolidHash[i][j] =
649 htonl(ntohl(tvp1->VolidHash[i][j]) + diff);
653 w = write(fd, tvp2, sizeof(struct vlheader_2));
654 if (w != sizeof(struct vlheader_2)) {
655 printf("Write of header failed %d; error %u\n", w, errno);
659 /* for garbage-collecting... */
660 for (i = 0; i < 31; i++)
661 tvp2->IpMappedAddr[i] = 0;
664 } else if (fromv == 2 || fromv == 3 || fromv == 4) {
665 if (tov == 2 || tov == 3 || tov == 4) {
666 memcpy(toaddr, fromaddr, sizeof(struct vlheader_2));
667 tvp2 = (struct vlheader_2 *)toaddr;
668 tvp2->vital_header.vldbversion = htonl(tov);
669 w = write(fd, tvp2, sizeof(struct vlheader_2));
670 if (w != sizeof(struct vlheader_2)) {
671 printf("Write of header failed %d; error %u\n", w, errno);
675 } else if (tov == 1) {
676 tvp2 = (struct vlheader_2 *)fromaddr;
677 tvp1 = (struct vlheader_1 *)toaddr;
678 memset(tvp1, 0, sizeof(struct vlheader_1));
679 tvp1->vital_header.vldbversion = htonl(1);
680 tvp1->vital_header.headersize = htonl(sizeof(struct vlheader_1));
682 ntohl(tvp1->vital_header.headersize) -
683 ntohl(tvp2->vital_header.headersize);
684 if (ntohl(tvp2->vital_header.freePtr))
685 tvp1->vital_header.freePtr =
686 htonl(ntohl(tvp2->vital_header.freePtr) + diff);
687 if (ntohl(tvp2->vital_header.eofPtr))
688 tvp1->vital_header.eofPtr =
689 htonl(ntohl(tvp2->vital_header.eofPtr) + diff);
690 tvp1->vital_header.allocs = tvp2->vital_header.allocs;
691 tvp1->vital_header.frees = tvp2->vital_header.frees;
692 tvp1->vital_header.MaxVolumeId = tvp2->vital_header.MaxVolumeId;
693 for (i = 0; i < 3; i++)
694 tvp1->vital_header.totalEntries[i] =
695 tvp2->vital_header.totalEntries[i];
697 for (i = 0; i < 31; i++)
698 tvp1->IpMappedAddr[i] = tvp2->IpMappedAddr[i];
700 for (i = 0; i < 8191; i++) {
701 if (ntohl(tvp2->VolnameHash[i]))
702 tvp1->VolnameHash[i] =
703 htonl(ntohl(tvp2->VolnameHash[i]) + diff);
706 for (i = 0; i < 3; i++) {
707 for (j = 0; j < 8191; j++) {
708 if (ntohl(tvp2->VolidHash[i][j]))
709 tvp1->VolidHash[i][j] =
710 htonl(ntohl(tvp2->VolidHash[i][j]) + diff);
714 w = write(fd, tvp1, sizeof(struct vlheader_1));
715 if (w != sizeof(struct vlheader_2)) {
716 printf("Write of header failed %d; error %u\n", w, errno);
720 /* for garbage-collecting... */
721 for (i = 0; i < 31; i++)
722 tvp1->IpMappedAddr[i] = 0;
731 /* Convert an address pointer to a vlentry from version 4 to version 3.
732 * This involves checking if the address is after any of the four
733 * MH block and if it is, subtract the size of the MH block.
735 * In going from version 4 to 3, the mh blocks go away and all entries
736 * move up in their place. The adresses then need to be updated.
738 * Before this can be called, the routine read_mhentries must be called.
741 Conv4to3(afs_uint32 addr)
746 if (!base[0] || !addr)
750 for (i = 0; i < VL_MAX_ADDREXTBLKS; i++) {
751 if (base[i] && base[0]->ex_contaddrs[i]
752 && (addr > base[0]->ex_contaddrs[i]))
753 raddr -= VL_ADDREXTBLK_SIZE;
759 /* this only works because the vlheader struct is essentially the same
760 * from version 1 to version 2 -- that is, the first bunch of fields
761 * aren't any more or any larger, so they match up pretty well.
765 convert_vlentry(int new, int fromvers, int tovers,
766 struct vlheader_1 *oldheader, struct vlheader_1 *newheader,
767 struct vlentry_1 *vlentryp)
770 struct vlentry_3 *vl3p = (struct vlentry_3 *)vlentryp;
772 /* For mh information blocks,
773 * If going to version 4 or greater, keep the mh info block.
774 * Otherwise, don't keep it (version 3 and earlier don't have them).
776 if (vl3p->flags == VLCONTBLOCK) {
778 w = write(new, vlentryp, VL_ADDREXTBLK_SIZE);
779 if (w != VL_ADDREXTBLK_SIZE) {
780 printf("Write of mh info block failed %d; error %u\n", w,
788 if (fromvers == 2 && tovers == 3) {
791 vl.volumeId[0] = vlentryp->volumeId[0];
792 vl.volumeId[1] = vlentryp->volumeId[1];
793 vl.volumeId[2] = vlentryp->volumeId[2];
794 vl.flags = vlentryp->flags;
795 vl.LockAfsId = vlentryp->LockAfsId;
796 vl.LockTimestamp = vlentryp->LockTimestamp;
797 vl.cloneId = vlentryp->cloneId;
798 vl.nextIdHash[0] = vlentryp->nextIdHash[0];
799 vl.nextIdHash[1] = vlentryp->nextIdHash[1];
800 vl.nextIdHash[2] = vlentryp->nextIdHash[2];
801 vl.nextNameHash = vlentryp->nextNameHash;
802 memcpy(vl.name, vlentryp->name, 65);
803 for (i = 0; i < 8; i++) {
804 vl.serverNumber[i] = vlentryp->serverNumber[i];
805 vl.serverPartition[i] = vlentryp->serverPartition[i];
806 vl.serverFlags[i] = vlentryp->serverFlags[i];
809 vl.serverNumber[i] = vl.serverPartition[i] = vl.serverFlags[i] =
811 w = write(new, &vl, sizeof(struct vlentry_3));
812 if (w != sizeof(struct vlentry_3)) {
813 printf("Write of entry failed %d; error %u\n", w, errno);
818 } else if (fromvers == 3 && tovers == 2) {
820 struct vlentry_3 *xnvlentry = (struct vlentry_3 *)vlentryp;
822 memset(&vl, 0, sizeof(struct vlentry_2));
823 vl.volumeId[0] = xnvlentry->volumeId[0];
824 vl.volumeId[1] = xnvlentry->volumeId[1];
825 vl.volumeId[2] = xnvlentry->volumeId[2];
826 vl.flags = xnvlentry->flags;
827 vl.LockAfsId = xnvlentry->LockAfsId;
828 vl.LockTimestamp = xnvlentry->LockTimestamp;
829 vl.cloneId = xnvlentry->cloneId;
830 for (i = 0; i < 3; i++) {
831 if (ntohl(xnvlentry->nextIdHash[i]))
832 vl.nextIdHash[i] = xnvlentry->nextIdHash[i];
834 if (ntohl(xnvlentry->nextNameHash))
835 vl.nextNameHash = xnvlentry->nextNameHash;
836 memcpy(vl.name, xnvlentry->name, 65);
837 for (i = 0; i < 8; i++) {
838 vl.serverNumber[i] = xnvlentry->serverNumber[i];
839 vl.serverPartition[i] = xnvlentry->serverPartition[i];
840 vl.serverFlags[i] = xnvlentry->serverFlags[i];
842 w = write(new, &vl, sizeof(struct vlentry_2));
843 if (w != sizeof(struct vlentry_2)) {
844 printf("Write of entry failed %d; error %u\n", w, errno);
848 } else if (fromvers == 3 && tovers == 1) {
850 struct vlentry_3 *xnvlentry = (struct vlentry_3 *)vlentryp;
854 1 ? sizeof(struct vlheader_1) : sizeof(struct vlheader_2))
856 1 ? sizeof(struct vlheader_1) : sizeof(struct vlheader_2));
857 memset(&vl, 0, sizeof(struct vlentry_1));
858 vl.volumeId[0] = xnvlentry->volumeId[0];
859 vl.volumeId[1] = xnvlentry->volumeId[1];
860 vl.volumeId[2] = xnvlentry->volumeId[2];
861 vl.flags = xnvlentry->flags;
862 vl.LockAfsId = xnvlentry->LockAfsId;
863 vl.LockTimestamp = xnvlentry->LockTimestamp;
864 vl.cloneId = xnvlentry->cloneId;
865 for (i = 0; i < 3; i++) {
866 if (ntohl(xnvlentry->nextIdHash[i]))
868 htonl(ntohl(xnvlentry->nextIdHash[i]) + diff);
870 if (ntohl(xnvlentry->nextNameHash))
871 vl.nextNameHash = htonl(ntohl(xnvlentry->nextNameHash) + diff);
873 memcpy(vl.name, xnvlentry->name, 65);
874 for (i = 0; i < 8; i++) {
875 vl.serverNumber[i] = xnvlentry->serverNumber[i];
876 vl.serverPartition[i] = xnvlentry->serverPartition[i];
877 vl.serverFlags[i] = xnvlentry->serverFlags[i];
879 for (i = 0; i < 8; i++) {
880 s = xnvlentry->serverNumber[i];
882 if (s > MaxServers[tovers - 1]) {
884 "%s: Too Many Servers (%d) for this version!\n",
888 newheader->IpMappedAddr[s] = oldheader->IpMappedAddr[s];
891 w = write(new, &vl, sizeof(struct vlentry_1));
892 if (w != sizeof(struct vlentry_1)) {
893 printf("Write of entry failed %d; error %u\n", w, errno);
897 } else if (fromvers == 4 && tovers == 3) {
899 /* We are converting from version 4 to 3. In this conversion, mh info
900 * blocks go away and all vlentries after them move up in the vldb file.
901 * When this happens, the linked list pointers need to be updated.
903 memcpy(&vl, vlentryp, sizeof(vl));
904 for (i = 0; i < 3; i++) {
905 vl.nextIdHash[i] = Conv4to3(vl.nextIdHash[i]);
907 vl.nextNameHash = Conv4to3(vl.nextNameHash);
909 w = write(new, &vl, sizeof(vl));
910 if (w != sizeof(vl)) {
911 printf("Write of entry failed %d; error %u\n", w, errno);
918 w = write(new, vlentryp, sizeof(struct vlentry_1));
919 if (w != sizeof(struct vlentry_1)) {
920 printf("Write of entry failed %d; error %u\n", w, errno);
923 } else if (tovers == 2) {
924 w = write(new, vlentryp, sizeof(struct vlentry_2));
925 if (w != sizeof(struct vlentry_2)) {
926 printf("Write of entry failed %d; error %u\n", w, errno);
929 } else if (tovers == 3 || tovers == 4) {
930 w = write(new, vlentryp, sizeof(struct vlentry_3));
931 if (w != sizeof(struct vlentry_3)) {
932 printf("Write of entry failed %d; error %u\n", w, errno);
938 "Skipping vlentry write - db corrupted - bad toversion %d\n",
946 rewrite_header(int new, int tovers, void *newheader)
950 pos = lseek(new, 64, L_SET); /* leave room for ubik */
953 fprintf(stderr, "%s: no garbage colection\n", pn);
955 } else if (pos != 64) {
956 fprintf(stderr, "%s: Can't rewind: no garbage collection\n", pn);
962 1) ? sizeof(struct vlheader_1) : sizeof(struct vlheader_2));
963 w = write(new, newheader, towrite);
965 printf("Write of entry failed %d; error %u\n", w, errno);
973 #include "AFS_component_version_number.c"
976 main(int argc, char **argv)
978 struct cmd_syndesc *ts;
981 ts = cmd_CreateSyntax("initcmd", handleit, NULL, "optional");
982 cmd_AddParm(ts, "-to", CMD_SINGLE, CMD_OPTIONAL, "goal version");
983 cmd_AddParm(ts, "-from", CMD_SINGLE, CMD_OPTIONAL, "current version");
984 cmd_AddParm(ts, "-path", CMD_SINGLE, CMD_OPTIONAL, "pathname");
985 cmd_AddParm(ts, "-showversion", CMD_FLAG, CMD_OPTIONAL,
986 "Just display version of current vldb");
987 cmd_AddParm(ts, "-dumpvldb", CMD_FLAG, CMD_OPTIONAL,
988 "display all vldb entries");
991 cmd_AddParm(ts, "-noGC", CMD_FLAG, CMD_OPTIONAL,
992 "Don't do garbage collection");
995 dbPath = AFSDIR_SERVER_VLDB_FILEPATH;
997 code = cmd_Dispatch(argc, argv);