mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-20 01:24:39 +08:00
618ee7838e
Add preadn() to provide pread() and readn() semantics. Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> Acked-by: Jiri Olsa <jolsa@kernel.org> Cc: Namhyung Kim <namhyung@kernel.org> Link: https://lore.kernel.org/r/ab8918a4-7ac8-a37e-2e2c-28438c422d87@intel.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
69 lines
1.2 KiB
C
69 lines
1.2 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
#include <unistd.h>
|
|
#include <stdbool.h>
|
|
#include <errno.h>
|
|
#include <linux/kernel.h>
|
|
#include <internal/lib.h>
|
|
|
|
unsigned int page_size;
|
|
|
|
static ssize_t ion(bool is_read, int fd, void *buf, size_t n)
|
|
{
|
|
void *buf_start = buf;
|
|
size_t left = n;
|
|
|
|
while (left) {
|
|
/* buf must be treated as const if !is_read. */
|
|
ssize_t ret = is_read ? read(fd, buf, left) :
|
|
write(fd, buf, left);
|
|
|
|
if (ret < 0 && errno == EINTR)
|
|
continue;
|
|
if (ret <= 0)
|
|
return ret;
|
|
|
|
left -= ret;
|
|
buf += ret;
|
|
}
|
|
|
|
BUG_ON((size_t)(buf - buf_start) != n);
|
|
return n;
|
|
}
|
|
|
|
/*
|
|
* Read exactly 'n' bytes or return an error.
|
|
*/
|
|
ssize_t readn(int fd, void *buf, size_t n)
|
|
{
|
|
return ion(true, fd, buf, n);
|
|
}
|
|
|
|
ssize_t preadn(int fd, void *buf, size_t n, off_t offs)
|
|
{
|
|
size_t left = n;
|
|
|
|
while (left) {
|
|
ssize_t ret = pread(fd, buf, left, offs);
|
|
|
|
if (ret < 0 && errno == EINTR)
|
|
continue;
|
|
if (ret <= 0)
|
|
return ret;
|
|
|
|
left -= ret;
|
|
buf += ret;
|
|
offs += ret;
|
|
}
|
|
|
|
return n;
|
|
}
|
|
|
|
/*
|
|
* Write exactly 'n' bytes or return an error.
|
|
*/
|
|
ssize_t writen(int fd, const void *buf, size_t n)
|
|
{
|
|
/* ion does not modify buf. */
|
|
return ion(false, fd, (void *)buf, n);
|
|
}
|