Esempio n. 1
0
struct super_block *sysv_read_super(struct super_block *sb,void *data,
				     int silent)
{
	struct buffer_head *bh;
	const char *found;
	kdev_t dev = sb->s_dev;
	struct inode *root_inode;
	unsigned long blocknr;
	
	if (1024 != sizeof (struct xenix_super_block))
		panic("Xenix FS: bad super-block size");
	if ((512 != sizeof (struct sysv4_super_block))
            || (512 != sizeof (struct sysv2_super_block)))
		panic("SystemV FS: bad super-block size");
	if (500 != sizeof (struct coh_super_block))
		panic("Coherent FS: bad super-block size");
	if (64 != sizeof (struct sysv_inode))
		panic("sysv fs: bad i-node size");
	MOD_INC_USE_COUNT;
	lock_super(sb);
	set_blocksize(dev,BLOCK_SIZE);
	sb->sv_block_base = 0;

	/* Try to read Xenix superblock */
	if ((bh = bread(dev, 1, BLOCK_SIZE)) != NULL) {
		if ((found = detect_xenix(sb,bh)) != NULL)
			goto ok;
		brelse(bh);
	}
	if ((bh = bread(dev, 0, BLOCK_SIZE)) != NULL) {
		/* Try to recognize SystemV superblock */
		if ((found = detect_sysv4(sb,bh)) != NULL)
			goto ok;
		if ((found = detect_sysv2(sb,bh)) != NULL)
			goto ok;
		/* Try to recognize Coherent superblock */
		if ((found = detect_coherent(sb,bh)) != NULL)
			goto ok;
		brelse(bh);
	}
	/* Try to recognize SystemV superblock */
	/* Offset by 1 track, i.e. most probably 9, 15, or 18 kilobytes. */
	/* 2kB blocks with offset of 9 and 15 kilobytes are not supported. */
	/* Maybe we should also check the device geometry ? */
	{	static int offsets[] = { 9, 15, 18, };
		int i;
		for (i = 0; i < sizeof(offsets)/sizeof(offsets[0]); i++)
			if ((bh = bread(dev, offsets[i], BLOCK_SIZE)) != NULL) {
				/* Try to recognize SystemV superblock */
				if ((found = detect_sysv4(sb,bh)) != NULL) {
					if (sb->sv_block_size>BLOCK_SIZE && (offsets[i] % 2))
						goto bad_shift;
					sb->sv_block_base = (offsets[i] << sb->sv_block_size_dec_bits) >> sb->sv_block_size_inc_bits;
					goto ok;
				}
				if ((found = detect_sysv2(sb,bh)) != NULL) {
					if (sb->sv_block_size>BLOCK_SIZE && (offsets[i] % 2))
						goto bad_shift;
					sb->sv_block_base = (offsets[i] << sb->sv_block_size_dec_bits) >> sb->sv_block_size_inc_bits;
					goto ok;
				}
				brelse(bh);
			}
	}
	bad_shift:
	sb->s_dev = 0;
	unlock_super(sb);
	if (!silent)
		printk("VFS: unable to read Xenix/SystemV/Coherent superblock on device "
		       "%s\n", kdevname(dev));
	failed:
	MOD_DEC_USE_COUNT;
	return NULL;

	ok:
	if (sb->sv_block_size >= BLOCK_SIZE) {
		if (sb->sv_block_size != BLOCK_SIZE) {
			brelse(bh);
			set_blocksize(dev, sb->sv_block_size);
			blocknr = (bh->b_blocknr << sb->sv_block_size_dec_bits) >> sb->sv_block_size_inc_bits;
			if ((bh = bread(dev, blocknr, sb->sv_block_size)) == NULL)
				goto bad_superblock;
		}
		switch (sb->sv_type) {
			case FSTYPE_XENIX:
				if (!detected_xenix(sb,bh,bh))
					goto bad_superblock;
				break;
			case FSTYPE_SYSV4:
				if (!detected_sysv4(sb,bh))
					goto bad_superblock;
				break;
			case FSTYPE_SYSV2:
				if (!detected_sysv2(sb,bh))
					goto bad_superblock;
				break;
			default: goto bad_superblock;
		goto superblock_ok;
		bad_superblock:
			brelse(bh);
			sb->s_dev = 0;
			unlock_super(sb);
			printk("SysV FS: cannot read superblock in %d byte mode\n", sb->sv_block_size);
			goto failed;
		superblock_ok:
		}
	} else {
Esempio n. 2
0
struct super_block *sysv_read_super(struct super_block *sb,void *data,
                                    int silent)
{
    struct buffer_head *bh;
    const char *found;
    int dev = sb->s_dev;

    if (1024 != sizeof (struct xenix_super_block))
        panic("Xenix FS: bad super-block size");
    if ((512 != sizeof (struct sysv4_super_block))
            || (512 != sizeof (struct sysv2_super_block)))
        panic("SystemV FS: bad super-block size");
    if (500 != sizeof (struct coh_super_block))
        panic("Coherent FS: bad super-block size");
    if (64 != sizeof (struct sysv_inode))
        panic("sysv fs: bad i-node size");
    lock_super(sb);
    sb->s_blocksize = BLOCK_SIZE; /* anything else not supported by the block device drivers */
    sb->s_blocksize_bits = BLOCK_SIZE_BITS;

    /* Try to read Xenix superblock */
    if ((bh = bread(dev, 1, BLOCK_SIZE)) != NULL) {
        if ((found = detect_xenix(sb,bh)) != NULL)
            goto ok;
        brelse(bh);
    }
    if ((bh = bread(dev, 0, BLOCK_SIZE)) != NULL) {
        /* Try to recognize SystemV superblock */
        if ((found = detect_sysv4(sb,bh)) != NULL)
            goto ok;
        if ((found = detect_sysv2(sb,bh)) != NULL)
            goto ok;
        /* Try to recognize Coherent superblock */
        if ((found = detect_coherent(sb,bh)) != NULL)
            goto ok;
        brelse(bh);
    }
    /* Try to recognize SystemV2 superblock */
    /* Offset by 1 track, i.e. most probably 9, 15, or 18 kilobytes. */
    {   static int offsets[] = { 9, 15, 18, };
        int i;
        for (i = 0; i < sizeof(offsets)/sizeof(offsets[0]); i++)
            if ((bh = bread(dev, offsets[i], BLOCK_SIZE)) != NULL) {
                /* Try to recognize SystemV superblock */
                if ((found = detect_sysv4(sb,bh)) != NULL) {
                    sb->sv_block_base = offsets[i];
                    goto ok;
                }
                if ((found = detect_sysv2(sb,bh)) != NULL) {
                    sb->sv_block_base = offsets[i];
                    goto ok;
                }
                brelse(bh);
            }
    }
    sb->s_dev=0;
    unlock_super(sb);
    if (!silent)
        printk("VFS: unable to read Xenix/SystemV/Coherent superblock on device %d/%d\n",MAJOR(dev),MINOR(dev));
    return NULL;

ok:
    sb->sv_ninodes = (sb->sv_firstdatazone - sb->sv_firstinodezone) << sb->sv_inodes_per_block_bits;
    if (!silent)
        printk("VFS: Found a %s FS (block size = %d) on device %d/%d\n",found,sb->sv_block_size,MAJOR(dev),MINOR(dev));
    sb->s_magic = SYSV_MAGIC_BASE + sb->sv_type;
    /* set up enough so that it can read an inode */
    sb->s_dev = dev;
    sb->s_op = &sysv_sops;
    sb->s_mounted = iget(sb,SYSV_ROOT_INO);
    unlock_super(sb);
    if (!sb->s_mounted) {
        brelse(bh);
        sb->s_dev = 0;
        printk("SysV FS: get root inode failed\n");
        return NULL;
    }
    sb->s_dirt = 1; /* brelse(bh); occurs when the disk is unmounted. */
    return sb;
}