]> git.ipfire.org Git - ipfire-2.x.git/blob - src/patches/suse-2.6.27.39/patches.fixes/udf-faster_anchor_detection.patch
Add a patch to fix Intel E100 wake-on-lan problems.
[ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.fixes / udf-faster_anchor_detection.patch
1 From: Jan Kara <jack@suse.cz>
2 Subject: [PATCH] udf: Try anchor in block 256 first
3 References: bnc#467174
4 Patch-mainline: 2.6.30
5
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.
13
14 Signed-off-by: Jan Kara <jack@suse.cz>
15
16 ---
17 fs/udf/super.c | 395 +++++++++++++++++++++++++-------------------------------
18 fs/udf/udf_sb.h | 2
19 2 files changed, 178 insertions(+), 219 deletions(-)
20
21 --- a/fs/udf/super.c
22 +++ b/fs/udf/super.c
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 *,
32 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);
38 - /*
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.
43 - */
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);
48 /*
49 * volume, partition, fileset and rootdir seem to be ignored
50 * currently
51 @@ -585,22 +576,19 @@ static int udf_remount_fs(struct super_b
52 return 0;
53 }
54
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)
59 {
60 struct volStructDesc *vsd = NULL;
61 loff_t sector = 32768;
62 int sectorsize;
63 struct buffer_head *bh = NULL;
64 - int iso9660 = 0;
65 int nsr02 = 0;
66 int nsr03 = 0;
67 struct udf_sb_info *sbi;
68
69 - /* Block size must be a multiple of 512 */
70 - if (sb->s_blocksize & 511)
71 - return 0;
72 sbi = UDF_SB(sb);
73 -
74 if (sb->s_blocksize < sizeof(struct volStructDesc))
75 sectorsize = sizeof(struct volStructDesc);
76 else
77 @@ -627,7 +615,6 @@ static int udf_vrs(struct super_block *s
78 break;
79 } else if (!strncmp(vsd->stdIdent, VSD_STD_ID_CD001,
80 VSD_STD_ID_LEN)) {
81 - iso9660 = sector;
82 switch (vsd->structType) {
83 case 0:
84 udf_debug("ISO9660 Boot Record found\n");
85 @@ -679,136 +666,6 @@ static int udf_vrs(struct super_block *s
86 return 0;
87 }
88
89 -/*
90 - * Check whether there is an anchor block in the given block
91 - */
92 -static int udf_check_anchor_block(struct super_block *sb, sector_t block)
93 -{
94 - struct buffer_head *bh;
95 - uint16_t ident;
96 -
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)
100 - return 0;
101 -
102 - bh = udf_read_tagged(sb, block, block, &ident);
103 - if (!bh)
104 - return 0;
105 - brelse(bh);
106 -
107 - return ident == TAG_IDENT_AVDP;
108 -}
109 -
110 -/* Search for an anchor volume descriptor pointer */
111 -static sector_t udf_scan_anchors(struct super_block *sb, sector_t lastblock)
112 -{
113 - sector_t last[6];
114 - int i;
115 - struct udf_sb_info *sbi = UDF_SB(sb);
116 -
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;
123 -
124 - /* according to spec, anchor is in either:
125 - * block 256
126 - * lastblock-256
127 - * lastblock
128 - * however, if the disc isn't closed, it could be 512 */
129 -
130 - for (i = 0; i < ARRAY_SIZE(last); i++) {
131 - if (last[i] < 0)
132 - continue;
133 - if (last[i] >= sb->s_bdev->bd_inode->i_size >>
134 - sb->s_blocksize_bits)
135 - continue;
136 -
137 - if (udf_check_anchor_block(sb, last[i])) {
138 - sbi->s_anchor[0] = last[i];
139 - sbi->s_anchor[1] = last[i] - 256;
140 - return last[i];
141 - }
142 -
143 - if (last[i] < 256)
144 - continue;
145 -
146 - if (udf_check_anchor_block(sb, last[i] - 256)) {
147 - sbi->s_anchor[1] = last[i] - 256;
148 - return last[i];
149 - }
150 - }
151 -
152 - if (udf_check_anchor_block(sb, sbi->s_session + 256)) {
153 - sbi->s_anchor[0] = sbi->s_session + 256;
154 - return last[0];
155 - }
156 - if (udf_check_anchor_block(sb, sbi->s_session + 512)) {
157 - sbi->s_anchor[0] = sbi->s_session + 512;
158 - return last[0];
159 - }
160 - return 0;
161 -}
162 -
163 -/*
164 - * Find an anchor volume descriptor. The function expects sbi->s_lastblock to
165 - * be the last block on the media.
166 - *
167 - * Return 1 if not found, 0 if ok
168 - *
169 - */
170 -static void udf_find_anchor(struct super_block *sb)
171 -{
172 - sector_t lastblock;
173 - struct buffer_head *bh = NULL;
174 - uint16_t ident;
175 - int i;
176 - struct udf_sb_info *sbi = UDF_SB(sb);
177 -
178 - lastblock = udf_scan_anchors(sb, sbi->s_last_block);
179 - if (lastblock)
180 - goto check_anchor;
181 -
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));
187 - if (lastblock)
188 - goto check_anchor;
189 -
190 - /* Secondly, we try with converted number of the last block */
191 - lastblock = udf_scan_anchors(sb, sbi->s_last_block);
192 - if (!lastblock) {
193 - /* VARCONV didn't help. Clear it. */
194 - UDF_CLEAR_FLAG(sb, UDF_FLAG_VARCONV);
195 - }
196 -
197 -check_anchor:
198 - /*
199 - * Check located anchors and the anchor block supplied via
200 - * mount options
201 - */
202 - for (i = 0; i < ARRAY_SIZE(sbi->s_anchor); i++) {
203 - if (!sbi->s_anchor[i])
204 - continue;
205 - bh = udf_read_tagged(sb, sbi->s_anchor[i],
206 - sbi->s_anchor[i], &ident);
207 - if (!bh)
208 - sbi->s_anchor[i] = 0;
209 - else {
210 - brelse(bh);
211 - if (ident != TAG_IDENT_AVDP)
212 - sbi->s_anchor[i] = 0;
213 - }
214 - }
215 -
216 - sbi->s_last_block = lastblock;
217 -}
218 -
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
223 return 0;
224 }
225
226 +static int udf_load_sequence(struct super_block *sb, struct buffer_head *bh,
227 + kernel_lb_addr *fileset)
228 +{
229 + struct anchorVolDescPtr *anchor;
230 + long main_s, main_e, reserve_s, reserve_e;
231 + struct udf_sb_info *sbi;
232 +
233 + sbi = UDF_SB(sb);
234 + anchor = (struct anchorVolDescPtr *)bh->b_data;
235 +
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;
240 + main_e += main_s;
241 +
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;
247 +
248 + /* Process the main & reserve sequences */
249 + /* responsible for finding the PartitionDesc(s) */
250 + if (!udf_process_sequence(sb, main_s, main_e, fileset))
251 + return 1;
252 + return !udf_process_sequence(sb, reserve_s, reserve_e, fileset);
253 +}
254 +
255 /*
256 - * udf_check_valid()
257 + * Check whether there is an anchor block in the given block and
258 + * load Volume Descriptor Sequence if so.
259 */
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)
263 {
264 - long block;
265 - struct udf_sb_info *sbi = UDF_SB(sb);
266 + struct buffer_head *bh;
267 + uint16_t ident;
268 + int ret;
269
270 - if (novrs) {
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)
275 + return 0;
276 +
277 + bh = udf_read_tagged(sb, block, block, &ident);
278 + if (!bh)
279 + return 0;
280 + if (ident != TAG_IDENT_AVDP) {
281 + brelse(bh);
282 return 0;
283 }
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);
287 - if (block == -1)
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);
292 - return !block;
293 + ret = udf_load_sequence(sb, bh, fileset);
294 + brelse(bh);
295 + return ret;
296 }
297
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)
302 {
303 - struct anchorVolDescPtr *anchor;
304 - uint16_t ident;
305 - struct buffer_head *bh;
306 - long main_s, main_e, reserve_s, reserve_e;
307 + sector_t last[6];
308 int i;
309 - struct udf_sb_info *sbi;
310 + struct udf_sb_info *sbi = UDF_SB(sb);
311 + int last_count = 0;
312
313 - if (!sb)
314 - return 1;
315 - sbi = UDF_SB(sb);
316 + /* First try user provided anchor */
317 + if (sbi->s_anchor) {
318 + if (udf_check_anchor_block(sb, sbi->s_anchor, fileset))
319 + return lastblock;
320 + }
321 + /*
322 + * according to spec, anchor is in either:
323 + * block 256
324 + * lastblock-256
325 + * lastblock
326 + * however, if the disc isn't closed, it could be 512.
327 + */
328 + if (udf_check_anchor_block(sb, sbi->s_session + 256, fileset))
329 + return lastblock;
330 + /*
331 + * The trouble is which block is the last one. Drives often misreport
332 + * this so we try various possibilities.
333 + */
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;
344
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)
350 continue;
351 -
352 - bh = udf_read_tagged(sb, sbi->s_anchor[i], sbi->s_anchor[i],
353 - &ident);
354 - if (!bh)
355 + if (udf_check_anchor_block(sb, last[i], fileset))
356 + return last[i];
357 + if (last[i] < 256)
358 continue;
359 + if (udf_check_anchor_block(sb, last[i] - 256, fileset))
360 + return last[i];
361 + }
362 +
363 + /* Finally try block 512 in case media is open */
364 + if (udf_check_anchor_block(sb, sbi->s_session + 512, fileset))
365 + return last[0];
366 + return 0;
367 +}
368
369 - anchor = (struct anchorVolDescPtr *)bh->b_data;
370 +/*
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.
374 + *
375 + * Return 1 if ok, 0 if not found.
376 + *
377 + */
378 +static int udf_find_anchor(struct super_block *sb,
379 + kernel_lb_addr *fileset)
380 +{
381 + sector_t lastblock;
382 + struct udf_sb_info *sbi = UDF_SB(sb);
383
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;
388 - main_e += main_s;
389 -
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);
398 + if (lastblock)
399 + goto out;
400
401 - brelse(bh);
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),
407 + fileset);
408 + if (lastblock)
409 + goto out;
410
411 - /* Process the main & reserve sequences */
412 - /* responsible for finding the PartitionDesc(s) */
413 - if (!(udf_process_sequence(sb, main_s, main_e,
414 - fileset) &&
415 - udf_process_sequence(sb, reserve_s, reserve_e,
416 - fileset)))
417 - break;
418 + /* Secondly, we try with converted number of the last block */
419 + lastblock = udf_scan_anchors(sb, sbi->s_last_block, fileset);
420 + if (!lastblock) {
421 + /* VARCONV didn't help. Clear it. */
422 + UDF_CLEAR_FLAG(sb, UDF_FLAG_VARCONV);
423 + return 0;
424 }
425 +out:
426 + sbi->s_last_block = lastblock;
427 + return 1;
428 +}
429
430 - if (i == ARRAY_SIZE(sbi->s_anchor)) {
431 - udf_debug("No Anchor block found\n");
432 - return 1;
433 +/*
434 + * Check Volume Structure Descriptor, find Anchor block and load Volume
435 + * Descriptor Sequence
436 + */
437 +static int udf_load_vrs(struct super_block *sb, struct udf_options *uopt,
438 + int silent, kernel_lb_addr *fileset)
439 +{
440 + struct udf_sb_info *sbi = UDF_SB(sb);
441 + loff_t nsr_off;
442 +
443 + if (!sb_set_blocksize(sb, uopt->blocksize)) {
444 + if (!silent)
445 + printk(KERN_WARNING "UDF-fs: Bad block size\n");
446 + return 0;
447 + }
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);
452 + if (!nsr_off) {
453 + if (!silent)
454 + printk(KERN_WARNING "UDF-fs: No VRS found\n");
455 + return 0;
456 + }
457 + if (nsr_off == -1)
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);
462 + } else {
463 + udf_debug("Validity check skipped because of novrs option\n");
464 }
465 - udf_debug("Using anchor in block %d\n", sbi->s_anchor[i]);
466
467 - return 0;
468 + /* Look for anchor block and load Volume Descriptor Sequence */
469 + sbi->s_anchor = uopt->anchor;
470 + if (!udf_find_anchor(sb, fileset)) {
471 + if (!silent)
472 + printk(KERN_WARNING "UDF-fs: No anchor found\n");
473 + return 0;
474 + }
475 + return 1;
476 }
477
478 static void udf_open_lvid(struct super_block *sb)
479 @@ -1908,18 +1879,6 @@ static int udf_fill_super(struct super_b
480
481 udf_debug("Multi-session=%d\n", sbi->s_session);
482
483 - sbi->s_last_block = uopt.lastblock;
484 - sbi->s_anchor[0] = sbi->s_anchor[1] = 0;
485 - sbi->s_anchor[2] = uopt.anchor;
486 -
487 - if (udf_check_valid(sb, uopt.novrs, silent)) {
488 - /* read volume recognition sequences */
489 - printk(KERN_WARNING "UDF-fs: No VRS found\n");
490 - goto error_out;
491 - }
492 -
493 - udf_find_anchor(sb);
494 -
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;
501
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");
505 goto error_out;
506 }
507 --- a/fs/udf/udf_sb.h
508 +++ b/fs/udf/udf_sb.h
509 @@ -114,7 +114,7 @@ struct udf_sb_info {
510
511 /* Sector headers */
512 __s32 s_session;
513 - __u32 s_anchor[3];
514 + __u32 s_anchor;
515 __u32 s_last_block;
516
517 struct buffer_head *s_lvid_bh;