From: Radoslaw Zarzynski Date: Fri, 29 Apr 2016 22:39:59 +0000 (+0200) Subject: rgw: RGWStorageStats does store sizes with byte precision. X-Git-Tag: v11.0.0~349^2~12 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=43ca8870bb25c9eebc356326cfa5609a647f9b09;p=ceph.git rgw: RGWStorageStats does store sizes with byte precision. Signed-off-by: Radoslaw Zarzynski --- diff --git a/src/rgw/rgw_admin.cc b/src/rgw/rgw_admin.cc index 48d40fb45b9b..bdc4e313c4b3 100644 --- a/src/rgw/rgw_admin.cc +++ b/src/rgw/rgw_admin.cc @@ -811,8 +811,10 @@ static void dump_bucket_usage(map& stats, Forma RGWStorageStats& s = iter->second; const char *cat_name = rgw_obj_category_name(iter->first); formatter->open_object_section(cat_name); - formatter->dump_int("size_kb", s.num_kb); - formatter->dump_int("size_kb_actual", s.num_kb_rounded); + formatter->dump_int("size", s.size); + formatter->dump_int("size_actual", s.size_rounded); + formatter->dump_int("size_kb", rgw_rounded_kb(s.size)); + formatter->dump_int("size_kb_actual", rgw_rounded_kb(s.size_rounded)); formatter->dump_int("num_objects", s.num_objects); formatter->close_section(); formatter->flush(cout); diff --git a/src/rgw/rgw_bucket.cc b/src/rgw/rgw_bucket.cc index 685968cd66c1..b4462bf71c22 100644 --- a/src/rgw/rgw_bucket.cc +++ b/src/rgw/rgw_bucket.cc @@ -736,8 +736,10 @@ static void dump_bucket_usage(map& stats, Forma RGWStorageStats& s = iter->second; const char *cat_name = rgw_obj_category_name(iter->first); formatter->open_object_section(cat_name); - formatter->dump_int("size_kb", s.num_kb); - formatter->dump_int("size_kb_actual", s.num_kb_rounded); + formatter->dump_int("size", s.size); + formatter->dump_int("size_actual", s.size_rounded); + formatter->dump_int("size_kb", rgw_rounded_kb(s.size)); + formatter->dump_int("size_kb_actual", rgw_rounded_kb(s.size_rounded)); formatter->dump_int("num_objects", s.num_objects); formatter->close_section(); } diff --git a/src/rgw/rgw_common.h b/src/rgw/rgw_common.h index 3520b722815c..d70c1a029803 100644 --- a/src/rgw/rgw_common.h +++ b/src/rgw/rgw_common.h @@ -1061,11 +1061,15 @@ WRITE_CLASS_ENCODER(RGWBucketEntryPoint) struct RGWStorageStats { RGWObjCategory category; - uint64_t num_kb; - uint64_t num_kb_rounded; + uint64_t size; + uint64_t size_rounded; uint64_t num_objects; - RGWStorageStats() : category(RGW_OBJ_CATEGORY_NONE), num_kb(0), num_kb_rounded(0), num_objects(0) {} + RGWStorageStats() + : category(RGW_OBJ_CATEGORY_NONE), + size(0), + size_rounded(0), + num_objects(0) {} void dump(Formatter *f) const; }; @@ -1822,6 +1826,11 @@ static inline uint64_t rgw_rounded_kb(uint64_t bytes) return (bytes + 1023) / 1024; } +static inline uint64_t rgw_rounded_objsize(uint64_t bytes) +{ + return ((bytes + 4095) & ~4095); +} + static inline uint64_t rgw_rounded_objsize_kb(uint64_t bytes) { return ((bytes + 4095) & ~4095) / 1024; diff --git a/src/rgw/rgw_json_enc.cc b/src/rgw/rgw_json_enc.cc index f5d18dcd225c..333cf1bb4471 100644 --- a/src/rgw/rgw_json_enc.cc +++ b/src/rgw/rgw_json_enc.cc @@ -545,8 +545,10 @@ void RGWBucketEntryPoint::decode_json(JSONObj *obj) { void RGWStorageStats::dump(Formatter *f) const { - encode_json("num_kb", num_kb, f); - encode_json("num_kb_rounded", num_kb_rounded, f); + encode_json("size", size, f); + encode_json("size_rounded", size_rounded, f); + encode_json("num_kb", rgw_rounded_kb(size), f); + encode_json("num_kb_rounded", rgw_rounded_kb(size_rounded), f); encode_json("num_objects", num_objects, f); } diff --git a/src/rgw/rgw_quota.cc b/src/rgw/rgw_quota.cc index 0ea17d5e7e88..6bda6ebe486b 100644 --- a/src/rgw/rgw_quota.cc +++ b/src/rgw/rgw_quota.cc @@ -106,9 +106,10 @@ bool RGWQuotaCache::can_use_cached_stats(RGWQuotaInfo& quota, RGWStorageStats quota.max_size_soft_threshold = quota.max_size_kb * store->ctx()->_conf->rgw_bucket_quota_soft_threshold; } - if (cached_stats.num_kb_rounded >= (uint64_t)quota.max_size_soft_threshold) { + const auto cached_stats_num_kb_rounded = rgw_rounded_kb(cached_stats.size_rounded); + if (cached_stats_num_kb_rounded >= (uint64_t)quota.max_size_soft_threshold) { ldout(store->ctx(), 20) << "quota: can't use cached stats, exceeded soft threshold (size): " - << cached_stats.num_kb_rounded << " >= " << quota.max_size_soft_threshold << dendl; + << cached_stats_num_kb_rounded << " >= " << quota.max_size_soft_threshold << dendl; return false; } } @@ -211,18 +212,24 @@ int RGWQuotaCache::get_stats(const rgw_user& user, rgw_bucket& bucket, RGWSto template class RGWQuotaStatsUpdate : public lru_map::UpdateContext { - int objs_delta; - uint64_t added_bytes; - uint64_t removed_bytes; + const int objs_delta; + const uint64_t added_bytes; + const uint64_t removed_bytes; public: - RGWQuotaStatsUpdate(int _objs_delta, uint64_t _added_bytes, uint64_t _removed_bytes) : - objs_delta(_objs_delta), added_bytes(_added_bytes), removed_bytes(_removed_bytes) {} - bool update(RGWQuotaCacheStats *entry) { - uint64_t rounded_kb_added = rgw_rounded_objsize_kb(added_bytes); - uint64_t rounded_kb_removed = rgw_rounded_objsize_kb(removed_bytes); - - entry->stats.num_kb_rounded += (rounded_kb_added - rounded_kb_removed); - entry->stats.num_kb += (added_bytes - removed_bytes) / 1024; + RGWQuotaStatsUpdate(const int objs_delta, + const uint64_t added_bytes, + const uint64_t removed_bytes) + : objs_delta(objs_delta), + added_bytes(added_bytes), + removed_bytes(removed_bytes) { + } + + bool update(RGWQuotaCacheStats * const entry) override { + const uint64_t rounded_added = rgw_rounded_objsize(added_bytes); + const uint64_t rounded_removed = rgw_rounded_objsize(removed_bytes); + + entry->stats.size += added_bytes - removed_bytes; + entry->stats.size_rounded += rounded_added - rounded_removed; entry->stats.num_objects += objs_delta; return true; @@ -269,7 +276,7 @@ int BucketAsyncRefreshHandler::init_fetch() return 0; } -void BucketAsyncRefreshHandler::handle_response(int r) +void BucketAsyncRefreshHandler::handle_response(const int r) { if (r < 0) { ldout(store->ctx(), 20) << "AsyncRefreshHandler::handle_response() r=" << r << dendl; @@ -278,11 +285,11 @@ void BucketAsyncRefreshHandler::handle_response(int r) RGWStorageStats bs; - map::iterator iter; - for (iter = stats->begin(); iter != stats->end(); ++iter) { - RGWStorageStats& s = iter->second; - bs.num_kb += s.num_kb; - bs.num_kb_rounded += s.num_kb_rounded; + for (const auto& pair : *stats) { + const RGWStorageStats& s = pair.second; + + bs.size += s.size; + bs.size_rounded += s.size_rounded; bs.num_objects += s.num_objects; } @@ -322,19 +329,21 @@ int RGWBucketStatsCache::fetch_stats_from_storage(const rgw_user& user, rgw_buck string master_ver; map bucket_stats; - int r = store->get_bucket_stats(bucket, RGW_NO_SHARD, &bucket_ver, &master_ver, bucket_stats, NULL); + int r = store->get_bucket_stats(bucket, RGW_NO_SHARD, &bucket_ver, + &master_ver, bucket_stats, nullptr); if (r < 0) { - ldout(store->ctx(), 0) << "could not get bucket info for bucket=" << bucket.name << dendl; + ldout(store->ctx(), 0) << "could not get bucket info for bucket=" + << bucket.name << dendl; return r; } stats = RGWStorageStats(); - map::iterator iter; - for (iter = bucket_stats.begin(); iter != bucket_stats.end(); ++iter) { - RGWStorageStats& s = iter->second; - stats.num_kb += s.num_kb; - stats.num_kb_rounded += s.num_kb_rounded; + for (const auto& pair : bucket_stats) { + const RGWStorageStats& s = pair.second; + + stats.size += s.size; + stats.size_rounded += s.size_rounded; stats.num_objects += s.num_objects; } @@ -669,26 +678,44 @@ class RGWQuotaHandlerImpl : public RGWQuotaHandler { RGWQuotaInfo def_bucket_quota; RGWQuotaInfo def_user_quota; - int check_quota(const char *entity, RGWQuotaInfo& quota, RGWStorageStats& stats, - uint64_t num_objs, uint64_t size_kb) { - if (!quota.enabled) + int check_quota(const char * const entity, + const RGWQuotaInfo& quota, + const RGWStorageStats& stats, + const uint64_t num_objs, + const uint64_t size) { + if (!quota.enabled) { return 0; + } - ldout(store->ctx(), 20) << entity << " quota: max_objects=" << quota.max_objects + ldout(store->ctx(), 20) << entity + << " quota: max_objects=" << quota.max_objects << " max_size_kb=" << quota.max_size_kb << dendl; if (quota.max_objects >= 0 && stats.num_objects + num_objs > (uint64_t)quota.max_objects) { - ldout(store->ctx(), 10) << "quota exceeded: stats.num_objects=" << stats.num_objects - << " " << entity << "_quota.max_objects=" << quota.max_objects << dendl; + ldout(store->ctx(), 10) << "quota exceeded: stats.num_objects=" + << stats.num_objects + << " " << entity << "_quota.max_objects=" + << quota.max_objects << dendl; return -ERR_QUOTA_EXCEEDED; } - if (quota.max_size_kb >= 0 && - stats.num_kb_rounded + size_kb > (uint64_t)quota.max_size_kb) { - ldout(store->ctx(), 10) << "quota exceeded: stats.num_kb_rounded=" << stats.num_kb_rounded << " size_kb=" << size_kb - << " " << entity << "_quota.max_size_kb=" << quota.max_size_kb << dendl; - return -ERR_QUOTA_EXCEEDED; + + /* Handling quota in KiBs due to backward compatibility. */ + if (quota.max_size_kb >= 0) { + const uint64_t size_kb = rgw_rounded_objsize_kb(size); + /* XXX: just div 1024 should be enough. */ + const uint64_t stats_num_kb_rounded = rgw_rounded_kb(stats.size_rounded); + + if (stats_num_kb_rounded + size_kb > (uint64_t)quota.max_size_kb) { + ldout(store->ctx(), 10) << "quota exceeded: stats_num_kb_rounded=" + << stats_num_kb_rounded + << " size_kb=" << size_kb << " " << entity + << "_quota.max_size_kb=" + << quota.max_size_kb << dendl; + + return -ERR_QUOTA_EXCEEDED; + } } return 0; @@ -712,54 +739,66 @@ public: def_user_quota.enabled = true; } } - virtual int check_quota(const rgw_user& user, rgw_bucket& bucket, - RGWQuotaInfo& user_quota, RGWQuotaInfo& bucket_quota, - uint64_t num_objs, uint64_t size) { + + virtual int check_quota(const rgw_user& user, + rgw_bucket& bucket, + RGWQuotaInfo& user_quota, + RGWQuotaInfo& bucket_quota, + uint64_t num_objs, + uint64_t size) override { if (!bucket_quota.enabled && !user_quota.enabled && !def_bucket_quota.enabled && !def_user_quota.enabled) return 0; - uint64_t size_kb = rgw_rounded_objsize_kb(size); - RGWStorageStats bucket_stats; /* - * we need to fetch bucket stats if the user quota is enabled, because the whole system relies - * on us periodically updating the user's bucket stats in the user's header, this happens in - * get_stats() if we actually fetch that info and not rely on cached data + * we need to fetch bucket stats if the user quota is enabled, because + * the whole system relies on us periodically updating the user's bucket + * stats in the user's header, this happens in get_stats() if we actually + * fetch that info and not rely on cached data */ - int ret = bucket_stats_cache.get_stats(user, bucket, bucket_stats, bucket_quota); - if (ret < 0) + int ret = bucket_stats_cache.get_stats(user, bucket, bucket_stats, + bucket_quota); + if (ret < 0) { return ret; + } if (bucket_quota.enabled) { - ret = check_quota("bucket", bucket_quota, bucket_stats, num_objs, size_kb); - if (ret < 0) + ret = check_quota("bucket", bucket_quota, bucket_stats, num_objs, size); + if (ret < 0) { return ret; + } } if (def_bucket_quota.enabled) { - ret = check_quota("def_bucket", def_bucket_quota, bucket_stats, num_objs, size_kb); - if (ret < 0) + ret = check_quota("def_bucket", def_bucket_quota, bucket_stats, + num_objs, size); + if (ret < 0) { return ret; + } } if (user_quota.enabled || def_user_quota.enabled) { RGWStorageStats user_stats; ret = user_stats_cache.get_stats(user, bucket, user_stats, user_quota); - if (ret < 0) + if (ret < 0) { return ret; + } if (user_quota.enabled) { - ret = check_quota("user", user_quota, user_stats, num_objs, size_kb); - if (ret < 0) + ret = check_quota("user", user_quota, user_stats, num_objs, size); + if (ret < 0) { return ret; + } } else if (def_user_quota.enabled) { - ret = check_quota("def_user", def_user_quota, user_stats, num_objs, size_kb); - if (ret < 0) + ret = check_quota("def_user", def_user_quota, user_stats, + num_objs, size); + if (ret < 0) { return ret; + } } } diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc index 5346dca65a33..446d78e66b38 100644 --- a/src/rgw/rgw_rados.cc +++ b/src/rgw/rgw_rados.cc @@ -7336,16 +7336,18 @@ int RGWRados::open_bucket_index_shard(rgw_bucket& bucket, librados::IoCtx& index return 0; } -static void accumulate_raw_stats(rgw_bucket_dir_header& header, map& stats) +static void accumulate_raw_stats(const rgw_bucket_dir_header& header, + map& stats) { - map::iterator iter = header.stats.begin(); - for (; iter != header.stats.end(); ++iter) { - RGWObjCategory category = (RGWObjCategory)iter->first; + for (const auto& pair : header.stats) { + const RGWObjCategory category = static_cast(pair.first); + const rgw_bucket_category_stats& header_stats = pair.second; + RGWStorageStats& s = stats[category]; - struct rgw_bucket_category_stats& header_stats = iter->second; - s.category = (RGWObjCategory)iter->first; - s.num_kb += ((header_stats.total_size + 1023) / 1024); - s.num_kb_rounded += ((header_stats.total_size_rounded + 1023) / 1024); + + s.category = category; + s.size += header_stats.total_size; + s.size_rounded += header_stats.total_size_rounded; s.num_objects += header_stats.num_entries; } } @@ -10250,14 +10252,16 @@ class RGWGetUserStatsContext : public RGWGetUserHeader_CB { RGWGetUserStats_CB *cb; public: - explicit RGWGetUserStatsContext(RGWGetUserStats_CB *_cb) : cb(_cb) {} + explicit RGWGetUserStatsContext(RGWGetUserStats_CB * const cb) + : cb(cb) {} + void handle_response(int r, cls_user_header& header) { - cls_user_stats& hs = header.stats; + const cls_user_stats& hs = header.stats; if (r >= 0) { RGWStorageStats stats; - stats.num_kb = (hs.total_bytes + 1023) / 1024; - stats.num_kb_rounded = (hs.total_bytes_rounded + 1023) / 1024; + stats.size = hs.total_bytes; + stats.size_rounded = hs.total_bytes_rounded; stats.num_objects = hs.total_entries; cb->set_response(stats); @@ -10278,10 +10282,10 @@ int RGWRados::get_user_stats(const rgw_user& user, RGWStorageStats& stats) if (r < 0) return r; - cls_user_stats& hs = header.stats; + const cls_user_stats& hs = header.stats; - stats.num_kb = (hs.total_bytes + 1023) / 1024; - stats.num_kb_rounded = (hs.total_bytes_rounded + 1023) / 1024; + stats.size = hs.total_bytes; + stats.size_rounded = hs.total_bytes_rounded; stats.num_objects = hs.total_entries; return 0; @@ -11589,8 +11593,8 @@ int RGWRados::update_user_bucket_stats(const string& user_id, rgw_bucket& bucket { cls_user_bucket_entry entry; - entry.size = stats.num_kb * 1024; - entry.size_rounded = stats.num_kb_rounded * 1024; + entry.size = stats.size; + entry.size_rounded = stats.size_rounded; entry.count += stats.num_objects; list entries;