f2fs: support volatile operations for transient data
authorJaegeuk Kim <jaegeuk@kernel.org>
Mon, 6 Oct 2014 23:11:16 +0000 (16:11 -0700)
committerJaegeuk Kim <jaegeuk@kernel.org>
Tue, 7 Oct 2014 18:54:41 +0000 (11:54 -0700)
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: Jaegeuk Kim <jaegeuk@kernel.org>
fs/f2fs/data.c
fs/f2fs/f2fs.h
fs/f2fs/file.c
fs/f2fs/inode.c

index 8bbd60633f374665d877da722eb4326ee346346c..8e58c4cc2cb96519359e45d66acd34191972786f 100644 (file)
@@ -1052,7 +1052,7 @@ static int f2fs_write_end(struct file *file,
 
        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);
        else
                set_page_dirty(page);
index 07fda632430bfff098e0b3ee61915e5800afff45..8171e80b2ee9f9709c953b4264ea92bee01011c6 100644 (file)
@@ -198,6 +198,7 @@ static inline bool __has_cursum_space(struct f2fs_summary_block *sum, int size,
 #define F2FS_IOCTL_MAGIC               0xf5
 #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_START_VOLATILE_WRITE  _IO(F2FS_IOCTL_MAGIC, 3)
 
 #if defined(__KERNEL__) && defined(CONFIG_COMPAT)
 /*
@@ -1060,6 +1061,7 @@ enum {
        FI_UPDATE_WRITE,        /* inode has in-place-update data */
        FI_NEED_IPU,            /* used for ipu per 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)
@@ -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);
 }
 
+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)
 {
        struct f2fs_inode *ri = F2FS_INODE(page);
index 3708b80125d0133dcbc822c11b6e4a44de76a106..8e68bb64f83598360ffa8fdb31010aa1c33248f5 100644 (file)
@@ -885,6 +885,9 @@ static int f2fs_ioc_commit_atomic_write(struct file *filp)
        if (!inode_owner_or_capable(inode))
                return -EACCES;
 
+       if (f2fs_is_volatile_file(inode))
+               return 0;
+
        ret = mnt_want_write_file(filp);
        if (ret)
                return ret;
@@ -897,6 +900,17 @@ static int f2fs_ioc_commit_atomic_write(struct file *filp)
        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)
 {
        struct inode *inode = file_inode(filp);
@@ -938,6 +952,8 @@ long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                return f2fs_ioc_start_atomic_write(filp);
        case F2FS_IOC_COMMIT_ATOMIC_WRITE:
                return f2fs_ioc_commit_atomic_write(filp);
+       case F2FS_IOC_START_VOLATILE_WRITE:
+               return f2fs_ioc_start_volatile_write(filp);
        case FITRIM:
                return f2fs_ioc_fitrim(filp, arg);
        default:
index 1b85f72d007124d960b932de7a1fcb621ac1cc79..0deead4505e7ce1d7ec2525d8b3bf3eca9b76e00 100644 (file)
@@ -270,7 +270,7 @@ void f2fs_evict_inode(struct inode *inode)
        nid_t xnid = F2FS_I(inode)->i_xattr_nid;
 
        /* 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);
 
        trace_f2fs_evict_inode(inode);