]> Pileus Git - ~andy/linux/commitdiff
ore/exofs: Change ore_check_io API
authorBoaz Harrosh <bharrosh@panasas.com>
Wed, 28 Sep 2011 10:25:50 +0000 (13:25 +0300)
committerBoaz Harrosh <bharrosh@panasas.com>
Fri, 14 Oct 2011 16:54:42 +0000 (18:54 +0200)
Current ore_check_io API receives a residual
pointer, to report partial IO. But it is actually
not used, because in a multiple devices IO there
is never a linearity in the IO failure.

On the other hand if every failing device is reported
through a received callback measures can be taken to
handle only failed devices. One at a time.

This will also be needed by the objects-layout-driver
for it's error reporting facility.

Exofs is not currently using the new information and
keeps the old behaviour of failing the complete IO in
case of an error. (No partial completion)

TODO: Use an ore_check_io callback to set_page_error only
the failing pages. And re-dirty write pages.

Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
fs/exofs/inode.c
fs/exofs/ore.c
include/scsi/osd_ore.h

index 5a62420cbdb172130d9aa04f171dc11a968aa551..86c0ac87b8e3c063047d48b7fd70a18aec7b90a1 100644 (file)
@@ -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",
index 4ca59d4927985c9fc2571eefc03f70aa32f58fd5..3b1cc3a132d7edb0ead6b47d0261e65fcd65f4d8 100644 (file)
@@ -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);
index 716dbeae8cd28a65ac31f0339597a2a54df6bf0a..af2231a0fd098de95f0faa06b5692025780972f1 100644 (file)
@@ -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);