]> git.itanic.dy.fi Git - linux-stable/commitdiff
ext4: export information about first/last errors via /sys/fs/ext4/<dev>
authorTheodore Ts'o <tytso@mit.edu>
Mon, 23 Dec 2019 23:44:49 +0000 (18:44 -0500)
committerTheodore Ts'o <tytso@mit.edu>
Thu, 26 Dec 2019 16:29:10 +0000 (11:29 -0500)
Make {first,last}_error_{ino,block,line,func,errcode} available via
sysfs.

Also add a missing newline for {first,last}_error_time.

Signed-off-by: Theodore Ts'o <tytso@mit.edu>
fs/ext4/sysfs.c

index a990d28d191b3155a037c4ce80ffe6750624d7a4..d218ebdafa4aa006c3a91c653481a67b73a578c4 100644 (file)
@@ -30,6 +30,9 @@ typedef enum {
        attr_feature,
        attr_pointer_ui,
        attr_pointer_ul,
+       attr_pointer_u64,
+       attr_pointer_u8,
+       attr_pointer_string,
        attr_pointer_atomic,
        attr_journal_task,
 } attr_id_t;
@@ -47,6 +50,7 @@ struct ext4_attr {
        struct attribute attr;
        short attr_id;
        short attr_ptr;
+       unsigned short attr_size;
        union {
                int offset;
                void *explicit_ptr;
@@ -155,9 +159,29 @@ static struct ext4_attr ext4_attr_##_name = {                      \
        },                                                      \
 }
 
+#define EXT4_ATTR_STRING(_name,_mode,_size,_struct,_elname)    \
+static struct ext4_attr ext4_attr_##_name = {                  \
+       .attr = {.name = __stringify(_name), .mode = _mode },   \
+       .attr_id = attr_pointer_string,                         \
+       .attr_size = _size,                                     \
+       .attr_ptr = ptr_##_struct##_offset,                     \
+       .u = {                                                  \
+               .offset = offsetof(struct _struct, _elname),\
+       },                                                      \
+}
+
 #define EXT4_RO_ATTR_ES_UI(_name,_elname)                              \
        EXT4_ATTR_OFFSET(_name, 0444, pointer_ui, ext4_super_block, _elname)
 
+#define EXT4_RO_ATTR_ES_U8(_name,_elname)                              \
+       EXT4_ATTR_OFFSET(_name, 0444, pointer_u8, ext4_super_block, _elname)
+
+#define EXT4_RO_ATTR_ES_U64(_name,_elname)                             \
+       EXT4_ATTR_OFFSET(_name, 0444, pointer_u64, ext4_super_block, _elname)
+
+#define EXT4_RO_ATTR_ES_STRING(_name,_elname,_size)                    \
+       EXT4_ATTR_STRING(_name, 0444, _size, ext4_super_block, _elname)
+
 #define EXT4_RW_ATTR_SBI_UI(_name,_elname)     \
        EXT4_ATTR_OFFSET(_name, 0644, pointer_ui, ext4_sb_info, _elname)
 
@@ -202,6 +226,16 @@ EXT4_RW_ATTR_SBI_UI(msg_ratelimit_burst, s_msg_ratelimit_state.burst);
 EXT4_RW_ATTR_SBI_UL(simulate_fail, s_simulate_fail);
 #endif
 EXT4_RO_ATTR_ES_UI(errors_count, s_error_count);
+EXT4_RO_ATTR_ES_U8(first_error_errcode, s_first_error_errcode);
+EXT4_RO_ATTR_ES_U8(last_error_errcode, s_last_error_errcode);
+EXT4_RO_ATTR_ES_UI(first_error_ino, s_first_error_ino);
+EXT4_RO_ATTR_ES_UI(last_error_ino, s_last_error_ino);
+EXT4_RO_ATTR_ES_U64(first_error_block, s_first_error_block);
+EXT4_RO_ATTR_ES_U64(last_error_block, s_last_error_block);
+EXT4_RO_ATTR_ES_UI(first_error_line, s_first_error_line);
+EXT4_RO_ATTR_ES_UI(last_error_line, s_last_error_line);
+EXT4_RO_ATTR_ES_STRING(first_error_func, s_first_error_func, 32);
+EXT4_RO_ATTR_ES_STRING(last_error_func, s_last_error_func, 32);
 EXT4_ATTR(first_error_time, 0444, first_error_time);
 EXT4_ATTR(last_error_time, 0444, last_error_time);
 EXT4_ATTR(journal_task, 0444, journal_task);
@@ -232,6 +266,16 @@ static struct attribute *ext4_attrs[] = {
        ATTR_LIST(msg_ratelimit_interval_ms),
        ATTR_LIST(msg_ratelimit_burst),
        ATTR_LIST(errors_count),
+       ATTR_LIST(first_error_ino),
+       ATTR_LIST(last_error_ino),
+       ATTR_LIST(first_error_block),
+       ATTR_LIST(last_error_block),
+       ATTR_LIST(first_error_line),
+       ATTR_LIST(last_error_line),
+       ATTR_LIST(first_error_func),
+       ATTR_LIST(last_error_func),
+       ATTR_LIST(first_error_errcode),
+       ATTR_LIST(last_error_errcode),
        ATTR_LIST(first_error_time),
        ATTR_LIST(last_error_time),
        ATTR_LIST(journal_task),
@@ -290,7 +334,7 @@ static void *calc_ptr(struct ext4_attr *a, struct ext4_sb_info *sbi)
 
 static ssize_t __print_tstamp(char *buf, __le32 lo, __u8 hi)
 {
-       return snprintf(buf, PAGE_SIZE, "%lld",
+       return snprintf(buf, PAGE_SIZE, "%lld\n",
                        ((time64_t)hi << 32) + le32_to_cpu(lo));
 }
 
@@ -333,6 +377,25 @@ static ssize_t ext4_attr_show(struct kobject *kobj,
                        return 0;
                return snprintf(buf, PAGE_SIZE, "%lu\n",
                                *((unsigned long *) ptr));
+       case attr_pointer_u8:
+               if (!ptr)
+                       return 0;
+               return snprintf(buf, PAGE_SIZE, "%u\n",
+                               *((unsigned char *) ptr));
+       case attr_pointer_u64:
+               if (!ptr)
+                       return 0;
+               if (a->attr_ptr == ptr_ext4_super_block_offset)
+                       return snprintf(buf, PAGE_SIZE, "%llu\n",
+                                       le64_to_cpup(ptr));
+               else
+                       return snprintf(buf, PAGE_SIZE, "%llu\n",
+                                       *((unsigned long long *) ptr));
+       case attr_pointer_string:
+               if (!ptr)
+                       return 0;
+               return snprintf(buf, PAGE_SIZE, "%.*s\n", a->attr_size,
+                               (char *) ptr);
        case attr_pointer_atomic:
                if (!ptr)
                        return 0;