Skip site navigation (1)Skip section navigation (2)
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>