5

As per manpage, readahead is Linux specific:

CONFORMING TO

The readahead() system call is Linux-specific, and its use should be avoided in portable applications.

and posix_fadvise is portable:

CONFORMING TO

POSIX.1-2001, POSIX.1-2008. Note that the type of the len argument was changed from size_t to off_t in POSIX.1-2001 TC1.

But both of them seem to do the same thing. But what are the consequences of exchanging both functions, other than risking portability?

1 Answer 1

10

Let's look at the code that these syscalls cause to be executed.

Citing mm/readahead.c here:

 611   │ ssize_t ksys_readahead(int fd, loff_t offset, size_t count)
 612   │ {
 613   │     ssize_t ret;
 614   │     struct fd f;
 615   │
 616   │     ret = -EBADF;
 617   │     f = fdget(fd);
 618   │     if (!f.file || !(f.file->f_mode & FMODE_READ))
 619   │         goto out;
 620   │
 621   │     /*
 622   │      * The readahead() syscall is intended to run only on files
 623   │      * that can execute readahead. If readahead is not possible
 624   │      * on this file, then we must return -EINVAL.
 625   │      */
 626   │     ret = -EINVAL;
 627   │     if (!f.file->f_mapping || !f.file->f_mapping->a_ops ||
 628   │         !S_ISREG(file_inode(f.file)->i_mode))
 629   │         goto out;
 630   │
 631   │     ret = vfs_fadvise(f.file, offset, count, POSIX_FADV_WILLNEED);
 632   │ out:
 633   │     fdput(f);
 634   │     return ret;
 635   │ }

Note line 631: this thing calls vfs_fadvise(…, POSIX_FADV_WILLNEED) underneath.

Comparing that to mm/fadvise.c:

 192   │ int ksys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice)
 193   │ {
 194   │     struct fd f = fdget(fd);
 195   │     int ret;
 196   │
 197   │     if (!f.file)
 198   │         return -EBADF;
 199   │
 200   │     ret = vfs_fadvise(f.file, offset, len, advice);
 201   │
 202   │     fdput(f);
 203   │     return ret;
 204   │ }

This code also just calls the same vfs_fadvise, so using posix_fadvise64(…, WILLNEED) is functionally the same.

The difference lies (potentially) in the errors reported when the file you use either function on is not suitable: readahead itself checks whether the file is readable, mapped, actually has any useful addressing operations, and returns EBADF or EINVAL if not.
fadvise64, the syscall behind posix_fadvise, directly calls vfs_fadvise, so that this checks for these things internally, and might return different errors. (I haven't checked whether it actually does).

1
  • 5
    The differences in error reporting are real. vfs_fadvise will (at least in the generic implementation) fail with ESPIPE on FIFOs and silently do nothing on unreadable files or those that don't support readahead for any reason.
    – TooTea
    Commented Dec 13, 2021 at 8:08

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .