From c594026329e6a78a6c9f3188514211647b3040d8 Mon Sep 17 00:00:00 2001 From: Andrew Perepechko Date: Mon, 26 Sep 2016 23:42:41 +0300 Subject: [PATCH] LU-8509 llite: drop_caches hangs in cl_inode_fini() This patch releases cl_pages on error in ll_write_begin() to avoid memory and object reference leaks. Also, it reuses per-cpu lu_env in ll_invalidatepage() in the same way as done in ll_releasepage(). Change-Id: I11a658941aff4dacd3cc83685ae3df67f28093a2 Signed-off-by: Andrew Perepechko Seagate-bug-id: MRP-3504 Reviewed-on: http://review.whamcloud.com/22745 Reviewed-by: Jinshan Xiong Reviewed-by: Bobi Jam Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Oleg Drokin --- lustre/llite/rw26.c | 40 ++++++++++++++++++++++------------------ lustre/tests/sanity.sh | 20 ++++++++++++++++++++ 2 files changed, 42 insertions(+), 18 deletions(-) diff --git a/lustre/llite/rw26.c b/lustre/llite/rw26.c index 1369c09..acf5a64 100644 --- a/lustre/llite/rw26.c +++ b/lustre/llite/rw26.c @@ -88,8 +88,6 @@ static void ll_invalidatepage(struct page *vmpage, struct cl_page *page; struct cl_object *obj; - __u16 refcheck; - LASSERT(PageLocked(vmpage)); LASSERT(!PageWriteback(vmpage)); @@ -103,20 +101,22 @@ static void ll_invalidatepage(struct page *vmpage, #else if (offset == 0) { #endif - env = cl_env_get(&refcheck); - if (!IS_ERR(env)) { - inode = vmpage->mapping->host; - obj = ll_i2info(inode)->lli_clob; - if (obj != NULL) { - page = cl_vmpage_page(vmpage, obj); - if (page != NULL) { - cl_page_delete(env, page); - cl_page_put(env, page); - } - } else - LASSERT(vmpage->private == 0); - cl_env_put(env, &refcheck); - } + /* See the comment in ll_releasepage() */ + env = cl_env_percpu_get(); + LASSERT(!IS_ERR(env)); + + inode = vmpage->mapping->host; + obj = ll_i2info(inode)->lli_clob; + if (obj != NULL) { + page = cl_vmpage_page(vmpage, obj); + if (page != NULL) { + cl_page_delete(env, page); + cl_page_put(env, page); + } + } else + LASSERT(vmpage->private == 0); + + cl_env_percpu_put(env); } } @@ -632,9 +632,9 @@ static int ll_write_begin(struct file *file, struct address_space *mapping, struct page **pagep, void **fsdata) { struct ll_cl_context *lcc; - const struct lu_env *env; + const struct lu_env *env = NULL; struct cl_io *io; - struct cl_page *page; + struct cl_page *page = NULL; struct cl_object *clob = ll_i2info(mapping->host)->lli_clob; pgoff_t index = pos >> PAGE_SHIFT; @@ -721,6 +721,10 @@ out: unlock_page(vmpage); put_page(vmpage); } + if (!IS_ERR_OR_NULL(page)) { + lu_ref_del(&page->cp_reference, "cl_io", io); + cl_page_put(env, page); + } if (io) io->ci_result = result; } else { diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index 320c39a..810f99d 100755 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -15790,6 +15790,26 @@ test_407() { } run_test 407 "transaction fail should cause operation fail" +test_408() { + dd if=/dev/zero of=$DIR/$tfile bs=4096 count=1 oflag=direct + + #define OBD_FAIL_OSC_BRW_PREP_REQ2 0x40a + lctl set_param fail_loc=0x8000040a + # let ll_prepare_partial_page() fail + dd if=/dev/zero of=$DIR/$tfile bs=2048 count=1 conv=notrunc || true + + rm -f $DIR/$tfile + + # create at least 100 unused inodes so that + # shrink_icache_memory(0) should not return 0 + touch $DIR/$tfile-{0..100} + rm -f $DIR/$tfile-{0..100} + sync + + echo 2 > /proc/sys/vm/drop_caches +} +run_test 408 "drop_caches should not hang due to page leaks" + # # tests that do cleanup/setup should be run at the end # -- 1.8.3.1