miss-sync issues on sync mount (miss-sync on utime)
Subsystems (3)
PATCH 2/2 miss-sync issues on sync mount (miss-sync on utime)
The 2nd patch fixes miss-sync issue on attribute operations, like utime.
---
Hiroyuki Machida
--- file.c | 4 ++++ 1 files changed, 4 insertions(+)
fs/fat/file.c +4 -0
@@ -201,6 +183,10 @@ int fat_notify_change(struct dentry *denelse mask = sbi->options.fs_fmask; inode->i_mode &=S_IFMT | (S_IRWXUGO & ~mask); + +if ( (!error) &&IS_SYNC (inode)) { + error =write_inode_now (inode,1 ); + } out:unlock_kernel ();return error;
OGAWA Hirofumi
maintainerfs/fat/file.c int fat_notify_change(struct dentry *den · line 189
Quoted 3 lines · Hiroyuki
fs/fat/file.c +3
-0+if ( (!error) &&IS_SYNC (inode)) { + error =write_inode_now (inode,1 ); + }
We don't need to sync the data pages at all here. And I think it is not right place for doing this. If we need this, since we need to see O_SYNC for fchxxx() VFS would be right place to do it.
But, personally, I'd like to kill the "-o sync" stuff for these independent meta data rather. Then...
Signature · 1 line
OGAWA Hirofumi <[email protected]>
Quoted 11 lines · OGAWA Hirofumi
fs/fat/file.c int fat_notify_change(struct dentry *den · line 189
Quoted 3 lines · Hiroyuki
fs/fat/file.c +3
-0+if ( (!error) &&IS_SYNC (inode)) { + error =write_inode_now (inode,1 ); + }We don't need to sync the data pages at all here. And I think it is not right place for doing this. If we need this, since we need to see
O_SYNCforfchxxx()VFS would be right place to do it.
I see, I'll look into those.
Quoted 2 lines
But, personally, I'd like to kill the "-o sync" stuff for these independent meta data rather. Then...
Signature · 2 lines
Hiroyuki Machida [email protected] SSW Dept. HENC, Sony Corp.
PATCH 1/2 miss-sync changes on attributes (Re: [PATCH 2/2][FAT] miss-sync issues on sync mount (miss-sync on utime))
In reply to OGAWA HirofumiI revise a previous patch. Now checking dirty flag is done at vfs layer, as OGAWA-san said. I realized ext2_sync_inode() is good for syncing inode without it's data. I moved it to vfs layer and rename it to sync_inode_wodata().
The first patch attached here is changes on vfs layer. Second patch attached at the next mail is changes on ext2 fs.
Quoted 14 lines · OGAWA Hirofumi
Review
Quoted 3 lines · Hiroyuki
(quoted diff) +3
-0+ if ( (!error) && IS_SYNC(inode)) { + error = write_inode_now(inode, 1); + }We don't need to sync the data pages at all here. And I think it is not right place for doing this. If we need this, since we need to see
O_SYNCforfchxxx()VFS would be right place to do it.But, personally, I'd like to kill the "-o sync" stuff for these independent meta data rather. Then...
Signature · 1 line
Hiroyuki Machida [email protected]
This patch adds inode-sync after attribute changes, if needed.
* fs-sync-attr.patch for 2.6.13
fs/fs-writeback.c | 19 +++++++++++++++++++ fs/open.c | 12 ++++++++++++ include/linux/fs.h | 1 + 4 files changed, 32 insertions(+)
fs/fs-writeback.c +19 -0
@@ -593,6 +593,25 @@ int sync_inode(struct inode *inode, struEXPORT_SYMBOL (sync_inode);/** +* sync_inode_wodata - sync(write and wait) inode to disk, without it's data. +* @inode: the inode to sync +* +* sync_inode_wodata() will write an inode then wait. It will also +* correctly update the inode on its superblock's dirty inode lists +* and will update inode->i_state. +* +* The caller must have a ref on the inode. +*/ +int sync_inode_wodata (struct inode *inode) +{ +struct writeback_control wbc = { + .sync_mode =WB_SYNC_ALL ,/* wait */ + .nr_to_write =0 ,/* no data to be written */ + }; +return sync_inode (inode, &wbc); +} + +/** * generic_osync_inode - flush all dirty data for a given inode to disk * @inode: inode to write * @mapping: the address_space that should be flushed
fs/open.c +12 -0
@@ -207,6 +207,8 @@ int do_truncate(struct dentry *dentry, ldown (&dentry->d_inode->i_sem); err =notify_change (dentry, &newattrs); +if (!err &&IS_SYNC (dentry->d_inode)) +sync_inode_wodata (dentry->d_inode);up (&dentry->d_inode->i_sem);return err; }
@@ -394,6 +396,8 @@ asmlinkage long sys_utime(char __user * }down (&inode->i_sem); error =notify_change (nd.dentry, &newattrs); +if (!error &&IS_SYNC (inode)) +sync_inode_wodata (inode);up (&inode->i_sem); dput_and_out:path_release (&nd);
@@ -447,6 +451,8 @@ long do_utimes(char __user * filename, s }down (&inode->i_sem); error =notify_change (nd.dentry, &newattrs); +if (!error &&IS_SYNC (inode)) +sync_inode_wodata (inode);up (&inode->i_sem); dput_and_out:path_release (&nd);
@@ -620,6 +626,8 @@ asmlinkage long sys_fchmod(unsigned int newattrs.ia_mode = (mode &S_IALLUGO ) | (inode->i_mode & ~S_IALLUGO ); newattrs.ia_valid =ATTR_MODE |ATTR_CTIME ; err =notify_change (dentry, &newattrs); +if (!err &&IS_SYNC (inode)) +sync_inode_wodata (inode);up (&inode->i_sem); out_putf:
@@ -654,6 +662,8 @@ asmlinkage long sys_chmod(const char __u newattrs.ia_mode = (mode &S_IALLUGO ) | (inode->i_mode & ~S_IALLUGO ); newattrs.ia_valid =ATTR_MODE |ATTR_CTIME ; error =notify_change (nd.dentry, &newattrs); +if (!error &&IS_SYNC (inode)) +sync_inode_wodata (inode);up (&inode->i_sem); dput_and_out:
@@ -692,6 +702,8 @@ static int chown_common(struct dentry * newattrs.ia_valid |=ATTR_KILL_SUID |ATTR_KILL_SGID ;down (&inode->i_sem); error =notify_change (dentry, &newattrs); +if (!error &&IS_SYNC (inode)) +sync_inode_wodata (inode);up (&inode->i_sem); out:return error;
include/linux/fs.h +1 -0
@@ -1082,6 +1082,7 @@ static inline void file_accessed(struct }int sync_inode (struct inode *inode,struct writeback_control *wbc); +int sync_inode_wodata (struct inode *inode);/** * struct export_operations - for nfsd to communicate with file systems
PATCH 2/2 replace ext2_sync_inode() with sync_inode_wodata( (Re: [PATCH 2/2][FAT] miss-sync issues on sync mount (miss-sync on utime))
This patch replaces ext2_sync_inode() with sync_inode_wodata(), which is introduced by fs-sync-attr.patch attached at
"[PATCH 1/2] miss-sync changes on attributes"
Quoted 31 lines · Hiroyuki
I revise a previous patch. Now checking dirty flag is done at vfs layer, as OGAWA-san said. I realized
ext2_sync_inode()is good for syncing inode without it's data. I moved it to vfs layer and rename it tosync_inode_wodata().The first patch attached here is changes on vfs layer. Second patch attached at the next mail is changes on ext2 fs.
Quoted 9 lines · OGAWA Hirofumi
Review
Quoted 3 lines · Hiroyuki
(quoted diff) +3
-0+ if ( (!error) && IS_SYNC(inode)) { + error = write_inode_now(inode, 1); + }Quoted 6 lines
We don't need to sync the data pages at all here. And I think it is not right place for doing this. If we need this, since we need to see
O_SYNCforfchxxx()VFS would be right place to do it.But, personally, I'd like to kill the "-o sync" stuff for these independent meta data rather. Then...
------------------------------------------------------------------------
Signature · 1 line
Hiroyuki Machida [email protected]
This patch replaces ext2_sync_inode() with sync_inode_wodata().
* ext2-inode-sync.patch for 2.6.13
ext2.h | 1 - fsync.c | 2 +- inode.c | 11 +---------- xattr.c | 2 +-
4 files changed, 3 insertions(+), 13 deletions(-)
fs/ext2/ext2.h +0 -1
@@ -127,7 +127,6 @@ extern void ext2_read_inode (struct inodextern int ext2_write_inode (struct inode *,int );extern void ext2_put_inode (struct inode *);extern void ext2_delete_inode (struct inode *); -extern int ext2_sync_inode (struct inode *);extern void ext2_discard_prealloc (struct inode *);extern int ext2_get_block (struct inode *,sector_t ,struct buffer_head *,int );extern void ext2_truncate (struct inode *);
fs/ext2/fsync.c +1 -1
@@ -44,7 +44,7 @@ int ext2_sync_file(struct file *file, stif (datasync && !(inode->i_state &I_DIRTY_DATASYNC ))return ret; - err =ext2_sync_inode (inode); + err =sync_inode_wodata (inode);if (ret ==0 ) ret = err;return ret;
fs/ext2/inode.c +1 -10
@@ -993,7 +993,7 @@ do_indirects: inode->i_mtime = inode->i_ctime =CURRENT_TIME_SEC ;if (inode_needs_sync (inode)) {sync_mapping_buffers (inode->i_mapping); -ext2_sync_inode (inode); +sync_inode_wodata (inode); }else {mark_inode_dirty (inode); }
@@ -1282,15 +1282,6 @@ int ext2_write_inode(struct inode *inodereturn ext2_update_inode (inode, wait); } -int ext2_sync_inode (struct inode *inode) -{ -struct writeback_control wbc = { - .sync_mode =WB_SYNC_ALL , - .nr_to_write =0 ,/* sys_fsync did this */ - }; -return sync_inode (inode, &wbc); -} -int ext2_setattr (struct dentry *dentry,struct iattr *iattr) {struct inode *inode = dentry->d_inode;
fs/ext2/xattr.c +1 -1
@@ -705,7 +705,7 @@ ext2_xattr_set2(struct inode *inode, strEXT2_I (inode)->i_file_acl = new_bh ? new_bh->b_blocknr :0 ; inode->i_ctime =CURRENT_TIME_SEC ;if (IS_SYNC (inode)) { - error =ext2_sync_inode (inode); + error =sync_inode_wodata (inode);/* In case sync failed due to ENOSPC the inode was actually * written (only some dirty data were not) so we just proceed * as if nothing happened and cleanup the unused block */
Re: [PATCH 1/2] miss-sync changes on attributes (Re: [PATCH 2/2][FAT] miss-sync issues on sync mount (miss-sync on utime))
In reply to Machida, HiroyukiPrevious patch didn't export sync_inode_wodata(), that had a problem with modula ext2 fs. Bug-fixed version is attached here.
Quoted 35 lines · Hiroyuki
I revise a previous patch. Now checking dirty flag is done at vfs layer, as OGAWA-san said. I realized
ext2_sync_inode()is good for syncing inode without it's data. I moved it to vfs layer and rename it tosync_inode_wodata().The first patch attached here is changes on vfs layer. Second patch attached at the next mail is changes on ext2 fs.
Quoted 9 lines · OGAWA Hirofumi
Review
Quoted 3 lines · Hiroyuki
(quoted diff) +3
-0+ if ( (!error) && IS_SYNC(inode)) { + error = write_inode_now(inode, 1); + }Quoted 6 lines
We don't need to sync the data pages at all here. And I think it is not right place for doing this. If we need this, since we need to see
O_SYNCforfchxxx()VFS would be right place to do it.But, personally, I'd like to kill the "-o sync" stuff for these independent meta data rather. Then...
------------------------------------------------------------------------
This patch adds inode-sync after attribute changes, if needed.
Quoted 8 lines
* fs-sync-attr.patch for 2.6.13
fs/fs-writeback.c | 19 +++++++++++++++++++ fs/open.c | 12 ++++++++++++ include/linux/fs.h | 1 + 4 files changed, 32 insertions(+)Signed-off-by Hiroyuki Machida <[email protected]>
:
This patch adds inode-sync after attribute changes, if needed.
* fs-sync-attr_2.patch for 2.6.13
fs/fs-writeback.c | 20 ++++++++++++++++++++ fs/open.c | 12 ++++++++++++ include/linux/fs.h | 1 + 3 files changed, 33 insertions(+)
fs/fs-writeback.c +20 -0
@@ -593,6 +593,26 @@ int sync_inode(struct inode *inode, struEXPORT_SYMBOL (sync_inode);/** +* sync_inode_wodata - sync(write and wait) inode to disk, without it's data. +* @inode: the inode to sync +* +* sync_inode_wodata() will write an inode then wait. It will also +* correctly update the inode on its superblock's dirty inode lists +* and will update inode->i_state. +* +* The caller must have a ref on the inode. +*/ +int sync_inode_wodata (struct inode *inode) +{ +struct writeback_control wbc = { + .sync_mode =WB_SYNC_ALL ,/* wait */ + .nr_to_write =0 ,/* no data to be written */ + }; +return sync_inode (inode, &wbc); +} +EXPORT_SYMBOL (sync_inode_wodata); + +/** * generic_osync_inode - flush all dirty data for a given inode to disk * @inode: inode to write * @mapping: the address_space that should be flushed
fs/open.c +12 -0
@@ -207,6 +207,8 @@ int do_truncate(struct dentry *dentry, ldown (&dentry->d_inode->i_sem); err =notify_change (dentry, &newattrs); +if (!err &&IS_SYNC (dentry->d_inode)) +sync_inode_wodata (dentry->d_inode);up (&dentry->d_inode->i_sem);return err; }
@@ -394,6 +396,8 @@ asmlinkage long sys_utime(char __user * }down (&inode->i_sem); error =notify_change (nd.dentry, &newattrs); +if (!error &&IS_SYNC (inode)) +sync_inode_wodata (inode);up (&inode->i_sem); dput_and_out:path_release (&nd);
@@ -447,6 +451,8 @@ long do_utimes(char __user * filename, s }down (&inode->i_sem); error =notify_change (nd.dentry, &newattrs); +if (!error &&IS_SYNC (inode)) +sync_inode_wodata (inode);up (&inode->i_sem); dput_and_out:path_release (&nd);
@@ -620,6 +626,8 @@ asmlinkage long sys_fchmod(unsigned int newattrs.ia_mode = (mode &S_IALLUGO ) | (inode->i_mode & ~S_IALLUGO ); newattrs.ia_valid =ATTR_MODE |ATTR_CTIME ; err =notify_change (dentry, &newattrs); +if (!err &&IS_SYNC (inode)) +sync_inode_wodata (inode);up (&inode->i_sem); out_putf:
@@ -654,6 +662,8 @@ asmlinkage long sys_chmod(const char __u newattrs.ia_mode = (mode &S_IALLUGO ) | (inode->i_mode & ~S_IALLUGO ); newattrs.ia_valid =ATTR_MODE |ATTR_CTIME ; error =notify_change (nd.dentry, &newattrs); +if (!error &&IS_SYNC (inode)) +sync_inode_wodata (inode);up (&inode->i_sem); dput_and_out:
@@ -692,6 +702,8 @@ static int chown_common(struct dentry * newattrs.ia_valid |=ATTR_KILL_SUID |ATTR_KILL_SGID ;down (&inode->i_sem); error =notify_change (dentry, &newattrs); +if (!error &&IS_SYNC (inode)) +sync_inode_wodata (inode);up (&inode->i_sem); out:return error;
include/linux/fs.h +1 -0
@@ -1082,6 +1082,7 @@ static inline void file_accessed(struct }int sync_inode (struct inode *inode,struct writeback_control *wbc); +int sync_inode_wodata (struct inode *inode);/** * struct export_operations - for nfsd to communicate with file systems
Re: [PATCH 1/2] miss-sync changes on attributes (Re: [PATCH 2/2][FAT] miss-sync issues on sync mount (miss-sync on utime))
In reply to Machida, HiroyukiQuoted 26 lines · Hiroyuki
This patch adds inode-sync after attribute changes, if needed.
* fs-sync-attr.patch for 2.6.13
fs/fs-writeback.c | 19 +++++++++++++++++++ fs/open.c | 12 ++++++++++++ include/linux/fs.h | 1 + 4 files changed, 32 insertions(+)Signed-off-by Hiroyuki Machida <[email protected]>fs/fs-writeback.c +8
-0@@ -593,6 +593,25 @@ int sync_inode(struct inode *inode, struEXPORT_SYMBOL (sync_inode);/** +* sync_inode_wodata - sync(write and wait) inode to disk, without it's data. +* @inode: the inode to sync +* +* sync_inode_wodata() will write an inode then wait. It will also +* correctly update the inode on its superblock's dirty inode lists +* and will update inode->i_state. +* +* The caller must have a ref on the inode.
fs/fs-writeback.c int sync_inode(struct inode *inode, stru · line 613
Quoted 10 lines
fs/fs-writeback.c +10
-0+*/ +int sync_inode_wodata (struct inode *inode) +{ +struct writeback_control wbc = { + .sync_mode =WB_SYNC_ALL ,/* wait */ + .nr_to_write =0 ,/* no data to be written */ + }; +return sync_inode (inode, &wbc); +} +
I think this function duplicates write_inode_now()?
OGAWA Hirofumi
maintainerRe: [PATCH 1/2] miss-sync changes on attributes (Re: [PATCH 2/2][FAT] miss-sync issues on sync mount (miss-sync on utime))
Quoted 13 lines · Andrew Morton
Quoted 13 lines
/**
+ *sync_inode_wodata- sync(write and wait) inode to disk, without it's data.
+ * @inode: the inode to sync
+ *
+ *sync_inode_wodata()will write an inode then wait. It will also
+ * correctly update the inode on its superblock's dirty inode lists
+ * and will updateinode->i_state.
+ *
+ * The caller must have a ref on the inode.
+ */fs/fs-writeback.c +3
-0+int sync_inode_wodata (struct inode *inode) +{ +struct writeback_control wbc = {
Quoted 8 lines
fs/fs-writeback.c int sync_inode(struct inode *inode, stru · line 613
Quoted 6 lines
fs/fs-writeback.c +6
-0+ .sync_mode = WB_SYNC_ALL, /* wait */ + .nr_to_write = 0,/* no data to be written */ + }; +return sync_inode (inode, &wbc); +} +I think this function duplicates
write_inode_now()?
write_inode_now() seems to write data pages, but this doesn't write (.nr_to_write = 0).
Signature · 1 line
OGAWA Hirofumi <[email protected]>
Re: [PATCH 1/2] miss-sync changes on attributes (Re: [PATCH 2/2][FAT] miss-sync issues on sync mount (miss-sync on utime))
Quoted 25 lines · OGAWA Hirofumi
Quoted 13 lines · Andrew Morton
Quoted 13 lines
/**
+ *sync_inode_wodata- sync(write and wait) inode to disk, without it's data.
+ * @inode: the inode to sync
+ *
+ *sync_inode_wodata()will write an inode then wait. It will also
+ * correctly update the inode on its superblock's dirty inode lists
+ * and will updateinode->i_state.
+ *
+ * The caller must have a ref on the inode.
+ */(quoted diff) +3
-0+int sync_inode_wodata(struct inode *inode) +{ + struct writeback_control wbc = {Quoted 8 lines
Review
Quoted 6 lines
(quoted diff) +6
-0+ .sync_mode = WB_SYNC_ALL, /* wait */ + .nr_to_write = 0,/* no data to be written */ + }; + return sync_inode(inode, &wbc); +} +I think this function duplicates
write_inode_now()?
Quoted 2 lines
write_inode_now()seems to write data pages, but this doesn't write (.nr_to_write = 0).
hm, OK.
However there's not much point in writing a brand-new function when write_inode_now() almost does the right thing. We can share the implementation within fs-writeback.c.
<looks>
Isn't write_inode_now() buggy? If !mapping_cap_writeback_dirty() we should still write the inode itself?
fs/fs-writeback.c renamed from fs/fs-writeback.c~write_inode_now-write-inode-if-not-bdi_cap_no_writeback +1 -1
@@ -558,7 +558,7 @@ int write_inode_now(struct inode *inode, };if (!mapping_cap_writeback_dirty (inode->i_mapping)) -return 0 ; + wbc.nr_to_write =0 ;might_sleep ();spin_lock (&inode_lock);
_
OGAWA Hirofumi
maintainerRe: [PATCH 1/2] miss-sync changes on attributes (Re: [PATCH 2/2][FAT] miss-sync issues on sync mount (miss-sync on utime))
Quoted 3 lines · Andrew Morton
However there's not much point in writing a brand-new function when
write_inode_now()almost does the right thing. We can share the implementation withinfs-writeback.c.
Indeed. We use the generic_osync_inode() for it?
Quoted 2 lines
Isn't
write_inode_now()buggy? If !mapping_cap_writeback_dirty() we should still write the inode itself?
Indeed. It seems we should write the dirty inode to backing device's buffers. sync_sb_inodes() too? If so, really buggy.. I'll check it.
Signature · 1 line
OGAWA Hirofumi <[email protected]>
OGAWA Hirofumi
maintainerRe: [PATCH 1/2] miss-sync changes on attributes (Re: [PATCH 2/2][FAT] miss-sync issues on sync mount (miss-sync on utime))
Quoted 5 lines · OGAWA Hirofumi
Quoted 2 lines
Isn't
write_inode_now()buggy? If !mapping_cap_writeback_dirty() we should still write the inode itself?Indeed. It seems we should write the dirty inode to backing device's buffers.
sync_sb_inodes()too? If so, really buggy.. I'll check it.
write_inode_now() seems ok.
If !mapping_cap_writeback_dirty(), the inode is bdev_inode itself or ram-based fs's inode, so ->write_inode() is not needed. And if backing_dev is ramdisk, mapping->backing_dev_info was setted the following special bdi.
static struct backing_dev_info rd_file_backing_dev_info = {
.ra_pages = 0, /* No readahead */
.capabilities = BDI_CAP_MAP_COPY, /* Does contribute to dirty memory */
.unplug_io_fn = default_unplug_io_fn,
};
Signature · 1 line
OGAWA Hirofumi <[email protected]>
Re: [PATCH 1/2] miss-sync changes on attributes (Re: [PATCH 2/2][FAT] miss-sync issues on sync mount (miss-sync on utime))
In reply to OGAWA HirofumiQuoted 9 lines · OGAWA Hirofumi
Quoted 3 lines · Andrew Morton
However there's not much point in writing a brand-new function when
write_inode_now()almost does the right thing. We can share the implementation withinfs-writeback.c.Indeed. We use the
generic_osync_inode()for it?
Please let me confirm.
Using generic_osync_inode(inode, NULL, OSYNC_INODE) instaed of sync_inode_wodata(inode) is peferable for changes on fs/open.c, even it would write data. Is it correct?
Signature · 1 line
Hiroyuki Machida [email protected]
Re: [PATCH 1/2] miss-sync changes on attributes (Re: [PATCH 2/2][FAT] miss-sync issues on sync mount (miss-sync on utime))
Quoted 12 lines · Hiroyuki
Quoted 8 lines · OGAWA Hirofumi
Quoted 3 lines · Andrew Morton
However there's not much point in writing a brand-new function when
write_inode_now()almost does the right thing. We can share the implementation withinfs-writeback.c.
Quoted 7 lines
Quoted 1 line
Indeed. We use the
generic_osync_inode()for it?Please let me confirm.
Usinggeneric_osync_inode(inode, NULL, OSYNC_INODE)instaed ofsync_inode_wodata(inode)is peferable for changes onfs/open.c, even it would write data. Is it correct?
I don't know. It depends on what you're actually trying to do, and I don't recall anyone having described that!
Re: [PATCH 1/2] miss-sync changes on attributes (Re: [PATCH 2/2][FAT] miss-sync issues on sync mount (miss-sync on utime))
Quoted 24 lines · Andrew Morton
Quoted 13 lines · Hiroyuki
Quoted 9 lines · OGAWA Hirofumi
Quoted 3 lines · Andrew Morton
However there's not much point in writing a brand-new function when
write_inode_now()almost does the right thing. We can share the implementation withinfs-writeback.c.Quoted 7 lines
Quoted 1 line
Indeed. We use the
generic_osync_inode()for it?Please let me confirm.
Usinggeneric_osync_inode(inode, NULL, OSYNC_INODE)instaed ofsync_inode_wodata(inode)is peferable for changes onfs/open.c, even it would write data. Is it correct?
Quoted 2 lines
I don't know. It depends on what you're actually trying to do, and I don't recall anyone having described that!
I'm just little confused, because I realized generic_osync_inode(,,OSYNC_INODE) calls sync_inode_now(), however Ogawasa-san pointed out sync_inode_now() which my first patch used is writing data page.
Signature · 2 lines
Hiroyuki Machida [email protected] SSW Dept. HENC, Sony Corp.
OGAWA Hirofumi
maintainerRe: [PATCH 1/2] miss-sync changes on attributes (Re: [PATCH 2/2][FAT] miss-sync issues on sync mount (miss-sync on utime))
In reply to Machida, HiroyukiQuoted 6 lines · Hiroyuki
Quoted 5 lines · OGAWA Hirofumi
Quoted 3 lines · Andrew Morton
However there's not much point in writing a brand-new function when
write_inode_now()almost does the right thing. We can share the implementation withinfs-writeback.c.
Quoted 6 lines
Quoted 1 line
Indeed. We use the
generic_osync_inode()for it?Please let me confirm.
Usinggeneric_osync_inode(inode, NULL, OSYNC_INODE)instaed ofsync_inode_wodata(inode)is peferable for changes onfs/open.c, even it would write data. Is it correct?
No, I only thought the interface is good. I don't know why it writes data pages even if OSYNC_INODE only.
Signature · 1 line
OGAWA Hirofumi <[email protected]>
Re: [PATCH 1/2] miss-sync changes on attributes (Re: [PATCH 2/2][FAT] miss-sync issues on sync mount (miss-sync on utime))
Quoted 14 lines · OGAWA Hirofumi
Quoted 11 lines · Hiroyuki
Quoted 8 lines · OGAWA Hirofumi
Quoted 3 lines · Andrew Morton
However there's not much point in writing a brand-new function when
write_inode_now()almost does the right thing. We can share the implementation withinfs-writeback.c.Indeed. We use the
generic_osync_inode()for it?
Quoted 8 lines
Quoted 4 lines
Please let me confirm.
Usinggeneric_osync_inode(inode, NULL, OSYNC_INODE)instaed ofsync_inode_wodata(inode)is peferable for changes onfs/open.c, even it would write data. Is it correct?No, I only thought the interface is good. I don't know why it writes data pages even if
OSYNC_INODEonly.
I checked 2.6.13 tree, following functions call generic_osync_inode(). However noone calls it with OSYNC_INODE. SO I can't find intention of it's usage.
Does anyone know why generic_osync_inode() trys to write data page, even if OSYNC_INODE only passed ?
- fs/reiserfs/file.c
reiserfs_file_write() OSYNC_METADATA | OSYNC_DATA
- mm/filemap.c
sync_page_range() OSYNC_METADATA
sync_page_range_nolock() OSYNC_METADATA
generic_file_direct_write OSYNC_METADATA
Signature · 1 line
Hiroyuki Machida [email protected]
PATCH 1/1 generic_osync_inode() with OSYNC_INODE only passed (Re: [PATCH 1/2] miss-sync changes on attributes)
generic_osync_inode() seems to do over-writing, if OSYNC_INODE only passed. According comments of generic_osync_inode(), it is expected to write inode itself only. Current implementation trys to write data page, even if OSYNC_INODE only passed. This patch fixes it.
This patch is preparetion of other patch to fix "miss-sync changes on attributes".
Quoted 46 lines · Hiroyuki
Quoted 23 lines · OGAWA Hirofumi
Quoted 10 lines · Hiroyuki
Quoted 8 lines · OGAWA Hirofumi
Quoted 3 lines · Andrew Morton
However there's not much point in writing a brand-new function when
write_inode_now()almost does the right thing. We can share the implementation withinfs-writeback.c.Quoted 7 lines
Quoted 1 line
Indeed. We use the
generic_osync_inode()for it?Please let me confirm.
Usinggeneric_osync_inode(inode, NULL, OSYNC_INODE)instaed ofsync_inode_wodata(inode)is peferable for changes onfs/open.c, even it would write data. Is it correct?Quoted 2 lines
No, I only thought the interface is good. I don't know why it writes data pages even if
OSYNC_INODEonly.I checked 2.6.13 tree, following functions call
generic_osync_inode(). However noone calls it withOSYNC_INODE. SO I can't find intention of it's usage.Does anyone know why
generic_osync_inode()trys to write data page, even ifOSYNC_INODEonly passed ?-
fs/reiserfs/file.c
reiserfs_file_write()OSYNC_METADATA|OSYNC_DATA
-mm/filemap.c
sync_page_range()OSYNC_METADATA
sync_page_range_nolock()OSYNC_METADATA
generic_file_direct_writeOSYNC_METADATA
Signature · 1 line
Hiroyuki Machida [email protected]
PATCH 1/1 generic_osync_inode() with OSYNC_INODE only passed (Re: [PATCH 1/2] miss-sync changes on attributes)
In reply to Machida, Hiroyukigeneric__inode() seems to do over-writing, if OSYNC_INODE only passed. According comments of generic_osync_inode(), it is expected to write inode itself only. Current implementation trys to write data page, even if OSYNC_INODE only passed. This patch fixes it.
This patch is preparetion of other patch to fix "miss-sync changes on attributes".
Quoted 46 lines · Hiroyuki
Quoted 23 lines · OGAWA Hirofumi
Quoted 10 lines · Hiroyuki
Quoted 8 lines · OGAWA Hirofumi
Quoted 3 lines · Andrew Morton
However there's not much point in writing a brand-new function when
write_inode_now()almost does the right thing. We can share the implementation withinfs-writeback.c.Quoted 7 lines
Quoted 1 line
Indeed. We use the
generic_osync_inode()for it?Please let me confirm.
Usinggeneric_osync_inode(inode, NULL, OSYNC_INODE)instaed ofsync_inode_wodata(inode)is peferable for changes onfs/open.c, even it would write data. Is it correct?Quoted 2 lines
No, I only thought the interface is good. I don't know why it writes data pages even if
OSYNC_INODEonly.I checked 2.6.13 tree, following functions call
generic_osync_inode(). However noone calls it withOSYNC_INODE. SO I can't find intention of it's usage.Does anyone know why
generic_osync_inode()trys to write data page, even ifOSYNC_INODEonly passed ?-
fs/reiserfs/file.c
reiserfs_file_write()OSYNC_METADATA|OSYNC_DATA
-mm/filemap.c
sync_page_range()OSYNC_METADATA
sync_page_range_nolock()OSYNC_METADATA
generic_file_direct_writeOSYNC_METADATA
Signature · 1 line
Hiroyuki Machida [email protected]
fs-writeback.c renamed from fs-writeback.c.ORG +15 -4
@@ -614,6 +614,7 @@ int generic_osync_inode(struct inode *inint err =0 ;int need_write_inode_now =0 ;int err2; +long nr_write; current->flags |=PF_SYNCWRITE ;if (what &OSYNC_DATA )
@@ -632,13 +633,23 @@ int generic_osync_inode(struct inode *inspin_lock (&inode_lock);if ((inode->i_state &I_DIRTY ) && - ((what &OSYNC_INODE ) || (inode->i_state &I_DIRTY_DATASYNC ))) + ((what &OSYNC_INODE ) || (inode->i_state &I_DIRTY_DATASYNC ))) { need_write_inode_now =1 ; + nr_write = (what ==OSYNC_INODE ) ?0 :LONG_MAX ; + }spin_unlock (&inode_lock); -if (need_write_inode_now) { - err2 =write_inode_now (inode,1 ); -if (!err) +if (need_write_inode_now && +mapping_cap_writeback_dirty (inode->i_mapping)) { +struct writeback_control wbc = { + .sync_mode =WB_SYNC_ALL , + }; + + wbc.nr_to_write = nr_write; +might_sleep (); + err2 =sync_inode (inode, &wbc); +wait_on_inode (inode); +if (!err) err = err2; }else
OGAWA Hirofumi
maintainerPATCH 1/1 Fix !mapping_cap_writeback_dirty(inode->i_mapping)
In reply to Andrew MortonQuoted 7 lines · Andrew Morton
Isn't
write_inode_now()buggy? If !mapping_cap_writeback_dirty() we should still write the inode itself?diff -puN
fs/fs-writeback.c~write_inode_now-write-inode-if-not-bdi_cap_no_writebackfs/fs-writeback.c
fs/fs-writeback.c int write_inode_now(struct inode *inode, · line 564
Quoted 8 lines
fs/fs-writeback.c renamed from fs/fs-writeback.c~write_inode_now-write-inode-if-not-bdi_cap_no_writeback +1
-1@@ -558,7 +558,7 @@ int write_inode_now(struct inode *inode, };if (!mapping_cap_writeback_dirty (inode->i_mapping)) -return 0 ; + wbc.nr_to_write =0 ;might_sleep ();spin_lock (&inode_lock);
You are right, and I was wrong.
Yes, if block device has BDI_CAP_NO_WRITEBACK and inode->i_mapping was changing to bd_inode->i_mapping,
the !mapping_cap_writeback_dirty(inode->i_mapping) is true, so we need to write the inode itself of block special file.
I think we need to fix sync_sb_inodes() too. What do you think?
Since wbc.nr_to_write includes the information on how many pages were written, we can't change wbc.nr_to_write in sync_sb_inodes().
This patch fixed the following case,
# mke2fs -m0 -F file
# mount -t ext2 file mnt -o loop
# cd mnt
# mknod ram b 1 0
# cat ram
# cd ..
# umount mnt
# e2fsck -f file
"mnt/ram" wasn't flushed and it was corruptedThanks.
Signature · 134 lines
OGAWA Hirofumi <[email protected]> Signed-off-by: OGAWA Hirofumi <[email protected]> --- fs/fs-writeback.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff -puN fs/fs-writeback.c~device-inode-write-fix fs/fs-writeback.c --- linux-2.6.14/fs/fs-writeback.c~device-inode-write-fix 2005-10-29 08:06:28.000000000 +0900 +++ linux-2.6.14-hirofumi/fs/fs-writeback.c 2005-10-29 08:06:28.000000000 +0900 @@ -151,7 +151,8 @@ static int write_inode(struct inode *ino * Called under inode_lock. */ static int -__sync_single_inode(struct inode *inode, struct writeback_control *wbc) +__sync_single_inode(struct inode *inode, struct writeback_control *wbc, + int inode_only) { unsigned dirty; struct address_space *mapping = inode->i_mapping; @@ -168,7 +169,9 @@ __sync_single_inode(struct inode *inode, spin_unlock(&inode_lock); - ret = do_writepages(mapping, wbc); + ret = 0; + if (!inode_only) + ret = do_writepages(mapping, wbc); /* Don't write the inode if only I_DIRTY_PAGES was set */ if (dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) { @@ -177,7 +180,7 @@ __sync_single_inode(struct inode *inode, ret = err; } - if (wait) { + if (!inode_only && wait) { int err = filemap_fdatawait(mapping); if (ret == 0) ret = err; @@ -242,7 +245,7 @@ __sync_single_inode(struct inode *inode, */ static int __writeback_single_inode(struct inode *inode, - struct writeback_control *wbc) + struct writeback_control *wbc, int inode_only) { wait_queue_head_t *wqh; @@ -267,7 +270,7 @@ __writeback_single_inode(struct inode *i spin_lock(&inode_lock); } while (inode->i_state & I_LOCK); } - return __sync_single_inode(inode, wbc); + return __sync_single_inode(inode, wbc, inode_only); } /* @@ -304,6 +307,7 @@ static void sync_sb_inodes(struct super_block *sb, struct writeback_control *wbc) { const unsigned long start = jiffies; /* livelock avoidance */ + int inode_only; if (!wbc->for_kupdate || list_empty(&sb->s_io)) list_splice_init(&sb->s_dirty, &sb->s_io); @@ -315,7 +319,8 @@ sync_sb_inodes(struct super_block *sb, s struct backing_dev_info *bdi = mapping->backing_dev_info; long pages_skipped; - if (!bdi_cap_writeback_dirty(bdi)) { + inode_only = 0; + if (!mapping_cap_writeback_dirty(mapping)) { list_move(&inode->i_list, &sb->s_dirty); if (sb == blockdev_superblock) { /* @@ -324,12 +329,7 @@ sync_sb_inodes(struct super_block *sb, s */ continue; } - /* - * Dirty memory-backed inode against a filesystem other - * than the kernel-internal bdev filesystem. Skip the - * entire superblock. - */ - break; + inode_only = 1; } if (wbc->nonblocking && bdi_write_congested(bdi)) { @@ -363,7 +363,7 @@ sync_sb_inodes(struct super_block *sb, s BUG_ON(inode->i_state & I_FREEING); __iget(inode); pages_skipped = wbc->pages_skipped; - __writeback_single_inode(inode, wbc); + __writeback_single_inode(inode, wbc, inode_only); if (wbc->sync_mode == WB_SYNC_HOLD) { inode->dirtied_when = jiffies; list_move(&inode->i_list, &sb->s_dirty); @@ -551,18 +551,18 @@ void sync_inodes(int wait) int write_inode_now(struct inode *inode, int sync) { - int ret; struct writeback_control wbc = { .nr_to_write = LONG_MAX, .sync_mode = WB_SYNC_ALL, }; + int ret, inode_only = 0; if (!mapping_cap_writeback_dirty(inode->i_mapping)) - return 0; + inode_only = 1; might_sleep(); spin_lock(&inode_lock); - ret = __writeback_single_inode(inode, &wbc); + ret = __writeback_single_inode(inode, &wbc, inode_only); spin_unlock(&inode_lock); if (sync) wait_on_inode(inode); @@ -586,7 +586,7 @@ int sync_inode(struct inode *inode, stru int ret; spin_lock(&inode_lock); - ret = __writeback_single_inode(inode, wbc); + ret = __writeback_single_inode(inode, wbc, 0); spin_unlock(&inode_lock); return ret; } _
OGAWA Hirofumi
maintainerPATCH 1/1 Don't use pdflush for filesystems has BDI_CAP_NO_WRITEBACK
Hi,
If inodes of filesystem has BDI_CAP_NO_WRITEBACK, it shouldn't be needed to flush the inodes by pdflush at all. So, this patch stops puting the inode on the sb->s_dirty, by setting I_DIRTY as initial state.
With this patch, I think unnecessary flush is stopped.
BTW, probably all most of on memory filesystems also doesn't need to flush by pdflush...?
Thanks.
Signature · 121 lines
OGAWA Hirofumi <[email protected]> Signed-off-by: OGAWA Hirofumi <[email protected]> --- fs/hugetlbfs/inode.c | 1 + fs/pipe.c | 8 +------- fs/ramfs/inode.c | 1 + fs/relayfs/inode.c | 1 + fs/sysfs/inode.c | 1 + include/linux/fs.h | 10 ++++++++++ kernel/cpuset.c | 1 + mm/shmem.c | 1 + 8 files changed, 17 insertions(+), 7 deletions(-) diff -puN fs/hugetlbfs/inode.c~add-set_inode_noflush fs/hugetlbfs/inode.c --- linux-2.6.14/fs/hugetlbfs/inode.c~add-set_inode_noflush 2005-10-29 08:13:57.000000000 +0900 +++ linux-2.6.14-hirofumi/fs/hugetlbfs/inode.c 2005-10-29 08:13:57.000000000 +0900 @@ -394,6 +394,7 @@ static struct inode *hugetlbfs_get_inode inode = new_inode(sb); if (inode) { struct hugetlbfs_inode_info *info; + set_inode_noflush(inode); inode->i_mode = mode; inode->i_uid = uid; inode->i_gid = gid; diff -puN fs/pipe.c~add-set_inode_noflush fs/pipe.c --- linux-2.6.14/fs/pipe.c~add-set_inode_noflush 2005-10-29 08:13:57.000000000 +0900 +++ linux-2.6.14-hirofumi/fs/pipe.c 2005-10-29 08:13:57.000000000 +0900 @@ -697,13 +697,7 @@ static struct inode * get_pipe_inode(voi PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 1; inode->i_fop = &rdwr_pipe_fops; - /* - * Mark the inode dirty from the very beginning, - * that way it will never be moved to the dirty - * list because "mark_inode_dirty()" will think - * that it already _is_ on the dirty list. - */ - inode->i_state = I_DIRTY; + set_inode_noflush(inode); inode->i_mode = S_IFIFO | S_IRUSR | S_IWUSR; inode->i_uid = current->fsuid; inode->i_gid = current->fsgid; diff -puN fs/ramfs/inode.c~add-set_inode_noflush fs/ramfs/inode.c --- linux-2.6.14/fs/ramfs/inode.c~add-set_inode_noflush 2005-10-29 08:13:57.000000000 +0900 +++ linux-2.6.14-hirofumi/fs/ramfs/inode.c 2005-10-29 08:13:57.000000000 +0900 @@ -55,6 +55,7 @@ struct inode *ramfs_get_inode(struct sup struct inode * inode = new_inode(sb); if (inode) { + set_inode_noflush(inode); inode->i_mode = mode; inode->i_uid = current->fsuid; inode->i_gid = current->fsgid; diff -puN fs/relayfs/inode.c~add-set_inode_noflush fs/relayfs/inode.c --- linux-2.6.14/fs/relayfs/inode.c~add-set_inode_noflush 2005-10-29 08:13:57.000000000 +0900 +++ linux-2.6.14-hirofumi/fs/relayfs/inode.c 2005-10-29 08:13:57.000000000 +0900 @@ -52,6 +52,7 @@ static struct inode *relayfs_get_inode(s return NULL; } + set_inode_noflush(inode); inode->i_mode = mode; inode->i_uid = 0; inode->i_gid = 0; diff -puN fs/sysfs/inode.c~add-set_inode_noflush fs/sysfs/inode.c --- linux-2.6.14/fs/sysfs/inode.c~add-set_inode_noflush 2005-10-29 08:13:57.000000000 +0900 +++ linux-2.6.14-hirofumi/fs/sysfs/inode.c 2005-10-29 08:13:57.000000000 +0900 @@ -113,6 +113,7 @@ struct inode * sysfs_new_inode(mode_t mo { struct inode * inode = new_inode(sysfs_sb); if (inode) { + set_inode_noflush(inode); inode->i_blksize = PAGE_CACHE_SIZE; inode->i_blocks = 0; inode->i_mapping->a_ops = &sysfs_aops; diff -puN include/linux/fs.h~add-set_inode_noflush include/linux/fs.h --- linux-2.6.14/include/linux/fs.h~add-set_inode_noflush 2005-10-29 08:13:57.000000000 +0900 +++ linux-2.6.14-hirofumi/include/linux/fs.h 2005-10-29 08:13:57.000000000 +0900 @@ -1075,6 +1075,16 @@ static inline void file_accessed(struct touch_atime(file->f_vfsmnt, file->f_dentry); } +static inline void set_inode_noflush(struct inode *inode) +{ + /* + * Mark the inode dirty from the very beginning, that way it + * will never be moved to the dirty list because "mark_inode_dirty()" + * will think that it already _is_ on the dirty list. + */ + inode->i_state |= I_DIRTY; +} + int sync_inode(struct inode *inode, struct writeback_control *wbc); /** diff -puN kernel/cpuset.c~add-set_inode_noflush kernel/cpuset.c --- linux-2.6.14/kernel/cpuset.c~add-set_inode_noflush 2005-10-29 08:13:57.000000000 +0900 +++ linux-2.6.14-hirofumi/kernel/cpuset.c 2005-10-29 08:13:57.000000000 +0900 @@ -236,6 +236,7 @@ static struct inode *cpuset_new_inode(mo struct inode *inode = new_inode(cpuset_sb); if (inode) { + set_inode_noflush(inode); inode->i_mode = mode; inode->i_uid = current->fsuid; inode->i_gid = current->fsgid; diff -puN mm/shmem.c~add-set_inode_noflush mm/shmem.c --- linux-2.6.14/mm/shmem.c~add-set_inode_noflush 2005-10-29 08:13:57.000000000 +0900 +++ linux-2.6.14-hirofumi/mm/shmem.c 2005-10-29 08:13:57.000000000 +0900 @@ -1283,6 +1283,7 @@ shmem_get_inode(struct super_block *sb, inode = new_inode(sb); if (inode) { + set_inode_noflush(inode); inode->i_mode = mode; inode->i_uid = current->fsuid; inode->i_gid = current->fsgid; _
OGAWA Hirofumi
maintainerRe: [PATCH] Don't use pdflush for filesystems has BDI_CAP_NO_WRITEBACK
fs/hugetlbfs/inode.c static struct inode *hugetlbfs_get_inode · line 400
Quoted 11 lines · OGAWA Hirofumi
diff -puN
fs/hugetlbfs/inode.c~add-set_inode_noflushfs/hugetlbfs/inode.cfs/hugetlbfs/inode.c renamed from fs/hugetlbfs/inode.c~add-set_inode_noflush +1
-0@@ -394,6 +394,7 @@ static struct inode *hugetlbfs_get_inode inode =new_inode (sb);if (inode) {struct hugetlbfs_inode_info *info; +set_inode_noflush (inode); inode->i_mode = mode; inode->i_uid = uid; inode->i_gid = gid;
Sigh, I'm forgetting block special file again. Sorry for wrong patch.
Signature · 1 line
OGAWA Hirofumi <[email protected]>