@@ -277,13 +277,80 @@ static const struct super_operations adfs_sops = {
277
277
.show_options = adfs_show_options ,
278
278
};
279
279
280
- static int adfs_fill_super (struct super_block * sb , void * data , int silent )
280
+ static int adfs_probe (struct super_block * sb , unsigned int offset , int silent ,
281
+ int (* validate )(struct super_block * sb ,
282
+ struct buffer_head * bh ,
283
+ struct adfs_discrecord * * bhp ))
281
284
{
285
+ struct adfs_sb_info * asb = ADFS_SB (sb );
282
286
struct adfs_discrecord * dr ;
283
287
struct buffer_head * bh ;
284
- struct object_info root_obj ;
288
+ unsigned int blocksize = BLOCK_SIZE ;
289
+ int ret , try ;
290
+
291
+ for (try = 0 ; try < 2 ; try ++ ) {
292
+ /* try to set the requested block size */
293
+ if (sb -> s_blocksize != blocksize &&
294
+ !sb_set_blocksize (sb , blocksize )) {
295
+ if (!silent )
296
+ adfs_msg (sb , KERN_ERR ,
297
+ "error: unsupported blocksize" );
298
+ return - EINVAL ;
299
+ }
300
+
301
+ /* read the buffer */
302
+ bh = sb_bread (sb , offset >> sb -> s_blocksize_bits );
303
+ if (!bh ) {
304
+ adfs_msg (sb , KERN_ERR ,
305
+ "error: unable to read block %u, try %d" ,
306
+ offset >> sb -> s_blocksize_bits , try );
307
+ return - EIO ;
308
+ }
309
+
310
+ /* validate it */
311
+ ret = validate (sb , bh , & dr );
312
+ if (ret ) {
313
+ brelse (bh );
314
+ return ret ;
315
+ }
316
+
317
+ /* does the block size match the filesystem block size? */
318
+ blocksize = 1 << dr -> log2secsize ;
319
+ if (sb -> s_blocksize == blocksize ) {
320
+ asb -> s_map = adfs_read_map (sb , dr );
321
+ brelse (bh );
322
+ return PTR_ERR_OR_ZERO (asb -> s_map );
323
+ }
324
+
325
+ brelse (bh );
326
+ }
327
+
328
+ return - EIO ;
329
+ }
330
+
331
+ static int adfs_validate_bblk (struct super_block * sb , struct buffer_head * bh ,
332
+ struct adfs_discrecord * * drp )
333
+ {
334
+ struct adfs_discrecord * dr ;
285
335
unsigned char * b_data ;
286
- unsigned int blocksize ;
336
+
337
+ b_data = bh -> b_data + (ADFS_DISCRECORD % sb -> s_blocksize );
338
+ if (adfs_checkbblk (b_data ))
339
+ return - EILSEQ ;
340
+
341
+ /* Do some sanity checks on the ADFS disc record */
342
+ dr = (struct adfs_discrecord * )(b_data + ADFS_DR_OFFSET );
343
+ if (adfs_checkdiscrecord (dr ))
344
+ return - EILSEQ ;
345
+
346
+ * drp = dr ;
347
+ return 0 ;
348
+ }
349
+
350
+ static int adfs_fill_super (struct super_block * sb , void * data , int silent )
351
+ {
352
+ struct adfs_discrecord * dr ;
353
+ struct object_info root_obj ;
287
354
struct adfs_sb_info * asb ;
288
355
struct inode * root ;
289
356
int ret = - EINVAL ;
@@ -308,72 +375,19 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent)
308
375
if (parse_options (sb , asb , data ))
309
376
goto error ;
310
377
311
- sb_set_blocksize (sb , BLOCK_SIZE );
312
- if (!(bh = sb_bread (sb , ADFS_DISCRECORD / BLOCK_SIZE ))) {
313
- adfs_msg (sb , KERN_ERR , "error: unable to read superblock" );
314
- ret = - EIO ;
315
- goto error ;
316
- }
317
-
318
- b_data = bh -> b_data + (ADFS_DISCRECORD % BLOCK_SIZE );
319
-
320
- if (adfs_checkbblk (b_data )) {
321
- ret = - EINVAL ;
322
- goto error_badfs ;
323
- }
324
-
325
- dr = (struct adfs_discrecord * )(b_data + ADFS_DR_OFFSET );
326
-
327
- /*
328
- * Do some sanity checks on the ADFS disc record
329
- */
330
- if (adfs_checkdiscrecord (dr )) {
331
- ret = - EINVAL ;
332
- goto error_badfs ;
333
- }
334
-
335
- blocksize = 1 << dr -> log2secsize ;
336
- brelse (bh );
337
-
338
- if (sb_set_blocksize (sb , blocksize )) {
339
- bh = sb_bread (sb , ADFS_DISCRECORD / sb -> s_blocksize );
340
- if (!bh ) {
341
- adfs_msg (sb , KERN_ERR ,
342
- "error: couldn't read superblock on 2nd try." );
343
- ret = - EIO ;
344
- goto error ;
345
- }
346
- b_data = bh -> b_data + (ADFS_DISCRECORD % sb -> s_blocksize );
347
- if (adfs_checkbblk (b_data )) {
348
- adfs_msg (sb , KERN_ERR ,
349
- "error: disc record mismatch, very weird!" );
350
- ret = - EINVAL ;
351
- goto error_free_bh ;
352
- }
353
- dr = (struct adfs_discrecord * )(b_data + ADFS_DR_OFFSET );
354
- } else {
378
+ /* Try to probe the filesystem boot block */
379
+ ret = adfs_probe (sb , ADFS_DISCRECORD , silent , adfs_validate_bblk );
380
+ if (ret == - EILSEQ ) {
355
381
if (!silent )
356
382
adfs_msg (sb , KERN_ERR ,
357
- "error: unsupported blocksize" );
383
+ "error: can't find an ADFS filesystem on dev %s." ,
384
+ sb -> s_id );
358
385
ret = - EINVAL ;
359
- goto error ;
360
386
}
387
+ if (ret )
388
+ goto error ;
361
389
362
- /*
363
- * blocksize on this device should now be set to the ADFS log2secsize
364
- */
365
-
366
- asb -> s_map = adfs_read_map (sb , dr );
367
- if (IS_ERR (asb -> s_map )) {
368
- ret = PTR_ERR (asb -> s_map );
369
- goto error_free_bh ;
370
- }
371
-
372
- brelse (bh );
373
-
374
- /*
375
- * set up enough so that we can read an inode
376
- */
390
+ /* set up enough so that we can read an inode */
377
391
sb -> s_op = & adfs_sops ;
378
392
379
393
dr = adfs_map_discrecord (asb -> s_map );
@@ -417,13 +431,6 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent)
417
431
}
418
432
return 0 ;
419
433
420
- error_badfs :
421
- if (!silent )
422
- adfs_msg (sb , KERN_ERR ,
423
- "error: can't find an ADFS filesystem on dev %s." ,
424
- sb -> s_id );
425
- error_free_bh :
426
- brelse (bh );
427
434
error :
428
435
sb -> s_fs_info = NULL ;
429
436
kfree (asb );
0 commit comments