summaryrefslogtreecommitdiff
path: root/mkfs_msdos.c
diff options
context:
space:
mode:
authorXin Li <delphij@google.com>2018-06-18 17:30:37 -0700
committerElliott Hughes <enh@google.com>2018-06-19 17:06:52 +0000
commit4d60a2217e117949a24e9d9401539d742211d461 (patch)
tree62eb8f9177960d43ce3cc65cc18908780e6f0bf3 /mkfs_msdos.c
parent6d2f393ed5bb34dff8868223e334016b374b3889 (diff)
downloadnewfs_msdos-4d60a2217e117949a24e9d9401539d742211d461.tar.gz
Integrate FreeBSD r335189 for -A option.
Bug: 110053628 Change-Id: Ic59054c7e13849b392971746cdaa901f11552fca
Diffstat (limited to 'mkfs_msdos.c')
-rw-r--r--mkfs_msdos.c125
1 files changed, 80 insertions, 45 deletions
diff --git a/mkfs_msdos.c b/mkfs_msdos.c
index 1697e21..a10f769 100644
--- a/mkfs_msdos.c
+++ b/mkfs_msdos.c
@@ -27,7 +27,7 @@
#ifndef lint
static const char rcsid[] =
- "$FreeBSD: head/sbin/newfs_msdos/mkfs_msdos.c 327570 2018-01-05 05:34:14Z imp $";
+ "$FreeBSD: head/sbin/newfs_msdos/mkfs_msdos.c 335189 2018-06-15 06:03:40Z delphij $";
#endif /* not lint */
#include <sys/param.h>
@@ -242,6 +242,8 @@ mkfs_msdos(const char *fname, const char *dtype, const struct msdos_options *op)
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 struct msdos_options *op)
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;