public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: green@linuxhacker.ru
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	devel@driverdev.osuosl.org,
	Andreas Dilger <andreas.dilger@intel.com>
Cc: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
	Lustre Development List <lustre-devel@lists.lustre.org>,
	Jinshan Xiong <jinshan.xiong@intel.com>,
	Prakash Surya <surya1@llnl.gov>,
	Oleg Drokin <green@linuxhacker.ru>
Subject: [PATCH 08/43] staging/lustre/obdclass: Add a preallocated percpu cl_env
Date: Wed, 30 Mar 2016 12:47:40 -0400	[thread overview]
Message-ID: <1459356495-2794775-9-git-send-email-green@linuxhacker.ru> (raw)
In-Reply-To: <1459356495-2794775-1-git-send-email-green@linuxhacker.ru>

From: Jinshan Xiong <jinshan.xiong@intel.com>

This change adds support for a single preallocated cl_env per CPU
which can be used in circumstances where reschedule is not possible.
Currently this interface is only used by the ll_releasepage function.

Signed-off-by: Jinshan Xiong <jinshan.xiong@intel.com>
Signed-off-by: Prakash Surya <surya1@llnl.gov>
Reviewed-on: http://review.whamcloud.com/8174
Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3321
Reviewed-by: Lai Siyao <lai.siyao@intel.com>
Reviewed-by: Bobi Jam <bobijam@gmail.com>
Signed-off-by: Oleg Drokin <green@linuxhacker.ru>
---
 drivers/staging/lustre/lustre/include/cl_object.h  |  12 +++
 drivers/staging/lustre/lustre/llite/rw26.c         |  54 +++++++----
 drivers/staging/lustre/lustre/obdclass/cl_lock.c   |   1 -
 drivers/staging/lustre/lustre/obdclass/cl_object.c | 107 +++++++++++++++++++++
 drivers/staging/lustre/lustre/obdclass/cl_page.c   |   1 -
 5 files changed, 152 insertions(+), 23 deletions(-)

diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h
index 5daf688..e8455dc 100644
--- a/drivers/staging/lustre/lustre/include/cl_object.h
+++ b/drivers/staging/lustre/lustre/include/cl_object.h
@@ -2773,6 +2773,16 @@ static inline void *cl_object_page_slice(struct cl_object *clob,
 	return (void *)((char *)page + clob->co_slice_off);
 }
 
+/**
+ * Return refcount of cl_object.
+ */
+static inline int cl_object_refc(struct cl_object *clob)
+{
+	struct lu_object_header *header = clob->co_lu.lo_header;
+
+	return atomic_read(&header->loh_ref);
+}
+
 /** @} cl_object */
 
 /** \defgroup cl_page cl_page
@@ -3226,6 +3236,8 @@ void cl_env_reexit(void *cookie);
 void cl_env_implant(struct lu_env *env, int *refcheck);
 void cl_env_unplant(struct lu_env *env, int *refcheck);
 unsigned int cl_env_cache_purge(unsigned int nr);
+struct lu_env *cl_env_percpu_get(void);
+void cl_env_percpu_put(struct lu_env *env);
 
 /** @} cl_env */
 
diff --git a/drivers/staging/lustre/lustre/llite/rw26.c b/drivers/staging/lustre/lustre/llite/rw26.c
index b5335de..cc49c21 100644
--- a/drivers/staging/lustre/lustre/llite/rw26.c
+++ b/drivers/staging/lustre/lustre/llite/rw26.c
@@ -107,12 +107,12 @@ static void ll_invalidatepage(struct page *vmpage, unsigned int offset,
 
 static int ll_releasepage(struct page *vmpage, gfp_t gfp_mask)
 {
-	struct cl_env_nest nest;
 	struct lu_env     *env;
+	void			*cookie;
 	struct cl_object  *obj;
 	struct cl_page    *page;
 	struct address_space *mapping;
-	int result;
+	int result = 0;
 
 	LASSERT(PageLocked(vmpage));
 	if (PageWriteback(vmpage) || PageDirty(vmpage))
@@ -126,30 +126,42 @@ static int ll_releasepage(struct page *vmpage, gfp_t gfp_mask)
 	if (!obj)
 		return 1;
 
-	/* 1 for page allocator, 1 for cl_page and 1 for page cache */
+	/* 1 for caller, 1 for cl_page and 1 for page cache */
 	if (page_count(vmpage) > 3)
 		return 0;
 
-	/* TODO: determine what gfp should be used by @gfp_mask. */
-	env = cl_env_nested_get(&nest);
-	if (IS_ERR(env))
-		/* If we can't allocate an env we won't call cl_page_put()
-		 * later on which further means it's impossible to drop
-		 * page refcount by cl_page, so ask kernel to not free
-		 * this page.
-		 */
-		return 0;
-
 	page = cl_vmpage_page(vmpage, obj);
-	result = !page;
-	if (page) {
-		if (!cl_page_in_use(page)) {
-			result = 1;
-			cl_page_delete(env, page);
-		}
-		cl_page_put(env, page);
+	if (!page)
+		return 1;
+
+	cookie = cl_env_reenter();
+	env = cl_env_percpu_get();
+	LASSERT(!IS_ERR(env));
+
+	if (!cl_page_in_use(page)) {
+		result = 1;
+		cl_page_delete(env, page);
 	}
-	cl_env_nested_put(&nest, env);
+
+	/* To use percpu env array, the call path can not be rescheduled;
+	 * otherwise percpu array will be messed if ll_releaspage() called
+	 * again on the same CPU.
+	 *
+	 * If this page holds the last refc of cl_object, the following
+	 * call path may cause reschedule:
+	 *   cl_page_put -> cl_page_free -> cl_object_put ->
+	 *     lu_object_put -> lu_object_free -> lov_delete_raid0 ->
+	 *     cl_locks_prune.
+	 *
+	 * However, the kernel can't get rid of this inode until all pages have
+	 * been cleaned up. Now that we hold page lock here, it's pretty safe
+	 * that we won't get into object delete path.
+	 */
+	LASSERT(cl_object_refc(obj) > 1);
+	cl_page_put(env, page);
+
+	cl_env_percpu_put(env);
+	cl_env_reexit(cookie);
 	return result;
 }
 
diff --git a/drivers/staging/lustre/lustre/obdclass/cl_lock.c b/drivers/staging/lustre/lustre/obdclass/cl_lock.c
index 32ecc5a..fe8059a 100644
--- a/drivers/staging/lustre/lustre/obdclass/cl_lock.c
+++ b/drivers/staging/lustre/lustre/obdclass/cl_lock.c
@@ -255,7 +255,6 @@ static void cl_lock_free(const struct lu_env *env, struct cl_lock *lock)
 	LINVRNT(!cl_lock_is_mutexed(lock));
 
 	cl_lock_trace(D_DLMTRACE, env, "free lock", lock);
-	might_sleep();
 	while (!list_empty(&lock->cll_layers)) {
 		struct cl_lock_slice *slice;
 
diff --git a/drivers/staging/lustre/lustre/obdclass/cl_object.c b/drivers/staging/lustre/lustre/obdclass/cl_object.c
index 65b6402..fa9b083 100644
--- a/drivers/staging/lustre/lustre/obdclass/cl_object.c
+++ b/drivers/staging/lustre/lustre/obdclass/cl_object.c
@@ -390,6 +390,8 @@ static int cache_stats_print(const struct cache_stats *cs,
 	return 0;
 }
 
+static void cl_env_percpu_refill(void);
+
 /**
  * Initialize client site.
  *
@@ -409,6 +411,7 @@ int cl_site_init(struct cl_site *s, struct cl_device *d)
 			atomic_set(&s->cs_pages_state[0], 0);
 		for (i = 0; i < ARRAY_SIZE(s->cs_locks_state); ++i)
 			atomic_set(&s->cs_locks_state[i], 0);
+		cl_env_percpu_refill();
 	}
 	return result;
 }
@@ -1001,6 +1004,104 @@ void cl_lvb2attr(struct cl_attr *attr, const struct ost_lvb *lvb)
 }
 EXPORT_SYMBOL(cl_lvb2attr);
 
+static struct cl_env cl_env_percpu[NR_CPUS];
+
+static int cl_env_percpu_init(void)
+{
+	struct cl_env *cle;
+	int tags = LCT_REMEMBER | LCT_NOREF;
+	int i, j;
+	int rc = 0;
+
+	for_each_possible_cpu(i) {
+		struct lu_env *env;
+
+		cle = &cl_env_percpu[i];
+		env = &cle->ce_lu;
+
+		INIT_LIST_HEAD(&cle->ce_linkage);
+		cle->ce_magic = &cl_env_init0;
+		rc = lu_env_init(env, LCT_CL_THREAD | tags);
+		if (rc == 0) {
+			rc = lu_context_init(&cle->ce_ses, LCT_SESSION | tags);
+			if (rc == 0) {
+				lu_context_enter(&cle->ce_ses);
+				env->le_ses = &cle->ce_ses;
+			} else {
+				lu_env_fini(env);
+			}
+		}
+		if (rc != 0)
+			break;
+	}
+	if (rc != 0) {
+		/* Indices 0 to i (excluding i) were correctly initialized,
+		 * thus we must uninitialize up to i, the rest are undefined.
+		 */
+		for (j = 0; j < i; j++) {
+			cle = &cl_env_percpu[i];
+			lu_context_exit(&cle->ce_ses);
+			lu_context_fini(&cle->ce_ses);
+			lu_env_fini(&cle->ce_lu);
+		}
+	}
+
+	return rc;
+}
+
+static void cl_env_percpu_fini(void)
+{
+	int i;
+
+	for_each_possible_cpu(i) {
+		struct cl_env *cle = &cl_env_percpu[i];
+
+		lu_context_exit(&cle->ce_ses);
+		lu_context_fini(&cle->ce_ses);
+		lu_env_fini(&cle->ce_lu);
+	}
+}
+
+static void cl_env_percpu_refill(void)
+{
+	int i;
+
+	for_each_possible_cpu(i)
+		lu_env_refill(&cl_env_percpu[i].ce_lu);
+}
+
+void cl_env_percpu_put(struct lu_env *env)
+{
+	struct cl_env *cle;
+	int cpu;
+
+	cpu = smp_processor_id();
+	cle = cl_env_container(env);
+	LASSERT(cle == &cl_env_percpu[cpu]);
+
+	cle->ce_ref--;
+	LASSERT(cle->ce_ref == 0);
+
+	CL_ENV_DEC(busy);
+	cl_env_detach(cle);
+	cle->ce_debug = NULL;
+
+	put_cpu();
+}
+EXPORT_SYMBOL(cl_env_percpu_put);
+
+struct lu_env *cl_env_percpu_get()
+{
+	struct cl_env *cle;
+
+	cle = &cl_env_percpu[get_cpu()];
+	cl_env_init0(cle, __builtin_return_address(0));
+
+	cl_env_attach(cle);
+	return &cle->ce_lu;
+}
+EXPORT_SYMBOL(cl_env_percpu_get);
+
 /*****************************************************************************
  *
  * Temporary prototype thing: mirror obd-devices into cl devices.
@@ -1154,6 +1255,11 @@ int cl_global_init(void)
 	if (result)
 		goto out_lock;
 
+	result = cl_env_percpu_init();
+	if (result)
+		/* no cl_env_percpu_fini on error */
+		goto out_lock;
+
 	return 0;
 out_lock:
 	cl_lock_fini();
@@ -1171,6 +1277,7 @@ out_store:
  */
 void cl_global_fini(void)
 {
+	cl_env_percpu_fini();
 	cl_lock_fini();
 	cl_page_fini();
 	lu_context_key_degister(&cl_key);
diff --git a/drivers/staging/lustre/lustre/obdclass/cl_page.c b/drivers/staging/lustre/lustre/obdclass/cl_page.c
index 8169836..bab8a74 100644
--- a/drivers/staging/lustre/lustre/obdclass/cl_page.c
+++ b/drivers/staging/lustre/lustre/obdclass/cl_page.c
@@ -123,7 +123,6 @@ static void cl_page_free(const struct lu_env *env, struct cl_page *page)
 	PASSERT(env, page, !page->cp_parent);
 	PASSERT(env, page, page->cp_state == CPS_FREEING);
 
-	might_sleep();
 	while (!list_empty(&page->cp_layers)) {
 		struct cl_page_slice *slice;
 
-- 
2.1.0

  parent reply	other threads:[~2016-03-30 16:49 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-03-30 16:47 [PATCH 00/43] Lustre IO stack simplifications and cleanups green
2016-03-30 16:47 ` [PATCH 01/43] staging/lustre/obdclass: limit lu_site hash table size green
2016-03-30 16:47 ` [PATCH 02/43] staging/lustre: Get rid of CFS_PAGE_MASK green
2016-03-30 16:47 ` [PATCH 03/43] staging/lustre: merge lclient/*.c into llite/ green
2016-03-30 16:47 ` [PATCH 04/43] staging/lustre: Reintroduce global env list green
2016-03-30 16:47 ` [PATCH 05/43] staging/lustre/osc: Adjustment on osc LRU for performance green
2016-03-30 16:47 ` [PATCH 06/43] staging/lustre/osc: to drop LRU pages with cl_lru_work green
2016-03-30 16:47 ` [PATCH 07/43] staging/lustre/clio: collapse layer of cl_page green
2016-03-30 16:47 ` green [this message]
2016-03-30 16:47 ` [PATCH 09/43] staging/lustre/clio: add pages into writeback cache in batches green
2016-03-30 16:47 ` [PATCH 10/43] staging/lustre/osc: add weight function for DLM lock green
2016-03-30 16:47 ` [PATCH 11/43] staging/lustre/clio: remove stackable cl_page completely green
2016-03-30 16:47 ` [PATCH 12/43] staging/lustre/clio: optimize read ahead code green
2016-03-30 16:47 ` [PATCH 13/43] staging/lustre/llite: remove lli_lvb green
2016-03-30 16:47 ` [PATCH 14/43] staging/lustre/lmv: remove lmv_init_{lock,unlock}() green
2016-03-30 16:47 ` [PATCH 15/43] staging/lustre/obd: remove struct client_obd_lock green
2016-03-30 16:47 ` [PATCH 16/43] staging/lustre/llite: remove some cl wrappers green
2016-03-30 16:47 ` [PATCH 17/43] staging/lustre: Remove struct ll_iattr green
2016-03-30 16:47 ` [PATCH 18/43] staging/lustre/clio: generalize cl_sync_io green
2016-03-30 16:47 ` [PATCH 19/43] staging/lustre/clio: cl_lock simplification green
2016-03-30 16:47 ` [PATCH 20/43] staging/lustre: update comments after " green
2016-03-30 16:47 ` [PATCH 21/43] staging/lustre/llite: clip page correctly for vvp_io_commit_sync green
2016-03-30 16:47 ` [PATCH 22/43] staging/lustre/llite: deadlock for page write green
2016-03-30 16:47 ` [PATCH 23/43] staging/lustre/llite: make sure we do cl_page_clip on the last page green
2016-03-30 16:47 ` [PATCH 24/43] staging/lustre/llite: merge lclient.h into llite/vvp_internal.h green
2016-03-30 16:47 ` [PATCH 25/43] staging/lustre/llite: rename ccc_device to vvp_device green
2016-03-30 16:47 ` [PATCH 26/43] staging/lustre/llite: rename ccc_object to vvp_object green
2016-03-30 16:47 ` [PATCH 27/43] staging/lustre/llite: rename ccc_page to vvp_page green
2016-03-30 16:48 ` [PATCH 28/43] staging/lustre/llite: rename ccc_lock to vvp_lock green
2016-03-30 16:48 ` [PATCH 29/43] staging/lustre:llite: remove struct ll_ra_read green
2016-03-30 16:48 ` [PATCH 30/43] staging/lustre/llite: merge ccc_io and vvp_io green
2016-03-30 16:48 ` [PATCH 31/43] staging/lustre/llite: use vui prefix for struct vvp_io members green
2016-03-30 16:48 ` [PATCH 32/43] staging/lustre/llite: move vvp_io functions to vvp_io.c green
2016-03-30 16:48 ` [PATCH 33/43] staging/lustre/llite: rename ccc_req to vvp_req green
2016-03-30 16:48 ` [PATCH 34/43] staging/lustre/llite: Rename struct ccc_grouplock to ll_grouplock green
2016-03-30 16:48 ` [PATCH 35/43] staging/lustre/llite: Rename struct vvp_thread_info to ll_thread_info green
2016-03-30 23:13   ` kbuild test robot
2016-03-30 23:39     ` [lustre-devel] " Oleg Drokin
2016-03-30 16:48 ` [PATCH 36/43] staging/lustre/llite: rename struct ccc_thread_info to vvp_thread_info green
2016-03-30 16:48 ` [PATCH 37/43] staging/lustre/llite: Remove ccc_global_{init,fini}() green
2016-03-30 16:48 ` [PATCH 38/43] staging/lustre/llite: Move ll_dirent_type_get and make it static green
2016-03-30 16:48 ` [PATCH 39/43] staging/lustre/llite: Move several declarations to llite_internal.h green
2016-03-30 16:48 ` [PATCH 40/43] staging/lustre/llite: Remove unused vui_local_lock field green
2016-03-30 16:48 ` [PATCH 41/43] staging/lustre/ldlm: ELC picks locks in a safer policy green
2016-03-30 16:48 ` [PATCH 42/43] staging/lustre/ldlm: revert changes to ldlm_cancel_aged_policy() green
2016-03-30 16:48 ` [PATCH 43/43] staging/lustre/ldlm: restore the ELC for enqueue green

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1459356495-2794775-9-git-send-email-green@linuxhacker.ru \
    --to=green@linuxhacker.ru \
    --cc=andreas.dilger@intel.com \
    --cc=devel@driverdev.osuosl.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=jinshan.xiong@intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lustre-devel@lists.lustre.org \
    --cc=surya1@llnl.gov \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox