fs: add fcntl() interface for setting/getting write life time hints
authorJens Axboe <axboe@kernel.dk>
Wed, 21 Jun 2017 00:07:40 +0000 (18:07 -0600)
committerJens Axboe <axboe@kernel.dk>
Wed, 21 Jun 2017 00:07:40 +0000 (18:07 -0600)
commitb2a03ebe185cbd9a1e703e32a5d6878db30d8631
treefaa3a66f1d76cec3227ec7018966b9c366c4be12
parent82f402fefa50f1675bf918bcd009981bd6b30ac8
fs: add fcntl() interface for setting/getting write life time hints

Define a set of write life time hints:

RWH_WRITE_LIFE_NONE No hints about write life time
RWH_WRITE_LIFE_SHORT Data written has a short life time
RWH_WRITE_LIFE_MEDIUM Data written has a medium life time
RWH_WRITE_LIFE_LONG Data written has a long life time
RWH_WRITE_LIFE_EXTREME Data written has an extremely long life tim

The intent is for these values to be relative to each other, no
absolute meaning should be attached to these flag names.

Add an fcntl interface for querying these flags, and also for
setting them as well:

F_GET_RW_HINT Returns the read/write hint set.

F_SET_RW_HINT Pass one of the above write hints.

The user passes in a 64-bit pointer to get/set these values, and
the interface returns 0/-1 on success/error.

Sample program testing/implementing basic setting/getting of write
hints is below.

Add support for storing the write life time hint in the inode flags
and in struct file as well, and pass them to the kiocb flags. If
both a file and its corresponding inode has a write hint, then we
use the one in the file, if available. The file hint can be used
for sync/direct IO, for buffered writeback only the inode hint
is available.

This is in preparation for utilizing these hints in the block layer,
to guide on-media data placement.

/*
 * writehint.c: check or set a file/inode write hint
 */
 #include <stdio.h>
 #include <fcntl.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <stdbool.h>
 #include <inttypes.h>

 #ifndef F_RW_GET_HINT
 #define F_LINUX_SPECIFIC_BASE 1024
 #define F_RW_GET_HINT (F_LINUX_SPECIFIC_BASE + 11)
 #define F_RW_SET_HINT (F_LINUX_SPECIFIC_BASE + 12)
 #endif

static char *str[] = { "WRITE_LIFE_NOT_SET", "WRITE_LIFE_NONE",
"WRITE_LIFE_SHORT", "WRITE_LIFE_MEDIUM",
"WRITE_LIFE_LONG", "WRITE_LIFE_EXTREME" };

int main(int argc, char *argv[])
{
uint64_t hint;
int fd, ret;

if (argc < 2) {
fprintf(stderr, "%s: file <hint>\n", argv[0]);
return 1;
}

fd = open(argv[1], O_RDONLY);
if (fd < 0) {
perror("open");
return 2;
}

if (argc > 2) {
hint = atoi(argv[2]);
ret = fcntl(fd, F_RW_SET_HINT, &hint);
if (ret < 0) {
perror("fcntl: F_RW_SET_HINT");
return 4;
}
}

ret = fcntl(fd, F_RW_GET_HINT, &hint);
if (ret < 0) {
perror("fcntl: F_RW_GET_HINT");
return 3;
}

printf("%s: hint %s\n", argv[1], str[hint]);
close(fd);
return 0;
}

Signed-off-by: Jens Axboe <axboe@kernel.dk>
fs/fcntl.c
fs/inode.c
fs/open.c
include/linux/fs.h
include/uapi/linux/fcntl.h