summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2017-07-06 07:02:24 -0400
committerJeff Layton <jlayton@redhat.com>2017-07-06 07:02:24 -0400
commit84cbadadc6eafc4798513773a2c8fce37dcd2fb8 (patch)
tree0cf2168d471693e85cc39b291df98164338cb2f5 /include
parent5e8fcc1a0ffa0fb794b3c0efa2c3c7612a771c36 (diff)
lib: add errseq_t type and infrastructure for handling it
An errseq_t is a way of recording errors in one place, and allowing any number of "subscribers" to tell whether an error has been set again since a previous time. It's implemented as an unsigned 32-bit value that is managed with atomic operations. The low order bits are designated to hold an error code (max size of MAX_ERRNO). The upper bits are used as a counter. The API works with consumers sampling an errseq_t value at a particular point in time. Later, that value can be used to tell whether new errors have been set since that time. Note that there is a 1 in 512k risk of collisions here if new errors are being recorded frequently, since we have so few bits to use as a counter. To mitigate this, one bit is used as a flag to tell whether the value has been sampled since a new value was recorded. That allows us to avoid bumping the counter if no one has sampled it since it was last bumped. Later patches will build on this infrastructure to change how writeback errors are tracked in the kernel. Signed-off-by: Jeff Layton <jlayton@redhat.com> Reviewed-by: NeilBrown <neilb@suse.com> Reviewed-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'include')
-rw-r--r--include/linux/errseq.h19
1 files changed, 19 insertions, 0 deletions
diff --git a/include/linux/errseq.h b/include/linux/errseq.h
new file mode 100644
index 000000000000..9e0d444ac88d
--- /dev/null
+++ b/include/linux/errseq.h
@@ -0,0 +1,19 @@
+#ifndef _LINUX_ERRSEQ_H
+#define _LINUX_ERRSEQ_H
+
+/* See lib/errseq.c for more info */
+
+typedef u32 errseq_t;
+
+errseq_t __errseq_set(errseq_t *eseq, int err);
+static inline void errseq_set(errseq_t *eseq, int err)
+{
+ /* Optimize for the common case of no error */
+ if (unlikely(err))
+ __errseq_set(eseq, err);
+}
+
+errseq_t errseq_sample(errseq_t *eseq);
+int errseq_check(errseq_t *eseq, errseq_t since);
+int errseq_check_and_advance(errseq_t *eseq, errseq_t *since);
+#endif