2121#include "xfs_health.h"
2222#include "xfs_healthmon.h"
2323#include "xfs_fsops.h"
24+ #include "xfs_notify_failure.h"
2425
2526#include <linux/anon_inodes.h>
2627#include <linux/eventpoll.h>
@@ -208,6 +209,19 @@ xfs_healthmon_merge_events(
208209 /* yes, we can race to shutdown */
209210 existing -> flags |= new -> flags ;
210211 return true;
212+
213+ case XFS_HEALTHMON_MEDIA_ERROR :
214+ /* physically adjacent errors can merge */
215+ if (existing -> daddr + existing -> bbcount == new -> daddr ) {
216+ existing -> bbcount += new -> bbcount ;
217+ return true;
218+ }
219+ if (new -> daddr + new -> bbcount == existing -> daddr ) {
220+ existing -> daddr = new -> daddr ;
221+ existing -> bbcount += new -> bbcount ;
222+ return true;
223+ }
224+ return false;
211225 }
212226
213227 return false;
@@ -522,6 +536,48 @@ xfs_healthmon_report_shutdown(
522536 xfs_healthmon_put (hm );
523537}
524538
539+ static inline enum xfs_healthmon_domain
540+ media_error_domain (
541+ enum xfs_device fdev )
542+ {
543+ switch (fdev ) {
544+ case XFS_DEV_DATA :
545+ return XFS_HEALTHMON_DATADEV ;
546+ case XFS_DEV_LOG :
547+ return XFS_HEALTHMON_LOGDEV ;
548+ case XFS_DEV_RT :
549+ return XFS_HEALTHMON_RTDEV ;
550+ }
551+
552+ ASSERT (0 );
553+ return 0 ;
554+ }
555+
556+ /* Add a media error event to the reporting queue. */
557+ void
558+ xfs_healthmon_report_media (
559+ struct xfs_mount * mp ,
560+ enum xfs_device fdev ,
561+ xfs_daddr_t daddr ,
562+ uint64_t bbcount )
563+ {
564+ struct xfs_healthmon_event event = {
565+ .type = XFS_HEALTHMON_MEDIA_ERROR ,
566+ .domain = media_error_domain (fdev ),
567+ .daddr = daddr ,
568+ .bbcount = bbcount ,
569+ };
570+ struct xfs_healthmon * hm = xfs_healthmon_get (mp );
571+
572+ if (!hm )
573+ return ;
574+
575+ trace_xfs_healthmon_report_media (hm , fdev , & event );
576+
577+ xfs_healthmon_push (hm , & event );
578+ xfs_healthmon_put (hm );
579+ }
580+
525581static inline void
526582xfs_healthmon_reset_outbuf (
527583 struct xfs_healthmon * hm )
@@ -574,6 +630,9 @@ static const unsigned int domain_map[] = {
574630 [XFS_HEALTHMON_AG ] = XFS_HEALTH_MONITOR_DOMAIN_AG ,
575631 [XFS_HEALTHMON_INODE ] = XFS_HEALTH_MONITOR_DOMAIN_INODE ,
576632 [XFS_HEALTHMON_RTGROUP ] = XFS_HEALTH_MONITOR_DOMAIN_RTGROUP ,
633+ [XFS_HEALTHMON_DATADEV ] = XFS_HEALTH_MONITOR_DOMAIN_DATADEV ,
634+ [XFS_HEALTHMON_RTDEV ] = XFS_HEALTH_MONITOR_DOMAIN_RTDEV ,
635+ [XFS_HEALTHMON_LOGDEV ] = XFS_HEALTH_MONITOR_DOMAIN_LOGDEV ,
577636};
578637
579638static const unsigned int type_map [] = {
@@ -584,6 +643,7 @@ static const unsigned int type_map[] = {
584643 [XFS_HEALTHMON_HEALTHY ] = XFS_HEALTH_MONITOR_TYPE_HEALTHY ,
585644 [XFS_HEALTHMON_UNMOUNT ] = XFS_HEALTH_MONITOR_TYPE_UNMOUNT ,
586645 [XFS_HEALTHMON_SHUTDOWN ] = XFS_HEALTH_MONITOR_TYPE_SHUTDOWN ,
646+ [XFS_HEALTHMON_MEDIA_ERROR ] = XFS_HEALTH_MONITOR_TYPE_MEDIA_ERROR ,
587647};
588648
589649/* Render event as a V0 structure */
@@ -635,6 +695,12 @@ xfs_healthmon_format_v0(
635695 hme .e .inode .ino = event -> ino ;
636696 hme .e .inode .gen = event -> gen ;
637697 break ;
698+ case XFS_HEALTHMON_DATADEV :
699+ case XFS_HEALTHMON_LOGDEV :
700+ case XFS_HEALTHMON_RTDEV :
701+ hme .e .media .daddr = event -> daddr ;
702+ hme .e .media .bbcount = event -> bbcount ;
703+ break ;
638704 default :
639705 break ;
640706 }
0 commit comments