Fri Mar 9 16:51:04 2012 UTC ()
Pull up the following revisions(s) (requested by tsutsui in ticket #105):
	sbin/newfs_ext2fs/mke2fs.c:	revision 1.15

Fix extremely slow newfs_ext2fs(8) operation on large USB stick.


(sborrill)
diff -r1.14 -r1.14.8.1 src/sbin/newfs_ext2fs/mke2fs.c

cvs diff -r1.14 -r1.14.8.1 src/sbin/newfs_ext2fs/mke2fs.c (expand / switch to unified diff)

--- src/sbin/newfs_ext2fs/mke2fs.c 2010/09/10 15:51:20 1.14
+++ src/sbin/newfs_ext2fs/mke2fs.c 2012/03/09 16:51:04 1.14.8.1
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: mke2fs.c,v 1.14 2010/09/10 15:51:20 tsutsui Exp $ */ 1/* $NetBSD: mke2fs.c,v 1.14.8.1 2012/03/09 16:51:04 sborrill Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2007 Izumi Tsutsui. All rights reserved. 4 * Copyright (c) 2007 Izumi Tsutsui. All rights reserved.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
14 * 14 *
@@ -90,51 +90,51 @@ @@ -90,51 +90,51 @@
90 * - Ext2fs Home Page 90 * - Ext2fs Home Page
91 * http://e2fsprogs.sourceforge.net/ext2.html 91 * http://e2fsprogs.sourceforge.net/ext2.html
92 * - Design and Implementation of the Second Extended Filesystem 92 * - Design and Implementation of the Second Extended Filesystem
93 * http://e2fsprogs.sourceforge.net/ext2intro.html 93 * http://e2fsprogs.sourceforge.net/ext2intro.html
94 * - Linux Documentation "The Second Extended Filesystem" 94 * - Linux Documentation "The Second Extended Filesystem"
95 * http://www.kernel.org/doc/Documentation/filesystems/ext2.txt 95 * http://www.kernel.org/doc/Documentation/filesystems/ext2.txt
96 */ 96 */
97 97
98#include <sys/cdefs.h> 98#include <sys/cdefs.h>
99#ifndef lint 99#ifndef lint
100#if 0 100#if 0
101static char sccsid[] = "@(#)mkfs.c 8.11 (Berkeley) 5/3/95"; 101static char sccsid[] = "@(#)mkfs.c 8.11 (Berkeley) 5/3/95";
102#else 102#else
103__RCSID("$NetBSD: mke2fs.c,v 1.14 2010/09/10 15:51:20 tsutsui Exp $"); 103__RCSID("$NetBSD: mke2fs.c,v 1.14.8.1 2012/03/09 16:51:04 sborrill Exp $");
104#endif 104#endif
105#endif /* not lint */ 105#endif /* not lint */
106 106
107#include <sys/param.h> 107#include <sys/param.h>
108#include <sys/mman.h> 108#include <sys/mman.h>
109#include <sys/time.h> 109#include <sys/time.h>
110#include <ufs/ext2fs/ext2fs_dinode.h> 110#include <ufs/ext2fs/ext2fs_dinode.h>
111#include <ufs/ext2fs/ext2fs_dir.h> 111#include <ufs/ext2fs/ext2fs_dir.h>
112#include <ufs/ext2fs/ext2fs.h> 112#include <ufs/ext2fs/ext2fs.h>
113#include <sys/ioctl.h> 113#include <sys/ioctl.h>
114 114
115#include <err.h> 115#include <err.h>
116#include <errno.h> 116#include <errno.h>
117#include <string.h> 117#include <string.h>
118#include <unistd.h> 118#include <unistd.h>
119#include <stdlib.h> 119#include <stdlib.h>
120#include <stddef.h> 120#include <stddef.h>
121#include <stdio.h> 121#include <stdio.h>
122#include <uuid.h> 122#include <uuid.h>
123 123
124#include "extern.h" 124#include "extern.h"
125 125
126static void initcg(uint); 126static void initcg(uint);
127static void zap_old_sblock(daddr_t); 127static void zap_old_sblock(int);
128static uint cgoverhead(uint); 128static uint cgoverhead(uint);
129static int fsinit(const struct timeval *); 129static int fsinit(const struct timeval *);
130static int makedir(struct ext2fs_direct *, int); 130static int makedir(struct ext2fs_direct *, int);
131static void copy_dir(struct ext2fs_direct *, struct ext2fs_direct *); 131static void copy_dir(struct ext2fs_direct *, struct ext2fs_direct *);
132static void init_resizeino(const struct timeval *); 132static void init_resizeino(const struct timeval *);
133static uint32_t alloc(uint32_t, uint16_t); 133static uint32_t alloc(uint32_t, uint16_t);
134static void iput(struct ext2fs_dinode *, ino_t); 134static void iput(struct ext2fs_dinode *, ino_t);
135static void rdfs(daddr_t, int, void *); 135static void rdfs(daddr_t, int, void *);
136static void wtfs(daddr_t, int, void *); 136static void wtfs(daddr_t, int, void *);
137static int ilog2(uint); 137static int ilog2(uint);
138static int skpc(int, size_t, uint8_t *); 138static int skpc(int, size_t, uint8_t *);
139 139
140/* XXX: some of these macro should be into <ufs/ext2fs/ext2fs.h>? */ 140/* XXX: some of these macro should be into <ufs/ext2fs/ext2fs.h>? */
@@ -542,53 +542,57 @@ mke2fs(const char *fsys, int fi, int fo) @@ -542,53 +542,57 @@ mke2fs(const char *fsys, int fi, int fo)
542 iobufsize = (NBLOCK_SUPERBLOCK + sblock.e2fs_ngdb) * sblock.e2fs_bsize; 542 iobufsize = (NBLOCK_SUPERBLOCK + sblock.e2fs_ngdb) * sblock.e2fs_bsize;
543 iobuf = mmap(0, iobufsize, PROT_READ|PROT_WRITE, 543 iobuf = mmap(0, iobufsize, PROT_READ|PROT_WRITE,
544 MAP_ANON|MAP_PRIVATE, -1, 0); 544 MAP_ANON|MAP_PRIVATE, -1, 0);
545 if (iobuf == NULL) 545 if (iobuf == NULL)
546 errx(EXIT_FAILURE, "Cannot allocate I/O buffer\n"); 546 errx(EXIT_FAILURE, "Cannot allocate I/O buffer\n");
547 memset(iobuf, 0, iobufsize); 547 memset(iobuf, 0, iobufsize);
548 548
549 /* 549 /*
550 * We now start writing to the filesystem 550 * We now start writing to the filesystem
551 */ 551 */
552 552
553 if (!Nflag) { 553 if (!Nflag) {
554 static const uint pbsize[] = { 1024, 2048, 4096, 0 }; 554 static const uint pbsize[] = { 1024, 2048, 4096, 0 };
555 uint pblock, epblock; 555 uint pblock;
556 /* 556 /*
557 * Validate the given file system size. 557 * Validate the given file system size.
558 * Verify that its last block can actually be accessed. 558 * Verify that its last block can actually be accessed.
559 * Convert to file system fragment sized units. 559 * Convert to file system fragment sized units.
560 */ 560 */
561 if (fssize <= 0) 561 if (fssize <= 0)
562 errx(EXIT_FAILURE, "Preposterous size %" PRId64 "\n", 562 errx(EXIT_FAILURE, "Preposterous size %" PRId64 "\n",
563 fssize); 563 fssize);
564 wtfs(fssize - 1, sectorsize, iobuf); 564 wtfs(fssize - 1, sectorsize, iobuf);
565 565
566 /* 566 /*
567 * Ensure there is nothing that looks like a filesystem 567 * Ensure there is nothing that looks like a filesystem
568 * superblock anywhere other than where ours will be. 568 * superblock anywhere other than where ours will be.
569 * If fsck_ext2fs finds the wrong one all hell breaks loose! 
570 * 569 *
571 * XXX: needs to check how fsck_ext2fs programs even 570 * Ext2fs superblock is always placed at the same SBOFF,
572 * on other OSes determine alternate superblocks 571 * so we just zap possible first backups.
573 */ 572 */
574 for (i = 0; pbsize[i] != 0; i++) { 573 for (i = 0; pbsize[i] != 0; i++) {
575 epblock = (uint64_t)bcount * bsize / pbsize[i]; 574 pblock = (pbsize[i] > BBSIZE) ? 0 : 1; /* 1st dblk */
576 for (pblock = ((pbsize[i] == SBSIZE) ? 1 : 0); 575 pblock += pbsize[i] * NBBY; /* next bg */
577 pblock < epblock; 576 /* zap first backup */
578 pblock += pbsize[i] * NBBY /* bpg */) 577 zap_old_sblock(pblock * pbsize[i]);
579 zap_old_sblock((daddr_t)pblock * 
580 pbsize[i] / sectorsize); 
581 } 578 }
 579 /*
 580 * Also zap possbile FFS magic leftover to prevent
 581 * kernel vfs_mountroot() and bootloadres from mis-recognizing
 582 * this file system as FFS.
 583 */
 584 zap_old_sblock(8192); /* SBLOCK_UFS1 */
 585 zap_old_sblock(65536); /* SBLOCK_UFS2 */
582 } 586 }
583 587
584 if (verbosity >= 3) 588 if (verbosity >= 3)
585 printf("super-block backups (for fsck_ext2fs -b #) at:\n"); 589 printf("super-block backups (for fsck_ext2fs -b #) at:\n");
586 /* If we are printing more than one line of numbers, line up columns */ 590 /* If we are printing more than one line of numbers, line up columns */
587 fld_width = verbosity < 4 ? 1 : snprintf(NULL, 0, "%" PRIu64, 591 fld_width = verbosity < 4 ? 1 : snprintf(NULL, 0, "%" PRIu64,
588 (uint64_t)cgbase(&sblock, ncg - 1)); 592 (uint64_t)cgbase(&sblock, ncg - 1));
589 /* Get terminal width */ 593 /* Get terminal width */
590 if (ioctl(fileno(stdout), TIOCGWINSZ, &winsize) == 0) 594 if (ioctl(fileno(stdout), TIOCGWINSZ, &winsize) == 0)
591 max_cols = winsize.ws_col; 595 max_cols = winsize.ws_col;
592 else 596 else
593 max_cols = 80; 597 max_cols = 80;
594 if (Nflag && verbosity == 3) 598 if (Nflag && verbosity == 3)
@@ -759,91 +763,92 @@ initcg(uint cylno) @@ -759,91 +763,92 @@ initcg(uint cylno)
759 dp = (struct ext2fs_dinode *)(buf + inodesize * j); 763 dp = (struct ext2fs_dinode *)(buf + inodesize * j);
760 /* h2fs32() just for consistency */ 764 /* h2fs32() just for consistency */
761 dp->e2di_gen = h2fs32(arc4random()); 765 dp->e2di_gen = h2fs32(arc4random());
762 } 766 }
763 wtfs(fsbtodb(&sblock, gd[cylno].ext2bgd_i_tables + i), 767 wtfs(fsbtodb(&sblock, gd[cylno].ext2bgd_i_tables + i),
764 sblock.e2fs_bsize, buf); 768 sblock.e2fs_bsize, buf);
765 } 769 }
766} 770}
767 771
768/* 772/*
769 * Zap possible lingering old superblock data 773 * Zap possible lingering old superblock data
770 */ 774 */
771static void 775static void
772zap_old_sblock(daddr_t sec) 776zap_old_sblock(int sblkoff)
773{ 777{
774 static daddr_t cg0_data; 778 static int cg0_data;
775 uint32_t oldfs[SBSIZE / sizeof(uint32_t)]; 779 uint32_t oldfs[SBSIZE / sizeof(uint32_t)];
776 static const struct fsm { 780 static const struct fsm {
777 uint32_t offset; 781 uint32_t offset;
778 uint32_t magic; 782 uint32_t magic;
779 uint32_t mask; 783 uint32_t mask;
780 } fs_magics[] = { 784 } fs_magics[] = {
781 {offsetof(struct ext2fs, e2fs_magic) / 4, E2FS_MAGIC, 0xffff}, 785 {offsetof(struct ext2fs, e2fs_magic) / 4, E2FS_MAGIC, 0xffff},
782 {offsetof(struct ext2fs, e2fs_magic) / 4, 786 {offsetof(struct ext2fs, e2fs_magic) / 4,
783 E2FS_MAGIC << 16, 0xffff0000}, 787 E2FS_MAGIC << 16, 0xffff0000},
784 {14, 0xef530000, 0xffff0000}, /* EXT2FS (big) */ 788 {14, 0xef530000, 0xffff0000}, /* EXT2FS (big) */
785 {0x55c / 4, 0x00011954, ~0U}, /* FS_UFS1_MAGIC */ 789 {0x55c / 4, 0x00011954, ~0U}, /* FS_UFS1_MAGIC */
786 {0x55c / 4, 0x19540119, ~0U}, /* FS_UFS2_MAGIC */ 790 {0x55c / 4, 0x19540119, ~0U}, /* FS_UFS2_MAGIC */
787 {0, 0x70162, ~0U}, /* LFS_MAGIC */ 791 {0, 0x70162, ~0U}, /* LFS_MAGIC */
788 {.offset = ~0U}, 792 {.offset = ~0U},
789 }; 793 };
790 const struct fsm *fsm; 794 const struct fsm *fsm;
791 795
792 if (Nflag) 796 if (Nflag)
793 return; 797 return;
794 798
795 /* don't override data before superblock */ 799 /* don't override data before superblock */
796 if (sec < SBOFF / sectorsize) 800 if (sblkoff < SBOFF)
797 return; 801 return;
798 802
799 if (cg0_data == 0) { 803 if (cg0_data == 0) {
800 cg0_data = 804 cg0_data =
801 ((daddr_t)sblock.e2fs.e2fs_first_dblock + cgoverhead(0)) * 805 ((daddr_t)sblock.e2fs.e2fs_first_dblock + cgoverhead(0)) *
802 sblock.e2fs_bsize / sectorsize; 806 sblock.e2fs_bsize;
803 } 807 }
804 808
805 /* Ignore anything that is beyond our filesystem */ 809 /* Ignore anything that is beyond our filesystem */
806 if (sec >= fssize) 810 if (sblkoff / sectorsize >= fssize)
807 return; 811 return;
808 /* Zero anything inside our filesystem... */ 812 /* Zero anything inside our filesystem... */
809 if (sec >= sblock.e2fs.e2fs_first_dblock * bsize / sectorsize) { 813 if (sblkoff >= sblock.e2fs.e2fs_first_dblock * bsize) {
810 /* ...unless we will write that area anyway */ 814 /* ...unless we will write that area anyway */
811 if (sec >= cg0_data) 815 if (sblkoff >= cg0_data)
812 /* assume iobuf is zero'ed here */ 816 /* assume iobuf is zero'ed here */
813 wtfs(sec, roundup(SBSIZE, sectorsize), iobuf); 817 wtfs(sblkoff / sectorsize,
 818 roundup(SBSIZE, sectorsize), iobuf);
814 return; 819 return;
815 } 820 }
816 821
817 /* 822 /*
818 * The sector might contain boot code, so we must validate it 823 * The sector might contain boot code, so we must validate it
819 * 824 *
820 * XXX: ext2fs won't preserve data after SBOFF, 825 * XXX: ext2fs won't preserve data after SBOFF,
821 * but first_dblock could have a different value. 826 * but first_dblock could have a different value.
822 */ 827 */
823 rdfs(sec, sizeof(oldfs), &oldfs); 828 rdfs(sblkoff / sectorsize, sizeof(oldfs), &oldfs);
824 for (fsm = fs_magics;; fsm++) { 829 for (fsm = fs_magics;; fsm++) {
825 uint32_t v; 830 uint32_t v;
826 if (fsm->mask == 0) 831 if (fsm->mask == 0)
827 return; 832 return;
828 v = oldfs[fsm->offset]; 833 v = oldfs[fsm->offset];
829 if ((v & fsm->mask) == fsm->magic || 834 if ((v & fsm->mask) == fsm->magic ||
830 (bswap32(v) & fsm->mask) == fsm->magic) 835 (bswap32(v) & fsm->mask) == fsm->magic)
831 break; 836 break;
832 } 837 }
833 838
834 /* Just zap the magic number */ 839 /* Just zap the magic number */
835 oldfs[fsm->offset] = 0; 840 oldfs[fsm->offset] = 0;
836 wtfs(sec, sizeof(oldfs), &oldfs); 841 wtfs(sblkoff / sectorsize, sizeof(oldfs), &oldfs);
837} 842}
838 843
839/* 844/*
840 * uint cgoverhead(uint c) 845 * uint cgoverhead(uint c)
841 * 846 *
842 * Return a number of reserved blocks on the specified group. 847 * Return a number of reserved blocks on the specified group.
843 * XXX: should be shared with src/sbin/fsck_ext2fs/setup.c 848 * XXX: should be shared with src/sbin/fsck_ext2fs/setup.c
844 */ 849 */
845uint 850uint
846cgoverhead(uint c) 851cgoverhead(uint c)
847{ 852{
848 uint overh; 853 uint overh;
849 854