aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLubomir Rintel <lkundrak@v3.sk>2010-08-10 21:03:34 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2010-08-11 00:24:18 -0400
commit6d0b5456e14ec19edae7c18de4d355c58b133bd6 (patch)
tree8bcb32b9122bd282844a6650e8e4059d8311ab41
parent496ee9b8f349a8ae2065114c414a47e89bdeb930 (diff)
fs/sysv/super.c: add support for non-PDP11 v7 filesystems
This adds byte order autodetection (of PDP-11 and LE filesystems). No attempt is made to detect big-endian filesystems -- were there any? Tested with PDP-11 v7 filesystems and PC-IX maintenance floppy. [akpm@linux-foundation.org: coding-style fixes] [AV: parser.h inclusion was a rudiment of discarded stuff] Signed-off-by: Lubomir Rintel <lkundrak@v3.sk> Cc: Christoph Hellwig <hch@lst.de> Cc: Al Viro <viro@ZenIV.linux.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/sysv/super.c74
1 files changed, 50 insertions, 24 deletions
diff --git a/fs/sysv/super.c b/fs/sysv/super.c
index 5c0aab0b7e18..a0b0cda6927e 100644
--- a/fs/sysv/super.c
+++ b/fs/sysv/super.c
@@ -434,12 +434,46 @@ Ebadsize:
434 goto failed; 434 goto failed;
435} 435}
436 436
437static int v7_fill_super(struct super_block *sb, void *data, int silent) 437static int v7_sanity_check(struct super_block *sb, struct buffer_head *bh)
438{ 438{
439 struct sysv_sb_info *sbi;
440 struct buffer_head *bh, *bh2 = NULL;
441 struct v7_super_block *v7sb; 439 struct v7_super_block *v7sb;
442 struct sysv_inode *v7i; 440 struct sysv_inode *v7i;
441 struct buffer_head *bh2;
442 struct sysv_sb_info *sbi;
443
444 sbi = sb->s_fs_info;
445
446 /* plausibility check on superblock */
447 v7sb = (struct v7_super_block *) bh->b_data;
448 if (fs16_to_cpu(sbi, v7sb->s_nfree) > V7_NICFREE ||
449 fs16_to_cpu(sbi, v7sb->s_ninode) > V7_NICINOD ||
450 fs32_to_cpu(sbi, v7sb->s_fsize) > V7_MAXSIZE)
451 return 0;
452
453 /* plausibility check on root inode: it is a directory,
454 with a nonzero size that is a multiple of 16 */
455 bh2 = sb_bread(sb, 2);
456 if (bh2 == NULL)
457 return 0;
458
459 v7i = (struct sysv_inode *)(bh2->b_data + 64);
460 if ((fs16_to_cpu(sbi, v7i->i_mode) & ~0777) != S_IFDIR ||
461 (fs32_to_cpu(sbi, v7i->i_size) == 0) ||
462 (fs32_to_cpu(sbi, v7i->i_size) & 017) ||
463 (fs32_to_cpu(sbi, v7i->i_size) > V7_NFILES *
464 sizeof(struct sysv_dir_entry))) {
465 brelse(bh2);
466 return 0;
467 }
468
469 brelse(bh2);
470 return 1;
471}
472
473static int v7_fill_super(struct super_block *sb, void *data, int silent)
474{
475 struct sysv_sb_info *sbi;
476 struct buffer_head *bh;
443 477
444 if (440 != sizeof (struct v7_super_block)) 478 if (440 != sizeof (struct v7_super_block))
445 panic("V7 FS: bad super-block size"); 479 panic("V7 FS: bad super-block size");
@@ -453,7 +487,6 @@ static int v7_fill_super(struct super_block *sb, void *data, int silent)
453 sbi->s_sb = sb; 487 sbi->s_sb = sb;
454 sbi->s_block_base = 0; 488 sbi->s_block_base = 0;
455 sbi->s_type = FSTYPE_V7; 489 sbi->s_type = FSTYPE_V7;
456 sbi->s_bytesex = BYTESEX_PDP;
457 sb->s_fs_info = sbi; 490 sb->s_fs_info = sbi;
458 491
459 sb_set_blocksize(sb, 512); 492 sb_set_blocksize(sb, 512);
@@ -465,34 +498,27 @@ static int v7_fill_super(struct super_block *sb, void *data, int silent)
465 goto failed; 498 goto failed;
466 } 499 }
467 500
468 /* plausibility check on superblock */ 501 /* Try PDP-11 UNIX */
469 v7sb = (struct v7_super_block *) bh->b_data; 502 sbi->s_bytesex = BYTESEX_PDP;
470 if (fs16_to_cpu(sbi, v7sb->s_nfree) > V7_NICFREE || 503 if (v7_sanity_check(sb, bh))
471 fs16_to_cpu(sbi, v7sb->s_ninode) > V7_NICINOD || 504 goto detected;
472 fs32_to_cpu(sbi, v7sb->s_fsize) > V7_MAXSIZE)
473 goto failed;
474 505
475 /* plausibility check on root inode: it is a directory, 506 /* Try PC/IX, v7/x86 */
476 with a nonzero size that is a multiple of 16 */ 507 sbi->s_bytesex = BYTESEX_LE;
477 if ((bh2 = sb_bread(sb, 2)) == NULL) 508 if (v7_sanity_check(sb, bh))
478 goto failed; 509 goto detected;
479 v7i = (struct sysv_inode *)(bh2->b_data + 64);
480 if ((fs16_to_cpu(sbi, v7i->i_mode) & ~0777) != S_IFDIR ||
481 (fs32_to_cpu(sbi, v7i->i_size) == 0) ||
482 (fs32_to_cpu(sbi, v7i->i_size) & 017) ||
483 (fs32_to_cpu(sbi, v7i->i_size) > V7_NFILES *
484 sizeof (struct sysv_dir_entry)))
485 goto failed;
486 brelse(bh2);
487 bh2 = NULL;
488 510
511 goto failed;
512
513detected:
489 sbi->s_bh1 = bh; 514 sbi->s_bh1 = bh;
490 sbi->s_bh2 = bh; 515 sbi->s_bh2 = bh;
491 if (complete_read_super(sb, silent, 1)) 516 if (complete_read_super(sb, silent, 1))
492 return 0; 517 return 0;
493 518
494failed: 519failed:
495 brelse(bh2); 520 printk(KERN_ERR "VFS: could not find a valid V7 on %s.\n",
521 sb->s_id);
496 brelse(bh); 522 brelse(bh);
497 kfree(sbi); 523 kfree(sbi);
498 return -EINVAL; 524 return -EINVAL;