From 9fbc5378d2737d38e2ac915f20b44d308e18bc68 Mon Sep 17 00:00:00 2001 From: Xie Rui Date: Thu, 22 Jun 2017 17:12:30 +0800 Subject: [PATCH] fix infinite loop in rest api for log list 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 --- src/rgw/rgw_metadata.cc | 9 +++++++-- src/rgw/rgw_rest_log.cc | 29 ++++++++++++++++++----------- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/rgw/rgw_metadata.cc b/src/rgw/rgw_metadata.cc index 5a286b4aeb6..28a2b94c7a0 100644 --- a/src/rgw/rgw_metadata.cc +++ b/src/rgw/rgw_metadata.cc @@ -149,13 +149,18 @@ int RGWMetadataLog::list_entries(void *handle, *truncated = false; return 0; } - + + list 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; diff --git a/src/rgw/rgw_rest_log.cc b/src/rgw/rgw_rest_log.cc index 9220917c99a..f932807cd02 100644 --- a/src/rgw/rgw_rest_log.cc +++ b/src/rgw/rgw_rest_log.cc @@ -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() { -- 2.39.5