Commit 1fb26939 authored by Jinshan Xiong's avatar Jinshan Xiong Committed by Greg Kroah-Hartman

staging: lustre: osc: Do not merge extents with partial pages

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: default avatarJinshan Xiong <jinshan.xiong@intel.com>
Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6666
Reviewed-on: http://review.whamcloud.com/15468Reviewed-by: default avatarAndreas Dilger <andreas.dilger@intel.com>
Reviewed-by: default avatarPatrick Farrell <paf@cray.com>
Reviewed-by: default avatarOleg Drokin <oleg.drokin@intel.com>
Signed-off-by: default avatarJames Simmons <jsimmons@infradead.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent e8b23722
...@@ -1931,7 +1931,8 @@ static int try_to_add_extent_for_io(struct client_obd *cli, ...@@ -1931,7 +1931,8 @@ static int try_to_add_extent_for_io(struct client_obd *cli,
} }
if (tmp->oe_srvlock != ext->oe_srvlock || 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; return 0;
/* remove break for strict check */ /* remove break for strict check */
...@@ -2666,11 +2667,13 @@ int osc_queue_sync_pages(const struct lu_env *env, struct osc_object *obj, ...@@ -2666,11 +2667,13 @@ int osc_queue_sync_pages(const struct lu_env *env, struct osc_object *obj,
struct osc_async_page *oap, *tmp; struct osc_async_page *oap, *tmp;
int page_count = 0; int page_count = 0;
int mppr = cli->cl_max_pages_per_rpc; int mppr = cli->cl_max_pages_per_rpc;
bool can_merge = true;
pgoff_t start = CL_PAGE_EOF; pgoff_t start = CL_PAGE_EOF;
pgoff_t end = 0; pgoff_t end = 0;
list_for_each_entry(oap, list, oap_pending_item) { 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) if (index > end)
end = index; end = index;
...@@ -2678,6 +2681,9 @@ int osc_queue_sync_pages(const struct lu_env *env, struct osc_object *obj, ...@@ -2678,6 +2681,9 @@ int osc_queue_sync_pages(const struct lu_env *env, struct osc_object *obj,
start = index; start = index;
++page_count; ++page_count;
mppr <<= (page_count > mppr); mppr <<= (page_count > mppr);
if (unlikely(opg->ops_from > 0 || opg->ops_to < PAGE_SIZE))
can_merge = false;
} }
ext = osc_extent_alloc(obj); ext = osc_extent_alloc(obj);
...@@ -2691,6 +2697,7 @@ int osc_queue_sync_pages(const struct lu_env *env, struct osc_object *obj, ...@@ -2691,6 +2697,7 @@ int osc_queue_sync_pages(const struct lu_env *env, struct osc_object *obj,
ext->oe_rw = !!(cmd & OBD_BRW_READ); ext->oe_rw = !!(cmd & OBD_BRW_READ);
ext->oe_sync = 1; ext->oe_sync = 1;
ext->oe_no_merge = !can_merge;
ext->oe_urgent = 1; ext->oe_urgent = 1;
ext->oe_start = start; ext->oe_start = start;
ext->oe_end = end; ext->oe_end = end;
......
...@@ -614,6 +614,10 @@ struct osc_extent { ...@@ -614,6 +614,10 @@ struct osc_extent {
oe_rw:1, oe_rw:1,
/** sync extent, queued by osc_queue_sync_pages() */ /** sync extent, queued by osc_queue_sync_pages() */
oe_sync:1, 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_srvlock:1,
oe_memalloc:1, oe_memalloc:1,
/** an ACTIVE extent is going to be truncated, so when this extent /** an ACTIVE extent is going to be truncated, so when this extent
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment