From: Yehuda Sadeh Date: Fri, 10 Jan 2014 23:38:37 +0000 (-0800) Subject: rgw: enable user quota X-Git-Tag: v0.78~270^2~20 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=cfb9553c84680287abc8e88c9ce1c4930baddaf8;p=ceph.git rgw: enable user quota Signed-off-by: Yehuda Sadeh --- diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index d07cc1bba1d6..0694786c3ab8 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -1415,7 +1415,8 @@ void RGWPutObj::execute() if (!chunked_upload) { /* with chunked upload we don't know how big is the upload. we also check sizes at the end anyway */ - ret = store->check_quota(s->bucket_owner.get_id(), s->bucket, bucket_quota, s->content_length); + ret = store->check_quota(s->bucket_owner.get_id(), s->bucket, + s->user.user_quota, bucket_quota, s->content_length); if (ret < 0) { goto done; } @@ -1465,7 +1466,8 @@ void RGWPutObj::execute() s->obj_size = ofs; perfcounter->inc(l_rgw_put_b, s->obj_size); - ret = store->check_quota(s->bucket_owner.get_id(), s->bucket, bucket_quota, s->obj_size); + ret = store->check_quota(s->bucket_owner.get_id(), s->bucket, + s->user.user_quota, bucket_quota, s->obj_size); if (ret < 0) { goto done; } diff --git a/src/rgw/rgw_quota.cc b/src/rgw/rgw_quota.cc index 4286e8bd558f..bf32a0f06bec 100644 --- a/src/rgw/rgw_quota.cc +++ b/src/rgw/rgw_quota.cc @@ -408,44 +408,68 @@ int RGWUserStatsCache::fetch_stats_from_storage(const string& user, rgw_bucket& class RGWQuotaHandlerImpl : public RGWQuotaHandler { RGWRados *store; - RGWBucketStatsCache stats_cache; + RGWBucketStatsCache bucket_stats_cache; + RGWUserStatsCache user_stats_cache; + + int check_quota(const char *entity, RGWQuotaInfo& quota, RGWStorageStats& stats, + uint64_t num_objs, uint64_t size_kb) { + 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; + + 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; + } + + return 0; + } public: - RGWQuotaHandlerImpl(RGWRados *_store) : store(_store), stats_cache(_store) {} - virtual int check_quota(const string& user, rgw_bucket& bucket, RGWQuotaInfo& bucket_quota, + RGWQuotaHandlerImpl(RGWRados *_store) : store(_store), bucket_stats_cache(_store), user_stats_cache(_store) {} + virtual int check_quota(const string& user, rgw_bucket& bucket, + RGWQuotaInfo& user_quota, RGWQuotaInfo& bucket_quota, uint64_t num_objs, uint64_t size) { uint64_t size_kb = rgw_rounded_kb(size); if (!bucket_quota.enabled) { return 0; } - RGWStorageStats stats; + RGWStorageStats bucket_stats; - int ret = stats_cache.get_stats(user, bucket, stats, bucket_quota); + int ret = bucket_stats_cache.get_stats(user, bucket, bucket_stats, bucket_quota); if (ret < 0) return ret; - ldout(store->ctx(), 20) << "bucket quota: max_objects=" << bucket_quota.max_objects - << " max_size_kb=" << bucket_quota.max_size_kb << dendl; + ret = check_quota("bucket", bucket_quota, bucket_stats, num_objs, size_kb); + if (ret < 0) + return ret; + + RGWStorageStats user_stats; + + ret = user_stats_cache.get_stats(user, bucket, user_stats, user_quota); + if (ret < 0) + return ret; + + ret = check_quota("user", user_quota, user_stats, num_objs, size_kb); + if (ret < 0) + return ret; - if (bucket_quota.max_objects >= 0 && - stats.num_objects + num_objs > (uint64_t)bucket_quota.max_objects) { - ldout(store->ctx(), 10) << "quota exceeded: stats.num_objects=" << stats.num_objects - << " bucket_quota.max_objects=" << bucket_quota.max_objects << dendl; - return -ERR_QUOTA_EXCEEDED; - } - if (bucket_quota.max_size_kb >= 0 && - stats.num_kb_rounded + size_kb > (uint64_t)bucket_quota.max_size_kb) { - ldout(store->ctx(), 10) << "quota exceeded: stats.num_kb_rounded=" << stats.num_kb_rounded << " size_kb=" << size_kb - << " bucket_quota.max_size_kb=" << bucket_quota.max_size_kb << dendl; - return -ERR_QUOTA_EXCEEDED; - } return 0; } virtual void update_stats(const string& user, rgw_bucket& bucket, int obj_delta, uint64_t added_bytes, uint64_t removed_bytes) { - stats_cache.adjust_stats(user, bucket, obj_delta, added_bytes, removed_bytes); + bucket_stats_cache.adjust_stats(user, bucket, obj_delta, added_bytes, removed_bytes); + user_stats_cache.adjust_stats(user, bucket, obj_delta, added_bytes, removed_bytes); }; }; diff --git a/src/rgw/rgw_quota.h b/src/rgw/rgw_quota.h index 4c6b4262a09e..5595a73739a6 100644 --- a/src/rgw/rgw_quota.h +++ b/src/rgw/rgw_quota.h @@ -62,7 +62,8 @@ public: RGWQuotaHandler() {} virtual ~RGWQuotaHandler() { } - virtual int check_quota(const string& bucket_owner, rgw_bucket& bucket, RGWQuotaInfo& bucket_quota, + virtual int check_quota(const string& bucket_owner, rgw_bucket& bucket, + RGWQuotaInfo& user_quota, RGWQuotaInfo& bucket_quota, uint64_t num_objs, uint64_t size) = 0; virtual void update_stats(const string& bucket_owner, rgw_bucket& bucket, int obj_delta, uint64_t added_bytes, uint64_t removed_bytes) = 0; diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc index fbedc6feaede..8a4927a315c8 100644 --- a/src/rgw/rgw_rados.cc +++ b/src/rgw/rgw_rados.cc @@ -5803,9 +5803,10 @@ int RGWRados::cls_user_remove_bucket(rgw_obj& obj, const cls_user_bucket& bucket return 0; } -int RGWRados::check_quota(const string& bucket_owner, rgw_bucket& bucket, RGWQuotaInfo& quota_info, uint64_t obj_size) +int RGWRados::check_quota(const string& bucket_owner, rgw_bucket& bucket, + RGWQuotaInfo& user_quota, RGWQuotaInfo& bucket_quota, uint64_t obj_size) { - return quota_handler->check_quota(bucket_owner, bucket, quota_info, 1, obj_size); + return quota_handler->check_quota(bucket_owner, bucket, user_quota, bucket_quota, 1, obj_size); } class IntentLogNameFilter : public RGWAccessListFilter diff --git a/src/rgw/rgw_rados.h b/src/rgw/rgw_rados.h index f7a594c41fe1..01da08181e8d 100644 --- a/src/rgw/rgw_rados.h +++ b/src/rgw/rgw_rados.h @@ -1447,7 +1447,8 @@ public: int cls_user_add_bucket(rgw_obj& obj, list& entries); int cls_user_remove_bucket(rgw_obj& obj, const cls_user_bucket& bucket); - int check_quota(const string& bucket_owner, rgw_bucket& bucket, RGWQuotaInfo& quota_info, uint64_t obj_size); + int check_quota(const string& bucket_owner, rgw_bucket& bucket, + RGWQuotaInfo& user_quota, RGWQuotaInfo& bucket_quota, uint64_t obj_size); string unique_id(uint64_t unique_num) { char buf[32];