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+
497525static inline void
498526xfs_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+
505571static 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 }
0 commit comments