1 From: Jan Kara <jack@suse.cz>
2 Subject: [PATCH] udf: Try anchor in block 256 first
6 Anchor block can be located at several places on the medium. Two of the
7 locations are relative to media end which is problematic to detect. Also
8 some drives report some block as last but are not able to read it or any
9 block nearby before it. So let's first try block 256 and if it is all fine,
10 don't look at other possible locations of anchor blocks to avoid IO errors.
11 This change required a larger reorganization of code but the new code is
12 hopefully more readable and definitely shorter.
14 Signed-off-by: Jan Kara <jack@suse.cz>
17 fs/udf/super.c | 395 +++++++++++++++++++++++++-------------------------------
19 2 files changed, 178 insertions(+), 219 deletions(-)
23 @@ -83,10 +83,7 @@ static int udf_fill_super(struct super_b
24 static void udf_put_super(struct super_block *);
25 static void udf_write_super(struct super_block *);
26 static int udf_remount_fs(struct super_block *, int *, char *);
27 -static int udf_check_valid(struct super_block *, int, int);
28 -static int udf_vrs(struct super_block *sb, int silent);
29 static void udf_load_logicalvolint(struct super_block *, kernel_extent_ad);
30 -static void udf_find_anchor(struct super_block *);
31 static int udf_find_fileset(struct super_block *, kernel_lb_addr *,
33 static void udf_load_fileset(struct super_block *, struct buffer_head *,
34 @@ -286,14 +283,8 @@ static int udf_show_options(struct seq_f
35 seq_printf(seq, ",session=%u", sbi->s_session);
36 if (UDF_QUERY_FLAG(sb, UDF_FLAG_LASTBLOCK_SET))
37 seq_printf(seq, ",lastblock=%u", sbi->s_last_block);
39 - * s_anchor[2] could be zeroed out in case there is no anchor
40 - * in the specified block, but then the "anchor=N" option
41 - * originally given by the user wasn't effective, so it's OK
42 - * if we don't show it.
44 - if (sbi->s_anchor[2] != 0)
45 - seq_printf(seq, ",anchor=%u", sbi->s_anchor[2]);
46 + if (sbi->s_anchor != 0)
47 + seq_printf(seq, ",anchor=%u", sbi->s_anchor);
49 * volume, partition, fileset and rootdir seem to be ignored
51 @@ -585,22 +576,19 @@ static int udf_remount_fs(struct super_b
55 -static int udf_vrs(struct super_block *sb, int silent)
56 +/* Check Volume Structure Descriptors (ECMA 167 2/9.1) */
57 +/* We also check any "CD-ROM Volume Descriptor Set" (ECMA 167 2/8.3.1) */
58 +static loff_t udf_check_vsd(struct super_block *sb)
60 struct volStructDesc *vsd = NULL;
61 loff_t sector = 32768;
63 struct buffer_head *bh = NULL;
67 struct udf_sb_info *sbi;
69 - /* Block size must be a multiple of 512 */
70 - if (sb->s_blocksize & 511)
74 if (sb->s_blocksize < sizeof(struct volStructDesc))
75 sectorsize = sizeof(struct volStructDesc);
77 @@ -627,7 +615,6 @@ static int udf_vrs(struct super_block *s
79 } else if (!strncmp(vsd->stdIdent, VSD_STD_ID_CD001,
82 switch (vsd->structType) {
84 udf_debug("ISO9660 Boot Record found\n");
85 @@ -679,136 +666,6 @@ static int udf_vrs(struct super_block *s
90 - * Check whether there is an anchor block in the given block
92 -static int udf_check_anchor_block(struct super_block *sb, sector_t block)
94 - struct buffer_head *bh;
97 - if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV) &&
98 - udf_fixed_to_variable(block) >=
99 - sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits)
102 - bh = udf_read_tagged(sb, block, block, &ident);
107 - return ident == TAG_IDENT_AVDP;
110 -/* Search for an anchor volume descriptor pointer */
111 -static sector_t udf_scan_anchors(struct super_block *sb, sector_t lastblock)
115 - struct udf_sb_info *sbi = UDF_SB(sb);
117 - last[0] = lastblock;
118 - last[1] = last[0] - 1;
119 - last[2] = last[0] + 1;
120 - last[3] = last[0] - 2;
121 - last[4] = last[0] - 150;
122 - last[5] = last[0] - 152;
124 - /* according to spec, anchor is in either:
128 - * however, if the disc isn't closed, it could be 512 */
130 - for (i = 0; i < ARRAY_SIZE(last); i++) {
133 - if (last[i] >= sb->s_bdev->bd_inode->i_size >>
134 - sb->s_blocksize_bits)
137 - if (udf_check_anchor_block(sb, last[i])) {
138 - sbi->s_anchor[0] = last[i];
139 - sbi->s_anchor[1] = last[i] - 256;
146 - if (udf_check_anchor_block(sb, last[i] - 256)) {
147 - sbi->s_anchor[1] = last[i] - 256;
152 - if (udf_check_anchor_block(sb, sbi->s_session + 256)) {
153 - sbi->s_anchor[0] = sbi->s_session + 256;
156 - if (udf_check_anchor_block(sb, sbi->s_session + 512)) {
157 - sbi->s_anchor[0] = sbi->s_session + 512;
164 - * Find an anchor volume descriptor. The function expects sbi->s_lastblock to
165 - * be the last block on the media.
167 - * Return 1 if not found, 0 if ok
170 -static void udf_find_anchor(struct super_block *sb)
172 - sector_t lastblock;
173 - struct buffer_head *bh = NULL;
176 - struct udf_sb_info *sbi = UDF_SB(sb);
178 - lastblock = udf_scan_anchors(sb, sbi->s_last_block);
182 - /* No anchor found? Try VARCONV conversion of block numbers */
183 - UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
184 - /* Firstly, we try to not convert number of the last block */
185 - lastblock = udf_scan_anchors(sb,
186 - udf_variable_to_fixed(sbi->s_last_block));
190 - /* Secondly, we try with converted number of the last block */
191 - lastblock = udf_scan_anchors(sb, sbi->s_last_block);
193 - /* VARCONV didn't help. Clear it. */
194 - UDF_CLEAR_FLAG(sb, UDF_FLAG_VARCONV);
199 - * Check located anchors and the anchor block supplied via
202 - for (i = 0; i < ARRAY_SIZE(sbi->s_anchor); i++) {
203 - if (!sbi->s_anchor[i])
205 - bh = udf_read_tagged(sb, sbi->s_anchor[i],
206 - sbi->s_anchor[i], &ident);
208 - sbi->s_anchor[i] = 0;
211 - if (ident != TAG_IDENT_AVDP)
212 - sbi->s_anchor[i] = 0;
216 - sbi->s_last_block = lastblock;
219 static int udf_find_fileset(struct super_block *sb,
220 kernel_lb_addr *fileset,
221 kernel_lb_addr *root)
222 @@ -1655,85 +1512,199 @@ static noinline int udf_process_sequence
226 +static int udf_load_sequence(struct super_block *sb, struct buffer_head *bh,
227 + kernel_lb_addr *fileset)
229 + struct anchorVolDescPtr *anchor;
230 + long main_s, main_e, reserve_s, reserve_e;
231 + struct udf_sb_info *sbi;
234 + anchor = (struct anchorVolDescPtr *)bh->b_data;
236 + /* Locate the main sequence */
237 + main_s = le32_to_cpu(anchor->mainVolDescSeqExt.extLocation);
238 + main_e = le32_to_cpu(anchor->mainVolDescSeqExt.extLength);
239 + main_e = main_e >> sb->s_blocksize_bits;
242 + /* Locate the reserve sequence */
243 + reserve_s = le32_to_cpu(anchor->reserveVolDescSeqExt.extLocation);
244 + reserve_e = le32_to_cpu(anchor->reserveVolDescSeqExt.extLength);
245 + reserve_e = reserve_e >> sb->s_blocksize_bits;
246 + reserve_e += reserve_s;
248 + /* Process the main & reserve sequences */
249 + /* responsible for finding the PartitionDesc(s) */
250 + if (!udf_process_sequence(sb, main_s, main_e, fileset))
252 + return !udf_process_sequence(sb, reserve_s, reserve_e, fileset);
256 - * udf_check_valid()
257 + * Check whether there is an anchor block in the given block and
258 + * load Volume Descriptor Sequence if so.
260 -static int udf_check_valid(struct super_block *sb, int novrs, int silent)
261 +static int udf_check_anchor_block(struct super_block *sb, sector_t block,
262 + kernel_lb_addr *fileset)
265 - struct udf_sb_info *sbi = UDF_SB(sb);
266 + struct buffer_head *bh;
271 - udf_debug("Validity check skipped because of novrs option\n");
272 + if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV) &&
273 + udf_fixed_to_variable(block) >=
274 + sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits)
277 + bh = udf_read_tagged(sb, block, block, &ident);
280 + if (ident != TAG_IDENT_AVDP) {
284 - /* Check that it is NSR02 compliant */
285 - /* Process any "CD-ROM Volume Descriptor Set" (ECMA 167 2/8.3.1) */
286 - block = udf_vrs(sb, silent);
288 - udf_debug("Failed to read byte 32768. Assuming open "
289 - "disc. Skipping validity check\n");
290 - if (block && !sbi->s_last_block)
291 - sbi->s_last_block = udf_get_last_block(sb);
293 + ret = udf_load_sequence(sb, bh, fileset);
298 -static int udf_load_sequence(struct super_block *sb, kernel_lb_addr *fileset)
299 +/* Search for an anchor volume descriptor pointer */
300 +static sector_t udf_scan_anchors(struct super_block *sb, sector_t lastblock,
301 + kernel_lb_addr *fileset)
303 - struct anchorVolDescPtr *anchor;
305 - struct buffer_head *bh;
306 - long main_s, main_e, reserve_s, reserve_e;
309 - struct udf_sb_info *sbi;
310 + struct udf_sb_info *sbi = UDF_SB(sb);
311 + int last_count = 0;
316 + /* First try user provided anchor */
317 + if (sbi->s_anchor) {
318 + if (udf_check_anchor_block(sb, sbi->s_anchor, fileset))
322 + * according to spec, anchor is in either:
326 + * however, if the disc isn't closed, it could be 512.
328 + if (udf_check_anchor_block(sb, sbi->s_session + 256, fileset))
331 + * The trouble is which block is the last one. Drives often misreport
332 + * this so we try various possibilities.
334 + last[last_count++] = lastblock;
335 + if (lastblock >= 1)
336 + last[last_count++] = lastblock - 1;
337 + last[last_count++] = lastblock + 1;
338 + if (lastblock >= 2)
339 + last[last_count++] = lastblock - 2;
340 + if (lastblock >= 150)
341 + last[last_count++] = lastblock - 150;
342 + if (lastblock >= 152)
343 + last[last_count++] = lastblock - 152;
345 - for (i = 0; i < ARRAY_SIZE(sbi->s_anchor); i++) {
346 - if (!sbi->s_anchor[i])
347 + for (i = 0; i < last_count; i++) {
348 + if (last[i] >= sb->s_bdev->bd_inode->i_size >>
349 + sb->s_blocksize_bits)
352 - bh = udf_read_tagged(sb, sbi->s_anchor[i], sbi->s_anchor[i],
355 + if (udf_check_anchor_block(sb, last[i], fileset))
359 + if (udf_check_anchor_block(sb, last[i] - 256, fileset))
363 + /* Finally try block 512 in case media is open */
364 + if (udf_check_anchor_block(sb, sbi->s_session + 512, fileset))
369 - anchor = (struct anchorVolDescPtr *)bh->b_data;
371 + * Find an anchor volume descriptor and load Volume Descriptor Sequence from
372 + * area specified by it. The function expects sbi->s_lastblock to be the last
373 + * block on the media.
375 + * Return 1 if ok, 0 if not found.
378 +static int udf_find_anchor(struct super_block *sb,
379 + kernel_lb_addr *fileset)
381 + sector_t lastblock;
382 + struct udf_sb_info *sbi = UDF_SB(sb);
384 - /* Locate the main sequence */
385 - main_s = le32_to_cpu(anchor->mainVolDescSeqExt.extLocation);
386 - main_e = le32_to_cpu(anchor->mainVolDescSeqExt.extLength);
387 - main_e = main_e >> sb->s_blocksize_bits;
390 - /* Locate the reserve sequence */
391 - reserve_s = le32_to_cpu(
392 - anchor->reserveVolDescSeqExt.extLocation);
393 - reserve_e = le32_to_cpu(
394 - anchor->reserveVolDescSeqExt.extLength);
395 - reserve_e = reserve_e >> sb->s_blocksize_bits;
396 - reserve_e += reserve_s;
397 + lastblock = udf_scan_anchors(sb, sbi->s_last_block, fileset);
402 + /* No anchor found? Try VARCONV conversion of block numbers */
403 + UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
404 + /* Firstly, we try to not convert number of the last block */
405 + lastblock = udf_scan_anchors(sb,
406 + udf_variable_to_fixed(sbi->s_last_block),
411 - /* Process the main & reserve sequences */
412 - /* responsible for finding the PartitionDesc(s) */
413 - if (!(udf_process_sequence(sb, main_s, main_e,
415 - udf_process_sequence(sb, reserve_s, reserve_e,
418 + /* Secondly, we try with converted number of the last block */
419 + lastblock = udf_scan_anchors(sb, sbi->s_last_block, fileset);
421 + /* VARCONV didn't help. Clear it. */
422 + UDF_CLEAR_FLAG(sb, UDF_FLAG_VARCONV);
426 + sbi->s_last_block = lastblock;
430 - if (i == ARRAY_SIZE(sbi->s_anchor)) {
431 - udf_debug("No Anchor block found\n");
434 + * Check Volume Structure Descriptor, find Anchor block and load Volume
435 + * Descriptor Sequence
437 +static int udf_load_vrs(struct super_block *sb, struct udf_options *uopt,
438 + int silent, kernel_lb_addr *fileset)
440 + struct udf_sb_info *sbi = UDF_SB(sb);
443 + if (!sb_set_blocksize(sb, uopt->blocksize)) {
445 + printk(KERN_WARNING "UDF-fs: Bad block size\n");
448 + sbi->s_last_block = uopt->lastblock;
449 + if (!uopt->novrs) {
450 + /* Check that it is NSR02 compliant */
451 + nsr_off = udf_check_vsd(sb);
454 + printk(KERN_WARNING "UDF-fs: No VRS found\n");
458 + udf_debug("Failed to read byte 32768. Assuming open "
459 + "disc. Skipping validity check\n");
460 + if (!sbi->s_last_block)
461 + sbi->s_last_block = udf_get_last_block(sb);
463 + udf_debug("Validity check skipped because of novrs option\n");
465 - udf_debug("Using anchor in block %d\n", sbi->s_anchor[i]);
468 + /* Look for anchor block and load Volume Descriptor Sequence */
469 + sbi->s_anchor = uopt->anchor;
470 + if (!udf_find_anchor(sb, fileset)) {
472 + printk(KERN_WARNING "UDF-fs: No anchor found\n");
478 static void udf_open_lvid(struct super_block *sb)
479 @@ -1908,18 +1879,6 @@ static int udf_fill_super(struct super_b
481 udf_debug("Multi-session=%d\n", sbi->s_session);
483 - sbi->s_last_block = uopt.lastblock;
484 - sbi->s_anchor[0] = sbi->s_anchor[1] = 0;
485 - sbi->s_anchor[2] = uopt.anchor;
487 - if (udf_check_valid(sb, uopt.novrs, silent)) {
488 - /* read volume recognition sequences */
489 - printk(KERN_WARNING "UDF-fs: No VRS found\n");
493 - udf_find_anchor(sb);
495 /* Fill in the rest of the superblock */
496 sb->s_op = &udf_sb_ops;
497 sb->s_export_op = &udf_export_ops;
498 @@ -1928,7 +1887,7 @@ static int udf_fill_super(struct super_b
499 sb->s_magic = UDF_SUPER_MAGIC;
500 sb->s_time_gran = 1000;
502 - if (udf_load_sequence(sb, &fileset)) {
503 + if (!udf_load_vrs(sb, &uopt, silent, &fileset)) {
504 printk(KERN_WARNING "UDF-fs: No partition found (1)\n");
507 --- a/fs/udf/udf_sb.h
508 +++ b/fs/udf/udf_sb.h
509 @@ -114,7 +114,7 @@ struct udf_sb_info {
517 struct buffer_head *s_lvid_bh;