errseq.c (70a02f840c5113cd9255ce4c1b1848bb48b0bd21) | errseq.c (14ebc28e07e68ff412aa42f7d8b67969e2f63d00) |
---|---|
1// SPDX-License-Identifier: GPL-2.0 2#include <linux/err.h> 3#include <linux/bug.h> 4#include <linux/atomic.h> 5#include <linux/errseq.h> 6 7/* 8 * An errseq_t is a way of recording errors in one place, and allowing any --- 32 unchanged lines hidden (view full) --- 41/* The lowest bit of the counter */ 42#define ERRSEQ_CTR_INC (1 << (ERRSEQ_SHIFT + 1)) 43 44/** 45 * errseq_set - set a errseq_t for later reporting 46 * @eseq: errseq_t field that should be set 47 * @err: error to set (must be between -1 and -MAX_ERRNO) 48 * | 1// SPDX-License-Identifier: GPL-2.0 2#include <linux/err.h> 3#include <linux/bug.h> 4#include <linux/atomic.h> 5#include <linux/errseq.h> 6 7/* 8 * An errseq_t is a way of recording errors in one place, and allowing any --- 32 unchanged lines hidden (view full) --- 41/* The lowest bit of the counter */ 42#define ERRSEQ_CTR_INC (1 << (ERRSEQ_SHIFT + 1)) 43 44/** 45 * errseq_set - set a errseq_t for later reporting 46 * @eseq: errseq_t field that should be set 47 * @err: error to set (must be between -1 and -MAX_ERRNO) 48 * |
49 * This function sets the error in *eseq, and increments the sequence counter | 49 * This function sets the error in @eseq, and increments the sequence counter |
50 * if the last sequence was sampled at some point in the past. 51 * 52 * Any error set will always overwrite an existing error. 53 * | 50 * if the last sequence was sampled at some point in the past. 51 * 52 * Any error set will always overwrite an existing error. 53 * |
54 * We do return the latest value here, primarily for debugging purposes. The 55 * return value should not be used as a previously sampled value in later calls 56 * as it will not have the SEEN flag set. | 54 * Return: The previous value, primarily for debugging purposes. The 55 * return value should not be used as a previously sampled value in later 56 * calls as it will not have the SEEN flag set. |
57 */ 58errseq_t errseq_set(errseq_t *eseq, int err) 59{ 60 errseq_t cur, old; 61 62 /* MAX_ERRNO must be able to serve as a mask */ 63 BUILD_BUG_ON_NOT_POWER_OF_2(MAX_ERRNO + 1); 64 --- 38 unchanged lines hidden (view full) --- 103 /* Raced with an update, try again */ 104 old = cur; 105 } 106 return cur; 107} 108EXPORT_SYMBOL(errseq_set); 109 110/** | 57 */ 58errseq_t errseq_set(errseq_t *eseq, int err) 59{ 60 errseq_t cur, old; 61 62 /* MAX_ERRNO must be able to serve as a mask */ 63 BUILD_BUG_ON_NOT_POWER_OF_2(MAX_ERRNO + 1); 64 --- 38 unchanged lines hidden (view full) --- 103 /* Raced with an update, try again */ 104 old = cur; 105 } 106 return cur; 107} 108EXPORT_SYMBOL(errseq_set); 109 110/** |
111 * errseq_sample - grab current errseq_t value 112 * @eseq: pointer to errseq_t to be sampled | 111 * errseq_sample() - Grab current errseq_t value. 112 * @eseq: Pointer to errseq_t to be sampled. |
113 * 114 * This function allows callers to sample an errseq_t value, marking it as 115 * "seen" if required. | 113 * 114 * This function allows callers to sample an errseq_t value, marking it as 115 * "seen" if required. |
116 * 117 * Return: The current errseq value. |
|
116 */ 117errseq_t errseq_sample(errseq_t *eseq) 118{ 119 errseq_t old = READ_ONCE(*eseq); 120 errseq_t new = old; 121 122 /* 123 * For the common case of no errors ever having been set, we can skip --- 5 unchanged lines hidden (view full) --- 129 if (old != new) 130 cmpxchg(eseq, old, new); 131 } 132 return new; 133} 134EXPORT_SYMBOL(errseq_sample); 135 136/** | 118 */ 119errseq_t errseq_sample(errseq_t *eseq) 120{ 121 errseq_t old = READ_ONCE(*eseq); 122 errseq_t new = old; 123 124 /* 125 * For the common case of no errors ever having been set, we can skip --- 5 unchanged lines hidden (view full) --- 131 if (old != new) 132 cmpxchg(eseq, old, new); 133 } 134 return new; 135} 136EXPORT_SYMBOL(errseq_sample); 137 138/** |
137 * errseq_check - has an error occurred since a particular sample point? 138 * @eseq: pointer to errseq_t value to be checked 139 * @since: previously-sampled errseq_t from which to check | 139 * errseq_check() - Has an error occurred since a particular sample point? 140 * @eseq: Pointer to errseq_t value to be checked. 141 * @since: Previously-sampled errseq_t from which to check. |
140 * | 142 * |
141 * Grab the value that eseq points to, and see if it has changed "since" 142 * the given value was sampled. The "since" value is not advanced, so there | 143 * Grab the value that eseq points to, and see if it has changed @since 144 * the given value was sampled. The @since value is not advanced, so there |
143 * is no need to mark the value as seen. 144 * | 145 * is no need to mark the value as seen. 146 * |
145 * Returns the latest error set in the errseq_t or 0 if it hasn't changed. | 147 * Return: The latest error set in the errseq_t or 0 if it hasn't changed. |
146 */ 147int errseq_check(errseq_t *eseq, errseq_t since) 148{ 149 errseq_t cur = READ_ONCE(*eseq); 150 151 if (likely(cur == since)) 152 return 0; 153 return -(cur & MAX_ERRNO); 154} 155EXPORT_SYMBOL(errseq_check); 156 157/** | 148 */ 149int errseq_check(errseq_t *eseq, errseq_t since) 150{ 151 errseq_t cur = READ_ONCE(*eseq); 152 153 if (likely(cur == since)) 154 return 0; 155 return -(cur & MAX_ERRNO); 156} 157EXPORT_SYMBOL(errseq_check); 158 159/** |
158 * errseq_check_and_advance - check an errseq_t and advance to current value 159 * @eseq: pointer to value being checked and reported 160 * @since: pointer to previously-sampled errseq_t to check against and advance | 160 * errseq_check_and_advance() - Check an errseq_t and advance to current value. 161 * @eseq: Pointer to value being checked and reported. 162 * @since: Pointer to previously-sampled errseq_t to check against and advance. |
161 * | 163 * |
162 * Grab the eseq value, and see whether it matches the value that "since" | 164 * Grab the eseq value, and see whether it matches the value that @since |
163 * points to. If it does, then just return 0. 164 * 165 * If it doesn't, then the value has changed. Set the "seen" flag, and try to 166 * swap it into place as the new eseq value. Then, set that value as the new 167 * "since" value, and return whatever the error portion is set to. 168 * 169 * Note that no locking is provided here for concurrent updates to the "since" 170 * value. The caller must provide that if necessary. Because of this, callers 171 * may want to do a lockless errseq_check before taking the lock and calling 172 * this. | 165 * points to. If it does, then just return 0. 166 * 167 * If it doesn't, then the value has changed. Set the "seen" flag, and try to 168 * swap it into place as the new eseq value. Then, set that value as the new 169 * "since" value, and return whatever the error portion is set to. 170 * 171 * Note that no locking is provided here for concurrent updates to the "since" 172 * value. The caller must provide that if necessary. Because of this, callers 173 * may want to do a lockless errseq_check before taking the lock and calling 174 * this. |
175 * 176 * Return: Negative errno if one has been stored, or 0 if no new error has 177 * occurred. |
|
173 */ 174int errseq_check_and_advance(errseq_t *eseq, errseq_t *since) 175{ 176 int err = 0; 177 errseq_t old, new; 178 179 /* 180 * Most callers will want to use the inline wrapper to check this, --- 26 unchanged lines hidden --- | 178 */ 179int errseq_check_and_advance(errseq_t *eseq, errseq_t *since) 180{ 181 int err = 0; 182 errseq_t old, new; 183 184 /* 185 * Most callers will want to use the inline wrapper to check this, --- 26 unchanged lines hidden --- |