]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
client: stop retrying the request when exceeding 256 times 45728/head
authorXiubo Li <xiubli@redhat.com>
Thu, 31 Mar 2022 07:16:49 +0000 (15:16 +0800)
committerXiubo Li <xiubli@redhat.com>
Mon, 23 May 2022 06:05:25 +0000 (14:05 +0800)
The type of 'retry_attempt' in 'MetaRequest' is 'int', while in
'ceph_mds_request_head' the type of 'num_retry' is '__u8'. So in
case the request retries exceeding 256 times, the MDS will receive
a incorrect retry seq.

In this case it's ususally a bug in MDS and continue retrying the
request makes no sense. For now let's limit it to 256. In future
this could be fixed in ceph code, so avoid using the hardcode here.

Fixes: https://tracker.ceph.com/issues/55144
Signed-off-by: Xiubo Li <xiubli@redhat.com>
src/client/Client.cc

index 7afb41c9e2ad9281b6828160d3ad53f92d211dde..c35a53521e8130bf4dc09fe0ddc2e233b15734d5 100644 (file)
@@ -2457,6 +2457,9 @@ void Client::send_request(MetaRequest *request, MetaSession *session,
   ldout(cct, 10) << __func__ << " rebuilding request " << request->get_tid()
                 << " for mds." << mds << dendl;
   auto r = build_client_request(request);
+  if (!r)
+    return;
+
   if (request->dentry()) {
     r->set_dentry_wanted();
   }
@@ -2500,6 +2503,28 @@ void Client::send_request(MetaRequest *request, MetaSession *session,
 
 ref_t<MClientRequest> Client::build_client_request(MetaRequest *request)
 {
+  /*
+   * The type of 'retry_attempt' in 'MetaRequest' is 'int',
+   * while in 'ceph_mds_request_head' the type of 'num_retry'
+   * is '__u8'. So in case the request retries exceeding 256
+   * times, the MDS will receive a incorrect retry seq.
+   *
+   * In this case it's ususally a bug in MDS and continue
+   * retrying the request makes no sense.
+   *
+   * In future this could be fixed in ceph code, so avoid
+   * using the hardcode here.
+   */
+  int max_retry = sizeof(((struct ceph_mds_request_head*)0)->num_retry);
+  max_retry = 1 << (max_retry * CHAR_BIT);
+  if (request->retry_attempt >= max_retry) {
+    request->abort(-EMULTIHOP);
+    request->caller_cond->notify_all();
+    ldout(cct, 1) << __func__ << " request tid " << request->tid
+                  << " seq overflow" << ", abort it" << dendl;
+    return nullptr;
+  }
+
   auto req = make_message<MClientRequest>(request->get_op());
   req->set_tid(request->tid);
   req->set_stamp(request->op_stamp);