Beispiel #1
0
static int
is_any_reiserfs_magic_string(struct reiserfs_super_block *rs)
{

	return ((is_reiserfs_3_5(rs) || is_reiserfs_3_6(rs) ||
	    is_reiserfs_jr(rs)));
}
Beispiel #2
0
/* return 1 if this is not super block */
static int print_super_block(struct buffer_head *bh)
{
	struct reiserfs_super_block *rs =
	    (struct reiserfs_super_block *)(bh->b_data);
	int skipped, data_blocks;
	char *version;
	char b[BDEVNAME_SIZE];

	if (is_reiserfs_3_5(rs)) {
		version = "3.5";
	} else if (is_reiserfs_3_6(rs)) {
		version = "3.6";
	} else if (is_reiserfs_jr(rs)) {
		version = ((sb_version(rs) == REISERFS_VERSION_2) ?
			   "3.6" : "3.5");
	} else {
		return 1;
	}

	printk("%s\'s super block is in block %llu\n", bdevname(bh->b_bdev, b),
	       (unsigned long long)bh->b_blocknr);
	printk("Reiserfs version %s\n", version);
	printk("Block count %u\n", sb_block_count(rs));
	printk("Blocksize %d\n", sb_blocksize(rs));
	printk("Free blocks %u\n", sb_free_blocks(rs));
	// FIXME: this would be confusing if
	// someone stores reiserfs super block in some data block ;)
//    skipped = (bh->b_blocknr * bh->b_size) / sb_blocksize(rs);
	skipped = bh->b_blocknr;
	data_blocks = sb_block_count(rs) - skipped - 1 - sb_bmap_nr(rs) -
	    (!is_reiserfs_jr(rs) ? sb_jp_journal_size(rs) +
	     1 : sb_reserved_for_journal(rs)) - sb_free_blocks(rs);
	printk
	    ("Busy blocks (skipped %d, bitmaps - %d, journal (or reserved) blocks - %d\n"
	     "1 super block, %d data blocks\n", skipped, sb_bmap_nr(rs),
	     (!is_reiserfs_jr(rs) ? (sb_jp_journal_size(rs) + 1) :
	      sb_reserved_for_journal(rs)), data_blocks);
	printk("Root block %u\n", sb_root_block(rs));
	printk("Journal block (first) %d\n", sb_jp_journal_1st_block(rs));
	printk("Journal dev %d\n", sb_jp_journal_dev(rs));
	printk("Journal orig size %d\n", sb_jp_journal_size(rs));
	printk("FS state %d\n", sb_fs_state(rs));
	printk("Hash function \"%s\"\n",
	       reiserfs_hashname(sb_hash_function_code(rs)));

	printk("Tree height %d\n", sb_tree_height(rs));
	return 0;
}
Beispiel #3
0
/*
 * Read the super block
 */
static int
read_super_block(struct reiserfs_mount *rmp, int offset)
{
	struct buf *bp;
	int error, bits;
	struct reiserfs_super_block *rs;
	struct reiserfs_sb_info *sbi;
	uint16_t fs_blocksize;

	if (offset == REISERFS_OLD_DISK_OFFSET) {
		reiserfs_log(LOG_DEBUG,
		    "reiserfs/super: read old format super block\n");
	} else {
		reiserfs_log(LOG_DEBUG,
		    "reiserfs/super: read new format super block\n");
	}

	/* Read the super block */
	if ((error = bread(rmp->rm_devvp, offset * btodb(REISERFS_BSIZE),
	    REISERFS_BSIZE, NOCRED, &bp)) != 0) {
		reiserfs_log(LOG_ERR, "can't read device\n");
		return (error);
	}

	/* Get it from the buffer data */
	rs = (struct reiserfs_super_block *)bp->b_data;
	if (!is_any_reiserfs_magic_string(rs)) {
		brelse(bp);
		return (EINVAL);
	}

	fs_blocksize = sb_blocksize(rs);
	brelse(bp);
	bp = NULL;

	if (fs_blocksize <= 0) {
		reiserfs_log(LOG_ERR, "unexpected null block size");
		return (EINVAL);
	}

	/* Read the super block (for double check)
	 * We can't read the same blkno with a different size: it causes
	 * panic() if INVARIANTS is set. So we keep REISERFS_BSIZE */
	if ((error = bread(rmp->rm_devvp,
	    offset * REISERFS_BSIZE / fs_blocksize * btodb(fs_blocksize),
	    REISERFS_BSIZE, NOCRED, &bp)) != 0) {
		reiserfs_log(LOG_ERR, "can't reread the super block\n");
		return (error);
	}

	rs = (struct reiserfs_super_block *)bp->b_data;
	if (sb_blocksize(rs) != fs_blocksize) {
		reiserfs_log(LOG_ERR, "unexpected block size "
		    "(found=%u, expected=%u)\n",
		    sb_blocksize(rs), fs_blocksize);
		brelse(bp);
		return (EINVAL);
	}

	reiserfs_log(LOG_DEBUG, "magic: `%s'\n", rs->s_v1.s_magic);
	reiserfs_log(LOG_DEBUG, "label: `%s'\n", rs->s_label);
	reiserfs_log(LOG_DEBUG, "block size:     %6d\n", sb_blocksize(rs));
	reiserfs_log(LOG_DEBUG, "block count:    %6u\n",
	    rs->s_v1.s_block_count);
	reiserfs_log(LOG_DEBUG, "bitmaps number: %6u\n",
	    rs->s_v1.s_bmap_nr);

	if (rs->s_v1.s_root_block == -1) {
		log(LOG_ERR,
		    "reiserfs: Unfinished reiserfsck --rebuild-tree run "
		    "detected. Please\n"
		    "run reiserfsck --rebuild-tree and wait for a "
		    "completion. If that\n"
		    "fails, get newer reiserfsprogs package");
		brelse(bp);
		return (EINVAL);
	}

	sbi = rmp->rm_reiserfs;
	sbi->s_blocksize = fs_blocksize;

	for (bits = 9, fs_blocksize >>= 9; fs_blocksize >>= 1; bits++)
		;
	sbi->s_blocksize_bits = bits;

	/* Copy the buffer and release it */
	sbi->s_rs = malloc(sizeof *rs, M_REISERFSMNT, M_WAITOK | M_ZERO);
	if (!sbi->s_rs) {
		reiserfs_log(LOG_ERR, "can not read the super block\n");
		brelse(bp);
		return (ENOMEM);
	}
	bcopy(rs, sbi->s_rs, sizeof(struct reiserfs_super_block));
	brelse(bp);

	if (is_reiserfs_jr(rs)) {
		if (sb_version(rs) == REISERFS_VERSION_2)
			reiserfs_log(LOG_INFO, "found reiserfs format \"3.6\""
			    " with non-standard journal");
		else if (sb_version(rs) == REISERFS_VERSION_1)
			reiserfs_log(LOG_INFO, "found reiserfs format \"3.5\""
			    " with non-standard journal");
		else {
			reiserfs_log(LOG_ERR, "found unknown "
			    "format \"%u\" of reiserfs with non-standard magic",
			    sb_version(rs));
			return (EINVAL);
		}
	} else {
		/*
		 * s_version of standard format may contain incorrect
		 * information, so we just look at the magic string
		 */
		reiserfs_log(LOG_INFO,
		    "found reiserfs format \"%s\" with standard journal\n",
		    is_reiserfs_3_5(rs) ? "3.5" : "3.6");
	}

	return (0);
}
Beispiel #4
0
/*
 * Common code for mount and mountroot
 */ 
static int
reiserfs_mountfs(struct vnode *devvp, struct mount *mp, struct thread *td)
{
	int error, old_format = 0;
	struct reiserfs_mount *rmp;
	struct reiserfs_sb_info *sbi;
	struct reiserfs_super_block *rs;
	struct cdev *dev;

	struct g_consumer *cp;
	struct bufobj *bo;

	//ronly = (mp->mnt_flag & MNT_RDONLY) != 0;

	dev = devvp->v_rdev;
	dev_ref(dev);
	DROP_GIANT();
	g_topology_lock();
	error = g_vfs_open(devvp, &cp, "reiserfs", /* read-only */ 0);
	g_topology_unlock();
	PICKUP_GIANT();
	VOP_UNLOCK(devvp, 0);
	if (error) {
		dev_rel(dev);
		return (error);
	}

	bo = &devvp->v_bufobj;
	bo->bo_private = cp;
	bo->bo_ops = g_vfs_bufops;

	if (devvp->v_rdev->si_iosize_max != 0)
		mp->mnt_iosize_max = devvp->v_rdev->si_iosize_max;
	if (mp->mnt_iosize_max > MAXPHYS)
		mp->mnt_iosize_max = MAXPHYS;

	rmp = NULL;
	sbi = NULL;

	/* rmp contains any information about this specific mount */
	rmp = malloc(sizeof *rmp, M_REISERFSMNT, M_WAITOK | M_ZERO);
	if (!rmp) {
		error = (ENOMEM);
		goto out;
	}
	sbi = malloc(sizeof *sbi, M_REISERFSMNT, M_WAITOK | M_ZERO);
	if (!sbi) {
		error = (ENOMEM);
		goto out;
	}
	rmp->rm_reiserfs = sbi;
	rmp->rm_mountp   = mp;
	rmp->rm_devvp    = devvp;
	rmp->rm_dev      = dev;
	rmp->rm_bo       = &devvp->v_bufobj;
	rmp->rm_cp       = cp;

	/* Set default values for options: non-aggressive tails */
	REISERFS_SB(sbi)->s_mount_opt = (1 << REISERFS_SMALLTAIL);
	REISERFS_SB(sbi)->s_rd_only   = 1;
	REISERFS_SB(sbi)->s_devvp     = devvp;

	/* Read the super block */
	if ((error = read_super_block(rmp, REISERFS_OLD_DISK_OFFSET)) == 0) {
		/* The read process succeeded, it's an old format */
		old_format = 1;
	} else if ((error = read_super_block(rmp, REISERFS_DISK_OFFSET)) != 0) {
		reiserfs_log(LOG_ERR, "can not find a ReiserFS filesystem\n");
		goto out;
	}

	rs = SB_DISK_SUPER_BLOCK(sbi);

	/*
	 * Let's do basic sanity check to verify that underlying device is
	 * not smaller than the filesystem. If the check fails then abort and
	 * scream, because bad stuff will happen otherwise.
	 */
#if 0
	if (s->s_bdev && s->s_bdev->bd_inode &&
	    i_size_read(s->s_bdev->bd_inode) <
	    sb_block_count(rs) * sb_blocksize(rs)) {
		reiserfs_log(LOG_ERR,
		    "reiserfs: filesystem cannot be mounted because it is "
		    "bigger than the device.\n");
		reiserfs_log(LOG_ERR, "reiserfs: you may need to run fsck "
		    "rr may be you forgot to reboot after fdisk when it "
		    "told you to.\n");
		goto out;
	}
#endif

	/*
	 * XXX This is from the original Linux code, but why affecting 2 values
	 * to the same variable?
	 */
	sbi->s_mount_state = SB_REISERFS_STATE(sbi);
	sbi->s_mount_state = REISERFS_VALID_FS;

	if ((error = (old_format ?
	    read_old_bitmaps(rmp) : read_bitmaps(rmp)))) {
		reiserfs_log(LOG_ERR, "unable to read bitmap\n");
		goto out;
	}

	/* Make data=ordered the default */
	if (!reiserfs_data_log(sbi) && !reiserfs_data_ordered(sbi) &&
	    !reiserfs_data_writeback(sbi)) {
		REISERFS_SB(sbi)->s_mount_opt |= (1 << REISERFS_DATA_ORDERED);
	}

	if (reiserfs_data_log(sbi)) {
		reiserfs_log(LOG_INFO, "using journaled data mode\n");
	} else if (reiserfs_data_ordered(sbi)) {
		reiserfs_log(LOG_INFO, "using ordered data mode\n");
	} else {
		reiserfs_log(LOG_INFO, "using writeback data mode\n");
	}

	/* TODO Not yet supported */
#if 0
	if(journal_init(sbi, jdev_name, old_format, commit_max_age)) {
		reiserfs_log(LOG_ERR, "unable to initialize journal space\n");
		goto out;
	} else {
		jinit_done = 1 ; /* once this is set, journal_release must
				    be called if we error out of the mount */
	}

	if (reread_meta_blocks(sbi)) {
		reiserfs_log(LOG_ERR,
		    "unable to reread meta blocks after journal init\n");
		goto out;
	}
#endif

	/* Define and initialize hash function */
	sbi->s_hash_function = hash_function(rmp);

	if (sbi->s_hash_function == NULL) {
		reiserfs_log(LOG_ERR, "couldn't determined hash function\n");
		error = (EINVAL);
		goto out;
	}

	if (is_reiserfs_3_5(rs) ||
	    (is_reiserfs_jr(rs) && SB_VERSION(sbi) == REISERFS_VERSION_1))
		bit_set(&(sbi->s_properties), REISERFS_3_5);
	else
		bit_set(&(sbi->s_properties), REISERFS_3_6);

	mp->mnt_data = rmp;
	mp->mnt_stat.f_fsid.val[0] = dev2udev(dev);
	mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
	MNT_ILOCK(mp);
	mp->mnt_flag |= MNT_LOCAL;
	mp->mnt_kern_flag |= MNTK_MPSAFE;
	MNT_IUNLOCK(mp);
#if defined(si_mountpoint)
	devvp->v_rdev->si_mountpoint = mp;
#endif

	return (0);

out:
	reiserfs_log(LOG_INFO, "*** error during mount ***\n");
	if (sbi) {
		if (SB_AP_BITMAP(sbi)) {
			int i;
			for (i = 0; i < SB_BMAP_NR(sbi); i++) {
				if (!SB_AP_BITMAP(sbi)[i].bp_data)
					break;
				free(SB_AP_BITMAP(sbi)[i].bp_data,
				    M_REISERFSMNT);
			}
			free(SB_AP_BITMAP(sbi), M_REISERFSMNT);
		}

		if (sbi->s_rs) {
			free(sbi->s_rs, M_REISERFSMNT);
			sbi->s_rs = NULL;
		}
	}

	if (cp != NULL) {
		DROP_GIANT();
		g_topology_lock();
		g_vfs_close(cp);
		g_topology_unlock();
		PICKUP_GIANT();
	}

	if (sbi)
		free(sbi, M_REISERFSMNT);
	if (rmp)
		free(rmp, M_REISERFSMNT);
	dev_rel(dev);
	return (error);
}