]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: copy swift versioned object to destination if overwritten
authorYehuda Sadeh <yehuda@redhat.com>
Wed, 2 Mar 2016 00:46:47 +0000 (16:46 -0800)
committerYehuda Sadeh <yehuda@redhat.com>
Sat, 12 Mar 2016 00:20:44 +0000 (16:20 -0800)
Only allow if target bucket owner is the source bucket owner.

Signed-off-by: Yehuda Sadeh <yehuda@redhat.com>
src/rgw/rgw_rados.cc
src/rgw/rgw_rados.h

index 0aaf4426bb5e5c9d36e8d589ad463ae640996598..6c6b5ca8cac95ea9262ff17ad59ffed462d63f69 100644 (file)
@@ -5651,6 +5651,76 @@ int RGWRados::BucketShard::init(rgw_bucket& _bucket, rgw_obj& obj)
 }
 
 
+int RGWRados::swift_versioning_copy(RGWBucketInfo& bucket_info, RGWRados::Object *source, RGWObjState *state,
+                                    rgw_user& user)
+{
+  if (!bucket_info.has_swift_versioning() || bucket_info.swift_ver_location.empty()) {
+    return 0;
+  }
+
+  if (!state->exists) {
+    return 0;
+  }
+
+  string client_id;
+  string op_id;
+
+  rgw_obj& obj = source->get_obj();
+  const string& src_name = obj.get_object();
+  char buf[src_name.size() + 32];
+  snprintf(buf, sizeof(buf), "%03d%s%lld.%06d", (int)src_name.size(), src_name.c_str(), (long long)state->mtime, 0);
+
+  RGWBucketInfo dest_bucket_info;
+
+  int r = get_bucket_info(source->get_ctx(), bucket_info.bucket.tenant, bucket_info.swift_ver_location, dest_bucket_info, NULL, NULL);
+  if (r < 0) {
+    ldout(cct, 10) << "failed to read dest bucket info: r=" << r << dendl;
+    return r;
+  }
+
+  if (dest_bucket_info.owner != bucket_info.owner) {
+    return -EPERM;
+  }
+
+  rgw_obj dest_obj(dest_bucket_info.bucket, buf);
+
+  string no_zone;
+
+  r = copy_obj(source->get_ctx(),
+               user,
+               client_id,
+               op_id,
+               NULL, /* req_info *info */
+               no_zone,
+               dest_obj,
+               obj,
+               dest_bucket_info,
+               bucket_info,
+               NULL, /* time_t *src_mtime */
+               NULL, /* time_t *mtime */
+               NULL, /* const time_t *mod_ptr */
+               NULL, /* const time_t *unmod_ptr */
+               NULL, /* const char *if_match */
+               NULL, /* const char *if_nomatch */
+               RGWRados::ATTRSMOD_NONE,
+               true, /* bool copy_if_newer */
+               state->attrset,
+               RGW_OBJ_CATEGORY_MAIN,
+               0, /* uint64_t olh_epoch */
+               0, /* time_t delete_at */
+               NULL, /* string *version_id */
+               NULL, /* string *ptag */
+               NULL, /* string *petag */
+               NULL, /* struct rgw_err *err */
+               NULL, /* void (*progress_cb)(off_t, void *) */
+               NULL); /* void *progress_data */
+  if (r == -ECANCELED || r == -ENOENT) { /* has already been overwritten, meaning another rgw process already copied it out */
+    return 0;
+  }
+
+  return r;
+}
+
 /**
  * Write/overwrite an object to the bucket storage.
  * bucket: the bucket to store the object in
@@ -5779,13 +5849,20 @@ int RGWRados::Object::Write::write_meta(uint64_t size,
 
   bool versioned_op = (target->versioning_enabled() || is_olh || versioned_target);
 
-  RGWRados::Bucket bop(store, target->get_bucket_info());
+  RGWBucketInfo& bucket_info = target->get_bucket_info();
+
+  RGWRados::Bucket bop(store, bucket_info);
   RGWRados::Bucket::UpdateIndex index_op(&bop, obj, state);
 
   if (versioned_op) {
     index_op.set_bilog_flags(RGW_BILOG_FLAG_VERSIONED_OP);
   }
 
+  r = store->swift_versioning_copy(bucket_info, target, state, meta.owner);
+  if (r < 0) {
+    goto done_cancel;
+  }
+
   r = index_op.prepare(CLS_RGW_OP_ADD);
   if (r < 0)
     return r;
@@ -7362,11 +7439,18 @@ int RGWRados::Object::Delete::delete_obj()
 
   bool ret_not_existed = (!state->exists);
 
-  RGWRados::Bucket bop(store, target->get_bucket_info());
+  RGWBucketInfo& bucket_info = target->get_bucket_info();
+
+  RGWRados::Bucket bop(store, bucket_info);
   RGWRados::Bucket::UpdateIndex index_op(&bop, obj, state);
 
   index_op.set_bilog_flags(params.bilog_flags);
 
+  r = store->swift_versioning_copy(bucket_info, target, state, params.bucket_owner);
+  if (r < 0) {
+    return r;
+  }
+
   r = index_op.prepare(CLS_RGW_OP_DEL);
   if (r < 0)
     return r;
index bf36a1e9ee54d2ef619d4af8f524a5ebd298bb5c..feea80f06744acb06941f51cebcac9ae04c99fc3 100644 (file)
@@ -2448,6 +2448,8 @@ public:
                        struct rgw_err *err,
                        void (*progress_cb)(off_t, void *),
                        void *progress_data);
+  int swift_versioning_copy(RGWBucketInfo& bucket_info, RGWRados::Object *source, RGWObjState *state,
+                            rgw_user& user);
   int copy_obj_to_remote_dest(RGWObjState *astate,
                               map<string, bufferlist>& src_attrs,
                               RGWRados::Object::Read& read_op,