-v0.69
+v0.70
~~~~~
+mds: disable adding snapshots by default. (re-enable them with "ceph mds allow_snaps")
\ No newline at end of file
* mdsmap flags
*/
#define CEPH_MDSMAP_DOWN (1<<0) /* cluster deliberately down */
+#define CEPH_MDSMAP_ALLOW_SNAPS (1<<1) /* cluster allowed to create snapshots */
/*
* mds states
::encode(cas_pool, bl);
// kclient ignores everything from here
- __u16 ev = 5;
+ __u16 ev = 6;
::encode(ev, bl);
::encode(compat, bl);
::encode(metadata_pool, bl);
::encode(failed, bl);
::encode(stopped, bl);
::encode(last_failure_osd_epoch, bl);
+ ::encode(ever_allowed_snaps, bl);
+ ::encode(explicitly_allowed_snaps, bl);
ENCODE_FINISH(bl);
}
}
::decode(stopped, p);
if (ev >= 4)
::decode(last_failure_osd_epoch, p);
+ if (ev >= 6) {
+ ::decode(ever_allowed_snaps, p);
+ ::decode(explicitly_allowed_snaps, p);
+ } else {
+ ever_allowed_snaps = true;
+ explicitly_allowed_snaps = false;
+ }
DECODE_FINISH(p);
}
map<int32_t,uint64_t> up; // who is in those roles
map<uint64_t,mds_info_t> mds_info;
+ bool ever_allowed_snaps; //< the cluster has ever allowed snap creation
+ bool explicitly_allowed_snaps; //< the user has explicitly enabled snap creation
+
public:
CompatSet compat;
max_file_size(0),
cas_pool(-1),
metadata_pool(0),
- max_mds(0)
+ max_mds(0),
+ ever_allowed_snaps(false),
+ explicitly_allowed_snaps(false)
{ }
utime_t get_session_timeout() {
void set_flag(int f) { flags |= f; }
void clear_flag(int f) { flags &= ~f; }
+ void set_snaps_allowed() {
+ set_flag(CEPH_MDSMAP_ALLOW_SNAPS);
+ ever_allowed_snaps = true;
+ explicitly_allowed_snaps = true;
+ }
+ bool allows_snaps() { return test_flag(CEPH_MDSMAP_ALLOW_SNAPS); }
+ void clear_snaps_allowed() { clear_flag(CEPH_MDSMAP_ALLOW_SNAPS); }
+
epoch_t get_epoch() const { return epoch; }
void inc_epoch() { epoch++; }
/* This function takes responsibility for the passed mdr*/
void Server::handle_client_mksnap(MDRequest *mdr)
{
+ if (!mds->mdsmap->allows_snaps()) {
+ // you can't make snapshots until you set an option right now
+ reply_request(mdr, -EPERM);
+ return;
+ }
+
MClientRequest *req = mdr->client_request;
CInode *diri = mdcache->get_inode(req->get_filepath().get_ino());
if (!diri || diri->state_test(CInode::STATE_PURGING)) {
r = 0;
}
+ } else if (prefix == "mds set") {
+ string key;
+ cmd_getval(g_ceph_context, cmdmap, "key", key);
+ string sure;
+ cmd_getval(g_ceph_context, cmdmap, "sure", sure);
+ if (key == "allow_new_snaps") {
+ if (sure != "--yes-i-really-mean-it") {
+ ss << "Snapshots are unstable and will probably break your FS! Add --yes-i-really-mean-it if you are sure";
+ r = -EPERM;
+ } else {
+ pending_mdsmap.set_snaps_allowed();
+ ss << "turned on snaps";
+ r = 0;
+ }
+ }
+ } else if (prefix == "mds unset") {
+ string key;
+ cmd_getval(g_ceph_context, cmdmap, "key", key);
+ string sure;
+ cmd_getval(g_ceph_context, cmdmap, "sure", sure);
+ if (key == "allow_new_snaps") {
+ if (sure != "--yes-i-really-mean-it") {
+ ss << "this won't get rid of snapshots or restore the cluster if it's broken. Add --yes-i-really-mean-it if you are sure";
+ r = -EPERM;
+ } else {
+ pending_mdsmap.clear_snaps_allowed();
+ ss << "disabled new snapshots";
+ r = 0;
+ }
+ }
} else if (prefix == "mds add_data_pool") {
int64_t poolid;
cmd_getval(g_ceph_context, cmdmap, "poolid", poolid);
COMMAND("mds compat rm_incompat " \
"name=feature,type=CephInt,range=0", \
"remove incompatible feature", "mds", "rw", "cli,rest")
+COMMAND("mds set " \
+ "name=key,type=CephChoices,strings=allow_new_snaps " \
+ "name=sure,type=CephString,req=false", \
+ "set <key>", \
+ "mds", "w", "cli,rest")
+COMMAND("mds unset " \
+ "name=key,type=CephChoices,strings=allow_new_snaps " \
+ "name=sure,type=CephString,req=false", \
+ "unset <key>", "mds", "w", "cli,rest")
COMMAND("mds add_data_pool " \
"name=poolid,type=CephInt,range=0", \
"add data pool <poolid>", "mds", "rw", "cli,rest")
'compat',
'rm_incompat', '1', '1']))
+ def test_mds_set(self):
+ self.assert_valid_command(['mds', 'set', 'allow_new_snaps'])
+ self.assert_valid_command(['mds', 'set', 'allow_new_snaps', 'sure'])
+ assert_equal({}, validate_command(sigdict, ['mds',
+ 'set',
+ 'invalid']))
+ assert_equal({}, validate_command(sigdict, ['mds',
+ 'set',
+ 'allow_new_snaps',
+ 'sure',
+ 'toomany']))
+
+ def test_mds_unset(self):
+ self.assert_valid_command(['mds', 'unset', 'allow_new_snaps'])
+ self.assert_valid_command(['mds', 'unset', 'allow_new_snaps', 'sure'])
+ assert_equal({}, validate_command(sigdict, ['mds',
+ 'unset',
+ 'invalid']))
+ assert_equal({}, validate_command(sigdict, ['mds',
+ 'unset',
+ 'allow_new_snaps',
+ 'sure',
+ 'toomany']))
+
def test_add_data_pool(self):
self.check_1_natural_arg('mds', 'add_data_pool')