]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: bucket quota can be checked in a way compliant with the Swift API.
authorRadoslaw Zarzynski <rzarzynski@mirantis.com>
Wed, 4 May 2016 17:21:45 +0000 (19:21 +0200)
committerRadoslaw Zarzynski <rzarzynski@mirantis.com>
Mon, 30 May 2016 09:41:00 +0000 (11:41 +0200)
Signed-off-by: Radoslaw Zarzynski <rzarzynski@mirantis.com>
src/rgw/rgw_json_enc.cc
src/rgw/rgw_op.cc
src/rgw/rgw_quota.cc
src/rgw/rgw_quota.h

index 24eaef8effb901e7caecfbdc0b1fe608c5618da1..2fd2bb0f56279cc55845508cdecb8d8433066a23 100644 (file)
@@ -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);
 }
 
index b972e07e1ab16b7b0307306f1472c004a1de0590..c68199cf5dab1c1c2dde1d266701d6e8b01e7307 100644 (file)
@@ -1951,6 +1951,8 @@ static int filter_out_bucket_quota(std::map<std::string, bufferlist>& 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;
 }
index 62233c1d2c3c2cffb0876cbec2d43696756165ea..af5150f139136dd744c8e6ede5ed65c8cac3fcf0 100644 (file)
@@ -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<uint64_t>(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<uint64_t>(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;
+  }
 }
 
 
index 767df7ce79b9f0931322cc9f64ae97682860a8bc..d55dcaff952e898bd5d5f0a9c7733ed584188c93 100644 (file)
@@ -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);
   }