fs: FAT: Add support for DOS 1.x formatted volumes
PATCH v5 1/1 fs: FAT: Add support for DOS 1.x formatted volumes
Add dos1xfloppy mount option to infer DOS 2.x BIOS Parameter Block defaults from block device geometry for ancient floppies and floppy images, as a fall-back from the default BPB parsing logic.
Validate that the entire BPB is zero like we expect, and that the floppy has a DOS-style 8086 code bootstrapping header.
Fixes kernel.org bug #42617.
Values are inferred from media size and a table.[0] Media size is assumed to be static for archaic FAT volumes. See also [1].
[0]: https://en.wikipedia.org/wiki/File_Allocation_Table#Exceptions
[1]: http://www.win.tue.nl/~aeb/linux/fs/fat/fat-1.html
---
Changes since v4:
* Read FAT FS block device size with i_size_read()
* In silent (probing) mode, don't message
* Use dos1xfloppy as a gate to allow trying static BPB values (don't require floppy to be archaic with this option)
* Split out BPB-parsing functionality of fat_fill_super() into two helpers, fat_read_bpb() and fat_read_static_bpb()
Thanks for your patience. I apologize for it taking so many revisions to get it right :).
--- fs/fat/fat.h | 3 +- fs/fat/inode.c | 353 ++++++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 266 insertions(+), 90 deletions(-)
fs/fat/fat.h +2 -1
@@ -52,7 +52,8 @@ struct fat_mount_options { usefree:1, /* Use free_clusters for FAT32 */ tz_set:1, /* Filesystem timestamps' offset set */ rodir:1, /* allow ATTR_RO for directory */ - discard:1; /* Issue discard requests on deletions */ + discard:1, /* Issue discard requests on deletions */ + dos1xfloppy:1; /* Assume default BPB for DOS 1.x floppies */ };#define FAT_HASH_BITS 8
fs/fat/inode.c +264 -89
488 lines not on this page · raw message
Signature · 1 line
1.9.0
OGAWA Hirofumi
maintainerQuoted 15 lines · Conrad Meyer
fs/fat/inode.c +15
-0+ sbi->sec_per_clus = fdefaults->sec_per_clus; + sbi->cluster_size = sb->s_blocksize * sbi->sec_per_clus; + sbi->cluster_bits =ffs (sbi->cluster_size) -1 ; + sbi->fats =2 ; + sbi->fat_start =1 ; + sbi->fat_length = fdefaults->fat_length; + + sbi->dir_per_block = sb->s_blocksize /sizeof (struct msdos_dir_entry ); + sbi->dir_per_block_bits =ffs (sbi->dir_per_block) -1 ; + sbi->dir_start = sbi->fat_start + sbi->fats * sbi->fat_length; + sbi->dir_entries = fdefaults->dir_entries; + + rootdir_sectors = sbi->dir_entries + *sizeof (struct msdos_dir_entry ) / sb->s_blocksize; + sbi->data_start = sbi->dir_start + rootdir_sectors;
fs/fat/inode.c int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, · line 1657
Quoted 10 lines
fs/fat/inode.c +10
-0+ total_sectors = fdefaults->nr_sectors; + total_clusters = (total_sectors - sbi->data_start) / sbi->sec_per_clus; + sbi->fat_bits = (total_clusters >MAX_FAT12 ) ?16 :12 ; + +/* some OSes set FAT_STATE_DIRTY and clean it on unmount. */ + sbi->dirty = b->fat16.state &FAT_STATE_DIRTY ; + +/* check that FAT table does not overflow */ + fat_clusters =calc_fat_clusters (sb); + total_clusters =min (total_clusters, fat_clusters -FAT_START_ENT );
Ah, you meant this duplicated one.
Let's use structure like fat_boot_sector (but more cpu friendly) on stack or something, instead of modify bh (BPB). Modifying bh in bdev is visible via /dev/foo, this is why I want to avoid to modify.
With this, we can share almost all codes on both of read_bpb() and static_bpb(), and avoids to modify bdev buffer? And those 2 helpers only has small chunk of code, and provide the required parameters?
Thanks.
Signature · 1 line
OGAWA Hirofumi <[email protected]>
Quoted 44 lines · On Mon, 14 Apr 2014 07:14:51 +0900 OGAWA Hirofumi…
Quoted 33 lines · Conrad Meyer
(quoted diff) +2
-0+ sbi->sec_per_clus = fdefaults->sec_per_clus; + sbi->cluster_size = sb->s_blocksize *
sbi->sec_per_clus;fs/fat/inode.c +6
-0+ sbi->cluster_bits =ffs (sbi->cluster_size) -1 ; + sbi->fats =2 ; + sbi->fat_start =1 ; + sbi->fat_length = fdefaults->fat_length; + + sbi->dir_per_block = sb->s_blocksize /
sizeof(struct msdos_dir_entry);(quoted diff) +1
-0+ sbi->dir_per_block_bits =
ffs(sbi->dir_per_block)- 1;(quoted diff) +1
-0+ sbi->dir_start = sbi->fat_start + sbi->fats *
sbi->fat_length;fs/fat/inode.c +4
-0+ sbi->dir_entries = fdefaults->dir_entries; + + rootdir_sectors = sbi->dir_entries + * sizeof(struct msdos_dir_entry) /
sb->s_blocksize;(quoted diff) +1
-0+ sbi->data_start = sbi->dir_start +
rootdir_sectors;(quoted diff) +2
-0+ total_sectors = fdefaults->nr_sectors; + total_clusters = (total_sectors -
sbi->data_start) /sbi->sec_per_clus;(quoted diff) +1
-0+ sbi->fat_bits = (total_clusters > MAX_FAT12) ?16 : 12; +
(quoted diff) +1
-0+ /* some OSes set FAT_STATE_DIRTY and clean it onunmount. */
fs/fat/inode.c +5
-0+ sbi->dirty = b->fat16.state &FAT_STATE_DIRTY ; + +/* check that FAT table does not overflow */ + fat_clusters =calc_fat_clusters (sb); + total_clusters = min(total_clusters,Quoted 1 line
fat_clusters-FAT_START_ENT);Ah, you meant this duplicated one.
Let's use structure like
fat_boot_sector(but more cpu friendly) on stack or something, instead of modify bh (BPB). Modifying bh in bdev is visible via/dev/foo, this is why I want to avoid to modify.
Quoted 6 lines
With this, we can share almost all codes on both of
read_bpb()andstatic_bpb(), and avoids to modify bdev buffer? And those 2 helpers only has small chunk of code, and provide the required parameters?Thanks.
Hi,
I think I understand the idea, sounds good to me. Working to clean up now.
Thanks again,
Conrad