Whamcloud - gitweb
LU-7434 ptlrpc: lost bulk leads to a hang
[fs/lustre-release.git] / lustre / target / tgt_handler.c
index 52fc489..ccf77a8 100644 (file)
@@ -21,7 +21,7 @@
  * GPL HEADER END
  */
 /*
- * Copyright (c) 2011, 2014, Intel Corporation.
+ * Copyright (c) 2012, 2015, Intel Corporation.
  */
 /*
  * lustre/target/tgt_handler.c
@@ -619,8 +619,13 @@ static int process_req_last_xid(struct ptlrpc_request *req)
                DEBUG_REQ(D_ERROR, req, "Unexpected xid %llx vs. "
                          "last_xid %llx\n", req->rq_xid,
                          req->rq_export->exp_last_xid);
-#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 7, 93, 0)
-               /* This LBUG() can be triggered in following case:
+               /* Some request is allowed to be sent during replay,
+                * such as OUT update requests, FLD requests, so it
+                * is possible that replay requests has smaller XID
+                * than the exp_last_xid.
+                *
+                * Some non-replay requests may have smaller XID as
+                * well:
                 *
                 * - Client send a no_resend RPC, like statfs;
                 * - The RPC timedout (or some other error) on client,
@@ -628,15 +633,9 @@ static int process_req_last_xid(struct ptlrpc_request *req)
                 * - Client send some other request to bump the
                 *   exp_last_xid on server;
                 * - The former RPC got chance to be processed;
-                * - LBUG();
-                *
-                * Let's keep this for debug purpose for now, and it
-                * should be removed when release.
                 */
-               LBUG();
-#endif
-               req->rq_status = -EPROTO;
-               RETURN(ptlrpc_error(req));
+               if (!(lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY))
+                       RETURN(-EPROTO);
        }
 
        /* try to release in-memory reply data */
@@ -731,8 +730,11 @@ int tgt_request_handle(struct ptlrpc_request *req)
        } else if (obd->obd_recovery_data.trd_processing_task !=
                   current_pid()) {
                rc = process_req_last_xid(req);
-               if (rc)
+               if (rc) {
+                       req->rq_status = rc;
+                       rc = ptlrpc_error(req);
                        GOTO(out, rc);
+               }
        }
 
        request_fail_id = tgt->lut_request_fail_id;
@@ -1107,6 +1109,35 @@ int tgt_obd_log_cancel(struct tgt_session_info *tsi)
        return err_serious(-EOPNOTSUPP);
 }
 
+int tgt_send_buffer(struct tgt_session_info *tsi, struct lu_rdbuf *rdbuf)
+{
+       struct tgt_thread_info  *tti = tgt_th_info(tsi->tsi_env);
+       struct ptlrpc_request   *req = tgt_ses_req(tsi);
+       struct obd_export       *exp = req->rq_export;
+       struct ptlrpc_bulk_desc *desc;
+       struct l_wait_info      *lwi = &tti->tti_u.update.tti_wait_info;
+       int                      i;
+       int                      rc;
+
+       ENTRY;
+
+       desc = ptlrpc_prep_bulk_exp(req, rdbuf->rb_nbufs, 1,
+                                 PTLRPC_BULK_PUT_SOURCE | PTLRPC_BULK_BUF_KVEC,
+                                   MDS_BULK_PORTAL, &ptlrpc_bulk_kvec_ops);
+       if (desc == NULL)
+               RETURN(-ENOMEM);
+
+       for (i = 0; i < rdbuf->rb_nbufs; i++)
+               desc->bd_frag_ops->add_iov_frag(desc,
+                                       rdbuf->rb_bufs[i].lb_buf,
+                                       rdbuf->rb_bufs[i].lb_len);
+
+       rc = target_bulk_io(exp, desc, lwi);
+       ptlrpc_free_bulk(desc);
+       RETURN(rc);
+}
+EXPORT_SYMBOL(tgt_send_buffer);
+
 int tgt_sendpage(struct tgt_session_info *tsi, struct lu_rdpg *rdpg, int nob)
 {
        struct tgt_thread_info  *tti = tgt_th_info(tsi->tsi_env);
@@ -1254,6 +1285,7 @@ int tgt_sync(const struct lu_env *env, struct lu_target *tgt,
                   tgt->lut_obd->obd_last_committed) {
                rc = dt_object_sync(env, obj, start, end);
        }
+       atomic_inc(&tgt->lut_sync_count);
 
        RETURN(rc);
 }
@@ -1262,14 +1294,27 @@ EXPORT_SYMBOL(tgt_sync);
  * Unified target DLM handlers.
  */
 
-/* Ensure that data and metadata are synced to the disk when lock is cancelled
- * (if requested) */
+/**
+ * Unified target BAST
+ *
+ * Ensure data and metadata are synced to disk when lock is canceled if Sync on
+ * Cancel (SOC) is enabled. If it's extent lock, normally sync obj is enough,
+ * but if it's cross-MDT lock, because remote object version is not set, a
+ * filesystem sync is needed.
+ *
+ * \param lock server side lock
+ * \param desc lock desc
+ * \param data ldlm_cb_set_arg
+ * \param flag indicates whether this cancelling or blocking callback
+ * \retval     0 on success
+ * \retval     negative number on error
+ */
 static int tgt_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
                            void *data, int flag)
 {
        struct lu_env            env;
        struct lu_target        *tgt;
-       struct dt_object        *obj;
+       struct dt_object        *obj = NULL;
        struct lu_fid            fid;
        int                      rc = 0;
 
@@ -1284,10 +1329,12 @@ static int tgt_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
        }
 
        if (flag == LDLM_CB_CANCELING &&
-           (lock->l_granted_mode & (LCK_PW | LCK_GROUP)) &&
+           (lock->l_granted_mode & (LCK_EX | LCK_PW | LCK_GROUP)) &&
            (tgt->lut_sync_lock_cancel == ALWAYS_SYNC_ON_CANCEL ||
             (tgt->lut_sync_lock_cancel == BLOCKING_SYNC_ON_CANCEL &&
-             lock->l_flags & LDLM_FL_CBPENDING))) {
+             ldlm_is_cbpending(lock))) &&
+           ((exp_connect_flags(lock->l_export) & OBD_CONNECT_MDS_MDS) ||
+            lock->l_resource->lr_type == LDLM_EXTENT)) {
                __u64 start = 0;
                __u64 end = OBD_OBJECT_EOF;
 
@@ -1297,14 +1344,15 @@ static int tgt_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
 
                ost_fid_from_resid(&fid, &lock->l_resource->lr_name,
                                   tgt->lut_lsd.lsd_osd_index);
-               obj = dt_locate(&env, tgt->lut_bottom, &fid);
-               if (IS_ERR(obj))
-                       GOTO(err_env, rc = PTR_ERR(obj));
-
-               if (!dt_object_exists(obj))
-                       GOTO(err_put, rc = -ENOENT);
 
                if (lock->l_resource->lr_type == LDLM_EXTENT) {
+                       obj = dt_locate(&env, tgt->lut_bottom, &fid);
+                       if (IS_ERR(obj))
+                               GOTO(err_env, rc = PTR_ERR(obj));
+
+                       if (!dt_object_exists(obj))
+                               GOTO(err_put, rc = -ENOENT);
+
                        start = lock->l_policy_data.l_extent.start;
                        end = lock->l_policy_data.l_extent.end;
                }
@@ -1318,7 +1366,8 @@ static int tgt_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
                               lock->l_policy_data.l_extent.end, rc);
                }
 err_put:
-               lu_object_put(&env, &obj->do_lu);
+               if (obj != NULL)
+                       lu_object_put(&env, &obj->do_lu);
 err_env:
                lu_env_fini(&env);
        }
@@ -1518,11 +1567,15 @@ EXPORT_SYMBOL(tgt_register_lfsck_in_notify);
 
 static int (*tgt_lfsck_query)(const struct lu_env *env,
                              struct dt_device *key,
-                             struct lfsck_request *lr) = NULL;
+                             struct lfsck_request *req,
+                             struct lfsck_reply *rep,
+                             struct lfsck_query *que) = NULL;
 
 void tgt_register_lfsck_query(int (*query)(const struct lu_env *,
                                           struct dt_device *,
-                                          struct lfsck_request *))
+                                          struct lfsck_request *,
+                                          struct lfsck_reply *,
+                                          struct lfsck_query *))
 {
        tgt_lfsck_query = query;
 }
@@ -1561,8 +1614,8 @@ static int tgt_handle_lfsck_query(struct tgt_session_info *tsi)
        if (reply == NULL)
                RETURN(-ENOMEM);
 
-       rc = tgt_lfsck_query(tsi->tsi_env, tsi->tsi_tgt->lut_bottom, request);
-       reply->lr_status = rc;
+       rc = tgt_lfsck_query(tsi->tsi_env, tsi->tsi_tgt->lut_bottom,
+                            request, reply, NULL);
 
        RETURN(rc < 0 ? rc : 0);
 }
@@ -1902,6 +1955,9 @@ int tgt_brw_read(struct tgt_session_info *tsi)
                        break;
                }
        }
+       if (OBD_FAIL_CHECK(OBD_FAIL_OST_READ_SIZE) &&
+           nob != cfs_fail_val)
+               rc = -E2BIG;
 
        if (body->oa.o_valid & OBD_MD_FLCKSUM) {
                cksum_type_t cksum_type =
@@ -1921,7 +1977,8 @@ int tgt_brw_read(struct tgt_session_info *tsi)
        /* Check if client was evicted while we were doing i/o before touching
         * network */
        if (likely(rc == 0 &&
-                  !CFS_FAIL_PRECHECK(OBD_FAIL_PTLRPC_CLIENT_BULK_CB2))) {
+                  !CFS_FAIL_PRECHECK(OBD_FAIL_PTLRPC_CLIENT_BULK_CB2) &&
+                  !CFS_FAIL_CHECK(OBD_FAIL_PTLRPC_DROP_BULK))) {
                rc = target_bulk_io(exp, desc, &lwi);
                no_reply = rc != 0;
        }