Skip to content

Commit 74c4795

Browse files
author
Darrick J. Wong
committed
xfs: convey filesystem shutdown events to the health monitor
Connect the filesystem shutdown code to the health monitor so that xfs can send events about that to the xfs_healer daemon. Signed-off-by: "Darrick J. Wong" <djwong@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de>
1 parent 5eb4cb1 commit 74c4795

5 files changed

Lines changed: 121 additions & 1 deletion

File tree

fs/xfs/libxfs/xfs_fs.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1028,6 +1028,9 @@ struct xfs_rtgroup_geometry {
10281028
#define XFS_HEALTH_MONITOR_TYPE_CORRUPT (4)
10291029
#define XFS_HEALTH_MONITOR_TYPE_HEALTHY (5)
10301030

1031+
/* filesystem shutdown */
1032+
#define XFS_HEALTH_MONITOR_TYPE_SHUTDOWN (6)
1033+
10311034
/* lost events */
10321035
struct xfs_health_monitor_lost {
10331036
__u64 count;
@@ -1054,6 +1057,20 @@ struct xfs_health_monitor_inode {
10541057
__u64 ino;
10551058
};
10561059

1060+
/* shutdown reasons */
1061+
#define XFS_HEALTH_SHUTDOWN_META_IO_ERROR (1u << 0)
1062+
#define XFS_HEALTH_SHUTDOWN_LOG_IO_ERROR (1u << 1)
1063+
#define XFS_HEALTH_SHUTDOWN_FORCE_UMOUNT (1u << 2)
1064+
#define XFS_HEALTH_SHUTDOWN_CORRUPT_INCORE (1u << 3)
1065+
#define XFS_HEALTH_SHUTDOWN_CORRUPT_ONDISK (1u << 4)
1066+
#define XFS_HEALTH_SHUTDOWN_DEVICE_REMOVED (1u << 5)
1067+
1068+
/* shutdown */
1069+
struct xfs_health_monitor_shutdown {
1070+
/* XFS_HEALTH_SHUTDOWN_* flags */
1071+
__u32 reasons;
1072+
};
1073+
10571074
struct xfs_health_monitor_event {
10581075
/* XFS_HEALTH_MONITOR_DOMAIN_* */
10591076
__u32 domain;
@@ -1074,6 +1091,7 @@ struct xfs_health_monitor_event {
10741091
struct xfs_health_monitor_fs fs;
10751092
struct xfs_health_monitor_group group;
10761093
struct xfs_health_monitor_inode inode;
1094+
struct xfs_health_monitor_shutdown shutdown;
10771095
} e;
10781096

10791097
/* zeroes */

fs/xfs/xfs_fsops.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "xfs_rtrmap_btree.h"
2626
#include "xfs_rtrefcount_btree.h"
2727
#include "xfs_metafile.h"
28+
#include "xfs_healthmon.h"
2829

2930
#include <linux/fserror.h>
3031

@@ -544,6 +545,7 @@ xfs_do_force_shutdown(
544545
xfs_stack_trace();
545546

546547
fserror_report_shutdown(mp->m_super, GFP_KERNEL);
548+
xfs_healthmon_report_shutdown(mp, flags);
547549
}
548550

549551
/*

fs/xfs/xfs_healthmon.c

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "xfs_rtgroup.h"
2121
#include "xfs_health.h"
2222
#include "xfs_healthmon.h"
23+
#include "xfs_fsops.h"
2324

2425
#include <linux/anon_inodes.h>
2526
#include <linux/eventpoll.h>
@@ -202,6 +203,11 @@ xfs_healthmon_merge_events(
202203
return false;
203204
}
204205
return false;
206+
207+
case XFS_HEALTHMON_SHUTDOWN:
208+
/* yes, we can race to shutdown */
209+
existing->flags |= new->flags;
210+
return true;
205211
}
206212

207213
return false;
@@ -494,6 +500,28 @@ xfs_healthmon_report_inode(
494500
xfs_healthmon_put(hm);
495501
}
496502

503+
/* Add a shutdown event to the reporting queue. */
504+
void
505+
xfs_healthmon_report_shutdown(
506+
struct xfs_mount *mp,
507+
uint32_t flags)
508+
{
509+
struct xfs_healthmon_event event = {
510+
.type = XFS_HEALTHMON_SHUTDOWN,
511+
.domain = XFS_HEALTHMON_MOUNT,
512+
.flags = flags,
513+
};
514+
struct xfs_healthmon *hm = xfs_healthmon_get(mp);
515+
516+
if (!hm)
517+
return;
518+
519+
trace_xfs_healthmon_report_shutdown(hm, flags);
520+
521+
xfs_healthmon_push(hm, &event);
522+
xfs_healthmon_put(hm);
523+
}
524+
497525
static inline void
498526
xfs_healthmon_reset_outbuf(
499527
struct xfs_healthmon *hm)
@@ -502,6 +530,44 @@ xfs_healthmon_reset_outbuf(
502530
hm->bufhead = 0;
503531
}
504532

533+
struct flags_map {
534+
unsigned int in_mask;
535+
unsigned int out_mask;
536+
};
537+
538+
static const struct flags_map shutdown_map[] = {
539+
{ SHUTDOWN_META_IO_ERROR, XFS_HEALTH_SHUTDOWN_META_IO_ERROR },
540+
{ SHUTDOWN_LOG_IO_ERROR, XFS_HEALTH_SHUTDOWN_LOG_IO_ERROR },
541+
{ SHUTDOWN_FORCE_UMOUNT, XFS_HEALTH_SHUTDOWN_FORCE_UMOUNT },
542+
{ SHUTDOWN_CORRUPT_INCORE, XFS_HEALTH_SHUTDOWN_CORRUPT_INCORE },
543+
{ SHUTDOWN_CORRUPT_ONDISK, XFS_HEALTH_SHUTDOWN_CORRUPT_ONDISK },
544+
{ SHUTDOWN_DEVICE_REMOVED, XFS_HEALTH_SHUTDOWN_DEVICE_REMOVED },
545+
};
546+
547+
static inline unsigned int
548+
__map_flags(
549+
const struct flags_map *map,
550+
size_t array_len,
551+
unsigned int flags)
552+
{
553+
const struct flags_map *m;
554+
unsigned int ret = 0;
555+
556+
for (m = map; m < map + array_len; m++) {
557+
if (flags & m->in_mask)
558+
ret |= m->out_mask;
559+
}
560+
561+
return ret;
562+
}
563+
564+
#define map_flags(map, flags) __map_flags((map), ARRAY_SIZE(map), (flags))
565+
566+
static inline unsigned int shutdown_mask(unsigned int in)
567+
{
568+
return map_flags(shutdown_map, in);
569+
}
570+
505571
static const unsigned int domain_map[] = {
506572
[XFS_HEALTHMON_MOUNT] = XFS_HEALTH_MONITOR_DOMAIN_MOUNT,
507573
[XFS_HEALTHMON_FS] = XFS_HEALTH_MONITOR_DOMAIN_FS,
@@ -517,6 +583,7 @@ static const unsigned int type_map[] = {
517583
[XFS_HEALTHMON_CORRUPT] = XFS_HEALTH_MONITOR_TYPE_CORRUPT,
518584
[XFS_HEALTHMON_HEALTHY] = XFS_HEALTH_MONITOR_TYPE_HEALTHY,
519585
[XFS_HEALTHMON_UNMOUNT] = XFS_HEALTH_MONITOR_TYPE_UNMOUNT,
586+
[XFS_HEALTHMON_SHUTDOWN] = XFS_HEALTH_MONITOR_TYPE_SHUTDOWN,
520587
};
521588

522589
/* Render event as a V0 structure */
@@ -545,6 +612,9 @@ xfs_healthmon_format_v0(
545612
case XFS_HEALTHMON_LOST:
546613
hme.e.lost.count = event->lostcount;
547614
break;
615+
case XFS_HEALTHMON_SHUTDOWN:
616+
hme.e.shutdown.reasons = shutdown_mask(event->flags);
617+
break;
548618
default:
549619
break;
550620
}

fs/xfs/xfs_healthmon.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ enum xfs_healthmon_type {
7272
XFS_HEALTHMON_LOST, /* message lost */
7373
XFS_HEALTHMON_UNMOUNT, /* filesystem is unmounting */
7474

75+
/* filesystem shutdown */
76+
XFS_HEALTHMON_SHUTDOWN,
77+
7578
/* metadata health events */
7679
XFS_HEALTHMON_SICK, /* runtime corruption observed */
7780
XFS_HEALTHMON_CORRUPT, /* fsck reported corruption */
@@ -119,6 +122,10 @@ struct xfs_healthmon_event {
119122
uint32_t gen;
120123
xfs_ino_t ino;
121124
};
125+
/* shutdown */
126+
struct {
127+
unsigned int flags;
128+
};
122129
};
123130
};
124131

@@ -132,6 +139,8 @@ void xfs_healthmon_report_inode(struct xfs_inode *ip,
132139
enum xfs_healthmon_type type, unsigned int old_mask,
133140
unsigned int new_mask);
134141

142+
void xfs_healthmon_report_shutdown(struct xfs_mount *mp, uint32_t flags);
143+
135144
long xfs_ioc_health_monitor(struct file *file,
136145
struct xfs_health_monitor __user *arg);
137146

fs/xfs/xfs_trace.h

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6012,7 +6012,8 @@ DEFINE_HEALTHMON_EVENT(xfs_healthmon_report_unmount);
60126012
{ XFS_HEALTHMON_UNMOUNT, "unmount" }, \
60136013
{ XFS_HEALTHMON_SICK, "sick" }, \
60146014
{ XFS_HEALTHMON_CORRUPT, "corrupt" }, \
6015-
{ XFS_HEALTHMON_HEALTHY, "healthy" }
6015+
{ XFS_HEALTHMON_HEALTHY, "healthy" }, \
6016+
{ XFS_HEALTHMON_SHUTDOWN, "shutdown" }
60166017

60176018
#define XFS_HEALTHMON_DOMAIN_STRINGS \
60186019
{ XFS_HEALTHMON_MOUNT, "mount" }, \
@@ -6022,6 +6023,7 @@ DEFINE_HEALTHMON_EVENT(xfs_healthmon_report_unmount);
60226023
{ XFS_HEALTHMON_RTGROUP, "rtgroup" }
60236024

60246025
TRACE_DEFINE_ENUM(XFS_HEALTHMON_LOST);
6026+
TRACE_DEFINE_ENUM(XFS_HEALTHMON_SHUTDOWN);
60256027
TRACE_DEFINE_ENUM(XFS_HEALTHMON_UNMOUNT);
60266028
TRACE_DEFINE_ENUM(XFS_HEALTHMON_SICK);
60276029
TRACE_DEFINE_ENUM(XFS_HEALTHMON_CORRUPT);
@@ -6063,6 +6065,9 @@ DECLARE_EVENT_CLASS(xfs_healthmon_event_class,
60636065
switch (__entry->domain) {
60646066
case XFS_HEALTHMON_MOUNT:
60656067
switch (__entry->type) {
6068+
case XFS_HEALTHMON_SHUTDOWN:
6069+
__entry->mask = event->flags;
6070+
break;
60666071
case XFS_HEALTHMON_LOST:
60676072
__entry->lostcount = event->lostcount;
60686073
break;
@@ -6207,6 +6212,22 @@ TRACE_EVENT(xfs_healthmon_report_inode,
62076212
__entry->gen)
62086213
);
62096214

6215+
TRACE_EVENT(xfs_healthmon_report_shutdown,
6216+
TP_PROTO(const struct xfs_healthmon *hm, uint32_t shutdown_flags),
6217+
TP_ARGS(hm, shutdown_flags),
6218+
TP_STRUCT__entry(
6219+
__field(dev_t, dev)
6220+
__field(uint32_t, shutdown_flags)
6221+
),
6222+
TP_fast_assign(
6223+
__entry->dev = hm->dev;
6224+
__entry->shutdown_flags = shutdown_flags;
6225+
),
6226+
TP_printk("dev %d:%d shutdown_flags %s",
6227+
MAJOR(__entry->dev), MINOR(__entry->dev),
6228+
__print_flags(__entry->shutdown_flags, "|", XFS_SHUTDOWN_STRINGS))
6229+
);
6230+
62106231
#endif /* _TRACE_XFS_H */
62116232

62126233
#undef TRACE_INCLUDE_PATH

0 commit comments

Comments
 (0)