^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <linux/bug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <linux/atomic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/errseq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * An errseq_t is a way of recording errors in one place, and allowing any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * number of "subscribers" to tell whether it has changed since a previous
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * point where it was sampled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * It's implemented as an unsigned 32-bit value. The low order bits are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * designated to hold an error code (between 0 and -MAX_ERRNO). The upper bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * are used as a counter. This is done with atomics instead of locking so that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * these functions can be called from any context.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * The general idea is for consumers to sample an errseq_t value. That value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * can later be used to tell whether any new errors have occurred since that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * sampling was done.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * Note that there is a risk of collisions if new errors are being recorded
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * frequently, since we have so few bits to use as a counter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * To mitigate this, one bit is used as a flag to tell whether the value has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * been sampled since a new value was recorded. That allows us to avoid bumping
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * the counter if no one has sampled it since the last time an error was
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * recorded.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * A new errseq_t should always be zeroed out. A errseq_t value of all zeroes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * is the special (but common) case where there has never been an error. An all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * zero value thus serves as the "epoch" if one wishes to know whether there
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * has ever been an error set since it was first initialized.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) /* The low bits are designated for error code (max of MAX_ERRNO) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define ERRSEQ_SHIFT ilog2(MAX_ERRNO + 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) /* This bit is used as a flag to indicate whether the value has been seen */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define ERRSEQ_SEEN (1 << ERRSEQ_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /* The lowest bit of the counter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define ERRSEQ_CTR_INC (1 << (ERRSEQ_SHIFT + 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * errseq_set - set a errseq_t for later reporting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * @eseq: errseq_t field that should be set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * @err: error to set (must be between -1 and -MAX_ERRNO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * This function sets the error in @eseq, and increments the sequence counter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * if the last sequence was sampled at some point in the past.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * Any error set will always overwrite an existing error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * Return: The previous value, primarily for debugging purposes. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * return value should not be used as a previously sampled value in later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * calls as it will not have the SEEN flag set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) errseq_t errseq_set(errseq_t *eseq, int err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) errseq_t cur, old;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) /* MAX_ERRNO must be able to serve as a mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) BUILD_BUG_ON_NOT_POWER_OF_2(MAX_ERRNO + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * Ensure the error code actually fits where we want it to go. If it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * doesn't then just throw a warning and don't record anything. We
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * also don't accept zero here as that would effectively clear a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * previous error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) old = READ_ONCE(*eseq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (WARN(unlikely(err == 0 || (unsigned int)-err > MAX_ERRNO),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) "err = %d\n", err))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return old;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) errseq_t new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /* Clear out error bits and set new error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) new = (old & ~(MAX_ERRNO|ERRSEQ_SEEN)) | -err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) /* Only increment if someone has looked at it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if (old & ERRSEQ_SEEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) new += ERRSEQ_CTR_INC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) /* If there would be no change, then call it done */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (new == old) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) cur = new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) /* Try to swap the new value into place */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) cur = cmpxchg(eseq, old, new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * Call it success if we did the swap or someone else beat us
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * to it for the same value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (likely(cur == old || cur == new))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) /* Raced with an update, try again */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) old = cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) return cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) EXPORT_SYMBOL(errseq_set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * errseq_sample() - Grab current errseq_t value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * @eseq: Pointer to errseq_t to be sampled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * This function allows callers to initialise their errseq_t variable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * If the error has been "seen", new callers will not see an old error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * If there is an unseen error in @eseq, the caller of this function will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * see it the next time it checks for an error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * Context: Any context.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * Return: The current errseq value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) errseq_t errseq_sample(errseq_t *eseq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) errseq_t old = READ_ONCE(*eseq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) /* If nobody has seen this error yet, then we can be the first. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (!(old & ERRSEQ_SEEN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) old = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return old;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) EXPORT_SYMBOL(errseq_sample);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * errseq_check() - Has an error occurred since a particular sample point?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) * @eseq: Pointer to errseq_t value to be checked.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * @since: Previously-sampled errseq_t from which to check.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) * Grab the value that eseq points to, and see if it has changed @since
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) * the given value was sampled. The @since value is not advanced, so there
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * is no need to mark the value as seen.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * Return: The latest error set in the errseq_t or 0 if it hasn't changed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) int errseq_check(errseq_t *eseq, errseq_t since)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) errseq_t cur = READ_ONCE(*eseq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (likely(cur == since))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) return -(cur & MAX_ERRNO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) EXPORT_SYMBOL(errseq_check);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * errseq_check_and_advance() - Check an errseq_t and advance to current value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * @eseq: Pointer to value being checked and reported.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) * @since: Pointer to previously-sampled errseq_t to check against and advance.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * Grab the eseq value, and see whether it matches the value that @since
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * points to. If it does, then just return 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * If it doesn't, then the value has changed. Set the "seen" flag, and try to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) * swap it into place as the new eseq value. Then, set that value as the new
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) * "since" value, and return whatever the error portion is set to.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) * Note that no locking is provided here for concurrent updates to the "since"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * value. The caller must provide that if necessary. Because of this, callers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * may want to do a lockless errseq_check before taking the lock and calling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * this.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * Return: Negative errno if one has been stored, or 0 if no new error has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * occurred.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) int errseq_check_and_advance(errseq_t *eseq, errseq_t *since)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) errseq_t old, new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) * Most callers will want to use the inline wrapper to check this,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) * so that the common case of no error is handled without needing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) * to take the lock that protects the "since" value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) old = READ_ONCE(*eseq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (old != *since) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) * Set the flag and try to swap it into place if it has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) * changed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * We don't care about the outcome of the swap here. If the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) * swap doesn't occur, then it has either been updated by a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) * writer who is altering the value in some way (updating
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * counter or resetting the error), or another reader who is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * just setting the "seen" flag. Either outcome is OK, and we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * can advance "since" and return an error based on what we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * have.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) new = old | ERRSEQ_SEEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if (new != old)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) cmpxchg(eseq, old, new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) *since = new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) err = -(new & MAX_ERRNO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) EXPORT_SYMBOL(errseq_check_and_advance);