summaryrefslogtreecommitdiffstats
path: root/include/linux/fs.h
diff options
context:
space:
mode:
authorJens Axboe <axboe@kernel.dk>2017-06-27 13:47:04 -0400
committerJens Axboe <axboe@kernel.dk>2017-06-27 14:05:22 -0400
commitc75b1d9421f80f4143e389d2d50ddfc8a28c8c35 (patch)
tree6fe665d5e9f8cfab50b764d418e732617a5d5129 /include/linux/fs.h
parent12e9a6d62236dacb87a6b2dd84dd9c29bb5be1de (diff)
fs: add fcntl() interface for setting/getting write life time hints
Define a set of write life time hints: RWH_WRITE_LIFE_NOT_SET No hint information set 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 time 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 on the underlying inode. F_SET_RW_HINT Set one of the above write hints on the underlying inode. F_GET_FILE_RW_HINT Returns the read/write hint set on the file descriptor. F_SET_FILE_RW_HINT Set one of the above write hints on the file descriptor. 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: get or set an inode write hint */ #include <stdio.h> #include <fcntl.h> #include <stdlib.h> #include <unistd.h> #include <stdbool.h> #include <inttypes.h> #ifndef F_GET_RW_HINT #define F_LINUX_SPECIFIC_BASE 1024 #define F_GET_RW_HINT (F_LINUX_SPECIFIC_BASE + 11) #define F_SET_RW_HINT (F_LINUX_SPECIFIC_BASE + 12) #endif static char *str[] = { "RWF_WRITE_LIFE_NOT_SET", "RWH_WRITE_LIFE_NONE", "RWH_WRITE_LIFE_SHORT", "RWH_WRITE_LIFE_MEDIUM", "RWH_WRITE_LIFE_LONG", "RWH_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_SET_RW_HINT, &hint); if (ret < 0) { perror("fcntl: F_SET_RW_HINT"); return 4; } } ret = fcntl(fd, F_GET_RW_HINT, &hint); if (ret < 0) { perror("fcntl: F_GET_RW_HINT"); return 3; } printf("%s: hint %s\n", argv[1], str[hint]); close(fd); return 0; } Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'include/linux/fs.h')
-rw-r--r--include/linux/fs.h47
1 files changed, 35 insertions, 12 deletions
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 4574121f4746..65adbddb3163 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -20,6 +20,7 @@
20#include <linux/rwsem.h> 20#include <linux/rwsem.h>
21#include <linux/capability.h> 21#include <linux/capability.h>
22#include <linux/semaphore.h> 22#include <linux/semaphore.h>
23#include <linux/fcntl.h>
23#include <linux/fiemap.h> 24#include <linux/fiemap.h>
24#include <linux/rculist_bl.h> 25#include <linux/rculist_bl.h>
25#include <linux/atomic.h> 26#include <linux/atomic.h>
@@ -265,6 +266,18 @@ struct page;
265struct address_space; 266struct address_space;
266struct writeback_control; 267struct writeback_control;
267 268
269/*
270 * Write life time hint values.
271 */
272enum rw_hint {
273 WRITE_LIFE_NOT_SET = 0,
274 WRITE_LIFE_NONE = RWH_WRITE_LIFE_NONE,
275 WRITE_LIFE_SHORT = RWH_WRITE_LIFE_SHORT,
276 WRITE_LIFE_MEDIUM = RWH_WRITE_LIFE_MEDIUM,
277 WRITE_LIFE_LONG = RWH_WRITE_LIFE_LONG,
278 WRITE_LIFE_EXTREME = RWH_WRITE_LIFE_EXTREME,
279};
280
268#define IOCB_EVENTFD (1 << 0) 281#define IOCB_EVENTFD (1 << 0)
269#define IOCB_APPEND (1 << 1) 282#define IOCB_APPEND (1 << 1)
270#define IOCB_DIRECT (1 << 2) 283#define IOCB_DIRECT (1 << 2)
@@ -280,6 +293,7 @@ struct kiocb {
280 void (*ki_complete)(struct kiocb *iocb, long ret, long ret2); 293 void (*ki_complete)(struct kiocb *iocb, long ret, long ret2);
281 void *private; 294 void *private;
282 int ki_flags; 295 int ki_flags;
296 enum rw_hint ki_hint;
283}; 297};
284 298
285static inline bool is_sync_kiocb(struct kiocb *kiocb) 299static inline bool is_sync_kiocb(struct kiocb *kiocb)
@@ -287,16 +301,6 @@ static inline bool is_sync_kiocb(struct kiocb *kiocb)
287 return kiocb->ki_complete == NULL; 301 return kiocb->ki_complete == NULL;
288} 302}
289 303
290static inline int iocb_flags(struct file *file);
291
292static inline void init_sync_kiocb(struct kiocb *kiocb, struct file *filp)
293{
294 *kiocb = (struct kiocb) {
295 .ki_filp = filp,
296 .ki_flags = iocb_flags(filp),
297 };
298}
299
300/* 304/*
301 * "descriptor" for what we're up to with a read. 305 * "descriptor" for what we're up to with a read.
302 * This allows us to use the same read code yet 306 * This allows us to use the same read code yet
@@ -597,6 +601,7 @@ struct inode {
597 spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */ 601 spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */
598 unsigned short i_bytes; 602 unsigned short i_bytes;
599 unsigned int i_blkbits; 603 unsigned int i_blkbits;
604 enum rw_hint i_write_hint;
600 blkcnt_t i_blocks; 605 blkcnt_t i_blocks;
601 606
602#ifdef __NEED_I_SIZE_ORDERED 607#ifdef __NEED_I_SIZE_ORDERED
@@ -851,6 +856,7 @@ struct file {
851 * Must not be taken from IRQ context. 856 * Must not be taken from IRQ context.
852 */ 857 */
853 spinlock_t f_lock; 858 spinlock_t f_lock;
859 enum rw_hint f_write_hint;
854 atomic_long_t f_count; 860 atomic_long_t f_count;
855 unsigned int f_flags; 861 unsigned int f_flags;
856 fmode_t f_mode; 862 fmode_t f_mode;
@@ -1026,8 +1032,6 @@ struct file_lock_context {
1026#define OFFT_OFFSET_MAX INT_LIMIT(off_t) 1032#define OFFT_OFFSET_MAX INT_LIMIT(off_t)
1027#endif 1033#endif
1028 1034
1029#include <linux/fcntl.h>
1030
1031extern void send_sigio(struct fown_struct *fown, int fd, int band); 1035extern void send_sigio(struct fown_struct *fown, int fd, int band);
1032 1036
1033/* 1037/*
@@ -1878,6 +1882,25 @@ static inline bool HAS_UNMAPPED_ID(struct inode *inode)
1878 return !uid_valid(inode->i_uid) || !gid_valid(inode->i_gid); 1882 return !uid_valid(inode->i_uid) || !gid_valid(inode->i_gid);
1879} 1883}
1880 1884
1885static inline enum rw_hint file_write_hint(struct file *file)
1886{
1887 if (file->f_write_hint != WRITE_LIFE_NOT_SET)
1888 return file->f_write_hint;
1889
1890 return file_inode(file)->i_write_hint;
1891}
1892
1893static inline int iocb_flags(struct file *file);
1894
1895static inline void init_sync_kiocb(struct kiocb *kiocb, struct file *filp)
1896{
1897 *kiocb = (struct kiocb) {
1898 .ki_filp = filp,
1899 .ki_flags = iocb_flags(filp),
1900 .ki_hint = file_write_hint(filp),
1901 };
1902}
1903
1881/* 1904/*
1882 * Inode state bits. Protected by inode->i_lock 1905 * Inode state bits. Protected by inode->i_lock
1883 * 1906 *