Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1523421 > unrolled thread
| Started by | Chao Yu <yuchao0@huawei.com> |
|---|---|
| First post | 2016-11-16 13:20 +0100 |
| Last post | 2016-11-17 04:00 +0100 |
| Articles | 10 — 3 participants |
Back to article view | Back to linux.kernel
[PATCH] f2fs: fix fdatasync Chao Yu <yuchao0@huawei.com> - 2016-11-16 13:20 +0100
Re: [PATCH] f2fs: fix fdatasync Christoph Hellwig <hch@infradead.org> - 2016-11-16 13:20 +0100
Re: [PATCH] f2fs: fix fdatasync Chao Yu <yuchao0@huawei.com> - 2016-11-17 02:20 +0100
Re: [PATCH] f2fs: fix fdatasync Jaegeuk Kim <jaegeuk@kernel.org> - 2016-11-17 03:40 +0100
Re: [PATCH] f2fs: fix fdatasync Jaegeuk Kim <jaegeuk@kernel.org> - 2016-11-16 20:20 +0100
Re: [PATCH] f2fs: fix fdatasync Jaegeuk Kim <jaegeuk@kernel.org> - 2016-11-17 04:00 +0100
Re: [PATCH] f2fs: fix fdatasync Chao Yu <yuchao0@huawei.com> - 2016-11-17 04:40 +0100
Re: [PATCH] f2fs: fix fdatasync Jaegeuk Kim <jaegeuk@kernel.org> - 2016-11-17 04:50 +0100
Re: [PATCH] f2fs: fix fdatasync Chao Yu <yuchao0@huawei.com> - 2016-11-17 18:30 +0100
Re: [PATCH] f2fs: fix fdatasync Chao Yu <yuchao0@huawei.com> - 2016-11-17 04:00 +0100
| From | Chao Yu <yuchao0@huawei.com> |
|---|---|
| Date | 2016-11-16 13:20 +0100 |
| Subject | [PATCH] f2fs: fix fdatasync |
| Message-ID | <sE7m1-2EG-23@gated-at.bofh.it> |
For below two cases, we can't guarantee data consistence:
a)
1. xfs_io "pwrite 0 4195328" "fsync"
2. xfs_io "pwrite 4195328 1024" "fdatasync"
3. godown
4. umount & mount
--> isize we updated before fdatasync won't be recovered
b)
1. xfs_io "pwrite -S 0xcc 0 4202496" "fsync"
2. xfs_io "fpunch 4194304 4096" "fdatasync"
3. godown
4. umount & mount
--> dnode we punched before fdatasync won't be recovered
The reason is that normally fdatasync won't be aware of modification
of metadata in file, e.g. isize changing, dnode updating, so in ->fsync
we will skip flushing node pages for above cases, result in making
fdatasynced file being lost during recovery.
Introduce FDATASYNC_INO global ino cache for tracking node changing,
later fdatasync choose to flush nodes depend on ino cache state.
Signed-off-by: Chao Yu <yuchao0@huawei.com>
---
fs/f2fs/checkpoint.c | 13 ++++++++++++-
fs/f2fs/f2fs.h | 7 +++++++
fs/f2fs/file.c | 11 +++++++++--
fs/f2fs/node.c | 5 ++++-
4 files changed, 32 insertions(+), 4 deletions(-)
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index 5039ed8..27d5679 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -464,12 +464,23 @@ bool exist_written_data(struct f2fs_sb_info *sbi, nid_t ino, int mode)
return e ? true : false;
}
+bool need_flush_nodes(struct f2fs_sb_info *sbi, nid_t ino)
+{
+ struct inode_management *im = &sbi->im[FDATASYNC_INO];
+ struct ino_entry *e;
+
+ spin_lock(&im->ino_lock);
+ e = radix_tree_lookup(&im->ino_root, ino);
+ spin_unlock(&im->ino_lock);
+ return e ? true : false;
+}
+
void release_ino_entry(struct f2fs_sb_info *sbi, bool all)
{
struct ino_entry *e, *tmp;
int i;
- for (i = all ? ORPHAN_INO: APPEND_INO; i <= UPDATE_INO; i++) {
+ for (i = all ? ORPHAN_INO: APPEND_INO; i < MAX_INO_ENTRY; i++) {
struct inode_management *im = &sbi->im[i];
spin_lock(&im->ino_lock);
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index cf74ec6..0978c58 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -161,6 +161,7 @@ enum {
ORPHAN_INO, /* for orphan ino list */
APPEND_INO, /* for append ino list */
UPDATE_INO, /* for update ino list */
+ FDATASYNC_INO, /* need to flush nodes during fdatasync */
MAX_INO_ENTRY, /* max. list */
};
@@ -1695,6 +1696,7 @@ static inline void f2fs_i_links_write(struct inode *inode, bool inc)
f2fs_mark_inode_dirty_sync(inode, true);
}
+void add_ino_entry(struct f2fs_sb_info *, nid_t, int);
static inline void f2fs_i_blocks_write(struct inode *inode,
blkcnt_t diff, bool add)
{
@@ -1706,6 +1708,8 @@ static inline void f2fs_i_blocks_write(struct inode *inode,
f2fs_mark_inode_dirty_sync(inode, true);
if (clean || recover)
set_inode_flag(inode, FI_AUTO_RECOVER);
+
+ add_ino_entry(F2FS_I_SB(inode), inode->i_ino, FDATASYNC_INO);
}
static inline void f2fs_i_size_write(struct inode *inode, loff_t i_size)
@@ -1720,6 +1724,8 @@ static inline void f2fs_i_size_write(struct inode *inode, loff_t i_size)
f2fs_mark_inode_dirty_sync(inode, true);
if (clean || recover)
set_inode_flag(inode, FI_AUTO_RECOVER);
+
+ add_ino_entry(F2FS_I_SB(inode), inode->i_ino, FDATASYNC_INO);
}
static inline bool f2fs_skip_inode_update(struct inode *inode)
@@ -2150,6 +2156,7 @@ void add_ino_entry(struct f2fs_sb_info *, nid_t, int type);
void remove_ino_entry(struct f2fs_sb_info *, nid_t, int type);
void release_ino_entry(struct f2fs_sb_info *, bool);
bool exist_written_data(struct f2fs_sb_info *, nid_t, int);
+bool need_flush_nodes(struct f2fs_sb_info *, nid_t);
int f2fs_sync_inode_meta(struct f2fs_sb_info *);
int acquire_orphan_inode(struct f2fs_sb_info *);
void release_orphan_inode(struct f2fs_sb_info *);
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 47b7b13..75017c2 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -209,8 +209,13 @@ static int f2fs_do_sync_file(struct file *file, loff_t start, loff_t end,
return ret;
}
- /* if the inode is dirty, let's recover all the time */
- if (!datasync && !f2fs_skip_inode_update(inode)) {
+ if (datasync) {
+ if (need_flush_nodes(sbi, ino)) {
+ f2fs_write_inode(inode, NULL);
+ goto go_write;
+ }
+ } else if (!f2fs_skip_inode_update(inode)) {
+ /* if the inode is dirty, let's recover all the time */
f2fs_write_inode(inode, NULL);
goto go_write;
}
@@ -276,6 +281,8 @@ static int f2fs_do_sync_file(struct file *file, loff_t start, loff_t end,
/* once recovery info is written, don't need to tack this */
remove_ino_entry(sbi, ino, APPEND_INO);
clear_inode_flag(inode, FI_APPEND_WRITE);
+
+ remove_ino_entry(sbi, ino, FDATASYNC_INO);
flush_out:
remove_ino_entry(sbi, ino, UPDATE_INO);
clear_inode_flag(inode, FI_UPDATE_WRITE);
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index 1b5b31a..0974d5b 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -62,7 +62,7 @@ bool available_free_memory(struct f2fs_sb_info *sbi, int type)
} else if (type == INO_ENTRIES) {
int i;
- for (i = 0; i <= UPDATE_INO; i++)
+ for (i = 0; i < MAX_INO_ENTRY; i++)
mem_size += (sbi->im[i].ino_num *
sizeof(struct ino_entry)) >> PAGE_SHIFT;
res = mem_size < ((avail_ram * nm_i->ram_thresh / 100) >> 1);
@@ -1670,6 +1670,9 @@ static int f2fs_set_node_page_dirty(struct page *page)
inc_page_count(F2FS_P_SB(page), F2FS_DIRTY_NODES);
SetPagePrivate(page);
f2fs_trace_pid(page);
+
+ add_ino_entry(F2FS_P_SB(page), ino_of_node(page),
+ FDATASYNC_INO);
return 1;
}
return 0;
--
2.8.2.311.gee88674
[toc] | [next] | [standalone]
| From | Christoph Hellwig <hch@infradead.org> |
|---|---|
| Date | 2016-11-16 13:20 +0100 |
| Message-ID | <sE7m1-2EG-39@gated-at.bofh.it> |
| In reply to | #1523421 |
On Wed, Nov 16, 2016 at 08:12:11PM +0800, Chao Yu wrote: > For below two cases, we can't guarantee data consistence: > > a) > 1. xfs_io "pwrite 0 4195328" "fsync" > 2. xfs_io "pwrite 4195328 1024" "fdatasync" > 3. godown > 4. umount & mount > --> isize we updated before fdatasync won't be recovered > > b) > 1. xfs_io "pwrite -S 0xcc 0 4202496" "fsync" > 2. xfs_io "fpunch 4194304 4096" "fdatasync" > 3. godown > 4. umount & mount > --> dnode we punched before fdatasync won't be recovered Can you please add testcases for these to xfstests?
[toc] | [prev] | [next] | [standalone]
| From | Chao Yu <yuchao0@huawei.com> |
|---|---|
| Date | 2016-11-17 02:20 +0100 |
| Message-ID | <sEjwS-2bf-13@gated-at.bofh.it> |
| In reply to | #1523424 |
On 2016/11/16 20:15, Christoph Hellwig wrote: > On Wed, Nov 16, 2016 at 08:12:11PM +0800, Chao Yu wrote: >> For below two cases, we can't guarantee data consistence: >> >> a) >> 1. xfs_io "pwrite 0 4195328" "fsync" >> 2. xfs_io "pwrite 4195328 1024" "fdatasync" >> 3. godown >> 4. umount & mount >> --> isize we updated before fdatasync won't be recovered >> >> b) >> 1. xfs_io "pwrite -S 0xcc 0 4202496" "fsync" >> 2. xfs_io "fpunch 4194304 4096" "fdatasync" >> 3. godown >> 4. umount & mount >> --> dnode we punched before fdatasync won't be recovered > > Can you please add testcases for these to xfstests? It's OK, will do. > > . >
[toc] | [prev] | [next] | [standalone]
| From | Jaegeuk Kim <jaegeuk@kernel.org> |
|---|---|
| Date | 2016-11-17 03:40 +0100 |
| Message-ID | <sEkMh-2Xd-7@gated-at.bofh.it> |
| In reply to | #1524000 |
Hi Chao, On Thu, Nov 17, 2016 at 09:13:03AM +0800, Chao Yu wrote: > On 2016/11/16 20:15, Christoph Hellwig wrote: > > On Wed, Nov 16, 2016 at 08:12:11PM +0800, Chao Yu wrote: > >> For below two cases, we can't guarantee data consistence: > >> > >> a) > >> 1. xfs_io "pwrite 0 4195328" "fsync" > >> 2. xfs_io "pwrite 4195328 1024" "fdatasync" > >> 3. godown > >> 4. umount & mount > >> --> isize we updated before fdatasync won't be recovered > >> > >> b) > >> 1. xfs_io "pwrite -S 0xcc 0 4202496" "fsync" > >> 2. xfs_io "fpunch 4194304 4096" "fdatasync" > >> 3. godown > >> 4. umount & mount > >> --> dnode we punched before fdatasync won't be recovered > > > > Can you please add testcases for these to xfstests? > > It's OK, will do. Let me take a look at this for a while. It seems there are another test cases as well in terms of this issue. Thanks, > > > > > . > >
[toc] | [prev] | [next] | [standalone]
| From | Jaegeuk Kim <jaegeuk@kernel.org> |
|---|---|
| Date | 2016-11-16 20:20 +0100 |
| Message-ID | <sEdUt-70N-25@gated-at.bofh.it> |
| In reply to | #1523421 |
Hi Chao,
On Wed, Nov 16, 2016 at 08:12:11PM +0800, Chao Yu wrote:
> For below two cases, we can't guarantee data consistence:
>
> a)
> 1. xfs_io "pwrite 0 4195328" "fsync"
> 2. xfs_io "pwrite 4195328 1024" "fdatasync"
> 3. godown
> 4. umount & mount
> --> isize we updated before fdatasync won't be recovered
>
> b)
> 1. xfs_io "pwrite -S 0xcc 0 4202496" "fsync"
> 2. xfs_io "fpunch 4194304 4096" "fdatasync"
> 3. godown
> 4. umount & mount
> --> dnode we punched before fdatasync won't be recovered
>
> The reason is that normally fdatasync won't be aware of modification
> of metadata in file, e.g. isize changing, dnode updating, so in ->fsync
> we will skip flushing node pages for above cases, result in making
> fdatasynced file being lost during recovery.
>
> Introduce FDATASYNC_INO global ino cache for tracking node changing,
> later fdatasync choose to flush nodes depend on ino cache state.
We don't need to add this additionally, and would be better to consider other
major metadata as well.
How about this?
---
fs/f2fs/f2fs.h | 11 ++++++++++-
fs/f2fs/file.c | 2 +-
2 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index c9672a3..50ffa4f 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -1727,8 +1727,17 @@ static inline void f2fs_i_size_write(struct inode *inode, loff_t i_size)
set_inode_flag(inode, FI_AUTO_RECOVER);
}
-static inline bool f2fs_skip_inode_update(struct inode *inode)
+static inline bool f2fs_skip_inode_update(struct inode *inode, int dsync)
{
+ if (dsync) {
+ struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
+ bool ret;
+
+ spin_lock(&sbi->inode_lock[DIRTY_META]);
+ ret = list_empty(&F2FS_I(inode)->gdirty_list);
+ spin_unlock(&sbi->inode_lock[DIRTY_META]);
+ return ret;
+ }
if (!is_inode_flag_set(inode, FI_AUTO_RECOVER))
return false;
return F2FS_I(inode)->last_disk_size == i_size_read(inode);
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index d48c120..50123c6 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -212,7 +212,7 @@ static int f2fs_do_sync_file(struct file *file, loff_t start, loff_t end,
}
/* if the inode is dirty, let's recover all the time */
- if (!datasync && !f2fs_skip_inode_update(inode)) {
+ if (!f2fs_skip_inode_update(inode, datasync)) {
f2fs_write_inode(inode, NULL);
goto go_write;
}
--
2.8.3
[toc] | [prev] | [next] | [standalone]
| From | Jaegeuk Kim <jaegeuk@kernel.org> |
|---|---|
| Date | 2016-11-17 04:00 +0100 |
| Message-ID | <sEl5D-33A-1@gated-at.bofh.it> |
| In reply to | #1523766 |
On Thu, Nov 17, 2016 at 10:51:37AM +0800, Chao Yu wrote:
> Hi Jaegeuk,
>
> On 2016/11/17 3:13, Jaegeuk Kim wrote:
> > Hi Chao,
> >
> > On Wed, Nov 16, 2016 at 08:12:11PM +0800, Chao Yu wrote:
> >> For below two cases, we can't guarantee data consistence:
> >>
> >> a)
> >> 1. xfs_io "pwrite 0 4195328" "fsync"
> >> 2. xfs_io "pwrite 4195328 1024" "fdatasync"
> >> 3. godown
> >> 4. umount & mount
> >> --> isize we updated before fdatasync won't be recovered
> >>
> >> b)
> >> 1. xfs_io "pwrite -S 0xcc 0 4202496" "fsync"
> >> 2. xfs_io "fpunch 4194304 4096" "fdatasync"
> >> 3. godown
> >> 4. umount & mount
> >> --> dnode we punched before fdatasync won't be recovered
> >>
> >> The reason is that normally fdatasync won't be aware of modification
> >> of metadata in file, e.g. isize changing, dnode updating, so in ->fsync
> >> we will skip flushing node pages for above cases, result in making
> >> fdatasynced file being lost during recovery.
> >>
> >> Introduce FDATASYNC_INO global ino cache for tracking node changing,
> >> later fdatasync choose to flush nodes depend on ino cache state.
> >
> > We don't need to add this additionally, and would be better to consider other
> > major metadata as well.
> >
> > How about this?
>
> Seems it can't track file after evict?
Do we need that? That means inode page was already up-to-date?
>
> Thanks,
>
> >
> > ---
> > fs/f2fs/f2fs.h | 11 ++++++++++-
> > fs/f2fs/file.c | 2 +-
> > 2 files changed, 11 insertions(+), 2 deletions(-)
> >
> > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> > index c9672a3..50ffa4f 100644
> > --- a/fs/f2fs/f2fs.h
> > +++ b/fs/f2fs/f2fs.h
> > @@ -1727,8 +1727,17 @@ static inline void f2fs_i_size_write(struct inode *inode, loff_t i_size)
> > set_inode_flag(inode, FI_AUTO_RECOVER);
> > }
> >
> > -static inline bool f2fs_skip_inode_update(struct inode *inode)
> > +static inline bool f2fs_skip_inode_update(struct inode *inode, int dsync)
> > {
> > + if (dsync) {
> > + struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
> > + bool ret;
> > +
> > + spin_lock(&sbi->inode_lock[DIRTY_META]);
> > + ret = list_empty(&F2FS_I(inode)->gdirty_list);
> > + spin_unlock(&sbi->inode_lock[DIRTY_META]);
> > + return ret;
> > + }
> > if (!is_inode_flag_set(inode, FI_AUTO_RECOVER))
> > return false;
> > return F2FS_I(inode)->last_disk_size == i_size_read(inode);
> > diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> > index d48c120..50123c6 100644
> > --- a/fs/f2fs/file.c
> > +++ b/fs/f2fs/file.c
> > @@ -212,7 +212,7 @@ static int f2fs_do_sync_file(struct file *file, loff_t start, loff_t end,
> > }
> >
> > /* if the inode is dirty, let's recover all the time */
> > - if (!datasync && !f2fs_skip_inode_update(inode)) {
> > + if (!f2fs_skip_inode_update(inode, datasync)) {
> > f2fs_write_inode(inode, NULL);
> > goto go_write;
> > }
> >
[toc] | [prev] | [next] | [standalone]
| From | Chao Yu <yuchao0@huawei.com> |
|---|---|
| Date | 2016-11-17 04:40 +0100 |
| Message-ID | <sElIm-3Bq-11@gated-at.bofh.it> |
| In reply to | #1524042 |
On 2016/11/17 10:59, Jaegeuk Kim wrote:
> On Thu, Nov 17, 2016 at 10:51:37AM +0800, Chao Yu wrote:
>> Hi Jaegeuk,
>>
>> On 2016/11/17 3:13, Jaegeuk Kim wrote:
>>> Hi Chao,
>>>
>>> On Wed, Nov 16, 2016 at 08:12:11PM +0800, Chao Yu wrote:
>>>> For below two cases, we can't guarantee data consistence:
>>>>
>>>> a)
>>>> 1. xfs_io "pwrite 0 4195328" "fsync"
>>>> 2. xfs_io "pwrite 4195328 1024" "fdatasync"
>>>> 3. godown
>>>> 4. umount & mount
>>>> --> isize we updated before fdatasync won't be recovered
>>>>
>>>> b)
>>>> 1. xfs_io "pwrite -S 0xcc 0 4202496" "fsync"
>>>> 2. xfs_io "fpunch 4194304 4096" "fdatasync"
>>>> 3. godown
>>>> 4. umount & mount
>>>> --> dnode we punched before fdatasync won't be recovered
>>>>
>>>> The reason is that normally fdatasync won't be aware of modification
>>>> of metadata in file, e.g. isize changing, dnode updating, so in ->fsync
>>>> we will skip flushing node pages for above cases, result in making
>>>> fdatasynced file being lost during recovery.
>>>>
>>>> Introduce FDATASYNC_INO global ino cache for tracking node changing,
>>>> later fdatasync choose to flush nodes depend on ino cache state.
>>>
>>> We don't need to add this additionally, and would be better to consider other
>>> major metadata as well.
>>>
>>> How about this?
>>
>> Seems it can't track file after evict?
>
> Do we need that? That means inode page was already up-to-date?
I mean if node/data page of inode were writeback by kworker, after evict, if
user open it again and call fdatasync, after sudden power-off, we will not
recover it.
Thanks,
>
>>
>> Thanks,
>>
>>>
>>> ---
>>> fs/f2fs/f2fs.h | 11 ++++++++++-
>>> fs/f2fs/file.c | 2 +-
>>> 2 files changed, 11 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
>>> index c9672a3..50ffa4f 100644
>>> --- a/fs/f2fs/f2fs.h
>>> +++ b/fs/f2fs/f2fs.h
>>> @@ -1727,8 +1727,17 @@ static inline void f2fs_i_size_write(struct inode *inode, loff_t i_size)
>>> set_inode_flag(inode, FI_AUTO_RECOVER);
>>> }
>>>
>>> -static inline bool f2fs_skip_inode_update(struct inode *inode)
>>> +static inline bool f2fs_skip_inode_update(struct inode *inode, int dsync)
>>> {
>>> + if (dsync) {
>>> + struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
>>> + bool ret;
>>> +
>>> + spin_lock(&sbi->inode_lock[DIRTY_META]);
>>> + ret = list_empty(&F2FS_I(inode)->gdirty_list);
>>> + spin_unlock(&sbi->inode_lock[DIRTY_META]);
>>> + return ret;
>>> + }
>>> if (!is_inode_flag_set(inode, FI_AUTO_RECOVER))
>>> return false;
>>> return F2FS_I(inode)->last_disk_size == i_size_read(inode);
>>> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
>>> index d48c120..50123c6 100644
>>> --- a/fs/f2fs/file.c
>>> +++ b/fs/f2fs/file.c
>>> @@ -212,7 +212,7 @@ static int f2fs_do_sync_file(struct file *file, loff_t start, loff_t end,
>>> }
>>>
>>> /* if the inode is dirty, let's recover all the time */
>>> - if (!datasync && !f2fs_skip_inode_update(inode)) {
>>> + if (!f2fs_skip_inode_update(inode, datasync)) {
>>> f2fs_write_inode(inode, NULL);
>>> goto go_write;
>>> }
>>>
>
> .
>
[toc] | [prev] | [next] | [standalone]
| From | Jaegeuk Kim <jaegeuk@kernel.org> |
|---|---|
| Date | 2016-11-17 04:50 +0100 |
| Message-ID | <sElS1-3EH-9@gated-at.bofh.it> |
| In reply to | #1524063 |
On Thu, Nov 17, 2016 at 11:35:58AM +0800, Chao Yu wrote: > On 2016/11/17 10:59, Jaegeuk Kim wrote: > > On Thu, Nov 17, 2016 at 10:51:37AM +0800, Chao Yu wrote: > >> Hi Jaegeuk, > >> > >> On 2016/11/17 3:13, Jaegeuk Kim wrote: > >>> Hi Chao, > >>> > >>> On Wed, Nov 16, 2016 at 08:12:11PM +0800, Chao Yu wrote: > >>>> For below two cases, we can't guarantee data consistence: > >>>> > >>>> a) > >>>> 1. xfs_io "pwrite 0 4195328" "fsync" > >>>> 2. xfs_io "pwrite 4195328 1024" "fdatasync" > >>>> 3. godown > >>>> 4. umount & mount > >>>> --> isize we updated before fdatasync won't be recovered > >>>> > >>>> b) > >>>> 1. xfs_io "pwrite -S 0xcc 0 4202496" "fsync" > >>>> 2. xfs_io "fpunch 4194304 4096" "fdatasync" > >>>> 3. godown > >>>> 4. umount & mount > >>>> --> dnode we punched before fdatasync won't be recovered > >>>> > >>>> The reason is that normally fdatasync won't be aware of modification > >>>> of metadata in file, e.g. isize changing, dnode updating, so in ->fsync > >>>> we will skip flushing node pages for above cases, result in making > >>>> fdatasynced file being lost during recovery. > >>>> > >>>> Introduce FDATASYNC_INO global ino cache for tracking node changing, > >>>> later fdatasync choose to flush nodes depend on ino cache state. > >>> > >>> We don't need to add this additionally, and would be better to consider other > >>> major metadata as well. > >>> > >>> How about this? > >> > >> Seems it can't track file after evict? > > > > Do we need that? That means inode page was already up-to-date? > > I mean if node/data page of inode were writeback by kworker, after evict, if > user open it again and call fdatasync, after sudden power-off, we will not > recover it. That will be handled by need_inode_block_update() below? Thanks,
[toc] | [prev] | [next] | [standalone]
| From | Chao Yu <yuchao0@huawei.com> |
|---|---|
| Date | 2016-11-17 18:30 +0100 |
| Message-ID | <sEyFz-3CT-21@gated-at.bofh.it> |
| In reply to | #1524068 |
On 2016/11/17 11:41, Jaegeuk Kim wrote: > On Thu, Nov 17, 2016 at 11:35:58AM +0800, Chao Yu wrote: >> On 2016/11/17 10:59, Jaegeuk Kim wrote: >>> On Thu, Nov 17, 2016 at 10:51:37AM +0800, Chao Yu wrote: >>>> Hi Jaegeuk, >>>> >>>> On 2016/11/17 3:13, Jaegeuk Kim wrote: >>>>> Hi Chao, >>>>> >>>>> On Wed, Nov 16, 2016 at 08:12:11PM +0800, Chao Yu wrote: >>>>>> For below two cases, we can't guarantee data consistence: >>>>>> >>>>>> a) >>>>>> 1. xfs_io "pwrite 0 4195328" "fsync" >>>>>> 2. xfs_io "pwrite 4195328 1024" "fdatasync" >>>>>> 3. godown >>>>>> 4. umount & mount >>>>>> --> isize we updated before fdatasync won't be recovered >>>>>> >>>>>> b) >>>>>> 1. xfs_io "pwrite -S 0xcc 0 4202496" "fsync" >>>>>> 2. xfs_io "fpunch 4194304 4096" "fdatasync" >>>>>> 3. godown >>>>>> 4. umount & mount >>>>>> --> dnode we punched before fdatasync won't be recovered >>>>>> >>>>>> The reason is that normally fdatasync won't be aware of modification >>>>>> of metadata in file, e.g. isize changing, dnode updating, so in ->fsync >>>>>> we will skip flushing node pages for above cases, result in making >>>>>> fdatasynced file being lost during recovery. >>>>>> >>>>>> Introduce FDATASYNC_INO global ino cache for tracking node changing, >>>>>> later fdatasync choose to flush nodes depend on ino cache state. >>>>> >>>>> We don't need to add this additionally, and would be better to consider other >>>>> major metadata as well. >>>>> >>>>> How about this? >>>> >>>> Seems it can't track file after evict? >>> >>> Do we need that? That means inode page was already up-to-date? >> >> I mean if node/data page of inode were writeback by kworker, after evict, if >> user open it again and call fdatasync, after sudden power-off, we will not >> recover it. > > That will be handled by need_inode_block_update() below? Confirmed, let me send v2 and do more tests. Thanks, > > Thanks, > > . >
[toc] | [prev] | [next] | [standalone]
| From | Chao Yu <yuchao0@huawei.com> |
|---|---|
| Date | 2016-11-17 04:00 +0100 |
| Message-ID | <sEl5D-33A-3@gated-at.bofh.it> |
| In reply to | #1523766 |
Hi Jaegeuk,
On 2016/11/17 3:13, Jaegeuk Kim wrote:
> Hi Chao,
>
> On Wed, Nov 16, 2016 at 08:12:11PM +0800, Chao Yu wrote:
>> For below two cases, we can't guarantee data consistence:
>>
>> a)
>> 1. xfs_io "pwrite 0 4195328" "fsync"
>> 2. xfs_io "pwrite 4195328 1024" "fdatasync"
>> 3. godown
>> 4. umount & mount
>> --> isize we updated before fdatasync won't be recovered
>>
>> b)
>> 1. xfs_io "pwrite -S 0xcc 0 4202496" "fsync"
>> 2. xfs_io "fpunch 4194304 4096" "fdatasync"
>> 3. godown
>> 4. umount & mount
>> --> dnode we punched before fdatasync won't be recovered
>>
>> The reason is that normally fdatasync won't be aware of modification
>> of metadata in file, e.g. isize changing, dnode updating, so in ->fsync
>> we will skip flushing node pages for above cases, result in making
>> fdatasynced file being lost during recovery.
>>
>> Introduce FDATASYNC_INO global ino cache for tracking node changing,
>> later fdatasync choose to flush nodes depend on ino cache state.
>
> We don't need to add this additionally, and would be better to consider other
> major metadata as well.
>
> How about this?
Seems it can't track file after evict?
Thanks,
>
> ---
> fs/f2fs/f2fs.h | 11 ++++++++++-
> fs/f2fs/file.c | 2 +-
> 2 files changed, 11 insertions(+), 2 deletions(-)
>
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index c9672a3..50ffa4f 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -1727,8 +1727,17 @@ static inline void f2fs_i_size_write(struct inode *inode, loff_t i_size)
> set_inode_flag(inode, FI_AUTO_RECOVER);
> }
>
> -static inline bool f2fs_skip_inode_update(struct inode *inode)
> +static inline bool f2fs_skip_inode_update(struct inode *inode, int dsync)
> {
> + if (dsync) {
> + struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
> + bool ret;
> +
> + spin_lock(&sbi->inode_lock[DIRTY_META]);
> + ret = list_empty(&F2FS_I(inode)->gdirty_list);
> + spin_unlock(&sbi->inode_lock[DIRTY_META]);
> + return ret;
> + }
> if (!is_inode_flag_set(inode, FI_AUTO_RECOVER))
> return false;
> return F2FS_I(inode)->last_disk_size == i_size_read(inode);
> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> index d48c120..50123c6 100644
> --- a/fs/f2fs/file.c
> +++ b/fs/f2fs/file.c
> @@ -212,7 +212,7 @@ static int f2fs_do_sync_file(struct file *file, loff_t start, loff_t end,
> }
>
> /* if the inode is dirty, let's recover all the time */
> - if (!datasync && !f2fs_skip_inode_update(inode)) {
> + if (!f2fs_skip_inode_update(inode, datasync)) {
> f2fs_write_inode(inode, NULL);
> goto go_write;
> }
>
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web