Whamcloud - gitweb
Branch b1_8
authorzam <zam>
Fri, 19 Dec 2008 13:54:49 +0000 (13:54 +0000)
committerzam <zam>
Fri, 19 Dec 2008 13:54:49 +0000 (13:54 +0000)
b=17688
i=oleg.drokin
i=alexey.lyashkov

A lockless truncate fix, to prevent excessive lock pingpong on multistipe
files.

lustre/include/obd.h
lustre/include/obd_class.h
lustre/liblustre/super.c
lustre/llite/llite_lib.c
lustre/lov/lov_obd.c
lustre/osc/osc_request.c
lustre/tests/sanityN.sh

index 2a5022f..2bf2265 100644 (file)
@@ -1173,7 +1173,7 @@ struct obd_ops {
                          struct ptlrpc_request_set *rqset);
         int (*o_match)(struct obd_export *, struct lov_stripe_md *, __u32 type,
                        ldlm_policy_data_t *, __u32 mode, int *flags, void *data,
-                       struct lustre_handle *lockh);
+                       struct lustre_handle *lockh, int *n_matches);
         int (*o_change_cbdata)(struct obd_export *, struct lov_stripe_md *,
                                ldlm_iterator_t it, void *data);
         int (*o_cancel)(struct obd_export *, struct lov_stripe_md *md,
index c07578d..b0080aa 100644 (file)
@@ -1346,7 +1346,8 @@ static inline int obd_enqueue(struct obd_export *exp,
 
 static inline int obd_match(struct obd_export *exp, struct lov_stripe_md *ea,
                             __u32 type, ldlm_policy_data_t *policy, __u32 mode,
-                            int *flags, void *data, struct lustre_handle *lockh)
+                            int *flags, void *data, struct lustre_handle *lockh,
+                            int *n_matches)
 {
         int rc;
         ENTRY;
@@ -1355,7 +1356,7 @@ static inline int obd_match(struct obd_export *exp, struct lov_stripe_md *ea,
         EXP_COUNTER_INCREMENT(exp, match);
 
         rc = OBP(exp->exp_obd, match)(exp, ea, type, policy, mode, flags, data,
-                                      lockh);
+                                      lockh, n_matches);
         RETURN(rc);
 }
 
index 107cd02..faab12a 100644 (file)
@@ -750,7 +750,8 @@ int llu_setattr_raw(struct inode *inode, struct iattr *attr)
 
                 /* check that there are no matching locks */
                 LASSERT(obd_match(sbi->ll_osc_exp, lsm, LDLM_EXTENT, &policy,
-                                  LCK_PW, &flags, inode, &match_lockh) <= 0);
+                                  LCK_PW, &flags, inode, &match_lockh, NULL)
+                                  <= 0);
 
                 /* XXX when we fix the AST intents to pass the discard-range
                  * XXX extent, make ast_flags always LDLM_AST_DISCARD_DATA
index c440e86..4af1867 100644 (file)
@@ -1434,11 +1434,10 @@ static int ll_setattr_do_truncate(struct inode *inode, loff_t new_size)
         ldlm_policy_data_t policy = { .l_extent = {new_size,
                                                    OBD_OBJECT_EOF } };
         struct lustre_handle lockh = { 0 };
-        int local_lock = 0; /* 0 - no local lock;
+        int local_lock = 1; /* 0 - no local lock;
                              * 1 - lock taken by lock_extent;
                              * 2 - by obd_match*/
         int ast_flags;
-        int err;
         ENTRY;
 
         UNLOCK_INODE_MUTEX(inode);
@@ -1446,24 +1445,34 @@ static int ll_setattr_do_truncate(struct inode *inode, loff_t new_size)
 
         if (sbi->ll_lockless_truncate_enable &&
             (sbi->ll_lco.lco_flags & OBD_CONNECT_TRUNCLOCK)) {
+                int n_matches = 0;
+
                 ast_flags = LDLM_FL_BLOCK_GRANTED;
                 rc = obd_match(sbi->ll_osc_exp, lsm, LDLM_EXTENT,
-                               &policy, LCK_PW, &ast_flags, inode, &lockh);
+                               &policy, LCK_PW, &ast_flags, inode, &lockh,
+                               &n_matches);
                 if (rc > 0) {
                         local_lock = 2;
                         rc = 0;
-                } else if (rc == 0) {
-                        rc = ll_file_punch(inode, new_size, 1);
+                } else {
+                        /* clear the lock handle as it not cleared
+                         * by obd_match if no matched lock found */
+                        lockh.cookie = 0;
+                        if (rc == 0 && n_matches == 0) {
+                                local_lock = 0;
+                                rc = ll_file_punch(inode, new_size, 1);
+                        }
                 }
-        } else {
+        }
+        if (local_lock == 1) {
                 /* XXX when we fix the AST intents to pass the discard-range
                  * XXX extent, make ast_flags always LDLM_AST_DISCARD_DATA
                  * XXX here. */
                 ast_flags = (new_size == 0) ? LDLM_AST_DISCARD_DATA : 0;
                 rc = ll_extent_lock(NULL, inode, lsm, LCK_PW, &policy,
                                     &lockh, ast_flags);
-                if (likely(rc == 0))
-                        local_lock = 1;
+                if (unlikely(rc != 0))
+                        local_lock = 0;
         }
 
         LOCK_INODE_MUTEX(inode);
@@ -1484,10 +1493,11 @@ static int ll_setattr_do_truncate(struct inode *inode, loff_t new_size)
                 }
         }
         if (local_lock) {
-                if (local_lock == 2)
-                        err = obd_cancel(sbi->ll_osc_exp, lsm, LCK_PW, &lockh);
-                else
-                        err = ll_extent_unlock(NULL, inode, lsm, LCK_PW, &lockh);
+                int err;
+
+                err = (local_lock == 2) ?
+                        obd_cancel(sbi->ll_osc_exp, lsm, LCK_PW, &lockh):
+                        ll_extent_unlock(NULL, inode, lsm, LCK_PW, &lockh);
                 if (unlikely(err != 0)){
                         CERROR("extent unlock failed: err=%d,"
                                " unlock method =%d\n", err, local_lock);
index d6ec791..2d3ed19 100644 (file)
@@ -2141,7 +2141,8 @@ out:
 
 static int lov_match(struct obd_export *exp, struct lov_stripe_md *lsm,
                      __u32 type, ldlm_policy_data_t *policy, __u32 mode,
-                     int *flags, void *data, struct lustre_handle *lockh)
+                     int *flags, void *data, struct lustre_handle *lockh,
+                     int *n_matches)
 {
         struct lov_request_set *set;
         struct obd_info oinfo;
@@ -2174,7 +2175,8 @@ static int lov_match(struct obd_export *exp, struct lov_stripe_md *lsm,
 
                 rc = obd_match(lov->lov_tgts[req->rq_idx]->ltd_exp,
                                req->rq_oi.oi_md, type, &sub_policy,
-                               mode, &lov_flags, data, lov_lockhp);
+                               mode, &lov_flags, data, lov_lockhp,
+                               n_matches);
                 rc = lov_update_match_set(set, req, rc);
                 if (rc <= 0)
                         break;
index 6654809..0d2f3f4 100644 (file)
@@ -3222,7 +3222,8 @@ static int osc_enqueue(struct obd_export *exp, struct obd_info *oinfo,
 
 static int osc_match(struct obd_export *exp, struct lov_stripe_md *lsm,
                      __u32 type, ldlm_policy_data_t *policy, __u32 mode,
-                     int *flags, void *data, struct lustre_handle *lockh)
+                     int *flags, void *data, struct lustre_handle *lockh,
+                     int *n_matches)
 {
         struct ldlm_res_id res_id;
         struct obd_device *obd = exp->exp_obd;
@@ -3254,7 +3255,8 @@ static int osc_match(struct obd_export *exp, struct lov_stripe_md *lsm,
                         ldlm_lock_addref(lockh, LCK_PR);
                         ldlm_lock_decref(lockh, LCK_PW);
                 }
-                RETURN(rc);
+                if (n_matches != NULL)
+                        (*n_matches)++;
         }
 
         RETURN(rc);
index f8844e6..8243a5b 100644 (file)
@@ -616,10 +616,12 @@ enable_lockless_truncate() {
 test_32a() { # bug 11270
         local p="$TMP/sanityN-$TESTNAME.parameters"
         save_lustre_params $HOSTNAME llite.*.lockless_truncate > $p
+        rm -f $DIR1/$tfile
         cancel_lru_locks osc
-        clear_llite_stats
         enable_lockless_truncate 1
+        lfs setstripe -c -1 -s 1m $DIR1/$tfile
         dd if=/dev/zero of=$DIR1/$tfile count=10 bs=1M > /dev/null 2>&1
+        clear_llite_stats
 
         log "checking cached lockless truncate"
         $TRUNCATE $DIR1/$tfile 8000000