mkdosfs: by default align all structures to cluster boundaries
Align all data structures (reserved sectors, FATs, root directory for FAT12/16) to an even multiple of the cluster size. This means that if the partition is aligned, so will all clusters be. This adds significant performance for anything where the physical sector size is larger than the logical sector size, e.g. flash media or large-sector hard disks. Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
This commit is contained in:
parent
171bc07b0c
commit
247ba068d4
@ -6,6 +6,9 @@
|
||||
.SH SYNOPSIS
|
||||
.B mkdosfs|mkfs.msdos|mkfs.vfat
|
||||
[
|
||||
.B \-a
|
||||
]
|
||||
[
|
||||
.B \-A
|
||||
]
|
||||
[
|
||||
@ -82,6 +85,14 @@ is the number of blocks on the device. If omitted,
|
||||
automatically determines the file system size.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B \-a
|
||||
Normally, for any filesystem except very small ones, \fBmkdosfs\fP
|
||||
will align all the data structures to cluster size, to make sure that
|
||||
as long as the partition is properly aligned, so will all the data
|
||||
structures in the filesystem. This option disables alignment; this
|
||||
may provide a handful of additional clusters of storage at the expense
|
||||
of much performance on flash media or large-sector hard disks.
|
||||
.TP
|
||||
.B \-A
|
||||
Use Atari variation of the MS-DOS file system. This is default if
|
||||
\fBmkdosfs\fP is run on an Atari, then this option turns off Atari
|
||||
|
||||
@ -311,6 +311,7 @@ static int root_dir_entries = 0; /* Number of root directory entries */
|
||||
static char *blank_sector; /* Blank sector - all zeros */
|
||||
static int hidden_sectors = 0; /* Number of hidden sectors */
|
||||
static int malloc_entire_fat = FALSE; /* Whether we should malloc() the entire FAT or not */
|
||||
static int align_structures = TRUE; /* Whether to enforce alignment */
|
||||
|
||||
/* Function prototype definitions */
|
||||
|
||||
@ -784,6 +785,18 @@ establish_params (int device_num,int size)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If alignment is enabled, round the first argument up to the second; the
|
||||
* latter must be a power of two.
|
||||
*/
|
||||
static unsigned int
|
||||
align_object (unsigned int sectors, unsigned int clustsize)
|
||||
{
|
||||
if (align_structures)
|
||||
return (sectors + clustsize - 1) & ~(clustsize - 1);
|
||||
else
|
||||
return sectors;
|
||||
}
|
||||
|
||||
/* Create the filesystem data tables */
|
||||
|
||||
@ -792,7 +805,6 @@ setup_tables (void)
|
||||
{
|
||||
unsigned num_sectors;
|
||||
unsigned cluster_count = 0, fat_length;
|
||||
unsigned fatdata; /* Sectors for FATs + data area */
|
||||
struct tm *ctime;
|
||||
struct msdos_volume_info *vi = (size_fat == 32 ? &bs.fat32.vi : &bs.oldfat.vi);
|
||||
|
||||
@ -887,13 +899,24 @@ setup_tables (void)
|
||||
|
||||
num_sectors = (long long)blocks*BLOCK_SIZE/sector_size;
|
||||
if (!atari_format) {
|
||||
unsigned fatdata1216; /* Sectors for FATs + data area (FAT12/16) */
|
||||
unsigned fatdata32; /* Sectors for FATs + data area (FAT32) */
|
||||
unsigned fatlength12, fatlength16, fatlength32;
|
||||
unsigned maxclust12, maxclust16, maxclust32;
|
||||
unsigned clust12, clust16, clust32;
|
||||
int maxclustsize;
|
||||
unsigned root_dir_sectors = cdiv(root_dir_entries*32, sector_size);
|
||||
|
||||
fatdata = num_sectors - cdiv (root_dir_entries * 32, sector_size) -
|
||||
reserved_sectors;
|
||||
/*
|
||||
* If the filesystem is 8192 sectors or less (4 MB with 512-byte
|
||||
* sectors, i.e. floppy size), don't align the data structures.
|
||||
*/
|
||||
if (num_sectors <= 8192) {
|
||||
if (align_structures && verbose >= 2)
|
||||
printf ("Disabling alignment due to tiny filesystem\n");
|
||||
|
||||
align_structures = FALSE;
|
||||
}
|
||||
|
||||
if (sectors_per_cluster)
|
||||
bs.cluster_size = maxclustsize = sectors_per_cluster;
|
||||
@ -901,22 +924,25 @@ setup_tables (void)
|
||||
/* An initial guess for bs.cluster_size should already be set */
|
||||
maxclustsize = 128;
|
||||
|
||||
if (verbose >= 2)
|
||||
printf( "%d sectors for FAT+data, starting with %d sectors/cluster\n",
|
||||
fatdata, bs.cluster_size );
|
||||
do {
|
||||
fatdata32 = num_sectors
|
||||
- align_object(reserved_sectors, bs.cluster_size);
|
||||
fatdata1216 = fatdata32
|
||||
- align_object(root_dir_sectors, bs.cluster_size);
|
||||
|
||||
if (verbose >= 2)
|
||||
printf( "Trying with %d sectors/cluster:\n", bs.cluster_size );
|
||||
|
||||
/* The factor 2 below avoids cut-off errors for nr_fats == 1.
|
||||
* The "nr_fats*3" is for the reserved first two FAT entries */
|
||||
clust12 = 2*((long long) fatdata *sector_size + nr_fats*3) /
|
||||
clust12 = 2*((long long) fatdata1216*sector_size + nr_fats*3) /
|
||||
(2*(int) bs.cluster_size * sector_size + nr_fats*3);
|
||||
fatlength12 = cdiv (((clust12+2) * 3 + 1) >> 1, sector_size);
|
||||
fatlength12 = cdiv(((clust12+2) * 3 + 1) >> 1, sector_size);
|
||||
fatlength12 = align_object(fatlength12, bs.cluster_size);
|
||||
/* Need to recalculate number of clusters, since the unused parts of the
|
||||
* FATS and data area together could make up space for an additional,
|
||||
* not really present cluster. */
|
||||
clust12 = (fatdata - nr_fats*fatlength12)/bs.cluster_size;
|
||||
clust12 = (fatdata1216 - nr_fats*fatlength12)/bs.cluster_size;
|
||||
maxclust12 = (fatlength12 * 2 * sector_size) / 3;
|
||||
if (maxclust12 > MAX_CLUST_12)
|
||||
maxclust12 = MAX_CLUST_12;
|
||||
@ -929,13 +955,14 @@ setup_tables (void)
|
||||
printf( "FAT12: too much clusters\n" );
|
||||
}
|
||||
|
||||
clust16 = ((long long) fatdata *sector_size + nr_fats*4) /
|
||||
clust16 = ((long long) fatdata1216 *sector_size + nr_fats*4) /
|
||||
((int) bs.cluster_size * sector_size + nr_fats*2);
|
||||
fatlength16 = cdiv ((clust16+2) * 2, sector_size);
|
||||
fatlength16 = align_object(fatlength16, bs.cluster_size);
|
||||
/* Need to recalculate number of clusters, since the unused parts of the
|
||||
* FATS and data area together could make up space for an additional,
|
||||
* not really present cluster. */
|
||||
clust16 = (fatdata - nr_fats*fatlength16)/bs.cluster_size;
|
||||
clust16 = (fatdata1216 - nr_fats*fatlength16)/bs.cluster_size;
|
||||
maxclust16 = (fatlength16 * sector_size) / 2;
|
||||
if (maxclust16 > MAX_CLUST_16)
|
||||
maxclust16 = MAX_CLUST_16;
|
||||
@ -957,13 +984,14 @@ setup_tables (void)
|
||||
clust16 = 0;
|
||||
}
|
||||
|
||||
clust32 = ((long long) fatdata *sector_size + nr_fats*8) /
|
||||
clust32 = ((long long) fatdata32 *sector_size + nr_fats*8) /
|
||||
((int) bs.cluster_size * sector_size + nr_fats*4);
|
||||
fatlength32 = cdiv ((clust32+2) * 4, sector_size);
|
||||
fatlength32 = cdiv((clust32+2) * 4, sector_size);
|
||||
fatlength32 = align_object(fatlength32, bs.cluster_size);
|
||||
/* Need to recalculate number of clusters, since the unused parts of the
|
||||
* FATS and data area together could make up space for an additional,
|
||||
* not really present cluster. */
|
||||
clust32 = (fatdata - nr_fats*fatlength32)/bs.cluster_size;
|
||||
clust32 = (fatdata32 - nr_fats*fatlength32)/bs.cluster_size;
|
||||
maxclust32 = (fatlength32 * sector_size) / 4;
|
||||
if (maxclust32 > MAX_CLUST_32)
|
||||
maxclust32 = MAX_CLUST_32;
|
||||
@ -1038,14 +1066,22 @@ setup_tables (void)
|
||||
bs.fat_length = CT_LE_W(0);
|
||||
bs.fat32.fat32_length = CT_LE_L(fatlength32);
|
||||
memcpy(vi->fs_type, MSDOS_FAT32_SIGN, 8);
|
||||
root_dir_entries = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
die("FAT not 12, 16 or 32 bits");
|
||||
}
|
||||
|
||||
/* Adjust the reserved number of sectors for alignment */
|
||||
reserved_sectors = align_object(reserved_sectors, bs.cluster_size);
|
||||
|
||||
/* Adjust the number of root directory entries to help enforce alignment */
|
||||
root_dir_entries = align_object(root_dir_sectors, bs.cluster_size)
|
||||
* (sector_size >> 5);
|
||||
}
|
||||
else {
|
||||
unsigned clusters, maxclust;
|
||||
unsigned clusters, maxclust, fatdata;
|
||||
|
||||
/* GEMDOS always uses a 12 bit FAT on floppies, and always a 16 bit FAT on
|
||||
* hard disks. So use 12 bit if the size of the file system suggests that
|
||||
@ -1207,9 +1243,19 @@ setup_tables (void)
|
||||
printf ("FAT size is %d sector%s, and provides %d cluster%s.\n",
|
||||
fat_length, (fat_length != 1) ? "s" : "",
|
||||
cluster_count, (cluster_count != 1) ? "s" : "");
|
||||
if (size_fat != 32)
|
||||
printf ("Root directory contains %d slots.\n",
|
||||
(int) (bs.dir_entries[0]) + (int) (bs.dir_entries[1]) * 256);
|
||||
printf ("There %s %u reserved sector%s.\n",
|
||||
(reserved_sectors != 1) ? "are" : "is",
|
||||
reserved_sectors,
|
||||
(reserved_sectors != 1) ? "s" : "");
|
||||
|
||||
if (size_fat != 32) {
|
||||
unsigned root_dir_entries =
|
||||
bs.dir_entries[0] + ((bs.dir_entries[1]) * 256);
|
||||
unsigned root_dir_sectors =
|
||||
cdiv (root_dir_entries*32, sector_size);
|
||||
printf ("Root directory contains %u slots and uses %u sectors\n",
|
||||
root_dir_entries, root_dir_sectors);
|
||||
}
|
||||
printf ("Volume ID is %08lx, ", volume_id &
|
||||
(atari_format ? 0x00ffffff : 0xffffffff));
|
||||
if ( strcmp(volume_name, " ") )
|
||||
@ -1383,10 +1429,10 @@ void
|
||||
usage (void)
|
||||
{
|
||||
fatal_error("\
|
||||
Usage: mkdosfs [-A] [-c] [-C] [-v] [-I] [-l bad-block-file] [-b backup-boot-sector]\n\
|
||||
[-m boot-msg-file] [-n volume-name] [-i volume-id]\n\
|
||||
[-s sectors-per-cluster] [-S logical-sector-size] [-f number-of-FATs]\n\
|
||||
[-h hidden-sectors] [-F fat-size] [-r root-dir-entries] [-R reserved-sectors]\n\
|
||||
Usage: mkdosfs [-a][-A][-c][-C][-v][-I][-l bad-block-file][-b backup-boot-sector]\n\
|
||||
[-m boot-msg-file][-n volume-name][-i volume-id]\n\
|
||||
[-s sectors-per-cluster][-S logical-sector-size][-f number-of-FATs]\n\
|
||||
[-h hidden-sectors][-F fat-size][-r root-dir-entries][-R reserved-sectors]\n\
|
||||
/dev/name [blocks]\n");
|
||||
}
|
||||
|
||||
@ -1431,7 +1477,7 @@ main (int argc, char **argv)
|
||||
struct stat statbuf;
|
||||
int i = 0, pos, ch;
|
||||
int create = 0;
|
||||
unsigned long long cblocks;
|
||||
unsigned long long cblocks = 0;
|
||||
int min_sector_size;
|
||||
|
||||
if (argc && *argv) { /* What's the program name? */
|
||||
@ -1449,7 +1495,7 @@ main (int argc, char **argv)
|
||||
printf ("%s " VERSION " (" VERSION_DATE ")\n",
|
||||
program_name);
|
||||
|
||||
while ((c = getopt (argc, argv, "Ab:cCf:F:Ii:l:m:n:r:R:s:S:h:v")) != EOF)
|
||||
while ((c = getopt (argc, argv, "aAb:cCf:F:Ii:l:m:n:r:R:s:S:h:v")) != EOF)
|
||||
/* Scan the command line for options */
|
||||
switch (c)
|
||||
{
|
||||
@ -1457,6 +1503,10 @@ main (int argc, char **argv)
|
||||
atari_format = !atari_format;
|
||||
break;
|
||||
|
||||
case 'a': /* a : skip alignment */
|
||||
align_structures = FALSE;
|
||||
break;
|
||||
|
||||
case 'b': /* b : location of backup boot sector */
|
||||
backup_boot = (int) strtol (optarg, &tmp, 0);
|
||||
if (*tmp || backup_boot < 2 || backup_boot > 0xffff)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user