From b801d865eb36890b98f3186727d0bf77313273f1 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong Date: Tue, 4 Oct 2011 22:54:48 -0700 Subject: [PATCH] LU-687 clio: retry if fault page was truncated In vvp_io_fault_start, if a page was truncated we should retry it in ll_fault() instead of return -EFAULT because it will cause fake OOM. Change-Id: Ia2ba40ca4ecd67170e6c2eb81ddc0ee34d9379a8 Signed-off-by: Jinshan Xiong Reviewed-on: http://review.whamcloud.com/1453 Tested-by: Hudson Reviewed-by: Niu Yawei Tested-by: Maloo Reviewed-by: Fan Yong Reviewed-by: Oleg Drokin --- lustre/include/obd_support.h | 3 +++ lustre/llite/llite_mmap.c | 9 +++------ lustre/llite/vvp_io.c | 22 ++++++++++++++++++---- lustre/tests/sanity.sh | 11 +++++++++++ 4 files changed, 35 insertions(+), 10 deletions(-) diff --git a/lustre/include/obd_support.h b/lustre/include/obd_support.h index 46a2bd1..85537da 100644 --- a/lustre/include/obd_support.h +++ b/lustre/include/obd_support.h @@ -422,6 +422,9 @@ int obd_alloc_fail(const void *ptr, const char *name, const char *type, #define OBD_FAIL_MDS_SYNC_CAPA_SL 0x1310 #define OBD_FAIL_SEQ_ALLOC 0x1311 +#define OBD_FAIL_LLITE 0x1400 +#define OBD_FAIL_LLITE_FAULT_TRUNC_RACE 0x1401 + /* Assign references to moved code to reduce code changes */ #define OBD_FAIL_PRECHECK(id) CFS_FAIL_PRECHECK(id) #define OBD_FAIL_CHECK(id) CFS_FAIL_CHECK(id) diff --git a/lustre/llite/llite_mmap.c b/lustre/llite/llite_mmap.c index dc032c0..4424382 100644 --- a/lustre/llite/llite_mmap.c +++ b/lustre/llite/llite_mmap.c @@ -234,13 +234,10 @@ struct page *ll_nopage(struct vm_area_struct *vma, unsigned long address, result = cl_io_loop(env, io); out_err: - if (result == 0) { - LASSERT(io->u.ci_fault.ft_page != NULL); + if (result == 0) page = vio->u.fault.ft_vmpage; - } else { - if (result == -ENOMEM) - page = NOPAGE_OOM; - } + else if (result == -ENOMEM) + page = NOPAGE_OOM; vma->vm_flags &= ~VM_RAND_READ; vma->vm_flags |= ra_flags; diff --git a/lustre/llite/vvp_io.c b/lustre/llite/vvp_io.c index 77351dc..cbf02cd 100644 --- a/lustre/llite/vvp_io.c +++ b/lustre/llite/vvp_io.c @@ -716,14 +716,28 @@ static int vvp_io_fault_start(const struct lu_env *env, if (kernel_result != 0) return kernel_result; + if (OBD_FAIL_CHECK(OBD_FAIL_LLITE_FAULT_TRUNC_RACE)) { + truncate_inode_pages_range(inode->i_mapping, + cl_offset(obj, fio->ft_index), offset); + } + /* Temporarily lock vmpage to keep cl_page_find() happy. */ lock_page(cfio->ft_vmpage); + /* Though we have already held a cl_lock upon this page, but * it still can be truncated locally. */ - page = ERR_PTR(-EFAULT); - if (likely(cfio->ft_vmpage->mapping != NULL)) - page = cl_page_find(env, obj, fio->ft_index, cfio->ft_vmpage, - CPT_CACHEABLE); + if (unlikely(cfio->ft_vmpage->mapping == NULL)) { + unlock_page(cfio->ft_vmpage); + + CDEBUG(D_PAGE, "llite: fault and truncate race happened!\n"); + + /* return +1 to stop cl_io_loop() and ll_fault() will catch + * and retry. */ + return +1; + } + + page = cl_page_find(env, obj, fio->ft_index, cfio->ft_vmpage, + CPT_CACHEABLE); unlock_page(cfio->ft_vmpage); if (IS_ERR(page)) { page_cache_release(cfio->ft_vmpage); diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index e54a142..052a207 100644 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -8281,6 +8281,17 @@ test_220() { #LU-325 } run_test 220 "the preallocated objects in MDS still can be used if ENOSPC is returned by OST with enough disk space" +test_221() { + cp `which date` $MOUNT + + #define OBD_FAIL_LLITE_FAULT_TRUNC_RACE 0x1401 + $LCTL set_param fail_loc=0x80001401 + + $MOUNT/date > /dev/null + rm -f $MOUNT/date +} +run_test 221 "make sure fault and truncate race to not cause OOM" + # # tests that do cleanup/setup should be run at the end # -- 1.8.3.1