Date: Fri, 15 Jun 2018 06:03:41 +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: r335189 - head/sbin/newfs_msdos Message-ID: <201806150603.w5F63fXk090717@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: delphij Date: Fri Jun 15 06:03:40 2018 New Revision: 335189 URL: https://svnweb.freebsd.org/changeset/base/335189 Log: Added option to cluster-align the start of the root directory. Obtained from: Android Obtained from: https://android.googlesource.com/platform/system/core/+/052f27562154d175267999106bd6bf18fc8c363e Obtained from: https://android.googlesource.com/platform/system/core/+/8218b6aae9cd4a19fa074a8a8203fe9275b35447 MFC after: 1 month Differential Revision: https://reviews.freebsd.org/D15672 Modified: head/sbin/newfs_msdos/mkfs_msdos.c head/sbin/newfs_msdos/mkfs_msdos.h head/sbin/newfs_msdos/newfs_msdos.8 head/sbin/newfs_msdos/newfs_msdos.c Modified: head/sbin/newfs_msdos/mkfs_msdos.c ============================================================================== --- head/sbin/newfs_msdos/mkfs_msdos.c Fri Jun 15 03:31:30 2018 (r335188) +++ head/sbin/newfs_msdos/mkfs_msdos.c Fri Jun 15 06:03:40 2018 (r335189) @@ -242,6 +242,8 @@ mkfs_msdos(const char *fname, const char *dtype, const ssize_t n; time_t now; u_int fat, bss, rds, cls, dir, lsn, x, x1, x2; + u_int extra_res, alignment, saved_x, attempts=0; + bool set_res, set_spf, set_spc; int fd, fd1, rv; struct msdos_options o = *op; @@ -486,50 +488,83 @@ mkfs_msdos(const char *fname, const char *dtype, const if (bpb.bpbBackup != MAXU16 && x <= bpb.bpbBackup) x = bpb.bpbBackup + 1; } - if (!bpb.bpbResSectors) - bpb.bpbResSectors = fat == 32 ? - MAX(x, MAX(16384 / bpb.bpbBytesPerSec, 4)) : x; - else if (bpb.bpbResSectors < x) { - warnx("too few reserved sectors (need %d have %d)", x, - bpb.bpbResSectors); - goto done; - } - if (fat != 32 && !bpb.bpbRootDirEnts) - bpb.bpbRootDirEnts = DEFRDE; - rds = howmany(bpb.bpbRootDirEnts, bpb.bpbBytesPerSec / sizeof(struct de)); - if (!bpb.bpbSecPerClust) - for (bpb.bpbSecPerClust = howmany(fat == 16 ? DEFBLK16 : - DEFBLK, bpb.bpbBytesPerSec); - bpb.bpbSecPerClust < MAXSPC && - bpb.bpbResSectors + - howmany((RESFTE + maxcls(fat)) * (fat / BPN), - bpb.bpbBytesPerSec * NPB) * - bpb.bpbFATs + - rds + - (u_int64_t) (maxcls(fat) + 1) * - bpb.bpbSecPerClust <= bpb.bpbHugeSectors; - bpb.bpbSecPerClust <<= 1) - continue; - if (fat != 32 && bpb.bpbBigFATsecs > MAXU16) { - warnx("too many sectors/FAT for FAT12/16"); - goto done; - } - x1 = bpb.bpbResSectors + rds; - x = bpb.bpbBigFATsecs ? bpb.bpbBigFATsecs : 1; - if (x1 + (u_int64_t)x * bpb.bpbFATs > bpb.bpbHugeSectors) { - warnx("meta data exceeds file system size"); - goto done; - } - x1 += x * bpb.bpbFATs; - x = (u_int64_t)(bpb.bpbHugeSectors - x1) * bpb.bpbBytesPerSec * NPB / - (bpb.bpbSecPerClust * bpb.bpbBytesPerSec * NPB + fat / - BPN * bpb.bpbFATs); - x2 = howmany((RESFTE + MIN(x, maxcls(fat))) * (fat / BPN), - bpb.bpbBytesPerSec * NPB); - if (!bpb.bpbBigFATsecs) { - bpb.bpbBigFATsecs = x2; - x1 += (bpb.bpbBigFATsecs - 1) * bpb.bpbFATs; - } + + extra_res = 0; + alignment = 0; + set_res = (bpb.bpbResSectors == 0); + set_spf = (bpb.bpbBigFATsecs == 0); + set_spc = (bpb.bpbSecPerClust == 0); + saved_x = x; + + /* + * Attempt to align the root directory to cluster if o.align is set. + * This is done by padding with reserved blocks. Note that this can + * cause other factors to change, which can in turn change the alignment. + * This should take at most 2 iterations, as increasing the reserved + * amount may cause the FAT size to decrease by 1, requiring another + * bpbFATs reserved blocks. If bpbSecPerClust changes, it will + * be half of its previous size, and thus will not throw off alignment. + */ + do { + x = saved_x; + if (set_res) + bpb.bpbResSectors = ((fat == 32) ? + MAX(x, MAX(16384 / bpb.bpbBytesPerSec, 4)) : x) + extra_res; + else if (bpb.bpbResSectors < x) { + warnx("too few reserved sectors (need %d have %d)", x, + bpb.bpbResSectors); + goto done; + } + if (fat != 32 && !bpb.bpbRootDirEnts) + bpb.bpbRootDirEnts = DEFRDE; + rds = howmany(bpb.bpbRootDirEnts, + bpb.bpbBytesPerSec / sizeof(struct de)); + if (set_spc) { + for (bpb.bpbSecPerClust = howmany(fat == 16 ? DEFBLK16 : + DEFBLK, bpb.bpbBytesPerSec); + bpb.bpbSecPerClust < MAXSPC && (bpb.bpbResSectors + + howmany((RESFTE + maxcls(fat)) * (fat / BPN), + bpb.bpbBytesPerSec * NPB) * bpb.bpbFATs + + rds + + (u_int64_t) (maxcls(fat) + 1) * bpb.bpbSecPerClust) <= + bpb.bpbHugeSectors; + bpb.bpbSecPerClust <<= 1) + continue; + + } + if (fat != 32 && bpb.bpbBigFATsecs > MAXU16) { + warnx("too many sectors/FAT for FAT12/16"); + goto done; + } + x1 = bpb.bpbResSectors + rds; + x = bpb.bpbBigFATsecs ? bpb.bpbBigFATsecs : 1; + if (x1 + (u_int64_t)x * bpb.bpbFATs > bpb.bpbHugeSectors) { + warnx("meta data exceeds file system size"); + goto done; + } + x1 += x * bpb.bpbFATs; + x = (u_int64_t)(bpb.bpbHugeSectors - x1) * bpb.bpbBytesPerSec * NPB / + (bpb.bpbSecPerClust * bpb.bpbBytesPerSec * NPB + + fat / BPN * bpb.bpbFATs); + x2 = howmany((RESFTE + MIN(x, maxcls(fat))) * (fat / BPN), + bpb.bpbBytesPerSec * NPB); + if (set_spf) { + if (bpb.bpbBigFATsecs == 0) + bpb.bpbBigFATsecs = x2; + x1 += (bpb.bpbBigFATsecs - 1) * bpb.bpbFATs; + } + if (set_res) { + /* attempt to align root directory */ + alignment = (bpb.bpbResSectors + bpb.bpbBigFATsecs * bpb.bpbFATs) % + bpb.bpbSecPerClust; + if (o.align) + extra_res += bpb.bpbSecPerClust - alignment; + } + attempts++; + } while (o.align && alignment != 0 && attempts < 2); + if (o.align && alignment != 0) + warnx("warning: Alignment failed."); + cls = (bpb.bpbHugeSectors - x1) / bpb.bpbSecPerClust; x = (u_int64_t)bpb.bpbBigFATsecs * bpb.bpbBytesPerSec * NPB / (fat / BPN) - RESFTE; Modified: head/sbin/newfs_msdos/mkfs_msdos.h ============================================================================== --- head/sbin/newfs_msdos/mkfs_msdos.h Fri Jun 15 03:31:30 2018 (r335188) +++ head/sbin/newfs_msdos/mkfs_msdos.h Fri Jun 15 06:03:40 2018 (r335189) @@ -34,6 +34,7 @@ #include <stdbool.h> #define ALLOPTS \ AOPT('@', off_t, offset, 0, "Offset in device") \ +AOPT('A', bool, align, -2, "Attempt to cluster align root directory") \ AOPT('B', const char *, bootstrap, -1, "Bootstrap file") \ AOPT('C', off_t, create_size, 0, "Create file") \ AOPT('F', uint8_t, fat_type, 12, "FAT type (12, 16, or 32)") \ @@ -61,7 +62,7 @@ AOPT('u', uint16_t, sectors_per_track, 1, "Sectors per struct msdos_options { #define AOPT(_opt, _type, _name, _min, _desc) _type _name; ALLOPTS -#undef AOPT +#undef AOPT uint32_t timestamp_set:1; uint32_t volume_id_set:1; uint32_t media_descriptor_set:1; Modified: head/sbin/newfs_msdos/newfs_msdos.8 ============================================================================== --- head/sbin/newfs_msdos/newfs_msdos.8 Fri Jun 15 03:31:30 2018 (r335188) +++ head/sbin/newfs_msdos/newfs_msdos.8 Fri Jun 15 06:03:40 2018 (r335189) @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd May 16, 2017 +.Dd June 14, 2018 .Dt NEWFS_MSDOS 8 .Os .Sh NAME @@ -35,6 +35,7 @@ .Nm .Op Fl N .Op Fl @ Ar offset +.Op Fl A .Op Fl B Ar boot .Op Fl C Ar create-size .Op Fl F Ar FAT-type @@ -91,6 +92,8 @@ Build the filesystem at the specified offset in bytes A suffix s, k, m, g (lower or upper case) appended to the offset specifies that the number is in sectors, kilobytes, megabytes or gigabytes, respectively. +.It Fl A +Attempt to cluster align root directory, useful for SD card. .It Fl B Ar boot Get bootstrap from file. .It Fl C Ar create-size Modified: head/sbin/newfs_msdos/newfs_msdos.c ============================================================================== --- head/sbin/newfs_msdos/newfs_msdos.c Fri Jun 15 03:31:30 2018 (r335188) +++ head/sbin/newfs_msdos/newfs_msdos.c Fri Jun 15 06:03:40 2018 (r335189) @@ -76,7 +76,7 @@ get_tstamp(const char *b) int main(int argc, char *argv[]) { - static const char opts[] = "@:NB:C:F:I:L:O:S:a:b:c:e:f:h:i:k:m:n:o:r:s:T:u:"; + static const char opts[] = "@:NAB:C:F:I:L:O:S:a:b:c:e:f:h:i:k:m:n:o:r:s:T:u:"; struct msdos_options o; const char *fname, *dtype; char buf[MAXPATHLEN]; @@ -92,6 +92,9 @@ main(int argc, char *argv[]) case 'N': o.no_create = 1; break; + case 'A': + o.align = true; + break; case 'B': o.bootstrap = optarg; break; @@ -175,6 +178,10 @@ main(int argc, char *argv[]) argv += optind; if (argc < 1 || argc > 2) usage(); + if (o.align) { + if (o.hidden_sectors_set) + errx(1, "align (-A) is incompatible with -r"); + } fname = *argv++; if (!o.create_size && !strchr(fname, '/')) { snprintf(buf, sizeof(buf), "%s%s", _PATH_DEV, fname);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201806150603.w5F63fXk090717>