fadvise: new module providing a simpler interface to posix_fadvise

* bootstrap.conf: Include the new module
* gl/lib/fadvise.c: Provide a simpler interface to posix_fadvise.
(fadvise): Provide hint to the whole file associated with a stream.
(fdadvise): Provide hint to the specific portion of a file
associated with a file descriptor.
* gl/lib/fadvise.h: Redefine POSIX_FADV_* to FADVISE_* enums.
* gl/modules/fadvise: New file.
* m4/jm-macros.m4: Remove the no longer needed posix_fadvise check.
* .x-sc_program_name: Exclude test-fadvise.c from this check.
* gl/tests/test-fadvise (main): New test program.
* gl/modules/fadvise-testss: A new index to reference the tests.
* src/sort.c (stream_open): Use the new interface.
* src/dd.c (iwrite): Likewise.
This commit is contained in:
Pádraig Brady 2010-07-14 09:49:16 +01:00
parent c88cfffb6c
commit 63b5e81648
9 changed files with 188 additions and 28 deletions

View File

@ -1,3 +1,4 @@
gl/lib/randint.c
lib/euidaccess-stat.c
gl/tests/test-mbsalign.c
gl/tests/test-fadvise.c

View File

@ -81,6 +81,7 @@ gnulib_modules="
exclude
exitfail
faccessat
fadvise
fchdir
fcntl
fcntl-safer

37
gl/lib/fadvise.c Normal file
View File

@ -0,0 +1,37 @@
/* Declare an access pattern hint for files.
Copyright (C) 2010 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include "fadvise.h"
#include <stdio.h>
#include <fcntl.h>
#include "ignore-value.h"
void
fdadvise (int fd, off_t offset, off_t len, fadvice_t advice)
{
#if HAVE_POSIX_FADVISE
ignore_value (posix_fadvise (fd, offset, len, advice));
#endif
}
void
fadvise (FILE *fp, fadvice_t advice)
{
if (fp)
fdadvise (fileno (fp), 0, 0, advice);
}

72
gl/lib/fadvise.h Normal file
View File

@ -0,0 +1,72 @@
/* Declare an access pattern hint for files.
Copyright (C) 2010 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
/* There are a few hints one can provide, which have the
following characteristics on Linux 2.6.31 at least.
POSIX_FADV_SEQUENTIAL
Doubles the size of read ahead done for file
POSIX_FADV_WILLNEED
_synchronously_ prepopulate the buffer cache with the file
POSIX_FADV_NOREUSE
Could lower priority of data in buffer caches,
but currently does nothing.
POSIX_FADV_DONTNEED
Drop the file from cache.
Note this is automatically done when files are unlinked.
We use this enum "type" both to make it explicit that
these options are mutually exclusive, and to discourage
the passing of the possibly undefined POSIX_FADV_... values.
Note we could #undef the POSIX_FADV_ values, but that would
preclude using the posix_fadvise() function with its standard
constants. Using posix_fadvise() might be required if the return
value is needed, but it must be guarded by appropriate #ifdefs. */
#if HAVE_POSIX_FADVISE
typedef enum {
FADVISE_NORMAL = POSIX_FADV_NORMAL,
FADVISE_SEQUENTIAL = POSIX_FADV_SEQUENTIAL,
FADVISE_NOREUSE = POSIX_FADV_NOREUSE,
FADVISE_DONTNEED = POSIX_FADV_DONTNEED,
FADVISE_WILLNEED = POSIX_FADV_WILLNEED,
FADVISE_RANDOM = POSIX_FADV_RANDOM,
} fadvice_t;
#else
typedef enum {
FADVISE_NORMAL,
FADVISE_SEQUENTIAL,
FADVISE_NOREUSE,
FADVISE_DONTNEED,
FADVISE_WILLNEED,
FADVISE_RANDOM,
} fadvice_t;
#endif
/* We ignore any errors as these hints are only advisory.
There is the chance one can pass invalid ADVICE, which will
not be indicated, but given the simplicity of the interface
this is unlikely. Also not returning errors allows the
unconditional passing of descriptors to non standard files,
which will just be ignored if unsupported. */
void fdadvise (int fd, off_t offset, off_t len, fadvice_t advice);
void fadvise (FILE *fp, fadvice_t advice);

24
gl/modules/fadvise Normal file
View File

@ -0,0 +1,24 @@
Description:
Declare an access pattern hint for files.
Files:
lib/fadvise.c
lib/fadvise.h
Depends-on:
ignore-value
configure.ac:
AC_CHECK_FUNCS_ONCE([posix_fadvise])
Makefile.am:
lib_SOURCES += fadvise.c fadvise.h
Include:
"fadvise.h"
License:
LGPL
Maintainer:
Pádraig Brady

43
gl/tests/test-fadvise.c Normal file
View File

@ -0,0 +1,43 @@
/* Test that fadvise works as advertised.
Copyright (C) 2010 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* Written by Pádraig Brady. */
#include <config.h>
#include <stdio.h>
#include "fadvise.h"
int
main (void)
{
/* Valid. */
fadvise (stdin, FADVISE_SEQUENTIAL);
fdadvise (fileno (stdin), 0, 0, FADVISE_RANDOM);
/* Ignored. */
fadvise (NULL, FADVISE_RANDOM);
/* Invalid. */
fdadvise (42, 0, 0, FADVISE_RANDOM);
/* Unfortunately C enums are not types.
One could hack type safety by wrapping in a struct,
but it's probably not worth the complexity in this case. */
fadvise (stdin, FADVISE_SEQUENTIAL + FADVISE_RANDOM);
fadvise (stdin, 4242);
return 0;
}

View File

@ -64,7 +64,6 @@ AC_DEFUN([coreutils_MACROS],
LIBS=$coreutils_saved_libs
# Used by sort.c.
AC_CHECK_FUNCS_ONCE([posix_fadvise])
AC_CHECK_FUNCS_ONCE([nl_langinfo])
# Used by tail.c.

View File

@ -27,10 +27,10 @@
#include "system.h"
#include "close-stream.h"
#include "error.h"
#include "fadvise.h"
#include "fd-reopen.h"
#include "gethrxtime.h"
#include "human.h"
#include "ignore-value.h"
#include "long-options.h"
#include "quote.h"
#include "quotearg.h"
@ -849,12 +849,9 @@ iwrite (int fd, char const *buf, size_t size)
posix_fadvise to tell the system not to pollute the buffer
cache with this data. Don't bother to diagnose lseek or
posix_fadvise failure. */
#ifdef POSIX_FADV_DONTNEED
off_t off = lseek (STDOUT_FILENO, 0, SEEK_CUR);
if (0 <= off)
ignore_value (posix_fadvise (STDOUT_FILENO,
off, 0, POSIX_FADV_DONTNEED));
#endif
fdadvise (STDOUT_FILENO, off, 0, FADVISE_DONTNEED);
/* Attempt to ensure that that final block is committed
to disk as quickly as possible. */

View File

@ -30,11 +30,11 @@
#include "system.h"
#include "argmatch.h"
#include "error.h"
#include "fadvise.h"
#include "filevercmp.h"
#include "hard-locale.h"
#include "hash.h"
#include "heap.h"
#include "ignore-value.h"
#include "md5.h"
#include "mbswidth.h"
#include "nproc.h"
@ -856,9 +856,13 @@ create_temp_file (int *pfd, bool survive_fd_exhaustion)
return node;
}
/* Predeclare an access pattern for input files.
Ignore any errors -- this is only advisory.
/* Return a stream for FILE, opened with mode HOW. A null FILE means
standard output; HOW should be "w". When opening for input, "-"
means standard input. To avoid confusion, do not return file
descriptors STDIN_FILENO, STDOUT_FILENO, or STDERR_FILENO when
opening an ordinary FILE. Return NULL if unsuccessful.
fadvise() is used to specify an access pattern for input files.
There are a few hints we could possibly provide,
and after careful testing it was decided that
specifying POSIX_FADV_SEQUENTIAL was not detrimental
@ -899,24 +903,6 @@ create_temp_file (int *pfd, bool survive_fd_exhaustion)
cache immediately after processing. This is done implicitly
however when the files are unlinked. */
static void
fadvise_input (FILE *fp)
{
#if HAVE_POSIX_FADVISE
if (fp)
{
int fd = fileno (fp);
ignore_value (posix_fadvise (fd, 0, 0, POSIX_FADV_SEQUENTIAL));
}
#endif
}
/* Return a stream for FILE, opened with mode HOW. A null FILE means
standard output; HOW should be "w". When opening for input, "-"
means standard input. To avoid confusion, do not return file
descriptors STDIN_FILENO, STDOUT_FILENO, or STDERR_FILENO when
opening an ordinary FILE. Return NULL if unsuccessful. */
static FILE *
stream_open (const char *file, const char *how)
{
@ -932,7 +918,7 @@ stream_open (const char *file, const char *how)
}
else
fp = fopen (file, how);
fadvise_input (fp);
fadvise (fp, FADVISE_SEQUENTIAL);
return fp;
}
return fopen (file, how);