-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * GPL HEADER END
- */
+// SPDX-License-Identifier: GPL-2.0
+
/*
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
- * Copyright (c) 2012, 2015, Intel Corporation.
+ * Copyright (c) 2012, 2017, Intel Corporation.
*/
+
/*
* This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lustre/ofd/ofd_dlm.c
*
* This file contains OBD Filter Device (OFD) LDLM-related code which is just
* intent handling for glimpse lock.
int error;
};
-int ofd_dlm_init(void)
-{
- ldlm_glimpse_work_kmem = kmem_cache_create("ldlm_glimpse_work_kmem",
- sizeof(struct ldlm_glimpse_work),
- 0, 0, NULL);
- if (ldlm_glimpse_work_kmem == NULL)
- return -ENOMEM;
- else
- return 0;
-}
-
-void ofd_dlm_exit(void)
-{
- if (ldlm_glimpse_work_kmem) {
- kmem_cache_destroy(ldlm_glimpse_work_kmem);
- ldlm_glimpse_work_kmem = NULL;
- }
-}
-
/**
* OFD interval callback.
*
* \param[in] n interval node
* \param[in,out] args intent arguments, gl work list for identified locks
*
- * \retval INTERVAL_ITER_STOP if the interval is lower than
+ * \retval true if the interval is lower than
* file size, caller stops execution
- * \retval INTERVAL_ITER_CONT if callback finished successfully
+ * \retval false if callback finished successfully
* and caller may continue execution
*/
-static enum interval_iter ofd_intent_cb(struct interval_node *n, void *args)
+static bool ofd_intent_cb(struct ldlm_lock *lock, struct ofd_intent_args *arg)
{
- struct ldlm_interval *node = (struct ldlm_interval *)n;
- struct ofd_intent_args *arg = args;
__u64 size = arg->size;
- struct ldlm_lock *victim_lock = NULL;
- struct ldlm_lock *lck;
struct ldlm_glimpse_work *gl_work = NULL;
- int rc = 0;
+ bool rc;
/* If the interval is lower than the current file size, just break. */
- if (interval_high(n) <= size)
- GOTO(out, rc = INTERVAL_ITER_STOP);
-
- /* Find the 'victim' lock from this interval */
- list_for_each_entry(lck, &node->li_group, l_sl_policy) {
-
- victim_lock = LDLM_LOCK_GET(lck);
-
- /* the same policy group - every lock has the
- * same extent, so needn't do it any more */
- break;
- }
-
- /* l_export can be null in race with eviction - In that case, we will
- * not find any locks in this interval */
- if (!victim_lock)
- GOTO(out, rc = INTERVAL_ITER_CONT);
+ if (lock->l_policy_data.l_extent.end <= size)
+ GOTO(out, rc = true);
/*
* This check is for lock taken in ofd_destroy_by_fid() that does
* Hence, if you are grabbing DLM locks on the server, always set
* non-NULL glimpse_ast (e.g., ldlm_request.c::ldlm_glimpse_ast()).
*/
- if (victim_lock->l_glimpse_ast == NULL) {
- LDLM_DEBUG(victim_lock, "no l_glimpse_ast");
+ if (lock->l_glimpse_ast == NULL) {
+ LDLM_DEBUG(lock, "no l_glimpse_ast");
arg->no_glimpse_ast = true;
- GOTO(out_release, rc = INTERVAL_ITER_STOP);
+ GOTO(out, rc = true);
}
/* If NO_EXPANSION is not set, this is an active lock, and we don't need
* to glimpse any further once we've glimpsed the client holding this
- * lock. So set us up to stop. See comment above this function. */
- if (!(victim_lock->l_flags & LDLM_FL_NO_EXPANSION))
- rc = INTERVAL_ITER_STOP;
+ * lock. So set us up to stop. See comment above this function.
+ */
+ if (!(lock->l_flags & LDLM_FL_NO_EXPANSION))
+ rc = true;
else
- rc = INTERVAL_ITER_CONT;
+ rc = false;
/* Check to see if we're already set up to send a glimpse to this
* client; if so, don't add this lock to the glimpse list - We need
* only glimpse each client once. (And if we know that client holds
* an active lock, we can stop glimpsing. So keep the rc set in the
- * check above.) */
+ * check above.)
+ */
list_for_each_entry(gl_work, &arg->gl_list, gl_list) {
- if (gl_work->gl_lock->l_export == victim_lock->l_export)
- GOTO(out_release, rc);
+ if (gl_work->gl_lock->l_export == lock->l_export)
+ GOTO(out, rc);
}
- if (!OBD_FAIL_CHECK(OBD_FAIL_OST_GL_WORK_ALLOC))
+ if (!CFS_FAIL_CHECK(OBD_FAIL_OST_GL_WORK_ALLOC))
OBD_SLAB_ALLOC_PTR_GFP(gl_work, ldlm_glimpse_work_kmem,
GFP_ATOMIC);
if (!gl_work) {
arg->error = -ENOMEM;
- GOTO(out_release, rc = INTERVAL_ITER_STOP);
+ GOTO(out, rc = true);
}
/* Populate the gl_work structure. */
- gl_work->gl_lock = victim_lock;
+ gl_work->gl_lock = ldlm_lock_get(lock);
list_add_tail(&gl_work->gl_list, &arg->gl_list);
/* There is actually no need for a glimpse descriptor when glimpsing
- * extent locks */
+ * extent locks
+ */
gl_work->gl_desc = NULL;
/* This tells ldlm_work_gl_ast_lock this was allocated from a slab and
- * must be freed in a slab-aware manner. */
+ * must be freed in a slab-aware manner.
+ */
gl_work->gl_flags = LDLM_GL_WORK_SLAB_ALLOCATED;
GOTO(out, rc);
-
-out_release:
- /* If the victim doesn't go on the glimpse list, we must release it */
- LDLM_LOCK_RELEASE(victim_lock);
-
out:
return rc;
}
* \retval ELDLM_LOCK_ABORTED in other cases except error
* \retval negative errno on error
*/
-int ofd_intent_policy(struct ldlm_namespace *ns, struct ldlm_lock **lockp,
- void *req_cookie, enum ldlm_mode mode, __u64 flags,
- void *data)
+
+int ofd_intent_policy(const struct lu_env *env, struct ldlm_namespace *ns,
+ struct ldlm_lock **lockp, void *req_cookie,
+ enum ldlm_mode mode, __u64 flags, void *data)
{
struct ptlrpc_request *req = req_cookie;
struct ldlm_lock *lock = *lockp;
struct ldlm_glimpse_work *pos, *tmp;
ENTRY;
+ /* update stats for intent in intent policy */
+ if (ptlrpc_req2svc(req)->srv_stats != NULL)
+ lprocfs_counter_incr(ptlrpc_req2svc(req)->srv_stats,
+ PTLRPC_LAST_CNTR + LDLM_GLIMPSE_ENQUEUE);
+
INIT_LIST_HEAD(&arg.gl_list);
arg.no_glimpse_ast = false;
arg.error = 0;
*/
if (flags & LDLM_FL_BLOCK_NOWAIT) {
- OBD_FAIL_TIMEOUT(OBD_FAIL_LDLM_AGL_DELAY, 5);
+ CFS_FAIL_TIMEOUT(OBD_FAIL_LDLM_AGL_DELAY, 5);
- if (OBD_FAIL_CHECK(OBD_FAIL_LDLM_AGL_NOLOCK))
+ if (CFS_FAIL_CHECK(OBD_FAIL_LDLM_AGL_NOLOCK))
RETURN(ELDLM_LOCK_ABORTED);
}
/* The lock met with no resistance; we're finished. */
if (rc == LDLM_ITER_CONTINUE) {
- if (OBD_FAIL_TIMEOUT(OBD_FAIL_LDLM_GLIMPSE, 2)) {
+ if (CFS_FAIL_TIMEOUT(OBD_FAIL_LDLM_GLIMPSE, 2)) {
ldlm_resource_unlink_lock(lock);
err = ELDLM_LOCK_ABORTED;
} else {
/* Check for PW locks beyond the size in the LVB, build the list
* of locks to glimpse (arg.gl_list) */
for (idx = 0; idx < LCK_MODE_NUM; idx++) {
+ struct ldlm_lock *lck;
+
tree = &res->lr_itree[idx];
if (tree->lit_mode == LCK_PR)
continue;
- interval_iterate_reverse(tree->lit_root, ofd_intent_cb, &arg);
+ for (lck = extent_last(tree);
+ lck;
+ lck = extent_prev(lck))
+ if (ofd_intent_cb(lck, &arg))
+ break;
+
if (arg.error) {
unlock_res(res);
GOTO(out, rc = arg.error);
* must clean up. Usually due to a race with unlink.*/
list_for_each_entry_safe(pos, tmp, &arg.gl_list, gl_list) {
list_del(&pos->gl_list);
- LDLM_LOCK_RELEASE(pos->gl_lock);
+ ldlm_lock_put(pos->gl_lock);
OBD_SLAB_FREE_PTR(pos, ldlm_glimpse_work_kmem);
}