[PATCH v8] fs: FAT: Add support for DOS 1.x formatted volumes

2014-04-21 Thread Conrad Meyer
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

2014-04-21 Thread Conrad Meyer
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

2014-04-14 Thread Conrad Meyer
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

2014-04-14 Thread Conrad Meyer
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

2014-04-13 Thread Conrad Meyer
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

2014-04-13 Thread Conrad Meyer
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

2014-04-13 Thread Conrad Meyer
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

2014-04-13 Thread Conrad Meyer
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

2014-04-13 Thread Conrad Meyer
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

2014-04-13 Thread Conrad Meyer
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

2014-04-13 Thread Conrad Meyer
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

2014-04-13 Thread Conrad Meyer
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

2014-03-31 Thread Conrad Meyer
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

2014-03-31 Thread Conrad Meyer
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

2014-03-31 Thread Conrad Meyer
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

2014-03-31 Thread Conrad Meyer
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

2014-03-31 Thread Conrad Meyer
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

2014-03-31 Thread Conrad Meyer
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

2014-03-31 Thread Conrad Meyer
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

2014-03-31 Thread Conrad Meyer
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

2014-03-31 Thread Conrad Meyer
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

2014-03-31 Thread Conrad Meyer
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

2014-03-30 Thread Conrad Meyer
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

2014-03-30 Thread Conrad Meyer
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

2014-03-29 Thread Conrad Meyer
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

2014-03-29 Thread Conrad Meyer
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

2014-03-29 Thread Conrad Meyer
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

2014-03-29 Thread Conrad Meyer
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

2014-03-28 Thread Conrad Meyer
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

2014-03-28 Thread Conrad Meyer
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

2014-03-20 Thread Conrad Meyer
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

2014-03-20 Thread Conrad Meyer
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

2014-03-11 Thread Conrad Meyer
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

2014-03-11 Thread Conrad Meyer
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

2014-03-09 Thread Conrad Meyer
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

2014-03-09 Thread Conrad Meyer
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)

2014-03-08 Thread Conrad Meyer
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()

2014-03-08 Thread Conrad Meyer
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

2014-03-08 Thread Conrad Meyer
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

2014-03-08 Thread Conrad Meyer
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

2014-03-08 Thread Conrad Meyer
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

2014-03-08 Thread Conrad Meyer
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)

2014-03-08 Thread Conrad Meyer
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()

2014-03-08 Thread Conrad Meyer
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