From: James Simmons <jsimmons@infradead.org>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
devel@driverdev.osuosl.org,
Andreas Dilger <andreas.dilger@intel.com>,
Oleg Drokin <oleg.drokin@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>,
James Simmons <jsimmons@infradead.org>
Subject: [PATCH 57/80] staging: lustre: osc: revise unstable pages accounting
Date: Tue, 16 Aug 2016 16:19:10 -0400 [thread overview]
Message-ID: <1471378773-24590-58-git-send-email-jsimmons@infradead.org> (raw)
In-Reply-To: <1471378773-24590-1-git-send-email-jsimmons@infradead.org>
From: Jinshan Xiong <jinshan.xiong@intel.com>
A few changes are made in this patch for unstable pages tracking:
1. Remove kernel NFS unstable pages tracking because it killed
performance
2. Track unstable pages as part of LRU cache. Otherwise Lustre
can use much more memory than max_cached_mb
3. Remove obd_unstable_pages tracking to avoid using global
atomic counter
4. Make unstable pages track optional. Tracking unstable pages is
turned off by default, and can be controlled by
llite.*.unstable_stats.
Signed-off-by: Jinshan Xiong <jinshan.xiong@intel.com>
Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4841
Reviewed-on: http://review.whamcloud.com/10003
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Reviewed-by: Lai Siyao <lai.siyao@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
Signed-off-by: James Simmons <jsimmons@infradead.org>
---
drivers/staging/lustre/lustre/include/cl_object.h | 35 +++-
.../staging/lustre/lustre/include/obd_support.h | 1 -
drivers/staging/lustre/lustre/llite/lproc_llite.c | 41 ++++-
drivers/staging/lustre/lustre/obdclass/class_obd.c | 2 -
drivers/staging/lustre/lustre/osc/osc_cache.c | 96 +---------
drivers/staging/lustre/lustre/osc/osc_internal.h | 2 +-
drivers/staging/lustre/lustre/osc/osc_page.c | 208 +++++++++++++++++---
drivers/staging/lustre/lustre/osc/osc_request.c | 13 +-
8 files changed, 253 insertions(+), 145 deletions(-)
diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h
index d269b32..ec6cf7c 100644
--- a/drivers/staging/lustre/lustre/include/cl_object.h
+++ b/drivers/staging/lustre/lustre/include/cl_object.h
@@ -1039,23 +1039,32 @@ do { \
} \
} while (0)
-static inline int __page_in_use(const struct cl_page *page, int refc)
-{
- if (page->cp_type == CPT_CACHEABLE)
- ++refc;
- LASSERT(atomic_read(&page->cp_ref) > 0);
- return (atomic_read(&page->cp_ref) > refc);
-}
-
-#define cl_page_in_use(pg) __page_in_use(pg, 1)
-#define cl_page_in_use_noref(pg) __page_in_use(pg, 0)
-
static inline struct page *cl_page_vmpage(struct cl_page *page)
{
LASSERT(page->cp_vmpage);
return page->cp_vmpage;
}
+/**
+ * Check if a cl_page is in use.
+ *
+ * Client cache holds a refcount, this refcount will be dropped when
+ * the page is taken out of cache, see vvp_page_delete().
+ */
+static inline bool __page_in_use(const struct cl_page *page, int refc)
+{
+ return (atomic_read(&page->cp_ref) > refc + 1);
+}
+
+/**
+ * Caller itself holds a refcount of cl_page.
+ */
+#define cl_page_in_use(pg) __page_in_use(pg, 1)
+/**
+ * Caller doesn't hold a refcount.
+ */
+#define cl_page_in_use_noref(pg) __page_in_use(pg, 0)
+
/** @} cl_page */
/** \addtogroup cl_lock cl_lock
@@ -2331,6 +2340,10 @@ struct cl_client_cache {
*/
spinlock_t ccc_lru_lock;
/**
+ * Set if unstable check is enabled
+ */
+ unsigned int ccc_unstable_check:1;
+ /**
* # of unstable pages for this mount point
*/
atomic_t ccc_unstable_nr;
diff --git a/drivers/staging/lustre/lustre/include/obd_support.h b/drivers/staging/lustre/lustre/include/obd_support.h
index 26fdff6..a11fff1 100644
--- a/drivers/staging/lustre/lustre/include/obd_support.h
+++ b/drivers/staging/lustre/lustre/include/obd_support.h
@@ -54,7 +54,6 @@ extern int at_early_margin;
extern int at_extra;
extern unsigned int obd_sync_filter;
extern unsigned int obd_max_dirty_pages;
-extern atomic_t obd_unstable_pages;
extern atomic_t obd_dirty_pages;
extern atomic_t obd_dirty_transit_pages;
extern char obd_jobid_var[];
diff --git a/drivers/staging/lustre/lustre/llite/lproc_llite.c b/drivers/staging/lustre/lustre/llite/lproc_llite.c
index 2f1f389..5f8e78d 100644
--- a/drivers/staging/lustre/lustre/llite/lproc_llite.c
+++ b/drivers/staging/lustre/lustre/llite/lproc_llite.c
@@ -828,10 +828,45 @@ static ssize_t unstable_stats_show(struct kobject *kobj,
pages = atomic_read(&cache->ccc_unstable_nr);
mb = (pages * PAGE_SIZE) >> 20;
- return sprintf(buf, "unstable_pages: %8d\n"
- "unstable_mb: %8d\n", pages, mb);
+ return sprintf(buf, "unstable_check: %8d\n"
+ "unstable_pages: %8d\n"
+ "unstable_mb: %8d\n",
+ cache->ccc_unstable_check, pages, mb);
}
-LUSTRE_RO_ATTR(unstable_stats);
+
+static ssize_t unstable_stats_store(struct kobject *kobj,
+ struct attribute *attr,
+ const char *buffer,
+ size_t count)
+{
+ struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
+ ll_kobj);
+ char kernbuf[128];
+ int val, rc;
+
+ if (!count)
+ return 0;
+ if (count < 0 || count >= sizeof(kernbuf))
+ return -EINVAL;
+
+ if (copy_from_user(kernbuf, buffer, count))
+ return -EFAULT;
+ kernbuf[count] = 0;
+
+ buffer += lprocfs_find_named_value(kernbuf, "unstable_check:", &count) -
+ kernbuf;
+ rc = lprocfs_write_helper(buffer, count, &val);
+ if (rc < 0)
+ return rc;
+
+ /* borrow lru lock to set the value */
+ spin_lock(&sbi->ll_cache->ccc_lru_lock);
+ sbi->ll_cache->ccc_unstable_check = !!val;
+ spin_unlock(&sbi->ll_cache->ccc_lru_lock);
+
+ return count;
+}
+LUSTRE_RW_ATTR(unstable_stats);
static ssize_t root_squash_show(struct kobject *kobj, struct attribute *attr,
char *buf)
diff --git a/drivers/staging/lustre/lustre/obdclass/class_obd.c b/drivers/staging/lustre/lustre/obdclass/class_obd.c
index 6edf53e..90a365b 100644
--- a/drivers/staging/lustre/lustre/obdclass/class_obd.c
+++ b/drivers/staging/lustre/lustre/obdclass/class_obd.c
@@ -57,8 +57,6 @@ unsigned int obd_dump_on_eviction;
EXPORT_SYMBOL(obd_dump_on_eviction);
unsigned int obd_max_dirty_pages = 256;
EXPORT_SYMBOL(obd_max_dirty_pages);
-atomic_t obd_unstable_pages;
-EXPORT_SYMBOL(obd_unstable_pages);
atomic_t obd_dirty_pages;
EXPORT_SYMBOL(obd_dirty_pages);
unsigned int obd_timeout = OBD_TIMEOUT_DEFAULT; /* seconds */
diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c
index 683b3c2..deaf912 100644
--- a/drivers/staging/lustre/lustre/osc/osc_cache.c
+++ b/drivers/staging/lustre/lustre/osc/osc_cache.c
@@ -1384,13 +1384,11 @@ static int osc_completion(const struct lu_env *env, struct osc_async_page *oap,
#define OSC_DUMP_GRANT(lvl, cli, fmt, args...) do { \
struct client_obd *__tmp = (cli); \
CDEBUG(lvl, "%s: grant { dirty: %ld/%ld dirty_pages: %d/%d " \
- "unstable_pages: %d/%d dropped: %ld avail: %ld, " \
- "reserved: %ld, flight: %d } lru {in list: %d, " \
- "left: %d, waiters: %d }" fmt, \
+ "dropped: %ld avail: %ld, reserved: %ld, flight: %d }" \
+ "lru {in list: %d, left: %d, waiters: %d }" fmt, \
__tmp->cl_import->imp_obd->obd_name, \
__tmp->cl_dirty, __tmp->cl_dirty_max, \
atomic_read(&obd_dirty_pages), obd_max_dirty_pages, \
- atomic_read(&obd_unstable_pages), obd_max_dirty_pages, \
__tmp->cl_lost_grant, __tmp->cl_avail_grant, \
__tmp->cl_reserved_grant, __tmp->cl_w_in_flight, \
atomic_read(&__tmp->cl_lru_in_list), \
@@ -1542,8 +1540,7 @@ static int osc_enter_cache_try(struct client_obd *cli,
return 0;
if (cli->cl_dirty + PAGE_SIZE <= cli->cl_dirty_max &&
- atomic_read(&obd_unstable_pages) + 1 +
- atomic_read(&obd_dirty_pages) <= obd_max_dirty_pages) {
+ atomic_read(&obd_dirty_pages) + 1 <= obd_max_dirty_pages) {
osc_consume_write_grant(cli, &oap->oap_brw_page);
if (transient) {
cli->cl_dirty_transit += PAGE_SIZE;
@@ -1671,8 +1668,7 @@ void osc_wake_cache_waiters(struct client_obd *cli)
ocw->ocw_rc = -EDQUOT;
/* we can't dirty more */
if ((cli->cl_dirty + PAGE_SIZE > cli->cl_dirty_max) ||
- (atomic_read(&obd_unstable_pages) + 1 +
- atomic_read(&obd_dirty_pages) > obd_max_dirty_pages)) {
+ (atomic_read(&obd_dirty_pages) + 1 > obd_max_dirty_pages)) {
CDEBUG(D_CACHE, "no dirty room: dirty: %ld osc max %ld, sys max %d\n",
cli->cl_dirty,
cli->cl_dirty_max, obd_max_dirty_pages);
@@ -1843,84 +1839,6 @@ static void osc_process_ar(struct osc_async_rc *ar, __u64 xid,
ar->ar_force_sync = 0;
}
-/**
- * Performs "unstable" page accounting. This function balances the
- * increment operations performed in osc_inc_unstable_pages. It is
- * registered as the RPC request callback, and is executed when the
- * bulk RPC is committed on the server. Thus at this point, the pages
- * involved in the bulk transfer are no longer considered unstable.
- */
-void osc_dec_unstable_pages(struct ptlrpc_request *req)
-{
- struct client_obd *cli = &req->rq_import->imp_obd->u.cli;
- struct ptlrpc_bulk_desc *desc = req->rq_bulk;
- int page_count = desc->bd_iov_count;
- int i;
-
- /* No unstable page tracking */
- if (!cli->cl_cache)
- return;
-
- LASSERT(page_count >= 0);
-
- for (i = 0; i < page_count; i++)
- dec_node_page_state(desc->bd_iov[i].bv_page, NR_UNSTABLE_NFS);
-
- atomic_sub(page_count, &cli->cl_cache->ccc_unstable_nr);
- LASSERT(atomic_read(&cli->cl_cache->ccc_unstable_nr) >= 0);
-
- atomic_sub(page_count, &cli->cl_unstable_count);
- LASSERT(atomic_read(&cli->cl_unstable_count) >= 0);
-
- atomic_sub(page_count, &obd_unstable_pages);
- LASSERT(atomic_read(&obd_unstable_pages) >= 0);
-
- wake_up_all(&cli->cl_cache->ccc_unstable_waitq);
-}
-
-/* "unstable" page accounting. See: osc_dec_unstable_pages. */
-void osc_inc_unstable_pages(struct ptlrpc_request *req)
-{
- struct client_obd *cli = &req->rq_import->imp_obd->u.cli;
- struct ptlrpc_bulk_desc *desc = req->rq_bulk;
- long page_count = desc->bd_iov_count;
- int i;
-
- /* No unstable page tracking */
- if (!cli->cl_cache)
- return;
-
- LASSERT(page_count >= 0);
-
- for (i = 0; i < page_count; i++)
- inc_node_page_state(desc->bd_iov[i].bv_page, NR_UNSTABLE_NFS);
-
- LASSERT(atomic_read(&cli->cl_cache->ccc_unstable_nr) >= 0);
- atomic_add(page_count, &cli->cl_cache->ccc_unstable_nr);
-
- LASSERT(atomic_read(&cli->cl_unstable_count) >= 0);
- atomic_add(page_count, &cli->cl_unstable_count);
-
- LASSERT(atomic_read(&obd_unstable_pages) >= 0);
- atomic_add(page_count, &obd_unstable_pages);
-
- /*
- * If the request has already been committed (i.e. brw_commit
- * called via rq_commit_cb), we need to undo the unstable page
- * increments we just performed because rq_commit_cb wont be
- * called again.
- */
- spin_lock(&req->rq_lock);
- if (unlikely(req->rq_committed)) {
- /* Drop lock before calling osc_dec_unstable_pages */
- spin_unlock(&req->rq_lock);
- osc_dec_unstable_pages(req);
- } else {
- req->rq_unstable = 1;
- spin_unlock(&req->rq_lock);
- }
-}
-
/* this must be called holding the loi list lock to give coverage to exit_cache,
* async_flag maintenance, and oap_request
*/
@@ -1932,9 +1850,6 @@ static void osc_ap_completion(const struct lu_env *env, struct client_obd *cli,
__u64 xid = 0;
if (oap->oap_request) {
- if (!rc)
- osc_inc_unstable_pages(oap->oap_request);
-
xid = ptlrpc_req_xid(oap->oap_request);
ptlrpc_req_finished(oap->oap_request);
oap->oap_request = NULL;
@@ -2421,9 +2336,6 @@ int osc_queue_async_io(const struct lu_env *env, struct cl_io *io,
return rc;
}
- if (osc_over_unstable_soft_limit(cli))
- brw_flags |= OBD_BRW_SOFT_SYNC;
-
oap->oap_cmd = cmd;
oap->oap_page_off = ops->ops_from;
oap->oap_count = ops->ops_to - ops->ops_from;
diff --git a/drivers/staging/lustre/lustre/osc/osc_internal.h b/drivers/staging/lustre/lustre/osc/osc_internal.h
index 2038885..eca5fef 100644
--- a/drivers/staging/lustre/lustre/osc/osc_internal.h
+++ b/drivers/staging/lustre/lustre/osc/osc_internal.h
@@ -197,7 +197,7 @@ int osc_quotacheck(struct obd_device *unused, struct obd_export *exp,
int osc_quota_poll_check(struct obd_export *exp, struct if_quotacheck *qchk);
void osc_inc_unstable_pages(struct ptlrpc_request *req);
void osc_dec_unstable_pages(struct ptlrpc_request *req);
-int osc_over_unstable_soft_limit(struct client_obd *cli);
+bool osc_over_unstable_soft_limit(struct client_obd *cli);
struct ldlm_lock *osc_dlmlock_at_pgoff(const struct lu_env *env,
struct osc_object *obj, pgoff_t index,
diff --git a/drivers/staging/lustre/lustre/osc/osc_page.c b/drivers/staging/lustre/lustre/osc/osc_page.c
index 355f496..583a0af 100644
--- a/drivers/staging/lustre/lustre/osc/osc_page.c
+++ b/drivers/staging/lustre/lustre/osc/osc_page.c
@@ -323,32 +323,6 @@ int osc_page_init(const struct lu_env *env, struct cl_object *obj,
return result;
}
-int osc_over_unstable_soft_limit(struct client_obd *cli)
-{
- long obd_upages, obd_dpages, osc_upages;
-
- /* Can't check cli->cl_unstable_count, therefore, no soft limit */
- if (!cli)
- return 0;
-
- obd_upages = atomic_read(&obd_unstable_pages);
- obd_dpages = atomic_read(&obd_dirty_pages);
-
- osc_upages = atomic_read(&cli->cl_unstable_count);
-
- /*
- * obd_max_dirty_pages is the max number of (dirty + unstable)
- * pages allowed at any given time. To simulate an unstable page
- * only limit, we subtract the current number of dirty pages
- * from this max. This difference is roughly the amount of pages
- * currently available for unstable pages. Thus, the soft limit
- * is half of that difference. Check osc_upages to ensure we don't
- * set SOFT_SYNC for OSCs without any outstanding unstable pages.
- */
- return osc_upages &&
- obd_upages >= (obd_max_dirty_pages - obd_dpages) / 2;
-}
-
/**
* Helper function called by osc_io_submit() for every page in an immediate
* transfer (i.e., transferred synchronously).
@@ -368,9 +342,6 @@ void osc_page_submit(const struct lu_env *env, struct osc_page *opg,
oap->oap_count = opg->ops_to - opg->ops_from;
oap->oap_brw_flags = brw_flags | OBD_BRW_SYNC;
- if (osc_over_unstable_soft_limit(oap->oap_cli))
- oap->oap_brw_flags |= OBD_BRW_SOFT_SYNC;
-
if (capable(CFS_CAP_SYS_RESOURCE)) {
oap->oap_brw_flags |= OBD_BRW_NOQUOTA;
oap->oap_cmd |= OBD_BRW_NOQUOTA;
@@ -540,6 +511,28 @@ static void discard_pagevec(const struct lu_env *env, struct cl_io *io,
}
/**
+ * Check if a cl_page can be released, i.e, it's not being used.
+ *
+ * If unstable account is turned on, bulk transfer may hold one refcount
+ * for recovery so we need to check vmpage refcount as well; otherwise,
+ * even we can destroy cl_page but the corresponding vmpage can't be reused.
+ */
+static inline bool lru_page_busy(struct client_obd *cli, struct cl_page *page)
+{
+ if (cl_page_in_use_noref(page))
+ return true;
+
+ if (cli->cl_cache->ccc_unstable_check) {
+ struct page *vmpage = cl_page_vmpage(page);
+
+ /* vmpage have two known users: cl_page and VM page cache */
+ if (page_count(vmpage) - page_mapcount(vmpage) > 2)
+ return true;
+ }
+ return false;
+}
+
+/**
* Drop @target of pages from LRU at most.
*/
int osc_lru_shrink(const struct lu_env *env, struct client_obd *cli,
@@ -584,7 +577,7 @@ int osc_lru_shrink(const struct lu_env *env, struct client_obd *cli,
break;
page = opg->ops_cl.cpl_page;
- if (cl_page_in_use_noref(page)) {
+ if (lru_page_busy(cli, page)) {
list_move_tail(&opg->ops_lru, &cli->cl_lru_list);
continue;
}
@@ -620,7 +613,7 @@ int osc_lru_shrink(const struct lu_env *env, struct client_obd *cli,
}
if (cl_page_own_try(env, io, page) == 0) {
- if (!cl_page_in_use_noref(page)) {
+ if (!lru_page_busy(cli, page)) {
/* remove it from lru list earlier to avoid
* lock contention
*/
@@ -742,6 +735,13 @@ out:
return rc;
}
+/**
+ * osc_lru_reserve() is called to reserve an LRU slot for a cl_page.
+ *
+ * Usually the LRU slots are reserved in osc_io_iter_rw_init().
+ * Only in the case that the LRU slots are in extreme shortage, it should
+ * have reserved enough slots for an IO.
+ */
static int osc_lru_reserve(const struct lu_env *env, struct osc_object *obj,
struct osc_page *opg)
{
@@ -787,4 +787,150 @@ out:
return rc;
}
+/**
+ * Atomic operations are expensive. We accumulate the accounting for the
+ * same page zone to get better performance.
+ * In practice this can work pretty good because the pages in the same RPC
+ * are likely from the same page zone.
+ */
+static inline void unstable_page_accounting(struct ptlrpc_bulk_desc *desc,
+ int factor)
+{
+ int page_count = desc->bd_iov_count;
+ void *zone = NULL;
+ int count = 0;
+ int i;
+
+ for (i = 0; i < page_count; i++) {
+ void *pz = page_zone(desc->bd_iov[i].bv_page);
+
+ if (likely(pz == zone)) {
+ ++count;
+ continue;
+ }
+
+ if (count > 0) {
+ mod_zone_page_state(zone, NR_UNSTABLE_NFS,
+ factor * count);
+ count = 0;
+ }
+ zone = pz;
+ ++count;
+ }
+ if (count > 0)
+ mod_zone_page_state(zone, NR_UNSTABLE_NFS, factor * count);
+}
+
+static inline void add_unstable_page_accounting(struct ptlrpc_bulk_desc *desc)
+{
+ unstable_page_accounting(desc, 1);
+}
+
+static inline void dec_unstable_page_accounting(struct ptlrpc_bulk_desc *desc)
+{
+ unstable_page_accounting(desc, -1);
+}
+
+/**
+ * Performs "unstable" page accounting. This function balances the
+ * increment operations performed in osc_inc_unstable_pages. It is
+ * registered as the RPC request callback, and is executed when the
+ * bulk RPC is committed on the server. Thus at this point, the pages
+ * involved in the bulk transfer are no longer considered unstable.
+ *
+ * If this function is called, the request should have been committed
+ * or req:rq_unstable must have been set; it implies that the unstable
+ * statistic have been added.
+ */
+void osc_dec_unstable_pages(struct ptlrpc_request *req)
+{
+ struct client_obd *cli = &req->rq_import->imp_obd->u.cli;
+ struct ptlrpc_bulk_desc *desc = req->rq_bulk;
+ int page_count = desc->bd_iov_count;
+ int unstable_count;
+
+ LASSERT(page_count >= 0);
+ dec_unstable_page_accounting(desc);
+
+ unstable_count = atomic_sub_return(page_count, &cli->cl_unstable_count);
+ LASSERT(unstable_count >= 0);
+
+ unstable_count = atomic_sub_return(page_count,
+ &cli->cl_cache->ccc_unstable_nr);
+ LASSERT(unstable_count >= 0);
+ if (!unstable_count)
+ wake_up_all(&cli->cl_cache->ccc_unstable_waitq);
+
+ if (osc_cache_too_much(cli))
+ (void)ptlrpcd_queue_work(cli->cl_lru_work);
+}
+
+/**
+ * "unstable" page accounting. See: osc_dec_unstable_pages.
+ */
+void osc_inc_unstable_pages(struct ptlrpc_request *req)
+{
+ struct client_obd *cli = &req->rq_import->imp_obd->u.cli;
+ struct ptlrpc_bulk_desc *desc = req->rq_bulk;
+ int page_count = desc->bd_iov_count;
+
+ /* No unstable page tracking */
+ if (!cli->cl_cache || !cli->cl_cache->ccc_unstable_check)
+ return;
+
+ add_unstable_page_accounting(desc);
+ atomic_add(page_count, &cli->cl_unstable_count);
+ atomic_add(page_count, &cli->cl_cache->ccc_unstable_nr);
+
+ /*
+ * If the request has already been committed (i.e. brw_commit
+ * called via rq_commit_cb), we need to undo the unstable page
+ * increments we just performed because rq_commit_cb wont be
+ * called again.
+ */
+ spin_lock(&req->rq_lock);
+ if (unlikely(req->rq_committed)) {
+ spin_unlock(&req->rq_lock);
+
+ osc_dec_unstable_pages(req);
+ } else {
+ req->rq_unstable = 1;
+ spin_unlock(&req->rq_lock);
+ }
+}
+
+/**
+ * Check if it piggybacks SOFT_SYNC flag to OST from this OSC.
+ * This function will be called by every BRW RPC so it's critical
+ * to make this function fast.
+ */
+bool osc_over_unstable_soft_limit(struct client_obd *cli)
+{
+ long unstable_nr, osc_unstable_count;
+
+ /* Can't check cli->cl_unstable_count, therefore, no soft limit */
+ if (!cli->cl_cache || !cli->cl_cache->ccc_unstable_check)
+ return false;
+
+ osc_unstable_count = atomic_read(&cli->cl_unstable_count);
+ unstable_nr = atomic_read(&cli->cl_cache->ccc_unstable_nr);
+
+ CDEBUG(D_CACHE,
+ "%s: cli: %p unstable pages: %lu, osc unstable pages: %lu\n",
+ cli->cl_import->imp_obd->obd_name, cli,
+ unstable_nr, osc_unstable_count);
+
+ /*
+ * If the LRU slots are in shortage - 25% remaining AND this OSC
+ * has one full RPC window of unstable pages, it's a good chance
+ * to piggyback a SOFT_SYNC flag.
+ * Please notice that the OST won't take immediate response for the
+ * SOFT_SYNC request so active OSCs will have more chance to carry
+ * the flag, this is reasonable.
+ */
+ return unstable_nr > cli->cl_cache->ccc_lru_max >> 2 &&
+ osc_unstable_count > cli->cl_max_pages_per_rpc *
+ cli->cl_max_rpcs_in_flight;
+}
+
/** @} osc */
diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c
index 042a081..e5669e2 100644
--- a/drivers/staging/lustre/lustre/osc/osc_request.c
+++ b/drivers/staging/lustre/lustre/osc/osc_request.c
@@ -807,17 +807,15 @@ static void osc_announce_cached(struct client_obd *cli, struct obdo *oa,
CERROR("dirty %lu - %lu > dirty_max %lu\n",
cli->cl_dirty, cli->cl_dirty_transit, cli->cl_dirty_max);
oa->o_undirty = 0;
- } else if (unlikely(atomic_read(&obd_unstable_pages) +
- atomic_read(&obd_dirty_pages) -
+ } else if (unlikely(atomic_read(&obd_dirty_pages) -
atomic_read(&obd_dirty_transit_pages) >
(long)(obd_max_dirty_pages + 1))) {
/* The atomic_read() allowing the atomic_inc() are
* not covered by a lock thus they may safely race and trip
* this CERROR() unless we add in a small fudge factor (+1).
*/
- CERROR("%s: dirty %d + %d - %d > system dirty_max %d\n",
+ CERROR("%s: dirty %d + %d > system dirty_max %d\n",
cli->cl_import->imp_obd->obd_name,
- atomic_read(&obd_unstable_pages),
atomic_read(&obd_dirty_pages),
atomic_read(&obd_dirty_transit_pages),
obd_max_dirty_pages);
@@ -1818,6 +1816,9 @@ static int brw_interpret(const struct lu_env *env,
}
kmem_cache_free(obdo_cachep, aa->aa_oa);
+ if (lustre_msg_get_opc(req->rq_reqmsg) == OST_WRITE && rc == 0)
+ osc_inc_unstable_pages(req);
+
list_for_each_entry_safe(ext, tmp, &aa->aa_exts, oe_link) {
list_del_init(&ext->oe_link);
osc_extent_finish(env, ext, 1, rc);
@@ -1888,6 +1889,7 @@ int osc_build_rpc(const struct lu_env *env, struct client_obd *cli,
int mpflag = 0;
int mem_tight = 0;
int page_count = 0;
+ bool soft_sync = false;
int i;
int rc;
struct ost_body *body;
@@ -1915,6 +1917,7 @@ int osc_build_rpc(const struct lu_env *env, struct client_obd *cli,
}
}
+ soft_sync = osc_over_unstable_soft_limit(cli);
if (mem_tight)
mpflag = cfs_memory_pressure_get_and_set();
@@ -1950,6 +1953,8 @@ int osc_build_rpc(const struct lu_env *env, struct client_obd *cli,
}
if (mem_tight)
oap->oap_brw_flags |= OBD_BRW_MEMALLOC;
+ if (soft_sync)
+ oap->oap_brw_flags |= OBD_BRW_SOFT_SYNC;
pga[i] = &oap->oap_brw_page;
pga[i]->off = oap->oap_obj_off + oap->oap_page_off;
CDEBUG(0, "put page %p index %lu oap %p flg %x to pga\n",
--
1.7.1
next prev parent reply other threads:[~2016-08-16 20:21 UTC|newest]
Thread overview: 94+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-08-16 20:18 [PATCH 00/80] staging: lustre: majority of missing fixes for 2.6 release James Simmons
2016-08-16 20:18 ` [PATCH 01/80] staging: lustre: llite: add md_op_data parameter to ll_get_dir_page James Simmons
2016-08-16 20:18 ` [PATCH 02/80] staging: lustre: llite: remove comment from ll_dir_read James Simmons
2016-08-16 20:18 ` [PATCH 03/80] staging: lustre: llite: style cleanup for llite_internal.h James Simmons
2016-08-16 20:18 ` [PATCH 04/80] staging: lustre: llite: pass inode to ll_release_page James Simmons
2016-08-16 20:18 ` [PATCH 05/80] staging: lustre: llite: change remove parameter to bool James Simmons
2016-08-16 20:18 ` [PATCH 06/80] staging: lustre: mdc: don't take rpc lock for readdir case James Simmons
2016-08-16 20:18 ` [PATCH 07/80] staging: lustre: lmv: remove unused lmv_get_mea function James Simmons
2016-08-16 20:18 ` [PATCH 08/80] staging: lustre: lmv: remove duplicate MAX_HASH_* James Simmons
2016-08-16 20:18 ` [PATCH 09/80] staging: lustre: lmv: change handling of lmv striping information James Simmons
2016-08-16 20:18 ` [PATCH 10/80] staging: lustre: lmv: remove lmv_get_easize James Simmons
2016-08-16 20:18 ` [PATCH 11/80] staging: lustre: lmv: replace obd_free_memmd with lmv_free_memmd James Simmons
2016-08-16 20:18 ` [PATCH 12/80] staging: lustre: create striped directory James Simmons
2016-08-16 20:18 ` [PATCH 13/80] staging: lustre: llite: fix "getdirstripe" to show stripe info James Simmons
2016-08-16 20:18 ` [PATCH 14/80] staging: lustre: delete striped directory James Simmons
2016-08-16 20:18 ` [PATCH 15/80] staging: lustre: obdclass: fix lmd_parse() to handle comma-separated NIDs James Simmons
2016-08-16 20:18 ` [PATCH 16/80] staging: lustre: obdclass: bug fixes for lu_device_type handling James Simmons
2016-08-16 20:18 ` [PATCH 17/80] staging: lustre: add ability to migrate inodes James Simmons
2016-08-16 20:18 ` [PATCH 18/80] staging: lustre: lmv: fix issue found by Klocwork Insight tool James Simmons
2016-08-16 20:18 ` [PATCH 19/80] staging: lustre: libcfs: Only dump log once per sec. to avoid EEXIST James Simmons
2016-08-16 20:18 ` [PATCH 20/80] staging: lustre: llite: enable clients to inject error for lfsck James Simmons
2016-08-16 20:18 ` [PATCH 21/80] staging: lustre: osc: allow to call brw_commit() multiple times James Simmons
2016-08-16 20:18 ` [PATCH 22/80] staging: lustre: llite: a few fixes for migration James Simmons
2016-08-16 20:18 ` [PATCH 23/80] staging: lustre: mdc: fixup MDS_SWAP_LAYOUTS ELC handling James Simmons
2016-08-16 20:18 ` [PATCH 24/80] staging: lustre: don't need to const __u64 parameters for lustre_idl.h James Simmons
2016-08-16 20:18 ` [PATCH 25/80] staging: lustre: const correct FID/OSTID/... helpers James Simmons
2016-08-16 20:18 ` [PATCH 26/80] staging: lustre: use bool for several function in lustre_idl.h/lustre_fid.h James Simmons
2016-08-16 20:18 ` [PATCH 27/80] staging: lustre: simplify inline functions in lustre_fid.h James Simmons
2016-08-16 20:18 ` [PATCH 28/80] staging: lustre: lmv: access lum_stripe_offset as little endian James Simmons
2016-08-16 20:18 ` [PATCH 29/80] staging: lustre: lmv: lookup remote migrating object in LMV James Simmons
2016-08-16 20:18 ` [PATCH 30/80] staging: lustre: lmv: Ensure lmv_intent_lookup cleans up reqp James Simmons
2016-08-16 20:18 ` [PATCH 31/80] staging: lustre: llite: avoid a deadlock in page write James Simmons
2016-08-16 20:18 ` [PATCH 32/80] staging: lustre: lov: handle the case of stripe size is not power 2 James Simmons
2016-08-16 20:18 ` [PATCH 33/80] staging: lustre: lmv: cleanup req in lmv_getattr_name() James Simmons
2016-08-16 20:18 ` [PATCH 34/80] staging: lustre: lmv: rename request to preq " James Simmons
2016-08-16 20:18 ` [PATCH 35/80] staging: lustre: obdclass: unified flow control interfaces James Simmons
2016-08-16 20:18 ` [PATCH 36/80] staging: lustre: reorder LOV_MAGIC_* definition James Simmons
2016-08-16 20:18 ` [PATCH 37/80] staging: lustre: ldlm: flock completion fixes James Simmons
2016-08-16 20:18 ` [PATCH 38/80] staging: lustre: move ioctls to lustre_ioctl.h James Simmons
2016-08-16 20:18 ` [PATCH 39/80] staging: lustre: llite: add error handler in inode prepare phase James Simmons
2016-08-16 20:18 ` [PATCH 40/80] staging: lustre: ptlrpc: Early replies need to honor at_max James Simmons
2016-08-16 20:18 ` [PATCH 41/80] staging: lustre: lmv: separate master object with master stripe James Simmons
2018-02-09 1:39 ` NeilBrown
2018-02-09 2:01 ` Oleg Drokin
2018-02-09 3:10 ` NeilBrown
2018-02-09 3:50 ` [lustre-devel] " Oleg Drokin
2018-02-10 20:57 ` James Simmons
2018-02-11 23:50 ` NeilBrown
2018-02-12 0:06 ` Oleg Drokin
2018-02-11 23:44 ` NeilBrown
2018-02-12 0:52 ` Oleg Drokin
2018-02-10 22:14 ` James Simmons
2018-02-12 7:41 ` Dan Carpenter
2016-08-16 20:18 ` [PATCH 42/80] staging: lustre: llite: validate names James Simmons
2016-08-16 20:18 ` [PATCH 43/80] staging: lustre: llite: fix inconsistencies of root squash feature James Simmons
2016-08-16 20:18 ` [PATCH 44/80] staging: lustre: Remove static declaration in anonymous union James Simmons
2016-08-16 20:18 ` [PATCH 45/80] staging: lustre: llite: Fix the deadlock in balance_dirty_pages() James Simmons
2016-08-16 20:18 ` [PATCH 46/80] staging: lustre: llite: Change readdir BRW metrics James Simmons
2016-08-16 20:19 ` [PATCH 47/80] staging: lustre: uapi: reduce scope of lustre_idl.h James Simmons
2016-08-16 20:19 ` [PATCH 48/80] staging: lustre: llite: a few fixes about readdir of striped dir James Simmons
2016-08-16 20:19 ` [PATCH 49/80] staging: lustre: lmv: validate lock with correct stripe FID James Simmons
2016-08-16 20:19 ` [PATCH 50/80] staging: lustre: lov: new pattern flag for partially repaired file James Simmons
2016-08-16 20:19 ` [PATCH 51/80] staging: lustre: lmv: Match MDT where the FID locates first James Simmons
2016-08-16 20:19 ` [PATCH 52/80] staging: lustre: llite: use the correct mode for striped directory James Simmons
2016-08-16 20:19 ` [PATCH 53/80] staging: lustre: obd: rename lsr_padding to lsr_valid James Simmons
2016-08-16 20:19 ` [PATCH 54/80] staging: lustre: llite: set dir LOV xattr length variable James Simmons
2016-08-16 20:19 ` [PATCH 55/80] staging: lustre: mdt: add mbo_ prefix to members of struct mdt_body James Simmons
2016-08-16 20:19 ` [PATCH 56/80] staging: lustre: clio: Reduce memory overhead of per-page allocation James Simmons
2016-08-16 20:19 ` James Simmons [this message]
2016-10-16 15:14 ` [PATCH 57/80] staging: lustre: osc: revise unstable pages accounting Greg Kroah-Hartman
2016-10-16 17:16 ` Oleg Drokin
2016-08-16 20:19 ` [PATCH 58/80] staging: lustre: mdc: always use D_INFO for debug info when mdc_put_rpc_lock fails James Simmons
2016-08-16 20:19 ` [PATCH 59/80] staging: lustre: fld: add fld description documentation James Simmons
2016-08-16 20:19 ` [PATCH 60/80] staging: lustre: ldlm: improve ldlm_lock_create() return value James Simmons
2016-08-16 20:19 ` [PATCH 61/80] staging: lustre: obdclass: compile issues with variable not being initialized James Simmons
2016-08-16 20:19 ` [PATCH 62/80] staging: lustre: obd: limit lu_object cache James Simmons
2016-08-16 20:19 ` [PATCH 63/80] staging: lustre: fid: do open-by-fid by default James Simmons
2016-08-16 20:19 ` [PATCH 64/80] staging: lustre: ptlrpc: add OBD_CONNECT_UNLINK_CLOSE flag James Simmons
2016-08-16 20:19 ` [PATCH 65/80] staging: lustre: llog: keep llog ctxt indices constant James Simmons
2016-08-16 20:19 ` [PATCH 66/80] staging: lustre: lmv: try all stripes for unknown hash functions James Simmons
2016-08-16 20:19 ` [PATCH 67/80] staging: lustre: ptlrpc: request gets stuck in UNREGISTERING phase James Simmons
2016-08-16 20:19 ` [PATCH 68/80] staging: lustre: lmv: build master LMV EA dynamically build via readdir James Simmons
2016-08-16 20:19 ` [PATCH 69/80] staging: lustre: osc: Automatically increase the max_dirty_mb James Simmons
2016-08-16 20:19 ` [PATCH 70/80] staging: lustre: include: fix one off errors in lustre_id.h James Simmons
2016-08-16 20:19 ` [PATCH 71/80] staging: lustre: llite: remove assert for acl refcount James Simmons
2016-08-16 20:19 ` [PATCH 72/80] staging: lustre: obd: validate open handle cookies James Simmons
2016-08-16 20:19 ` [PATCH 73/80] staging: lustre: lmv: build error with gcc 4.7.0 20110509 James Simmons
2016-08-16 20:19 ` [PATCH 74/80] staging: lustre: obd: implement md_read_page James Simmons
2016-08-16 20:19 ` [PATCH 75/80] staging: lustre: llite: set op_max_pages James Simmons
2016-08-16 20:19 ` [PATCH 76/80] staging: lustre: lnet: Do not drop message when shutting down LNet James Simmons
2016-08-16 20:19 ` [PATCH 77/80] staging: lustre: lnet: Correct position of lnet_ni_decref() James Simmons
2016-08-16 20:19 ` [PATCH 78/80] staging: lustre: lnet: make connection more stable with packet loss James Simmons
2016-08-16 20:19 ` [PATCH 79/80] staging: lustre: lnet: lock improvement for ko2iblnd James Simmons
2016-08-16 20:19 ` [PATCH 80/80] staging: lustre: lnet: Stop Infinite CON RACE Condition James Simmons
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=1471378773-24590-58-git-send-email-jsimmons@infradead.org \
--to=jsimmons@infradead.org \
--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=oleg.drokin@intel.com \
/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
all inboxes | Powered by JetHome®