summaryrefslogtreecommitdiff
path: root/fs/exofs
diff options
context:
space:
mode:
authorBoaz Harrosh <bharrosh@panasas.com>2011-08-26 21:00:32 -0700
committerBoaz Harrosh <bharrosh@panasas.com>2011-10-14 18:54:39 +0200
commit154a9300cd87eee7538f356c9d339f06b0b1d257 (patch)
treefc8f427a2db1a3817883f35048f0a62751083c36 /fs/exofs
parent6851a5e5c12b35f8bb8986d0ff16ca9be4cf2c09 (diff)
downloadkernel-common-154a9300cd87eee7538f356c9d339f06b0b1d257.tar.gz
kernel-common-154a9300cd87eee7538f356c9d339f06b0b1d257.tar.bz2
kernel-common-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.c35
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",