summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYehuda Sadeh <yehuda@inktank.com>2013-07-18 17:40:52 -0700
committerGreg Farnum <greg@inktank.com>2013-07-19 13:21:49 -0700
commit7cd0bd85d458b2cf8f48036362890cf3b22895b3 (patch)
treeed85943cf0ca864c5ab7dcdcc6f8f8bae5e3b20b
parent89ecba209b4f7e8932e92768ac2f028fa2d59b71 (diff)
downloadceph-7cd0bd85d458b2cf8f48036362890cf3b22895b3.tar.gz
rgw: bucket entry point object ver fixes
Multiple fixes: - sync master, secondary entry point ver on creation - use correct entry point version when removing entry point - check correct version on bucket removal Signed-off-by: Yehuda Sadeh <yehuda@inktank.com>
-rw-r--r--src/rgw/rgw_cache.h8
-rw-r--r--src/rgw/rgw_common.h1
-rw-r--r--src/rgw/rgw_metadata.cc2
-rw-r--r--src/rgw/rgw_op.cc35
-rw-r--r--src/rgw/rgw_op.h1
-rw-r--r--src/rgw/rgw_rados.cc30
-rw-r--r--src/rgw/rgw_rados.h7
-rw-r--r--src/rgw/rgw_rest_conn.cc8
-rw-r--r--src/rgw/rgw_rest_conn.h2
-rw-r--r--src/rgw/rgw_rest_s3.cc1
10 files changed, 70 insertions, 25 deletions
diff --git a/src/rgw/rgw_cache.h b/src/rgw/rgw_cache.h
index 1a36e1a78d2..b6c4e15eede 100644
--- a/src/rgw/rgw_cache.h
+++ b/src/rgw/rgw_cache.h
@@ -208,7 +208,7 @@ public:
int obj_stat(void *ctx, rgw_obj& obj, uint64_t *psize, time_t *pmtime, uint64_t *epoch, map<string, bufferlist> *attrs,
bufferlist *first_chunk, RGWObjVersionTracker *objv_tracker);
- int delete_obj(void *ctx, rgw_obj& obj);
+ int delete_obj(void *ctx, rgw_obj& obj, RGWObjVersionTracker *objv_tracker);
};
template <class T>
@@ -224,13 +224,13 @@ void RGWCache<T>::normalize_bucket_and_obj(rgw_bucket& src_bucket, string& src_o
}
template <class T>
-int RGWCache<T>::delete_obj(void *ctx, rgw_obj& obj)
+int RGWCache<T>::delete_obj(void *ctx, rgw_obj& obj, RGWObjVersionTracker *objv_tracker)
{
rgw_bucket bucket;
string oid;
normalize_bucket_and_obj(obj.bucket, obj.object, bucket, oid);
if (bucket.name[0] != '.')
- return T::delete_obj(ctx, obj);
+ return T::delete_obj(ctx, obj, objv_tracker);
string name = normal_name(obj);
cache.remove(name);
@@ -238,7 +238,7 @@ int RGWCache<T>::delete_obj(void *ctx, rgw_obj& obj)
ObjectCacheInfo info;
distribute_cache(name, obj, info, REMOVE_OBJ);
- return T::delete_obj(ctx, obj);
+ return T::delete_obj(ctx, obj, objv_tracker);
}
template <class T>
diff --git a/src/rgw/rgw_common.h b/src/rgw/rgw_common.h
index 9d7c3d41542..1d3596d4418 100644
--- a/src/rgw/rgw_common.h
+++ b/src/rgw/rgw_common.h
@@ -653,6 +653,7 @@ struct RGWBucketInfo
string placement_rule;
bool has_instance_obj;
RGWObjVersionTracker objv_tracker; /* we don't need to serialize this, for runtime tracking */
+ obj_version ep_objv; /* entry point object version, for runtime tracking only */
void encode(bufferlist& bl) const {
ENCODE_START(8, 4, bl);
diff --git a/src/rgw/rgw_metadata.cc b/src/rgw/rgw_metadata.cc
index c370addc293..7be73e6ca0c 100644
--- a/src/rgw/rgw_metadata.cc
+++ b/src/rgw/rgw_metadata.cc
@@ -588,7 +588,7 @@ int RGWMetadataManager::remove_entry(RGWMetadataHandler *handler, string& key, R
rgw_obj obj(bucket, oid);
- ret = store->delete_obj(NULL, obj);
+ ret = store->delete_obj(NULL, obj, objv_tracker);
/* cascading ret into post_modify() */
ret = post_modify(handler, section, key, log_data, objv_tracker, ret);
diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc
index 1dcd8fb8c93..644f8a8921d 100644
--- a/src/rgw/rgw_op.cc
+++ b/src/rgw/rgw_op.cc
@@ -920,7 +920,7 @@ int RGWCreateBucket::verify_permission()
return 0;
}
-static int forward_request_to_master(struct req_state *s, RGWRados *store, bufferlist& in_data, JSONParser *jp)
+static int forward_request_to_master(struct req_state *s, obj_version *objv, RGWRados *store, bufferlist& in_data, JSONParser *jp)
{
if (!store->rest_master_conn) {
ldout(s->cct, 0) << "rest connection is invalid" << dendl;
@@ -929,7 +929,7 @@ static int forward_request_to_master(struct req_state *s, RGWRados *store, buffe
ldout(s->cct, 0) << "sending create_bucket request to master region" << dendl;
bufferlist response;
#define MAX_REST_RESPONSE (128 * 1024) // we expect a very small response
- int ret = store->rest_master_conn->forward(s->user.user_id, s->info, MAX_REST_RESPONSE, &in_data, &response);
+ int ret = store->rest_master_conn->forward(s->user.user_id, s->info, objv, MAX_REST_RESPONSE, &in_data, &response);
if (ret < 0)
return ret;
@@ -989,10 +989,11 @@ void RGWCreateBucket::execute()
if (!store->region.is_master) {
JSONParser jp;
- ret = forward_request_to_master(s, store, in_data, &jp);
+ ret = forward_request_to_master(s, NULL, store, in_data, &jp);
if (ret < 0)
return;
+ JSONDecoder::decode_json("entry_point_object_ver", ep_objv, &jp);
JSONDecoder::decode_json("object_ver", objv, &jp);
JSONDecoder::decode_json("bucket_info", master_info, &jp);
ldout(s->cct, 20) << "parsed: objv.tag=" << objv.tag << " objv.ver=" << objv.ver << dendl;
@@ -1022,7 +1023,7 @@ void RGWCreateBucket::execute()
s->bucket.name = s->bucket_name_str;
ret = store->create_bucket(s->user, s->bucket, region_name, placement_rule, attrs, info, pobjv,
- creation_time, pmaster_bucket, true);
+ &ep_objv, creation_time, pmaster_bucket, true);
/* continue if EEXIST and create_bucket will fail below. this way we can recover
* from a partial create by retrying it. */
ldout(s->cct, 20) << "rgw_create_bucket returned ret=" << ret << " bucket=" << s->bucket << dendl;
@@ -1068,7 +1069,27 @@ void RGWDeleteBucket::execute()
if (!s->bucket_name)
return;
- ret = store->delete_bucket(s->bucket, s->bucket_info.objv_tracker);
+ RGWObjVersionTracker ot;
+ ot.read_version = s->bucket_info.ep_objv;
+
+ if (s->system_request) {
+ string tag = s->info.args.get(RGW_SYS_PARAM_PREFIX "tag");
+ string ver_str = s->info.args.get(RGW_SYS_PARAM_PREFIX "ver");
+ if (!tag.empty()) {
+ ot.read_version.tag = tag;
+ uint64_t ver;
+ string err;
+ ver = strict_strtol(ver_str.c_str(), 10, &err);
+ if (!err.empty()) {
+ ldout(s->cct, 0) << "failed to parse ver param" << dendl;
+ ret = -EINVAL;
+ return;
+ }
+ ot.read_version.ver = ver;
+ }
+ }
+
+ ret = store->delete_bucket(s->bucket, ot);
if (ret == 0) {
ret = rgw_unlink_bucket(store, s->user.user_id, s->bucket.name, false);
@@ -1084,7 +1105,7 @@ void RGWDeleteBucket::execute()
if (!store->region.is_master) {
bufferlist in_data;
JSONParser jp;
- ret = forward_request_to_master(s, store, in_data, &jp);
+ ret = forward_request_to_master(s, &ot.read_version, store, in_data, &jp);
if (ret < 0) {
if (ret == -ENOENT) { /* adjust error,
we want to return with NoSuchBucket and not NoSuchKey */
@@ -1092,8 +1113,6 @@ void RGWDeleteBucket::execute()
}
return;
}
-
- JSONDecoder::decode_json("object_ver", objv_tracker.read_version, &jp);
}
}
diff --git a/src/rgw/rgw_op.h b/src/rgw/rgw_op.h
index 7a2e4920ba8..7bca53b5e43 100644
--- a/src/rgw/rgw_op.h
+++ b/src/rgw/rgw_op.h
@@ -243,6 +243,7 @@ protected:
string location_constraint;
string placement_rule;
RGWBucketInfo info;
+ obj_version ep_objv;
bufferlist in_data;
diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc
index 308adff5ae9..a8061e99bf1 100644
--- a/src/rgw/rgw_rados.cc
+++ b/src/rgw/rgw_rados.cc
@@ -1776,6 +1776,7 @@ int RGWRados::create_bucket(RGWUserInfo& owner, rgw_bucket& bucket,
map<std::string, bufferlist>& attrs,
RGWBucketInfo& info,
obj_version *pobjv,
+ obj_version *pep_objv,
time_t creation_time,
rgw_bucket *pmaster_bucket,
bool exclusive)
@@ -1833,7 +1834,7 @@ int RGWRados::create_bucket(RGWUserInfo& owner, rgw_bucket& bucket,
time(&info.creation_time);
else
info.creation_time = creation_time;
- ret = put_linked_bucket_info(info, exclusive, 0, &attrs, true);
+ ret = put_linked_bucket_info(info, exclusive, 0, pep_objv, &attrs, true);
if (ret == -EEXIST) {
/* we need to reread the info and return it, caller will have a use for it */
r = get_bucket_info(NULL, bucket.name, info, NULL, NULL);
@@ -3074,7 +3075,7 @@ int RGWRados::defer_gc(void *ctx, rgw_obj& obj)
* obj: name of the object to delete
* Returns: 0 on success, -ERR# otherwise.
*/
-int RGWRados::delete_obj_impl(void *ctx, rgw_obj& obj)
+int RGWRados::delete_obj_impl(void *ctx, rgw_obj& obj, RGWObjVersionTracker *objv_tracker)
{
rgw_bucket bucket;
std::string oid, key;
@@ -3100,6 +3101,11 @@ int RGWRados::delete_obj_impl(void *ctx, rgw_obj& obj)
r = prepare_update_index(state, bucket, CLS_RGW_OP_DEL, obj, tag);
if (r < 0)
return r;
+
+ if (objv_tracker) {
+ objv_tracker->prepare_op_for_write(&op);
+ }
+
cls_refcount_put(op, tag, true);
r = io_ctx.operate(oid, &op);
bool removed = (r >= 0);
@@ -3133,11 +3139,11 @@ int RGWRados::delete_obj_impl(void *ctx, rgw_obj& obj)
return 0;
}
-int RGWRados::delete_obj(void *ctx, rgw_obj& obj)
+int RGWRados::delete_obj(void *ctx, rgw_obj& obj, RGWObjVersionTracker *objv_tracker)
{
int r;
- r = delete_obj_impl(ctx, obj);
+ r = delete_obj_impl(ctx, obj, objv_tracker);
if (r == -ECANCELED)
r = 0;
@@ -4606,7 +4612,8 @@ int RGWRados::get_bucket_info(void *ctx, string& bucket_name, RGWBucketInfo& inf
RGWBucketEntryPoint entry_point;
time_t ep_mtime;
- int ret = get_bucket_entrypoint_info(ctx, bucket_name, entry_point, NULL, &ep_mtime);
+ RGWObjVersionTracker ot;
+ int ret = get_bucket_entrypoint_info(ctx, bucket_name, entry_point, &ot, &ep_mtime);
if (ret < 0) {
info.bucket.name = bucket_name; /* only init this field */
return ret;
@@ -4614,6 +4621,7 @@ int RGWRados::get_bucket_info(void *ctx, string& bucket_name, RGWBucketInfo& inf
if (entry_point.has_bucket_info) {
info = entry_point.old_bucket_info;
+ info.ep_objv = ot.read_version;
ldout(cct, 20) << "rgw_get_bucket_info: old bucket info, bucket=" << info.bucket << " owner " << info.owner << dendl;
return 0;
}
@@ -4629,6 +4637,7 @@ int RGWRados::get_bucket_info(void *ctx, string& bucket_name, RGWBucketInfo& inf
get_bucket_meta_oid(entry_point.bucket, oid);
ret = get_bucket_instance_from_oid(ctx, oid, info, pmtime, pattrs);
+ info.ep_objv = ot.read_version;
if (ret < 0) {
info.bucket.name = bucket_name;
return ret;
@@ -4657,7 +4666,7 @@ int RGWRados::put_bucket_instance_info(RGWBucketInfo& info, bool exclusive,
return rgw_bucket_instance_store_info(this, key, bl, exclusive, pattrs, &info.objv_tracker, mtime);
}
-int RGWRados::put_linked_bucket_info(RGWBucketInfo& info, bool exclusive, time_t mtime,
+int RGWRados::put_linked_bucket_info(RGWBucketInfo& info, bool exclusive, time_t mtime, obj_version *pep_objv,
map<string, bufferlist> *pattrs, bool create_entry_point)
{
bufferlist bl;
@@ -4678,7 +4687,14 @@ int RGWRados::put_linked_bucket_info(RGWBucketInfo& info, bool exclusive, time_t
entry_point.creation_time = info.creation_time;
entry_point.linked = true;
RGWObjVersionTracker ot;
- ot.generate_new_write_ver(cct);
+ if (pep_objv && !pep_objv->tag.empty()) {
+ ot.write_version = *pep_objv;
+ } else {
+ ot.generate_new_write_ver(cct);
+ if (pep_objv) {
+ *pep_objv = ot.write_version;
+ }
+ }
ret = put_bucket_entrypoint_info(info.bucket.name, entry_point, exclusive, ot, mtime);
if (ret < 0)
return ret;
diff --git a/src/rgw/rgw_rados.h b/src/rgw/rgw_rados.h
index fb1a1756ba8..99e66a91b1c 100644
--- a/src/rgw/rgw_rados.h
+++ b/src/rgw/rgw_rados.h
@@ -843,7 +843,7 @@ class RGWRados
v.push_back(info);
return clone_objs(ctx, dst_obj, v, attrs, category, pmtime, true, false);
}
- int delete_obj_impl(void *ctx, rgw_obj& src_obj);
+ int delete_obj_impl(void *ctx, rgw_obj& src_obj, RGWObjVersionTracker *objv_tracker);
int complete_atomic_overwrite(RGWRadosCtx *rctx, RGWObjState *state, rgw_obj& obj);
int update_placement_map();
@@ -983,6 +983,7 @@ public:
map<std::string,bufferlist>& attrs,
RGWBucketInfo& bucket_info,
obj_version *pobjv,
+ obj_version *pep_objv,
time_t creation_time,
rgw_bucket *master_bucket,
bool exclusive = true);
@@ -1142,7 +1143,7 @@ public:
int bucket_suspended(rgw_bucket& bucket, bool *suspended);
/** Delete an object.*/
- virtual int delete_obj(void *ctx, rgw_obj& src_obj);
+ virtual int delete_obj(void *ctx, rgw_obj& src_obj, RGWObjVersionTracker *objv_tracker = NULL);
/** Remove an object from the bucket index */
int delete_obj_index(rgw_obj& obj);
@@ -1294,7 +1295,7 @@ public:
virtual int get_bucket_info(void *ctx, string& bucket_name, RGWBucketInfo& info,
time_t *pmtime, map<string, bufferlist> *pattrs = NULL);
- virtual int put_linked_bucket_info(RGWBucketInfo& info, bool exclusive, time_t mtime,
+ virtual int put_linked_bucket_info(RGWBucketInfo& info, bool exclusive, time_t mtime, obj_version *pep_objv,
map<string, bufferlist> *pattrs, bool create_entry_point);
int cls_rgw_init_index(librados::IoCtx& io_ctx, librados::ObjectWriteOperation& op, string& oid);
diff --git a/src/rgw/rgw_rest_conn.cc b/src/rgw/rgw_rest_conn.cc
index 5caf3ce0bcd..35a8ac258e6 100644
--- a/src/rgw/rgw_rest_conn.cc
+++ b/src/rgw/rgw_rest_conn.cc
@@ -27,7 +27,7 @@ int RGWRESTConn::get_url(string& endpoint)
return 0;
}
-int RGWRESTConn::forward(const string& uid, req_info& info, size_t max_response, bufferlist *inbl, bufferlist *outbl)
+int RGWRESTConn::forward(const string& uid, req_info& info, obj_version *objv, size_t max_response, bufferlist *inbl, bufferlist *outbl)
{
string url;
int ret = get_url(url);
@@ -36,6 +36,12 @@ int RGWRESTConn::forward(const string& uid, req_info& info, size_t max_response,
list<pair<string, string> > params;
params.push_back(make_pair<string, string>(RGW_SYS_PARAM_PREFIX "uid", uid));
params.push_back(make_pair<string, string>(RGW_SYS_PARAM_PREFIX "region", region));
+ if (objv) {
+ params.push_back(make_pair<string, string>(RGW_SYS_PARAM_PREFIX "tag", objv->tag));
+ char buf[16];
+ snprintf(buf, sizeof(buf), "%lld", (long long)objv->ver);
+ params.push_back(make_pair<string, string>(RGW_SYS_PARAM_PREFIX "ver", buf));
+ }
RGWRESTSimpleRequest req(cct, url, NULL, &params);
return req.forward_request(key, info, max_response, inbl, outbl);
}
diff --git a/src/rgw/rgw_rest_conn.h b/src/rgw/rgw_rest_conn.h
index 6fe572d2cf7..4a0b6087d26 100644
--- a/src/rgw/rgw_rest_conn.h
+++ b/src/rgw/rgw_rest_conn.h
@@ -20,7 +20,7 @@ public:
int get_url(string& endpoint);
/* sync request */
- int forward(const string& uid, req_info& info, size_t max_response, bufferlist *inbl, bufferlist *outbl);
+ int forward(const string& uid, req_info& info, obj_version *objv, size_t max_response, bufferlist *inbl, bufferlist *outbl);
/* async request */
int put_obj_init(const string& uid, rgw_obj& obj, uint64_t obj_size,
diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc
index 6e482e8a251..9e8ec3f88a5 100644
--- a/src/rgw/rgw_rest_s3.cc
+++ b/src/rgw/rgw_rest_s3.cc
@@ -449,6 +449,7 @@ void RGWCreateBucket_ObjStore_S3::send_response()
JSONFormatter f; /* use json formatter for system requests output */
f.open_object_section("info");
+ encode_json("entry_point_object_ver", ep_objv, &f);
encode_json("object_ver", info.objv_tracker.read_version, &f);
encode_json("bucket_info", info, &f);
f.close_section();