From: Sebastien Ponce Date: Thu, 29 Jan 2015 03:51:37 +0000 (+0100) Subject: rados: Added --striper option to the command line X-Git-Tag: v9.0.3~100^2~4 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=49ab5bb3c436fbe069327859c76b351c4fe06043;p=ceph.git rados: Added --striper option to the command line Fixes: #10759 the new --striper option allows to use the striping API provided by libradosstriper. Signed-off-by: Sebastien Ponce --- diff --git a/doc/man/8/rados.rst b/doc/man/8/rados.rst index 6dec6ca807736..ce8a8032a95a3 100644 --- a/doc/man/8/rados.rst +++ b/doc/man/8/rados.rst @@ -57,6 +57,11 @@ Options Set the block size for put/get ops and for write benchmarking. +.. option:: --striper + + Uses the striping API of rados rather than the default one. + Available for stat, get, put, truncate, rm, ls and all xattr related operation + Global commands =============== diff --git a/src/test/Makefile.am b/src/test/Makefile.am index 9d56f055b9869..3c8d630feb218 100644 --- a/src/test/Makefile.am +++ b/src/test/Makefile.am @@ -79,7 +79,8 @@ check_SCRIPTS += \ test/osd/osd-config.sh \ test/osd/osd-bench.sh \ test/osd/osd-copy-from.sh \ - test/mon/mon-handle-forward.sh + test/mon/mon-handle-forward.sh \ + test/libradosstriper/rados-striper.sh if ENABLE_ROOT_MAKE_CHECK check_SCRIPTS += test/ceph-disk-root.sh diff --git a/src/test/libradosstriper/rados-striper.sh b/src/test/libradosstriper/rados-striper.sh new file mode 100755 index 0000000000000..b6820271bac95 --- /dev/null +++ b/src/test/libradosstriper/rados-striper.sh @@ -0,0 +1,89 @@ +#!/bin/bash +# +# Copyright (C) 2014 Red Hat +# +# Author: Sebastien Ponce +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Library Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Library Public License for more details. +# +source test/ceph-helpers.sh + +function run() { + local dir=$1 + shift + + export CEPH_MON="127.0.0.1:7112" + export CEPH_ARGS + CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none " + CEPH_ARGS+="--mon-host=$CEPH_MON " + + # create a cluster with one monitor and three osds + run_mon $dir a || return 1 + run_osd $dir 0 || return 1 + run_osd $dir 1 || return 1 + run_osd $dir 2 || return 1 + + # create toyfile + dd if=/dev/urandom of=$dir/toyfile bs=1234 count=1 + + # put a striped object + rados --pool rbd --striper put toyfile $dir/toyfile || return 1 + + # stat it, with and without striping + rados --pool rbd --striper stat toyfile | cut -d ',' -f 2 > $dir/stripedStat || return 1 + rados --pool rbd stat toyfile.0000000000000000 | cut -d ',' -f 2 > $dir/stat || return 1 + echo ' size 1234' > $dir/refstat + diff -w $dir/stripedStat $dir/refstat || return 1 + diff -w $dir/stat $dir/refstat || return 1 + rados --pool rbd stat toyfile >& $dir/staterror + grep -q 'No such file or directory' $dir/staterror || return 1 + + # get the file back with and without striping + rados --pool rbd --striper get toyfile $dir/stripedGroup || return 1 + diff -w $dir/toyfile $dir/stripedGroup || return 1 + rados --pool rbd get toyfile.0000000000000000 $dir/nonSTripedGroup || return 1 + diff -w $dir/toyfile $dir/nonSTripedGroup || return 1 + + # test truncate + rados --pool rbd --striper truncate toyfile 12 + rados --pool rbd --striper stat toyfile | cut -d ',' -f 2 > $dir/stripedStat || return 1 + rados --pool rbd stat toyfile.0000000000000000 | cut -d ',' -f 2 > $dir/stat || return 1 + echo ' size 12' > $dir/reftrunc + diff -w $dir/stripedStat $dir/reftrunc || return 1 + diff -w $dir/stat $dir/reftrunc || return 1 + + # test xattrs + rados --pool rbd --striper setxattr toyfile somexattr somevalue || return 1 + rados --pool rbd --striper getxattr toyfile somexattr > $dir/xattrvalue || return 1 + rados --pool rbd getxattr toyfile.0000000000000000 somexattr > $dir/xattrvalue2 || return 1 + echo 'somevalue' > $dir/refvalue + diff -w $dir/xattrvalue $dir/refvalue || return 1 + diff -w $dir/xattrvalue2 $dir/refvalue || return 1 + rados --pool rbd --striper listxattr toyfile > $dir/xattrlist || return 1 + echo 'somexattr' > $dir/reflist + diff -w $dir/xattrlist $dir/reflist || return 1 + rados --pool rbd listxattr toyfile.0000000000000000 | grep -v striper > $dir/xattrlist2 || return 1 + diff -w $dir/xattrlist2 $dir/reflist || return 1 + rados --pool rbd --striper rmxattr toyfile somexattr || return 1 + rados --pool rbd --striper getxattr toyfile somexattr >& $dir/rmxattrerror + grep -q 'No data available' $dir/rmxattrerror || return 1 + rados --pool rbd getxattr toyfile.0000000000000000 somexattr >& $dir/rmxattrerror2 + grep -q 'No data available' $dir/rmxattrerror2 || return 1 + + # test rm + rados --pool rbd --striper rm toyfile || return 1 + rados --pool rbd --striper stat toyfile >& $dir/staterror2 + grep -q 'No such file or directory' $dir/staterror2 || return 1 + rados --pool rbd stat toyfile.0000000000000000 >& $dir/staterror3 + grep -q 'No such file or directory' $dir/staterror3 || return 1 +} + +main rados-striper "$@" diff --git a/src/tools/Makefile-client.am b/src/tools/Makefile-client.am index 1fb78540e0436..e417eb5fa3336 100644 --- a/src/tools/Makefile-client.am +++ b/src/tools/Makefile-client.am @@ -18,7 +18,7 @@ rados_SOURCES = \ tools/rados/RadosImport.cc \ tools/rados/PoolDump.cc rados_SOURCES += common/obj_bencher.cc # needs cleanup so it can go in libcommon.la -rados_LDADD = libcls_lock_client.la $(LIBRADOS) $(CEPH_GLOBAL) +rados_LDADD = libcls_lock_client.la $(LIBRADOS) $(LIBRADOSSTRIPER) $(CEPH_GLOBAL) bin_PROGRAMS += rados diff --git a/src/tools/rados/rados.cc b/src/tools/rados/rados.cc index d127bf61280b3..f0bb7accf7b3a 100644 --- a/src/tools/rados/rados.cc +++ b/src/tools/rados/rados.cc @@ -16,6 +16,8 @@ #include "include/rados/librados.hpp" #include "include/rados/rados_types.hpp" +#include "include/radosstriper/libradosstriper.hpp" +using namespace libradosstriper; #include "common/config.h" #include "common/ceph_argparse.h" @@ -174,6 +176,10 @@ void usage(ostream& out) " Use with cp to specify the locator of the new object\n" " --target-nspace\n" " Use with cp to specify the namespace of the new object\n" +" --striper\n" +" Use radostriper interface rather than pure rados\n" +" Available for stat, get, put, truncate, rm, ls and \n" +" all xattr related operations\n" "\n" "BENCH OPTIONS:\n" " -t N\n" @@ -243,7 +249,9 @@ 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) +static int do_get(IoCtx& io_ctx, RadosStriper& striper, + const char *objname, const char *outfile, unsigned op_size, + bool use_striper) { string oid(objname); @@ -263,7 +271,11 @@ static int do_get(IoCtx& io_ctx, const char *objname, const char *outfile, unsig int ret; while (true) { bufferlist outdata; - ret = io_ctx.read(oid, outdata, op_size, offset); + if (use_striper) { + ret = striper.read(oid, &outdata, op_size, offset); + } else { + ret = io_ctx.read(oid, outdata, op_size, offset); + } if (ret <= 0) { goto out; } @@ -353,7 +365,9 @@ static int do_copy_pool(Rados& rados, const char *src_pool, const char *target_p return 0; } -static int do_put(IoCtx& io_ctx, const char *objname, const char *infile, int op_size) +static int do_put(IoCtx& io_ctx, RadosStriper& striper, + const char *objname, const char *infile, int op_size, + bool use_striper) { string oid(objname); bufferlist indata; @@ -381,7 +395,11 @@ static int do_put(IoCtx& io_ctx, const char *objname, const char *infile, int op } if (count == 0) { if (!offset) { // in case we have to create an empty object - ret = io_ctx.write_full(oid, indata); // indata is empty + if (use_striper) { + ret = striper.write_full(oid, indata); // indata is empty + } else { + ret = io_ctx.write_full(oid, indata); // indata is empty + } if (ret < 0) { goto out; } @@ -389,10 +407,17 @@ static int do_put(IoCtx& io_ctx, const char *objname, const char *infile, int op continue; } indata.append(buf, count); - if (offset == 0) - ret = io_ctx.write_full(oid, indata); - else - ret = io_ctx.write(oid, indata, count, offset); + if (use_striper) { + if (offset == 0) + ret = striper.write_full(oid, indata); + else + ret = striper.write(oid, indata, count, offset); + } else { + if (offset == 0) + ret = io_ctx.write_full(oid, indata); + else + ret = io_ctx.write(oid, indata, count, offset); + } indata.clear(); if (ret < 0) { @@ -1147,6 +1172,7 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts, bool block_size_specified = false; bool cleanup = true; bool no_verify = false; + bool use_striper = false; const char *snapname = NULL; snap_t snapid = CEPH_NOSNAP; std::map::const_iterator i; @@ -1173,6 +1199,7 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts, Rados rados; IoCtx io_ctx; + RadosStriper striper; i = opts.find("create"); if (i != opts.end()) { @@ -1370,6 +1397,17 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts, if (prev_op_size != default_op_size && prev_op_size != op_size) cerr << "INFO: op_size has been rounded to " << op_size << std::endl; } + + // create striper interface + if (opts.find("striper") != opts.end()) { + ret = RadosStriper::striper_create(io_ctx, &striper); + if (0 != ret) { + cerr << "error opening pool " << pool_name << " with striper interface: " + << cpp_strerror(ret) << std::endl; + goto out; + } + use_striper = true; + } } // snapname? @@ -1535,18 +1573,34 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts, librados::NObjectIterator i = io_ctx.nobjects_begin(); librados::NObjectIterator i_end = io_ctx.nobjects_end(); for (; i != i_end; ++i) { + if (use_striper) { + // in case of --striper option, we only list striped + // objects, so we only display the first object of + // each, without its suffix '.000...000' + size_t l = i->get_oid().length(); + if (l <= 17 || + (0 != i->get_oid().compare(l-17, 17,".0000000000000000"))) continue; + } if (!formatter) { // Only include namespace in output when wildcard specified if (wildcard) *outstream << i->get_nspace() << "\t"; - *outstream << i->get_oid(); + if (use_striper) { + *outstream << i->get_oid().substr(0, i->get_oid().length()-17); + } else { + *outstream << i->get_oid(); + } if (i->get_locator().size()) *outstream << "\t" << i->get_locator(); *outstream << std::endl; } else { formatter->open_object_section("object"); formatter->dump_string("namespace", i->get_nspace()); - formatter->dump_string("name", i->get_oid()); + if (use_striper) { + formatter->dump_string("name", i->get_oid().substr(0, i->get_oid().length()-17)); + } else { + formatter->dump_string("name", i->get_oid()); + } if (i->get_locator().size()) formatter->dump_string("locator", i->get_locator()); formatter->close_section(); //object @@ -1608,7 +1662,11 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts, string oid(nargs[1]); uint64_t size; time_t mtime; - ret = io_ctx.stat(oid, &size, &mtime); + if (use_striper) { + ret = striper.stat(oid, &size, &mtime); + } else { + ret = io_ctx.stat(oid, &size, &mtime); + } if (ret < 0) { cerr << " error stat-ing " << pool_name << "/" << oid << ": " << cpp_strerror(ret) << std::endl; @@ -1622,7 +1680,7 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts, else if (strcmp(nargs[0], "get") == 0) { if (!pool_name || nargs.size() < 3) usage_exit(); - ret = do_get(io_ctx, nargs[1], nargs[2], op_size); + ret = do_get(io_ctx, striper, nargs[1], nargs[2], op_size, use_striper); if (ret < 0) { cerr << "error getting " << pool_name << "/" << nargs[1] << ": " << cpp_strerror(ret) << std::endl; goto out; @@ -1631,7 +1689,7 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts, else if (strcmp(nargs[0], "put") == 0) { if (!pool_name || nargs.size() < 3) usage_exit(); - ret = do_put(io_ctx, nargs[1], nargs[2], op_size); + ret = do_put(io_ctx, striper, nargs[1], nargs[2], op_size, use_striper); if (ret < 0) { cerr << "error putting " << pool_name << "/" << nargs[1] << ": " << cpp_strerror(ret) << std::endl; goto out; @@ -1653,7 +1711,11 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts, cerr << "error, cannot truncate to negative value" << std::endl; usage_exit(); } - ret = io_ctx.trunc(oid, size); + if (use_striper) { + ret = striper.trunc(oid, size); + } else { + ret = io_ctx.trunc(oid, size); + } if (ret < 0) { cerr << "error truncating oid " << oid << " to " << size << ": " @@ -1680,7 +1742,11 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts, } while (ret > 0); } - ret = io_ctx.setxattr(oid, attr_name.c_str(), bl); + if (use_striper) { + ret = striper.setxattr(oid, attr_name.c_str(), bl); + } else { + ret = io_ctx.setxattr(oid, attr_name.c_str(), bl); + } if (ret < 0) { cerr << "error setting xattr " << pool_name << "/" << oid << "/" << attr_name << ": " << cpp_strerror(ret) << std::endl; goto out; @@ -1696,7 +1762,11 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts, string attr_name(nargs[2]); bufferlist bl; - ret = io_ctx.getxattr(oid, attr_name.c_str(), bl); + if (use_striper) { + ret = striper.getxattr(oid, attr_name.c_str(), bl); + } else { + ret = io_ctx.getxattr(oid, attr_name.c_str(), bl); + } if (ret < 0) { cerr << "error getting xattr " << pool_name << "/" << oid << "/" << attr_name << ": " << cpp_strerror(ret) << std::endl; goto out; @@ -1712,7 +1782,11 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts, string oid(nargs[1]); string attr_name(nargs[2]); - ret = io_ctx.rmxattr(oid, attr_name.c_str()); + if (use_striper) { + ret = striper.rmxattr(oid, attr_name.c_str()); + } else { + ret = io_ctx.rmxattr(oid, attr_name.c_str()); + } if (ret < 0) { cerr << "error removing xattr " << pool_name << "/" << oid << "/" << attr_name << ": " << cpp_strerror(ret) << std::endl; goto out; @@ -1724,7 +1798,11 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts, string oid(nargs[1]); map attrset; bufferlist bl; - ret = io_ctx.getxattrs(oid, attrset); + if (use_striper) { + ret = striper.getxattrs(oid, attrset); + } else { + ret = io_ctx.getxattrs(oid, attrset); + } if (ret < 0) { cerr << "error getting xattr set " << pool_name << "/" << oid << ": " << cpp_strerror(ret) << std::endl; goto out; @@ -2003,7 +2081,11 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts, ++iter; for (; iter != nargs.end(); ++iter) { const string & oid = *iter; - ret = io_ctx.remove(oid); + if (use_striper) { + ret = striper.remove(oid); + } else { + ret = io_ctx.remove(oid); + } if (ret < 0) { string name = (nspace.size() ? nspace + "/" : "" ) + oid; cerr << "error removing " << pool_name << ">" << name << ": " << cpp_strerror(ret) << std::endl; @@ -2754,6 +2836,8 @@ int main(int argc, const char **argv) opts["target_locator"] = val; } else if (ceph_argparse_witharg(args, i, &val, "--target-nspace" , (char *)NULL)) { opts["target_nspace"] = val; + } else if (ceph_argparse_flag(args, i, "--striper" , (char *)NULL)) { + opts["striper"] = "true"; } else if (ceph_argparse_witharg(args, i, &val, "-t", "--concurrent-ios", (char*)NULL)) { opts["concurrent-ios"] = val; } else if (ceph_argparse_witharg(args, i, &val, "--block-size", (char*)NULL)) {