From: Radoslaw Zarzynski Date: Wed, 4 May 2016 17:21:45 +0000 (+0200) Subject: rgw: bucket quota can be checked in a way compliant with the Swift API. X-Git-Tag: v11.0.0~349^2~7 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=d07c967d9836bf013d6cba29927290c63f7c3b59;p=ceph.git rgw: bucket quota can be checked in a way compliant with the Swift API. Signed-off-by: Radoslaw Zarzynski --- diff --git a/src/rgw/rgw_json_enc.cc b/src/rgw/rgw_json_enc.cc index 24eaef8effb9..2fd2bb0f5627 100644 --- a/src/rgw/rgw_json_enc.cc +++ b/src/rgw/rgw_json_enc.cc @@ -488,6 +488,8 @@ void RGWUserInfo::decode_json(JSONObj *obj) void RGWQuotaInfo::dump(Formatter *f) const { f->dump_bool("enabled", enabled); + f->dump_bool("check_on_raw", check_on_raw); + f->dump_int("max_size", max_size); f->dump_int("max_size_kb", rgw_rounded_kb(max_size)); f->dump_int("max_objects", max_objects); @@ -503,6 +505,8 @@ void RGWQuotaInfo::decode_json(JSONObj *obj) max_size = max_size_kb * 1024; } JSONDecoder::decode_json("max_objects", max_objects, obj); + + JSONDecoder::decode_json("check_on_raw", check_on_raw, obj); JSONDecoder::decode_json("enabled", enabled, obj); } diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index b972e07e1ab1..c68199cf5dab 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -1951,6 +1951,8 @@ static int filter_out_bucket_quota(std::map& add_attrs, } } + /* Swift requries checking on raw usage instead of the 4 KiB rounded one. */ + quota.check_on_raw = true; quota.enabled = quota.max_size > 0 || quota.max_objects > 0; return 0; } diff --git a/src/rgw/rgw_quota.cc b/src/rgw/rgw_quota.cc index 62233c1d2c3c..af5150f13913 100644 --- a/src/rgw/rgw_quota.cc +++ b/src/rgw/rgw_quota.cc @@ -706,6 +706,19 @@ public: const uint64_t num_objs) const; }; +class RGWQuotaInfoRawApplier : public RGWQuotaInfoApplier { +public: + virtual bool is_size_exceeded(const char * const entity, + const RGWQuotaInfo& qinfo, + const RGWStorageStats& stats, + const uint64_t size) const; + + virtual bool is_num_objs_exceeded(const char * const entity, + const RGWQuotaInfo& qinfo, + const RGWStorageStats& stats, + const uint64_t num_objs) const; +}; + bool RGWQuotaInfoDefApplier::is_size_exceeded(const char * const entity, const RGWQuotaInfo& qinfo, @@ -749,12 +762,59 @@ bool RGWQuotaInfoDefApplier::is_num_objs_exceeded(const char * const entity, return false; } +bool RGWQuotaInfoRawApplier::is_size_exceeded(const char * const entity, + const RGWQuotaInfo& qinfo, + const RGWStorageStats& stats, + const uint64_t size) const +{ + if (qinfo.max_size < 0) { + /* The limit is not enabled. */ + return false; + } + + const uint64_t cur_size = stats.size; + + if (cur_size + size > static_cast(qinfo.max_size)) { + dout(10) << "quota exceeded: stats.size=" << stats.size + << " size=" << size << " " + << entity << "_quota.max_size=" << qinfo.max_size << dendl; + return true; + } + + return false; +} + +bool RGWQuotaInfoRawApplier::is_num_objs_exceeded(const char * const entity, + const RGWQuotaInfo& qinfo, + const RGWStorageStats& stats, + const uint64_t num_objs) const +{ + if (qinfo.max_objects < 0) { + /* The limit is not enabled. */ + return false; + } + + if (stats.num_objects + num_objs > static_cast(qinfo.max_objects)) { + dout(10) << "quota exceeded: stats.num_objects=" << stats.num_objects + << " " << entity << "_quota.max_objects=" << qinfo.max_objects + << dendl; + return true; + } + + return false; +} + const RGWQuotaInfoApplier& RGWQuotaInfoApplier::get_instance( const RGWQuotaInfo& qinfo) { static RGWQuotaInfoDefApplier default_qapplier; + static RGWQuotaInfoRawApplier raw_qapplier; - return default_qapplier; + if (qinfo.check_on_raw) { + return raw_qapplier; + } else { + return default_qapplier; + } } diff --git a/src/rgw/rgw_quota.h b/src/rgw/rgw_quota.h index 767df7ce79b9..d55dcaff952e 100644 --- a/src/rgw/rgw_quota.h +++ b/src/rgw/rgw_quota.h @@ -42,17 +42,21 @@ public: int64_t max_size; int64_t max_objects; bool enabled; + /* Do we want to compare with raw, not rounded RGWStorageStats::size (true) + * or maybe rounded-to-4KiB RGWStorageStats::size_rounded (false)? */ + bool check_on_raw; RGWQuotaInfo() : max_size_soft_threshold(-1), max_objs_soft_threshold(-1), max_size(-1), max_objects(-1), - enabled(false) { + enabled(false), + check_on_raw(false) { } void encode(bufferlist& bl) const { - ENCODE_START(2, 1, bl); + ENCODE_START(3, 1, bl); if (max_size < 0) { ::encode(-rgw_rounded_kb(abs(max_size)), bl); } else { @@ -61,10 +65,11 @@ public: ::encode(max_objects, bl); ::encode(enabled, bl); ::encode(max_size, bl); + ::encode(check_on_raw, bl); ENCODE_FINISH(bl); } void decode(bufferlist::iterator& bl) { - DECODE_START_LEGACY_COMPAT_LEN(2, 1, 1, bl); + DECODE_START_LEGACY_COMPAT_LEN(3, 1, 1, bl); int64_t max_size_kb; ::decode(max_size_kb, bl); ::decode(max_objects, bl); @@ -74,6 +79,9 @@ public: } else { ::decode(max_size, bl); } + if (struct_v >= 3) { + ::decode(check_on_raw, bl); + } DECODE_FINISH(bl); }