Whamcloud - gitweb
LU-6666 osc: Do not merge extents with partial pages 68/15468/3
authorJinshan Xiong <jinshan.xiong@intel.com>
Thu, 2 Jul 2015 07:30:55 +0000 (15:30 +0800)
committerOleg Drokin <oleg.drokin@intel.com>
Mon, 30 Nov 2015 17:19:19 +0000 (17:19 +0000)
After range lock is introduced to Lustre, it's possible for
multiple threads to submit osc_extents with partial pages, and
finally I/O engine may try to merge these extents, which will
end up with assert in osc_build_rpc().

In this patch, osc_extent::oe_no_merge is introduced, and this flag
is set if osc_extent submitted via osc_io_submit() includes partial
pages. This flag is used by I/O engine to stop merging this kind
of extents.

Signed-off-by: Jinshan Xiong <jinshan.xiong@intel.com>
Change-Id: I0c851912beb0370553bc2e2b05f80dee175a2f1f
Reviewed-on: http://review.whamcloud.com/15468
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Reviewed-by: Patrick Farrell <paf@cray.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/osc/osc_cache.c
lustre/osc/osc_cl_internal.h

index 0d616bf..afa0eaa 100644 (file)
@@ -1880,7 +1880,8 @@ static int try_to_add_extent_for_io(struct client_obd *cli,
                }
 
                if (tmp->oe_srvlock != ext->oe_srvlock ||
-                   !tmp->oe_grants != !ext->oe_grants)
+                   !tmp->oe_grants != !ext->oe_grants ||
+                   tmp->oe_no_merge || ext->oe_no_merge)
                        RETURN(0);
 
                /* remove break for strict check */
@@ -2610,18 +2611,24 @@ int osc_queue_sync_pages(const struct lu_env *env, struct osc_object *obj,
        struct osc_async_page *oap;
        int     page_count = 0;
        int     mppr       = cli->cl_max_pages_per_rpc;
+       bool    can_merge   = true;
        pgoff_t start      = CL_PAGE_EOF;
        pgoff_t end        = 0;
        ENTRY;
 
        list_for_each_entry(oap, list, oap_pending_item) {
-               pgoff_t index = osc_index(oap2osc(oap));
+               struct osc_page *opg = oap2osc_page(oap);
+               pgoff_t index = osc_index(opg);
+
                if (index > end)
                        end = index;
                if (index < start)
                        start = index;
                ++page_count;
                mppr <<= (page_count > mppr);
+
+               if (unlikely(opg->ops_from > 0 || opg->ops_to < PAGE_SIZE))
+                       can_merge = false;
        }
 
        ext = osc_extent_alloc(obj);
@@ -2637,6 +2644,7 @@ int osc_queue_sync_pages(const struct lu_env *env, struct osc_object *obj,
 
        ext->oe_rw = !!(cmd & OBD_BRW_READ);
        ext->oe_sync = 1;
+       ext->oe_no_merge = !can_merge;
        ext->oe_urgent = 1;
        ext->oe_start = start;
        ext->oe_end = ext->oe_max_end = end;
index aa75fca..e3ef013 100644 (file)
@@ -612,6 +612,9 @@ struct osc_extent {
                                oe_rw:1,
        /** sync extent, queued by osc_queue_sync_pages() */
                                oe_sync:1,
+       /** set if this extent has partial, sync pages.
+        * Extents with partial page(s) can't merge with others in RPC */
+                               oe_no_merge:1,
                                oe_srvlock:1,
                                oe_memalloc:1,
        /** an ACTIVE extent is going to be truncated, so when this extent