diff options
author | Yehuda Sadeh <yehuda@inktank.com> | 2013-09-19 09:48:25 -0700 |
---|---|---|
committer | Yehuda Sadeh <yehuda@inktank.com> | 2013-09-19 09:48:25 -0700 |
commit | 8d41d3f8968f6f6a2ddbe868ac370edce81996fb (patch) | |
tree | eaeee74ed24b86f65d19b6d9f9e45ddbfcc2dedf | |
parent | 131124d7ac75273ca04311d56f2d996fcb61c7e8 (diff) | |
download | ceph-8d41d3f8968f6f6a2ddbe868ac370edce81996fb.tar.gz |
rgw: radosgw-admin object rewrite
A radosgw-admin command that copies the object into itself while
preserving mtime and attributes so that data can be restriped.
Especially useful when migrating from argonaut (where objects
weren't striped).
Signed-off-by: Yehuda Sadeh <yehuda@inktank.com>
-rw-r--r-- | src/rgw/rgw_admin.cc | 13 | ||||
-rw-r--r-- | src/rgw/rgw_cache.h | 8 | ||||
-rw-r--r-- | src/rgw/rgw_rados.cc | 43 | ||||
-rw-r--r-- | src/rgw/rgw_rados.h | 5 |
4 files changed, 61 insertions, 8 deletions
diff --git a/src/rgw/rgw_admin.cc b/src/rgw/rgw_admin.cc index 067a70bfeba..1e0532935eb 100644 --- a/src/rgw/rgw_admin.cc +++ b/src/rgw/rgw_admin.cc @@ -159,6 +159,7 @@ enum { OPT_TEMP_REMOVE, OPT_OBJECT_RM, OPT_OBJECT_UNLINK, + OPT_OBJECT_REWRITE, OPT_GC_LIST, OPT_GC_PROCESS, OPT_CLUSTER_INFO, @@ -327,6 +328,8 @@ static int get_cmd(const char *cmd, const char *prev_cmd, bool *need_more) return OPT_OBJECT_RM; if (strcmp(cmd, "unlink") == 0) return OPT_OBJECT_UNLINK; + if (strcmp(cmd, "rewrite") == 0) + return OPT_OBJECT_REWRITE; } else if (strcmp(prev_cmd, "cluster") == 0) { if (strcmp(cmd, "info") == 0) return OPT_CLUSTER_INFO; @@ -1758,6 +1761,16 @@ next: } } + if (opt_cmd == OPT_OBJECT_REWRITE) { + rgw_obj obj(bucket, object); + int ret = store->rewrite_obj(obj); + + if (ret < 0) { + cerr << "ERROR: object remove returned: " << cpp_strerror(-ret) << std::endl; + return 1; + } + } + if (opt_cmd == OPT_OBJECT_UNLINK) { list<string> oid_list; oid_list.push_back(object); diff --git a/src/rgw/rgw_cache.h b/src/rgw/rgw_cache.h index e4002f6af25..14428c0c3cd 100644 --- a/src/rgw/rgw_cache.h +++ b/src/rgw/rgw_cache.h @@ -192,7 +192,8 @@ public: int put_obj_meta(void *ctx, rgw_obj& obj, uint64_t size, time_t *mtime, map<std::string, bufferlist>& attrs, RGWObjCategory category, int flags, map<std::string, bufferlist>* rmattrs, const bufferlist *data, - RGWObjManifest *manifest, const string *ptag, list<string> *remove_objs); + RGWObjManifest *manifest, const string *ptag, list<string> *remove_objs, + time_t *set_mtime); int put_obj_data(void *ctx, rgw_obj& obj, const char *data, off_t ofs, size_t len, bool exclusive); @@ -352,7 +353,8 @@ template <class T> int RGWCache<T>::put_obj_meta(void *ctx, rgw_obj& obj, uint64_t size, time_t *mtime, map<std::string, bufferlist>& attrs, RGWObjCategory category, int flags, map<std::string, bufferlist>* rmattrs, const bufferlist *data, - RGWObjManifest *manifest, const string *ptag, list<string> *remove_objs) + RGWObjManifest *manifest, const string *ptag, list<string> *remove_objs, + time_t *set_mtime) { rgw_bucket bucket; string oid; @@ -369,7 +371,7 @@ int RGWCache<T>::put_obj_meta(void *ctx, rgw_obj& obj, uint64_t size, time_t *mt info.flags |= CACHE_FLAG_DATA; } } - int ret = T::put_obj_meta(ctx, obj, size, mtime, attrs, category, flags, rmattrs, data, manifest, ptag, remove_objs); + int ret = T::put_obj_meta(ctx, obj, size, mtime, attrs, category, flags, rmattrs, data, manifest, ptag, remove_objs, set_mtime); if (cacheable) { string name = normal_name(bucket, oid); if (ret >= 0) { diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc index 48c7b2a31df..4351c9c7e4a 100644 --- a/src/rgw/rgw_rados.cc +++ b/src/rgw/rgw_rados.cc @@ -1038,7 +1038,8 @@ int RGWRados::put_obj_meta(void *ctx, rgw_obj& obj, uint64_t size, const bufferlist *data, RGWObjManifest *manifest, const string *ptag, - list<string> *remove_objs) + list<string> *remove_objs, + time_t *set_mtime) { rgw_bucket bucket; std::string oid, key; @@ -1125,6 +1126,10 @@ int RGWRados::put_obj_meta(void *ctx, rgw_obj& obj, uint64_t size, if (r < 0) return r; + if (set_mtime) { + op.mtime(set_mtime); + } + r = io_ctx.operate(oid, &op); if (r < 0) goto done_cancel; @@ -1136,7 +1141,11 @@ int RGWRados::put_obj_meta(void *ctx, rgw_obj& obj, uint64_t size, ldout(cct, 0) << "ERROR: complete_atomic_overwrite returned r=" << r << dendl; } - ut = ceph_clock_now(cct); + if (!set_mtime) { + ut = ceph_clock_now(cct); + } else { + ut = utime_t(*set_mtime, 0); + } r = complete_update_index(bucket, obj.object, index_tag, epoch, size, ut, etag, content_type, &acl_bl, category, remove_objs); if (r < 0) @@ -1231,6 +1240,31 @@ bool RGWRados::aio_completed(void *handle) AioCompletion *c = (AioCompletion *)handle; return c->is_complete(); } + + +int RGWRados::rewrite_obj(rgw_obj& obj) +{ + map<string, bufferlist> attrset; + off_t ofs = 0; + off_t end = -1; + void *handle = NULL; + + time_t mtime; + uint64_t total_len; + uint64_t obj_size; + RGWRadosCtx rctx(this); + int ret = prepare_get_obj((void *)&rctx, obj, &ofs, &end, &attrset, + NULL, NULL, &mtime, NULL, NULL, &total_len, + &obj_size, &handle, NULL); + if (ret < 0) + return ret; + + attrset.erase(RGW_ATTR_ID_TAG); + + return copy_obj_data((void *)&rctx, handle, end, obj, obj, NULL, &mtime, attrset, RGW_OBJ_CATEGORY_MAIN, NULL); +} + + /** * Copy an object. * dest_obj: the object to copy into @@ -1313,7 +1347,7 @@ int RGWRados::copy_obj(void *ctx, } if (copy_data) { /* refcounting tail wouldn't work here, just copy the data */ - return copy_obj_data(ctx, handle, end, dest_obj, src_obj, mtime, attrset, category, err); + return copy_obj_data(ctx, handle, end, dest_obj, src_obj, mtime, NULL, attrset, category, err); } map<uint64_t, RGWObjManifestPart>::iterator miter = astate->manifest.objs.begin(); @@ -1412,6 +1446,7 @@ int RGWRados::copy_obj_data(void *ctx, rgw_obj& dest_obj, rgw_obj& src_obj, time_t *mtime, + time_t *set_mtime, map<string, bufferlist>& attrs, RGWObjCategory category, struct rgw_err *err) @@ -1470,7 +1505,7 @@ int RGWRados::copy_obj_data(void *ctx, } manifest.obj_size = ofs; - ret = put_obj_meta(ctx, dest_obj, end + 1, NULL, attrs, category, PUT_OBJ_CREATE, NULL, &first_chunk, &manifest, NULL, NULL); + ret = put_obj_meta(ctx, dest_obj, end + 1, NULL, attrs, category, PUT_OBJ_CREATE, NULL, &first_chunk, &manifest, NULL, NULL, set_mtime); if (mtime) obj_stat(ctx, dest_obj, NULL, mtime, NULL, NULL, NULL); diff --git a/src/rgw/rgw_rados.h b/src/rgw/rgw_rados.h index d1b106a07b5..46febeab0b4 100644 --- a/src/rgw/rgw_rados.h +++ b/src/rgw/rgw_rados.h @@ -466,7 +466,8 @@ public: virtual int put_obj_meta(void *ctx, rgw_obj& obj, uint64_t size, time_t *mtime, map<std::string, bufferlist>& attrs, RGWObjCategory category, int flags, map<std::string, bufferlist>* rmattrs, const bufferlist *data, - RGWObjManifest *manifest, const string *ptag, list<string> *remove_objs); + RGWObjManifest *manifest, const string *ptag, list<string> *remove_objs, + time_t *set_mtime = NULL); virtual int put_obj_data(void *ctx, rgw_obj& obj, const char *data, off_t ofs, size_t len, bool exclusive); virtual int aio_put_obj_data(void *ctx, rgw_obj& obj, bufferlist& bl, @@ -519,6 +520,7 @@ public: return clone_objs(ctx, dst_obj, v, attrs, category, pmtime, truncate_dest, exclusive, xattr_cond); } + int rewrite_obj(rgw_obj& obj); /** * Copy an object. * dest_obj: the object to copy into @@ -544,6 +546,7 @@ public: rgw_obj& dest_obj, rgw_obj& src_obj, time_t *mtime, + time_t *set_mtime, map<string, bufferlist>& attrs, RGWObjCategory category, struct rgw_err *err); |