fs/fat: Atari FAT updates
Add support for the Atari-variant of the FAT filesystem
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index ffbbf05..ea769f0 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -17,6 +17,7 @@
#include <linux/seq_file.h>
#include <linux/parser.h>
#include <linux/uio.h>
+#include <linux/major.h>
#include <linux/blkdev.h>
#include <linux/backing-dev.h>
#include <asm/unaligned.h>
@@ -1012,7 +1013,7 @@ enum {
Opt_check_n, Opt_check_r, Opt_check_s, Opt_uid, Opt_gid,
Opt_umask, Opt_dmask, Opt_fmask, Opt_allow_utime, Opt_codepage,
Opt_usefree, Opt_nocase, Opt_quiet, Opt_showexec, Opt_debug,
- Opt_immutable, Opt_dots, Opt_nodots,
+ Opt_immutable, Opt_dots, Opt_nodots, Opt_atari_no, Opt_atari_yes,
Opt_charset, Opt_shortname_lower, Opt_shortname_win95,
Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes,
Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes,
@@ -1051,6 +1052,9 @@ 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_atari_yes, "atari=yes"},
+ {Opt_atari_yes, "atari"},
+ {Opt_atari_no, "atari=no"},
{Opt_dos1xfloppy, "dos1xfloppy"},
{Opt_obsolete, "conv=binary"},
{Opt_obsolete, "conv=text"},
@@ -1134,6 +1138,13 @@ static int parse_options(struct super_block *sb, char *options, int is_vfat,
opts->tz_set = 0;
opts->nfs = 0;
opts->errors = FAT_ERRORS_RO;
+ opts->atari = 0;
+
+#ifdef CONFIG_ATARI
+ if (MACH_IS_ATARI)
+ /* make Atari GEMDOS format the default if machine is an Atari */
+ opts->atari = 1;
+#endif
*debug = 0;
opts->utf8 = IS_ENABLED(CONFIG_FAT_DEFAULT_UTF8) && is_vfat;
@@ -1187,6 +1198,12 @@ static int parse_options(struct super_block *sb, char *options, int is_vfat,
case Opt_immutable:
opts->sys_immutable = 1;
break;
+ case Opt_atari_yes:
+ opts->atari = 1;
+ break;
+ case Opt_atari_no:
+ opts->atari = 0;
+ break;
case Opt_uid:
if (match_int(&args[0], &option))
return -EINVAL;
@@ -1751,8 +1768,31 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
total_clusters = (total_sectors - sbi->data_start) / sbi->sec_per_clus;
- if (sbi->fat_bits != 32)
- sbi->fat_bits = (total_clusters > MAX_FAT12) ? 16 : 12;
+ if (!sbi->options.atari) {
+ if (sbi->fat_bits != 32)
+ sbi->fat_bits = (total_clusters > MAX_FAT12) ? 16 : 12;
+ } else {
+ int sectors;
+ /* Atari GEMDOS partitions always have 16-bit fat */
+ if (sbi->fat_bits != 32)
+ sbi->fat_bits = 16;
+ /* If more clusters than fat entries in 16-bit fat, we assume
+ * it's a real MSDOS partition with 12-bit fat.
+ */
+ if (sbi->fat_bits != 32 && total_clusters+2 > sbi->
+ fat_length*SECTOR_SIZE*8/sbi->fat_bits)
+ sbi->fat_bits = 12;
+ /* if it's a floppy disk --> 12bit fat */
+ if (sbi->fat_bits != 32 && MAJOR(sb->s_dev) == FLOPPY_MAJOR)
+ sbi->fat_bits = 12;
+ /* if it's a ramdisk or loopback device and has one of the usual
+ * floppy sizes -> 12bit FAT */
+ sectors = total_sectors + sbi->data_start;
+ if (sbi->fat_bits != 32 && (MAJOR(sb->s_dev) == RAMDISK_MAJOR ||
+ MAJOR(sb->s_dev) == LOOP_MAJOR) &&
+ (sectors == 720 || sectors == 1440 || sectors == 2880))
+ sbi->fat_bits = 12;
+ }
/* some OSes set FAT_STATE_DIRTY and clean it on unmount. */
if (sbi->fat_bits == 32)