[Ocfs2-devel] [PATCH] test error handling during mount stage
Heming Zhao
heming.zhao at suse.com
Sun Apr 24 13:11:26 UTC 2022
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
More information about the Ocfs2-devel
mailing list