Linux Kernel Code Error Checking


In Linux user space programming, functions often return integers with the convention that a return value of 0 indicates success of a call to the function and that different (usually negative) non-zero values are used to indicate different errors. In kernel programming, however, many functions may return pointers instead of integers, which complicates this approach since a pointer may use non-zero values to encode valid memory addresses that are returned as the result of a successful call to a function.

Linux addresses this challenge by exploiting the facts that (1) the upper portions of the range of valid (virtual) addresses are unused, and (2) the use of negative values to indicate errors will make their higher order bits non-zero whether they're returned as pointers or integers, and then (3) providing a useful macro and inline functions in the include/linux/err.h file that can handle different combinations of pointer, integer, and Boolean types, in a portable manner that works across different hardware architectures:

The IS_ERR_VALUE macro checks whether the upper range of a (pointer or integer) value is non-empty (i.e., contains an error value).

The ERR_PTR function converts a (long) integer value into a (void *) pointer value.

The PTR_ERR function converts a (const void *) pointer value into a (long) integer value.

The IS_ERR function converts a (const void *) pointer value into an (unsigned long) integer value, uses the IS_ERR_VALUE macro to check whether the upper range of the value is non-empty (i.e., contains an error value), and returns a bool value accordingly.

The IS_ERR_OR_NULL function returns a bool value that is true if (1) the passed (const void *) pointer value is 0 or (2) the result of converting it into an (unsigned long) integer value and then using the IS_ERR_VALUE macro on it indicates that the upper range of the value is non-empty (i.e., contains an error value).

The ERR_CAST function converts a (const void *) pointer into a (void *) pointer (casting away constness).

The PTR_ERR_OR_ZERO function uses the IS_ERR function to check whether the passed (const void *) pointer value contains an error, and returns an (int) integer value that is 0 if it does not, or is the error value obtained by calling the PTR_ERR function with it if it does.