diff options
-rw-r--r-- | src/rgw/rgw_admin.cc | 14 | ||||
-rw-r--r-- | src/rgw/rgw_rados.cc | 26 | ||||
-rw-r--r-- | src/rgw/rgw_rados.h | 2 | ||||
-rw-r--r-- | src/test/cli/radosgw-admin/help.t | 1 |
4 files changed, 43 insertions, 0 deletions
diff --git a/src/rgw/rgw_admin.cc b/src/rgw/rgw_admin.cc index 860a4d19eba..a3b1271d9ce 100644 --- a/src/rgw/rgw_admin.cc +++ b/src/rgw/rgw_admin.cc @@ -55,6 +55,7 @@ void _usage() cerr << " bucket rm remove bucket\n"; cerr << " bucket check check bucket index\n"; cerr << " object rm remove object\n"; + cerr << " object unlink unlink object from bucket index\n"; cerr << " cluster info show cluster params info\n"; cerr << " pool add add an existing pool for data placement\n"; cerr << " pool rm remove an existing pool from data placement set\n"; @@ -155,6 +156,7 @@ enum { OPT_USAGE_TRIM, OPT_TEMP_REMOVE, OPT_OBJECT_RM, + OPT_OBJECT_UNLINK, OPT_GC_LIST, OPT_GC_PROCESS, OPT_CLUSTER_INFO, @@ -227,6 +229,7 @@ static int get_cmd(const char *cmd, const char *prev_cmd, bool *need_more) strcmp(cmd, "key") == 0 || strcmp(cmd, "buckets") == 0 || strcmp(cmd, "bucket") == 0 || + strcmp(cmd, "object") == 0 || strcmp(cmd, "pool") == 0 || strcmp(cmd, "pools") == 0 || strcmp(cmd, "log") == 0 || @@ -318,6 +321,8 @@ static int get_cmd(const char *cmd, const char *prev_cmd, bool *need_more) } else if (strcmp(prev_cmd, "object") == 0) { if (strcmp(cmd, "rm") == 0) return OPT_OBJECT_RM; + if (strcmp(cmd, "unlink") == 0) + return OPT_OBJECT_UNLINK; } else if (strcmp(prev_cmd, "cluster") == 0) { if (strcmp(cmd, "info") == 0) return OPT_CLUSTER_INFO; @@ -1627,6 +1632,14 @@ next: } } + if (opt_cmd == OPT_OBJECT_UNLINK) { + int ret = store->remove_obj_from_index(bucket, object); + if (ret < 0) { + cerr << "ERROR: remove_obj_from_index() returned error: " << cpp_strerror(-ret) << std::endl; + return 1; + } + } + if (opt_cmd == OPT_BUCKET_CHECK) { map<RGWObjCategory, RGWBucketStats> existing_stats; map<RGWObjCategory, RGWBucketStats> calculated_stats; @@ -1757,5 +1770,6 @@ next: store->params.dump(formatter); formatter->flush(cout); } + return 0; } diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc index d75b0d8a8e5..895dd7001e1 100644 --- a/src/rgw/rgw_rados.cc +++ b/src/rgw/rgw_rados.cc @@ -3228,6 +3228,32 @@ int RGWRados::cls_obj_usage_log_trim(string& oid, string& user, uint64_t start_e return r; } +int RGWRados::remove_obj_from_index(rgw_bucket& bucket, const string& oid) +{ + librados::IoCtx io_ctx; + + int r = open_bucket_ctx(bucket, io_ctx); + if (r < 0) + return r; + + string dir_oid = dir_oid_prefix; + dir_oid.append(bucket.marker); + + rgw_bucket_dir_entry entry; + entry.epoch = (uint64_t)-1; // ULLONG_MAX, needed to that objclass doesn't skip out request + entry.name = oid; + + bufferlist updates; + updates.append(CEPH_RGW_REMOVE); + ::encode(entry, updates); + + bufferlist out; + + r = io_ctx.exec(dir_oid, "rgw", "dir_suggest_changes", updates, out); + + return r; +} + int RGWRados::check_disk_state(librados::IoCtx io_ctx, rgw_bucket& bucket, rgw_bucket_dir_entry& list_state, diff --git a/src/rgw/rgw_rados.h b/src/rgw/rgw_rados.h index e2ab4e24499..e50ef5d4490 100644 --- a/src/rgw/rgw_rados.h +++ b/src/rgw/rgw_rados.h @@ -720,6 +720,8 @@ public: map<RGWObjCategory, RGWBucketStats> *existing_stats, map<RGWObjCategory, RGWBucketStats> *calculated_stats); int bucket_rebuild_index(rgw_bucket& bucket); + int remove_obj_from_index(rgw_bucket& bucket, const string& oid); + private: int process_intent_log(rgw_bucket& bucket, string& oid, time_t epoch, int flags, bool purge); diff --git a/src/test/cli/radosgw-admin/help.t b/src/test/cli/radosgw-admin/help.t index 0ab4eace52b..1927023a2a7 100644 --- a/src/test/cli/radosgw-admin/help.t +++ b/src/test/cli/radosgw-admin/help.t @@ -21,6 +21,7 @@ bucket rm remove bucket bucket check check bucket index object rm remove object + object unlink unlink object from bucket index cluster info show cluster params info pool add add an existing pool for data placement pool rm remove an existing pool from data placement set |