summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYehuda Sadeh <yehuda@inktank.com>2013-09-19 09:48:25 -0700
committerYehuda Sadeh <yehuda@inktank.com>2013-09-19 09:48:25 -0700
commit8d41d3f8968f6f6a2ddbe868ac370edce81996fb (patch)
treeeaeee74ed24b86f65d19b6d9f9e45ddbfcc2dedf
parent131124d7ac75273ca04311d56f2d996fcb61c7e8 (diff)
downloadceph-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.cc13
-rw-r--r--src/rgw/rgw_cache.h8
-rw-r--r--src/rgw/rgw_rados.cc43
-rw-r--r--src/rgw/rgw_rados.h5
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);