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))); }
/* 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; }
/* * 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); }
/* * 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); }