Whamcloud - gitweb
LU-8307 ldlm: cond_resched in ldlm_bl_thread_main
[fs/lustre-release.git] / lustre / ldlm / ldlm_lockd.c
index c2a420d..b29b721 100644 (file)
@@ -23,7 +23,7 @@
  * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
- * Copyright (c) 2010, 2015, Intel Corporation.
+ * Copyright (c) 2010, 2016, Intel Corporation.
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
@@ -40,6 +40,7 @@
 #include <linux/kthread.h>
 #include <linux/list.h>
 #include <libcfs/libcfs.h>
+#include <lustre/lustre_errno.h>
 #include <lustre_dlm.h>
 #include <obd_class.h>
 #include "ldlm_internal.h"
@@ -55,10 +56,9 @@ MODULE_PARM_DESC(ldlm_cpts, "CPU partitions ldlm threads should run on");
 static struct mutex    ldlm_ref_mutex;
 static int ldlm_refcount;
 
-struct ldlm_cb_async_args {
-        struct ldlm_cb_set_arg *ca_set_arg;
-        struct ldlm_lock       *ca_lock;
-};
+struct kobject *ldlm_kobj;
+struct kset *ldlm_ns_kset;
+struct kset *ldlm_svc_kset;
 
 /* LDLM state */
 
@@ -180,15 +180,10 @@ static int expired_lock_main(void *arg)
 
                spin_lock_bh(&waiting_locks_spinlock);
                if (expired_lock_thread.elt_dump) {
-                       struct libcfs_debug_msg_data msgdata = {
-                               .msg_file = __FILE__,
-                               .msg_fn = "waiting_locks_callback",
-                               .msg_line = expired_lock_thread.elt_dump };
                        spin_unlock_bh(&waiting_locks_spinlock);
 
                        /* from waiting_locks_callback, but not in timer */
                        libcfs_debug_dumplog();
-                       libcfs_run_lbug_upcall(&msgdata);
 
                        spin_lock_bh(&waiting_locks_spinlock);
                        expired_lock_thread.elt_dump = 0;
@@ -331,9 +326,9 @@ static void waiting_locks_callback(unsigned long unused)
                         continue;
                 }
                 ldlm_lock_to_ns(lock)->ns_timeouts++;
-                LDLM_ERROR(lock, "lock callback timer expired after %lds: "
+               LDLM_ERROR(lock, "lock callback timer expired after %llds: "
                            "evicting client at %s ",
-                           cfs_time_current_sec() - lock->l_last_activity,
+                          ktime_get_real_seconds() - lock->l_last_activity,
                            libcfs_nid2str(
                                    lock->l_export->exp_connection->c_peer.nid));
 
@@ -362,7 +357,7 @@ static void waiting_locks_callback(unsigned long unused)
                lock = list_entry(waiting_locks_list.next, struct ldlm_lock,
                                       l_pending_chain);
                 timeout_rounded = (cfs_time_t)round_timeout(lock->l_callback_timeout);
-                cfs_timer_arm(&waiting_locks_timer, timeout_rounded);
+               mod_timer(&waiting_locks_timer, timeout_rounded);
         }
        spin_unlock_bh(&waiting_locks_spinlock);
 }
@@ -397,10 +392,9 @@ static int __ldlm_add_waiting_lock(struct ldlm_lock *lock, int seconds)
 
         timeout_rounded = round_timeout(lock->l_callback_timeout);
 
-        if (cfs_time_before(timeout_rounded,
-                            cfs_timer_deadline(&waiting_locks_timer)) ||
-            !cfs_timer_is_armed(&waiting_locks_timer)) {
-                cfs_timer_arm(&waiting_locks_timer, timeout_rounded);
+       if (cfs_time_before(timeout_rounded, waiting_locks_timer.expires) ||
+           !timer_pending(&waiting_locks_timer)) {
+               mod_timer(&waiting_locks_timer, timeout_rounded);
         }
         /* if the new lock has a shorter timeout than something earlier on
            the list, we'll wait the longer amount of time; no big deal. */
@@ -465,7 +459,7 @@ static int ldlm_add_waiting_lock(struct ldlm_lock *lock)
        }
 
        ldlm_set_waited(lock);
-       lock->l_last_activity = cfs_time_current_sec();
+       lock->l_last_activity = ktime_get_real_seconds();
        ret = __ldlm_add_waiting_lock(lock, timeout);
        if (ret) {
                /* grab ref on the lock if it has been added to the
@@ -504,13 +498,13 @@ static int __ldlm_del_waiting_lock(struct ldlm_lock *lock)
                 /* Removing the head of the list, adjust timer. */
                 if (list_next == &waiting_locks_list) {
                         /* No more, just cancel. */
-                        cfs_timer_disarm(&waiting_locks_timer);
+                       del_timer(&waiting_locks_timer);
                 } else {
                         struct ldlm_lock *next;
                        next = list_entry(list_next, struct ldlm_lock,
                                               l_pending_chain);
-                        cfs_timer_arm(&waiting_locks_timer,
-                                      round_timeout(next->l_callback_timeout));
+                       mod_timer(&waiting_locks_timer,
+                                 round_timeout(next->l_callback_timeout));
                 }
         }
        list_del_init(&lock->l_pending_chain);
@@ -658,7 +652,7 @@ static int ldlm_handle_ast_error(struct ldlm_lock *lock,
                                 struct ptlrpc_request *req, int rc,
                                 const char *ast_type)
 {
-       lnet_process_id_t peer = req->rq_import->imp_connection->c_peer;
+       struct lnet_process_id peer = req->rq_import->imp_connection->c_peer;
 
        if (!req->rq_replied || (rc && rc != -EINVAL)) {
                if (lock->l_export && lock->l_export->exp_libclient) {
@@ -675,6 +669,23 @@ static int ldlm_handle_ast_error(struct ldlm_lock *lock,
                                   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",
@@ -733,7 +744,9 @@ static int ldlm_cb_interpret(const struct lu_env *env,
                 * - Glimpse callback of remote lock might return
                 *   -ELDLM_NO_LOCK_DATA when inode is cleared. LU-274
                 */
-               if (rc == -ELDLM_NO_LOCK_DATA) {
+               if (unlikely(arg->gl_interpret_reply)) {
+                       rc = arg->gl_interpret_reply(env, req, data, rc);
+               } 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);
@@ -927,7 +940,7 @@ int ldlm_server_blocking_ast(struct ldlm_lock *lock,
         if (AT_OFF)
                 req->rq_timeout = ldlm_get_rq_timeout();
 
-       lock->l_last_activity = cfs_time_current_sec();
+       lock->l_last_activity = ktime_get_real_seconds();
 
         if (lock->l_export && lock->l_export->exp_nid_stats &&
             lock->l_export->exp_nid_stats->nid_ldlm_stats)
@@ -1017,7 +1030,7 @@ int ldlm_server_completion_ast(struct ldlm_lock *lock, __u64 flags, void *data)
                }
         }
 
-       lock->l_last_activity = cfs_time_current_sec();
+       lock->l_last_activity = ktime_get_real_seconds();
 
        LDLM_DEBUG(lock, "server preparing completion AST");
 
@@ -1127,7 +1140,7 @@ int ldlm_server_glimpse_ast(struct ldlm_lock *lock, void *data)
         if (AT_OFF)
                 req->rq_timeout = ldlm_get_rq_timeout();
 
-       lock->l_last_activity = cfs_time_current_sec();
+       lock->l_last_activity = ktime_get_real_seconds();
 
        req->rq_interpret_reply = ldlm_cb_interpret;
 
@@ -1684,10 +1697,10 @@ int ldlm_request_cancel(struct ptlrpc_request *req,
                 }
 
                if ((flags & LATF_STATS) && ldlm_is_ast_sent(lock)) {
-                       long delay = cfs_time_sub(cfs_time_current_sec(),
-                                                 lock->l_last_activity);
-                       LDLM_DEBUG(lock, "server cancels blocked lock after "
-                                  CFS_DURATION_T"s", delay);
+                       time64_t delay = ktime_get_real_seconds() -
+                                        lock->l_last_activity;
+                       LDLM_DEBUG(lock, "server cancels blocked lock after %llds",
+                                  (s64)delay);
                        at_measured(&lock->l_export->exp_bl_lock_at, delay);
                }
                 ldlm_lock_cancel(lock);
@@ -2754,6 +2767,11 @@ static int ldlm_bl_thread_main(void *arg)
 
                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);
@@ -2906,6 +2924,40 @@ void ldlm_destroy_export(struct obd_export *exp)
 }
 EXPORT_SYMBOL(ldlm_destroy_export);
 
+static ssize_t cancel_unused_locks_before_replay_show(struct kobject *kobj,
+                                                     struct attribute *attr,
+                                                     char *buf)
+{
+       return sprintf(buf, "%d\n", ldlm_cancel_unused_locks_before_replay);
+}
+
+static ssize_t cancel_unused_locks_before_replay_store(struct kobject *kobj,
+                                                      struct attribute *attr,
+                                                      const char *buffer,
+                                                      size_t count)
+{
+       int rc;
+       unsigned long val;
+
+       rc = kstrtoul(buffer, 10, &val);
+       if (rc)
+               return rc;
+
+       ldlm_cancel_unused_locks_before_replay = val;
+
+       return count;
+}
+LUSTRE_RW_ATTR(cancel_unused_locks_before_replay);
+
+static struct attribute *ldlm_attrs[] = {
+       &lustre_attr_cancel_unused_locks_before_replay.attr,
+       NULL,
+};
+
+static struct attribute_group ldlm_attr_group = {
+       .attrs = ldlm_attrs,
+};
+
 static int ldlm_setup(void)
 {
        static struct ptlrpc_service_conf       conf;
@@ -2925,9 +2977,25 @@ static int ldlm_setup(void)
         if (ldlm_state == NULL)
                 RETURN(-ENOMEM);
 
+       ldlm_kobj = kobject_create_and_add("ldlm", lustre_kobj);
+       if (!ldlm_kobj)
+               GOTO(out, -ENOMEM);
+
+       rc = sysfs_create_group(ldlm_kobj, &ldlm_attr_group);
+       if (rc)
+               GOTO(out, rc);
+
+       ldlm_ns_kset = kset_create_and_add("namespaces", NULL, ldlm_kobj);
+       if (!ldlm_ns_kset)
+               GOTO(out, -ENOMEM);
+
+       ldlm_svc_kset = kset_create_and_add("services", NULL, ldlm_kobj);
+       if (!ldlm_svc_kset)
+               GOTO(out, -ENOMEM);
+
 #ifdef CONFIG_PROC_FS
-        rc = ldlm_proc_setup();
-        if (rc != 0)
+       rc = ldlm_proc_setup();
+       if (rc != 0)
                GOTO(out, rc);
 #endif /* CONFIG_PROC_FS */
 
@@ -3047,7 +3115,7 @@ static int ldlm_setup(void)
 
        INIT_LIST_HEAD(&waiting_locks_list);
        spin_lock_init(&waiting_locks_spinlock);
-       cfs_timer_init(&waiting_locks_timer, waiting_locks_callback, NULL);
+       setup_timer(&waiting_locks_timer, waiting_locks_callback, 0);
 
        task = kthread_run(expired_lock_main, NULL, "ldlm_elt");
        if (IS_ERR(task)) {
@@ -3119,6 +3187,13 @@ static int ldlm_cleanup(void)
                ptlrpc_unregister_service(ldlm_state->ldlm_cancel_service);
 #endif
 
+       if (ldlm_ns_kset)
+               kset_unregister(ldlm_ns_kset);
+       if (ldlm_svc_kset)
+               kset_unregister(ldlm_svc_kset);
+       if (ldlm_kobj)
+               kobject_put(ldlm_kobj);
+
        ldlm_proc_cleanup();
 
 #ifdef HAVE_SERVER_SUPPORT