]> git.apps.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>
Tue, 9 Mar 2021 17:07:27 +0000 (17:07 +0000)
Signed-off-by: Radoslaw Zarzynski <rzarzyns@redhat.com>
(cherry picked from commit d333b35aa10bf03a8bc047994d5cf3fed019b49a)

src/tools/rados/rados.cc

index db5dcf2177638f2330d480c0738d009298524876..15b0cad0439599bb14707d9dc62165ac6c23b477 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"
@@ -187,6 +188,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"
@@ -463,10 +466,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;
@@ -559,11 +560,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, bool create_object,
             const bool use_striper)
 {
-  string oid(objname);
   bool stdio = (strcmp(infile, "-") == 0);
   int ret = 0;
   int fd = STDIN_FILENO;
@@ -621,10 +621,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;
@@ -1838,6 +1837,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;
+  }
+}
+
 /**********************************************
 
 **********************************************/
@@ -1891,6 +1900,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;
   std::string input_file;
   bool with_reference = false;
 
@@ -2112,6 +2122,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)) {
@@ -2491,15 +2512,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;
@@ -2508,117 +2531,148 @@ 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;
     }
+    const char* in_filename;
+    if (obj_name) {
+      in_filename = nargs[1];
+    } else {
+      obj_name = nargs[1];
+      in_filename = nargs[2];
+    }
     bool create_object = !obj_offset_specified;
-    ret = do_put(io_ctx, nargs[1], nargs[2], op_size, obj_offset, create_object, use_striper);
+    ret = do_put(io_ctx, *obj_name, in_filename, op_size, obj_offset, create_object, 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;
@@ -2630,27 +2684,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 {
@@ -2659,30 +2712,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
@@ -2690,34 +2746,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;
     }
 
@@ -2726,21 +2784,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 {
@@ -2755,20 +2813,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 {
@@ -2819,15 +2878,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;
     }
 
@@ -2838,11 +2897,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 {
@@ -2860,62 +2922,71 @@ 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 = "";
     do {
       map<string, bufferlist> values;
-      ret = io_ctx.omap_get_vals(oid, last_read, MAX_OMAP_BYTES_PER_REQUEST, &values);
+      ret = io_ctx.omap_get_vals(*obj_name, last_read, MAX_OMAP_BYTES_PER_REQUEST, &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;
       }
@@ -2942,6 +3013,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;
@@ -2988,38 +3060,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;
     }
   }
@@ -3312,27 +3388,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;
     }
@@ -3377,19 +3456,21 @@ 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];
+    }
     string last_read;
     bool more = true;
     do {
       set<string> out_keys;
-      ret = io_ctx.omap_get_keys2(nargs[1], last_read, MAX_OMAP_BYTES_PER_REQUEST, &out_keys, &more);
+      ret = io_ctx.omap_get_keys2(*obj_name, last_read, MAX_OMAP_BYTES_PER_REQUEST, &out_keys, &more);
       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;
       }
 
@@ -3429,18 +3510,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
@@ -3461,10 +3543,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;
     }
 
@@ -3570,17 +3652,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;
       }
@@ -3589,33 +3673,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;
       }
@@ -3624,33 +3710,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;
       }
@@ -3659,17 +3747,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;
       }
@@ -3784,47 +3872,50 @@ 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;
     }
   } else if (strcmp(nargs[0], "tier-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];
+    }
     ObjectReadOperation op;
     op.tier_flush();
     librados::AioCompletion *completion =
       librados::Rados::aio_create_completion();
-    io_ctx.aio_operate(oid.c_str(), completion, &op,
+    io_ctx.aio_operate(*obj_name, completion, &op,
                       librados::OPERATION_IGNORE_CACHE |
                       librados::OPERATION_IGNORE_OVERLAY,
                       NULL);
@@ -3832,22 +3923,23 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts,
     ret = completion->get_return_value();
     completion->release();
     if (ret < 0) {
-      cerr << "error tier-flush " << pool_name << "/" << oid << " : " 
+      cerr << "error tier-flush " << pool_name << "/" << prettify(*obj_name) << " : "
           << cpp_strerror(ret) << std::endl;
       return 1;
     }
   } else if (strcmp(nargs[0], "tier-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];
+    }
     ObjectReadOperation op;
     op.tier_evict();
     librados::AioCompletion *completion =
       librados::Rados::aio_create_completion();
-    io_ctx.aio_operate(oid.c_str(), completion, &op,
+    io_ctx.aio_operate(*obj_name, completion, &op,
                       librados::OPERATION_IGNORE_CACHE |
                       librados::OPERATION_IGNORE_OVERLAY,
                       NULL);
@@ -3855,7 +3947,7 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts,
     ret = completion->get_return_value();
     completion->release();
     if (ret < 0) {
-      cerr << "error tier-evict " << pool_name << "/" << oid << " : " 
+      cerr << "error tier-evict " << pool_name << "/" << prettify(*obj_name) << " : "
           << cpp_strerror(ret) << std::endl;
       return 1;
     }
@@ -4105,6 +4197,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)) {