summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSage Weil <sage@inktank.com>2013-01-20 21:53:37 -0800
committerSage Weil <sage@inktank.com>2013-02-20 17:09:49 -0800
commit5551aa5b3b5c2e9e7006476b9cd8cc181d2c9a04 (patch)
treeb9797460d5a143ae52fe4c5a93185ea11aeeebd5
parentb531aa3688d9e8831837c23abac0bdaba04ec793 (diff)
downloadceph-5551aa5b3b5c2e9e7006476b9cd8cc181d2c9a04.tar.gz
mds: parse ceph.*.layout vxattr key/value content
Use qi to parse a strictly formatted set of key/value pairs. Be picky about whitespace. Any subset of recognized keys is allowed. Parse the same set of keys as the ceph.*.layout.* vxattrs. Signed-off-by: Sage Weil <sage@inktank.com>
-rwxr-xr-xqa/workunits/misc/layout_vxattrs.sh17
-rw-r--r--src/mds/Server.cc41
2 files changed, 57 insertions, 1 deletions
diff --git a/qa/workunits/misc/layout_vxattrs.sh b/qa/workunits/misc/layout_vxattrs.sh
index d181e03212c..e6c7c65212a 100755
--- a/qa/workunits/misc/layout_vxattrs.sh
+++ b/qa/workunits/misc/layout_vxattrs.sh
@@ -32,6 +32,18 @@ getfattr -n ceph.file.layout.stripe_unit file2 | grep -q 1048576
getfattr -n ceph.file.layout.stripe_count file2 | grep -q 8
getfattr -n ceph.file.layout.object_size file2 | grep -q 10485760
+setfattr -n ceph.file.layout -v "stripe_unit=4194304 stripe_count=16 object_size=41943040 pool=data" file2
+getfattr -n ceph.file.layout.stripe_unit file2 | grep -q 4194304
+getfattr -n ceph.file.layout.stripe_count file2 | grep -q 16
+getfattr -n ceph.file.layout.object_size file2 | grep -q 41943040
+getfattr -n ceph.file.layout.pool file2 | grep -q data
+
+setfattr -n ceph.file.layout -v "stripe_unit=1048576" file2
+getfattr -n ceph.file.layout.stripe_unit file2 | grep -q 1048576
+getfattr -n ceph.file.layout.stripe_count file2 | grep -q 16
+getfattr -n ceph.file.layout.object_size file2 | grep -q 41943040
+getfattr -n ceph.file.layout.pool file2 | grep -q data
+
# dir
rm -f dir/file || true
rmdir dir || true
@@ -55,6 +67,11 @@ getfattr -n ceph.dir.layout.stripe_unit dir | grep -q 1048576
getfattr -n ceph.dir.layout.stripe_count dir | grep -q 8
getfattr -n ceph.dir.layout.object_size dir | grep -q 10485760
+setfattr -n ceph.file.layout -v "stripe_count=16" file2
+getfattr -n ceph.file.layout.stripe_count file2 | grep -q 16
+setfattr -n ceph.file.layout -v "object_size=10485760 stripe_count=8 stripe_unit=1048576 pool=data" file2
+getfattr -n ceph.file.layout.stripe_count file2 | grep -q 8
+
touch dir/file
getfattr -n ceph.file.layout.pool dir/file | grep -q data
getfattr -n ceph.file.layout.stripe_unit dir/file | grep -q 1048576
diff --git a/src/mds/Server.cc b/src/mds/Server.cc
index ac51e60d0a9..20372947f5f 100644
--- a/src/mds/Server.cc
+++ b/src/mds/Server.cc
@@ -15,6 +15,10 @@
#include <boost/lexical_cast.hpp>
#include "include/assert.h" // lexical_cast includes system assert.h
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/fusion/include/std_pair.hpp>
+
#include "MDS.h"
#include "Server.h"
#include "Locker.h"
@@ -3512,12 +3516,47 @@ void Server::handle_client_setdirlayout(MDRequest *mdr)
// XATTRS
+// parse a map of keys/values.
+namespace qi = boost::spirit::qi;
+
+template <typename Iterator>
+struct keys_and_values
+ : qi::grammar<Iterator, std::map<string, string>()>
+{
+ keys_and_values()
+ : keys_and_values::base_type(query)
+ {
+ query = pair >> *(qi::lit(' ') >> pair);
+ pair = key >> '=' >> value;
+ key = qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z_0-9");
+ value = +qi::char_("a-zA-Z_0-9");
+ }
+ qi::rule<Iterator, std::map<string, string>()> query;
+ qi::rule<Iterator, std::pair<string, string>()> pair;
+ qi::rule<Iterator, string()> key, value;
+};
+
int Server::parse_layout_vxattr(string name, string value, ceph_file_layout *layout)
{
dout(20) << "parse_layout_vxattr name " << name << " value '" << value << "'" << dendl;
try {
if (name == "layout") {
- // XXX implement me
+ string::iterator begin = value.begin();
+ string::iterator end = value.end();
+ keys_and_values<string::iterator> p; // create instance of parser
+ std::map<string, string> m; // map to receive results
+ if (!qi::parse(begin, end, p, m)) { // returns true if successful
+ return -EINVAL;
+ }
+ string left(begin, end);
+ dout(10) << " parsed " << m << " left '" << left << "'" << dendl;
+ if (begin != end)
+ return -EINVAL;
+ for (map<string,string>::iterator q = m.begin(); q != m.end(); ++q) {
+ int r = parse_layout_vxattr(string("layout.") + q->first, q->second, layout);
+ if (r < 0)
+ return r;
+ }
} else if (name == "layout.object_size") {
layout->fl_object_size = boost::lexical_cast<unsigned>(value);
} else if (name == "layout.stripe_unit") {