#include <linux/kthread.h>
#include <linux/list.h>
#include <libcfs/libcfs.h>
-#include <lustre/lustre_errno.h>
+#include <lustre_errno.h>
#include <lustre_dlm.h>
#include <obd_class.h>
#include "ldlm_internal.h"
module_param(ldlm_cpts, charp, 0444);
MODULE_PARM_DESC(ldlm_cpts, "CPU partitions ldlm threads should run on");
-static struct mutex ldlm_ref_mutex;
+static DEFINE_MUTEX(ldlm_ref_mutex);
static int ldlm_refcount;
struct kobject *ldlm_kobj;
return timeout < 1 ? 1 : timeout;
}
-#define ELT_STOPPED 0
-#define ELT_READY 1
-#define ELT_TERMINATE 2
-
struct ldlm_bl_pool {
spinlock_t blp_lock;
/**
* Protects both waiting_locks_list and expired_lock_thread.
*/
-static spinlock_t waiting_locks_spinlock; /* BH lock (timer) */
+static DEFINE_SPINLOCK(waiting_locks_spinlock); /* BH lock (timer) */
/**
* List for contended locks.
*
* All access to it should be under waiting_locks_spinlock.
*/
-static struct list_head waiting_locks_list;
-static struct timer_list waiting_locks_timer;
+static LIST_HEAD(waiting_locks_list);
+static void waiting_locks_callback(unsigned long unused);
+static DEFINE_TIMER(waiting_locks_timer, waiting_locks_callback, 0, 0);
+
+enum elt_state {
+ ELT_STOPPED,
+ ELT_READY,
+ ELT_TERMINATE,
+};
-static struct expired_lock_thread {
- wait_queue_head_t elt_waitq;
- int elt_state;
- int elt_dump;
- struct list_head elt_expired_locks;
-} expired_lock_thread;
+static DECLARE_WAIT_QUEUE_HEAD(expired_lock_wait_queue);
+static enum elt_state expired_lock_thread_state = ELT_STOPPED;
+static int expired_lock_dump;
+static LIST_HEAD(expired_lock_list);
static inline int have_expired_locks(void)
{
ENTRY;
spin_lock_bh(&waiting_locks_spinlock);
- need_to_run = !list_empty(&expired_lock_thread.elt_expired_locks);
+ need_to_run = !list_empty(&expired_lock_list);
spin_unlock_bh(&waiting_locks_spinlock);
RETURN(need_to_run);
*/
static int expired_lock_main(void *arg)
{
- struct list_head *expired = &expired_lock_thread.elt_expired_locks;
+ struct list_head *expired = &expired_lock_list;
struct l_wait_info lwi = { 0 };
int do_dump;
ENTRY;
- expired_lock_thread.elt_state = ELT_READY;
- wake_up(&expired_lock_thread.elt_waitq);
+ expired_lock_thread_state = ELT_READY;
+ wake_up(&expired_lock_wait_queue);
while (1) {
- l_wait_event(expired_lock_thread.elt_waitq,
+ l_wait_event(expired_lock_wait_queue,
have_expired_locks() ||
- expired_lock_thread.elt_state == ELT_TERMINATE,
+ expired_lock_thread_state == ELT_TERMINATE,
&lwi);
spin_lock_bh(&waiting_locks_spinlock);
- if (expired_lock_thread.elt_dump) {
+ if (expired_lock_dump) {
spin_unlock_bh(&waiting_locks_spinlock);
/* from waiting_locks_callback, but not in timer */
libcfs_debug_dumplog();
spin_lock_bh(&waiting_locks_spinlock);
- expired_lock_thread.elt_dump = 0;
+ expired_lock_dump = 0;
}
do_dump = 0;
libcfs_debug_dumplog();
}
- if (expired_lock_thread.elt_state == ELT_TERMINATE)
+ if (expired_lock_thread_state == ELT_TERMINATE)
break;
}
- expired_lock_thread.elt_state = ELT_STOPPED;
- wake_up(&expired_lock_thread.elt_waitq);
+ expired_lock_thread_state = ELT_STOPPED;
+ wake_up(&expired_lock_wait_queue);
RETURN(0);
}
* the waiting_locks_list and ldlm_add_waiting_lock()
* already grabbed a ref */
list_del(&lock->l_pending_chain);
- list_add(&lock->l_pending_chain,
- &expired_lock_thread.elt_expired_locks);
+ list_add(&lock->l_pending_chain, &expired_lock_list);
need_dump = 1;
}
- if (!list_empty(&expired_lock_thread.elt_expired_locks)) {
+ if (!list_empty(&expired_lock_list)) {
if (obd_dump_on_timeout && need_dump)
- expired_lock_thread.elt_dump = __LINE__;
+ expired_lock_dump = __LINE__;
- wake_up(&expired_lock_thread.elt_waitq);
+ wake_up(&expired_lock_wait_queue);
}
/*
/* the lock was not in any list, grab an extra ref before adding
* the lock to the expired list */
LDLM_LOCK_GET(lock);
- list_add(&lock->l_pending_chain,
- &expired_lock_thread.elt_expired_locks);
- wake_up(&expired_lock_thread.elt_waitq);
+ list_add(&lock->l_pending_chain, &expired_lock_list);
+ wake_up(&expired_lock_wait_queue);
spin_unlock_bh(&waiting_locks_spinlock);
}
libcfs_nid2str(peer.nid));
ldlm_lock_cancel(lock);
rc = -ERESTART;
+ } else if (rc == -ENODEV || rc == -ESHUTDOWN ||
+ (rc == -EIO &&
+ req->rq_import->imp_state == LUSTRE_IMP_CLOSED)) {
+ /* Upon umount process the AST fails because cannot be
+ * sent. This shouldn't lead to the client eviction.
+ * -ENODEV error is returned by ptl_send_rpc() for
+ * new request in such import.
+ * -SHUTDOWN is returned by ptlrpc_import_delay_req()
+ * if imp_invalid is set or obd_no_recov.
+ * Meanwhile there is also check for LUSTRE_IMP_CLOSED
+ * in ptlrpc_import_delay_req() as well with -EIO code.
+ * In all such cases errors are ignored.
+ */
+ LDLM_DEBUG(lock, "%s AST can't be sent due to a server"
+ " %s failure or umount process: rc = %d\n",
+ ast_type,
+ req->rq_import->imp_obd->obd_name, rc);
} else {
LDLM_ERROR(lock,
"client (nid %s) %s %s AST (req@%p x%llu status %d rc %d), evict it",
/* update lvbo to return proper attributes.
* see bug 23174 */
ldlm_resource_getref(res);
- ldlm_res_lvbo_update(res, NULL, 1);
+ ldlm_lvbo_update(res, lock, NULL, 1);
ldlm_resource_putref(res);
}
ldlm_lock_cancel(lock);
} else if (rc == -ELDLM_NO_LOCK_DATA) {
LDLM_DEBUG(lock, "lost race - client has a lock but no "
"inode");
- ldlm_res_lvbo_update(lock->l_resource, NULL, 1);
+ ldlm_lvbo_update(lock->l_resource, lock, NULL, 1);
} else if (rc != 0) {
rc = ldlm_handle_ast_error(lock, req, rc, "glimpse");
} else {
- rc = ldlm_res_lvbo_update(lock->l_resource, req, 1);
+ rc = ldlm_lvbo_update(lock->l_resource, lock, req, 1);
}
break;
case LDLM_BL_CALLBACK:
if (res != NULL) {
ldlm_resource_getref(res);
LDLM_RESOURCE_ADDREF(res);
- ldlm_res_lvbo_update(res, NULL, 1);
+
+ if (!ldlm_is_discard_data(lock))
+ ldlm_lvbo_update(res, lock, NULL, 1);
}
pres = res;
}
lock_res_and_lock(lock);
if (lock->l_granted_mode == LCK_PW &&
!lock->l_readers && !lock->l_writers &&
- cfs_time_after(cfs_time_current(),
- cfs_time_add(lock->l_last_used,
- cfs_time_seconds(10)))) {
+ ktime_after(ktime_get(),
+ ktime_add(lock->l_last_used,
+ ktime_set(10, 0)))) {
unlock_res_and_lock(lock);
if (ldlm_bl_to_thread_lock(ns, NULL, lock))
ldlm_handle_bl_callback(ns, NULL, lock);
if (rc == LDLM_ITER_STOP)
break;
+
+ /* If there are many namespaces, we will not sleep waiting for
+ * work, and must do a cond_resched to avoid holding the CPU
+ * for too long */
+ cond_resched();
}
atomic_dec(&blp->blp_num_threads);
},
};
ldlm_state->ldlm_cb_service = \
- ptlrpc_register_service(&conf, ldlm_svc_proc_dir);
+ ptlrpc_register_service(&conf, ldlm_svc_kset,
+ ldlm_svc_proc_dir);
if (IS_ERR(ldlm_state->ldlm_cb_service)) {
CERROR("failed to start service\n");
rc = PTR_ERR(ldlm_state->ldlm_cb_service);
},
};
ldlm_state->ldlm_cancel_service = \
- ptlrpc_register_service(&conf, ldlm_svc_proc_dir);
+ ptlrpc_register_service(&conf, ldlm_svc_kset,
+ ldlm_svc_proc_dir);
if (IS_ERR(ldlm_state->ldlm_cancel_service)) {
CERROR("failed to start service\n");
rc = PTR_ERR(ldlm_state->ldlm_cancel_service);
}
#ifdef HAVE_SERVER_SUPPORT
- INIT_LIST_HEAD(&expired_lock_thread.elt_expired_locks);
- expired_lock_thread.elt_state = ELT_STOPPED;
- init_waitqueue_head(&expired_lock_thread.elt_waitq);
-
- INIT_LIST_HEAD(&waiting_locks_list);
- spin_lock_init(&waiting_locks_spinlock);
- setup_timer(&waiting_locks_timer, waiting_locks_callback, 0);
-
task = kthread_run(expired_lock_main, NULL, "ldlm_elt");
if (IS_ERR(task)) {
rc = PTR_ERR(task);
GOTO(out, rc);
}
- wait_event(expired_lock_thread.elt_waitq,
- expired_lock_thread.elt_state == ELT_READY);
+ wait_event(expired_lock_wait_queue,
+ expired_lock_thread_state == ELT_READY);
#endif /* HAVE_SERVER_SUPPORT */
rc = ldlm_pools_init();
ldlm_proc_cleanup();
#ifdef HAVE_SERVER_SUPPORT
- if (expired_lock_thread.elt_state != ELT_STOPPED) {
- expired_lock_thread.elt_state = ELT_TERMINATE;
- wake_up(&expired_lock_thread.elt_waitq);
- wait_event(expired_lock_thread.elt_waitq,
- expired_lock_thread.elt_state == ELT_STOPPED);
+ if (expired_lock_thread_state != ELT_STOPPED) {
+ expired_lock_thread_state = ELT_TERMINATE;
+ wake_up(&expired_lock_wait_queue);
+ wait_event(expired_lock_wait_queue,
+ expired_lock_thread_state == ELT_STOPPED);
}
#endif
int ldlm_init(void)
{
- mutex_init(&ldlm_ref_mutex);
- mutex_init(ldlm_namespace_lock(LDLM_NAMESPACE_SERVER));
- mutex_init(ldlm_namespace_lock(LDLM_NAMESPACE_CLIENT));
-
- INIT_LIST_HEAD(&ldlm_srv_namespace_list);
- INIT_LIST_HEAD(&ldlm_cli_active_namespace_list);
- INIT_LIST_HEAD(&ldlm_cli_inactive_namespace_list);
-
ldlm_resource_slab = kmem_cache_create("ldlm_resources",
sizeof(struct ldlm_resource), 0,
SLAB_HWCACHE_ALIGN, NULL);