|
@@ -313,6 +313,7 @@ static int __commit_inmem_pages(struct inode *inode,
|
|
|
struct inmem_pages *cur, *tmp;
|
|
|
struct f2fs_io_info fio = {
|
|
|
.sbi = sbi,
|
|
|
+ .ino = inode->i_ino,
|
|
|
.type = DATA,
|
|
|
.op = REQ_OP_WRITE,
|
|
|
.op_flags = REQ_SYNC | REQ_PRIO,
|
|
@@ -485,15 +486,17 @@ static int __submit_flush_wait(struct f2fs_sb_info *sbi,
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-static int submit_flush_wait(struct f2fs_sb_info *sbi)
|
|
|
+static int submit_flush_wait(struct f2fs_sb_info *sbi, nid_t ino)
|
|
|
{
|
|
|
- int ret = __submit_flush_wait(sbi, sbi->sb->s_bdev);
|
|
|
+ int ret = 0;
|
|
|
int i;
|
|
|
|
|
|
- if (!sbi->s_ndevs || ret)
|
|
|
- return ret;
|
|
|
+ if (!sbi->s_ndevs)
|
|
|
+ return __submit_flush_wait(sbi, sbi->sb->s_bdev);
|
|
|
|
|
|
- for (i = 1; i < sbi->s_ndevs; i++) {
|
|
|
+ for (i = 0; i < sbi->s_ndevs; i++) {
|
|
|
+ if (!is_dirty_device(sbi, ino, i, FLUSH_INO))
|
|
|
+ continue;
|
|
|
ret = __submit_flush_wait(sbi, FDEV(i).bdev);
|
|
|
if (ret)
|
|
|
break;
|
|
@@ -519,7 +522,9 @@ repeat:
|
|
|
fcc->dispatch_list = llist_del_all(&fcc->issue_list);
|
|
|
fcc->dispatch_list = llist_reverse_order(fcc->dispatch_list);
|
|
|
|
|
|
- ret = submit_flush_wait(sbi);
|
|
|
+ cmd = llist_entry(fcc->dispatch_list, struct flush_cmd, llnode);
|
|
|
+
|
|
|
+ ret = submit_flush_wait(sbi, cmd->ino);
|
|
|
atomic_inc(&fcc->issued_flush);
|
|
|
|
|
|
llist_for_each_entry_safe(cmd, next,
|
|
@@ -537,7 +542,7 @@ repeat:
|
|
|
goto repeat;
|
|
|
}
|
|
|
|
|
|
-int f2fs_issue_flush(struct f2fs_sb_info *sbi)
|
|
|
+int f2fs_issue_flush(struct f2fs_sb_info *sbi, nid_t ino)
|
|
|
{
|
|
|
struct flush_cmd_control *fcc = SM_I(sbi)->fcc_info;
|
|
|
struct flush_cmd cmd;
|
|
@@ -547,19 +552,20 @@ int f2fs_issue_flush(struct f2fs_sb_info *sbi)
|
|
|
return 0;
|
|
|
|
|
|
if (!test_opt(sbi, FLUSH_MERGE)) {
|
|
|
- ret = submit_flush_wait(sbi);
|
|
|
+ ret = submit_flush_wait(sbi, ino);
|
|
|
atomic_inc(&fcc->issued_flush);
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
- if (atomic_inc_return(&fcc->issing_flush) == 1) {
|
|
|
- ret = submit_flush_wait(sbi);
|
|
|
+ if (atomic_inc_return(&fcc->issing_flush) == 1 || sbi->s_ndevs > 1) {
|
|
|
+ ret = submit_flush_wait(sbi, ino);
|
|
|
atomic_dec(&fcc->issing_flush);
|
|
|
|
|
|
atomic_inc(&fcc->issued_flush);
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+ cmd.ino = ino;
|
|
|
init_completion(&cmd.wait);
|
|
|
|
|
|
llist_add(&cmd.llnode, &fcc->issue_list);
|
|
@@ -583,7 +589,7 @@ int f2fs_issue_flush(struct f2fs_sb_info *sbi)
|
|
|
} else {
|
|
|
struct flush_cmd *tmp, *next;
|
|
|
|
|
|
- ret = submit_flush_wait(sbi);
|
|
|
+ ret = submit_flush_wait(sbi, ino);
|
|
|
|
|
|
llist_for_each_entry_safe(tmp, next, list, llnode) {
|
|
|
if (tmp == &cmd) {
|
|
@@ -2384,6 +2390,20 @@ void allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
|
|
|
mutex_unlock(&curseg->curseg_mutex);
|
|
|
}
|
|
|
|
|
|
+static void update_device_state(struct f2fs_io_info *fio)
|
|
|
+{
|
|
|
+ struct f2fs_sb_info *sbi = fio->sbi;
|
|
|
+ unsigned int devidx;
|
|
|
+
|
|
|
+ if (!sbi->s_ndevs)
|
|
|
+ return;
|
|
|
+
|
|
|
+ devidx = f2fs_target_device_index(sbi, fio->new_blkaddr);
|
|
|
+
|
|
|
+ /* update device state for fsync */
|
|
|
+ set_dirty_device(sbi, fio->ino, devidx, FLUSH_INO);
|
|
|
+}
|
|
|
+
|
|
|
static void do_write_page(struct f2fs_summary *sum, struct f2fs_io_info *fio)
|
|
|
{
|
|
|
int type = __get_segment_type(fio);
|
|
@@ -2398,6 +2418,8 @@ reallocate:
|
|
|
if (err == -EAGAIN) {
|
|
|
fio->old_blkaddr = fio->new_blkaddr;
|
|
|
goto reallocate;
|
|
|
+ } else if (!err) {
|
|
|
+ update_device_state(fio);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -2458,6 +2480,8 @@ int rewrite_data_page(struct f2fs_io_info *fio)
|
|
|
stat_inc_inplace_blocks(fio->sbi);
|
|
|
|
|
|
err = f2fs_submit_page_bio(fio);
|
|
|
+ if (!err)
|
|
|
+ update_device_state(fio);
|
|
|
|
|
|
f2fs_update_iostat(fio->sbi, fio->io_type, F2FS_BLKSIZE);
|
|
|
|