aboutsummaryrefslogtreecommitdiffstats
path: root/fs/exofs
diff options
context:
space:
mode:
authorBoaz Harrosh <bharrosh@panasas.com>2011-08-27 00:00:32 -0400
committerBoaz Harrosh <bharrosh@panasas.com>2011-10-14 12:54:39 -0400
commit154a9300cd87eee7538f356c9d339f06b0b1d257 (patch)
treefc8f427a2db1a3817883f35048f0a62751083c36 /fs/exofs
parent6851a5e5c12b35f8bb8986d0ff16ca9be4cf2c09 (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/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 d87c1f7562f..96366a1d7ea 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
152enum {PAGE_WAS_NOT_IN_IO = 17};
152static int update_read_page(struct page *page, int ret) 153static 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
178static void update_write_page(struct page *page, int ret) 184static 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",