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);
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to