diff options
author | Boaz Harrosh <bharrosh@panasas.com> | 2011-08-26 21:00:32 -0700 |
---|---|---|
committer | Boaz Harrosh <bharrosh@panasas.com> | 2011-10-14 18:54:39 +0200 |
commit | 154a9300cd87eee7538f356c9d339f06b0b1d257 (patch) | |
tree | fc8f427a2db1a3817883f35048f0a62751083c36 /fs/exofs | |
parent | 6851a5e5c12b35f8bb8986d0ff16ca9be4cf2c09 (diff) | |
download | linux-154a9300cd87eee7538f356c9d339f06b0b1d257.tar.gz linux-154a9300cd87eee7538f356c9d339f06b0b1d257.tar.bz2 linux-154a9300cd87eee7538f356c9d339f06b0b1d257.zip |
exofs: Support for short read/writes
If at read/write_done the actual IO was shorter then requested,
reported in returned ios->length. It is not an error. The reminder
of the pages should just be unlocked but not marked uptodate or
end_page_writeback. They will be re issued later by the VFS.
Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Diffstat (limited to 'fs/exofs')
-rw-r--r-- | fs/exofs/inode.c | 35 |
1 files changed, 26 insertions, 9 deletions
diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c index d87c1f7562fb..96366a1d7eae 100644 --- a/fs/exofs/inode.c +++ b/fs/exofs/inode.c @@ -149,14 +149,17 @@ static int pcol_add_page(struct page_collect *pcol, struct page *page, return 0; } +enum {PAGE_WAS_NOT_IN_IO = 17}; static int update_read_page(struct page *page, int ret) { - if (ret == 0) { + switch (ret) { + case 0: /* Everything is OK */ SetPageUptodate(page); if (PageError(page)) ClearPageError(page); - } else if (ret == -EFAULT) { + break; + case -EFAULT: /* In this case we were trying to read something that wasn't on * disk yet - return a page full of zeroes. This should be OK, * because the object should be empty (if there was a write @@ -167,16 +170,22 @@ static int update_read_page(struct page *page, int ret) SetPageUptodate(page); if (PageError(page)) ClearPageError(page); - ret = 0; /* recovered error */ EXOFS_DBGMSG("recovered read error\n"); - } else /* Error */ + /* fall through */ + case PAGE_WAS_NOT_IN_IO: + ret = 0; /* recovered error */ + break; + default: SetPageError(page); - + } return ret; } static void update_write_page(struct page *page, int ret) { + if (unlikely(ret == PAGE_WAS_NOT_IN_IO)) + return; /* don't pass start don't collect $200 */ + if (ret) { mapping_set_error(page->mapping, ret); SetPageError(page); @@ -195,10 +204,14 @@ static int __readpages_done(struct page_collect *pcol) u64 length = 0; int ret = ore_check_io(pcol->ios, &resid); - if (likely(!ret)) + if (likely(!ret)) { good_bytes = pcol->length; - else + ret = PAGE_WAS_NOT_IN_IO; + } else { good_bytes = pcol->length - resid; + } + if (good_bytes > pcol->ios->length) + good_bytes = pcol->ios->length; EXOFS_DBGMSG2("readpages_done(0x%lx) good_bytes=0x%llx" " length=0x%lx nr_pages=%u\n", @@ -518,10 +531,14 @@ static void writepages_done(struct ore_io_state *ios, void *p) atomic_dec(&pcol->sbi->s_curr_pending); - if (likely(!ret)) + if (likely(!ret)) { good_bytes = pcol->length; - else + ret = PAGE_WAS_NOT_IN_IO; + } else { good_bytes = pcol->length - resid; + } + if (good_bytes > pcol->ios->length) + good_bytes = pcol->ios->length; EXOFS_DBGMSG2("writepages_done(0x%lx) good_bytes=0x%llx" " length=0x%lx nr_pages=%u\n", |