[PATCH v8] 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 Signed-off-by: Conrad Meyer --- Changes from v7: * Move struct fat_bios_param_block from fat.h to fat/inode.c --- Documentation/filesystems/vfat.txt | 5 + fs/fat/fat.h | 3 +- fs/fat/inode.c | 342 - 3 files changed, 273 insertions(+), 77 deletions(-) diff --git a/Documentation/filesystems/vfat.txt b/Documentation/filesystems/vfat.txt index 5cf57b3..223c321 100644 --- a/Documentation/filesystems/vfat.txt +++ b/Documentation/filesystems/vfat.txt @@ -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. + : 0,1,yes,no,true,false diff --git a/fs/fat/fat.h b/fs/fat/fat.h index 7270bdb..13b7202 100644 --- a/fs/fat/fat.h +++ b/fs/fat/fat.h @@ -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 diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 992e8cb..d44c510 100644 --- a/fs/fat/inode.c +++ b/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) { @@ -931,6 +993,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; } @@ -945,7 +1009,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_
[PATCH v8] 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 Signed-off-by: Conrad Meyer cse@gmail.com --- Changes from v7: * Move struct fat_bios_param_block from fat.h to fat/inode.c --- Documentation/filesystems/vfat.txt | 5 + fs/fat/fat.h | 3 +- fs/fat/inode.c | 342 - 3 files changed, 273 insertions(+), 77 deletions(-) diff --git a/Documentation/filesystems/vfat.txt b/Documentation/filesystems/vfat.txt index 5cf57b3..223c321 100644 --- a/Documentation/filesystems/vfat.txt +++ b/Documentation/filesystems/vfat.txt @@ -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 diff --git a/fs/fat/fat.h b/fs/fat/fat.h index 7270bdb..13b7202 100644 --- a/fs/fat/fat.h +++ b/fs/fat/fat.h @@ -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 diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 992e8cb..d44c510 100644 --- a/fs/fat/inode.c +++ b/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) { @@ -931,6 +993,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; } @@ -945,7 +1009,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
[PATCH v7] 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 Signed-off-by: Conrad Meyer --- Changes since v6: * Update show_options() * Add option documentation to Doc/filesystems/vfat.txt Thanks. --- Documentation/filesystems/vfat.txt | 5 + fs/fat/fat.h | 28 +++- fs/fat/inode.c | 318 - 3 files changed, 274 insertions(+), 77 deletions(-) diff --git a/Documentation/filesystems/vfat.txt b/Documentation/filesystems/vfat.txt index 5cf57b3..223c321 100644 --- a/Documentation/filesystems/vfat.txt +++ b/Documentation/filesystems/vfat.txt @@ -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. + : 0,1,yes,no,true,false diff --git a/fs/fat/fat.h b/fs/fat/fat.h index 7270bdb..bcb0d67 100644 --- a/fs/fat/fat.h +++ b/fs/fat/fat.h @@ -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 @@ -139,6 +140,31 @@ struct fat_slot_info { struct buffer_head *bh; }; +/* + * 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 inline struct msdos_sb_info *MSDOS_SB(struct super_block *sb) { return sb->s_fs_info; diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 992e8cb..70ba768 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -35,9 +35,47 @@ #define CONFIG_FAT_DEFAULT_IOCHARSET "" #endif +#define KB_IN_SECTORS 2 + 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) { @@ -931,6 +969,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; } @@ -945,7 +985,
[PATCH v7] 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 Signed-off-by: Conrad Meyer cse@gmail.com --- Changes since v6: * Update show_options() * Add option documentation to Doc/filesystems/vfat.txt Thanks. --- Documentation/filesystems/vfat.txt | 5 + fs/fat/fat.h | 28 +++- fs/fat/inode.c | 318 - 3 files changed, 274 insertions(+), 77 deletions(-) diff --git a/Documentation/filesystems/vfat.txt b/Documentation/filesystems/vfat.txt index 5cf57b3..223c321 100644 --- a/Documentation/filesystems/vfat.txt +++ b/Documentation/filesystems/vfat.txt @@ -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 diff --git a/fs/fat/fat.h b/fs/fat/fat.h index 7270bdb..bcb0d67 100644 --- a/fs/fat/fat.h +++ b/fs/fat/fat.h @@ -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 @@ -139,6 +140,31 @@ struct fat_slot_info { struct buffer_head *bh; }; +/* + * 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 inline struct msdos_sb_info *MSDOS_SB(struct super_block *sb) { return sb-s_fs_info; diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 992e8cb..70ba768 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -35,9 +35,47 @@ #define CONFIG_FAT_DEFAULT_IOCHARSET #endif +#define KB_IN_SECTORS 2 + 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) { @@ -931,6 +969,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; } @@ -945,7 +985,7 @@ enum { Opt_uni_xl_no
[PATCH v6] 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 Signed-off-by: Conrad Meyer --- Changes since v5: * Leave the bulk of sbi-> filling logic to the aptly named fat_fill_super() * Create separate structure for deserialized BPB values * fat_read_bpb() deserializes BPB from raw fat_boot_sector and performs validations * fat_read_static_bpb() validates raw fat_boot_sector as dos1x and fills in BPB values from table Thanks, Conrad --- fs/fat/fat.h | 28 - fs/fat/inode.c | 316 +++-- 2 files changed, 267 insertions(+), 77 deletions(-) diff --git a/fs/fat/fat.h b/fs/fat/fat.h index 7270bdb..bcb0d67 100644 --- a/fs/fat/fat.h +++ b/fs/fat/fat.h @@ -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 @@ -139,6 +140,31 @@ struct fat_slot_info { struct buffer_head *bh; }; +/* + * 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 inline struct msdos_sb_info *MSDOS_SB(struct super_block *sb) { return sb->s_fs_info; diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 992e8cb..7727136 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -35,9 +35,47 @@ #define CONFIG_FAT_DEFAULT_IOCHARSET "" #endif +#define KB_IN_SECTORS 2 + 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) { @@ -945,7 +983,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 = { @@ -978,6 +1016,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"}, @@ -1180,6 +
Re: [PATCH v5] fs: FAT: Add support for DOS 1.x formatted volumes
On Mon, 14 Apr 2014 07:14:51 +0900 OGAWA Hirofumi wrote: > Conrad Meyer writes: > > > + 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; > > + 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. Hi, I think I understand the idea, sounds good to me. Working to clean up now. Thanks again, Conrad -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v5] 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 Signed-off-by: Conrad Meyer --- 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(-) diff --git a/fs/fat/fat.h b/fs/fat/fat.h index 7270bdb..13b7202 100644 --- a/fs/fat/fat.h +++ b/fs/fat/fat.h @@ -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 diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 992e8cb..85ea562 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -35,9 +35,47 @@ #define CONFIG_FAT_DEFAULT_IOCHARSET "" #endif +#define KB_IN_SECTORS 2 + 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) { @@ -945,7 +983,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 = { @@ -978,6 +1016,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"}, @@ -1180,6 +1219,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: @@ -1326,69 +1368,50 @@ static unsigned long calc_fat_clusters(struct super_block *sb) return sbi->fat_length * sb->s_blocksize * 8 / sbi->fat_bits; } -/* - * Read the super block of an MS-DOS FS. - */ -int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, - void (*setup)(struct super_block *)) +static bool fat_bpb_is_zero(struct fat_boot_sector *b) { - struct inode *root_inode = NULL, *fat_inode = NULL; - struct inode *fsinfo_inode = NULL; - struct buffer_head *bh; - struct fat_boot_sector *b; - struct msdos_sb_info
Re: [PATCH v4] fs: FAT: Add support for DOS 1.x formatted volumes
On Sun, 13 Apr 2014 12:57:42 +0900 OGAWA Hirofumi wrote: > Conrad Meyer writes: > > Hi, > > Sorry for late reply. > > > + > > + bd_sects = > > part_nr_sects_read(sb->s_bdev->bd_part); > > This would be better to use > i_read_size(>s_bdev->bd_inode->i_size) Ok, easy to fix. > > > + if (!fat_bpb_is_zero(b)) { > > + fat_msg(sb, KERN_ERR, "%s; DOS > > 2.x BPB is non-zero", > > + notdos1x); > > + brelse(bh); > > + goto out_invalid; > > + } > > Please don't message if silent. While auto detection, user > don't want to see message from kernel. Okay, fixed. > > > + if (sbi->options.dos1xfloppy) { > > + /* 16-bit DOS 1.x reliably wrote > > bootstrap short-jmp code */ > > + if (b->ignored[0] != 0xeb || > > b->ignored[2] != 0x90) { > > + fat_msg(sb, KERN_ERR, "%s; no > > bootstrapping code", > > + notdos1x); > > + brelse(bh); > > + goto out_invalid; > > + } > > [...] > > Looks like I was not explain my suggestion correctly. I was > intended to allow dos1xfloppy by option, not allow > dos1xfloppy only. > > I.e. > > err = read-from-bpb(); > if (err == -ENOTFATFS) > if (dos1xfloppy) > err = read-from-static-bpb(); > if (err) > goto error; > > > + if (sbi->options.dos1xfloppy) > > + total_sectors = fdefaults->nr_sectors; > > + else > > + total_sectors = > > get_unaligned_le16(>sectors); if (total_sectors == 0) > > total_sectors = > > le32_to_cpu(b->total_sect); > > Can we make 2 helpers to read from BPB and static BPB? If > possible, we would not be bothered by if (dos1xfloppy), > like above crappy pseudo. > > Thanks. We would have to duplicate, replace, or skip large parts of fat_fill_super(). This is why my initial approach was to just fill in BPB values in the SB copy in memory. We read from BPB over the course of 215 lines of code, ending here: > @@ -1527,7 +1659,10 @@ int fat_fill_super(struct > super_block *sb, void *data, int silent, int isvfat, > 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(>sectors); > + if (sbi->options.dos1xfloppy) > + total_sectors = fdefaults->nr_sectors; > + else > + total_sectors = > get_unaligned_le16(>sectors); if (total_sectors == 0) > total_sectors = > le32_to_cpu(b->total_sect); I will make an attempt at it. Thanks, Conrad -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v4] fs: FAT: Add support for DOS 1.x formatted volumes
On Sun, 13 Apr 2014 12:57:42 +0900 OGAWA Hirofumi hirof...@mail.parknet.co.jp wrote: Conrad Meyer ceme...@uw.edu writes: Hi, Sorry for late reply. + + bd_sects = part_nr_sects_read(sb-s_bdev-bd_part); This would be better to use i_read_size(sb-s_bdev-bd_inode-i_size) Ok, easy to fix. + if (!fat_bpb_is_zero(b)) { + fat_msg(sb, KERN_ERR, %s; DOS 2.x BPB is non-zero, + notdos1x); + brelse(bh); + goto out_invalid; + } Please don't message if silent. While auto detection, user don't want to see message from kernel. Okay, fixed. + if (sbi-options.dos1xfloppy) { + /* 16-bit DOS 1.x reliably wrote bootstrap short-jmp code */ + if (b-ignored[0] != 0xeb || b-ignored[2] != 0x90) { + fat_msg(sb, KERN_ERR, %s; no bootstrapping code, + notdos1x); + brelse(bh); + goto out_invalid; + } [...] Looks like I was not explain my suggestion correctly. I was intended to allow dos1xfloppy by option, not allow dos1xfloppy only. I.e. err = read-from-bpb(); if (err == -ENOTFATFS) if (dos1xfloppy) err = read-from-static-bpb(); if (err) goto error; + if (sbi-options.dos1xfloppy) + total_sectors = fdefaults-nr_sectors; + else + total_sectors = get_unaligned_le16(b-sectors); if (total_sectors == 0) total_sectors = le32_to_cpu(b-total_sect); Can we make 2 helpers to read from BPB and static BPB? If possible, we would not be bothered by if (dos1xfloppy), like above crappy pseudo. Thanks. We would have to duplicate, replace, or skip large parts of fat_fill_super(). This is why my initial approach was to just fill in BPB values in the SB copy in memory. We read from BPB over the course of 215 lines of code, ending here: @@ -1527,7 +1659,10 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, 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); + if (sbi-options.dos1xfloppy) + total_sectors = fdefaults-nr_sectors; + else + total_sectors = get_unaligned_le16(b-sectors); if (total_sectors == 0) total_sectors = le32_to_cpu(b-total_sect); I will make an attempt at it. Thanks, Conrad -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v5] 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 Signed-off-by: Conrad Meyer cse@gmail.com --- 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(-) diff --git a/fs/fat/fat.h b/fs/fat/fat.h index 7270bdb..13b7202 100644 --- a/fs/fat/fat.h +++ b/fs/fat/fat.h @@ -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 diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 992e8cb..85ea562 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -35,9 +35,47 @@ #define CONFIG_FAT_DEFAULT_IOCHARSET #endif +#define KB_IN_SECTORS 2 + 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) { @@ -945,7 +983,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 = { @@ -978,6 +1016,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}, @@ -1180,6 +1219,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: @@ -1326,69 +1368,50 @@ static unsigned long calc_fat_clusters(struct super_block *sb) return sbi-fat_length * sb-s_blocksize * 8 / sbi-fat_bits; } -/* - * Read the super block of an MS-DOS FS. - */ -int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, - void (*setup)(struct super_block *)) +static bool fat_bpb_is_zero(struct fat_boot_sector *b) { - struct inode *root_inode = NULL, *fat_inode = NULL; - struct inode *fsinfo_inode = NULL; - struct buffer_head *bh; - struct fat_boot_sector *b; - struct msdos_sb_info *sbi; - u16 logical_sector_size; - u32 total_sectors, total_clusters, fat_clusters
Re: [PATCH v5] fs: FAT: Add support for DOS 1.x formatted volumes
On Mon, 14 Apr 2014 07:14:51 +0900 OGAWA Hirofumi hirof...@mail.parknet.co.jp wrote: Conrad Meyer cse@gmail.com writes: + 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; + 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. Hi, I think I understand the idea, sounds good to me. Working to clean up now. Thanks again, Conrad -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v6] 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 Signed-off-by: Conrad Meyer cse@gmail.com --- Changes since v5: * Leave the bulk of sbi- filling logic to the aptly named fat_fill_super() * Create separate structure for deserialized BPB values * fat_read_bpb() deserializes BPB from raw fat_boot_sector and performs validations * fat_read_static_bpb() validates raw fat_boot_sector as dos1x and fills in BPB values from table Thanks, Conrad --- fs/fat/fat.h | 28 - fs/fat/inode.c | 316 +++-- 2 files changed, 267 insertions(+), 77 deletions(-) diff --git a/fs/fat/fat.h b/fs/fat/fat.h index 7270bdb..bcb0d67 100644 --- a/fs/fat/fat.h +++ b/fs/fat/fat.h @@ -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 @@ -139,6 +140,31 @@ struct fat_slot_info { struct buffer_head *bh; }; +/* + * 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 inline struct msdos_sb_info *MSDOS_SB(struct super_block *sb) { return sb-s_fs_info; diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 992e8cb..7727136 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -35,9 +35,47 @@ #define CONFIG_FAT_DEFAULT_IOCHARSET #endif +#define KB_IN_SECTORS 2 + 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) { @@ -945,7 +983,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 = { @@ -978,6 +1016,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}, @@ -1180,6 +1219,9 @@ static int parse_options(struct super_block *sb, char *options, int is_vfat
[PATCH v4] 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. 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 Signed-off-by: Conrad Meyer --- Changes since v3! * No EOF on floppy_defaults array (use ARRAY_SIZE instead) * Use correct format string/types for sector_t in fat_msg() * Pull out massive if () zero boolean expression into a hopefully expressively named helper function, fat_is_bpb_zero() Thanks for the feedback. --- fs/fat/fat.h | 3 +- fs/fat/inode.c | 175 ++--- 2 files changed, 157 insertions(+), 21 deletions(-) diff --git a/fs/fat/fat.h b/fs/fat/fat.h index 7270bdb..13b7202 100644 --- a/fs/fat/fat.h +++ b/fs/fat/fat.h @@ -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 diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 992e8cb..0f08ca4 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -35,9 +35,47 @@ #define CONFIG_FAT_DEFAULT_IOCHARSET "" #endif +#define KB_IN_SECTORS 2 + 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) { @@ -945,7 +983,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 = { @@ -978,6 +1016,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"}, @@ -1180,6 +1219,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: @@ -1326,21 +1368,49 @@ 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(>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(>dir_entries)) + return false; + if (get_unaligned_le16(>sectors)) + return false; + if (b->media) + return false; + if (b->fat_length) + return false; + if (b->secs_track) + return false; + if (b->heads) +
Re: [PATCH v2] fs: FAT: Add support for DOS 1.x formatted volumes
On Mon, Mar 31, 2014 at 3:13 PM, Andrew Morton wrote: > On Sat, 29 Mar 2014 12:10:35 -0700 Conrad Meyer wrote: > >> + .nr_sectors = 360 * KB_IN_SECTORS, >> + .sec_per_clus = 2, >> + .dir_entries = 112, >> + .media = 0xFD, >> + .fat_length = 2, >> +}, >> +{ 0 } }; > > We don't really need this EOF element. Ah, right, I forgot about ARRAY_SIZE. This is an old version of this patch, see v3 here: https://lkml.org/lkml/2014/3/31/275 But the same criticism is valid there, too. >> + if (get_unaligned_le16(>sector_size) != 0 || b->sec_per_clus != 0 || >> + b->reserved != 0 || b->fats != 0 || >> + get_unaligned_le16(>dir_entries) != 0 || >> + get_unaligned_le16(>sectors) != 0 || b->media != 0 || >> + b->fat_length != 0 || b->secs_track != 0 || b->heads != 0 || >> + b->secs_track != 0 || b->heads != 0) > > Impressive! I aim to please. Not sure what would be better -- memcmp() part of the struct to a zeroed array? > >> + return; >> + >> + bd_sects = part_nr_sects_read(sb->s_bdev->bd_part); >> + for (di = floppy_defaults; di->nr_sectors; di++) { > > Can do something like > > for (di = floppy_defaults; > di < floppy_defaults + ARRAY_SIZE(floppy_defaults); di++) { Yep, I should revise and send a v4 patch. Thanks. > >> + if (di->nr_sectors == bd_sects) >> + break; >> + } >> + if (di->nr_sectors == 0) { >> + fat_msg(sb, KERN_WARNING, >> + "DOS volume lacks BPB and isn't a recognized floppy >> size (%ld sectors)", >> + (long)bd_sects); > > sector_t can be u64 on 32-bit so one should really use %Lu and cast to > u64. Thanks, will fix. Conrad -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] fs: ext4: Sign-extend tv_sec after ORing in epoch bits
The problem exists in mainline (v3.14) and linux-next (20140328), so it looks like it didn't land. Unless it's queued in an ext4 tree and didn't get selected for Linus for some reason? Thanks, Conrad On Mon, Mar 31, 2014 at 8:34 AM, Andreas Dilger wrote: > Hmm, > I thought there was a separate patch to fix this a few months ago, that was > "more correct" than this one? Did that not land? > > Cheers, Andreas > >> On Mar 30, 2014, at 8:58, Conrad Meyer wrote: >> >> Fixes kernel.org bug #23732. >> >> Background: ext4 stores time as a 34-bit quantity; 2 bits in some extra >> bits unneeded for nanoseconds in the inode, and 32 bits in the seconds >> field. >> >> On systems with 64-bit time_t, the EXT4_*INODE_GET_XTIME() code >> incorrectly sign-extended the low 32-bits of the seconds quantity before >> ORing in the 2 "epoch" bits from nanoseconds. >> >> This patch ORs in the 2 higher bits, then sign extends the 34-bit signed >> number to 64 bits. >> >> Signed-off-by: Conrad Meyer >> --- >> Patch against next-20140328. >> >> Note, the on-disk format has always been written correctly. It was just >> interpreted incorrectly. >> >> Repro: >> Before: >> $ touch -d 2038-01-31 test-123 >> $ sudo sh -c "echo 3 > /proc/sys/vm/drop_caches" >> $ ls -ld test-123 >> drwxrwxr-x 2 cmeyer cmeyer 4096 Dec 25 1901 test-123 >> >> After: >> $ ls -ld test-123 >> drwxrwxr-x 2 cmeyer cmeyer 4096 Jan 31 2038 test-123 >> >> Thanks! >> --- >> fs/ext4/ext4.h | 14 -- >> 1 file changed, 12 insertions(+), 2 deletions(-) >> >> diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h >> index f4f889e..07ee03d 100644 >> --- a/fs/ext4/ext4.h >> +++ b/fs/ext4/ext4.h >> @@ -710,6 +710,8 @@ struct move_extent { >> #define EXT4_EPOCH_BITS 2 >> #define EXT4_EPOCH_MASK ((1 << EXT4_EPOCH_BITS) - 1) >> #define EXT4_NSEC_MASK (~0UL << EXT4_EPOCH_BITS) >> +#define EXT4_EPOCH_SIGN (((1UL << (EXT4_EPOCH_BITS - 1)) << 16) << 16) >> +#define EXT4_SIGN_EXT (~1UL << EXT4_EPOCH_BITS) << 16) << 16) - 1)) >> >> /* >> * Extended fields will fit into an inode if the filesystem was formatted >> @@ -761,19 +763,23 @@ do { \ >> >> #define EXT4_INODE_GET_XTIME(xtime, inode, raw_inode) \ >> do { \ >> -(inode)->xtime.tv_sec = (signed)le32_to_cpu((raw_inode)->xtime); \ >> +(inode)->xtime.tv_sec = (__u64)le32_to_cpu((raw_inode)->xtime); >> \ >>if (EXT4_FITS_IN_INODE(raw_inode, EXT4_I(inode), xtime ## _extra)) \ >>ext4_decode_extra_time(&(inode)->xtime, \ >> raw_inode->xtime ## _extra); \ >>else \ >>(inode)->xtime.tv_nsec = 0; \ >> +if (sizeof((inode)->xtime.tv_sec) > 4) { \ >> +if ((inode)->xtime.tv_sec & EXT4_EPOCH_SIGN) \ >> +(inode)->xtime.tv_sec |= EXT4_SIGN_EXT; \ >> +} \ >> } while (0) >> >> #define EXT4_EINODE_GET_XTIME(xtime, einode, raw_inode) \ >> do { \ >>if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime)) \ >>(einode)->xtime.tv_sec = \ >> -(signed)le32_to_cpu((raw_inode)->xtime); \ >> +(__u64)le32_to_cpu((raw_inode)->xtime); \ >>else \ >>(einode)->xtime.tv_sec = 0; \ >>if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime ## _extra)) \ >> @@ -781,6 +787,10 @@ do { \ >> raw_inode->xtime ## _extra); \ >>else \ >>(einode)->xtime.tv_nsec = 0; \ >> +if (sizeof((einode)->xtime.tv_sec) > 4) { \ >> +if ((einode)->xtime.tv_sec & EXT4_EPOCH_SIGN) \ >> +(einode)->xtime.tv_sec |= EXT4_SIGN_EXT; \ >> +} \ >> } while (0) >> >> #define i_disk_version osd1.linux1.l_i_version >> -- >> 1.9.0 >> -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v3] 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. 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 Signed-off-by: Conrad Meyer --- Based on next-20140328. Changes since v2: * Only attempt to infer BPB values if mounted with -o dos1xfloppy * Set sbi->* values directly instead of writing out BPB Works fine in local tests. Can mount 1985 floppy image and explore files (with dos1xfloppy option). Without option, mount fails (expected). Thanks. --- fs/fat/fat.h | 3 +- fs/fat/inode.c | 154 ++--- 2 files changed, 137 insertions(+), 20 deletions(-) diff --git a/fs/fat/fat.h b/fs/fat/fat.h index 7270bdb..13b7202 100644 --- a/fs/fat/fat.h +++ b/fs/fat/fat.h @@ -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 diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 992e8cb..d032e3c 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -35,9 +35,47 @@ #define CONFIG_FAT_DEFAULT_IOCHARSET "" #endif +#define KB_IN_SECTORS 2 + 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, +}, +{ 0 } }; static int fat_add_cluster(struct inode *inode) { @@ -945,7 +983,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 = { @@ -978,6 +1016,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"}, @@ -1180,6 +1219,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: @@ -1332,13 +1374,16 @@ static unsigned long calc_fat_clusters(struct super_block *sb) int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, void (*setup)(struct super_block *)) { + static const char *notdos1x = "This doesn't look like a DOS 1.x volume"; struct inode *root_inode = NULL, *fat_inode = NULL; + struct fat_floppy_defaults *fdefaults = NULL; struct inode *fsinfo_inode = NULL; struct buffer_head *bh; struct fat_boot_sector *b; struct msdos_sb_info *sbi; u16 logical_sector_size; u32 total_sectors, total_clusters, fat_clusters, rootdir_sectors; + sector_t bd_sects; int debug; unsigned int media; long error; @@
Re: [PATCH v2] fs: FAT: Add support for DOS 1.x formatted volumes
On Mon, 31 Mar 2014 23:07:32 +0900 OGAWA Hirofumi wrote: > Conrad Meyer writes: > > > +static void fat_update_archaic_boot_sector(struct > > super_block *sb, > > + struct fat_boot_sector *b) > > +{ > > + struct fat_floppy_defaults *di; > > + sector_t bd_sects; > > + > > + /* 16-bit DOS 1.x reliably wrote bootstrap > > short-jmp code */ > > + if (b->ignored[0] != 0xeb || b->ignored[2] != > > 0x90) > > + return; > > + > > + /* > > +* If any value in this region is non-zero, > > don't assume it is archaic > > +* DOS. > > +*/ > > + if (get_unaligned_le16(>sector_size) != 0 || > > b->sec_per_clus != 0 || > > + b->reserved != 0 || b->fats != 0 || > > + get_unaligned_le16(>dir_entries) != 0 > > || > > + get_unaligned_le16(>sectors) != 0 || > > b->media != 0 || > > + b->fat_length != 0 || b->secs_track != 0 > > || b->heads != 0 || > > + b->secs_track != 0 || b->heads != 0) > > + return; > > Probably, too weak detection to use by default. So, how > about to use mount option to enable this? > > And only if user asked to enable explicitly by mount > option, allow this format. Okay. Do you have a preference for option name? "archaicdos", "dos1x", "guessbpb", other? > > + bd_sects = > > part_nr_sects_read(sb->s_bdev->bd_part); > > + for (di = floppy_defaults; di->nr_sectors; di++) > > { > > + if (di->nr_sectors == bd_sects) > > + break; > > + } > > + if (di->nr_sectors == 0) { > > + fat_msg(sb, KERN_WARNING, > > + "DOS volume lacks BPB and isn't > > a recognized floppy size (%ld sectors)", > > + (long)bd_sects); > > + return; > > + } > > + > > + fat_msg(sb, KERN_INFO, > > + "Volume lacks BPB but looks like archaic > > DOS; assuming default BPB values"); + > > + b->sec_per_clus = di->sec_per_clus; > > + put_unaligned_le16(di->dir_entries, > > >dir_entries); > > + b->media = di->media; > > + b->fat_length = cpu_to_le16(di->fat_length); > > + put_unaligned_le16(SECTOR_SIZE, >sector_size); > > + b->reserved = cpu_to_le16(1); > > + b->fats = 2; > > + put_unaligned_le16(bd_sects, >sectors); > > +} > > + > > +/* > > * Read the super block of an MS-DOS FS. > > */ > > int fat_fill_super(struct super_block *sb, void *data, > > int silent, int isvfat, @@ -1297,6 +1387,8 @@ int > > fat_fill_super(struct super_block *sb, void *data, int > > silent, int isvfat, } > > b = (struct fat_boot_sector *) bh->b_data; > > + fat_update_archaic_boot_sector(sb, b); > > This would be better to set sbi->* directly, not via > modified BPB. Hm, I thought so too, but there are lots of sbi-> fields and I didn't want to duplicate any shared filling logic in a different place. But I will make the change... > > > if (!b->reserved) { > > if (!silent) > > fat_msg(sb, KERN_ERR, "bogus > > number of reserved sectors"); @@ -1364,6 +1456,7 @@ 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; > > + fat_update_archaic_boot_sector(sb, b); > > This doesn't need. If logical_sector_size is 512, this > format doesn't work. Right. Okay, give me some time to revise a v3 patch. Thanks, Conrad -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v2] fs: FAT: Add support for DOS 1.x formatted volumes
On Mon, 31 Mar 2014 23:07:32 +0900 OGAWA Hirofumi hirof...@mail.parknet.co.jp wrote: Conrad Meyer ceme...@uw.edu writes: +static void fat_update_archaic_boot_sector(struct super_block *sb, + struct fat_boot_sector *b) +{ + struct fat_floppy_defaults *di; + sector_t bd_sects; + + /* 16-bit DOS 1.x reliably wrote bootstrap short-jmp code */ + if (b-ignored[0] != 0xeb || b-ignored[2] != 0x90) + return; + + /* +* If any value in this region is non-zero, don't assume it is archaic +* DOS. +*/ + if (get_unaligned_le16(b-sector_size) != 0 || b-sec_per_clus != 0 || + b-reserved != 0 || b-fats != 0 || + get_unaligned_le16(b-dir_entries) != 0 || + get_unaligned_le16(b-sectors) != 0 || b-media != 0 || + b-fat_length != 0 || b-secs_track != 0 || b-heads != 0 || + b-secs_track != 0 || b-heads != 0) + return; Probably, too weak detection to use by default. So, how about to use mount option to enable this? And only if user asked to enable explicitly by mount option, allow this format. Okay. Do you have a preference for option name? archaicdos, dos1x, guessbpb, other? + bd_sects = part_nr_sects_read(sb-s_bdev-bd_part); + for (di = floppy_defaults; di-nr_sectors; di++) { + if (di-nr_sectors == bd_sects) + break; + } + if (di-nr_sectors == 0) { + fat_msg(sb, KERN_WARNING, + DOS volume lacks BPB and isn't a recognized floppy size (%ld sectors), + (long)bd_sects); + return; + } + + fat_msg(sb, KERN_INFO, + Volume lacks BPB but looks like archaic DOS; assuming default BPB values); + + b-sec_per_clus = di-sec_per_clus; + put_unaligned_le16(di-dir_entries, b-dir_entries); + b-media = di-media; + b-fat_length = cpu_to_le16(di-fat_length); + put_unaligned_le16(SECTOR_SIZE, b-sector_size); + b-reserved = cpu_to_le16(1); + b-fats = 2; + put_unaligned_le16(bd_sects, b-sectors); +} + +/* * Read the super block of an MS-DOS FS. */ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, @@ -1297,6 +1387,8 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, } b = (struct fat_boot_sector *) bh-b_data; + fat_update_archaic_boot_sector(sb, b); This would be better to set sbi-* directly, not via modified BPB. Hm, I thought so too, but there are lots of sbi- fields and I didn't want to duplicate any shared filling logic in a different place. But I will make the change... if (!b-reserved) { if (!silent) fat_msg(sb, KERN_ERR, bogus number of reserved sectors); @@ -1364,6 +1456,7 @@ 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; + fat_update_archaic_boot_sector(sb, b); This doesn't need. If logical_sector_size is 512, this format doesn't work. Right. Okay, give me some time to revise a v3 patch. Thanks, Conrad -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v3] 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. 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 Signed-off-by: Conrad Meyer cse@gmail.com --- Based on next-20140328. Changes since v2: * Only attempt to infer BPB values if mounted with -o dos1xfloppy * Set sbi-* values directly instead of writing out BPB Works fine in local tests. Can mount 1985 floppy image and explore files (with dos1xfloppy option). Without option, mount fails (expected). Thanks. --- fs/fat/fat.h | 3 +- fs/fat/inode.c | 154 ++--- 2 files changed, 137 insertions(+), 20 deletions(-) diff --git a/fs/fat/fat.h b/fs/fat/fat.h index 7270bdb..13b7202 100644 --- a/fs/fat/fat.h +++ b/fs/fat/fat.h @@ -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 diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 992e8cb..d032e3c 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -35,9 +35,47 @@ #define CONFIG_FAT_DEFAULT_IOCHARSET #endif +#define KB_IN_SECTORS 2 + 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, +}, +{ 0 } }; static int fat_add_cluster(struct inode *inode) { @@ -945,7 +983,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 = { @@ -978,6 +1016,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}, @@ -1180,6 +1219,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: @@ -1332,13 +1374,16 @@ static unsigned long calc_fat_clusters(struct super_block *sb) int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, void (*setup)(struct super_block *)) { + static const char *notdos1x = This doesn't look like a DOS 1.x volume; struct inode *root_inode = NULL, *fat_inode = NULL; + struct fat_floppy_defaults *fdefaults = NULL; struct inode *fsinfo_inode = NULL; struct buffer_head *bh; struct fat_boot_sector *b; struct msdos_sb_info *sbi; u16 logical_sector_size; u32 total_sectors, total_clusters, fat_clusters, rootdir_sectors; + sector_t bd_sects; int debug; unsigned int media; long error; @@ -1378,17 +1423,66 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, } b
Re: [PATCH] fs: ext4: Sign-extend tv_sec after ORing in epoch bits
The problem exists in mainline (v3.14) and linux-next (20140328), so it looks like it didn't land. Unless it's queued in an ext4 tree and didn't get selected for Linus for some reason? Thanks, Conrad On Mon, Mar 31, 2014 at 8:34 AM, Andreas Dilger adil...@dilger.ca wrote: Hmm, I thought there was a separate patch to fix this a few months ago, that was more correct than this one? Did that not land? Cheers, Andreas On Mar 30, 2014, at 8:58, Conrad Meyer ceme...@uw.edu wrote: Fixes kernel.org bug #23732. Background: ext4 stores time as a 34-bit quantity; 2 bits in some extra bits unneeded for nanoseconds in the inode, and 32 bits in the seconds field. On systems with 64-bit time_t, the EXT4_*INODE_GET_XTIME() code incorrectly sign-extended the low 32-bits of the seconds quantity before ORing in the 2 epoch bits from nanoseconds. This patch ORs in the 2 higher bits, then sign extends the 34-bit signed number to 64 bits. Signed-off-by: Conrad Meyer cse@gmail.com --- Patch against next-20140328. Note, the on-disk format has always been written correctly. It was just interpreted incorrectly. Repro: Before: $ touch -d 2038-01-31 test-123 $ sudo sh -c echo 3 /proc/sys/vm/drop_caches $ ls -ld test-123 drwxrwxr-x 2 cmeyer cmeyer 4096 Dec 25 1901 test-123 After: $ ls -ld test-123 drwxrwxr-x 2 cmeyer cmeyer 4096 Jan 31 2038 test-123 Thanks! --- fs/ext4/ext4.h | 14 -- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index f4f889e..07ee03d 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -710,6 +710,8 @@ struct move_extent { #define EXT4_EPOCH_BITS 2 #define EXT4_EPOCH_MASK ((1 EXT4_EPOCH_BITS) - 1) #define EXT4_NSEC_MASK (~0UL EXT4_EPOCH_BITS) +#define EXT4_EPOCH_SIGN (((1UL (EXT4_EPOCH_BITS - 1)) 16) 16) +#define EXT4_SIGN_EXT (~1UL EXT4_EPOCH_BITS) 16) 16) - 1)) /* * Extended fields will fit into an inode if the filesystem was formatted @@ -761,19 +763,23 @@ do { \ #define EXT4_INODE_GET_XTIME(xtime, inode, raw_inode) \ do { \ -(inode)-xtime.tv_sec = (signed)le32_to_cpu((raw_inode)-xtime); \ +(inode)-xtime.tv_sec = (__u64)le32_to_cpu((raw_inode)-xtime); \ if (EXT4_FITS_IN_INODE(raw_inode, EXT4_I(inode), xtime ## _extra)) \ ext4_decode_extra_time((inode)-xtime, \ raw_inode-xtime ## _extra); \ else \ (inode)-xtime.tv_nsec = 0; \ +if (sizeof((inode)-xtime.tv_sec) 4) { \ +if ((inode)-xtime.tv_sec EXT4_EPOCH_SIGN) \ +(inode)-xtime.tv_sec |= EXT4_SIGN_EXT; \ +} \ } while (0) #define EXT4_EINODE_GET_XTIME(xtime, einode, raw_inode) \ do { \ if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime)) \ (einode)-xtime.tv_sec = \ -(signed)le32_to_cpu((raw_inode)-xtime); \ +(__u64)le32_to_cpu((raw_inode)-xtime); \ else \ (einode)-xtime.tv_sec = 0; \ if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime ## _extra)) \ @@ -781,6 +787,10 @@ do { \ raw_inode-xtime ## _extra); \ else \ (einode)-xtime.tv_nsec = 0; \ +if (sizeof((einode)-xtime.tv_sec) 4) { \ +if ((einode)-xtime.tv_sec EXT4_EPOCH_SIGN) \ +(einode)-xtime.tv_sec |= EXT4_SIGN_EXT; \ +} \ } while (0) #define i_disk_version osd1.linux1.l_i_version -- 1.9.0 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v2] fs: FAT: Add support for DOS 1.x formatted volumes
On Mon, Mar 31, 2014 at 3:13 PM, Andrew Morton a...@linux-foundation.org wrote: On Sat, 29 Mar 2014 12:10:35 -0700 Conrad Meyer ceme...@uw.edu wrote: + .nr_sectors = 360 * KB_IN_SECTORS, + .sec_per_clus = 2, + .dir_entries = 112, + .media = 0xFD, + .fat_length = 2, +}, +{ 0 } }; We don't really need this EOF element. Ah, right, I forgot about ARRAY_SIZE. This is an old version of this patch, see v3 here: https://lkml.org/lkml/2014/3/31/275 But the same criticism is valid there, too. + if (get_unaligned_le16(b-sector_size) != 0 || b-sec_per_clus != 0 || + b-reserved != 0 || b-fats != 0 || + get_unaligned_le16(b-dir_entries) != 0 || + get_unaligned_le16(b-sectors) != 0 || b-media != 0 || + b-fat_length != 0 || b-secs_track != 0 || b-heads != 0 || + b-secs_track != 0 || b-heads != 0) Impressive! I aim to please. Not sure what would be better -- memcmp() part of the struct to a zeroed array? + return; + + bd_sects = part_nr_sects_read(sb-s_bdev-bd_part); + for (di = floppy_defaults; di-nr_sectors; di++) { Can do something like for (di = floppy_defaults; di floppy_defaults + ARRAY_SIZE(floppy_defaults); di++) { Yep, I should revise and send a v4 patch. Thanks. + if (di-nr_sectors == bd_sects) + break; + } + if (di-nr_sectors == 0) { + fat_msg(sb, KERN_WARNING, + DOS volume lacks BPB and isn't a recognized floppy size (%ld sectors), + (long)bd_sects); sector_t can be u64 on 32-bit so one should really use %Lu and cast to u64. Thanks, will fix. Conrad -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v4] 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. 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 Signed-off-by: Conrad Meyer cse@gmail.com --- Changes since v3! * No EOF on floppy_defaults array (use ARRAY_SIZE instead) * Use correct format string/types for sector_t in fat_msg() * Pull out massive if () zero boolean expression into a hopefully expressively named helper function, fat_is_bpb_zero() Thanks for the feedback. --- fs/fat/fat.h | 3 +- fs/fat/inode.c | 175 ++--- 2 files changed, 157 insertions(+), 21 deletions(-) diff --git a/fs/fat/fat.h b/fs/fat/fat.h index 7270bdb..13b7202 100644 --- a/fs/fat/fat.h +++ b/fs/fat/fat.h @@ -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 diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 992e8cb..0f08ca4 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -35,9 +35,47 @@ #define CONFIG_FAT_DEFAULT_IOCHARSET #endif +#define KB_IN_SECTORS 2 + 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) { @@ -945,7 +983,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 = { @@ -978,6 +1016,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}, @@ -1180,6 +1219,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: @@ -1326,21 +1368,49 @@ 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; +} + /* * Read the super block of an MS-DOS FS. */ int fat_fill_super(struct
[PATCH] fs: ext4: Sign-extend tv_sec after ORing in epoch bits
Fixes kernel.org bug #23732. Background: ext4 stores time as a 34-bit quantity; 2 bits in some extra bits unneeded for nanoseconds in the inode, and 32 bits in the seconds field. On systems with 64-bit time_t, the EXT4_*INODE_GET_XTIME() code incorrectly sign-extended the low 32-bits of the seconds quantity before ORing in the 2 "epoch" bits from nanoseconds. This patch ORs in the 2 higher bits, then sign extends the 34-bit signed number to 64 bits. Signed-off-by: Conrad Meyer --- Patch against next-20140328. Note, the on-disk format has always been written correctly. It was just interpreted incorrectly. Repro: Before: $ touch -d 2038-01-31 test-123 $ sudo sh -c "echo 3 > /proc/sys/vm/drop_caches" $ ls -ld test-123 drwxrwxr-x 2 cmeyer cmeyer 4096 Dec 25 1901 test-123 After: $ ls -ld test-123 drwxrwxr-x 2 cmeyer cmeyer 4096 Jan 31 2038 test-123 Thanks! --- fs/ext4/ext4.h | 14 -- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index f4f889e..07ee03d 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -710,6 +710,8 @@ struct move_extent { #define EXT4_EPOCH_BITS 2 #define EXT4_EPOCH_MASK ((1 << EXT4_EPOCH_BITS) - 1) #define EXT4_NSEC_MASK (~0UL << EXT4_EPOCH_BITS) +#define EXT4_EPOCH_SIGN (((1UL << (EXT4_EPOCH_BITS - 1)) << 16) << 16) +#define EXT4_SIGN_EXT (~1UL << EXT4_EPOCH_BITS) << 16) << 16) - 1)) /* * Extended fields will fit into an inode if the filesystem was formatted @@ -761,19 +763,23 @@ do { \ #define EXT4_INODE_GET_XTIME(xtime, inode, raw_inode) \ do { \ - (inode)->xtime.tv_sec = (signed)le32_to_cpu((raw_inode)->xtime); \ + (inode)->xtime.tv_sec = (__u64)le32_to_cpu((raw_inode)->xtime);\ if (EXT4_FITS_IN_INODE(raw_inode, EXT4_I(inode), xtime ## _extra)) \ ext4_decode_extra_time(&(inode)->xtime,\ raw_inode->xtime ## _extra);\ else \ (inode)->xtime.tv_nsec = 0;\ + if (sizeof((inode)->xtime.tv_sec) > 4) { \ + if ((inode)->xtime.tv_sec & EXT4_EPOCH_SIGN) \ + (inode)->xtime.tv_sec |= EXT4_SIGN_EXT;\ + } \ } while (0) #define EXT4_EINODE_GET_XTIME(xtime, einode, raw_inode) \ do { \ if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime)) \ (einode)->xtime.tv_sec = \ - (signed)le32_to_cpu((raw_inode)->xtime); \ + (__u64)le32_to_cpu((raw_inode)->xtime);\ else \ (einode)->xtime.tv_sec = 0;\ if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime ## _extra))\ @@ -781,6 +787,10 @@ do { \ raw_inode->xtime ## _extra);\ else \ (einode)->xtime.tv_nsec = 0; \ + if (sizeof((einode)->xtime.tv_sec) > 4) { \ + if ((einode)->xtime.tv_sec & EXT4_EPOCH_SIGN) \ + (einode)->xtime.tv_sec |= EXT4_SIGN_EXT; \ + } \ } while (0) #define i_disk_version osd1.linux1.l_i_version -- 1.9.0 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] fs: ext4: Sign-extend tv_sec after ORing in epoch bits
Fixes kernel.org bug #23732. Background: ext4 stores time as a 34-bit quantity; 2 bits in some extra bits unneeded for nanoseconds in the inode, and 32 bits in the seconds field. On systems with 64-bit time_t, the EXT4_*INODE_GET_XTIME() code incorrectly sign-extended the low 32-bits of the seconds quantity before ORing in the 2 epoch bits from nanoseconds. This patch ORs in the 2 higher bits, then sign extends the 34-bit signed number to 64 bits. Signed-off-by: Conrad Meyer cse@gmail.com --- Patch against next-20140328. Note, the on-disk format has always been written correctly. It was just interpreted incorrectly. Repro: Before: $ touch -d 2038-01-31 test-123 $ sudo sh -c echo 3 /proc/sys/vm/drop_caches $ ls -ld test-123 drwxrwxr-x 2 cmeyer cmeyer 4096 Dec 25 1901 test-123 After: $ ls -ld test-123 drwxrwxr-x 2 cmeyer cmeyer 4096 Jan 31 2038 test-123 Thanks! --- fs/ext4/ext4.h | 14 -- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index f4f889e..07ee03d 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -710,6 +710,8 @@ struct move_extent { #define EXT4_EPOCH_BITS 2 #define EXT4_EPOCH_MASK ((1 EXT4_EPOCH_BITS) - 1) #define EXT4_NSEC_MASK (~0UL EXT4_EPOCH_BITS) +#define EXT4_EPOCH_SIGN (((1UL (EXT4_EPOCH_BITS - 1)) 16) 16) +#define EXT4_SIGN_EXT (~1UL EXT4_EPOCH_BITS) 16) 16) - 1)) /* * Extended fields will fit into an inode if the filesystem was formatted @@ -761,19 +763,23 @@ do { \ #define EXT4_INODE_GET_XTIME(xtime, inode, raw_inode) \ do { \ - (inode)-xtime.tv_sec = (signed)le32_to_cpu((raw_inode)-xtime); \ + (inode)-xtime.tv_sec = (__u64)le32_to_cpu((raw_inode)-xtime);\ if (EXT4_FITS_IN_INODE(raw_inode, EXT4_I(inode), xtime ## _extra)) \ ext4_decode_extra_time((inode)-xtime,\ raw_inode-xtime ## _extra);\ else \ (inode)-xtime.tv_nsec = 0;\ + if (sizeof((inode)-xtime.tv_sec) 4) { \ + if ((inode)-xtime.tv_sec EXT4_EPOCH_SIGN) \ + (inode)-xtime.tv_sec |= EXT4_SIGN_EXT;\ + } \ } while (0) #define EXT4_EINODE_GET_XTIME(xtime, einode, raw_inode) \ do { \ if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime)) \ (einode)-xtime.tv_sec = \ - (signed)le32_to_cpu((raw_inode)-xtime); \ + (__u64)le32_to_cpu((raw_inode)-xtime);\ else \ (einode)-xtime.tv_sec = 0;\ if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime ## _extra))\ @@ -781,6 +787,10 @@ do { \ raw_inode-xtime ## _extra);\ else \ (einode)-xtime.tv_nsec = 0; \ + if (sizeof((einode)-xtime.tv_sec) 4) { \ + if ((einode)-xtime.tv_sec EXT4_EPOCH_SIGN) \ + (einode)-xtime.tv_sec |= EXT4_SIGN_EXT; \ + } \ } while (0) #define i_disk_version osd1.linux1.l_i_version -- 1.9.0 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2] fs: FAT: Add support for DOS 1.x formatted volumes
When possible, infer DOS 2.x BIOS Parameter Block from block device geometry (for floppies and floppy images). Update in-memory only. We only perform this update when the entire BPB region is zeroed, like produced by DOS 1.x-era FORMAT (and other OEM variations on DOS). Fixes kernel.org bug #42617. BPB default 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 Signed-off-by: Conrad Meyer --- Diff from v3.14-rc8. Changes since v1: * Check for FAT bootstrap prefix (EB xx 90) to help avoid conflicting with other filesystems * Move default from a switch to a static table Thanks! --- fs/fat/inode.c | 93 ++ 1 file changed, 93 insertions(+) diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 854b578..c31fbdc 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -35,9 +35,47 @@ #define CONFIG_FAT_DEFAULT_IOCHARSET "" #endif +#define KB_IN_SECTORS 2 + 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, +}, +{ 0 } }; static int fat_add_cluster(struct inode *inode) { @@ -1246,6 +1284,58 @@ static unsigned long calc_fat_clusters(struct super_block *sb) } /* + * If this FAT filesystem is archaic (lacking a BIOS Parameter Block, ca. DOS + * 1.x), fix it up in-place by creating a DOS 2.x BIOS Parameter Block from + * defaults for the media size. + */ +static void fat_update_archaic_boot_sector(struct super_block *sb, + struct fat_boot_sector *b) +{ + struct fat_floppy_defaults *di; + sector_t bd_sects; + + /* 16-bit DOS 1.x reliably wrote bootstrap short-jmp code */ + if (b->ignored[0] != 0xeb || b->ignored[2] != 0x90) + return; + + /* +* If any value in this region is non-zero, don't assume it is archaic +* DOS. +*/ + if (get_unaligned_le16(>sector_size) != 0 || b->sec_per_clus != 0 || + b->reserved != 0 || b->fats != 0 || + get_unaligned_le16(>dir_entries) != 0 || + get_unaligned_le16(>sectors) != 0 || b->media != 0 || + b->fat_length != 0 || b->secs_track != 0 || b->heads != 0 || + b->secs_track != 0 || b->heads != 0) + return; + + bd_sects = part_nr_sects_read(sb->s_bdev->bd_part); + for (di = floppy_defaults; di->nr_sectors; di++) { + if (di->nr_sectors == bd_sects) + break; + } + if (di->nr_sectors == 0) { + fat_msg(sb, KERN_WARNING, + "DOS volume lacks BPB and isn't a recognized floppy size (%ld sectors)", + (long)bd_sects); + return; + } + + fat_msg(sb, KERN_INFO, + "Volume lacks BPB but looks like archaic DOS; assuming default BPB values"); + + b->sec_per_clus = di->sec_per_clus; + put_unaligned_le16(di->dir_entries, >dir_entries); + b->media = di->media; + b->fat_length = cpu_to_le16(di->fat_length); + put_unaligned_le16(SECTOR_SIZE, >sector_size); + b->reserved = cpu_to_le16(1); + b->fats = 2; + put_unaligned_le16(bd_sects, >sectors); +} + +/* * Read the super block of an MS-DOS FS. */ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, @@ -1297,6 +1387,8 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, } b = (struct fat_boot_sector *) bh->b_data; + fat_update_archaic_boot_sector(sb, b); + if (!b->reserved) { if (!silent) fat_msg(sb, KERN_ERR, "bogus number of reserved sectors"); @@ -1364,6 +1456,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, goto
Re: [PATCH] fs: FAT: Add support for DOS 1.x formatted volumes
On Sun, 30 Mar 2014 02:56:46 +0900 OGAWA Hirofumi wrote: > Conrad Meyer writes: > > Hi, > > > When possible, infer DOS 2.x BIOS Parameter Block from > > block device geometry (for floppies and floppy images). > > Update in-memory only. We only perform this update when > > the entire BPB region is zeroed, like produced by DOS > > 1.x-era FORMAT (and other OEM variations on DOS). > > > > Fixes kernel.org bug #42617. > > > > BPB default 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 > > [...] > > > +static void fat_update_archaic_boot_sector(struct > > super_block *sb, > > + struct fat_boot_sector *b) > > +{ > > + sector_t bd_sects; > > + > > + if (get_unaligned_le16(>sector_size) != 0 || > > b->sec_per_clus != 0 || > > + b->reserved != 0 || b->fats != 0 || > > + get_unaligned_le16(>dir_entries) != 0 > > || > > + get_unaligned_le16(>sectors) != 0 || > > b->media != 0 || > > + b->fat_length != 0 || b->secs_track != 0 > > || b->heads != 0 || > > + b->secs_track != 0 || b->heads != 0) > > + return; > > + > > + bd_sects = > > part_nr_sects_read(sb->s_bdev->bd_part); > > + switch (bd_sects) { > > + case 160 * KB_IN_SECTORS: > > + b->sec_per_clus = 1; > > + put_unaligned_le16(64, >dir_entries); > > + b->media = 0xFE; > > + b->fat_length = cpu_to_le16(1); > > + break; > > [...] > > Hm, this looks like check the volume size. But if there is > newer fat format on same volume size, how to detect it? Or, > it is conflicting? Newer fat volumes will have some non-zero values in the BPB -- see the early return at the top of the update function. So this code will ignore them. > > [BTW, we should avoid to mount if it doesn't seem fatfs, to > prevent mis-mount as fatfs (auto mount is depending on this > detection).] > > Thanks. Hmm, good point. The checks for zero values in 0x0b through ~0x19 (BPB 2 with some of the BPB 3 fields) should help prevent conflicts, to some degree. We can also check the 3-byte field "ignored" in struct fat_boot_sector -- it is commonly "eb xx 90" (x86: JMP [rel8] ; NOP) but can also be "e9 xx xx xx xx" (x86: JMP [rel32]). These old floppies were only ever created on 16-bit machines, so I think we can conditionalize on "eb xx 90". I will fix and resend. The first three bytes are on all the images from 1985 I have are: eb 1c 90. Here's the full boot sector. Perhaps we can also conditionalize on the "Not system boot floppy" string? Probably not, we want to support mounting boot floppies as well. 000: eb1c 9000 010: fa33 ...3 020: c08e d0bc 0006 fb0e e846 00b4 06b0 00b7 .F.. 030: 07b9 ba4f 18cd 10b4 02ba b700 .O.. 040: cd10 beb8 102e 8a04 0ac0 74f9 56b4 0ebb ..t.V... 050: 0700 cd10 5e46 ebed 074e 6f74 2073 7973 ^F...Not sys 060: 7465 6d20 626f 6f74 2066 6c6f 7070 792e tem boot floppy. 070: 0058 5bba 8b10 8bca 2bd0 d1fa d1fa d1fa .X[.+... 080: d1fa 2bda 5351 cb00 ..+.SQ.. The rest (0x090-0x1ff) is zeroes. And here's the disassembly of the address signified by "JMP +0x1c" (0x1e): 0x001e fa cli 0x001f 33c0xor %ax,%ax 0x0021 8ed0mov %ax,%ss 0x0023 bc0006 mov $0x600,%sp 0x0026 fb sti 0x0027 0e push %cs 0x0028 e84600 call func_0071 Not sure how common that is among FAT images; mkfs.fat does not appear to generate valid code, other than eb 3c 90 at the beginning of the sector. Thanks, Conrad -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] fs: FAT: Add support for DOS 1.x formatted volumes
On Sun, 30 Mar 2014 02:56:46 +0900 OGAWA Hirofumi hirof...@mail.parknet.co.jp wrote: Conrad Meyer ceme...@uw.edu writes: Hi, When possible, infer DOS 2.x BIOS Parameter Block from block device geometry (for floppies and floppy images). Update in-memory only. We only perform this update when the entire BPB region is zeroed, like produced by DOS 1.x-era FORMAT (and other OEM variations on DOS). Fixes kernel.org bug #42617. BPB default 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 [...] +static void fat_update_archaic_boot_sector(struct super_block *sb, + struct fat_boot_sector *b) +{ + sector_t bd_sects; + + if (get_unaligned_le16(b-sector_size) != 0 || b-sec_per_clus != 0 || + b-reserved != 0 || b-fats != 0 || + get_unaligned_le16(b-dir_entries) != 0 || + get_unaligned_le16(b-sectors) != 0 || b-media != 0 || + b-fat_length != 0 || b-secs_track != 0 || b-heads != 0 || + b-secs_track != 0 || b-heads != 0) + return; + + bd_sects = part_nr_sects_read(sb-s_bdev-bd_part); + switch (bd_sects) { + case 160 * KB_IN_SECTORS: + b-sec_per_clus = 1; + put_unaligned_le16(64, b-dir_entries); + b-media = 0xFE; + b-fat_length = cpu_to_le16(1); + break; [...] Hm, this looks like check the volume size. But if there is newer fat format on same volume size, how to detect it? Or, it is conflicting? Newer fat volumes will have some non-zero values in the BPB -- see the early return at the top of the update function. So this code will ignore them. [BTW, we should avoid to mount if it doesn't seem fatfs, to prevent mis-mount as fatfs (auto mount is depending on this detection).] Thanks. Hmm, good point. The checks for zero values in 0x0b through ~0x19 (BPB 2 with some of the BPB 3 fields) should help prevent conflicts, to some degree. We can also check the 3-byte field ignored in struct fat_boot_sector -- it is commonly eb xx 90 (x86: JMP [rel8] ; NOP) but can also be e9 xx xx xx xx (x86: JMP [rel32]). These old floppies were only ever created on 16-bit machines, so I think we can conditionalize on eb xx 90. I will fix and resend. The first three bytes are on all the images from 1985 I have are: eb 1c 90. Here's the full boot sector. Perhaps we can also conditionalize on the Not system boot floppy string? Probably not, we want to support mounting boot floppies as well. 000: eb1c 9000 010: fa33 ...3 020: c08e d0bc 0006 fb0e e846 00b4 06b0 00b7 .F.. 030: 07b9 ba4f 18cd 10b4 02ba b700 .O.. 040: cd10 beb8 102e 8a04 0ac0 74f9 56b4 0ebb ..t.V... 050: 0700 cd10 5e46 ebed 074e 6f74 2073 7973 ^F...Not sys 060: 7465 6d20 626f 6f74 2066 6c6f 7070 792e tem boot floppy. 070: 0058 5bba 8b10 8bca 2bd0 d1fa d1fa d1fa .X[.+... 080: d1fa 2bda 5351 cb00 ..+.SQ.. The rest (0x090-0x1ff) is zeroes. And here's the disassembly of the address signified by JMP +0x1c (0x1e): 0x001e fa cli 0x001f 33c0xor %ax,%ax 0x0021 8ed0mov %ax,%ss 0x0023 bc0006 mov $0x600,%sp 0x0026 fb sti 0x0027 0e push %cs 0x0028 e84600 call func_0071 Not sure how common that is among FAT images; mkfs.fat does not appear to generate valid code, other than eb 3c 90 at the beginning of the sector. Thanks, Conrad -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2] fs: FAT: Add support for DOS 1.x formatted volumes
When possible, infer DOS 2.x BIOS Parameter Block from block device geometry (for floppies and floppy images). Update in-memory only. We only perform this update when the entire BPB region is zeroed, like produced by DOS 1.x-era FORMAT (and other OEM variations on DOS). Fixes kernel.org bug #42617. BPB default 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 Signed-off-by: Conrad Meyer cse@gmail.com --- Diff from v3.14-rc8. Changes since v1: * Check for FAT bootstrap prefix (EB xx 90) to help avoid conflicting with other filesystems * Move default from a switch to a static table Thanks! --- fs/fat/inode.c | 93 ++ 1 file changed, 93 insertions(+) diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 854b578..c31fbdc 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -35,9 +35,47 @@ #define CONFIG_FAT_DEFAULT_IOCHARSET #endif +#define KB_IN_SECTORS 2 + 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, +}, +{ 0 } }; static int fat_add_cluster(struct inode *inode) { @@ -1246,6 +1284,58 @@ static unsigned long calc_fat_clusters(struct super_block *sb) } /* + * If this FAT filesystem is archaic (lacking a BIOS Parameter Block, ca. DOS + * 1.x), fix it up in-place by creating a DOS 2.x BIOS Parameter Block from + * defaults for the media size. + */ +static void fat_update_archaic_boot_sector(struct super_block *sb, + struct fat_boot_sector *b) +{ + struct fat_floppy_defaults *di; + sector_t bd_sects; + + /* 16-bit DOS 1.x reliably wrote bootstrap short-jmp code */ + if (b-ignored[0] != 0xeb || b-ignored[2] != 0x90) + return; + + /* +* If any value in this region is non-zero, don't assume it is archaic +* DOS. +*/ + if (get_unaligned_le16(b-sector_size) != 0 || b-sec_per_clus != 0 || + b-reserved != 0 || b-fats != 0 || + get_unaligned_le16(b-dir_entries) != 0 || + get_unaligned_le16(b-sectors) != 0 || b-media != 0 || + b-fat_length != 0 || b-secs_track != 0 || b-heads != 0 || + b-secs_track != 0 || b-heads != 0) + return; + + bd_sects = part_nr_sects_read(sb-s_bdev-bd_part); + for (di = floppy_defaults; di-nr_sectors; di++) { + if (di-nr_sectors == bd_sects) + break; + } + if (di-nr_sectors == 0) { + fat_msg(sb, KERN_WARNING, + DOS volume lacks BPB and isn't a recognized floppy size (%ld sectors), + (long)bd_sects); + return; + } + + fat_msg(sb, KERN_INFO, + Volume lacks BPB but looks like archaic DOS; assuming default BPB values); + + b-sec_per_clus = di-sec_per_clus; + put_unaligned_le16(di-dir_entries, b-dir_entries); + b-media = di-media; + b-fat_length = cpu_to_le16(di-fat_length); + put_unaligned_le16(SECTOR_SIZE, b-sector_size); + b-reserved = cpu_to_le16(1); + b-fats = 2; + put_unaligned_le16(bd_sects, b-sectors); +} + +/* * Read the super block of an MS-DOS FS. */ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, @@ -1297,6 +1387,8 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, } b = (struct fat_boot_sector *) bh-b_data; + fat_update_archaic_boot_sector(sb, b); + if (!b-reserved) { if (!silent) fat_msg(sb, KERN_ERR, bogus number of reserved sectors); @@ -1364,6 +1456,7 @@ 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; + fat_update_archaic_boot_sector(sb, b
[PATCH] fs: FAT: Add support for DOS 1.x formatted volumes
When possible, infer DOS 2.x BIOS Parameter Block from block device geometry (for floppies and floppy images). Update in-memory only. We only perform this update when the entire BPB region is zeroed, like produced by DOS 1.x-era FORMAT (and other OEM variations on DOS). Fixes kernel.org bug #42617. BPB default 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 Signed-off-by: Conrad Meyer --- Diff is from Linus' v3.14-rc8. I am a kernel newbie, apologies in advance for newbie mistakes. Let me know what is wrong and I will fix it and learn. Thanks! --- fs/fat/inode.c | 62 ++ 1 file changed, 62 insertions(+) diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 854b578..f3686d6 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -35,6 +35,8 @@ #define CONFIG_FAT_DEFAULT_IOCHARSET "" #endif +#define KB_IN_SECTORS 2 + static int fat_default_codepage = CONFIG_FAT_DEFAULT_CODEPAGE; static char fat_default_iocharset[] = CONFIG_FAT_DEFAULT_IOCHARSET; @@ -1246,6 +1248,63 @@ static unsigned long calc_fat_clusters(struct super_block *sb) } /* + * If this FAT filesystem is archaic (lacking a BIOS Parameter Block, ca. DOS + * 1.x), fix it up in-place by creating a DOS 2.x BIOS Parameter Block from + * defaults for the media size. + */ +static void fat_update_archaic_boot_sector(struct super_block *sb, + struct fat_boot_sector *b) +{ + sector_t bd_sects; + + if (get_unaligned_le16(>sector_size) != 0 || b->sec_per_clus != 0 || + b->reserved != 0 || b->fats != 0 || + get_unaligned_le16(>dir_entries) != 0 || + get_unaligned_le16(>sectors) != 0 || b->media != 0 || + b->fat_length != 0 || b->secs_track != 0 || b->heads != 0 || + b->secs_track != 0 || b->heads != 0) + return; + + bd_sects = part_nr_sects_read(sb->s_bdev->bd_part); + switch (bd_sects) { + case 160 * KB_IN_SECTORS: + b->sec_per_clus = 1; + put_unaligned_le16(64, >dir_entries); + b->media = 0xFE; + b->fat_length = cpu_to_le16(1); + break; + case 180 * KB_IN_SECTORS: + b->sec_per_clus = 1; + put_unaligned_le16(64, >dir_entries); + b->media = 0xFC; + b->fat_length = cpu_to_le16(2); + break; + case 320 * KB_IN_SECTORS: + b->sec_per_clus = 2; + put_unaligned_le16(112, >dir_entries); + b->media = 0xFF; + b->fat_length = cpu_to_le16(1); + break; + case 360 * KB_IN_SECTORS: + b->sec_per_clus = 2; + put_unaligned_le16(112, >dir_entries); + b->media = 0xFD; + b->fat_length = cpu_to_le16(2); + break; + default: + fat_msg(sb, KERN_WARNING, + "DOS volume lacks BPB and isn't a recognized floppy size (%ld sectors)", + (long)bd_sects); + return; + } + + put_unaligned_le16(SECTOR_SIZE, >sector_size); + b->reserved = cpu_to_le16(1); + b->fats = 2; + put_unaligned_le16(bd_sects, >sectors); +} + +/* * Read the super block of an MS-DOS FS. */ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, @@ -1297,6 +1356,8 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, } b = (struct fat_boot_sector *) bh->b_data; + fat_update_archaic_boot_sector(sb, b); + if (!b->reserved) { if (!silent) fat_msg(sb, KERN_ERR, "bogus number of reserved sectors"); @@ -1364,6 +1425,7 @@ 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; + fat_update_archaic_boot_sector(sb, b); } mutex_init(>s_lock); -- 1.9.0 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] fs: FAT: Add support for DOS 1.x formatted volumes
When possible, infer DOS 2.x BIOS Parameter Block from block device geometry (for floppies and floppy images). Update in-memory only. We only perform this update when the entire BPB region is zeroed, like produced by DOS 1.x-era FORMAT (and other OEM variations on DOS). Fixes kernel.org bug #42617. BPB default 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 Signed-off-by: Conrad Meyer cse@gmail.com --- Diff is from Linus' v3.14-rc8. I am a kernel newbie, apologies in advance for newbie mistakes. Let me know what is wrong and I will fix it and learn. Thanks! --- fs/fat/inode.c | 62 ++ 1 file changed, 62 insertions(+) diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 854b578..f3686d6 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -35,6 +35,8 @@ #define CONFIG_FAT_DEFAULT_IOCHARSET #endif +#define KB_IN_SECTORS 2 + static int fat_default_codepage = CONFIG_FAT_DEFAULT_CODEPAGE; static char fat_default_iocharset[] = CONFIG_FAT_DEFAULT_IOCHARSET; @@ -1246,6 +1248,63 @@ static unsigned long calc_fat_clusters(struct super_block *sb) } /* + * If this FAT filesystem is archaic (lacking a BIOS Parameter Block, ca. DOS + * 1.x), fix it up in-place by creating a DOS 2.x BIOS Parameter Block from + * defaults for the media size. + */ +static void fat_update_archaic_boot_sector(struct super_block *sb, + struct fat_boot_sector *b) +{ + sector_t bd_sects; + + if (get_unaligned_le16(b-sector_size) != 0 || b-sec_per_clus != 0 || + b-reserved != 0 || b-fats != 0 || + get_unaligned_le16(b-dir_entries) != 0 || + get_unaligned_le16(b-sectors) != 0 || b-media != 0 || + b-fat_length != 0 || b-secs_track != 0 || b-heads != 0 || + b-secs_track != 0 || b-heads != 0) + return; + + bd_sects = part_nr_sects_read(sb-s_bdev-bd_part); + switch (bd_sects) { + case 160 * KB_IN_SECTORS: + b-sec_per_clus = 1; + put_unaligned_le16(64, b-dir_entries); + b-media = 0xFE; + b-fat_length = cpu_to_le16(1); + break; + case 180 * KB_IN_SECTORS: + b-sec_per_clus = 1; + put_unaligned_le16(64, b-dir_entries); + b-media = 0xFC; + b-fat_length = cpu_to_le16(2); + break; + case 320 * KB_IN_SECTORS: + b-sec_per_clus = 2; + put_unaligned_le16(112, b-dir_entries); + b-media = 0xFF; + b-fat_length = cpu_to_le16(1); + break; + case 360 * KB_IN_SECTORS: + b-sec_per_clus = 2; + put_unaligned_le16(112, b-dir_entries); + b-media = 0xFD; + b-fat_length = cpu_to_le16(2); + break; + default: + fat_msg(sb, KERN_WARNING, + DOS volume lacks BPB and isn't a recognized floppy size (%ld sectors), + (long)bd_sects); + return; + } + + put_unaligned_le16(SECTOR_SIZE, b-sector_size); + b-reserved = cpu_to_le16(1); + b-fats = 2; + put_unaligned_le16(bd_sects, b-sectors); +} + +/* * Read the super block of an MS-DOS FS. */ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, @@ -1297,6 +1356,8 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, } b = (struct fat_boot_sector *) bh-b_data; + fat_update_archaic_boot_sector(sb, b); + if (!b-reserved) { if (!silent) fat_msg(sb, KERN_ERR, bogus number of reserved sectors); @@ -1364,6 +1425,7 @@ 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; + fat_update_archaic_boot_sector(sb, b); } mutex_init(sbi-s_lock); -- 1.9.0 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] Staging: vt6655: Fix sparse-indicated type mismatch to kmalloc
Signed-off-by: Conrad Meyer --- Patch is against next-20140320. Fixes a minor sparse warning in the staging driver vt6655. p->length is u16; implicit cast to size_t is fine. No reason to cast GFP_KERNEL... --- drivers/staging/vt6655/wpactl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/vt6655/wpactl.c b/drivers/staging/vt6655/wpactl.c index d17224f..c27ed5d 100644 --- a/drivers/staging/vt6655/wpactl.c +++ b/drivers/staging/vt6655/wpactl.c @@ -855,11 +855,11 @@ int wpa_ioctl(PSDevice pDevice, struct iw_point *p) if (p->length < sizeof(struct viawget_wpa_param) || p->length > VIAWGET_WPA_MAX_BUF_SIZE || !p->pointer) return -EINVAL; - param = kmalloc((int)p->length, (int)GFP_KERNEL); + param = kmalloc(p->length, GFP_KERNEL); if (param == NULL) return -ENOMEM; if (copy_from_user(param, p->pointer, p->length)) { ret = -EFAULT; -- 1.8.5.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] Staging: vt6655: Fix sparse-indicated type mismatch to kmalloc
Signed-off-by: Conrad Meyer cse@gmail.com --- Patch is against next-20140320. Fixes a minor sparse warning in the staging driver vt6655. p-length is u16; implicit cast to size_t is fine. No reason to cast GFP_KERNEL... --- drivers/staging/vt6655/wpactl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/vt6655/wpactl.c b/drivers/staging/vt6655/wpactl.c index d17224f..c27ed5d 100644 --- a/drivers/staging/vt6655/wpactl.c +++ b/drivers/staging/vt6655/wpactl.c @@ -855,11 +855,11 @@ int wpa_ioctl(PSDevice pDevice, struct iw_point *p) if (p-length sizeof(struct viawget_wpa_param) || p-length VIAWGET_WPA_MAX_BUF_SIZE || !p-pointer) return -EINVAL; - param = kmalloc((int)p-length, (int)GFP_KERNEL); + param = kmalloc(p-length, GFP_KERNEL); if (param == NULL) return -ENOMEM; if (copy_from_user(param, p-pointer, p-length)) { ret = -EFAULT; -- 1.8.5.3 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] Staging: comedi: fixup: dev_warn() with correct dev
Replace hw_dev with class_dev in new dev_warn()s. Sending this as a patch on top of the one already applied, since GregKH already took that one. If this is the wrong way to fix it, please let me know how I should proceed, I'm new. Thanks! Signed-off-by: Conrad Meyer --- .../comedi/drivers/addi-data/hwdrv_apci1500.c | 104 ++--- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c index cdc6d3d..2f71dd0 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c @@ -253,7 +253,7 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev, if (data[0] == 2) { i_MaxChannel = 6; } else { - dev_warn(dev->hw_dev, + dev_warn(dev->class_dev, "The specified port event does not exist\n"); return -EINVAL; } @@ -270,7 +270,7 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev, data[1] = APCI1500_OR_PRIORITY; break; default: - dev_warn(dev->hw_dev, + dev_warn(dev->class_dev, "The specified interrupt logic does not exist\n"); return -EINVAL; } @@ -315,7 +315,7 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev, case 5: break; default: - dev_warn(dev->hw_dev, + dev_warn(dev->class_dev, "The option indicated in the event mask does not exist\n"); return -EINVAL; } @@ -326,7 +326,7 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev, if (data[1] != APCI1500_AND && data[1] != APCI1500_OR && data[1] != APCI1500_OR_PRIORITY) { - dev_warn(dev->hw_dev, + dev_warn(dev->class_dev, "The choice for interrupt logic does not exist\n"); return -EINVAL; } @@ -336,7 +336,7 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev, if (data[1] == APCI1500_OR_PRIORITY && i_PatternTransition != 0) { - dev_warn(dev->hw_dev, + dev_warn(dev->class_dev, "Transition error on an OR PRIORITY logic\n"); return -EINVAL; } @@ -354,7 +354,7 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev, } if (i_PatternTransitionCount > 1) { - dev_warn(dev->hw_dev, + dev_warn(dev->class_dev, "Transition error on an AND logic\n"); return -EINVAL; } @@ -434,7 +434,7 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev, /* Test the event logic */ if (data[1] != APCI1500_OR) { - dev_warn(dev->hw_dev, + dev_warn(dev->class_dev, "The choice for interrupt logic does not exist\n"); return -EINVAL; } @@ -568,7 +568,7 @@ static int i_APCI1500_StartStopInputEvent(struct comedi_device *dev, if (data[1] == 1) { /* Test if event initialised */ if (i_Event1Status != 1) { - dev_warn(dev->hw_dev, + dev_warn(dev->class_dev, "Event 1 not initialised\n"); return -EINVAL; } @@ -609,7 +609,7 @@ static int i_APCI1500_StartStopInputEvent(struct comedi_device *dev, } else if (data[1] == 2) { if (i_Event2Status != 1) { - dev_warn(dev->hw_dev, + dev_warn(dev->class_dev, "Event 2 not initialised\n"); return -EINVAL; } @@ -642,7 +642,7 @@ static int i_APCI1500_StartStopInputEvent(struct comedi_device *dev, APCI1500_Z8536_CONTROL_REGISTER); i_Event2InterruptSt
[PATCH] Staging: comedi: fixup: dev_warn() with correct dev
Replace hw_dev with class_dev in new dev_warn()s. Sending this as a patch on top of the one already applied, since GregKH already took that one. If this is the wrong way to fix it, please let me know how I should proceed, I'm new. Thanks! Signed-off-by: Conrad Meyer cse@gmail.com --- .../comedi/drivers/addi-data/hwdrv_apci1500.c | 104 ++--- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c index cdc6d3d..2f71dd0 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c @@ -253,7 +253,7 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev, if (data[0] == 2) { i_MaxChannel = 6; } else { - dev_warn(dev-hw_dev, + dev_warn(dev-class_dev, The specified port event does not exist\n); return -EINVAL; } @@ -270,7 +270,7 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev, data[1] = APCI1500_OR_PRIORITY; break; default: - dev_warn(dev-hw_dev, + dev_warn(dev-class_dev, The specified interrupt logic does not exist\n); return -EINVAL; } @@ -315,7 +315,7 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev, case 5: break; default: - dev_warn(dev-hw_dev, + dev_warn(dev-class_dev, The option indicated in the event mask does not exist\n); return -EINVAL; } @@ -326,7 +326,7 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev, if (data[1] != APCI1500_AND data[1] != APCI1500_OR data[1] != APCI1500_OR_PRIORITY) { - dev_warn(dev-hw_dev, + dev_warn(dev-class_dev, The choice for interrupt logic does not exist\n); return -EINVAL; } @@ -336,7 +336,7 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev, if (data[1] == APCI1500_OR_PRIORITY i_PatternTransition != 0) { - dev_warn(dev-hw_dev, + dev_warn(dev-class_dev, Transition error on an OR PRIORITY logic\n); return -EINVAL; } @@ -354,7 +354,7 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev, } if (i_PatternTransitionCount 1) { - dev_warn(dev-hw_dev, + dev_warn(dev-class_dev, Transition error on an AND logic\n); return -EINVAL; } @@ -434,7 +434,7 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev, /* Test the event logic */ if (data[1] != APCI1500_OR) { - dev_warn(dev-hw_dev, + dev_warn(dev-class_dev, The choice for interrupt logic does not exist\n); return -EINVAL; } @@ -568,7 +568,7 @@ static int i_APCI1500_StartStopInputEvent(struct comedi_device *dev, if (data[1] == 1) { /* Test if event initialised */ if (i_Event1Status != 1) { - dev_warn(dev-hw_dev, + dev_warn(dev-class_dev, Event 1 not initialised\n); return -EINVAL; } @@ -609,7 +609,7 @@ static int i_APCI1500_StartStopInputEvent(struct comedi_device *dev, } else if (data[1] == 2) { if (i_Event2Status != 1) { - dev_warn(dev-hw_dev, + dev_warn(dev-class_dev, Event 2 not initialised\n); return -EINVAL; } @@ -642,7 +642,7 @@ static int i_APCI1500_StartStopInputEvent(struct comedi_device *dev, APCI1500_Z8536_CONTROL_REGISTER); i_Event2InterruptStatus = 1; } else { - dev_warn(dev-hw_dev, + dev_warn(dev-class_dev, The port parameter is in error\n
[PATCH 2/2] Staging: comedi: Validate early to flatten code
Take advantage of -EINVAL returns to flatten code structure and hopefully reduce the number of 80+ character lines. Signed-off-by: Conrad Meyer --- .../comedi/drivers/addi-data/hwdrv_apci1500.c | 621 ++--- 1 file changed, 303 insertions(+), 318 deletions(-) diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c index e43db39..cdc6d3d 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c @@ -307,439 +307,424 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev, i_PatternTransition | (1 << (i_MaxChannel - i_Count)); break; case 4: i_PatternTransition = i_PatternTransition | (1 << (i_MaxChannel - i_Count)); break; case 5: break; default: dev_warn(dev->hw_dev, "The option indicated in the event mask does not exist\n"); return -EINVAL; } } if (data[0] == 1) { /* Test the interrupt logic */ - if (data[1] == APCI1500_AND || - data[1] == APCI1500_OR || - data[1] == APCI1500_OR_PRIORITY) { - /* Tests if a transition was declared */ - /* for a OR PRIORITY logic*/ - - if (data[1] == APCI1500_OR_PRIORITY - && i_PatternTransition != 0) { - dev_warn(dev->hw_dev, - "Transition error on an OR PRIORITY logic\n"); - return -EINVAL; - } + if (data[1] != APCI1500_AND && data[1] != APCI1500_OR && + data[1] != APCI1500_OR_PRIORITY) { + dev_warn(dev->hw_dev, + "The choice for interrupt logic does not exist\n"); + return -EINVAL; + } - /* Tests if more than one transition */ - /* was declared for an AND logic */ + /* Tests if a transition was declared */ + /* for a OR PRIORITY logic*/ - if (data[1] == APCI1500_AND) { - for (i_Count = 0; i_Count < 8; i_Count++) { - i_PatternTransitionCount = - i_PatternTransitionCount + - ((i_PatternTransition >> - i_Count) & 0x1); + if (data[1] == APCI1500_OR_PRIORITY + && i_PatternTransition != 0) { + dev_warn(dev->hw_dev, + "Transition error on an OR PRIORITY logic\n"); + return -EINVAL; + } - } + /* Tests if more than one transition */ + /* was declared for an AND logic */ - if (i_PatternTransitionCount > 1) { - dev_warn(dev->hw_dev, - "Transition error on an AND logic\n"); - return -EINVAL; - } - } + if (data[1] == APCI1500_AND) { + for (i_Count = 0; i_Count < 8; i_Count++) { + i_PatternTransitionCount = + i_PatternTransitionCount + + ((i_PatternTransition >> + i_Count) & 0x1); - /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Disable Port A */ - outb(0xF0, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the polarity register of port 1*/ - outb(APCI1500_RW_PORT_A_PATTERN_POLARITY, -
[PATCH 2/2] Staging: comedi: Validate early to flatten code
Take advantage of -EINVAL returns to flatten code structure and hopefully reduce the number of 80+ character lines. Signed-off-by: Conrad Meyer cse@gmail.com --- .../comedi/drivers/addi-data/hwdrv_apci1500.c | 621 ++--- 1 file changed, 303 insertions(+), 318 deletions(-) diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c index e43db39..cdc6d3d 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c @@ -307,439 +307,424 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev, i_PatternTransition | (1 (i_MaxChannel - i_Count)); break; case 4: i_PatternTransition = i_PatternTransition | (1 (i_MaxChannel - i_Count)); break; case 5: break; default: dev_warn(dev-hw_dev, The option indicated in the event mask does not exist\n); return -EINVAL; } } if (data[0] == 1) { /* Test the interrupt logic */ - if (data[1] == APCI1500_AND || - data[1] == APCI1500_OR || - data[1] == APCI1500_OR_PRIORITY) { - /* Tests if a transition was declared */ - /* for a OR PRIORITY logic*/ - - if (data[1] == APCI1500_OR_PRIORITY -i_PatternTransition != 0) { - dev_warn(dev-hw_dev, - Transition error on an OR PRIORITY logic\n); - return -EINVAL; - } + if (data[1] != APCI1500_AND data[1] != APCI1500_OR + data[1] != APCI1500_OR_PRIORITY) { + dev_warn(dev-hw_dev, + The choice for interrupt logic does not exist\n); + return -EINVAL; + } - /* Tests if more than one transition */ - /* was declared for an AND logic */ + /* Tests if a transition was declared */ + /* for a OR PRIORITY logic*/ - if (data[1] == APCI1500_AND) { - for (i_Count = 0; i_Count 8; i_Count++) { - i_PatternTransitionCount = - i_PatternTransitionCount + - ((i_PatternTransition - i_Count) 0x1); + if (data[1] == APCI1500_OR_PRIORITY +i_PatternTransition != 0) { + dev_warn(dev-hw_dev, + Transition error on an OR PRIORITY logic\n); + return -EINVAL; + } - } + /* Tests if more than one transition */ + /* was declared for an AND logic */ - if (i_PatternTransitionCount 1) { - dev_warn(dev-hw_dev, - Transition error on an AND logic\n); - return -EINVAL; - } - } + if (data[1] == APCI1500_AND) { + for (i_Count = 0; i_Count 8; i_Count++) { + i_PatternTransitionCount = + i_PatternTransitionCount + + ((i_PatternTransition + i_Count) 0x1); - /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, - devpriv-iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Disable Port A */ - outb(0xF0, - devpriv-iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the polarity register of port 1*/ - outb(APCI1500_RW_PORT_A_PATTERN_POLARITY, - devpriv-iobase + - APCI1500_Z8536_CONTROL_REGISTER); - outb(i_PatternPolarity, - devpriv-iobase
[PATCH 3/3] Staging: comedi: do not initialize statics to 0 (apci1500)
Minor style cleanup per checkpatch.pl. Signed-off-by: Conrad Meyer --- .../comedi/drivers/addi-data/hwdrv_apci1500.c | 22 +++--- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c index 4f5ce6a..1f7adc5 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c @@ -124,50 +124,50 @@ enum { APCI1500_RW_PORT_A_SPECIFICATION, APCI1500_RW_PORT_A_HANDSHAKE_SPECIFICATION, APCI1500_RW_PORT_A_DATA_PCITCH_POLARITY, APCI1500_RW_PORT_A_DATA_DIRECTION, APCI1500_RW_PORT_A_SPECIAL_IO_CONTROL, APCI1500_RW_PORT_A_PATTERN_POLARITY, APCI1500_RW_PORT_A_PATTERN_TRANSITION, APCI1500_RW_PORT_A_PATTERN_MASK, APCI1500_RW_PORT_B_SPECIFICATION, APCI1500_RW_PORT_B_HANDSHAKE_SPECIFICATION, APCI1500_RW_PORT_B_DATA_PCITCH_POLARITY, APCI1500_RW_PORT_B_DATA_DIRECTION, APCI1500_RW_PORT_B_SPECIAL_IO_CONTROL, APCI1500_RW_PORT_B_PATTERN_POLARITY, APCI1500_RW_PORT_B_PATTERN_TRANSITION, APCI1500_RW_PORT_B_PATTERN_MASK }; -static int i_TimerCounter1Init = 0; -static int i_TimerCounter2Init = 0; -static int i_WatchdogCounter3Init = 0; -static int i_Event1Status = 0, i_Event2Status = 0; -static int i_TimerCounterWatchdogInterrupt = 0; -static int i_Logic = 0, i_CounterLogic = 0; -static int i_InterruptMask = 0; -static int i_InputChannel = 0; -static int i_TimerCounter1Enabled = 0, i_TimerCounter2Enabled = 0, - i_WatchdogCounter3Enabled = 0; +static int i_TimerCounter1Init; +static int i_TimerCounter2Init; +static int i_WatchdogCounter3Init; +static int i_Event1Status, i_Event2Status; +static int i_TimerCounterWatchdogInterrupt; +static int i_Logic, i_CounterLogic; +static int i_InterruptMask; +static int i_InputChannel; +static int i_TimerCounter1Enabled, i_TimerCounter2Enabled, + i_WatchdogCounter3Enabled; /* ++ | Function Name : int i_APCI1500_ConfigDigitalInputEvent | |(struct comedi_device *dev,struct comedi_subdevice *s, | | struct comedi_insn *insn,unsigned int *data) | ++ | Task : An event can be generated for each port. | | The first event is related to the first 8 channels | | (port 1) and the second to the following 6 channels| | (port 2). An interrupt is generated when one or both | | events have occurred | ++ | Input Parameters : struct comedi_device *dev : Driver handle | | unsigned int *data : Data Pointer contains | | configuration parameters as below | || |data[0]:Number of the input port on | | which the event will take place| | (1 or 2) @@ -960,41 +960,41 @@ static int i_acpi1500_config_output(struct comedi_device *dev, ++ | Task : Writes port value To the selected port| ++ | Input Parameters : struct comedi_device *dev : Driver handle | | unsigned int ui_NoOfChannels: No Of Channels To Write | | unsigned int *data : Data Pointer to read status | ++ | Output Parameters : -- | ++ | Return Value : TRUE : No error occur | | : FALSE : Error occur. Return the error | | | ++ */ static int i_APCI1500_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn
[PATCH 1/3] Staging: comedi: Fix some raw printks with dev_warn()
Brought to you with the help of sed and manual clean-up after. $ sed -i -e 's|printk("\\n|dev_warn(dev->hw_dev,\n\t"|' \ addi-data/hwdrv_apci1500.c Since all of these printk()s were for invalid API inputs and most of them returned -EINVAL, I fixed the rest of them to return -EINVAL as well. Signed-off-by: Conrad Meyer --- .../comedi/drivers/addi-data/hwdrv_apci1500.c | 166 + 1 file changed, 107 insertions(+), 59 deletions(-) diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c index 2628ac4..0ccf784 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c @@ -242,56 +242,58 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev, int i; /*/ /* Selects the master interrupt control register */ /*/ outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); /**/ /* Disables the main interrupt on the board */ /**/ outb(0x00, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); if (data[0] == 1) { i_MaxChannel = 8; } /* if (data[0] == 1) */ else { if (data[0] == 2) { i_MaxChannel = 6; } /* if(data[0]==2) */ else { - printk("\nThe specified port event does not exist\n"); + dev_warn(dev->hw_dev, + "The specified port event does not exist\n"); return -EINVAL; } /* else if(data[0]==2) */ } /* else if (data[0] == 1) */ switch (data[1]) { case 0: data[1] = APCI1500_AND; break; case 1: data[1] = APCI1500_OR; break; case 2: data[1] = APCI1500_OR_PRIORITY; break; default: - printk("\nThe specified interrupt logic does not exist\n"); + dev_warn(dev->hw_dev, + "The specified interrupt logic does not exist\n"); return -EINVAL; } /* switch(data[1]); */ i_Logic = data[1]; for (i_Count = i_MaxChannel, i = 0; i_Count > 0; i_Count--, i++) { i_EventMask = data[2 + i]; switch (i_EventMask) { case 0: i_PatternMask = i_PatternMask | (1 << (i_MaxChannel - i_Count)); break; case 1: i_PatternMask = i_PatternMask | (1 << (i_MaxChannel - i_Count)); i_PatternPolarity = i_PatternPolarity | (1 << (i_MaxChannel - i_Count)); break; case 2: i_PatternMask = @@ -301,86 +303,83 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev, i_Count)); break; case 3: i_PatternMask = i_PatternMask | (1 << (i_MaxChannel - i_Count)); i_PatternPolarity = i_PatternPolarity | (1 << (i_MaxChannel - i_Count)); i_PatternTransition = i_PatternTransition | (1 << (i_MaxChannel - i_Count)); break; case 4: i_PatternTransition = i_PatternTransition | (1 << (i_MaxChannel - i_Count)); break; case 5: break; default: - printk("\nThe option indicated in the event mask does not exist\n"); + dev_warn(dev->hw_dev, + "The option indicated in the event mask does not exist\n"); return -EINVAL; } /* switch(i_EventMask) */ } /* for (i_Count = i_MaxChannel; i_Count >0;i_C
Updated: [PATCH] Staging: comedi: Fix 80-char line limit style issue in addi_apci_1500.c
Rename some very long functions in addi-data/hwdrv_apci1500.c. Signed-off-by: Conrad Meyer --- .../staging/comedi/drivers/addi-data/hwdrv_apci1500.c | 18 -- drivers/staging/comedi/drivers/addi_apci_1500.c| 4 ++-- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c index 0549105..2628ac4 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c @@ -1035,70 +1035,69 @@ static int i_APCI1500_Initialisation(struct comedi_device *dev, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); /* Deletes all interrupts */ outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); return insn->n; } static int apci1500_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { struct addi_private *devpriv = dev->private; data[1] = inw(devpriv->i_IobaseAddon + APCI1500_DIGITAL_IP); return insn->n; } /* ++ -| Function Name : int i_APCI1500_ConfigDigitalOutputErrorInterrupt +| Function Name : int i_apci1500_config_output | (struct comedi_device *dev,struct comedi_subdevice *s struct comedi_insn | *insn,unsigned int *data) | | | ++ | Task : Configures the digital output memory and the digital | output error interrupt | ++ | Input Parameters : struct comedi_device *dev : Driver handle | | unsigned int *data : Data Pointer contains | | configuration parameters as below | | struct comedi_subdevice *s, :pointer to subdevice structure | struct comedi_insn *insn :pointer to insn structure | |data[0] :1:Memory on | | 0:Memory off | | data[1] :1 Enable the voltage error interrupt | :0 Disable the voltage error interrupt | | | ++ | Output Parameters : -- | ++ | Return Value : TRUE : No error occur | | : FALSE : Error occur. Return the error | | | ++ */ -static int i_APCI1500_ConfigDigitalOutputErrorInterrupt(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) +static int i_acpi1500_config_output(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_insn *insn, + unsigned int *data) { struct addi_private *devpriv = dev->private; devpriv->b_OutputMemoryStatus = data[0]; return insn->n; } /* ++ | Function Name : int i_APCI1500_WriteDigitalOutput | |(struct comedi_device *dev,struct comedi_subdevice *s, | | struct comedi_insn *insn,unsigned int *data) | ++ | Task : Writes port
[PATCH] Staging: comedi: Fix 80-char line limit style issue in addi_apci_1500.c
Fix minor checkpatch.pl style issues (80-char line limits) in addi_apci_1500.c. Signed-off-by: Conrad Meyer --- drivers/staging/comedi/drivers/addi_apci_1500.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/staging/comedi/drivers/addi_apci_1500.c b/drivers/staging/comedi/drivers/addi_apci_1500.c index 74f7ace..f23ca3d 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1500.c +++ b/drivers/staging/comedi/drivers/addi_apci_1500.c @@ -26,11 +26,13 @@ static const struct addi_board apci1500_boardtypes[] = { .di_read= i_APCI1500_Initialisation, .di_write = i_APCI1500_StartStopInputEvent, .di_bits= apci1500_di_insn_bits, - .do_config = i_APCI1500_ConfigDigitalOutputErrorInterrupt, + .do_config = + i_APCI1500_ConfigDigitalOutputErrorInterrupt, .do_write = i_APCI1500_WriteDigitalOutput, .do_bits= i_APCI1500_ConfigureInterrupt, .timer_config = i_APCI1500_ConfigCounterTimerWatchdog, - .timer_write= i_APCI1500_StartStopTriggerTimerCounterWatchdog, + .timer_write= + i_APCI1500_StartStopTriggerTimerCounterWatchdog, .timer_read = i_APCI1500_ReadInterruptMask, .timer_bits = i_APCI1500_ReadCounterTimerWatchdog, }, -- 1.8.5.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] Staging: comedi: Fix 80-char line limit style issue in addi_apci_1500.c
Fix minor checkpatch.pl style issues (80-char line limits) in addi_apci_1500.c. Signed-off-by: Conrad Meyer cse@gmail.com --- drivers/staging/comedi/drivers/addi_apci_1500.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/staging/comedi/drivers/addi_apci_1500.c b/drivers/staging/comedi/drivers/addi_apci_1500.c index 74f7ace..f23ca3d 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1500.c +++ b/drivers/staging/comedi/drivers/addi_apci_1500.c @@ -26,11 +26,13 @@ static const struct addi_board apci1500_boardtypes[] = { .di_read= i_APCI1500_Initialisation, .di_write = i_APCI1500_StartStopInputEvent, .di_bits= apci1500_di_insn_bits, - .do_config = i_APCI1500_ConfigDigitalOutputErrorInterrupt, + .do_config = + i_APCI1500_ConfigDigitalOutputErrorInterrupt, .do_write = i_APCI1500_WriteDigitalOutput, .do_bits= i_APCI1500_ConfigureInterrupt, .timer_config = i_APCI1500_ConfigCounterTimerWatchdog, - .timer_write= i_APCI1500_StartStopTriggerTimerCounterWatchdog, + .timer_write= + i_APCI1500_StartStopTriggerTimerCounterWatchdog, .timer_read = i_APCI1500_ReadInterruptMask, .timer_bits = i_APCI1500_ReadCounterTimerWatchdog, }, -- 1.8.5.3 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Updated: [PATCH] Staging: comedi: Fix 80-char line limit style issue in addi_apci_1500.c
Rename some very long functions in addi-data/hwdrv_apci1500.c. Signed-off-by: Conrad Meyer cse@gmail.com --- .../staging/comedi/drivers/addi-data/hwdrv_apci1500.c | 18 -- drivers/staging/comedi/drivers/addi_apci_1500.c| 4 ++-- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c index 0549105..2628ac4 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c @@ -1035,70 +1035,69 @@ static int i_APCI1500_Initialisation(struct comedi_device *dev, devpriv-iobase + APCI1500_Z8536_CONTROL_REGISTER); /* Deletes all interrupts */ outb(0, devpriv-iobase + APCI1500_Z8536_CONTROL_REGISTER); return insn-n; } static int apci1500_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { struct addi_private *devpriv = dev-private; data[1] = inw(devpriv-i_IobaseAddon + APCI1500_DIGITAL_IP); return insn-n; } /* ++ -| Function Name : int i_APCI1500_ConfigDigitalOutputErrorInterrupt +| Function Name : int i_apci1500_config_output | (struct comedi_device *dev,struct comedi_subdevice *s struct comedi_insn | *insn,unsigned int *data) | | | ++ | Task : Configures the digital output memory and the digital | output error interrupt | ++ | Input Parameters : struct comedi_device *dev : Driver handle | | unsigned int *data : Data Pointer contains | | configuration parameters as below | | struct comedi_subdevice *s, :pointer to subdevice structure | struct comedi_insn *insn :pointer to insn structure | |data[0] :1:Memory on | | 0:Memory off | | data[1] :1 Enable the voltage error interrupt | :0 Disable the voltage error interrupt | | | ++ | Output Parameters : -- | ++ | Return Value : TRUE : No error occur | | : FALSE : Error occur. Return the error | | | ++ */ -static int i_APCI1500_ConfigDigitalOutputErrorInterrupt(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) +static int i_acpi1500_config_output(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_insn *insn, + unsigned int *data) { struct addi_private *devpriv = dev-private; devpriv-b_OutputMemoryStatus = data[0]; return insn-n; } /* ++ | Function Name : int i_APCI1500_WriteDigitalOutput | |(struct comedi_device *dev,struct comedi_subdevice *s, | | struct comedi_insn *insn,unsigned int *data) | ++ | Task : Writes port value To the selected port
[PATCH 3/3] Staging: comedi: do not initialize statics to 0 (apci1500)
Minor style cleanup per checkpatch.pl. Signed-off-by: Conrad Meyer cse@gmail.com --- .../comedi/drivers/addi-data/hwdrv_apci1500.c | 22 +++--- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c index 4f5ce6a..1f7adc5 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c @@ -124,50 +124,50 @@ enum { APCI1500_RW_PORT_A_SPECIFICATION, APCI1500_RW_PORT_A_HANDSHAKE_SPECIFICATION, APCI1500_RW_PORT_A_DATA_PCITCH_POLARITY, APCI1500_RW_PORT_A_DATA_DIRECTION, APCI1500_RW_PORT_A_SPECIAL_IO_CONTROL, APCI1500_RW_PORT_A_PATTERN_POLARITY, APCI1500_RW_PORT_A_PATTERN_TRANSITION, APCI1500_RW_PORT_A_PATTERN_MASK, APCI1500_RW_PORT_B_SPECIFICATION, APCI1500_RW_PORT_B_HANDSHAKE_SPECIFICATION, APCI1500_RW_PORT_B_DATA_PCITCH_POLARITY, APCI1500_RW_PORT_B_DATA_DIRECTION, APCI1500_RW_PORT_B_SPECIAL_IO_CONTROL, APCI1500_RW_PORT_B_PATTERN_POLARITY, APCI1500_RW_PORT_B_PATTERN_TRANSITION, APCI1500_RW_PORT_B_PATTERN_MASK }; -static int i_TimerCounter1Init = 0; -static int i_TimerCounter2Init = 0; -static int i_WatchdogCounter3Init = 0; -static int i_Event1Status = 0, i_Event2Status = 0; -static int i_TimerCounterWatchdogInterrupt = 0; -static int i_Logic = 0, i_CounterLogic = 0; -static int i_InterruptMask = 0; -static int i_InputChannel = 0; -static int i_TimerCounter1Enabled = 0, i_TimerCounter2Enabled = 0, - i_WatchdogCounter3Enabled = 0; +static int i_TimerCounter1Init; +static int i_TimerCounter2Init; +static int i_WatchdogCounter3Init; +static int i_Event1Status, i_Event2Status; +static int i_TimerCounterWatchdogInterrupt; +static int i_Logic, i_CounterLogic; +static int i_InterruptMask; +static int i_InputChannel; +static int i_TimerCounter1Enabled, i_TimerCounter2Enabled, + i_WatchdogCounter3Enabled; /* ++ | Function Name : int i_APCI1500_ConfigDigitalInputEvent | |(struct comedi_device *dev,struct comedi_subdevice *s, | | struct comedi_insn *insn,unsigned int *data) | ++ | Task : An event can be generated for each port. | | The first event is related to the first 8 channels | | (port 1) and the second to the following 6 channels| | (port 2). An interrupt is generated when one or both | | events have occurred | ++ | Input Parameters : struct comedi_device *dev : Driver handle | | unsigned int *data : Data Pointer contains | | configuration parameters as below | || |data[0]:Number of the input port on | | which the event will take place| | (1 or 2) @@ -960,41 +960,41 @@ static int i_acpi1500_config_output(struct comedi_device *dev, ++ | Task : Writes port value To the selected port| ++ | Input Parameters : struct comedi_device *dev : Driver handle | | unsigned int ui_NoOfChannels: No Of Channels To Write | | unsigned int *data : Data Pointer to read status | ++ | Output Parameters : -- | ++ | Return Value : TRUE : No error occur | | : FALSE : Error occur. Return the error | | | ++ */ static int i_APCI1500_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn
[PATCH 1/3] Staging: comedi: Fix some raw printks with dev_warn()
Brought to you with the help of sed and manual clean-up after. $ sed -i -e 's|printk(\\n|dev_warn(dev-hw_dev,\n\t|' \ addi-data/hwdrv_apci1500.c Since all of these printk()s were for invalid API inputs and most of them returned -EINVAL, I fixed the rest of them to return -EINVAL as well. Signed-off-by: Conrad Meyer cse@gmail.com --- .../comedi/drivers/addi-data/hwdrv_apci1500.c | 166 + 1 file changed, 107 insertions(+), 59 deletions(-) diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c index 2628ac4..0ccf784 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c @@ -242,56 +242,58 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev, int i; /*/ /* Selects the master interrupt control register */ /*/ outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL, devpriv-iobase + APCI1500_Z8536_CONTROL_REGISTER); /**/ /* Disables the main interrupt on the board */ /**/ outb(0x00, devpriv-iobase + APCI1500_Z8536_CONTROL_REGISTER); if (data[0] == 1) { i_MaxChannel = 8; } /* if (data[0] == 1) */ else { if (data[0] == 2) { i_MaxChannel = 6; } /* if(data[0]==2) */ else { - printk(\nThe specified port event does not exist\n); + dev_warn(dev-hw_dev, + The specified port event does not exist\n); return -EINVAL; } /* else if(data[0]==2) */ } /* else if (data[0] == 1) */ switch (data[1]) { case 0: data[1] = APCI1500_AND; break; case 1: data[1] = APCI1500_OR; break; case 2: data[1] = APCI1500_OR_PRIORITY; break; default: - printk(\nThe specified interrupt logic does not exist\n); + dev_warn(dev-hw_dev, + The specified interrupt logic does not exist\n); return -EINVAL; } /* switch(data[1]); */ i_Logic = data[1]; for (i_Count = i_MaxChannel, i = 0; i_Count 0; i_Count--, i++) { i_EventMask = data[2 + i]; switch (i_EventMask) { case 0: i_PatternMask = i_PatternMask | (1 (i_MaxChannel - i_Count)); break; case 1: i_PatternMask = i_PatternMask | (1 (i_MaxChannel - i_Count)); i_PatternPolarity = i_PatternPolarity | (1 (i_MaxChannel - i_Count)); break; case 2: i_PatternMask = @@ -301,86 +303,83 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev, i_Count)); break; case 3: i_PatternMask = i_PatternMask | (1 (i_MaxChannel - i_Count)); i_PatternPolarity = i_PatternPolarity | (1 (i_MaxChannel - i_Count)); i_PatternTransition = i_PatternTransition | (1 (i_MaxChannel - i_Count)); break; case 4: i_PatternTransition = i_PatternTransition | (1 (i_MaxChannel - i_Count)); break; case 5: break; default: - printk(\nThe option indicated in the event mask does not exist\n); + dev_warn(dev-hw_dev, + The option indicated in the event mask does not exist\n); return -EINVAL; } /* switch(i_EventMask) */ } /* for (i_Count = i_MaxChannel; i_Count 0;i_Count --) */ if (data[0] == 1) { // /* Test the interrupt logic