From 80441cda8c49f1f3ec2c75a03d844335a4d746dc Mon Sep 17 00:00:00 2001 From: John Spray Date: Mon, 15 Sep 2014 20:47:18 +0100 Subject: [PATCH] mon: prevent cache pools being used CephFS Fixes two things: * EC pools are now permissible if they have a cache overlay * Pools are not permissible if they are a cache tier. Fixes: #9435 Signed-off-by: John Spray --- qa/workunits/cephtool/test.sh | 35 ++++++++++++++++- src/mon/MDSMonitor.cc | 74 ++++++++++++++++++++++------------- src/mon/MDSMonitor.h | 2 + 3 files changed, 83 insertions(+), 28 deletions(-) diff --git a/qa/workunits/cephtool/test.sh b/qa/workunits/cephtool/test.sh index 97b2b3d3c4ebd..fa2002316cb03 100755 --- a/qa/workunits/cephtool/test.sh +++ b/qa/workunits/cephtool/test.sh @@ -414,7 +414,7 @@ function test_mon_mds() expect_false ceph mds set allow_new_snaps taco # we should never be able to add EC pools as data or metadata pools - # create an ec-pool + # create an ec-pool... ceph osd pool create mds-ec-pool 10 10 erasure set +e ceph mds add_data_pool mds-ec-pool 2>$TMPFILE @@ -441,6 +441,39 @@ function test_mon_mds() ceph fs new cephfs mds-ec-pool mds-ec-pool 2>$TMPFILE check_response 'erasure-code' $? 22 set -e + + # ... however if we create a cache tier in front of the EC pool, we should + # be permitted to use it... + ceph osd pool create mds-tier 2 + ceph osd tier add mds-ec-pool mds-tier + ceph osd tier set-overlay mds-ec-pool mds-tier + ceph osd tier cache-mode mds-tier writeback + tier_poolnum=$(ceph osd dump | grep "pool.* 'mds-tier" | awk '{print $2;}') + + set -e + ceph fs new cephfs fs_metadata mds-ec-pool + ceph fs rm cephfs --yes-i-really-mean-it + + # ... but we should be forbidden from using the cache pool in the FS directly. + set +e + ceph mds newfs $metadata_poolnum $tier_poolnum --yes-i-really-mean-it 2>$TMPFILE + check_response 'in use as a cache tier' $? 22 + ceph mds newfs $tier_poolnum $data_poolnum --yes-i-really-mean-it 2>$TMPFILE + check_response 'in use as a cache tier' $? 22 + ceph mds newfs $tier_poolnum $tier_poolnum --yes-i-really-mean-it 2>$TMPFILE + check_response 'in use as a cache tier' $? 22 + ceph fs new cephfs fs_metadata mds-tier 2>$TMPFILE + check_response 'in use as a cache tier' $? 22 + ceph fs new cephfs mds-tier fs_data 2>$TMPFILE + check_response 'in use as a cache tier' $? 22 + ceph fs new cephfs mds-tier mds-tier 2>$TMPFILE + check_response 'in use as a cache tier' $? 22 + set -e + + # Clean up tier + EC pools + ceph osd tier remove-overlay mds-ec-pool + ceph osd tier remove mds-ec-pool mds-tier + ceph osd pool delete mds-tier mds-tier --yes-i-really-really-mean-it ceph osd pool delete mds-ec-pool mds-ec-pool --yes-i-really-really-mean-it ceph mds stat diff --git a/src/mon/MDSMonitor.cc b/src/mon/MDSMonitor.cc index 520eb6947c97e..34216ea1d0603 100644 --- a/src/mon/MDSMonitor.cc +++ b/src/mon/MDSMonitor.cc @@ -958,6 +958,45 @@ bool MDSMonitor::prepare_command(MMonCommand *m) } +/** + * Return 0 if the pool is suitable for use with CephFS, or + * in case of errors return a negative error code, and populate + * the passed stringstream with an explanation. + */ +int MDSMonitor::_check_pool( + const int64_t pool_id, + std::stringstream *ss) const +{ + assert(ss != NULL); + + const pg_pool_t *pool = mon->osdmon()->osdmap.get_pg_pool(pool_id); + if (!pool) { + *ss << "pool id '" << pool_id << "' does not exist"; + return -ENOENT; + } + + const string& pool_name = mon->osdmon()->osdmap.get_pool_name(pool_id); + + if (pool->is_erasure()) { + // EC pools are only acceptable with a cache tier overlay + if (!pool->has_tiers() || !pool->has_read_tier() || !pool->has_write_tier()) { + *ss << "pool '" << pool_name << "' (id '" << pool_id << "')" + << " is an erasure-code pool"; + return -EINVAL; + } + } + + if (pool->is_tier()) { + *ss << " pool '" << pool_name << "' (id '" << pool_id + << "') is already in use as a cache tier."; + return -EINVAL; + } + + // Nothing special about this pool, so it is permissible + return 0; +} + + /** * Handle a command for creating or removing a filesystem. * @@ -990,30 +1029,13 @@ bool MDSMonitor::management_command( return true; } - // Check that the requested pools exist - const pg_pool_t *p = mon->osdmon()->osdmap.get_pg_pool(data); - if (!p) { - ss << "pool id '" << data << "' does not exist"; - r = -ENOENT; - return true; - } else if (p->is_erasure()) { - const string& pn = mon->osdmon()->osdmap.get_pool_name(data); - ss << "pool '" << pn << "' (id '" << data << "')" - << " is an erasure-code pool"; - r = -EINVAL; + r = _check_pool(data, &ss); + if (r) { return true; } - p = mon->osdmon()->osdmap.get_pg_pool(metadata); - if (!p) { - ss << "pool id '" << metadata << "' does not exist"; - r = -ENOENT; - return true; - } else if (p->is_erasure()) { - const string& pn = mon->osdmon()->osdmap.get_pool_name(metadata); - ss << "pool '" << pn << "' (id '" << metadata << "')" - << " is an erasure-code pool"; - r = -EINVAL; + r = _check_pool(metadata, &ss); + if (r) { return true; } @@ -1100,15 +1122,13 @@ bool MDSMonitor::management_command( request_proposal(mon->osdmon()); } - if (data_pool->is_erasure()) { - ss << "data pool '" << data_name << " is an erasure-code pool"; - r = -EINVAL; + r = _check_pool(data, &ss); + if (r) { return true; } - if (metadata_pool->is_erasure()) { - ss << "metadata pool '" << metadata_name << " is an erasure-code pool"; - r = -EINVAL; + r = _check_pool(metadata, &ss); + if (r) { return true; } diff --git a/src/mon/MDSMonitor.h b/src/mon/MDSMonitor.h index 0343c3247f892..305730fe605ed 100644 --- a/src/mon/MDSMonitor.h +++ b/src/mon/MDSMonitor.h @@ -139,6 +139,8 @@ private: // MDS daemon GID to latest health state from that GID std::map pending_daemon_health; std::set pending_daemon_health_rm; + + int _check_pool(const int64_t pool_id, std::stringstream *ss) const; }; #endif -- 2.39.5