📄 super.c
字号:
" with non-standard journal"); else { reiserfs_warning(s, "sh-2012: read_super_block: found unknown " "format \"%u\" of reiserfs with non-standard magic", sb_version(rs)); return 1; } } else /* s_version of standard format may contain incorrect information, so we just look at the magic string */ reiserfs_info(s, "found reiserfs format \"%s\" with standard journal\n", is_reiserfs_3_5(rs) ? "3.5" : "3.6"); s->s_op = &reiserfs_sops; s->s_export_op = &reiserfs_export_ops;#ifdef CONFIG_QUOTA s->s_qcop = &reiserfs_qctl_operations; s->dq_op = &reiserfs_quota_operations;#endif /* new format is limited by the 32 bit wide i_blocks field, want to ** be one full block below that. */ s->s_maxbytes = (512LL << 32) - s->s_blocksize; return 0;}/* after journal replay, reread all bitmap and super blocks */static int reread_meta_blocks(struct super_block *s){ ll_rw_block(READ, 1, &(SB_BUFFER_WITH_SB(s))); wait_on_buffer(SB_BUFFER_WITH_SB(s)); if (!buffer_uptodate(SB_BUFFER_WITH_SB(s))) { reiserfs_warning(s, "reread_meta_blocks, error reading the super"); return 1; } return 0;}/////////////////////////////////////////////////////// hash detection stuff// if root directory is empty - we set default - Yura's - hash and// warn about it// FIXME: we look for only one name in a directory. If tea and yura// bith have the same value - we ask user to send report to the// mailing liststatic __u32 find_hash_out(struct super_block *s){ int retval; struct inode *inode; struct cpu_key key; INITIALIZE_PATH(path); struct reiserfs_dir_entry de; __u32 hash = DEFAULT_HASH; inode = s->s_root->d_inode; do { // Some serious "goto"-hater was there ;) u32 teahash, r5hash, yurahash; make_cpu_key(&key, inode, ~0, TYPE_DIRENTRY, 3); retval = search_by_entry_key(s, &key, &path, &de); if (retval == IO_ERROR) { pathrelse(&path); return UNSET_HASH; } if (retval == NAME_NOT_FOUND) de.de_entry_num--; set_de_name_and_namelen(&de); if (deh_offset(&(de.de_deh[de.de_entry_num])) == DOT_DOT_OFFSET) { /* allow override in this case */ if (reiserfs_rupasov_hash(s)) { hash = YURA_HASH; } reiserfs_warning(s, "FS seems to be empty, autodetect " "is using the default hash"); break; } r5hash = GET_HASH_VALUE(r5_hash(de.de_name, de.de_namelen)); teahash = GET_HASH_VALUE(keyed_hash(de.de_name, de.de_namelen)); yurahash = GET_HASH_VALUE(yura_hash(de.de_name, de.de_namelen)); if (((teahash == r5hash) && (GET_HASH_VALUE(deh_offset(&(de.de_deh[de.de_entry_num]))) == r5hash)) || ((teahash == yurahash) && (yurahash == GET_HASH_VALUE(deh_offset (& (de. de_deh[de. de_entry_num]))))) || ((r5hash == yurahash) && (yurahash == GET_HASH_VALUE(deh_offset (&(de.de_deh[de.de_entry_num])))))) { reiserfs_warning(s, "Unable to automatically detect hash function. " "Please mount with -o hash={tea,rupasov,r5}", reiserfs_bdevname(s)); hash = UNSET_HASH; break; } if (GET_HASH_VALUE(deh_offset(&(de.de_deh[de.de_entry_num]))) == yurahash) hash = YURA_HASH; else if (GET_HASH_VALUE (deh_offset(&(de.de_deh[de.de_entry_num]))) == teahash) hash = TEA_HASH; else if (GET_HASH_VALUE (deh_offset(&(de.de_deh[de.de_entry_num]))) == r5hash) hash = R5_HASH; else { reiserfs_warning(s, "Unrecognised hash function"); hash = UNSET_HASH; } } while (0); pathrelse(&path); return hash;}// finds out which hash names are sorted withstatic int what_hash(struct super_block *s){ __u32 code; code = sb_hash_function_code(SB_DISK_SUPER_BLOCK(s)); /* reiserfs_hash_detect() == true if any of the hash mount options ** were used. We must check them to make sure the user isn't ** using a bad hash value */ if (code == UNSET_HASH || reiserfs_hash_detect(s)) code = find_hash_out(s); if (code != UNSET_HASH && reiserfs_hash_detect(s)) { /* detection has found the hash, and we must check against the ** mount options */ if (reiserfs_rupasov_hash(s) && code != YURA_HASH) { reiserfs_warning(s, "Error, %s hash detected, " "unable to force rupasov hash", reiserfs_hashname(code)); code = UNSET_HASH; } else if (reiserfs_tea_hash(s) && code != TEA_HASH) { reiserfs_warning(s, "Error, %s hash detected, " "unable to force tea hash", reiserfs_hashname(code)); code = UNSET_HASH; } else if (reiserfs_r5_hash(s) && code != R5_HASH) { reiserfs_warning(s, "Error, %s hash detected, " "unable to force r5 hash", reiserfs_hashname(code)); code = UNSET_HASH; } } else { /* find_hash_out was not called or could not determine the hash */ if (reiserfs_rupasov_hash(s)) { code = YURA_HASH; } else if (reiserfs_tea_hash(s)) { code = TEA_HASH; } else if (reiserfs_r5_hash(s)) { code = R5_HASH; } } /* if we are mounted RW, and we have a new valid hash code, update ** the super */ if (code != UNSET_HASH && !(s->s_flags & MS_RDONLY) && code != sb_hash_function_code(SB_DISK_SUPER_BLOCK(s))) { set_sb_hash_function_code(SB_DISK_SUPER_BLOCK(s), code); } return code;}// return pointer to appropriate functionstatic hashf_t hash_function(struct super_block *s){ switch (what_hash(s)) { case TEA_HASH: reiserfs_info(s, "Using tea hash to sort names\n"); return keyed_hash; case YURA_HASH: reiserfs_info(s, "Using rupasov hash to sort names\n"); return yura_hash; case R5_HASH: reiserfs_info(s, "Using r5 hash to sort names\n"); return r5_hash; } return NULL;}// this is used to set up correct value for old partitionsstatic int function2code(hashf_t func){ if (func == keyed_hash) return TEA_HASH; if (func == yura_hash) return YURA_HASH; if (func == r5_hash) return R5_HASH; BUG(); // should never happen return 0;}#define SWARN(silent, s, ...) \ if (!(silent)) \ reiserfs_warning (s, __VA_ARGS__)static int reiserfs_fill_super(struct super_block *s, void *data, int silent){ struct inode *root_inode; struct reiserfs_transaction_handle th; int old_format = 0; unsigned long blocks; unsigned int commit_max_age = 0; int jinit_done = 0; struct reiserfs_iget_args args; struct reiserfs_super_block *rs; char *jdev_name; struct reiserfs_sb_info *sbi; int errval = -EINVAL; sbi = kzalloc(sizeof(struct reiserfs_sb_info), GFP_KERNEL); if (!sbi) { errval = -ENOMEM; goto error; } s->s_fs_info = sbi; /* Set default values for options: non-aggressive tails, RO on errors */ REISERFS_SB(s)->s_mount_opt |= (1 << REISERFS_SMALLTAIL); REISERFS_SB(s)->s_mount_opt |= (1 << REISERFS_ERROR_RO); /* no preallocation minimum, be smart in reiserfs_file_write instead */ REISERFS_SB(s)->s_alloc_options.preallocmin = 0; /* Preallocate by 16 blocks (17-1) at once */ REISERFS_SB(s)->s_alloc_options.preallocsize = 17;#ifdef CONFIG_REISERFS_FS_XATTR /* Initialize the rwsem for xattr dir */ init_rwsem(&REISERFS_SB(s)->xattr_dir_sem);#endif /* setup default block allocator options */ reiserfs_init_alloc_options(s); jdev_name = NULL; if (reiserfs_parse_options (s, (char *)data, &(sbi->s_mount_opt), &blocks, &jdev_name, &commit_max_age) == 0) { goto error; } if (blocks) { SWARN(silent, s, "jmacd-7: reiserfs_fill_super: resize option " "for remount only"); goto error; } /* try old format (undistributed bitmap, super block in 8-th 1k block of a device) */ if (!read_super_block(s, REISERFS_OLD_DISK_OFFSET_IN_BYTES)) old_format = 1; /* try new format (64-th 1k block), which can contain reiserfs super block */ else if (read_super_block(s, REISERFS_DISK_OFFSET_IN_BYTES)) { SWARN(silent, s, "sh-2021: reiserfs_fill_super: can not find reiserfs on %s", reiserfs_bdevname(s)); goto error; } rs = SB_DISK_SUPER_BLOCK(s); /* 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 (s->s_bdev && s->s_bdev->bd_inode && i_size_read(s->s_bdev->bd_inode) < sb_block_count(rs) * sb_blocksize(rs)) { SWARN(silent, s, "Filesystem on %s cannot be mounted because it is bigger than the device", reiserfs_bdevname(s)); SWARN(silent, s, "You may need to run fsck or increase size of your LVM partition"); SWARN(silent, s, "Or may be you forgot to reboot after fdisk when it told you to"); goto error; } sbi->s_mount_state = SB_REISERFS_STATE(s); sbi->s_mount_state = REISERFS_VALID_FS; if ((errval = reiserfs_init_bitmap_cache(s))) { SWARN(silent, s, "jmacd-8: reiserfs_fill_super: unable to read bitmap"); goto error; } errval = -EINVAL;#ifdef CONFIG_REISERFS_CHECK SWARN(silent, s, "CONFIG_REISERFS_CHECK is set ON"); SWARN(silent, s, "- it is slow mode for debugging.");#endif /* make data=ordered the default */ if (!reiserfs_data_log(s) && !reiserfs_data_ordered(s) && !reiserfs_data_writeback(s)) { REISERFS_SB(s)->s_mount_opt |= (1 << REISERFS_DATA_ORDERED); } if (reiserfs_data_log(s)) { reiserfs_info(s, "using journaled data mode\n"); } else if (reiserfs_data_ordered(s)) { reiserfs_info(s, "using ordered data mode\n"); } else { reiserfs_info(s, "using writeback data mode\n"); } if (reiserfs_barrier_flush(s)) { printk("reiserfs: using flush barriers\n"); } // set_device_ro(s->s_dev, 1) ; if (journal_init(s, jdev_name, old_format, commit_max_age)) { SWARN(silent, s, "sh-2022: reiserfs_fill_super: unable to initialize journal space"); goto error; } else { jinit_done = 1; /* once this is set, journal_release must be called ** if we error out of the mount */ } if (reread_meta_blocks(s)) { SWARN(silent, s, "jmacd-9: reiserfs_fill_super: unable to reread meta blocks after journal init"); goto error; } if (replay_only(s)) goto error; if (bdev_read_only(s->s_bdev) && !(s->s_flags & MS_RDONLY)) { SWARN(silent, s, "clm-7000: Detected readonly device, marking FS readonly"); s->s_flags |= MS_RDONLY; } args.objectid = REISERFS_ROOT_OBJECTID; args.dirid = REISERFS_ROOT_PARENT_OBJECTID; root_inode = iget5_locked(s, REISERFS_ROOT_OBJECTID, reiserfs_find_actor, reiserfs_init_locked_inode, (void *)(&args)); if (!root_inode) { SWARN(silent, s, "jmacd-10: reiserfs_fill_super: get root inode failed"); goto error; } if (root_inode->i_state & I_NEW) { reiserfs_read_locked_inode(root_inode, &args); unlock_new_inode(root_inode); } s->s_root = d_alloc_root(root_inode); if (!s->s_root) { iput(root_inode); goto error; } // define and initialize hash function sbi->s_hash_function = hash_function(s); if (sbi->s_hash_function == NULL) { dput(s->s_root); s->s_root = NULL; goto error; } if (is_reiserfs_3_5(rs) || (is_reiserfs_jr(rs) && SB_VERSION(s) == REISERFS_VERSION_1)) set_bit(REISERFS_3_5, &(sbi->s_properties)); else if (old_format) set_bit(REISERFS_OLD_FORMAT, &(sbi->s_properties)); else set_bit(REISERFS_3_6, &(sbi->s_properties)); if (!(s->s_flags & MS_RDONLY)) { errval = journal_begin(&th, s, 1); if (errval) { dput(s->s_root); s->s_root = NULL; goto error; } reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); set_sb_umount_state(rs, REISERFS_ERROR_FS); set_sb_fs_state(rs, 0); /* Clear out s_bmap_nr if it would wrap. We can handle this * case, but older revisions can't. This will cause the * file system to fail mount on those older implementations, * avoiding corruption. -jeffm */ if (bmap_would_wrap(reiserfs_bmap_count(s)) && sb_bmap_nr(rs) != 0) { reiserfs_warning(s, "super-2030: This file system " "claims to use %u bitmap blocks in " "its super block, but requires %u. " "Clearing to zero.", sb_bmap_nr(rs), reiserfs_bmap_count(s)); set_sb_bmap_nr(rs, 0); } if (old_format_only(s)) { /* filesystem of format 3.5 either with standard or non-standard journal */ if (convert_reiserfs(s)) { /* and -o conv is given */ if (!silent) reiserfs_info(s, "converting 3.5 filesystem to the 3.6 format"); if (is_reiserfs_3_5(rs)) /* put magic string of 3.6 format. 2.2 will not be able to mount this filesystem anymore */ memcpy(rs->s_v1.s_magic, reiserfs_3_6_magic_string, sizeof (reiserfs_3_6_magic_string)); set_sb_version(rs, REISERFS_VERSION_2); reiserfs_convert_objectid_map_v1(s); set_bit(REISERFS_3_6, &(sbi->s_properties)); clear_bit(REISERFS_3_5, &(sbi->s_properties)); } else if (!silent) { reiserfs_info(s, "using 3.5.x disk format\n"); } } journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB(s)); errval = journal_end(&th, s, 1); if (errval) { dput(s->s_root);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -