diff options
author | Christoph Hellwig <hch@lst.de> | 2010-10-06 04:48:20 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2010-10-25 21:18:19 -0400 |
commit | c37650161a53c01ddd88587675f9a4adc909a73e (patch) | |
tree | 85821998de9a6723dedc42488b9491db9692d1e3 /fs | |
parent | 81fca444001e5a41ab80ce8cf9a5734c00ec6546 (diff) |
fs: add sync_inode_metadata
Add a new helper to write out the inode using the writeback code,
that is including the correct dirty bit and list manipulation. A few
of filesystems already opencode this, and a lot of others should be
using it instead of using write_inode_now which also writes out the
data.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/exofs/file.c | 6 | ||||
-rw-r--r-- | fs/ext2/dir.c | 2 | ||||
-rw-r--r-- | fs/ext2/ext2.h | 1 | ||||
-rw-r--r-- | fs/ext2/inode.c | 11 | ||||
-rw-r--r-- | fs/ext2/xattr.c | 2 | ||||
-rw-r--r-- | fs/fs-writeback.c | 20 | ||||
-rw-r--r-- | fs/libfs.c | 6 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 16 |
8 files changed, 28 insertions, 36 deletions
diff --git a/fs/exofs/file.c b/fs/exofs/file.c index 68cb23e3bb98..b905c79b4f0a 100644 --- a/fs/exofs/file.c +++ b/fs/exofs/file.c | |||
@@ -46,10 +46,6 @@ static int exofs_file_fsync(struct file *filp, int datasync) | |||
46 | { | 46 | { |
47 | int ret; | 47 | int ret; |
48 | struct inode *inode = filp->f_mapping->host; | 48 | struct inode *inode = filp->f_mapping->host; |
49 | struct writeback_control wbc = { | ||
50 | .sync_mode = WB_SYNC_ALL, | ||
51 | .nr_to_write = 0, /* metadata-only; caller takes care of data */ | ||
52 | }; | ||
53 | struct super_block *sb; | 49 | struct super_block *sb; |
54 | 50 | ||
55 | if (!(inode->i_state & I_DIRTY)) | 51 | if (!(inode->i_state & I_DIRTY)) |
@@ -57,7 +53,7 @@ static int exofs_file_fsync(struct file *filp, int datasync) | |||
57 | if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) | 53 | if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) |
58 | return 0; | 54 | return 0; |
59 | 55 | ||
60 | ret = sync_inode(inode, &wbc); | 56 | ret = sync_inode_metadata(inode, 1); |
61 | 57 | ||
62 | /* This is a good place to write the sb */ | 58 | /* This is a good place to write the sb */ |
63 | /* TODO: Sechedule an sb-sync on create */ | 59 | /* TODO: Sechedule an sb-sync on create */ |
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c index 764109886ec0..2709b34206ab 100644 --- a/fs/ext2/dir.c +++ b/fs/ext2/dir.c | |||
@@ -98,7 +98,7 @@ static int ext2_commit_chunk(struct page *page, loff_t pos, unsigned len) | |||
98 | if (IS_DIRSYNC(dir)) { | 98 | if (IS_DIRSYNC(dir)) { |
99 | err = write_one_page(page, 1); | 99 | err = write_one_page(page, 1); |
100 | if (!err) | 100 | if (!err) |
101 | err = ext2_sync_inode(dir); | 101 | err = sync_inode_metadata(dir, 1); |
102 | } else { | 102 | } else { |
103 | unlock_page(page); | 103 | unlock_page(page); |
104 | } | 104 | } |
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h index 416daa62242c..6346a2acf326 100644 --- a/fs/ext2/ext2.h +++ b/fs/ext2/ext2.h | |||
@@ -120,7 +120,6 @@ extern unsigned long ext2_count_free (struct buffer_head *, unsigned); | |||
120 | extern struct inode *ext2_iget (struct super_block *, unsigned long); | 120 | extern struct inode *ext2_iget (struct super_block *, unsigned long); |
121 | extern int ext2_write_inode (struct inode *, struct writeback_control *); | 121 | extern int ext2_write_inode (struct inode *, struct writeback_control *); |
122 | extern void ext2_evict_inode(struct inode *); | 122 | extern void ext2_evict_inode(struct inode *); |
123 | extern int ext2_sync_inode (struct inode *); | ||
124 | extern int ext2_get_block(struct inode *, sector_t, struct buffer_head *, int); | 123 | extern int ext2_get_block(struct inode *, sector_t, struct buffer_head *, int); |
125 | extern int ext2_setattr (struct dentry *, struct iattr *); | 124 | extern int ext2_setattr (struct dentry *, struct iattr *); |
126 | extern void ext2_set_inode_flags(struct inode *inode); | 125 | extern void ext2_set_inode_flags(struct inode *inode); |
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 533699c16040..40ad210a5049 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c | |||
@@ -1203,7 +1203,7 @@ static int ext2_setsize(struct inode *inode, loff_t newsize) | |||
1203 | inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; | 1203 | inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; |
1204 | if (inode_needs_sync(inode)) { | 1204 | if (inode_needs_sync(inode)) { |
1205 | sync_mapping_buffers(inode->i_mapping); | 1205 | sync_mapping_buffers(inode->i_mapping); |
1206 | ext2_sync_inode (inode); | 1206 | sync_inode_metadata(inode, 1); |
1207 | } else { | 1207 | } else { |
1208 | mark_inode_dirty(inode); | 1208 | mark_inode_dirty(inode); |
1209 | } | 1209 | } |
@@ -1523,15 +1523,6 @@ int ext2_write_inode(struct inode *inode, struct writeback_control *wbc) | |||
1523 | return __ext2_write_inode(inode, wbc->sync_mode == WB_SYNC_ALL); | 1523 | return __ext2_write_inode(inode, wbc->sync_mode == WB_SYNC_ALL); |
1524 | } | 1524 | } |
1525 | 1525 | ||
1526 | int ext2_sync_inode(struct inode *inode) | ||
1527 | { | ||
1528 | struct writeback_control wbc = { | ||
1529 | .sync_mode = WB_SYNC_ALL, | ||
1530 | .nr_to_write = 0, /* sys_fsync did this */ | ||
1531 | }; | ||
1532 | return sync_inode(inode, &wbc); | ||
1533 | } | ||
1534 | |||
1535 | int ext2_setattr(struct dentry *dentry, struct iattr *iattr) | 1526 | int ext2_setattr(struct dentry *dentry, struct iattr *iattr) |
1536 | { | 1527 | { |
1537 | struct inode *inode = dentry->d_inode; | 1528 | struct inode *inode = dentry->d_inode; |
diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c index 8c29ae15129e..f84700be3274 100644 --- a/fs/ext2/xattr.c +++ b/fs/ext2/xattr.c | |||
@@ -699,7 +699,7 @@ ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh, | |||
699 | EXT2_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0; | 699 | EXT2_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0; |
700 | inode->i_ctime = CURRENT_TIME_SEC; | 700 | inode->i_ctime = CURRENT_TIME_SEC; |
701 | if (IS_SYNC(inode)) { | 701 | if (IS_SYNC(inode)) { |
702 | error = ext2_sync_inode (inode); | 702 | error = sync_inode_metadata(inode, 1); |
703 | /* In case sync failed due to ENOSPC the inode was actually | 703 | /* In case sync failed due to ENOSPC the inode was actually |
704 | * written (only some dirty data were not) so we just proceed | 704 | * written (only some dirty data were not) so we just proceed |
705 | * as if nothing happened and cleanup the unused block */ | 705 | * as if nothing happened and cleanup the unused block */ |
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index ab38fef1c9a1..29e3f409bbd0 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c | |||
@@ -1198,3 +1198,23 @@ int sync_inode(struct inode *inode, struct writeback_control *wbc) | |||
1198 | return ret; | 1198 | return ret; |
1199 | } | 1199 | } |
1200 | EXPORT_SYMBOL(sync_inode); | 1200 | EXPORT_SYMBOL(sync_inode); |
1201 | |||
1202 | /** | ||
1203 | * sync_inode - write an inode to disk | ||
1204 | * @inode: the inode to sync | ||
1205 | * @wait: wait for I/O to complete. | ||
1206 | * | ||
1207 | * Write an inode to disk and adjust it's dirty state after completion. | ||
1208 | * | ||
1209 | * Note: only writes the actual inode, no associated data or other metadata. | ||
1210 | */ | ||
1211 | int sync_inode_metadata(struct inode *inode, int wait) | ||
1212 | { | ||
1213 | struct writeback_control wbc = { | ||
1214 | .sync_mode = wait ? WB_SYNC_ALL : WB_SYNC_NONE, | ||
1215 | .nr_to_write = 0, /* metadata-only */ | ||
1216 | }; | ||
1217 | |||
1218 | return sync_inode(inode, &wbc); | ||
1219 | } | ||
1220 | EXPORT_SYMBOL(sync_inode_metadata); | ||
diff --git a/fs/libfs.c b/fs/libfs.c index 62baa0387d6e..2dbf4877d7ef 100644 --- a/fs/libfs.c +++ b/fs/libfs.c | |||
@@ -892,10 +892,6 @@ EXPORT_SYMBOL_GPL(generic_fh_to_parent); | |||
892 | */ | 892 | */ |
893 | int generic_file_fsync(struct file *file, int datasync) | 893 | int generic_file_fsync(struct file *file, int datasync) |
894 | { | 894 | { |
895 | struct writeback_control wbc = { | ||
896 | .sync_mode = WB_SYNC_ALL, | ||
897 | .nr_to_write = 0, /* metadata-only; caller takes care of data */ | ||
898 | }; | ||
899 | struct inode *inode = file->f_mapping->host; | 895 | struct inode *inode = file->f_mapping->host; |
900 | int err; | 896 | int err; |
901 | int ret; | 897 | int ret; |
@@ -906,7 +902,7 @@ int generic_file_fsync(struct file *file, int datasync) | |||
906 | if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) | 902 | if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) |
907 | return ret; | 903 | return ret; |
908 | 904 | ||
909 | err = sync_inode(inode, &wbc); | 905 | err = sync_inode_metadata(inode, 1); |
910 | if (ret == 0) | 906 | if (ret == 0) |
911 | ret = err; | 907 | ret = err; |
912 | return ret; | 908 | return ret; |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 661a6cf8e826..184938fcff04 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -281,23 +281,13 @@ commit_metadata(struct svc_fh *fhp) | |||
281 | { | 281 | { |
282 | struct inode *inode = fhp->fh_dentry->d_inode; | 282 | struct inode *inode = fhp->fh_dentry->d_inode; |
283 | const struct export_operations *export_ops = inode->i_sb->s_export_op; | 283 | const struct export_operations *export_ops = inode->i_sb->s_export_op; |
284 | int error = 0; | ||
285 | 284 | ||
286 | if (!EX_ISSYNC(fhp->fh_export)) | 285 | if (!EX_ISSYNC(fhp->fh_export)) |
287 | return 0; | 286 | return 0; |
288 | 287 | ||
289 | if (export_ops->commit_metadata) { | 288 | if (export_ops->commit_metadata) |
290 | error = export_ops->commit_metadata(inode); | 289 | return export_ops->commit_metadata(inode); |
291 | } else { | 290 | return sync_inode_metadata(inode, 1); |
292 | struct writeback_control wbc = { | ||
293 | .sync_mode = WB_SYNC_ALL, | ||
294 | .nr_to_write = 0, /* metadata only */ | ||
295 | }; | ||
296 | |||
297 | error = sync_inode(inode, &wbc); | ||
298 | } | ||
299 | |||
300 | return error; | ||
301 | } | 291 | } |
302 | 292 | ||
303 | /* | 293 | /* |