]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
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 | ||
82094b55 AF |
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 | |
2cb7cef9 BS |
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) | |
82094b55 | 222 | @@ -1655,85 +1512,199 @@ static noinline int udf_process_sequence |
2cb7cef9 BS |
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 | } | |
2cb7cef9 BS |
477 | |
478 | static void udf_open_lvid(struct super_block *sb) | |
82094b55 | 479 | @@ -1908,18 +1879,6 @@ static int udf_fill_super(struct super_b |
2cb7cef9 BS |
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; | |
82094b55 | 498 | @@ -1928,7 +1887,7 @@ static int udf_fill_super(struct super_b |
2cb7cef9 BS |
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 | } | |
82094b55 AF |
507 | --- a/fs/udf/udf_sb.h |
508 | +++ b/fs/udf/udf_sb.h | |
2cb7cef9 BS |
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; |