mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-08 14:23:19 +00:00
fs/fat/: add support for DOS 1.x formatted volumes
Add structure for parsed BPB information, struct fat_bios_param_block, and move all of the deserialization and validation logic from fat_fill_super() into fat_read_bpb(). Add a '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. When fat_read_bpb() finds an invalid FAT filesystem and dos1xfloppy is set, fall back to fat_read_static_bpb(). fat_read_static_bpb() validates that the entire BPB is zero, and that the floppy has a DOS-style 8086 code bootstrapping header. Then it fills in default BPB values from media size and a table.[0] Media size is assumed to be static for archaic FAT volumes. See also: [1]. Fixes kernel.org bug #42617. [0]: https://en.wikipedia.org/wiki/File_Allocation_Table#Exceptions [1]: http://www.win.tue.nl/~aeb/linux/fs/fat/fat-1.html [hirofumi@mail.parknet.co.jp: fix missed error code] Signed-off-by: Conrad Meyer <cse.cem@gmail.com> Acked-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> Tested-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
a19189e553
commit
190a8843de
@ -172,6 +172,11 @@ nfs=stale_rw|nostale_ro
|
||||
To maintain backward compatibility, '-o nfs' is also accepted,
|
||||
defaulting to stale_rw
|
||||
|
||||
dos1xfloppy -- If set, use a fallback default BIOS Parameter Block
|
||||
configuration, determined by backing device size. These static
|
||||
parameters match defaults assumed by DOS 1.x for 160 kiB,
|
||||
180 kiB, 320 kiB, and 360 kiB floppies and floppy images.
|
||||
|
||||
|
||||
<bool>: 0,1,yes,no,true,false
|
||||
|
||||
|
@ -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
|
||||
|
343
fs/fat/inode.c
343
fs/fat/inode.c
@ -35,9 +35,71 @@
|
||||
#define CONFIG_FAT_DEFAULT_IOCHARSET ""
|
||||
#endif
|
||||
|
||||
#define KB_IN_SECTORS 2
|
||||
|
||||
/*
|
||||
* A deserialized copy of the on-disk structure laid out in struct
|
||||
* fat_boot_sector.
|
||||
*/
|
||||
struct fat_bios_param_block {
|
||||
u16 fat_sector_size;
|
||||
u8 fat_sec_per_clus;
|
||||
u16 fat_reserved;
|
||||
u8 fat_fats;
|
||||
u16 fat_dir_entries;
|
||||
u16 fat_sectors;
|
||||
u16 fat_fat_length;
|
||||
u32 fat_total_sect;
|
||||
|
||||
u8 fat16_state;
|
||||
u32 fat16_vol_id;
|
||||
|
||||
u32 fat32_length;
|
||||
u32 fat32_root_cluster;
|
||||
u16 fat32_info_sector;
|
||||
u8 fat32_state;
|
||||
u32 fat32_vol_id;
|
||||
};
|
||||
|
||||
static int fat_default_codepage = CONFIG_FAT_DEFAULT_CODEPAGE;
|
||||
static char fat_default_iocharset[] = CONFIG_FAT_DEFAULT_IOCHARSET;
|
||||
|
||||
static struct fat_floppy_defaults {
|
||||
unsigned nr_sectors;
|
||||
unsigned sec_per_clus;
|
||||
unsigned dir_entries;
|
||||
unsigned media;
|
||||
unsigned fat_length;
|
||||
} floppy_defaults[] = {
|
||||
{
|
||||
.nr_sectors = 160 * KB_IN_SECTORS,
|
||||
.sec_per_clus = 1,
|
||||
.dir_entries = 64,
|
||||
.media = 0xFE,
|
||||
.fat_length = 1,
|
||||
},
|
||||
{
|
||||
.nr_sectors = 180 * KB_IN_SECTORS,
|
||||
.sec_per_clus = 1,
|
||||
.dir_entries = 64,
|
||||
.media = 0xFC,
|
||||
.fat_length = 2,
|
||||
},
|
||||
{
|
||||
.nr_sectors = 320 * KB_IN_SECTORS,
|
||||
.sec_per_clus = 2,
|
||||
.dir_entries = 112,
|
||||
.media = 0xFF,
|
||||
.fat_length = 1,
|
||||
},
|
||||
{
|
||||
.nr_sectors = 360 * KB_IN_SECTORS,
|
||||
.sec_per_clus = 2,
|
||||
.dir_entries = 112,
|
||||
.media = 0xFD,
|
||||
.fat_length = 2,
|
||||
},
|
||||
};
|
||||
|
||||
static int fat_add_cluster(struct inode *inode)
|
||||
{
|
||||
@ -853,6 +915,8 @@ static int fat_show_options(struct seq_file *m, struct dentry *root)
|
||||
seq_puts(m, ",nfs=stale_rw");
|
||||
if (opts->discard)
|
||||
seq_puts(m, ",discard");
|
||||
if (opts->dos1xfloppy)
|
||||
seq_puts(m, ",dos1xfloppy");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -867,7 +931,7 @@ enum {
|
||||
Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes,
|
||||
Opt_obsolete, Opt_flush, Opt_tz_utc, Opt_rodir, Opt_err_cont,
|
||||
Opt_err_panic, Opt_err_ro, Opt_discard, Opt_nfs, Opt_time_offset,
|
||||
Opt_nfs_stale_rw, Opt_nfs_nostale_ro, Opt_err,
|
||||
Opt_nfs_stale_rw, Opt_nfs_nostale_ro, Opt_err, Opt_dos1xfloppy,
|
||||
};
|
||||
|
||||
static const match_table_t fat_tokens = {
|
||||
@ -900,6 +964,7 @@ static const match_table_t fat_tokens = {
|
||||
{Opt_nfs_stale_rw, "nfs"},
|
||||
{Opt_nfs_stale_rw, "nfs=stale_rw"},
|
||||
{Opt_nfs_nostale_ro, "nfs=nostale_ro"},
|
||||
{Opt_dos1xfloppy, "dos1xfloppy"},
|
||||
{Opt_obsolete, "conv=binary"},
|
||||
{Opt_obsolete, "conv=text"},
|
||||
{Opt_obsolete, "conv=auto"},
|
||||
@ -1102,6 +1167,9 @@ static int parse_options(struct super_block *sb, char *options, int is_vfat,
|
||||
case Opt_nfs_nostale_ro:
|
||||
opts->nfs = FAT_NFS_NOSTALE_RO;
|
||||
break;
|
||||
case Opt_dos1xfloppy:
|
||||
opts->dos1xfloppy = 1;
|
||||
break;
|
||||
|
||||
/* msdos specific */
|
||||
case Opt_dots:
|
||||
@ -1247,6 +1315,169 @@ static unsigned long calc_fat_clusters(struct super_block *sb)
|
||||
return sbi->fat_length * sb->s_blocksize * 8 / sbi->fat_bits;
|
||||
}
|
||||
|
||||
static bool fat_bpb_is_zero(struct fat_boot_sector *b)
|
||||
{
|
||||
if (get_unaligned_le16(&b->sector_size))
|
||||
return false;
|
||||
if (b->sec_per_clus)
|
||||
return false;
|
||||
if (b->reserved)
|
||||
return false;
|
||||
if (b->fats)
|
||||
return false;
|
||||
if (get_unaligned_le16(&b->dir_entries))
|
||||
return false;
|
||||
if (get_unaligned_le16(&b->sectors))
|
||||
return false;
|
||||
if (b->media)
|
||||
return false;
|
||||
if (b->fat_length)
|
||||
return false;
|
||||
if (b->secs_track)
|
||||
return false;
|
||||
if (b->heads)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int fat_read_bpb(struct super_block *sb, struct fat_boot_sector *b,
|
||||
int silent, struct fat_bios_param_block *bpb)
|
||||
{
|
||||
int error = -EINVAL;
|
||||
|
||||
/* Read in BPB ... */
|
||||
memset(bpb, 0, sizeof(*bpb));
|
||||
bpb->fat_sector_size = get_unaligned_le16(&b->sector_size);
|
||||
bpb->fat_sec_per_clus = b->sec_per_clus;
|
||||
bpb->fat_reserved = le16_to_cpu(b->reserved);
|
||||
bpb->fat_fats = b->fats;
|
||||
bpb->fat_dir_entries = get_unaligned_le16(&b->dir_entries);
|
||||
bpb->fat_sectors = get_unaligned_le16(&b->sectors);
|
||||
bpb->fat_fat_length = le16_to_cpu(b->fat_length);
|
||||
bpb->fat_total_sect = le32_to_cpu(b->total_sect);
|
||||
|
||||
bpb->fat16_state = b->fat16.state;
|
||||
bpb->fat16_vol_id = get_unaligned_le32(b->fat16.vol_id);
|
||||
|
||||
bpb->fat32_length = le32_to_cpu(b->fat32.length);
|
||||
bpb->fat32_root_cluster = le32_to_cpu(b->fat32.root_cluster);
|
||||
bpb->fat32_info_sector = le16_to_cpu(b->fat32.info_sector);
|
||||
bpb->fat32_state = b->fat32.state;
|
||||
bpb->fat32_vol_id = get_unaligned_le32(b->fat32.vol_id);
|
||||
|
||||
/* Validate this looks like a FAT filesystem BPB */
|
||||
if (!bpb->fat_reserved) {
|
||||
if (!silent)
|
||||
fat_msg(sb, KERN_ERR,
|
||||
"bogus number of reserved sectors");
|
||||
goto out;
|
||||
}
|
||||
if (!bpb->fat_fats) {
|
||||
if (!silent)
|
||||
fat_msg(sb, KERN_ERR, "bogus number of FAT structure");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Earlier we checked here that b->secs_track and b->head are nonzero,
|
||||
* but it turns out valid FAT filesystems can have zero there.
|
||||
*/
|
||||
|
||||
if (!fat_valid_media(b->media)) {
|
||||
if (!silent)
|
||||
fat_msg(sb, KERN_ERR, "invalid media value (0x%02x)",
|
||||
(unsigned)b->media);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!is_power_of_2(bpb->fat_sector_size)
|
||||
|| (bpb->fat_sector_size < 512)
|
||||
|| (bpb->fat_sector_size > 4096)) {
|
||||
if (!silent)
|
||||
fat_msg(sb, KERN_ERR, "bogus logical sector size %u",
|
||||
(unsigned)bpb->fat_sector_size);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!is_power_of_2(bpb->fat_sec_per_clus)) {
|
||||
if (!silent)
|
||||
fat_msg(sb, KERN_ERR, "bogus sectors per cluster %u",
|
||||
(unsigned)bpb->fat_sec_per_clus);
|
||||
goto out;
|
||||
}
|
||||
|
||||
error = 0;
|
||||
|
||||
out:
|
||||
return error;
|
||||
}
|
||||
|
||||
static int fat_read_static_bpb(struct super_block *sb,
|
||||
struct fat_boot_sector *b, int silent,
|
||||
struct fat_bios_param_block *bpb)
|
||||
{
|
||||
static const char *notdos1x = "This doesn't look like a DOS 1.x volume";
|
||||
|
||||
struct fat_floppy_defaults *fdefaults = NULL;
|
||||
int error = -EINVAL;
|
||||
sector_t bd_sects;
|
||||
unsigned i;
|
||||
|
||||
bd_sects = i_size_read(sb->s_bdev->bd_inode) / SECTOR_SIZE;
|
||||
|
||||
/* 16-bit DOS 1.x reliably wrote bootstrap short-jmp code */
|
||||
if (b->ignored[0] != 0xeb || b->ignored[2] != 0x90) {
|
||||
if (!silent)
|
||||
fat_msg(sb, KERN_ERR,
|
||||
"%s; no bootstrapping code", notdos1x);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* If any value in this region is non-zero, it isn't archaic
|
||||
* DOS.
|
||||
*/
|
||||
if (!fat_bpb_is_zero(b)) {
|
||||
if (!silent)
|
||||
fat_msg(sb, KERN_ERR,
|
||||
"%s; DOS 2.x BPB is non-zero", notdos1x);
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(floppy_defaults); i++) {
|
||||
if (floppy_defaults[i].nr_sectors == bd_sects) {
|
||||
fdefaults = &floppy_defaults[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (fdefaults == NULL) {
|
||||
if (!silent)
|
||||
fat_msg(sb, KERN_WARNING,
|
||||
"This looks like a DOS 1.x volume, but isn't a recognized floppy size (%llu sectors)",
|
||||
(u64)bd_sects);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!silent)
|
||||
fat_msg(sb, KERN_INFO,
|
||||
"This looks like a DOS 1.x volume; assuming default BPB values");
|
||||
|
||||
memset(bpb, 0, sizeof(*bpb));
|
||||
bpb->fat_sector_size = SECTOR_SIZE;
|
||||
bpb->fat_sec_per_clus = fdefaults->sec_per_clus;
|
||||
bpb->fat_reserved = 1;
|
||||
bpb->fat_fats = 2;
|
||||
bpb->fat_dir_entries = fdefaults->dir_entries;
|
||||
bpb->fat_sectors = fdefaults->nr_sectors;
|
||||
bpb->fat_fat_length = fdefaults->fat_length;
|
||||
|
||||
error = 0;
|
||||
|
||||
out:
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the super block of an MS-DOS FS.
|
||||
*/
|
||||
@ -1256,12 +1487,11 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
|
||||
struct inode *root_inode = NULL, *fat_inode = NULL;
|
||||
struct inode *fsinfo_inode = NULL;
|
||||
struct buffer_head *bh;
|
||||
struct fat_boot_sector *b;
|
||||
struct fat_bios_param_block bpb;
|
||||
struct msdos_sb_info *sbi;
|
||||
u16 logical_sector_size;
|
||||
u32 total_sectors, total_clusters, fat_clusters, rootdir_sectors;
|
||||
int debug;
|
||||
unsigned int media;
|
||||
long error;
|
||||
char buf[50];
|
||||
|
||||
@ -1298,100 +1528,72 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
|
||||
goto out_fail;
|
||||
}
|
||||
|
||||
b = (struct fat_boot_sector *) bh->b_data;
|
||||
if (!b->reserved) {
|
||||
if (!silent)
|
||||
fat_msg(sb, KERN_ERR, "bogus number of reserved sectors");
|
||||
brelse(bh);
|
||||
goto out_invalid;
|
||||
}
|
||||
if (!b->fats) {
|
||||
if (!silent)
|
||||
fat_msg(sb, KERN_ERR, "bogus number of FAT structure");
|
||||
brelse(bh);
|
||||
goto out_invalid;
|
||||
}
|
||||
error = fat_read_bpb(sb, (struct fat_boot_sector *)bh->b_data, silent,
|
||||
&bpb);
|
||||
if (error == -EINVAL && sbi->options.dos1xfloppy)
|
||||
error = fat_read_static_bpb(sb,
|
||||
(struct fat_boot_sector *)bh->b_data, silent, &bpb);
|
||||
brelse(bh);
|
||||
|
||||
/*
|
||||
* Earlier we checked here that b->secs_track and b->head are nonzero,
|
||||
* but it turns out valid FAT filesystems can have zero there.
|
||||
*/
|
||||
if (error == -EINVAL)
|
||||
goto out_invalid;
|
||||
else if (error)
|
||||
goto out_fail;
|
||||
|
||||
media = b->media;
|
||||
if (!fat_valid_media(media)) {
|
||||
if (!silent)
|
||||
fat_msg(sb, KERN_ERR, "invalid media value (0x%02x)",
|
||||
media);
|
||||
brelse(bh);
|
||||
goto out_invalid;
|
||||
}
|
||||
logical_sector_size = get_unaligned_le16(&b->sector_size);
|
||||
if (!is_power_of_2(logical_sector_size)
|
||||
|| (logical_sector_size < 512)
|
||||
|| (logical_sector_size > 4096)) {
|
||||
if (!silent)
|
||||
fat_msg(sb, KERN_ERR, "bogus logical sector size %u",
|
||||
logical_sector_size);
|
||||
brelse(bh);
|
||||
goto out_invalid;
|
||||
}
|
||||
sbi->sec_per_clus = b->sec_per_clus;
|
||||
if (!is_power_of_2(sbi->sec_per_clus)) {
|
||||
if (!silent)
|
||||
fat_msg(sb, KERN_ERR, "bogus sectors per cluster %u",
|
||||
sbi->sec_per_clus);
|
||||
brelse(bh);
|
||||
goto out_invalid;
|
||||
}
|
||||
logical_sector_size = bpb.fat_sector_size;
|
||||
sbi->sec_per_clus = bpb.fat_sec_per_clus;
|
||||
|
||||
error = -EIO;
|
||||
if (logical_sector_size < sb->s_blocksize) {
|
||||
fat_msg(sb, KERN_ERR, "logical sector size too small for device"
|
||||
" (logical sector size = %u)", logical_sector_size);
|
||||
brelse(bh);
|
||||
goto out_fail;
|
||||
}
|
||||
|
||||
if (logical_sector_size > sb->s_blocksize) {
|
||||
brelse(bh);
|
||||
struct buffer_head *bh_resize;
|
||||
|
||||
if (!sb_set_blocksize(sb, logical_sector_size)) {
|
||||
fat_msg(sb, KERN_ERR, "unable to set blocksize %u",
|
||||
logical_sector_size);
|
||||
goto out_fail;
|
||||
}
|
||||
bh = sb_bread(sb, 0);
|
||||
if (bh == NULL) {
|
||||
|
||||
/* Verify that the larger boot sector is fully readable */
|
||||
bh_resize = sb_bread(sb, 0);
|
||||
if (bh_resize == NULL) {
|
||||
fat_msg(sb, KERN_ERR, "unable to read boot sector"
|
||||
" (logical sector size = %lu)",
|
||||
sb->s_blocksize);
|
||||
goto out_fail;
|
||||
}
|
||||
b = (struct fat_boot_sector *) bh->b_data;
|
||||
brelse(bh_resize);
|
||||
}
|
||||
|
||||
mutex_init(&sbi->s_lock);
|
||||
sbi->cluster_size = sb->s_blocksize * sbi->sec_per_clus;
|
||||
sbi->cluster_bits = ffs(sbi->cluster_size) - 1;
|
||||
sbi->fats = b->fats;
|
||||
sbi->fats = bpb.fat_fats;
|
||||
sbi->fat_bits = 0; /* Don't know yet */
|
||||
sbi->fat_start = le16_to_cpu(b->reserved);
|
||||
sbi->fat_length = le16_to_cpu(b->fat_length);
|
||||
sbi->fat_start = bpb.fat_reserved;
|
||||
sbi->fat_length = bpb.fat_fat_length;
|
||||
sbi->root_cluster = 0;
|
||||
sbi->free_clusters = -1; /* Don't know yet */
|
||||
sbi->free_clus_valid = 0;
|
||||
sbi->prev_free = FAT_START_ENT;
|
||||
sb->s_maxbytes = 0xffffffff;
|
||||
|
||||
if (!sbi->fat_length && b->fat32.length) {
|
||||
if (!sbi->fat_length && bpb.fat32_length) {
|
||||
struct fat_boot_fsinfo *fsinfo;
|
||||
struct buffer_head *fsinfo_bh;
|
||||
|
||||
/* Must be FAT32 */
|
||||
sbi->fat_bits = 32;
|
||||
sbi->fat_length = le32_to_cpu(b->fat32.length);
|
||||
sbi->root_cluster = le32_to_cpu(b->fat32.root_cluster);
|
||||
sbi->fat_length = bpb.fat32_length;
|
||||
sbi->root_cluster = bpb.fat32_root_cluster;
|
||||
|
||||
/* MC - if info_sector is 0, don't multiply by 0 */
|
||||
sbi->fsinfo_sector = le16_to_cpu(b->fat32.info_sector);
|
||||
sbi->fsinfo_sector = bpb.fat32_info_sector;
|
||||
if (sbi->fsinfo_sector == 0)
|
||||
sbi->fsinfo_sector = 1;
|
||||
|
||||
@ -1399,7 +1601,6 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
|
||||
if (fsinfo_bh == NULL) {
|
||||
fat_msg(sb, KERN_ERR, "bread failed, FSINFO block"
|
||||
" (sector = %lu)", sbi->fsinfo_sector);
|
||||
brelse(bh);
|
||||
goto out_fail;
|
||||
}
|
||||
|
||||
@ -1422,35 +1623,28 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
|
||||
|
||||
/* interpret volume ID as a little endian 32 bit integer */
|
||||
if (sbi->fat_bits == 32)
|
||||
sbi->vol_id = (((u32)b->fat32.vol_id[0]) |
|
||||
((u32)b->fat32.vol_id[1] << 8) |
|
||||
((u32)b->fat32.vol_id[2] << 16) |
|
||||
((u32)b->fat32.vol_id[3] << 24));
|
||||
sbi->vol_id = bpb.fat32_vol_id;
|
||||
else /* fat 16 or 12 */
|
||||
sbi->vol_id = (((u32)b->fat16.vol_id[0]) |
|
||||
((u32)b->fat16.vol_id[1] << 8) |
|
||||
((u32)b->fat16.vol_id[2] << 16) |
|
||||
((u32)b->fat16.vol_id[3] << 24));
|
||||
sbi->vol_id = bpb.fat16_vol_id;
|
||||
|
||||
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 = get_unaligned_le16(&b->dir_entries);
|
||||
sbi->dir_entries = bpb.fat_dir_entries;
|
||||
if (sbi->dir_entries & (sbi->dir_per_block - 1)) {
|
||||
if (!silent)
|
||||
fat_msg(sb, KERN_ERR, "bogus directory-entries per block"
|
||||
" (%u)", sbi->dir_entries);
|
||||
brelse(bh);
|
||||
goto out_invalid;
|
||||
}
|
||||
|
||||
rootdir_sectors = sbi->dir_entries
|
||||
* sizeof(struct msdos_dir_entry) / sb->s_blocksize;
|
||||
sbi->data_start = sbi->dir_start + rootdir_sectors;
|
||||
total_sectors = get_unaligned_le16(&b->sectors);
|
||||
total_sectors = bpb.fat_sectors;
|
||||
if (total_sectors == 0)
|
||||
total_sectors = le32_to_cpu(b->total_sect);
|
||||
total_sectors = bpb.fat_total_sect;
|
||||
|
||||
total_clusters = (total_sectors - sbi->data_start) / sbi->sec_per_clus;
|
||||
|
||||
@ -1459,9 +1653,9 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
|
||||
|
||||
/* some OSes set FAT_STATE_DIRTY and clean it on unmount. */
|
||||
if (sbi->fat_bits == 32)
|
||||
sbi->dirty = b->fat32.state & FAT_STATE_DIRTY;
|
||||
sbi->dirty = bpb.fat32_state & FAT_STATE_DIRTY;
|
||||
else /* fat 16 or 12 */
|
||||
sbi->dirty = b->fat16.state & FAT_STATE_DIRTY;
|
||||
sbi->dirty = bpb.fat16_state & FAT_STATE_DIRTY;
|
||||
|
||||
/* check that FAT table does not overflow */
|
||||
fat_clusters = calc_fat_clusters(sb);
|
||||
@ -1470,7 +1664,6 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
|
||||
if (!silent)
|
||||
fat_msg(sb, KERN_ERR, "count of clusters too big (%u)",
|
||||
total_clusters);
|
||||
brelse(bh);
|
||||
goto out_invalid;
|
||||
}
|
||||
|
||||
@ -1483,8 +1676,6 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
|
||||
if (sbi->prev_free < FAT_START_ENT)
|
||||
sbi->prev_free = FAT_START_ENT;
|
||||
|
||||
brelse(bh);
|
||||
|
||||
/* set up enough so that it can read an inode */
|
||||
fat_hash_init(sb);
|
||||
dir_hash_init(sb);
|
||||
|
Loading…
Reference in New Issue
Block a user