In osc_enter_cache(), when there is high contention on grant, the
returned grant could be consumed by other process immediately, then
we should repeat flush until get enough grant or no dirty to be
flushed. Otherwise, mmap writer could easily get -EDQUOT on the
osc_enter_cache() and result in SIGBUS at the end.
Because we now changed to async flush in osc_enter_cache(), the
wakeup condition is changed accordingly.
This patch also temporarily disabled osc lru shrinker in
osc_io_unplug() to avoid the potential stack overrun problem.
See LU-2859.
Signed-off-by: Niu Yawei <yawei.niu@intel.com>
Change-Id: I0c7c90ffe27dab6ded7ad07ed78017acb8665d59
Reviewed-on: http://review.whamcloud.com/5732
Tested-by: Hudson
Tested-by: Maloo <whamcloud.maloo@gmail.com>
Reviewed-by: Keith Mannthey <keith.mannthey@intel.com>
Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
{
int rc;
client_obd_list_lock(&cli->cl_loi_list_lock);
{
int rc;
client_obd_list_lock(&cli->cl_loi_list_lock);
- rc = cfs_list_empty(&ocw->ocw_entry) || cli->cl_w_in_flight == 0;
+ rc = cfs_list_empty(&ocw->ocw_entry);
client_obd_list_unlock(&cli->cl_loi_list_lock);
return rc;
}
client_obd_list_unlock(&cli->cl_loi_list_lock);
return rc;
}
cfs_waitq_init(&ocw.ocw_waitq);
ocw.ocw_oap = oap;
ocw.ocw_grant = bytes;
cfs_waitq_init(&ocw.ocw_waitq);
ocw.ocw_oap = oap;
ocw.ocw_grant = bytes;
- if (cli->cl_dirty > 0 || cli->cl_w_in_flight > 0) {
+ while (cli->cl_dirty > 0 || cli->cl_w_in_flight > 0) {
cfs_list_add_tail(&ocw.ocw_entry, &cli->cl_cache_waiters);
ocw.ocw_rc = 0;
client_obd_list_unlock(&cli->cl_loi_list_lock);
cfs_list_add_tail(&ocw.ocw_entry, &cli->cl_cache_waiters);
ocw.ocw_rc = 0;
client_obd_list_unlock(&cli->cl_loi_list_lock);
- /* If ocw_entry isn't empty, which means it's not waked up
- * by osc_wake_cache_waiters(), then the page must not be
- * granted yet. */
- if (!cfs_list_empty(&ocw.ocw_entry)) {
- rc = -EDQUOT;
- cfs_list_del_init(&ocw.ocw_entry);
- } else {
- rc = ocw.ocw_rc;
- }
+ LASSERT(cfs_list_empty(&ocw.ocw_entry));
+ rc = ocw.ocw_rc;
if (rc != -EDQUOT)
GOTO(out, rc);
if (osc_enter_cache_try(cli, oap, bytes, 0))
if (rc != -EDQUOT)
GOTO(out, rc);
if (osc_enter_cache_try(cli, oap, bytes, 0))
ENTRY;
cfs_list_for_each_safe(l, tmp, &cli->cl_cache_waiters) {
ENTRY;
cfs_list_for_each_safe(l, tmp, &cli->cl_cache_waiters) {
- /* if we can't dirty more, we must wait until some is written */
+ ocw = cfs_list_entry(l, struct osc_cache_waiter, ocw_entry);
+ cfs_list_del_init(&ocw->ocw_entry);
+
+ ocw->ocw_rc = -EDQUOT;
+ /* we can't dirty more */
if ((cli->cl_dirty + CFS_PAGE_SIZE > cli->cl_dirty_max) ||
(cfs_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);
if ((cli->cl_dirty + CFS_PAGE_SIZE > cli->cl_dirty_max) ||
(cfs_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);
- return;
- }
-
- /* if still dirty cache but no grant wait for pending RPCs that
- * may yet return us some grant before doing sync writes */
- if (cli->cl_w_in_flight && cli->cl_avail_grant < CFS_PAGE_SIZE) {
- CDEBUG(D_CACHE, "%u BRW writes in flight, no grant\n",
- cli->cl_w_in_flight);
- return;
- ocw = cfs_list_entry(l, struct osc_cache_waiter, ocw_entry);
- cfs_list_del_init(&ocw->ocw_entry);
-
ocw->ocw_rc = 0;
if (!osc_enter_cache_try(cli, ocw->ocw_oap, ocw->ocw_grant, 0))
ocw->ocw_rc = -EDQUOT;
ocw->ocw_rc = 0;
if (!osc_enter_cache_try(cli, ocw->ocw_oap, ocw->ocw_grant, 0))
ocw->ocw_rc = -EDQUOT;
CDEBUG(D_CACHE, "wake up %p for oap %p, avail grant %ld, %d\n",
ocw, ocw->ocw_oap, cli->cl_avail_grant, ocw->ocw_rc);
CDEBUG(D_CACHE, "wake up %p for oap %p, avail grant %ld, %d\n",
ocw, ocw->ocw_oap, cli->cl_avail_grant, ocw->ocw_rc);
has_rpcs = __osc_list_maint(cli, osc);
if (has_rpcs) {
if (!async) {
has_rpcs = __osc_list_maint(cli, osc);
if (has_rpcs) {
if (!async) {
+ /* disable osc_lru_shrink() temporarily to avoid
+ * potential stack overrun problem. LU-2859 */
+ cfs_atomic_inc(&cli->cl_lru_shrinkers);
osc_check_rpcs(env, cli, pol);
osc_check_rpcs(env, cli, pol);
+ cfs_atomic_dec(&cli->cl_lru_shrinkers);
} else {
CDEBUG(D_CACHE, "Queue writeback work for client %p.\n",
cli);
} else {
CDEBUG(D_CACHE, "Queue writeback work for client %p.\n",
cli);