Whamcloud - gitweb
LU-4300 ldlm: ELC picks locks in a safer policy 75/9175/3
authorJinshan Xiong <jinshan.xiong@intel.com>
Fri, 7 Feb 2014 07:03:25 +0000 (23:03 -0800)
committerOleg Drokin <oleg.drokin@intel.com>
Sat, 1 Mar 2014 02:46:54 +0000 (02:46 +0000)
Change the policy of ELC to pick locks that have no dirty pages,
no page in writeback state, and no locked pages.

Signed-off-by: Jinshan Xiong <jinshan.xiong@intel.com>
Change-Id: Ie73130c4100e3b91c211635f6a72fe5dad994426
Reviewed-on: http://review.whamcloud.com/9175
Tested-by: Jenkins
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Bobi Jam <bobijam@gmail.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/include/lustre_dlm.h
lustre/ldlm/ldlm_request.c
lustre/mdc/mdc_request.c
lustre/osc/osc_lock.c
lustre/osc/osc_request.c

index 22d32f4..bd3e589 100644 (file)
@@ -279,7 +279,7 @@ typedef int (*ldlm_res_policy)(struct ldlm_namespace *, struct ldlm_lock **,
                               void *req_cookie, ldlm_mode_t mode, __u64 flags,
                               void *data);
 
-typedef int (*ldlm_cancel_for_recovery)(struct ldlm_lock *lock);
+typedef int (*ldlm_cancel_cbt)(struct ldlm_lock *lock);
 
 /**
  * LVB operations.
@@ -500,8 +500,11 @@ struct ldlm_namespace {
        /** Limit of parallel AST RPC count. */
        unsigned                ns_max_parallel_ast;
 
-       /** Callback to cancel locks before replaying it during recovery. */
-       ldlm_cancel_for_recovery ns_cancel_for_recovery;
+       /**
+        * Callback to check if a lock is good to be canceled by ELC or
+        * during recovery.
+        */
+       ldlm_cancel_cbt         ns_cancel;
 
        /** LDLM lock stats */
        struct lprocfs_stats    *ns_stats;
@@ -558,10 +561,10 @@ static inline int ns_connect_lru_resize(struct ldlm_namespace *ns)
 }
 
 static inline void ns_register_cancel(struct ldlm_namespace *ns,
-                                      ldlm_cancel_for_recovery arg)
+                                     ldlm_cancel_cbt arg)
 {
-        LASSERT(ns != NULL);
-        ns->ns_cancel_for_recovery = arg;
+       LASSERT(ns != NULL);
+       ns->ns_cancel = arg;
 }
 
 struct ldlm_lock;
index a90d452..59723ae 100644 (file)
@@ -1449,7 +1449,6 @@ static ldlm_policy_res_t ldlm_cancel_no_wait_policy(struct ldlm_namespace *ns,
                                                     int count)
 {
        ldlm_policy_res_t result = LDLM_POLICY_CANCEL_LOCK;
-       ldlm_cancel_for_recovery cb = ns->ns_cancel_for_recovery;
 
        /* don't check added & count since we want to process all locks
         * from unused list.
@@ -1458,7 +1457,7 @@ static ldlm_policy_res_t ldlm_cancel_no_wait_policy(struct ldlm_namespace *ns,
        switch (lock->l_resource->lr_type) {
                case LDLM_EXTENT:
                case LDLM_IBITS:
-                       if (cb && cb(lock))
+                       if (ns->ns_cancel != NULL && ns->ns_cancel(lock) != 0)
                                break;
                default:
                        result = LDLM_POLICY_SKIP_LOCK;
@@ -1485,20 +1484,20 @@ static ldlm_policy_res_t ldlm_cancel_lrur_policy(struct ldlm_namespace *ns,
                                                  int unused, int added,
                                                  int count)
 {
-        cfs_time_t cur = cfs_time_current();
-        struct ldlm_pool *pl = &ns->ns_pool;
-        __u64 slv, lvf, lv;
-        cfs_time_t la;
+       cfs_time_t cur = cfs_time_current();
+       struct ldlm_pool *pl = &ns->ns_pool;
+       __u64 slv, lvf, lv;
+       cfs_time_t la;
 
        /* Stop LRU processing when we reach past @count or have checked all
         * locks in LRU. */
-        if (count && added >= count)
-                return LDLM_POLICY_KEEP_LOCK;
+       if (count && added >= count)
+               return LDLM_POLICY_KEEP_LOCK;
 
-        slv = ldlm_pool_get_slv(pl);
-        lvf = ldlm_pool_get_lvf(pl);
-        la = cfs_duration_sec(cfs_time_sub(cur,
-                              lock->l_last_used));
+       slv = ldlm_pool_get_slv(pl);
+       lvf = ldlm_pool_get_lvf(pl);
+       la = cfs_duration_sec(cfs_time_sub(cur,
+                             lock->l_last_used));
        lv = lvf * la * unused;
 
        /* Inform pool about current CLV to see it via proc. */
@@ -1506,8 +1505,13 @@ static ldlm_policy_res_t ldlm_cancel_lrur_policy(struct ldlm_namespace *ns,
 
        /* Stop when SLV is not yet come from server or lv is smaller than
         * it is. */
-       return (slv == 0 || lv < slv) ?
-               LDLM_POLICY_KEEP_LOCK : LDLM_POLICY_CANCEL_LOCK;
+       if (slv == 0 || lv < slv)
+               return LDLM_POLICY_KEEP_LOCK;
+
+       if (ns->ns_cancel != NULL && ns->ns_cancel(lock) == 0)
+               return LDLM_POLICY_KEEP_LOCK;
+
+       return LDLM_POLICY_CANCEL_LOCK;
 }
 
 /**
@@ -1544,12 +1548,17 @@ static ldlm_policy_res_t ldlm_cancel_aged_policy(struct ldlm_namespace *ns,
                                                 int unused, int added,
                                                 int count)
 {
-       /* Stop LRU processing if young lock is found and we reach past count */
-        return ((added >= count) &&
-                cfs_time_before(cfs_time_current(),
-                                cfs_time_add(lock->l_last_used,
-                                             ns->ns_max_age))) ?
-                LDLM_POLICY_KEEP_LOCK : LDLM_POLICY_CANCEL_LOCK;
+        if (added >= count)
+               return LDLM_POLICY_KEEP_LOCK;
+
+       if (cfs_time_before(cfs_time_current(),
+                           cfs_time_add(lock->l_last_used, ns->ns_max_age)))
+                return LDLM_POLICY_KEEP_LOCK;
+
+        if (ns->ns_cancel != NULL && ns->ns_cancel(lock) == 0)
+                return LDLM_POLICY_KEEP_LOCK;
+
+       return LDLM_POLICY_CANCEL_LOCK;
 }
 
 /**
index 77c76c6..85fd541 100644 (file)
@@ -3050,18 +3050,18 @@ struct obd_uuid *mdc_get_uuid(struct obd_export *exp) {
  * recovery, non zero value will be return if the lock can be canceled,
  * or zero returned for not
  */
-static int mdc_cancel_for_recovery(struct ldlm_lock *lock)
+static int mdc_cancel_weight(struct ldlm_lock *lock)
 {
-        if (lock->l_resource->lr_type != LDLM_IBITS)
-                RETURN(0);
+       if (lock->l_resource->lr_type != LDLM_IBITS)
+               RETURN(0);
 
-        /* FIXME: if we ever get into a situation where there are too many
-         * opened files with open locks on a single node, then we really
-         * should replay these open locks to reget it */
-        if (lock->l_policy_data.l_inodebits.bits & MDS_INODELOCK_OPEN)
-                RETURN(0);
+       /* FIXME: if we ever get into a situation where there are too many
+        * opened files with open locks on a single node, then we really
+        * should replay these open locks to reget it */
+       if (lock->l_policy_data.l_inodebits.bits & MDS_INODELOCK_OPEN)
+               RETURN(0);
 
-        RETURN(1);
+       RETURN(1);
 }
 
 static int mdc_resource_inode_free(struct ldlm_resource *res)
@@ -3107,7 +3107,7 @@ static int mdc_setup(struct obd_device *obd, struct lustre_cfg *cfg)
        sptlrpc_lprocfs_cliobd_attach(obd);
        ptlrpc_lprocfs_register_obd(obd);
 
-        ns_register_cancel(obd->obd_namespace, mdc_cancel_for_recovery);
+       ns_register_cancel(obd->obd_namespace, mdc_cancel_weight);
 
        obd->obd_namespace->ns_lvbo = &inode_lvbo;
 
index 749b970..3422d54 100644 (file)
@@ -908,7 +908,11 @@ static int weigh_cb(const struct lu_env *env, struct cl_io *io,
 {
        struct cl_page *page = ops->ops_cl.cpl_page;
 
-       if (cl_page_is_vmlocked(env, page)) {
+       if (cl_page_is_vmlocked(env, page)
+#if defined(__KERNEL__)
+           || PageDirty(page->cp_vmpage) || PageWriteback(page->cp_vmpage)
+#endif
+          ) {
                (*(unsigned long *)cbdata)++;
                return CLP_GANG_ABORT;
        }
index 0884aaf..ed8b962 100644 (file)
@@ -2620,14 +2620,13 @@ int osc_enqueue_base(struct obd_export *exp, struct ldlm_res_id *res_id,
 
  no_match:
         if (intent) {
-                CFS_LIST_HEAD(cancels);
-                req = ptlrpc_request_alloc(class_exp2cliimp(exp),
-                                           &RQF_LDLM_ENQUEUE_LVB);
-                if (req == NULL)
-                        RETURN(-ENOMEM);
+               req = ptlrpc_request_alloc(class_exp2cliimp(exp),
+                                          &RQF_LDLM_ENQUEUE_LVB);
+               if (req == NULL)
+                       RETURN(-ENOMEM);
 
-                rc = ldlm_prep_enqueue_req(exp, req, &cancels, 0);
-                if (rc) {
+               rc = ptlrpc_request_pack(req, LUSTRE_DLM_VERSION, LDLM_ENQUEUE);
+               if (rc < 0) {
                         ptlrpc_request_free(req);
                         RETURN(rc);
                 }
@@ -3493,16 +3492,13 @@ static int osc_import_event(struct obd_device *obd,
  * \retval zero the lock can't be canceled
  * \retval other ok to cancel
  */
-static int osc_cancel_for_recovery(struct ldlm_lock *lock)
+static int osc_cancel_weight(struct ldlm_lock *lock)
 {
        /*
-        * Cancel all unused extent lock in granted mode LCK_PR or LCK_CR.
-        *
-        * XXX as a future improvement, we can also cancel unused write lock
-        * if it doesn't have dirty data and active mmaps.
+        * Cancel all unused and granted extent lock.
         */
        if (lock->l_resource->lr_type == LDLM_EXTENT &&
-           (lock->l_granted_mode == LCK_PR || lock->l_granted_mode == LCK_CR)&&
+           lock->l_granted_mode == lock->l_req_mode &&
            osc_ldlm_weigh_ast(lock) == 0)
                RETURN(1);
 
@@ -3569,7 +3565,7 @@ int osc_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
                                    ptlrpc_add_rqs_to_pool);
 
        CFS_INIT_LIST_HEAD(&cli->cl_grant_shrink_list);
-       ns_register_cancel(obd->obd_namespace, osc_cancel_for_recovery);
+       ns_register_cancel(obd->obd_namespace, osc_cancel_weight);
        RETURN(rc);
 
 out_ptlrpcd_work: