]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
tools/rados: add support for binary object names.
authorRadoslaw Zarzynski <rzarzyns@redhat.com>
Fri, 5 Feb 2021 15:28:04 +0000 (15:28 +0000)
committerRadoslaw Zarzynski <rzarzyns@redhat.com>
Wed, 17 Feb 2021 18:13:44 +0000 (18:13 +0000)
Signed-off-by: Radoslaw Zarzynski <rzarzyns@redhat.com>
(cherry picked from commit d333b35aa10bf03a8bc047994d5cf3fed019b49a)

Conflicts:
src/tools/rados/rados.cc
  * no input-file option,
  * no commands for cache tiering,
  * older API for omap retrival.

src/tools/rados/rados.cc

index 5bc1f56d37bb33c22228da339aae07237cf7a7af..bb6caa172eb7032c2becf956402c2818e196026b 100644 (file)
@@ -48,6 +48,7 @@
 #include <climits>
 #include <locale>
 #include <memory>
+#include <optional>
 
 #include "cls/lock/cls_lock_client.h"
 #include "include/compat.h"
@@ -185,6 +186,8 @@ void usage(ostream& out)
 "        set the object size for put/get ops and for write benchmarking\n"
 "   --max-objects\n"
 "        set the max number of objects for write benchmarking\n"
+"   --obj-name-file file\n"
+"        use the content of the specified file in place of <obj-name>\n"
 "   -s name\n"
 "   --snap name\n"
 "        select given snap name for (read) IO\n"
@@ -453,10 +456,8 @@ static int dump_data(std::string const &filename, bufferlist const &data)
 }
 
 
-static int do_get(IoCtx& io_ctx, const char *objname, const char *outfile, unsigned op_size, [[maybe_unused]] const bool use_striper)
+static int do_get(IoCtx& io_ctx, const std::string& oid, const char *outfile, unsigned op_size, [[maybe_unused]] const bool use_striper)
 {
-  string oid(objname);
-
   int fd;
   if (strcmp(outfile, "-") == 0) {
     fd = STDOUT_FILENO;
@@ -549,11 +550,10 @@ static int do_copy_pool(Rados& rados, const char *src_pool, const char *target_p
 }
 
 static int do_put(IoCtx& io_ctx, 
-            const char *objname, const char *infile, int op_size,
+            const std::string& oid, const char *infile, int op_size,
             uint64_t obj_offset,
             const bool use_striper)
 {
-  string oid(objname);
   bool stdio = (strcmp(infile, "-") == 0);
   int ret = 0;
   int fd = STDIN_FILENO;
@@ -611,10 +611,9 @@ static int do_put(IoCtx& io_ctx,
 }
 
 static int do_append(IoCtx& io_ctx, 
-                  const char *objname, const char *infile, int op_size,
+                  const std::string& oid, const char *infile, int op_size,
                   const bool use_striper)
 {
-  string oid(objname);
   bool stdio = (strcmp(infile, "-") == 0);
   int ret = 0;
   int fd = STDIN_FILENO;
@@ -1828,6 +1827,16 @@ static int do_get_inconsistent_cmd(const std::vector<const char*> &nargs,
   return ret;
 }
 
+static std::string prettify(const std::string& s)
+{
+  if (std::find_if_not(s.begin(), s.end(),
+                       (int (*)(int))isprint) != s.end()) {
+    return "(binary key)";
+  } else {
+    return s;
+  }
+}
+
 /**********************************************
 
 **********************************************/
@@ -1880,6 +1889,7 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts,
   bool omap_key_valid = false;
   std::string omap_key;
   std::string omap_key_pretty;
+  std::optional<std::string> obj_name;
   bool with_reference = false;
 
   Rados rados;
@@ -2099,6 +2109,17 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts,
         omap_key_pretty = "(binary key)";
     }
   }
+  i = opts.find("obj-name-file");
+  if (i != opts.end()) {
+    string err;
+    bufferlist indata;
+    ret = indata.read_file(i->second.c_str(), &err);
+    if (ret < 0) {
+      cerr << err << std::endl;
+      return 1;
+    }
+    obj_name = std::string(indata.c_str(), indata.length());
+  }
   i = opts.find("offset_align");
   if (i != opts.end()) {
     if (rados_sistrtoll(i, &offset_align)) {
@@ -2474,15 +2495,17 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts,
     }
   }
   else if (strcmp(nargs[0], "mapext") == 0) {
-    if (!pool_name || nargs.size() < 2) {
+    if (!pool_name || (nargs.size() < 2 && !obj_name)) {
       usage(cerr);
       return 1;
     }
-    string oid(nargs[1]);
+    if (!obj_name) {
+      obj_name = nargs[1];
+    }
     std::map<uint64_t,uint64_t> m;
-    ret = io_ctx.mapext(oid, 0, -1, m);
+    ret = io_ctx.mapext(*obj_name, 0, -1, m);
     if (ret < 0) {
-      cerr << "mapext error on " << pool_name << "/" << oid << ": " << cpp_strerror(ret) << std::endl;
+      cerr << "mapext error on " << pool_name << "/" << prettify(*obj_name) << ": " << cpp_strerror(ret) << std::endl;
       return 1;
     }
     std::map<uint64_t,uint64_t>::iterator iter;
@@ -2491,116 +2514,147 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts,
     }
   }
   else if (strcmp(nargs[0], "stat") == 0) {
-    if (!pool_name || nargs.size() < 2) {
+    if (!pool_name || (nargs.size() < 2 && !obj_name)) {
       usage(cerr);
       return 1;
     }
-    string oid(nargs[1]);
+    if (!obj_name) {
+      obj_name = nargs[1];
+    }
     uint64_t size;
     time_t mtime;
 
-    ret = detail::stat(io_ctx, oid, size, mtime, use_striper);
+    ret = detail::stat(io_ctx, *obj_name, size, mtime, use_striper);
 
     if (ret < 0) {
-      cerr << " error stat-ing " << pool_name << "/" << oid << ": "
+      cerr << " error stat-ing " << pool_name << "/" << prettify(*obj_name) << ": "
            << cpp_strerror(ret) << std::endl;
       return 1;
     } else {
       utime_t t(mtime, 0);
-      cout << pool_name << "/" << oid
+      cout << pool_name << "/" << prettify(*obj_name)
            << " mtime " << t << ", size " << size << std::endl;
     }
   }
   else if (strcmp(nargs[0], "stat2") == 0) {
-    if (!pool_name || nargs.size() < 2) {
+    if (!pool_name || (nargs.size() < 2 && !obj_name)) {
       usage(cerr);
       return 1;
     }
-    string oid(nargs[1]);
+    if (!obj_name) {
+      obj_name = nargs[1];
+    }
     uint64_t size;
     struct timespec mtime;
 
-    ret = detail::stat2(io_ctx, oid, size, mtime, use_striper);
+    ret = detail::stat2(io_ctx, *obj_name, size, mtime, use_striper);
 
     if (ret < 0) {
-      cerr << " error stat-ing " << pool_name << "/" << oid << ": "
+      cerr << " error stat-ing " << pool_name << "/" << prettify(*obj_name) << ": "
           << cpp_strerror(ret) << std::endl;
       return 1;
     } else {
       utime_t t(mtime);
-      cout << pool_name << "/" << oid
+      cout << pool_name << "/" << prettify(*obj_name)
           << " mtime " << t << ", size " << size << std::endl;
     }
   } 
   else if (strcmp(nargs[0], "touch") == 0) {
-    if (!pool_name || nargs.size() < 2) {
+    if (!pool_name || (nargs.size() < 2 && !obj_name)) {
       usage(cerr);
       return 1;
     }
-    string oid(nargs[1]);
     time_t timestamp = time(NULL);
-    if (nargs.size() > 2) {
+    if (nargs.size() > (obj_name ? 1 : 2)) {
       char* endptr = NULL;
-      timestamp = static_cast<time_t>(strtoll(nargs[2], &endptr, 10));
+      timestamp = static_cast<time_t>(strtoll(nargs[obj_name ? 1 : 2], &endptr, 10));
       if (*endptr) {
-        cerr << "Invalid value for timestamp: '" << nargs[2] << "'" << std::endl;
+        cerr << "Invalid value for timestamp: '" << nargs[obj_name ? 1 : 2] << "'" << std::endl;
         ret = -EINVAL;
         return 1;
       }
     }
-    
+    if (!obj_name) {
+       obj_name = nargs[1];
+    }
     ObjectWriteOperation op;
     op.create(false);
     op.mtime(&timestamp);
-    ret = io_ctx.operate(oid, &op);
+    ret = io_ctx.operate(*obj_name, &op);
     if (ret < 0) {
-      cerr << " error touch-ing " << pool_name << "/" << oid << ": "
+      cerr << " error touch-ing " << pool_name << "/" << prettify(*obj_name) << ": "
           << cpp_strerror(ret) << std::endl;
       return 1;
     }
   }
   else if (strcmp(nargs[0], "get") == 0) {
-    if (!pool_name || nargs.size() < 3) {
+    if (!pool_name || nargs.size() < (obj_name ? 2 : 3)) {
       usage(cerr);
       return 1;
     }
-    ret = do_get(io_ctx, nargs[1], nargs[2], op_size, use_striper);
+    const char* out_filename;
+    if (obj_name) {
+      out_filename = nargs[1];
+    } else {
+      obj_name = nargs[1];
+      out_filename = nargs[2];
+    }
+    ret = do_get(io_ctx, *obj_name, out_filename, op_size, use_striper);
     if (ret < 0) {
-      cerr << "error getting " << pool_name << "/" << nargs[1] << ": " << cpp_strerror(ret) << std::endl;
+      cerr << "error getting " << pool_name << "/" << prettify(*obj_name) << ": " << cpp_strerror(ret) << std::endl;
       return 1;
     }
   }
   else if (strcmp(nargs[0], "put") == 0) {
-    if (!pool_name || nargs.size() < 3) {
+    if (!pool_name || nargs.size() < (obj_name ? 2 : 3)) {
       usage(cerr);
       return 1;
     }
-    ret = do_put(io_ctx, nargs[1], nargs[2], op_size, obj_offset, use_striper);
+    const char* in_filename;
+    if (obj_name) {
+      in_filename = nargs[1];
+    } else {
+      obj_name = nargs[1];
+      in_filename = nargs[2];
+    }
+    ret = do_put(io_ctx, *obj_name, in_filename, op_size, obj_offset, use_striper);
     if (ret < 0) {
-      cerr << "error putting " << pool_name << "/" << nargs[1] << ": " << cpp_strerror(ret) << std::endl;
+      cerr << "error putting " << pool_name << "/" << prettify(*obj_name) << ": " << cpp_strerror(ret) << std::endl;
       return 1;
     }
   }
   else if (strcmp(nargs[0], "append") == 0) {
-    if (!pool_name || nargs.size() < 3) {
+    if (!pool_name || nargs.size() < (obj_name ? 2 : 3)) {
       usage(cerr);
       return 1;
     }
-    ret = do_append(io_ctx, nargs[1], nargs[2], op_size, use_striper);
+    const char* in_filename;
+    if (obj_name) {
+      in_filename = nargs[1];
+    } else {
+      obj_name = nargs[1];
+      in_filename = nargs[2];
+    }
+    ret = do_append(io_ctx, *obj_name, in_filename, op_size, use_striper);
     if (ret < 0) {
-      cerr << "error appending " << pool_name << "/" << nargs[1] << ": " << cpp_strerror(ret) << std::endl;
+      cerr << "error appending " << pool_name << "/" << prettify(*obj_name) << ": " << cpp_strerror(ret) << std::endl;
       return 1;
     }
   }
   else if (strcmp(nargs[0], "truncate") == 0) {
-    if (!pool_name || nargs.size() < 3) {
+    if (!pool_name || nargs.size() < (obj_name ? 2 : 3)) {
       usage(cerr);
       return 1;
     }
 
-    string oid(nargs[1]);
     char* endptr = NULL;
-    long size = strtoll(nargs[2], &endptr, 10);
+    long size;
+    if (!obj_name) {
+      obj_name = nargs[1];
+      size = strtoll(nargs[2], &endptr, 10);
+    } else {
+      size = strtoll(nargs[1], &endptr, 10);
+    }
     if (*endptr) {
       cerr << "Invalid value for size: '" << nargs[2] << "'" << std::endl;
       ret = -EINVAL;
@@ -2612,27 +2666,26 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts,
       return 1;
     }
 
-    ret = detail::trunc(io_ctx, oid, size, use_striper);
+    ret = detail::trunc(io_ctx, *obj_name, size, use_striper);
 
     if (ret < 0) {
       cerr << "error truncating oid "
-          << oid << " to " << size << ": "
+          << prettify(*obj_name) << " to " << size << ": "
           << cpp_strerror(ret) << std::endl;
     } else {
       ret = 0;
     }
   }
   else if (strcmp(nargs[0], "setxattr") == 0) {
-    if (!pool_name || nargs.size() < 3 || nargs.size() > 4) {
+    if (!pool_name || nargs.size() < (obj_name ? 2 : 3) ||
+       nargs.size() > (obj_name ? 3 : 4)) {
       usage(cerr);
       return 1;
     }
-
-    string oid(nargs[1]);
-    string attr_name(nargs[2]);
+    string attr_name(nargs[obj_name ? 1 : 2]);
     bufferlist bl;
-    if (nargs.size() == 4) {
-      string attr_val(nargs[3]);
+    if (nargs.size() == (obj_name ? 3 : 4)) {
+      string attr_val(nargs[obj_name ? 2 : 3]);
       bl.append(attr_val.c_str(), attr_val.length());
     } else {
       do {
@@ -2641,30 +2694,33 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts,
          return 1;
       } while (ret > 0);
     }
+    if (!obj_name) {
+      obj_name = nargs[1];
+    }
 
-    ret = detail::setxattr(io_ctx, oid, attr_name, bl, use_striper);
+    ret = detail::setxattr(io_ctx, *obj_name, attr_name, bl, use_striper);
 
     if (ret < 0) {
-      cerr << "error setting xattr " << pool_name << "/" << oid << "/" << attr_name << ": " << cpp_strerror(ret) << std::endl;
+      cerr << "error setting xattr " << pool_name << "/" << prettify(*obj_name) << "/" << attr_name << ": " << cpp_strerror(ret) << std::endl;
       return 1;
     }
     else
       ret = 0;
   }
   else if (strcmp(nargs[0], "getxattr") == 0) {
-    if (!pool_name || nargs.size() < 3) {
+    if (!pool_name || nargs.size() < (obj_name ? 2 : 3)) {
       usage(cerr);
       return 1;
     }
-
-    string oid(nargs[1]);
-    string attr_name(nargs[2]);
-
+    string attr_name(nargs[obj_name ? 1 : 2]);
+    if (!obj_name) {
+      *obj_name = nargs[1];
+    }
     bufferlist bl;
-    ret = detail::getxattr(io_ctx, oid, attr_name, bl, use_striper);
+    ret = detail::getxattr(io_ctx, *obj_name, attr_name, bl, use_striper);
 
     if (ret < 0) {
-      cerr << "error getting xattr " << pool_name << "/" << oid << "/" << attr_name << ": " << cpp_strerror(ret) << std::endl;
+      cerr << "error getting xattr " << pool_name << "/" << prettify(*obj_name) << "/" << attr_name << ": " << cpp_strerror(ret) << std::endl;
       return 1;
     }
     else
@@ -2672,34 +2728,36 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts,
     string s(bl.c_str(), bl.length());
     cout << s;
   } else if (strcmp(nargs[0], "rmxattr") == 0) {
-    if (!pool_name || nargs.size() < 3) {
+    if (!pool_name || nargs.size() < (obj_name ? 2 : 3)) {
       usage(cerr);
       return 1;
     }
 
-    string oid(nargs[1]);
-    string attr_name(nargs[2]);
-
-    ret = detail::rmxattr(io_ctx, oid, attr_name, use_striper);
+    string attr_name(nargs[obj_name ? 1 : 2]);
+    if (!obj_name) {
+      *obj_name = nargs[1];
+    }
+    ret = detail::rmxattr(io_ctx, *obj_name, attr_name, use_striper);
 
     if (ret < 0) {
-      cerr << "error removing xattr " << pool_name << "/" << oid << "/" << attr_name << ": " << cpp_strerror(ret) << std::endl;
+      cerr << "error removing xattr " << pool_name << "/" << prettify(*obj_name) << "/" << attr_name << ": " << cpp_strerror(ret) << std::endl;
       return 1;
     }
   } else if (strcmp(nargs[0], "listxattr") == 0) {
-    if (!pool_name || nargs.size() < 2) {
+    if (!pool_name || (nargs.size() < 2 && !obj_name)) {
       usage(cerr);
       return 1;
     }
-
-    string oid(nargs[1]);
+    if (!obj_name) {
+      obj_name = nargs[1];
+    }
     bufferlist bl;
     map<std::string, bufferlist> attrset;
 
-    ret = detail::getxattrs(io_ctx, oid, attrset, use_striper);
+    ret = detail::getxattrs(io_ctx, *obj_name, attrset, use_striper);
 
     if (ret < 0) {
-      cerr << "error getting xattr set " << pool_name << "/" << oid << ": " << cpp_strerror(ret) << std::endl;
+      cerr << "error getting xattr set " << pool_name << "/" << prettify(*obj_name) << ": " << cpp_strerror(ret) << std::endl;
       return 1;
     }
 
@@ -2708,21 +2766,21 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts,
       cout << iter->first << std::endl;
     }
   } else if (strcmp(nargs[0], "getomapheader") == 0) {
-    if (!pool_name || nargs.size() < 2) {
+    if (!pool_name || (nargs.size() < 2 && !obj_name)) {
       usage(cerr);
       return 1;
     }
-
-    string oid(nargs[1]);
     string outfile;
-    if (nargs.size() >= 3) {
-      outfile = nargs[2];
+    if (nargs.size() >= (obj_name ? 2 : 3)) {
+      outfile = nargs[obj_name ? 1 : 2];
+    }
+    if (!obj_name) {
+      obj_name = nargs[1];
     }
-
     bufferlist header;
-    ret = io_ctx.omap_get_header(oid, &header);
+    ret = io_ctx.omap_get_header(*obj_name, &header);
     if (ret < 0) {
-      cerr << "error getting omap header " << pool_name << "/" << oid
+      cerr << "error getting omap header " << pool_name << "/" << prettify(*obj_name)
           << ": " << cpp_strerror(ret) << std::endl;
       return 1;
     } else {
@@ -2737,20 +2795,21 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts,
       ret = 0;
     }
   } else if (strcmp(nargs[0], "setomapheader") == 0) {
-    if (!pool_name || nargs.size() < 3) {
+    if (!pool_name || nargs.size() < (obj_name ? 2 : 3)) {
       usage(cerr);
       return 1;
     }
 
-    string oid(nargs[1]);
-    string val(nargs[2]);
-
     bufferlist bl;
-    bl.append(val);
-
-    ret = io_ctx.omap_set_header(oid, bl);
+    if (!obj_name) {
+      obj_name = nargs[1];
+      bl.append(nargs[2]); // val
+    } else {
+      bl.append(nargs[1]); // val
+    }
+    ret = io_ctx.omap_set_header(*obj_name, bl);
     if (ret < 0) {
-      cerr << "error setting omap value " << pool_name << "/" << oid
+      cerr << "error setting omap value " << pool_name << "/" << prettify(*obj_name)
           << ": " << cpp_strerror(ret) << std::endl;
       return 1;
     } else {
@@ -2794,15 +2853,15 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts,
       ret = 0;
     }
   } else if (strcmp(nargs[0], "getomapval") == 0) {
-    uint32_t min_args = (omap_key_valid ? 2 : 3);
+    uint32_t min_args = (omap_key_valid ? (obj_name ? 1 : 2)
+                                       : (obj_name ? 2 : 3));
     if (!pool_name || nargs.size() < min_args || nargs.size() > min_args + 1) {
       usage(cerr);
       return 1;
     }
 
-    string oid(nargs[1]);
     if (!omap_key_valid) {
-      omap_key = nargs[2];
+      omap_key = nargs[obj_name ? 1 : 2];
       omap_key_pretty = omap_key;
     }
 
@@ -2813,11 +2872,14 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts,
     if (nargs.size() > min_args) {
       outfile = nargs[min_args];
     }
+    if (!obj_name) {
+       obj_name = nargs[1];
+    }
 
     map<string, bufferlist> values;
-    ret = io_ctx.omap_get_vals_by_keys(oid, keys, &values);
+    ret = io_ctx.omap_get_vals_by_keys(*obj_name, keys, &values);
     if (ret < 0) {
-      cerr << "error getting omap value " << pool_name << "/" << oid << "/"
+      cerr << "error getting omap value " << pool_name << "/" << prettify(*obj_name) << "/"
           << omap_key_pretty << ": " << cpp_strerror(ret) << std::endl;
       return 1;
     } else {
@@ -2835,63 +2897,72 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts,
       }
       ret = 0;
     } else {
-      cout << "No such key: " << pool_name << "/" << oid << "/"
+      cout << "No such key: " << pool_name << "/" << prettify(*obj_name) << "/"
            << omap_key_pretty << std::endl;
       return 1;
     }
   } else if (strcmp(nargs[0], "rmomapkey") == 0) {
-    uint32_t num_args = (omap_key_valid ? 2 : 3);
+    uint32_t num_args = (omap_key_valid ? (obj_name ? 1 : 2)
+                                       : (obj_name ? 2 : 3));
     if (!pool_name || nargs.size() != num_args) {
       usage(cerr);
       return 1;
     }
 
-    string oid(nargs[1]);
     if (!omap_key_valid) {
-      omap_key = nargs[2];
+      omap_key = nargs[obj_name ? 1 : 2];
       omap_key_pretty = omap_key;
     }
+    if (!obj_name) {
+      obj_name = nargs[1];
+    }
     set<string> keys;
     keys.insert(omap_key);
 
-    ret = io_ctx.omap_rm_keys(oid, keys);
+    ret = io_ctx.omap_rm_keys(*obj_name, keys);
     if (ret < 0) {
-      cerr << "error removing omap key " << pool_name << "/" << oid << "/"
+      cerr << "error removing omap key " << pool_name << "/" << prettify(*obj_name) << "/"
           << omap_key_pretty << ": " << cpp_strerror(ret) << std::endl;
       return 1;
     } else {
       ret = 0;
     }
   } else if (strcmp(nargs[0], "clearomap") == 0) {
-    if (!pool_name || nargs.size() < 2) {
+    if (!pool_name || (nargs.size() < 2 && !obj_name)) {
       usage(cerr);
       return 1;
     }
+    // strip nargs[0] which is "clearomap"
+    std::vector<std::string> oids(std::next(std::begin(nargs)),
+                                  std::end(nargs));
+    if (obj_name) {
+      oids.push_back(*obj_name);
+    }
 
-    for (unsigned i=1; i < nargs.size(); i++){
-      string oid(nargs[i]);
+    for (const auto& oid : oids) {
       ret = io_ctx.omap_clear(oid);
       if (ret < 0) {
-        cerr << "error clearing omap keys " << pool_name << "/" << oid << "/"
+        cerr << "error clearing omap keys " << pool_name << "/" << prettify(*obj_name) << "/"
              << cpp_strerror(ret) << std::endl;
         return 1;
       }
     }
     ret = 0;
   } else if (strcmp(nargs[0], "listomapvals") == 0) {
-    if (!pool_name || nargs.size() < 2) {
+    if (!pool_name || (nargs.size() < 2 && !obj_name)) {
       usage(cerr);
       return 1;
     }
-
-    string oid(nargs[1]);
+    if (!obj_name) {
+      obj_name = nargs[1];
+    }
     string last_read = "";
     int MAX_READ = 512;
     do {
       map<string, bufferlist> values;
-      ret = io_ctx.omap_get_vals(oid, last_read, MAX_READ, &values);
+      ret = io_ctx.omap_get_vals(*obj_name, last_read, MAX_READ, &values);
       if (ret < 0) {
-       cerr << "error getting omap keys " << pool_name << "/" << oid << ": "
+       cerr << "error getting omap keys " << pool_name << "/" << prettify(*obj_name) << ": "
             << cpp_strerror(ret) << std::endl;
        return 1;
       }
@@ -2918,6 +2989,7 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts,
     ret = 0;
   }
   else if (strcmp(nargs[0], "cp") == 0) {
+    // XXX: binary names aren't supported for this operation
     if (!pool_name) {
       usage(cerr);
       return 1;
@@ -2964,38 +3036,42 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts,
       return 1;
     }
   } else if (strcmp(nargs[0], "rm") == 0) {
-    if (!pool_name || nargs.size() < 2) {
+    if (!pool_name || (nargs.size() < 2 && !obj_name)) {
       usage(cerr);
       return 1;
     }
-    vector<const char *>::iterator iter = nargs.begin();
-    ++iter;
-    for (; iter != nargs.end(); ++iter) {
-      const string & oid = *iter;
-
-    if (forcefull) {
-        ret = detail::remove(io_ctx, oid, (CEPH_OSD_FLAG_FULL_FORCE |
-                             CEPH_OSD_FLAG_FULL_TRY), use_striper);
-    } else {
-        ret = detail::remove(io_ctx, oid, use_striper);
+    // strip nargs[0] which is "rm"
+    std::vector<std::string> oids(std::next(std::begin(nargs)),
+                                  std::end(nargs));
+    if (obj_name) {
+      oids.push_back(*obj_name);
     }
+    for (const auto& oid : oids) {
+      if (forcefull) {
+          ret = detail::remove(io_ctx, oid, (CEPH_OSD_FLAG_FULL_FORCE |
+                               CEPH_OSD_FLAG_FULL_TRY), use_striper);
+      } else {
+          ret = detail::remove(io_ctx, oid, use_striper);
+      }
 
-    if (ret < 0) {
-        string name = (nspace.size() ? nspace + "/" : "" ) + oid;
-        cerr << "error removing " << pool_name << ">" << name << ": " << cpp_strerror(ret) << std::endl;
-        return 1;
+      if (ret < 0) {
+          string name = (nspace.size() ? nspace + "/" : "" ) + prettify(oid);
+          cerr << "error removing " << pool_name << ">" << name << ": " << cpp_strerror(ret) << std::endl;
+          return 1;
       }
     }
   }
   else if (strcmp(nargs[0], "create") == 0) {
-    if (!pool_name || nargs.size() < 2) {
+    if (!pool_name || (nargs.size() < 2 && !obj_name)) {
       usage(cerr);
       return 1;
     }
-    string oid(nargs[1]);
-    ret = io_ctx.create(oid, true);
+    if (!obj_name) {
+      obj_name = nargs[1];
+    }
+    ret = io_ctx.create(*obj_name, true);
     if (ret < 0) {
-      cerr << "error creating " << pool_name << "/" << oid << ": " << cpp_strerror(ret) << std::endl;
+      cerr << "error creating " << pool_name << "/" << prettify(*obj_name) << ": " << cpp_strerror(ret) << std::endl;
       return 1;
     }
   }
@@ -3288,27 +3364,30 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts,
       }
     }
   } else if (strcmp(nargs[0], "set-alloc-hint") == 0) {
-    if (!pool_name || nargs.size() < 4) {
+    // cmd, [oid, ] obj_size, write_size
+    if (!pool_name || nargs.size() < (obj_name ? 3 : 4)) {
       usage(cerr);
       return 1;
     }
     string err;
-    string oid(nargs[1]);
-    uint64_t expected_object_size = strict_strtoll(nargs[2], 10, &err);
+    uint64_t expected_object_size = strict_strtoll(nargs[obj_name ? 1 : 2], 10, &err);
     if (!err.empty()) {
       cerr << "couldn't parse expected_object_size: " << err << std::endl;
       usage(cerr);
       return 1;
     }
-    uint64_t expected_write_size = strict_strtoll(nargs[3], 10, &err);
+    uint64_t expected_write_size = strict_strtoll(nargs[obj_name ? 2 : 3], 10, &err);
     if (!err.empty()) {
       cerr << "couldn't parse expected_write_size: " << err << std::endl;
       usage(cerr);
       return 1;
     }
-    ret = io_ctx.set_alloc_hint(oid, expected_object_size, expected_write_size);
+    if (!obj_name) {
+      obj_name = nargs[1];
+    }
+    ret = io_ctx.set_alloc_hint(*obj_name, expected_object_size, expected_write_size);
     if (ret < 0) {
-      cerr << "error setting alloc-hint " << pool_name << "/" << oid << ": "
+      cerr << "error setting alloc-hint " << pool_name << "/" << prettify(*obj_name) << ": "
            << cpp_strerror(ret) << std::endl;
       return 1;
     }
@@ -3353,16 +3432,18 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts,
     lg.run();
     lg.cleanup();
   } else if (strcmp(nargs[0], "listomapkeys") == 0) {
-    if (!pool_name || nargs.size() < 2) {
+    if (!pool_name || (nargs.size() < 2 && !obj_name)) {
       usage(cerr);
       return 1;
     }
-
+    if (!obj_name) {
+      obj_name = nargs[1];
+    }
     set<string> out_keys;
-    ret = io_ctx.omap_get_keys(nargs[1], "", LONG_MAX, &out_keys);
+    ret = io_ctx.omap_get_keys(*obj_name, "", LONG_MAX, &out_keys);
     if (ret < 0) {
       cerr << "error getting omap key set " << pool_name << "/"
-          << nargs[1] << ": "  << cpp_strerror(ret) << std::endl;
+          << prettify(*obj_name) << ": "  << cpp_strerror(ret) << std::endl;
       return 1;
     }
 
@@ -3401,18 +3482,19 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts,
       cout << "watcher=" << i->addr << " client." << i->watcher_id << " cookie=" << i->cookie << std::endl;
     }
   } else if (strcmp(nargs[0], "listsnaps") == 0) {
-    if (!pool_name || nargs.size() < 2) {
+    if (!pool_name || (nargs.size() < 2 && !obj_name)) {
       usage(cerr);
       return 1;
     }
+    if (!obj_name) {
+       obj_name = nargs[1];
+    }
 
-    string oid(nargs[1]);
     snap_set_t ls;
-
     io_ctx.snap_set_read(LIBRADOS_SNAP_DIR);
-    ret = io_ctx.list_snaps(oid, &ls);
+    ret = io_ctx.list_snaps(*obj_name, &ls);
     if (ret < 0) {
-      cerr << "error listing snap shots " << pool_name << "/" << oid << ": " << cpp_strerror(ret) << std::endl;
+      cerr << "error listing snap shots " << pool_name << "/" << prettify(*obj_name) << ": " << cpp_strerror(ret) << std::endl;
       return 1;
     }
     else
@@ -3433,10 +3515,10 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts,
 
     if (formatter) {
       formatter->open_object_section("object");
-      formatter->dump_string("name", oid);
+      formatter->dump_string("name", *obj_name);
       formatter->open_array_section("clones");
     } else {
-      cout << oid << ":" << std::endl;
+      cout << prettify(*obj_name) << ":" << std::endl;
       cout << "cloneid snaps   size    overlap" << std::endl;
     }
 
@@ -3542,17 +3624,19 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts,
     }
     ret = do_get_inconsistent_cmd<inconsistent_snapset_t>(nargs, rados, *formatter);
   } else if (strcmp(nargs[0], "cache-flush") == 0) {
-    if (!pool_name || nargs.size() < 2) {
+    if (!pool_name || (nargs.size() < 2 && !obj_name)) {
       usage(cerr);
       return 1;
     }
-    string oid(nargs[1]);
+    if (!obj_name) {
+      obj_name = nargs[1];
+    }
     if (with_clones) {
       snap_set_t ls;
       io_ctx.snap_set_read(LIBRADOS_SNAP_DIR);
-      ret = io_ctx.list_snaps(oid, &ls);
+      ret = io_ctx.list_snaps(*obj_name, &ls);
       if (ret < 0) {
-        cerr << "error listing snapshots " << pool_name << "/" << oid << ": "
+        cerr << "error listing snapshots " << pool_name << "/" << prettify(*obj_name) << ": "
              << cpp_strerror(ret) << std::endl;
         return 1;
       }
@@ -3561,33 +3645,35 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts,
         if (snapid != CEPH_NOSNAP && ci->cloneid > snapid)
           break;
         io_ctx.snap_set_read(ci->cloneid);
-        ret = do_cache_flush(io_ctx, oid);
+        ret = do_cache_flush(io_ctx, *obj_name);
         if (ret < 0) {
-          cerr << "error from cache-flush " << oid << ": "
+          cerr << "error from cache-flush " << prettify(*obj_name) << ": "
                << cpp_strerror(ret) << std::endl;
           return 1;
         }
       }
     } else {
-      ret = do_cache_flush(io_ctx, oid);
+      ret = do_cache_flush(io_ctx, *obj_name);
       if (ret < 0) {
-        cerr << "error from cache-flush " << oid << ": "
+        cerr << "error from cache-flush " << prettify(*obj_name) << ": "
             << cpp_strerror(ret) << std::endl;
         return 1;
       }
     }
   } else if (strcmp(nargs[0], "cache-try-flush") == 0) {
-    if (!pool_name || nargs.size() < 2) {
+    if (!pool_name || (nargs.size() < 2 && !obj_name)) {
       usage(cerr);
       return 1;
     }
-    string oid(nargs[1]);
+    if (!obj_name) {
+      obj_name = nargs[1];
+    }
     if (with_clones) {
       snap_set_t ls;
       io_ctx.snap_set_read(LIBRADOS_SNAP_DIR);
-      ret = io_ctx.list_snaps(oid, &ls);
+      ret = io_ctx.list_snaps(*obj_name, &ls);
       if (ret < 0) {
-        cerr << "error listing snapshots " << pool_name << "/" << oid << ": "
+        cerr << "error listing snapshots " << pool_name << "/" << prettify(*obj_name) << ": "
              << cpp_strerror(ret) << std::endl;
         return 1;
       }
@@ -3596,33 +3682,35 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts,
         if (snapid != CEPH_NOSNAP && ci->cloneid > snapid)
           break;
         io_ctx.snap_set_read(ci->cloneid);
-        ret = do_cache_try_flush(io_ctx, oid);
+        ret = do_cache_try_flush(io_ctx, *obj_name);
         if (ret < 0) {
-          cerr << "error from cache-flush " << oid << ": "
+          cerr << "error from cache-flush " << prettify(*obj_name) << ": "
                << cpp_strerror(ret) << std::endl;
           return 1;
         }
       }
     } else {
-      ret = do_cache_try_flush(io_ctx, oid);
+      ret = do_cache_try_flush(io_ctx, *obj_name);
       if (ret < 0) {
-        cerr << "error from cache-flush " << oid << ": "
+        cerr << "error from cache-flush " << prettify(*obj_name) << ": "
              << cpp_strerror(ret) << std::endl;
         return 1;
       }
     }
   } else if (strcmp(nargs[0], "cache-evict") == 0) {
-    if (!pool_name || nargs.size() < 2) {
+    if (!pool_name || (nargs.size() < 2 && !obj_name)) {
       usage(cerr);
       return 1;
     }
-    string oid(nargs[1]);
+    if (!obj_name) {
+      obj_name = nargs[1];
+    }
     if (with_clones) {
       snap_set_t ls;
       io_ctx.snap_set_read(LIBRADOS_SNAP_DIR);
-      ret = io_ctx.list_snaps(oid, &ls);
+      ret = io_ctx.list_snaps(*obj_name, &ls);
       if (ret < 0) {
-        cerr << "error listing snapshots " << pool_name << "/" << oid << ": "
+        cerr << "error listing snapshots " << pool_name << "/" << prettify(*obj_name) << ": "
              << cpp_strerror(ret) << std::endl;
         return 1;
       }
@@ -3631,17 +3719,17 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts,
         if (snapid != CEPH_NOSNAP && ci->cloneid > snapid)
           break;
         io_ctx.snap_set_read(ci->cloneid);
-        ret = do_cache_evict(io_ctx, oid);
+        ret = do_cache_evict(io_ctx, *obj_name);
         if (ret < 0) {
-          cerr << "error from cache-flush " << oid << ": "
+          cerr << "error from cache-flush " << prettify(*obj_name) << ": "
                << cpp_strerror(ret) << std::endl;
           return 1;
         }
       }
     } else {
-      ret = do_cache_evict(io_ctx, oid);
+      ret = do_cache_evict(io_ctx, *obj_name);
       if (ret < 0) {
-        cerr << "error from cache-flush " << oid << ": "
+        cerr << "error from cache-flush " << prettify(*obj_name) << ": "
              << cpp_strerror(ret) << std::endl;
         return 1;
       }
@@ -3760,32 +3848,34 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts,
       return 1;
     }
   } else if (strcmp(nargs[0], "tier-promote") == 0) {
-    if (!pool_name || nargs.size() < 2) {
+    if (!pool_name || (nargs.size() < 2 && !obj_name)) {
       usage(cerr);
       return 1;
     }
-    string oid(nargs[1]);
-
+    if (!obj_name) {
+      obj_name = nargs[1];
+    }
     ObjectWriteOperation op;
     op.tier_promote();
-    ret = io_ctx.operate(oid, &op);
+    ret = io_ctx.operate(*obj_name, &op);
     if (ret < 0) {
-      cerr << "error tier-promote " << pool_name << "/" << oid << " : " 
+      cerr << "error tier-promote " << pool_name << "/" << prettify(*obj_name) << " : "
           << cpp_strerror(ret) << std::endl;
       return 1;
     }
   } else if (strcmp(nargs[0], "unset-manifest") == 0) {
-    if (!pool_name || nargs.size() < 2) {
+    if (!pool_name || (nargs.size() < 2 && !obj_name)) {
       usage(cerr);
       return 1;
     }
-    string oid(nargs[1]);
-
+    if (!obj_name) {
+      obj_name = nargs[1];
+    }
     ObjectWriteOperation op;
     op.unset_manifest();
-    ret = io_ctx.operate(oid, &op);
+    ret = io_ctx.operate(*obj_name, &op);
     if (ret < 0) {
-      cerr << "error unset-manifest " << pool_name << "/" << oid << " : " 
+      cerr << "error unset-manifest " << pool_name << "/" << prettify(*obj_name) << " : "
           << cpp_strerror(ret) << std::endl;
       return 1;
     }
@@ -4035,6 +4125,8 @@ int main(int argc, const char **argv)
       opts["with-clones"] = "true";
     } else if (ceph_argparse_witharg(args, i, &val, "--omap-key-file", (char*)NULL)) {
       opts["omap-key-file"] = val;
+    } else if (ceph_argparse_witharg(args, i, &val, "--obj-name-file", (char*)NULL)) {
+      opts["obj-name-file"] = val;
     } else if (ceph_argparse_flag(args, i, "--with-reference", (char*)NULL)) {
       opts["with-reference"] = "true";
     } else if (ceph_argparse_witharg(args, i, &val, "--pgid", (char*)NULL)) {