Understanding of is_err () functions in Linux

Source: Internet
Author: User

From http://jimmy-lee.blog.hexun.com/6075934_d.html

And http://blog.chinaunix.net/u3/97568/showart_1978276.html. Thank you for sharing.

In the FS section of Linux source code, such a function (located in kernel/include/Linux/fs. h) is often encountered ):

/*
* Kernel pointers have redundant information, so we can use
* Scheme where we can return either an error code or a dentry
* Pointer with the same return value.
*
* This shoshould be a per-architecture thing, to allow different
* Error and pointer decisions.
*/
Static inline void * err_ptr (long error)
{
Return (void *) error;
}

Static inline long ptr_err (const void * PTR)
{
Return (long) PTR;
}

Static inline long is_err (const void * PTR)
{
Return (unsigned long) PTR> (unsigned long)-1000l;
}

The following is my understanding of the is_err function, which is not completely correct. If you have any mistakes, please let me know.

In the is_err () function (unsigned long)-1000l, it actually represents 0xfffff000 (because the negative number is the complement of the original code in the computer). in Linux, the virtual memory space is allocated, 0 ~ 3G is for the user space, while 3G ~ 4G is for the Linux kernel, while 0xfffff000 is located in the virtual memory space of the Linux kernel. The size from 0xfffff000 to 4G is only 4 kb, which is actually the size of a page_size, in this case, if a pointer is located in the 4 kb area, the pointer cannot be the first address of a page because it is not enough to allocate a page.

The top 4 kb of the kernel virtual space is generally not used as the allocation space. (I did not find the exact evidence, but I thought this space was retained according to the subsequent analysis. Its address range is used for incorrect judgment ).

If the parameter passed to the is_err () function is the first address pointer of a page, it must be an error pointer.
Is_err () can also be used to detect an error code, which is used with err_ptr (). See the following code: (kernel/fs/namespace. c/sys_mount ())

Asmlinkage long sys_mount (char * dev_name, char * dir_name, char * type,
Unsigned long flags, void * Data)
{
Int retval;
....
Char * dir_page;
....

Dir_page = getname (dir_name );
Retval = ptr_err (dir_page );
If (is_err (dir_page ))
Goto out1;

....
}

Getname () returns the first address of an allocated page or err_ptr (-enomem) due to insufficient memory, then, the pointer type address is converted into an integer through ptr_err (), and is_err () is used to determine whether it is a valid first page address, which is the same as the previous analysis.
Next, let's take a look at the returned error code. enomem is in the kernel/include/ASM-*/error. the value defined in H is 12, and the returned value through err_ptr (-enomem) is a pointer type, pointing to 0xfffff4. In terms of pointers, it points to the top 4 kb space of the virtual kernel space, then, is_err () is used to determine whether the returned value is false.

In Linux, the error code errcode value ranges from 1 ~??, This ?? It is unlikely that it is larger than 4 kb. Therefore, through err_ptr (-errcode), The top4kb (0xfffff000 ~) mapped to the virtual kernel space is ~ 4G), and then through is_err (), we can detect "is error "!

In conclusion, is_err () can detect whether the first address of the page is valid or error codes.

 

Is_err () has some advantages.
Functions in the kernel often return pointers. The problem is that if an error occurs, the returned pointer is also expected to be used.
Fortunately, the pointer returned by the kernel generally points to the page boundary (4 K boundary), that is

PTR & 0 xfff = 0

In this way, the PTR value cannot fall between (0xfffff000, 0 xffffffff,
In general, the kernel error code is also a small negative number, which is converted into unsigned long between-1000 and 0,
It is exactly between (0xfffff000, 0 xffffffff. Therefore, you can use

(Unsigned long) PTR> (unsigned long)-1000l

To determine whether the return value of the kernel function is a valid pointer or an error code.

There must be three situations for any pointer involved: Valid pointer, null pointer, error pointer, or invalid pointer. the so-called error pointer means that it has reached the last page. for example, for a 32-bit system, if the maximum kernel space address is 0 xffffffff, the last page is 0xfffff000 ~ 0 xffffffff (assume that 4 K is a page). This address is retained. If it exceeds this address, it is definitely incorrect.
In the Linux kernel, there are multiple possible errors:
Include/ASM-generic/errno-base.h file:

# Define eperm 1/* operation not permitted */

# Define enoent 2/* no such file or directory */

# Define esrch 3/* no such process */

# Define eintr 4/* interrupted system call */

# Define EIO 5/* I/O Error */

# Define enxio 6/* no such device or address */

# Define e2big 7/* argument list too long */

# Define enoexec 8/* exec format Error */

# Define ebadf 9/* Bad file number */

# Define echild 10/* No Child processes */

# Define eagain 11/* try again */

# Define enomem 12/* out of memory */

# Define eacces 13/* permission denied */

# Define efault 14/* Bad address */

# Define enotblk 15/* block device required */

# Define ebusy 16/* device or resource busy */

# Define eexist 17/* file exists */

# Define exdev 18/* cross-device link */

# Define enodev 19/* no such device */

# Define enotdir 20/* not a directory */

# Define eisdir 21/* is a directory */

# Define einval 22/* invalid argument */

# Define enfile 23/* file table overflow */

# Define emfile 24/* too program open files */

# Define enotty 25/* not a typewriter */

# Define etxtbsy 26/* Text File busy */

# Define efbig 27/* file too large */

# Define enospc 28/* no space left on device */

# Define espipe 29/* illegal seek */

# Define erofs 30/* read-only file system */

# Define emlink 31/* too worker links */

# Define epipe 32/* broken pipe */

# Define Edom 33/* Math argument out of domain of func */

# Define erange 34/* Math result not representable */

When an error occurs, the returned values are-ebusy,-einval,-enodev,-epipe,-eagain,-enomem, and so on. We can see that this value is actually in-1000 ~ Between 0.

For a function that returns a pointer, we usually return NULL to indicate a failure, but this cannot indicate the failure (insufficient memory? Hardware error or network inaccessible ?)
Therefore, you can use err_ptr (-enome) to determine the returned value, because this pointer is obviously invalid.
See include/iinux/err. h

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.