diff options
author | Boaz Harrosh <bharrosh@panasas.com> | 2010-01-19 12:24:45 -0500 |
---|---|---|
committer | Boaz Harrosh <bharrosh@panasas.com> | 2010-02-28 06:35:26 -0500 |
commit | 22ddc556380cf5645c52292b6d980766646eb864 (patch) | |
tree | 07d498ba10f4393fb4cde6a79b22a50b6a0f7efb | |
parent | 518f167a37b3c53f3cf44d27800455ca24e920f6 (diff) |
exofs: Recover in the case of read-passed-end-of-file
In check_io, implement the case of reading passed end of
file, by clearing the pages and recover with no error. In
a raid arrangement this can become a legitimate situation
in case of holes in the file.
Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
-rw-r--r-- | fs/exofs/ios.c | 36 |
1 files changed, 30 insertions, 6 deletions
diff --git a/fs/exofs/ios.c b/fs/exofs/ios.c index 3cc0dd3f0eb2..439c5d097b27 100644 --- a/fs/exofs/ios.c +++ b/fs/exofs/ios.c | |||
@@ -173,6 +173,21 @@ static int exofs_io_execute(struct exofs_io_state *ios) | |||
173 | return ret; | 173 | return ret; |
174 | } | 174 | } |
175 | 175 | ||
176 | static void _clear_bio(struct bio *bio) | ||
177 | { | ||
178 | struct bio_vec *bv; | ||
179 | unsigned i; | ||
180 | |||
181 | __bio_for_each_segment(bv, bio, i, 0) { | ||
182 | unsigned this_count = bv->bv_len; | ||
183 | |||
184 | if (likely(PAGE_SIZE == this_count)) | ||
185 | clear_highpage(bv->bv_page); | ||
186 | else | ||
187 | zero_user(bv->bv_page, bv->bv_offset, this_count); | ||
188 | } | ||
189 | } | ||
190 | |||
176 | int exofs_check_io(struct exofs_io_state *ios, u64 *resid) | 191 | int exofs_check_io(struct exofs_io_state *ios, u64 *resid) |
177 | { | 192 | { |
178 | enum osd_err_priority acumulated_osd_err = 0; | 193 | enum osd_err_priority acumulated_osd_err = 0; |
@@ -181,16 +196,25 @@ int exofs_check_io(struct exofs_io_state *ios, u64 *resid) | |||
181 | 196 | ||
182 | for (i = 0; i < ios->numdevs; i++) { | 197 | for (i = 0; i < ios->numdevs; i++) { |
183 | struct osd_sense_info osi; | 198 | struct osd_sense_info osi; |
184 | int ret = osd_req_decode_sense(ios->per_dev[i].or, &osi); | 199 | struct osd_request *or = ios->per_dev[i].or; |
200 | int ret; | ||
201 | |||
202 | if (unlikely(!or)) | ||
203 | continue; | ||
185 | 204 | ||
205 | ret = osd_req_decode_sense(or, &osi); | ||
186 | if (likely(!ret)) | 206 | if (likely(!ret)) |
187 | continue; | 207 | continue; |
188 | 208 | ||
189 | if (unlikely(ret == -EFAULT)) { | 209 | if (OSD_ERR_PRI_CLEAR_PAGES == osi.osd_err_pri) { |
190 | EXOFS_DBGMSG("%s: EFAULT Need page clear\n", __func__); | 210 | /* start read offset passed endof file */ |
191 | /*FIXME: All the pages in this device range should: | 211 | _clear_bio(ios->per_dev[i].bio); |
192 | * clear_highpage(page); | 212 | EXOFS_DBGMSG("start read offset passed end of file " |
193 | */ | 213 | "offset=0x%llx, length=0x%llx\n", |
214 | _LLU(ios->offset), | ||
215 | _LLU(ios->length)); | ||
216 | |||
217 | continue; /* we recovered */ | ||
194 | } | 218 | } |
195 | 219 | ||
196 | if (osi.osd_err_pri >= acumulated_osd_err) { | 220 | if (osi.osd_err_pri >= acumulated_osd_err) { |