Heming Zhao
2022-Apr-24 13:11 UTC
[Ocfs2-devel] [PATCH] test error handling during mount stage
this patch is for test my serial patch only. I don't any plan to add this patch into upstream code. test script: ``` path="/sys/kernel/debug/ocfs2/mnt_dbg" dev=$1 mnt=$2 if [ -z "$dev" ];then echo "input device. eg: /dev/vdd" exit 1 fi if [ -z "$mnt" ];then echo "input mount point. eg: /mnt" exit 1 fi echo "please monitor: journalctl -f" for i in {1..39}; do already_mount=`lsblk | grep $mnt` if [ -n "$already_mount" ]; then umount $mnt fi echo "===> error $i <====" echo "$i" > $path echo "$path: `cat $path`" mount -t ocfs2 $dev $mnt sleep 1 done ``` Signed-off-by: Heming Zhao <heming.zhao at suse.com> --- fs/ocfs2/super.c | 169 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 151 insertions(+), 18 deletions(-) diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index f7298816d8d9..4af861f973fc 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -66,6 +66,52 @@ struct kmem_cache *ocfs2_qf_chunk_cachep; static struct dentry *ocfs2_debugfs_root; +enum { + mnt_dbg_off, + mnt_dbg_fill_super_1, + mnt_dbg_fill_super_2,//useless + mnt_dbg_fill_super_3,//useless + mnt_dbg_fill_super_4, + mnt_dbg_fill_super_5, + mnt_dbg_fill_super_6, + mnt_dbg_fill_super_7, + mnt_dbg_fill_super_8, + mnt_dbg_fill_super_9, + mnt_dbg_fill_super_10,//useless + mnt_dbg_fill_super_11, + mnt_dbg_fill_super_12, + mnt_dbg_fill_super_13, + mnt_dbg_fill_super_14, + mnt_dbg_fill_super_15, + mnt_dbg_sb_probe_1, + mnt_dbg_sb_probe_2, + mnt_dbg_sb_probe_3, + mnt_dbg_init_super_1, + mnt_dbg_init_super_2, + mnt_dbg_init_super_3, + mnt_dbg_init_super_4, + mnt_dbg_init_super_5, + mnt_dbg_init_super_6, + mnt_dbg_init_super_7, + mnt_dbg_init_super_8, + mnt_dbg_init_super_9, + mnt_dbg_init_super_10, + mnt_dbg_init_super_11, + mnt_dbg_init_super_12, + mnt_dbg_init_super_13, + mnt_dbg_init_super_14, + mnt_dbg_init_super_15, + mnt_dbg_mount_volume_1, + mnt_dbg_mount_volume_2, + mnt_dbg_mount_volume_3, + mnt_dbg_mount_volume_4, + mnt_dbg_mount_volume_5, + mnt_dbg_mount_volume_6, + mnt_dbg_last = mnt_dbg_mount_volume_6, +}; + +static u64 mnt_dbg; + MODULE_AUTHOR("Oracle"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("OCFS2 cluster file system"); @@ -121,6 +167,7 @@ static void ocfs2_free_inode(struct inode *inode); static int ocfs2_susp_quotas(struct ocfs2_super *osb, int unsuspend); static int ocfs2_enable_quotas(struct ocfs2_super *osb); static void ocfs2_disable_quotas(struct ocfs2_super *osb); +int mnt_err_inject(u64 mnt_dbg_num); static struct dquot **ocfs2_get_dquots(struct inode *inode) { @@ -727,6 +774,15 @@ static int ocfs2_remount(struct super_block *sb, int *flags, char *data) return ret; } +int mnt_err_inject(u64 mnt_dbg_num) +{ + if (mnt_dbg == mnt_dbg_num) { + mlog(ML_ERROR, "trigger dbg num: %llu\n", mnt_dbg); + return -EINVAL; + } + return 0; +} + static int ocfs2_sb_probe(struct super_block *sb, struct buffer_head **bh, int *sector_size, @@ -741,7 +797,7 @@ static int ocfs2_sb_probe(struct super_block *sb, /* may be > 512 */ *sector_size = bdev_logical_block_size(sb->s_bdev); - if (*sector_size > OCFS2_MAX_BLOCKSIZE) { + if (*sector_size > OCFS2_MAX_BLOCKSIZE || mnt_err_inject(mnt_dbg_sb_probe_1) < 0) { mlog(ML_ERROR, "Hardware sector size too large: %d (max=%d)\n", *sector_size, OCFS2_MAX_BLOCKSIZE); status = -EINVAL; @@ -772,7 +828,7 @@ static int ocfs2_sb_probe(struct super_block *sb, } brelse(*bh); *bh = NULL; - if (status < 0) { + if (status < 0 || (status = mnt_err_inject(mnt_dbg_sb_probe_2)) < 0) { mlog(ML_ERROR, "This is an ocfs v1 filesystem which must be " "upgraded before mounting with ocfs v2\n"); goto bail; @@ -808,6 +864,10 @@ static int ocfs2_sb_probe(struct super_block *sb, break; } } + if ((status = mnt_err_inject(mnt_dbg_sb_probe_3)) < 0) { + brelse(*bh); + *bh = NULL; + } bail: return status; @@ -987,7 +1047,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) trace_ocfs2_fill_super(sb, data, silent); - if (!ocfs2_parse_options(sb, data, &parsed_options, 0)) { + if (!ocfs2_parse_options(sb, data, &parsed_options, 0) || mnt_err_inject(mnt_dbg_fill_super_1) < 0) { status = -EINVAL; goto out; } @@ -999,6 +1059,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) goto out; } + //add mnt_err_inject() in ocfs2_initialize_super() status = ocfs2_initialize_super(sb, bh, sector_size, &stats); brelse(bh); bh = NULL; @@ -1007,7 +1068,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) osb = OCFS2_SB(sb); - if (!ocfs2_check_set_options(sb, &parsed_options)) { + if (!ocfs2_check_set_options(sb, &parsed_options) || mnt_err_inject(mnt_dbg_fill_super_4) < 0) { status = -EINVAL; goto out_super; } @@ -1025,7 +1086,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) osb->osb_dir_resv_level = parsed_options.dir_resv_level; status = ocfs2_verify_userspace_stack(osb, &parsed_options); - if (status) + if (status || (status = mnt_err_inject(mnt_dbg_fill_super_5)) < 0) goto out_super; sb->s_magic = OCFS2_SUPER_MAGIC; @@ -1036,7 +1097,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) /* Hard readonly mode only if: bdev_read_only, SB_RDONLY, * heartbeat=none */ if (bdev_read_only(sb->s_bdev)) { - if (!sb_rdonly(sb)) { + if (!sb_rdonly(sb) || mnt_err_inject(mnt_dbg_fill_super_6) < 0) { status = -EACCES; mlog(ML_ERROR, "Readonly device detected but readonly " "mount was not specified.\n"); @@ -1045,7 +1106,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) /* You should not be able to start a local heartbeat * on a readonly device. */ - if (osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL) { + if ((osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL) || mnt_err_inject(mnt_dbg_fill_super_7) < 0) { status = -EROFS; mlog(ML_ERROR, "Local heartbeat specified on readonly " "device.\n"); @@ -1053,7 +1114,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) } status = ocfs2_check_journals_nolocks(osb); - if (status < 0) { + if (status < 0 || (status = mnt_err_inject(mnt_dbg_fill_super_8)) < 0) { if (status == -EROFS) mlog(ML_ERROR, "Recovery required on readonly " "file system, but write access is " @@ -1074,7 +1135,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) } status = ocfs2_verify_heartbeat(osb); - if (status < 0) + if (status < 0 || (status = mnt_err_inject(mnt_dbg_fill_super_9)) < 0) goto out_super; osb->osb_debug_root = debugfs_create_dir(osb->uuid_str, @@ -1087,6 +1148,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) ocfs2_blockcheck_stats_debugfs_install( &osb->osb_ecc_stats, osb->osb_debug_root); + //add mnt_err_inject() in ocfs2_mount_volume() status = ocfs2_mount_volume(sb); if (status < 0) goto out_debugfs; @@ -1094,14 +1156,14 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) if (osb->root_inode) inode = igrab(osb->root_inode); - if (!inode) { + if (!inode || mnt_err_inject(mnt_dbg_fill_super_11) < 0) { status = -EIO; goto out_dismount; } osb->osb_dev_kset = kset_create_and_add(sb->s_id, NULL, &ocfs2_kset->kobj); - if (!osb->osb_dev_kset) { + if (!osb->osb_dev_kset || mnt_err_inject(mnt_dbg_fill_super_12) < 0) { status = -ENOMEM; mlog(ML_ERROR, "Unable to create device kset %s.\n", sb->s_id); goto out_dismount; @@ -1109,7 +1171,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) /* Create filecheck sysfs related directories/files at * /sys/fs/ocfs2/<devname>/filecheck */ - if (ocfs2_filecheck_create_sysfs(osb)) { + if (ocfs2_filecheck_create_sysfs(osb) || mnt_err_inject(mnt_dbg_fill_super_13) < 0) { status = -ENOMEM; mlog(ML_ERROR, "Unable to create filecheck sysfs directory at " "/sys/fs/ocfs2/%s/filecheck.\n", sb->s_id); @@ -1117,7 +1179,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) } root = d_make_root(inode); - if (!root) { + if (!root || mnt_err_inject(mnt_dbg_fill_super_14) < 0) { status = -ENOMEM; goto out_dismount; } @@ -1150,7 +1212,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) * log recovery can happen but that waits for proper quota setup */ if (!sb_rdonly(sb)) { status = ocfs2_enable_quotas(osb); - if (status < 0) { + if (status < 0 || (status = mnt_err_inject(mnt_dbg_fill_super_15)) < 0) { /* We have to err-out specially here because * s_root is already set */ mlog_errno(status); @@ -1572,6 +1634,21 @@ static int ocfs2_show_options(struct seq_file *s, struct dentry *root) return 0; } +static int ocfs2_mnt_dbg_set(void *data, u64 val) +{ + u64 *mnt_dbg_num = (u64 *) data; + *mnt_dbg_num = val; + mlog(ML_ERROR, "set value: %llu\n", val); + return 0; +} +static int ocfs2_mnt_dbg_get(void *data, u64 *val) +{ + u64 *mnt_dbg_num = (u64 *) data; + *val = *mnt_dbg_num; + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(ocfs2_mnt_dbg_fops, ocfs2_mnt_dbg_get, ocfs2_mnt_dbg_set, "%llu\n"); + static int __init ocfs2_init(void) { int status; @@ -1586,6 +1663,9 @@ static int __init ocfs2_init(void) ocfs2_debugfs_root = debugfs_create_dir("ocfs2", NULL); + debugfs_create_file("mnt_dbg", S_IFREG|S_IRUSR, ocfs2_debugfs_root, + &mnt_dbg, &ocfs2_mnt_dbg_fops); + ocfs2_set_locking_protocol(); status = register_quota_format(&ocfs2_quota_format); @@ -1815,16 +1895,22 @@ static int ocfs2_mount_volume(struct super_block *sb) " disk does not match the running cluster name.\n"); goto out; } + if ((status = mnt_err_inject(mnt_dbg_mount_volume_1)) < 0) { + goto out_dlm; + } status = ocfs2_super_lock(osb, 1); if (status < 0) { mlog_errno(status); goto out_dlm; } + if ((status = mnt_err_inject(mnt_dbg_mount_volume_2)) < 0) { + goto out_super_lock; + } /* This will load up the node map and add ourselves to it. */ status = ocfs2_find_slot(osb); - if (status < 0) { + if (status < 0 || (status = mnt_err_inject(mnt_dbg_mount_volume_3)) < 0) { mlog_errno(status); goto out_super_lock; } @@ -1835,9 +1921,12 @@ static int ocfs2_mount_volume(struct super_block *sb) mlog_errno(status); goto out_super_lock; } + if ((status = mnt_err_inject(mnt_dbg_mount_volume_4)) < 0) { + goto out_system_inodes; + } status = ocfs2_check_volume(osb); - if (status < 0) { + if (status < 0 || (status = mnt_err_inject(mnt_dbg_mount_volume_5)) < 0) { mlog_errno(status); goto out_system_inodes; } @@ -1847,6 +1936,10 @@ static int ocfs2_mount_volume(struct super_block *sb) mlog_errno(status); goto out_system_inodes; } + if ((status = mnt_err_inject(mnt_dbg_mount_volume_6)) < 0) { + ocfs2_truncate_log_shutdown(osb); + goto out_system_inodes; + } ocfs2_super_unlock(osb, 1); return 0; @@ -2032,6 +2125,9 @@ static int ocfs2_initialize_super(struct super_block *sb, mlog_errno(status); goto out; } + if ((status = mnt_err_inject(mnt_dbg_init_super_1)) < 0) { + goto out; + } sb->s_fs_info = osb; sb->s_op = &ocfs2_sops; @@ -2087,7 +2183,7 @@ static int ocfs2_initialize_super(struct super_block *sb, MAJOR(osb->sb->s_dev), MINOR(osb->sb->s_dev)); osb->max_slots = le16_to_cpu(di->id2.i_super.s_max_slots); - if (osb->max_slots > OCFS2_MAX_SLOTS || osb->max_slots == 0) { + if (osb->max_slots > OCFS2_MAX_SLOTS || osb->max_slots == 0 || mnt_err_inject(mnt_dbg_init_super_2) < 0) { mlog(ML_ERROR, "Invalid number of node slots (%u)\n", osb->max_slots); status = -EINVAL; @@ -2102,6 +2198,9 @@ static int ocfs2_initialize_super(struct super_block *sb, mlog_errno(status); goto out; } + if ((status = mnt_err_inject(mnt_dbg_init_super_3)) < 0) { + goto out_recovery_map; + } init_waitqueue_head(&osb->checkpoint_event); @@ -2126,6 +2225,9 @@ static int ocfs2_initialize_super(struct super_block *sb, status = -ENOMEM; goto out_recovery_map; } + if ((status = mnt_err_inject(mnt_dbg_init_super_4)) < 0) { + goto out_vol_label; + } osb->slot_recovery_generations kcalloc(osb->max_slots, sizeof(*osb->slot_recovery_generations), @@ -2135,6 +2237,9 @@ static int ocfs2_initialize_super(struct super_block *sb, mlog_errno(status); goto out_vol_label; } + if ((status = mnt_err_inject(mnt_dbg_init_super_5)) < 0) { + goto out_slot_recovery_gen; + } init_waitqueue_head(&osb->osb_wipe_event); osb->osb_orphan_wipes = kcalloc(osb->max_slots, @@ -2145,6 +2250,9 @@ static int ocfs2_initialize_super(struct super_block *sb, mlog_errno(status); goto out_slot_recovery_gen; } + if ((status = mnt_err_inject(mnt_dbg_init_super_6)) < 0) { + goto out_orphan_wipes; + } osb->osb_rf_lock_tree = RB_ROOT; @@ -2207,6 +2315,9 @@ static int ocfs2_initialize_super(struct super_block *sb, status = ocfs2_journal_alloc(osb); if (status < 0) goto out_orphan_wipes; + if ((status = mnt_err_inject(mnt_dbg_init_super_7)) < 0) { + goto out_journal; + } INIT_WORK(&osb->dquot_drop_work, ocfs2_drop_dquot_refs); init_llist_head(&osb->dquot_drop_list); @@ -2223,6 +2334,9 @@ static int ocfs2_initialize_super(struct super_block *sb, status = -EINVAL; goto out_journal; } + if ((status = mnt_err_inject(mnt_dbg_init_super_8)) < 0) { + goto out_journal; + } total_blocks = ocfs2_clusters_to_blocks(osb->sb, le32_to_cpu(di->i_clusters)); @@ -2235,6 +2349,9 @@ static int ocfs2_initialize_super(struct super_block *sb, status = -EFBIG; goto out_journal; } + if ((status = mnt_err_inject(mnt_dbg_init_super_9)) < 0) { + goto out_journal; + } if (ocfs2_setup_osb_uuid(osb, di->id2.i_super.s_uuid, sizeof(di->id2.i_super.s_uuid))) { @@ -2242,6 +2359,9 @@ static int ocfs2_initialize_super(struct super_block *sb, status = -ENOMEM; goto out_journal; } + if ((status = mnt_err_inject(mnt_dbg_init_super_10)) < 0) { + goto out_uuid_str; + } strlcpy(osb->vol_label, di->id2.i_super.s_label, OCFS2_MAX_VOL_LABEL_LEN); @@ -2262,6 +2382,9 @@ static int ocfs2_initialize_super(struct super_block *sb, mlog_errno(status); goto out_uuid_str; } + if ((status = mnt_err_inject(mnt_dbg_init_super_11)) < 0) { + goto out_dlm_out; + } atomic_set(&osb->vol_state, VOLUME_INIT); @@ -2271,13 +2394,16 @@ static int ocfs2_initialize_super(struct super_block *sb, mlog_errno(status); goto out_dlm_out; } + if ((status = mnt_err_inject(mnt_dbg_init_super_12)) < 0) { + goto out_system_inodes; + } /* * global bitmap */ inode = ocfs2_get_system_file_inode(osb, GLOBAL_BITMAP_SYSTEM_INODE, OCFS2_INVALID_SLOT); - if (!inode) { + if (!inode || mnt_err_inject(mnt_dbg_init_super_13) < 0) { status = -EINVAL; mlog_errno(status); goto out_system_inodes; @@ -2295,6 +2421,9 @@ static int ocfs2_initialize_super(struct super_block *sb, mlog_errno(status); goto out_system_inodes; } + if ((status = mnt_err_inject(mnt_dbg_init_super_14)) < 0) { + goto out_slot_info; + } osb->ocfs2_wq = alloc_ordered_workqueue("ocfs2_wq", WQ_MEM_RECLAIM); if (!osb->ocfs2_wq) { @@ -2302,6 +2431,10 @@ static int ocfs2_initialize_super(struct super_block *sb, mlog_errno(status); goto out_slot_info; } + if ((status = mnt_err_inject(mnt_dbg_init_super_15)) < 0) { + destroy_workqueue(osb->ocfs2_wq); + goto out_slot_info; + } return status; -- 2.35.1