Commit eb7a43c7 authored by Zhao Minmin's avatar Zhao Minmin Committed by Baokun Li
Browse files

ext4: report error to userspace by netlink

hulk inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I8TNRU


CVE: NA

-------------------------------------------------

Implement the ext3/ext4 file system error report.

This patch is used to implement abnormal alarm of ext3/ext4 filesystem.
You can archieve this by setting "FILESYSTEM_MONITOR" or "FILESYSTEM_ALARM"
on in configuration file. With this setting, alarm will be raised when
ext3/ext4 file system expection occurs.

Signed-off-by: default avatarZhao Minmin <zhaominmin1@huawei.com>
Reviewed-by: default avatarYi Zhang <yi.zhang@huawei.com>
Link: http://hulk.huawei.com/pipermail/kernel.openeuler/2016-March/009711.html


Signed-off-by: default avatarWang Hui <john.wanghui@huawei.com>
Signed-off-by: default avatarKefeng Wang <wangkefeng.wang@huawei.com>

[yebin: cherry-pick this patch from openeuler, commit 6636f443]
conflicts :
fs/ext4/super.c
fs/ext4/ext4.h

Signed-off-by: default avatarYe Bin <yebin10@huawei.com>
Reviewed-by: default avatarZhang Yi <yi.zhang@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>

Conflicts:
	fs/ext4/super.c

Signed-off-by: default avatarBaokun Li <libaokun1@huawei.com>
parent 47634ecf
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -47,6 +47,15 @@

#include <linux/compiler.h>

#define NL_EXT4_ERROR_GROUP    1
#define EXT4_ERROR_MAGIC       0xAE32014U
struct ext4_err_msg {
	int magic;
	char s_id[32];
	unsigned long s_flags;
	int ext4_errno;
};

/*
 * The fourth extended filesystem constants/structures
 */
+53 −1
Original line number Diff line number Diff line
@@ -57,6 +57,10 @@
#include "mballoc.h"
#include "fsmap.h"

#include <uapi/linux/netlink.h>
#include <net/sock.h>
#include <net/net_namespace.h>

#define CREATE_TRACE_POINTS
#include <trace/events/ext4.h>

@@ -84,6 +88,8 @@ static void ext4_unregister_li_request(struct super_block *sb);
static void ext4_clear_request_list(void);
static struct inode *ext4_get_journal_inode(struct super_block *sb,
					    unsigned int journal_inum);
static void ext4_netlink_send_info(struct super_block *sb, int ext4_errno);
static struct sock *ext4nl;
static int ext4_validate_options(struct fs_context *fc);
static int ext4_check_opt_consistency(struct fs_context *fc,
				      struct super_block *sb);
@@ -678,6 +684,42 @@ static void save_error_info(struct super_block *sb, int error,
	spin_unlock(&sbi->s_error_lock);
}

static void ext4_netlink_send_info(struct super_block *sb, int ext4_errno)
{
	int size;
	sk_buff_data_t old_tail;
	struct sk_buff *skb;
	struct nlmsghdr *nlh;
	struct ext4_err_msg *msg;

	if (ext4nl) {
		size = NLMSG_SPACE(sizeof(struct ext4_err_msg));
		skb = alloc_skb(size, GFP_ATOMIC);
		if (!skb) {
			printk(KERN_ERR "Cannot alloc skb!");
			return;
		}
		old_tail = skb->tail;
		nlh = nlmsg_put(skb, 0, 0, NLMSG_ERROR, size - sizeof(*nlh), 0);
		if (!nlh)
			goto nlmsg_failure;
		msg = (struct ext4_err_msg *)NLMSG_DATA(nlh);
		msg->magic = EXT4_ERROR_MAGIC;
		memcpy(msg->s_id, sb->s_id, sizeof(sb->s_id));
		msg->s_flags = sb->s_flags;
		msg->ext4_errno = ext4_errno;
		nlh->nlmsg_len = skb->tail - old_tail;
		NETLINK_CB(skb).portid = 0;
		NETLINK_CB(skb).dst_group = NL_EXT4_ERROR_GROUP;
		netlink_broadcast(ext4nl, skb, 0, NL_EXT4_ERROR_GROUP,
		 GFP_ATOMIC);
		return;
nlmsg_failure:
		if (skb)
			kfree_skb(skb);
	}
}

/* Deal with the reporting of failure conditions on a filesystem such as
 * inconsistencies detected or read IO failures.
 *
@@ -739,9 +781,12 @@ static void ext4_handle_error(struct super_block *sb, bool force_ro, int error,
			sb->s_id);
	}

	if (sb_rdonly(sb) || continue_fs)
	if (sb_rdonly(sb))
		return;

	if (continue_fs)
		goto out;

	ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only");
	/*
	 * Make sure updated value of ->s_mount_flags will be visible before
@@ -749,6 +794,8 @@ static void ext4_handle_error(struct super_block *sb, bool force_ro, int error,
	 */
	smp_wmb();
	sb->s_flags |= SB_RDONLY;
out:
	ext4_netlink_send_info(sb, force_ro ? 2 : 1);
}

static void update_super_work(struct work_struct *work)
@@ -7342,6 +7389,7 @@ wait_queue_head_t ext4__ioend_wq[EXT4_WQ_HASH_SZ];
static int __init ext4_init_fs(void)
{
	int i, err;
	struct netlink_kernel_cfg cfg = {.groups = NL_EXT4_ERROR_GROUP,};

	ratelimit_state_init(&ext4_mount_msg_ratelimit, 30 * HZ, 64);
	ext4_li_info = NULL;
@@ -7393,6 +7441,9 @@ static int __init ext4_init_fs(void)
	if (err)
		goto out;

	ext4nl = netlink_kernel_create(&init_net, NETLINK_FILESYSTEM, &cfg);
	if (!ext4nl)
		printk(KERN_ERR "EXT4-fs: Cannot create netlink socket.\n");
	return 0;
out:
	unregister_as_ext2();
@@ -7433,6 +7484,7 @@ static void __exit ext4_exit_fs(void)
	ext4_exit_post_read_processing();
	ext4_exit_es();
	ext4_exit_pending();
	netlink_kernel_release(ext4nl);
}

MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
+1 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
#define NETLINK_RDMA		20
#define NETLINK_CRYPTO		21	/* Crypto layer */
#define NETLINK_SMC		22	/* SMC monitoring */
#define NETLINK_FILESYSTEM	28	/* filesystem alarm*/

#define NETLINK_INET_DIAG	NETLINK_SOCK_DIAG