Added option to cluster-align the start of the root directory.
Obtained from: Android Obtained from:052f275621
Obtained from:8218b6aae9
MFC after: 1 month Differential Revision: https://reviews.freebsd.org/D15672
This commit is contained in:
parent
982cd953f3
commit
284893ba03
@ -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;
|
||||
|
@ -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 track")
|
||||
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;
|
||||
|
@ -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 in the device or file.
|
||||
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
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user