]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
fix infinite loop in rest api for log list
authorXie Rui <jerry.xr86@gmail.com>
Thu, 22 Jun 2017 09:12:30 +0000 (17:12 +0800)
committerCasey Bodley <cbodley@redhat.com>
Wed, 28 Jun 2017 14:18:42 +0000 (10:18 -0400)
as max_entries_str is empty, it will be infinite loop when log is more than MAX_ENTRIES(1000) from marker.
and max_entries maybe overflow if use it to count the left entries.

Fixes: http://tracker.ceph.com/issues/20386
Signed-off-by: xierui <jerry.xr86@gmail.com>
src/rgw/rgw_metadata.cc
src/rgw/rgw_rest_log.cc

index 5a286b4aeb67509c714342c8d0859753ce72e293..28a2b94c7a0a85518a99f5985cc3734c0daac1d1 100644 (file)
@@ -149,13 +149,18 @@ int RGWMetadataLog::list_entries(void *handle,
     *truncated = false;
     return 0;
   }
-
+  
+  list<cls_log_entry> log_entries;
+  
   int ret = store->time_log_list(ctx->cur_oid, ctx->from_time, ctx->end_time,
-                                max_entries, entries, ctx->marker,
+                                max_entries, log_entries, ctx->marker,
                                 last_marker, truncated);
   if ((ret < 0) && (ret != -ENOENT))
     return ret;
 
+  ctx->marker = *last_marker;
+  entries.splice(entries.end(), log_entries);
+  
   if (ret == -ENOENT)
     *truncated = false;
 
index 9220917c99a63f2395715ebb65d91cad75f85363..f932807cd02742645b58c20141a2fdb66a94c4f2 100644 (file)
@@ -54,7 +54,8 @@ void RGWOp_MDLog_List::execute() {
              ut_et;
   void    *handle;
   unsigned shard_id, max_entries = LOG_CLASS_LIST_MAX_ENTRIES;
-
+  unsigned left_cnt;
+  
   shard_id = (unsigned)strict_strtol(shard.c_str(), 10, &err);
   if (!err.empty()) {
     dout(5) << "Error parsing shard_id " << shard << dendl;
@@ -94,16 +95,16 @@ void RGWOp_MDLog_List::execute() {
   RGWMetadataLog meta_log{s->cct, store, period};
 
   meta_log.init_list_entries(shard_id, ut_st, ut_et, marker, &handle);
-
+  left_cnt = max_entries;
+  
   do {
-    http_ret = meta_log.list_entries(handle, max_entries, entries,
+    http_ret = meta_log.list_entries(handle, left_cnt, entries,
                                     &last_marker, &truncated);
     if (http_ret < 0) 
       break;
 
-    if (!max_entries_str.empty()) 
-      max_entries -= entries.size();
-  } while (truncated && (max_entries > 0));
+    left_cnt =  max_entries - entries.size();
+  } while (truncated && (left_cnt > 0));
 
   meta_log.complete_list_entries(handle);
 }
@@ -577,6 +578,7 @@ void RGWOp_DATALog_List::execute() {
   real_time  ut_st, 
              ut_et;
   unsigned shard_id, max_entries = LOG_CLASS_LIST_MAX_ENTRIES;
+  unsigned left_cnt;
 
   s->info.args.get_bool("extra-info", &extra_info, false);
 
@@ -605,19 +607,24 @@ void RGWOp_DATALog_List::execute() {
       return;
     }
   } 
-  
+
+  dout(10) << __func__ << " shard " << shard << " st " << st << " et " << et << " marker " 
+         << marker << " max_entries "<< max_entries << dendl;
+  left_cnt = max_entries;
+
   do {
     // Note that last_marker is updated to be the marker of the last
     // entry listed
     http_ret = store->data_log->list_entries(shard_id, ut_st, ut_et, 
-                                            max_entries, entries, marker,
+                                            left_cnt, entries, marker,
                                             &last_marker, &truncated);
     if (http_ret < 0) 
       break;
 
-    if (!max_entries_str.empty()) 
-      max_entries -= entries.size();
-  } while (truncated && (max_entries > 0));
+    assert(max_entries >= entries.size());
+    left_cnt = max_entries - entries.size();
+    marker = last_marker;
+  } while (truncated && (left_cnt > 0));
 }
 
 void RGWOp_DATALog_List::send_response() {