diff options
author | Boaz Harrosh <bharrosh@panasas.com> | 2011-08-27 00:00:32 -0400 |
---|---|---|
committer | Boaz Harrosh <bharrosh@panasas.com> | 2011-10-14 12:54:39 -0400 |
commit | 154a9300cd87eee7538f356c9d339f06b0b1d257 (patch) | |
tree | fc8f427a2db1a3817883f35048f0a62751083c36 /fs | |
parent | 6851a5e5c12b35f8bb8986d0ff16ca9be4cf2c09 (diff) |
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')
-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, | |||
149 | return 0; | 149 | return 0; |
150 | } | 150 | } |
151 | 151 | ||
152 | enum {PAGE_WAS_NOT_IN_IO = 17}; | ||
152 | static int update_read_page(struct page *page, int ret) | 153 | static int update_read_page(struct page *page, int ret) |
153 | { | 154 | { |
154 | if (ret == 0) { | 155 | switch (ret) { |
156 | case 0: | ||
155 | /* Everything is OK */ | 157 | /* Everything is OK */ |
156 | SetPageUptodate(page); | 158 | SetPageUptodate(page); |
157 | if (PageError(page)) | 159 | if (PageError(page)) |
158 | ClearPageError(page); | 160 | ClearPageError(page); |
159 | } else if (ret == -EFAULT) { | 161 | break; |
162 | case -EFAULT: | ||
160 | /* In this case we were trying to read something that wasn't on | 163 | /* In this case we were trying to read something that wasn't on |
161 | * disk yet - return a page full of zeroes. This should be OK, | 164 | * disk yet - return a page full of zeroes. This should be OK, |
162 | * because the object should be empty (if there was a write | 165 | * 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) | |||
167 | SetPageUptodate(page); | 170 | SetPageUptodate(page); |
168 | if (PageError(page)) | 171 | if (PageError(page)) |
169 | ClearPageError(page); | 172 | ClearPageError(page); |
170 | ret = 0; /* recovered error */ | ||
171 | EXOFS_DBGMSG("recovered read error\n"); | 173 | EXOFS_DBGMSG("recovered read error\n"); |
172 | } else /* Error */ | 174 | /* fall through */ |
175 | case PAGE_WAS_NOT_IN_IO: | ||
176 | ret = 0; /* recovered error */ | ||
177 | break; | ||
178 | default: | ||
173 | SetPageError(page); | 179 | SetPageError(page); |
174 | 180 | } | |
175 | return ret; | 181 | return ret; |
176 | } | 182 | } |
177 | 183 | ||
178 | static void update_write_page(struct page *page, int ret) | 184 | static void update_write_page(struct page *page, int ret) |
179 | { | 185 | { |
186 | if (unlikely(ret == PAGE_WAS_NOT_IN_IO)) | ||
187 | return; /* don't pass start don't collect $200 */ | ||
188 | |||
180 | if (ret) { | 189 | if (ret) { |
181 | mapping_set_error(page->mapping, ret); | 190 | mapping_set_error(page->mapping, ret); |
182 | SetPageError(page); | 191 | SetPageError(page); |
@@ -195,10 +204,14 @@ static int __readpages_done(struct page_collect *pcol) | |||
195 | u64 length = 0; | 204 | u64 length = 0; |
196 | int ret = ore_check_io(pcol->ios, &resid); | 205 | int ret = ore_check_io(pcol->ios, &resid); |
197 | 206 | ||
198 | if (likely(!ret)) | 207 | if (likely(!ret)) { |
199 | good_bytes = pcol->length; | 208 | good_bytes = pcol->length; |
200 | else | 209 | ret = PAGE_WAS_NOT_IN_IO; |
210 | } else { | ||
201 | good_bytes = pcol->length - resid; | 211 | good_bytes = pcol->length - resid; |
212 | } | ||
213 | if (good_bytes > pcol->ios->length) | ||
214 | good_bytes = pcol->ios->length; | ||
202 | 215 | ||
203 | EXOFS_DBGMSG2("readpages_done(0x%lx) good_bytes=0x%llx" | 216 | EXOFS_DBGMSG2("readpages_done(0x%lx) good_bytes=0x%llx" |
204 | " length=0x%lx nr_pages=%u\n", | 217 | " length=0x%lx nr_pages=%u\n", |
@@ -518,10 +531,14 @@ static void writepages_done(struct ore_io_state *ios, void *p) | |||
518 | 531 | ||
519 | atomic_dec(&pcol->sbi->s_curr_pending); | 532 | atomic_dec(&pcol->sbi->s_curr_pending); |
520 | 533 | ||
521 | if (likely(!ret)) | 534 | if (likely(!ret)) { |
522 | good_bytes = pcol->length; | 535 | good_bytes = pcol->length; |
523 | else | 536 | ret = PAGE_WAS_NOT_IN_IO; |
537 | } else { | ||
524 | good_bytes = pcol->length - resid; | 538 | good_bytes = pcol->length - resid; |
539 | } | ||
540 | if (good_bytes > pcol->ios->length) | ||
541 | good_bytes = pcol->ios->length; | ||
525 | 542 | ||
526 | EXOFS_DBGMSG2("writepages_done(0x%lx) good_bytes=0x%llx" | 543 | EXOFS_DBGMSG2("writepages_done(0x%lx) good_bytes=0x%llx" |
527 | " length=0x%lx nr_pages=%u\n", | 544 | " length=0x%lx nr_pages=%u\n", |