summaryrefslogtreecommitdiff
path: root/fs/f2fs
diff options
context:
space:
mode:
authorChao Yu <yuchao0@huawei.com>2017-01-07 18:50:26 +0800
committerGreg Kroah-Hartman <gregkh@google.com>2017-10-03 15:20:50 +0000
commitdc8b8cea1e70b6649498a9850745c394e39d290c (patch)
tree02babca923d9fd588fa597cd6d471beea60aa0a3 /fs/f2fs
parent7129702a487ad1a4689bdf41c3657f829472c18c (diff)
f2fs: introduce FI_ATOMIC_COMMIT
commit 5fe457430e554a2f5188f13c1a2e36ad845640c5 upstream. This patch introduces a new flag to indicate inode status of doing atomic write committing, so that, we can keep atomic write status for inode during atomic committing, then we can skip GCing pages of atomic write inode, that avoids random GCed datas being mixed with current transaction, so isolation of transaction can be kept. Signed-off-by: Chao Yu <yuchao0@huawei.com> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Diffstat (limited to 'fs/f2fs')
-rw-r--r--fs/f2fs/data.c2
-rw-r--r--fs/f2fs/f2fs.h6
-rw-r--r--fs/f2fs/file.c11
-rw-r--r--fs/f2fs/gc.c6
-rw-r--r--fs/f2fs/segment.c10
5 files changed, 26 insertions, 9 deletions
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index f1001c871cb6..4ac72a3f920a 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -2017,7 +2017,7 @@ static int f2fs_set_data_page_dirty(struct page *page)
if (!PageUptodate(page))
SetPageUptodate(page);
- if (f2fs_is_atomic_file(inode)) {
+ if (f2fs_is_atomic_file(inode) && !f2fs_is_commit_atomic_write(inode)) {
if (!IS_ATOMIC_WRITTEN_PAGE(page)) {
register_inmem_page(inode, page);
return 1;
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 3eb53e3a8eae..807855d37c63 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -1706,6 +1706,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_ATOMIC_COMMIT, /* indicate the state of atomical committing */
FI_VOLATILE_FILE, /* indicate volatile file */
FI_FIRST_BLOCK_WRITTEN, /* indicate #0 data block was written */
FI_DROP_CACHE, /* drop dirty page cache */
@@ -1895,6 +1896,11 @@ static inline bool f2fs_is_atomic_file(struct inode *inode)
return is_inode_flag_set(inode, FI_ATOMIC_FILE);
}
+static inline bool f2fs_is_commit_atomic_write(struct inode *inode)
+{
+ return is_inode_flag_set(inode, FI_ATOMIC_COMMIT);
+}
+
static inline bool f2fs_is_volatile_file(struct inode *inode)
{
return is_inode_flag_set(inode, FI_VOLATILE_FILE);
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 9da13847cda4..e4e5d76d80b0 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -1573,14 +1573,15 @@ static int f2fs_ioc_commit_atomic_write(struct file *filp)
goto err_out;
if (f2fs_is_atomic_file(inode)) {
- clear_inode_flag(inode, FI_ATOMIC_FILE);
ret = commit_inmem_pages(inode);
- if (ret) {
- set_inode_flag(inode, FI_ATOMIC_FILE);
+ if (ret)
goto err_out;
- }
+
ret = f2fs_do_sync_file(filp, 0, LLONG_MAX, 0, true);
- stat_dec_atomic_write(inode);
+ if (!ret) {
+ clear_inode_flag(inode, FI_ATOMIC_FILE);
+ stat_dec_atomic_write(inode);
+ }
} else {
ret = f2fs_do_sync_file(filp, 0, LLONG_MAX, 0, true);
}
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index d3a36e4b442c..7f0c3e02408c 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -569,6 +569,9 @@ static void move_encrypted_block(struct inode *inode, block_t bidx,
if (!check_valid_map(F2FS_I_SB(inode), segno, off))
goto out;
+ if (f2fs_is_atomic_file(inode))
+ goto out;
+
set_new_dnode(&dn, inode, NULL, NULL, 0);
err = get_dnode_of_data(&dn, bidx, LOOKUP_NODE);
if (err)
@@ -661,6 +664,9 @@ static void move_data_page(struct inode *inode, block_t bidx, int gc_type,
if (!check_valid_map(F2FS_I_SB(inode), segno, off))
goto out;
+ if (f2fs_is_atomic_file(inode))
+ goto out;
+
if (gc_type == BG_GC) {
if (PageWriteback(page))
goto out;
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 12f8d5ab7ccf..6a870677d58a 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -242,12 +242,12 @@ void drop_inmem_pages(struct inode *inode)
{
struct f2fs_inode_info *fi = F2FS_I(inode);
- clear_inode_flag(inode, FI_ATOMIC_FILE);
- stat_dec_atomic_write(inode);
-
mutex_lock(&fi->inmem_lock);
__revoke_inmem_pages(inode, &fi->inmem_pages, true, false);
mutex_unlock(&fi->inmem_lock);
+
+ clear_inode_flag(inode, FI_ATOMIC_FILE);
+ stat_dec_atomic_write(inode);
}
static int __commit_inmem_pages(struct inode *inode,
@@ -316,6 +316,8 @@ int commit_inmem_pages(struct inode *inode)
f2fs_balance_fs(sbi, true);
f2fs_lock_op(sbi);
+ set_inode_flag(inode, FI_ATOMIC_COMMIT);
+
mutex_lock(&fi->inmem_lock);
err = __commit_inmem_pages(inode, &revoke_list);
if (err) {
@@ -337,6 +339,8 @@ int commit_inmem_pages(struct inode *inode)
}
mutex_unlock(&fi->inmem_lock);
+ clear_inode_flag(inode, FI_ATOMIC_COMMIT);
+
f2fs_unlock_op(sbi);
return err;
}