From 1fb26939dcc84503a9d018a5857f0a5f90022e88 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong Date: Thu, 10 Nov 2016 12:30:55 -0500 Subject: [PATCH] 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: Jinshan Xiong Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6666 Reviewed-on: http://review.whamcloud.com/15468 Reviewed-by: Andreas Dilger Reviewed-by: Patrick Farrell Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/osc/osc_cache.c | 11 +++++++++-- drivers/staging/lustre/lustre/osc/osc_cl_internal.h | 4 ++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c index cbbe85ecf4be..560bcaf8087e 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cache.c +++ b/drivers/staging/lustre/lustre/osc/osc_cache.c @@ -1931,7 +1931,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 */ @@ -2666,11 +2667,13 @@ int osc_queue_sync_pages(const struct lu_env *env, struct osc_object *obj, struct osc_async_page *oap, *tmp; 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; 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; @@ -2678,6 +2681,9 @@ int osc_queue_sync_pages(const struct lu_env *env, struct osc_object *obj, 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); @@ -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_sync = 1; + ext->oe_no_merge = !can_merge; ext->oe_urgent = 1; ext->oe_start = start; ext->oe_end = end; diff --git a/drivers/staging/lustre/lustre/osc/osc_cl_internal.h b/drivers/staging/lustre/lustre/osc/osc_cl_internal.h index 8a554128ed7f..31735d5e65ce 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cl_internal.h +++ b/drivers/staging/lustre/lustre/osc/osc_cl_internal.h @@ -614,6 +614,10 @@ 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 -- 2.39.2