Whamcloud - gitweb
LU-3285 lvbo: pass lock as parameter to lvbo_update()
[fs/lustre-release.git] / lustre / ldlm / ldlm_lockd.c
index 807da6f..04e3c8e 100644 (file)
@@ -40,7 +40,7 @@
 #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"
@@ -53,7 +53,7 @@ static char *ldlm_cpts;
 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;
@@ -78,10 +78,6 @@ static inline unsigned int ldlm_get_rq_timeout(void)
         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;
 
@@ -123,7 +119,7 @@ struct ldlm_bl_work_item {
 /**
  * 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.
@@ -136,15 +132,20 @@ static spinlock_t waiting_locks_spinlock;   /* BH lock (timer) */
  *
  * 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)
 {
@@ -152,7 +153,7 @@ 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);
@@ -163,30 +164,30 @@ static inline int have_expired_locks(void)
  */
 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;
@@ -248,12 +249,12 @@ static int expired_lock_main(void *arg)
                        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);
 }
 
@@ -336,16 +337,15 @@ static void waiting_locks_callback(unsigned long unused)
                  * 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);
        }
 
         /*
@@ -639,9 +639,8 @@ static void ldlm_failed_ast(struct ldlm_lock *lock, int rc,
                /* 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);
 }
 
@@ -669,6 +668,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",
@@ -697,7 +713,7 @@ static int ldlm_handle_ast_error(struct ldlm_lock *lock,
                        /* 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);
@@ -732,11 +748,11 @@ static int ldlm_cb_interpret(const struct lu_env *env,
                } 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:
@@ -1674,7 +1690,9 @@ int ldlm_request_cancel(struct ptlrpc_request *req,
                         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;
                 }
@@ -1930,9 +1948,9 @@ static void ldlm_handle_gl_callback(struct ptlrpc_request *req,
         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);
@@ -2750,6 +2768,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);
@@ -3007,7 +3030,8 @@ static int ldlm_setup(void)
                },
        };
        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);
@@ -3050,7 +3074,8 @@ static int ldlm_setup(void)
                },
        };
        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);
@@ -3087,14 +3112,6 @@ static int ldlm_setup(void)
        }
 
 #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);
@@ -3102,8 +3119,8 @@ static int ldlm_setup(void)
                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();
@@ -3175,11 +3192,11 @@ static int ldlm_cleanup(void)
        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
 
@@ -3191,14 +3208,6 @@ static int ldlm_cleanup(void)
 
 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);