aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2009-03-11 10:57:47 -0400
committerJan Kara <jack@suse.cz>2009-04-02 06:29:55 -0400
commit1197e4dfcf4ac17d763a59e5de1d4d4b9781a555 (patch)
tree61a98ed0c7dfeb5a078c60aa0857f16a7e780c3f /fs
parent4136801aec27b56ae4d06b638b4e9956346b08c8 (diff)
udf: use hardware sector size
This patch makes the UDF FS driver use the hardware sector size as the default logical block size, which is required by the UDF specifications. While the previous default of 2048 bytes was correct for optical disks, it was not for hard disks or USB storage devices, and made it impossible to use such a device with the default mount options. (The Linux mkudffs tool uses a default block size of 2048 bytes even on devices with smaller hardware sectors, so this bug is unlikely to be noticed unless UDF-formatted USB storage devices are exchanged with other OSs.) To avoid regressions for people who use loopback optical disk images or who used the (sometimes wrong) defaults of mkudffs, we also try with a block size of 2048 bytes if no anchor was found with the hardware sector size. Signed-off-by: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs')
-rw-r--r--fs/udf/super.c70
-rw-r--r--fs/udf/udf_sb.h1
2 files changed, 50 insertions, 21 deletions
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 36a467ca1622..f8fece43f6c6 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -86,7 +86,6 @@ static int udf_remount_fs(struct super_block *, int *, char *);
86static int udf_check_valid(struct super_block *, int, int); 86static int udf_check_valid(struct super_block *, int, int);
87static int udf_vrs(struct super_block *sb, int silent); 87static int udf_vrs(struct super_block *sb, int silent);
88static void udf_load_logicalvolint(struct super_block *, struct kernel_extent_ad); 88static void udf_load_logicalvolint(struct super_block *, struct kernel_extent_ad);
89static void udf_find_anchor(struct super_block *);
90static int udf_find_fileset(struct super_block *, struct kernel_lb_addr *, 89static int udf_find_fileset(struct super_block *, struct kernel_lb_addr *,
91 struct kernel_lb_addr *); 90 struct kernel_lb_addr *);
92static void udf_load_fileset(struct super_block *, struct buffer_head *, 91static void udf_load_fileset(struct super_block *, struct buffer_head *,
@@ -260,7 +259,7 @@ static int udf_show_options(struct seq_file *seq, struct vfsmount *mnt)
260 259
261 if (!UDF_QUERY_FLAG(sb, UDF_FLAG_STRICT)) 260 if (!UDF_QUERY_FLAG(sb, UDF_FLAG_STRICT))
262 seq_puts(seq, ",nostrict"); 261 seq_puts(seq, ",nostrict");
263 if (sb->s_blocksize != UDF_DEFAULT_BLOCKSIZE) 262 if (UDF_QUERY_FLAG(sb, UDF_FLAG_BLOCKSIZE_SET))
264 seq_printf(seq, ",bs=%lu", sb->s_blocksize); 263 seq_printf(seq, ",bs=%lu", sb->s_blocksize);
265 if (UDF_QUERY_FLAG(sb, UDF_FLAG_UNHIDE)) 264 if (UDF_QUERY_FLAG(sb, UDF_FLAG_UNHIDE))
266 seq_puts(seq, ",unhide"); 265 seq_puts(seq, ",unhide");
@@ -416,7 +415,6 @@ static int udf_parse_options(char *options, struct udf_options *uopt,
416 int option; 415 int option;
417 416
418 uopt->novrs = 0; 417 uopt->novrs = 0;
419 uopt->blocksize = UDF_DEFAULT_BLOCKSIZE;
420 uopt->partition = 0xFFFF; 418 uopt->partition = 0xFFFF;
421 uopt->session = 0xFFFFFFFF; 419 uopt->session = 0xFFFFFFFF;
422 uopt->lastblock = 0; 420 uopt->lastblock = 0;
@@ -444,6 +442,7 @@ static int udf_parse_options(char *options, struct udf_options *uopt,
444 if (match_int(&args[0], &option)) 442 if (match_int(&args[0], &option))
445 return 0; 443 return 0;
446 uopt->blocksize = option; 444 uopt->blocksize = option;
445 uopt->flags |= (1 << UDF_FLAG_BLOCKSIZE_SET);
447 break; 446 break;
448 case Opt_unhide: 447 case Opt_unhide:
449 uopt->flags |= (1 << UDF_FLAG_UNHIDE); 448 uopt->flags |= (1 << UDF_FLAG_UNHIDE);
@@ -789,12 +788,13 @@ static sector_t udf_scan_anchors(struct super_block *sb, sector_t lastblock)
789 * Return 1 if not found, 0 if ok 788 * Return 1 if not found, 0 if ok
790 * 789 *
791 */ 790 */
792static void udf_find_anchor(struct super_block *sb) 791static int udf_find_anchor(struct super_block *sb)
793{ 792{
794 sector_t lastblock; 793 sector_t lastblock;
795 struct buffer_head *bh = NULL; 794 struct buffer_head *bh = NULL;
796 uint16_t ident; 795 uint16_t ident;
797 int i; 796 int i;
797 int anchor_found = 0;
798 struct udf_sb_info *sbi = UDF_SB(sb); 798 struct udf_sb_info *sbi = UDF_SB(sb);
799 799
800 lastblock = udf_scan_anchors(sb, sbi->s_last_block); 800 lastblock = udf_scan_anchors(sb, sbi->s_last_block);
@@ -832,10 +832,13 @@ check_anchor:
832 brelse(bh); 832 brelse(bh);
833 if (ident != TAG_IDENT_AVDP) 833 if (ident != TAG_IDENT_AVDP)
834 sbi->s_anchor[i] = 0; 834 sbi->s_anchor[i] = 0;
835 else
836 anchor_found = 1;
835 } 837 }
836 } 838 }
837 839
838 sbi->s_last_block = lastblock; 840 sbi->s_last_block = lastblock;
841 return anchor_found;
839} 842}
840 843
841static int udf_find_fileset(struct super_block *sb, 844static int udf_find_fileset(struct super_block *sb,
@@ -1721,6 +1724,32 @@ static int udf_check_valid(struct super_block *sb, int novrs, int silent)
1721 return !block; 1724 return !block;
1722} 1725}
1723 1726
1727static int udf_check_volume(struct super_block *sb,
1728 struct udf_options *uopt, int silent)
1729{
1730 struct udf_sb_info *sbi = UDF_SB(sb);
1731
1732 if (!sb_set_blocksize(sb, uopt->blocksize)) {
1733 if (!silent)
1734 printk(KERN_WARNING "UDF-fs: Bad block size\n");
1735 return 0;
1736 }
1737 sbi->s_last_block = uopt->lastblock;
1738 if (udf_check_valid(sb, uopt->novrs, silent)) {
1739 if (!silent)
1740 printk(KERN_WARNING "UDF-fs: No VRS found\n");
1741 return 0;
1742 }
1743 sbi->s_anchor[0] = sbi->s_anchor[1] = 0;
1744 sbi->s_anchor[2] = uopt->anchor;
1745 if (!udf_find_anchor(sb)) {
1746 if (!silent)
1747 printk(KERN_WARNING "UDF-fs: No anchor found\n");
1748 return 0;
1749 }
1750 return 1;
1751}
1752
1724static int udf_load_sequence(struct super_block *sb, struct kernel_lb_addr *fileset) 1753static int udf_load_sequence(struct super_block *sb, struct kernel_lb_addr *fileset)
1725{ 1754{
1726 struct anchorVolDescPtr *anchor; 1755 struct anchorVolDescPtr *anchor;
@@ -1889,6 +1918,7 @@ static void udf_free_partition(struct udf_part_map *map)
1889static int udf_fill_super(struct super_block *sb, void *options, int silent) 1918static int udf_fill_super(struct super_block *sb, void *options, int silent)
1890{ 1919{
1891 int i; 1920 int i;
1921 int found_anchor;
1892 struct inode *inode = NULL; 1922 struct inode *inode = NULL;
1893 struct udf_options uopt; 1923 struct udf_options uopt;
1894 struct kernel_lb_addr rootdir, fileset; 1924 struct kernel_lb_addr rootdir, fileset;
@@ -1941,13 +1971,6 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
1941 sbi->s_dmode = uopt.dmode; 1971 sbi->s_dmode = uopt.dmode;
1942 sbi->s_nls_map = uopt.nls_map; 1972 sbi->s_nls_map = uopt.nls_map;
1943 1973
1944 /* Set the block size for all transfers */
1945 if (!sb_min_blocksize(sb, uopt.blocksize)) {
1946 udf_debug("Bad block size (%d)\n", uopt.blocksize);
1947 printk(KERN_ERR "udf: bad block size (%d)\n", uopt.blocksize);
1948 goto error_out;
1949 }
1950
1951 if (uopt.session == 0xFFFFFFFF) 1974 if (uopt.session == 0xFFFFFFFF)
1952 sbi->s_session = udf_get_last_session(sb); 1975 sbi->s_session = udf_get_last_session(sb);
1953 else 1976 else
@@ -1955,17 +1978,22 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
1955 1978
1956 udf_debug("Multi-session=%d\n", sbi->s_session); 1979 udf_debug("Multi-session=%d\n", sbi->s_session);
1957 1980
1958 sbi->s_last_block = uopt.lastblock; 1981 if (uopt.flags & (1 << UDF_FLAG_BLOCKSIZE_SET)) {
1959 sbi->s_anchor[0] = sbi->s_anchor[1] = 0; 1982 found_anchor = udf_check_volume(sb, &uopt, silent);
1960 sbi->s_anchor[2] = uopt.anchor; 1983 } else {
1961 1984 uopt.blocksize = bdev_hardsect_size(sb->s_bdev);
1962 if (udf_check_valid(sb, uopt.novrs, silent)) { 1985 found_anchor = udf_check_volume(sb, &uopt, silent);
1963 /* read volume recognition sequences */ 1986 if (!found_anchor && uopt.blocksize != UDF_DEFAULT_BLOCKSIZE) {
1964 printk(KERN_WARNING "UDF-fs: No VRS found\n"); 1987 if (!silent)
1965 goto error_out; 1988 printk(KERN_NOTICE
1989 "UDF-fs: Rescanning with blocksize "
1990 "%d\n", UDF_DEFAULT_BLOCKSIZE);
1991 uopt.blocksize = UDF_DEFAULT_BLOCKSIZE;
1992 found_anchor = udf_check_volume(sb, &uopt, silent);
1993 }
1966 } 1994 }
1967 1995 if (!found_anchor)
1968 udf_find_anchor(sb); 1996 goto error_out;
1969 1997
1970 /* Fill in the rest of the superblock */ 1998 /* Fill in the rest of the superblock */
1971 sb->s_op = &udf_sb_ops; 1999 sb->s_op = &udf_sb_ops;
diff --git a/fs/udf/udf_sb.h b/fs/udf/udf_sb.h
index 158221ecdc42..2dd921928338 100644
--- a/fs/udf/udf_sb.h
+++ b/fs/udf/udf_sb.h
@@ -30,6 +30,7 @@
30#define UDF_FLAG_GID_SET 16 30#define UDF_FLAG_GID_SET 16
31#define UDF_FLAG_SESSION_SET 17 31#define UDF_FLAG_SESSION_SET 17
32#define UDF_FLAG_LASTBLOCK_SET 18 32#define UDF_FLAG_LASTBLOCK_SET 18
33#define UDF_FLAG_BLOCKSIZE_SET 19
33 34
34#define UDF_PART_FLAG_UNALLOC_BITMAP 0x0001 35#define UDF_PART_FLAG_UNALLOC_BITMAP 0x0001
35#define UDF_PART_FLAG_UNALLOC_TABLE 0x0002 36#define UDF_PART_FLAG_UNALLOC_TABLE 0x0002