Date: Sat, 4 Jul 2020 18:37:04 +0000 (UTC) From: Xin LI <delphij@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r362936 - head/sbin/newfs_msdos Message-ID: <202007041837.064Ib4PL082461@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: delphij Date: Sat Jul 4 18:37:04 2020 New Revision: 362936 URL: https://svnweb.freebsd.org/changeset/base/362936 Log: Gather writes to larger chunks (MAXPHYS) instead of issuing them in sectors. On my SanDisk Cruzer Blade 16GB USB stick this made formatting much faster: x before + after +--------------------------------------------------------------------------+ |+ | |+ x | |+ x x| |A MA|| +--------------------------------------------------------------------------+ N Min Max Median Avg Stddev x 3 15.89 16.38 16 16.09 0.2570992 + 3 0.32 0.37 0.35 0.34666667 0.025166115 Difference at 95.0% confidence -15.7433 +/- 0.414029 -97.8455% +/- 0.25668% (Student's t, pooled s = 0.182665) Reviewed by: emaste MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D24508 Modified: head/sbin/newfs_msdos/mkfs_msdos.c Modified: head/sbin/newfs_msdos/mkfs_msdos.c ============================================================================== --- head/sbin/newfs_msdos/mkfs_msdos.c Sat Jul 4 18:01:29 2020 (r362935) +++ head/sbin/newfs_msdos/mkfs_msdos.c Sat Jul 4 18:37:04 2020 (r362936) @@ -64,6 +64,7 @@ static const char rcsid[] = #define DOSMAGIC 0xaa55 /* DOS magic number */ #define MINBPS 512 /* minimum bytes per sector */ +#define MAXBPS 4096 /* maximum bytes per sector */ #define MAXSPC 128 /* maximum sectors per cluster */ #define MAXNFT 16 /* maximum number of FATs */ #define DEFBLK 4096 /* default block size */ @@ -77,6 +78,25 @@ static const char rcsid[] = #define MAXCLS16 0xfff4U /* maximum FAT16 clusters */ #define MAXCLS32 0xffffff4U /* maximum FAT32 clusters */ +#ifndef CTASSERT +#define CTASSERT(x) _CTASSERT(x, __LINE__) +#define _CTASSERT(x, y) __CTASSERT(x, y) +#define __CTASSERT(x, y) typedef char __assert_ ## y [(x) ? 1 : -1] +#endif + +/* + * For better performance, we want to write larger chunks instead of + * individual sectors (the size can only be 512, 1024, 2048 or 4096 + * bytes). Assert that MAXPHYS can always hold an integer number of + * sectors by asserting that both are power of two numbers and the + * MAXPHYS is greater than MAXBPS. + */ +CTASSERT(powerof2(MAXPHYS)); +CTASSERT(powerof2(MAXBPS)); +CTASSERT(MAXPHYS > MAXBPS); + +const static ssize_t chunksize = MAXPHYS; + #define mincls(fat) ((fat) == 12 ? MINCLS12 : \ (fat) == 16 ? MINCLS16 : \ MINCLS32) @@ -243,6 +263,7 @@ mkfs_msdos(const char *fname, const char *dtype, const struct bsx *bsx; struct de *de; u_int8_t *img; + u_int8_t *physbuf, *physbuf_end; const char *bname; ssize_t n; time_t now; @@ -252,7 +273,7 @@ mkfs_msdos(const char *fname, const char *dtype, const int fd, fd1, rv; struct msdos_options o = *op; - img = NULL; + physbuf = NULL; rv = -1; fd = fd1 = -1; @@ -343,15 +364,13 @@ mkfs_msdos(const char *fname, const char *dtype, const bpb.bpbSecPerClust = 64; /* otherwise 32k */ } } - if (!powerof2(bpb.bpbBytesPerSec)) { - warnx("bytes/sector (%u) is not a power of 2", bpb.bpbBytesPerSec); + if (bpb.bpbBytesPerSec < MINBPS || + bpb.bpbBytesPerSec > MAXBPS || + !powerof2(bpb.bpbBytesPerSec)) { + warnx("Invalid bytes/sector (%u): must be 512, 1024, 2048 or 4096", + bpb.bpbBytesPerSec); goto done; } - if (bpb.bpbBytesPerSec < MINBPS) { - warnx("bytes/sector (%u) is too small; minimum is %u", - bpb.bpbBytesPerSec, MINBPS); - goto done; - } if (o.volume_label && !oklabel(o.volume_label)) { warnx("%s: bad volume label", o.volume_label); @@ -621,11 +640,14 @@ mkfs_msdos(const char *fname, const char *dtype, const tm = localtime(&now); } - - if (!(img = malloc(bpb.bpbBytesPerSec))) { + physbuf = malloc(chunksize); + if (physbuf == NULL) { warn(NULL); goto done; } + physbuf_end = physbuf + chunksize; + img = physbuf; + dir = bpb.bpbResSectors + (bpb.bpbFATsecs ? bpb.bpbFATsecs : bpb.bpbBigFATsecs) * bpb.bpbFATs; memset(&si_sa, 0, sizeof(si_sa)); @@ -750,19 +772,37 @@ mkfs_msdos(const char *fname, const char *dtype, const (u_int)tm->tm_mday; mk2(de->deMDate, x); } - if ((n = write(fd, img, bpb.bpbBytesPerSec)) == -1) { - warn("%s", fname); - goto done; + /* + * Issue a write of chunksize once we have collected + * enough sectors. + */ + img += bpb.bpbBytesPerSec; + if (img >= physbuf_end) { + n = write(fd, physbuf, chunksize); + if (n != chunksize) { + warnx("%s: can't write sector %u", fname, lsn); + goto done; + } + img = physbuf; } - if ((unsigned)n != bpb.bpbBytesPerSec) { - warnx("%s: can't write sector %u", fname, lsn); - goto done; - } } + /* + * Write remaining sectors, if the last write didn't end + * up filling a whole chunk. + */ + if (img != physbuf) { + ssize_t tailsize = img - physbuf; + + n = write(fd, physbuf, tailsize); + if (n != tailsize) { + warnx("%s: can't write sector %u", fname, lsn); + goto done; + } + } } rv = 0; done: - free(img); + free(physbuf); if (fd != -1) close(fd); if (fd1 != -1)
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202007041837.064Ib4PL082461>