diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c index 5a62420cbdb172130d9aa04f171dc11a968aa551..86c0ac87b8e3c063047d48b7fd70a18aec7b90a1 100644 --- a/fs/exofs/inode.c +++ b/fs/exofs/inode.c @@ -194,19 +194,16 @@ static void update_write_page(struct page *page, int ret) static int __readpages_done(struct page_collect *pcol) { int i; - u64 resid; u64 good_bytes; u64 length = 0; - int ret = ore_check_io(pcol->ios, &resid); + int ret = ore_check_io(pcol->ios, NULL); if (likely(!ret)) { good_bytes = pcol->length; ret = PAGE_WAS_NOT_IN_IO; } else { - good_bytes = pcol->length - resid; + good_bytes = 0; } - 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", @@ -519,10 +516,9 @@ static void writepages_done(struct ore_io_state *ios, void *p) { struct page_collect *pcol = p; int i; - u64 resid; u64 good_bytes; u64 length = 0; - int ret = ore_check_io(ios, &resid); + int ret = ore_check_io(ios, NULL); atomic_dec(&pcol->sbi->s_curr_pending); @@ -530,10 +526,8 @@ static void writepages_done(struct ore_io_state *ios, void *p) good_bytes = pcol->length; ret = PAGE_WAS_NOT_IN_IO; } else { - good_bytes = pcol->length - resid; + good_bytes = 0; } - 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", diff --git a/fs/exofs/ore.c b/fs/exofs/ore.c index 4ca59d4927985c9fc2571eefc03f70aa32f58fd5..3b1cc3a132d7edb0ead6b47d0261e65fcd65f4d8 100644 --- a/fs/exofs/ore.c +++ b/fs/exofs/ore.c @@ -317,7 +317,7 @@ static void _clear_bio(struct bio *bio) } } -int ore_check_io(struct ore_io_state *ios, u64 *resid) +int ore_check_io(struct ore_io_state *ios, ore_on_dev_error on_dev_error) { enum osd_err_priority acumulated_osd_err = 0; int acumulated_lin_err = 0; @@ -325,7 +325,8 @@ int ore_check_io(struct ore_io_state *ios, u64 *resid) for (i = 0; i < ios->numdevs; i++) { struct osd_sense_info osi; - struct osd_request *or = ios->per_dev[i].or; + struct ore_per_dev_state *per_dev = &ios->per_dev[i]; + struct osd_request *or = per_dev->or; int ret; if (unlikely(!or)) @@ -337,29 +338,31 @@ int ore_check_io(struct ore_io_state *ios, u64 *resid) if (OSD_ERR_PRI_CLEAR_PAGES == osi.osd_err_pri) { /* start read offset passed endof file */ - _clear_bio(ios->per_dev[i].bio); + _clear_bio(per_dev->bio); ORE_DBGMSG("start read offset passed end of file " "offset=0x%llx, length=0x%llx\n", - _LLU(ios->per_dev[i].offset), - _LLU(ios->per_dev[i].length)); + _LLU(per_dev->offset), + _LLU(per_dev->length)); continue; /* we recovered */ } + if (on_dev_error) { + u64 residual = ios->reading ? + or->in.residual : or->out.residual; + u64 offset = (ios->offset + ios->length) - residual; + struct ore_dev *od = ios->oc->ods[ + per_dev->dev - ios->oc->first_dev]; + + on_dev_error(ios, od, per_dev->dev, osi.osd_err_pri, + offset, residual); + } if (osi.osd_err_pri >= acumulated_osd_err) { acumulated_osd_err = osi.osd_err_pri; acumulated_lin_err = ret; } } - /* TODO: raid specific residual calculations */ - if (resid) { - if (likely(!acumulated_lin_err)) - *resid = 0; - else - *resid = ios->length; - } - return acumulated_lin_err; } EXPORT_SYMBOL(ore_check_io); diff --git a/include/scsi/osd_ore.h b/include/scsi/osd_ore.h index 716dbeae8cd28a65ac31f0339597a2a54df6bf0a..af2231a0fd098de95f0faa06b5692025780972f1 100644 --- a/include/scsi/osd_ore.h +++ b/include/scsi/osd_ore.h @@ -153,7 +153,10 @@ int ore_get_io_state(struct ore_layout *layout, struct ore_components *comps, struct ore_io_state **ios); void ore_put_io_state(struct ore_io_state *ios); -int ore_check_io(struct ore_io_state *ios, u64 *resid); +typedef void (*ore_on_dev_error)(struct ore_io_state *ios, struct ore_dev *od, + unsigned dev_index, enum osd_err_priority oep, + u64 dev_offset, u64 dev_len); +int ore_check_io(struct ore_io_state *ios, ore_on_dev_error rep); int ore_create(struct ore_io_state *ios); int ore_remove(struct ore_io_state *ios);