From: Zhao Minmin zhaominmin1@huawei.com
hulk inclusion category: feature bugzilla: 34592 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: Zhao Minmin zhaominmin1@huawei.com Reviewed-by: Yi Zhang yi.zhang@huawei.com Link: http://hulk.huawei.com/pipermail/kernel.openeuler/2016-March/009711.html Signed-off-by: Wang Hui john.wanghui@huawei.com Signed-off-by: Kefeng Wang wangkefeng.wang@huawei.com
[yebin: cherry-pick this patch from redhat-7.5, commit 13848b1856c1]
Signed-off-by: Ye Bin yebin10@huawei.com Reviewed-by: Wenan Mao maowenan@huawei.com Reviewed-by: Yi Zhang yi.zhang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- fs/ext4/ext4.h | 9 ++++++++ fs/ext4/super.c | 51 ++++++++++++++++++++++++++++++++++++++++++++ include/uapi/linux/netlink.h | 1 + 3 files changed, 61 insertions(+)
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index b1bcc6e..83bec07 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -54,6 +54,15 @@ #endif #endif
+#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 */ diff --git a/fs/ext4/super.c b/fs/ext4/super.c index bd6c1cf..33f1e7c 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -54,6 +54,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 struct dentry *ext4_mount(struct file_system_type *fs_type, int flags, 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;
/* * Lock ordering @@ -439,6 +445,42 @@ static bool system_going_down(void) || system_state == SYSTEM_RESTART; }
+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. * @@ -469,6 +511,9 @@ static void ext4_handle_error(struct super_block *sb) if (journal) jbd2_journal_abort(journal, -EIO); } + + ext4_netlink_send_info(sb, 1); + /* * We force ERRORS_RO behavior when system is rebooting. Otherwise we * could panic during 'reboot -f' as the underlying device got already @@ -700,6 +745,7 @@ void __ext4_abort(struct super_block *sb, const char *function, if (EXT4_SB(sb)->s_journal) jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO); save_error_info(sb, function, line); + ext4_netlink_send_info(sb, 2); } if (test_opt(sb, ERRORS_PANIC) && !system_going_down()) { if (EXT4_SB(sb)->s_journal && @@ -6063,6 +6109,7 @@ static inline int ext3_feature_set_ok(struct super_block *sb) 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; @@ -6102,6 +6149,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(); @@ -6133,6 +6183,7 @@ static void __exit ext4_exit_fs(void) ext4_exit_system_zone(); ext4_exit_pageio(); ext4_exit_es(); + netlink_kernel_release(ext4nl); }
MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others"); diff --git a/include/uapi/linux/netlink.h b/include/uapi/linux/netlink.h index 776bc92..ecaefee 100644 --- a/include/uapi/linux/netlink.h +++ b/include/uapi/linux/netlink.h @@ -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