diff options
author | Boaz Harrosh <bharrosh@panasas.com> | 2009-12-27 10:01:42 -0500 |
---|---|---|
committer | Boaz Harrosh <bharrosh@panasas.com> | 2010-01-05 02:14:32 -0500 |
commit | efd124b999fb4d426b30675f1684521af0872789 (patch) | |
tree | f9421d61b3c4faf682fc1a52b72b241fa9b37558 /fs | |
parent | 89be503021f550575fc896671b569941140b2c2e (diff) |
exofs: simple_write_end does not mark_inode_dirty
exofs uses simple_write_end() for it's .write_end handler. But
it is not enough because simple_write_end() does not call
mark_inode_dirty() when it extends i_size. So even if we do
call mark_inode_dirty at beginning of write out, with a very
long IO and a saturated system we might get the .write_inode()
called while still extend-writing to file and miss out on the last
i_size updates.
So override .write_end, call simple_write_end(), and afterwords if
i_size was changed call mark_inode_dirty().
It stands to logic that since simple_write_end() was the one extending
i_size it should also call mark_inode_dirty(). But it looks like all
users of simple_write_end() are memory-bound pseudo filesystems, who
could careless about mark_inode_dirty(). I might submit a
warning-comment patch to simple_write_end() in future.
CC: Stable <stable@kernel.org>
Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/exofs/inode.c | 17 |
1 files changed, 16 insertions, 1 deletions
diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c index 698a8636d39c..2afbcebeda71 100644 --- a/fs/exofs/inode.c +++ b/fs/exofs/inode.c | |||
@@ -738,13 +738,28 @@ static int exofs_write_begin_export(struct file *file, | |||
738 | fsdata); | 738 | fsdata); |
739 | } | 739 | } |
740 | 740 | ||
741 | static int exofs_write_end(struct file *file, struct address_space *mapping, | ||
742 | loff_t pos, unsigned len, unsigned copied, | ||
743 | struct page *page, void *fsdata) | ||
744 | { | ||
745 | struct inode *inode = mapping->host; | ||
746 | /* According to comment in simple_write_end i_mutex is held */ | ||
747 | loff_t i_size = inode->i_size; | ||
748 | int ret; | ||
749 | |||
750 | ret = simple_write_end(file, mapping,pos, len, copied, page, fsdata); | ||
751 | if (i_size != inode->i_size) | ||
752 | mark_inode_dirty(inode); | ||
753 | return ret; | ||
754 | } | ||
755 | |||
741 | const struct address_space_operations exofs_aops = { | 756 | const struct address_space_operations exofs_aops = { |
742 | .readpage = exofs_readpage, | 757 | .readpage = exofs_readpage, |
743 | .readpages = exofs_readpages, | 758 | .readpages = exofs_readpages, |
744 | .writepage = exofs_writepage, | 759 | .writepage = exofs_writepage, |
745 | .writepages = exofs_writepages, | 760 | .writepages = exofs_writepages, |
746 | .write_begin = exofs_write_begin_export, | 761 | .write_begin = exofs_write_begin_export, |
747 | .write_end = simple_write_end, | 762 | .write_end = exofs_write_end, |
748 | }; | 763 | }; |
749 | 764 | ||
750 | /****************************************************************************** | 765 | /****************************************************************************** |