Source kernel commit:
b3a289a2a9397b2e731f334d7d36623a0f9192c5
Create the basic infrastructure that we need to report health events to
userspace. We need a compact form for recording critical information
about an event and queueing them; a means to notice that we've lost some
events; and a means to format the events into something that userspace
can handle. Make the kernel export C structures via read().
In a previous iteration of this new subsystem, I wanted to explore data
exchange formats that are more flexible and easier for humans to read
than C structures. The thought being that when we want to rev (or
worse, enlarge) the event format, it ought to be trivially easy to do
that in a way that doesn't break old userspace.
I looked at formats such as protobufs and capnproto. These look really
nice in that extending the wire format is fairly easy, you can give it a
data schema and it generates the serialization code for you, handles
endianness problems, etc. The huge downside is that neither support C
all that well.
Too hard, and didn't want to port either of those huge sprawling
libraries first to the kernel and then again to xfsprogs. Then I
thought, how about JSON? Javascript objects are human readable, the
kernel can emit json without much fuss (it's all just strings!) and
there are plenty of interpreters for python/rust/c/etc.
There's a proposed schema format for json, which means that xfs can
publish a description of the events that kernel will emit. Userspace
consumers (e.g. xfsprogs/xfs_healer) can embed the same schema document
and use it to validate the incoming events from the kernel, which means
it can discard events that it doesn't understand, or garbage being
emitted due to bugs.
However, json has a huge crutch -- javascript is well known for its
vague definitions of what are numbers. This makes expressing a large
number rather fraught, because the runtime is free to represent a number
in nearly any way it wants. Stupider ones will truncate values to word
size, others will roll out doubles for uint52_t (yes, fifty-two) with
the resulting loss of precision. Not good when you're dealing with
discrete units.
It just so happens that python's json library is smart enough to see a
sequence of digits and put them in a u64 (at least on x86_64/aarch64)
but an actual javascript interpreter (pasting into Firefox) isn't
necessarily so clever.
It turns out that none of the proposed json schemas were ever ratified
even in an open-consensus way, so json blobs are still just loosely
structured blobs. The parsing in userspace was also noticeably slow and
memory-consumptive.
Hence only the C interface survives.
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
#define XFS_RTGROUP_GEOM_SICK_RMAPBT (1U << 3) /* reverse mappings */
#define XFS_RTGROUP_GEOM_SICK_REFCNTBT (1U << 4) /* reference counts */
+/* Health monitor event domains */
+
+/* affects the whole fs */
+#define XFS_HEALTH_MONITOR_DOMAIN_MOUNT (0)
+
+/* Health monitor event types */
+
+/* status of the monitor itself */
+#define XFS_HEALTH_MONITOR_TYPE_RUNNING (0)
+#define XFS_HEALTH_MONITOR_TYPE_LOST (1)
+
+/* lost events */
+struct xfs_health_monitor_lost {
+ __u64 count;
+};
+
+struct xfs_health_monitor_event {
+ /* XFS_HEALTH_MONITOR_DOMAIN_* */
+ __u32 domain;
+
+ /* XFS_HEALTH_MONITOR_TYPE_* */
+ __u32 type;
+
+ /* Timestamp of the event, in nanoseconds since the Unix epoch */
+ __u64 time_ns;
+
+ /*
+ * Details of the event. The primary clients are written in python
+ * and rust, so break this up because bindgen hates anonymous structs
+ * and unions.
+ */
+ union {
+ struct xfs_health_monitor_lost lost;
+ } e;
+
+ /* zeroes */
+ __u64 pad[2];
+};
+
struct xfs_health_monitor {
__u64 flags; /* flags */
__u8 format; /* output format */
__u8 pad[23]; /* zeroes */
};
+/* Return all health status events, not just deltas */
+#define XFS_HEALTH_MONITOR_VERBOSE (1ULL << 0)
+
+#define XFS_HEALTH_MONITOR_ALL (XFS_HEALTH_MONITOR_VERBOSE)
+
+/* Initial return format version */
+#define XFS_HEALTH_MONITOR_FMT_V0 (0)
+
/*
* ioctl commands that are used by Linux filesystems
*/