#define ldlm_set_flock_deadlock(_l) LDLM_SET_FLAG(( _l), 1ULL << 15)
#define ldlm_clear_flock_deadlock(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 15)
-/** discard (no writeback) on cancel */
+/** discard (no writeback (PW locks) or page retention (PR locks)) on cancel */
#define LDLM_FL_DISCARD_DATA 0x0000000000010000ULL // bit 16
#define ldlm_is_discard_data(_l) LDLM_TEST_FLAG(( _l), 1ULL << 16)
#define ldlm_set_discard_data(_l) LDLM_SET_FLAG(( _l), 1ULL << 16)
int osc_extent_release(const struct lu_env *env, struct osc_extent *ext);
int osc_lock_discard_pages(const struct lu_env *env, struct osc_object *osc,
- pgoff_t start, pgoff_t end, enum cl_lock_mode mode);
+ pgoff_t start, pgoff_t end, bool discard_pages);
typedef int (*osc_page_gang_cbt)(const struct lu_env *, struct cl_io *,
struct osc_page *, void *);
LDLM_LRU_FLAG_LRUR = 0x08, /* Cancel locks from lru resize */
LDLM_LRU_FLAG_NO_WAIT = 0x10, /* Cancel locks w/o blocking (neither
* sending nor waiting for any RPCs) */
+ LDLM_LRU_FLAG_CLEANUP = 0x20, /* Used when clearing lru, tells
+ * prepare_lru_list to set discard flag
+ * on PR extent locks so we don't waste
+ * time saving pages that will be
+ * discarded momentarily */
};
int ldlm_cancel_lru(struct ldlm_namespace *ns, int nr,
* (typically before replaying locks) w/o
* sending any RPCs or waiting for any
* outstanding RPC to complete.
+ *
+ * flags & LDLM_CANCEL_CLEANUP - when cancelling read locks, do not check for
+ * other read locks covering the same pages, just
+ * discard those pages.
*/
static int ldlm_prepare_lru_list(struct ldlm_namespace *ns,
struct list_head *cancels, int count, int max,
* this flag and call l_blocking_ast */
lock->l_flags |= LDLM_FL_CBPENDING | LDLM_FL_CANCELING;
+ if ((lru_flags & LDLM_LRU_FLAG_CLEANUP) &&
+ lock->l_resource->lr_type == LDLM_EXTENT &&
+ lock->l_granted_mode == LCK_PR)
+ ldlm_set_discard_data(lock);
+
/* We can't re-add to l_lru as it confuses the
* refcounting in ldlm_lock_remove_from_lru() if an AST
* arrives after we drop lr_lock below. We use l_bl_ast
/* Try to cancel all @ns_nr_unused locks. */
canceled = ldlm_cancel_lru(ns, unused, 0,
- LDLM_LRU_FLAG_PASSED);
+ LDLM_LRU_FLAG_PASSED |
+ LDLM_LRU_FLAG_CLEANUP);
if (canceled < unused) {
CDEBUG(D_DLMTRACE,
"not all requested locks are canceled, requested: %d, canceled: %d\n",
} else {
tmp = ns->ns_max_unused;
ns->ns_max_unused = 0;
- ldlm_cancel_lru(ns, 0, 0, LDLM_LRU_FLAG_PASSED);
+ ldlm_cancel_lru(ns, 0, 0, LDLM_LRU_FLAG_PASSED |
+ LDLM_LRU_FLAG_CLEANUP);
ns->ns_max_unused = tmp;
}
return count;
* behind this being that lock cancellation cannot be delayed indefinitely).
*/
int osc_lock_discard_pages(const struct lu_env *env, struct osc_object *osc,
- pgoff_t start, pgoff_t end, enum cl_lock_mode mode)
+ pgoff_t start, pgoff_t end, bool discard)
{
struct osc_thread_info *info = osc_env_info(env);
struct cl_io *io = &info->oti_io;
if (result != 0)
GOTO(out, result);
- cb = mode == CLM_READ ? check_and_discard_cb : discard_cb;
+ cb = discard ? discard_cb : check_and_discard_cb;
info->oti_fn_index = info->oti_next_index = start;
do {
res = osc_page_gang_lookup(env, io, osc,
}
static int osc_lock_flush(struct osc_object *obj, pgoff_t start, pgoff_t end,
- enum cl_lock_mode mode, int discard)
+ enum cl_lock_mode mode, bool discard)
{
struct lu_env *env;
__u16 refcheck;
rc = 0;
}
- rc2 = osc_lock_discard_pages(env, obj, start, end, mode);
+ rc2 = osc_lock_discard_pages(env, obj, start, end, discard);
if (rc == 0 && rc2 < 0)
rc = rc2;
{
struct cl_object *obj = NULL;
int result = 0;
- int discard;
+ bool discard;
enum cl_lock_mode mode = CLM_READ;
ENTRY;
LASSERT(ols->ols_dlmlock == NULL);
result = osc_lock_flush(osc, descr->cld_start, descr->cld_end,
- descr->cld_mode, 0);
+ descr->cld_mode, false);
if (result)
CERROR("Pages for lockless lock %p were not purged(%d)\n",
ols, result);
osc_cache_truncate_start(env, osc, 0, NULL);
/* Discard all caching pages */
- osc_lock_discard_pages(env, osc, 0, CL_PAGE_EOF, CLM_WRITE);
+ osc_lock_discard_pages(env, osc, 0, CL_PAGE_EOF, true);
/* Clear ast data of dlm lock. Do this after discarding all pages */
osc_object_prune(env, osc2cl(osc));