Commit 02a1335f authored by Jaegeuk Kim's avatar Jaegeuk Kim

f2fs: support volatile operations for transient data

This patch adds support for volatile writes which keep data pages in memory
until f2fs_evict_inode is called by iput.

For instance, we can use this feature for the sqlite database as follows.
While supporting atomic writes for main database file, we can keep its journal
data temporarily in the page cache by the following sequence.

1. open
 -> ioctl(F2FS_IOC_START_VOLATILE_WRITE);
2. writes
 : keep all the data in the page cache.
3. flush to the database file with atomic writes
  a. ioctl(F2FS_IOC_START_ATOMIC_WRITE);
  b. writes
  c. ioctl(F2FS_IOC_COMMIT_ATOMIC_WRITE);
4. close
 -> drop the cached data
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent 88b88a66
...@@ -1052,7 +1052,7 @@ static int f2fs_write_end(struct file *file, ...@@ -1052,7 +1052,7 @@ static int f2fs_write_end(struct file *file,
trace_f2fs_write_end(inode, pos, len, copied); trace_f2fs_write_end(inode, pos, len, copied);
if (f2fs_is_atomic_file(inode)) if (f2fs_is_atomic_file(inode) || f2fs_is_volatile_file(inode))
register_inmem_page(inode, page); register_inmem_page(inode, page);
else else
set_page_dirty(page); set_page_dirty(page);
......
...@@ -198,6 +198,7 @@ static inline bool __has_cursum_space(struct f2fs_summary_block *sum, int size, ...@@ -198,6 +198,7 @@ static inline bool __has_cursum_space(struct f2fs_summary_block *sum, int size,
#define F2FS_IOCTL_MAGIC 0xf5 #define F2FS_IOCTL_MAGIC 0xf5
#define F2FS_IOC_START_ATOMIC_WRITE _IO(F2FS_IOCTL_MAGIC, 1) #define F2FS_IOC_START_ATOMIC_WRITE _IO(F2FS_IOCTL_MAGIC, 1)
#define F2FS_IOC_COMMIT_ATOMIC_WRITE _IO(F2FS_IOCTL_MAGIC, 2) #define F2FS_IOC_COMMIT_ATOMIC_WRITE _IO(F2FS_IOCTL_MAGIC, 2)
#define F2FS_IOC_START_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 3)
#if defined(__KERNEL__) && defined(CONFIG_COMPAT) #if defined(__KERNEL__) && defined(CONFIG_COMPAT)
/* /*
...@@ -1060,6 +1061,7 @@ enum { ...@@ -1060,6 +1061,7 @@ enum {
FI_UPDATE_WRITE, /* inode has in-place-update data */ FI_UPDATE_WRITE, /* inode has in-place-update data */
FI_NEED_IPU, /* used for ipu per file */ FI_NEED_IPU, /* used for ipu per file */
FI_ATOMIC_FILE, /* indicate atomic file */ FI_ATOMIC_FILE, /* indicate atomic file */
FI_VOLATILE_FILE, /* indicate volatile file */
}; };
static inline void set_inode_flag(struct f2fs_inode_info *fi, int flag) static inline void set_inode_flag(struct f2fs_inode_info *fi, int flag)
...@@ -1151,6 +1153,11 @@ static inline bool f2fs_is_atomic_file(struct inode *inode) ...@@ -1151,6 +1153,11 @@ static inline bool f2fs_is_atomic_file(struct inode *inode)
return is_inode_flag_set(F2FS_I(inode), FI_ATOMIC_FILE); return is_inode_flag_set(F2FS_I(inode), FI_ATOMIC_FILE);
} }
static inline bool f2fs_is_volatile_file(struct inode *inode)
{
return is_inode_flag_set(F2FS_I(inode), FI_VOLATILE_FILE);
}
static inline void *inline_data_addr(struct page *page) static inline void *inline_data_addr(struct page *page)
{ {
struct f2fs_inode *ri = F2FS_INODE(page); struct f2fs_inode *ri = F2FS_INODE(page);
......
...@@ -885,6 +885,9 @@ static int f2fs_ioc_commit_atomic_write(struct file *filp) ...@@ -885,6 +885,9 @@ static int f2fs_ioc_commit_atomic_write(struct file *filp)
if (!inode_owner_or_capable(inode)) if (!inode_owner_or_capable(inode))
return -EACCES; return -EACCES;
if (f2fs_is_volatile_file(inode))
return 0;
ret = mnt_want_write_file(filp); ret = mnt_want_write_file(filp);
if (ret) if (ret)
return ret; return ret;
...@@ -897,6 +900,17 @@ static int f2fs_ioc_commit_atomic_write(struct file *filp) ...@@ -897,6 +900,17 @@ static int f2fs_ioc_commit_atomic_write(struct file *filp)
return ret; return ret;
} }
static int f2fs_ioc_start_volatile_write(struct file *filp)
{
struct inode *inode = file_inode(filp);
if (!inode_owner_or_capable(inode))
return -EACCES;
set_inode_flag(F2FS_I(inode), FI_VOLATILE_FILE);
return 0;
}
static int f2fs_ioc_fitrim(struct file *filp, unsigned long arg) static int f2fs_ioc_fitrim(struct file *filp, unsigned long arg)
{ {
struct inode *inode = file_inode(filp); struct inode *inode = file_inode(filp);
...@@ -938,6 +952,8 @@ long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ...@@ -938,6 +952,8 @@ long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
return f2fs_ioc_start_atomic_write(filp); return f2fs_ioc_start_atomic_write(filp);
case F2FS_IOC_COMMIT_ATOMIC_WRITE: case F2FS_IOC_COMMIT_ATOMIC_WRITE:
return f2fs_ioc_commit_atomic_write(filp); return f2fs_ioc_commit_atomic_write(filp);
case F2FS_IOC_START_VOLATILE_WRITE:
return f2fs_ioc_start_volatile_write(filp);
case FITRIM: case FITRIM:
return f2fs_ioc_fitrim(filp, arg); return f2fs_ioc_fitrim(filp, arg);
default: default:
......
...@@ -270,7 +270,7 @@ void f2fs_evict_inode(struct inode *inode) ...@@ -270,7 +270,7 @@ void f2fs_evict_inode(struct inode *inode)
nid_t xnid = F2FS_I(inode)->i_xattr_nid; nid_t xnid = F2FS_I(inode)->i_xattr_nid;
/* some remained atomic pages should discarded */ /* some remained atomic pages should discarded */
if (f2fs_is_atomic_file(inode)) if (f2fs_is_atomic_file(inode) || f2fs_is_volatile_file(inode))
commit_inmem_pages(inode, true); commit_inmem_pages(inode, true);
trace_f2fs_evict_inode(inode); trace_f2fs_evict_inode(inode);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment