From e851ecbb12647f3e66f6d4c1ebdb0741eb3a3d2c Mon Sep 17 00:00:00 2001 From: Dan Lambright Date: Mon, 5 Oct 2015 19:52:02 +0000 Subject: cluster/tier: add pause tier for snapshots This is a backport of 12304 Snaps of tiered volumes cannot handle files undergoing migration. We implement a helper mechanism to "pause" migration. Any files undergoing migration are aborted. Clean up is done to remove sticky bits and data at the destination. Migration is restarted after snap completes. For testing an internal switch is added. It is not exposed externally. gluster volume set vol1 tier-pause [true|false] > Change-Id: Ia85bbf89ac142e9b7e73fcbef98bb9da86097799 > BUG: 1267950 > Signed-off-by: Dan Lambright > Reviewed-on: http://review.gluster.org/12304 > Reviewed-by: N Balachandran > Tested-by: NetBSD Build System > Tested-by: Gluster Build System Signed-off-by: Dan Lambright Conflicts: xlators/mgmt/glusterd/src/glusterd-messages.h Change-Id: I5f039d8d38a4c915bd873969f336b96755a0b8f1 BUG: 1274101 Reviewed-on: http://review.gluster.org/12411 Tested-by: NetBSD Build System Tested-by: Gluster Build System Reviewed-by: Dan Lambright Tested-by: Dan Lambright --- xlators/cluster/dht/src/dht-rebalance.c | 125 +++++++++++++++++++++++++++++++- 1 file changed, 122 insertions(+), 3 deletions(-) (limited to 'xlators/cluster/dht/src/dht-rebalance.c') diff --git a/xlators/cluster/dht/src/dht-rebalance.c b/xlators/cluster/dht/src/dht-rebalance.c index 1e98142e9ec..3cb247f1865 100644 --- a/xlators/cluster/dht/src/dht-rebalance.c +++ b/xlators/cluster/dht/src/dht-rebalance.c @@ -731,7 +731,7 @@ out: static inline int __dht_rebalance_migrate_data (xlator_t *from, xlator_t *to, fd_t *src, fd_t *dst, - uint64_t ia_size, int hole_exists) + uint64_t ia_size, int hole_exists) { int ret = 0; int count = 0; @@ -783,6 +783,68 @@ __dht_rebalance_migrate_data (xlator_t *from, xlator_t *to, fd_t *src, fd_t *dst return ret; } +static int +__tier_migrate_data (gf_defrag_info_t *defrag, xlator_t *from, xlator_t *to, fd_t *src, fd_t *dst, + uint64_t ia_size, int hole_exists) +{ + int ret = 0; + int count = 0; + off_t offset = 0; + struct iovec *vector = NULL; + struct iobref *iobref = NULL; + uint64_t total = 0; + size_t read_size = 0; + + /* if file size is '0', no need to enter this loop */ + while (total < ia_size) { + + read_size = (((ia_size - total) > DHT_REBALANCE_BLKSIZE) ? + DHT_REBALANCE_BLKSIZE : (ia_size - total)); + + ret = syncop_readv (from, src, read_size, + offset, 0, &vector, &count, &iobref, NULL, + NULL); + if (!ret || (ret < 0)) { + break; + } + + if (hole_exists) + ret = dht_write_with_holes (to, dst, vector, count, + ret, offset, iobref); + else + ret = syncop_writev (to, dst, vector, count, + offset, iobref, 0, NULL, NULL); + if (defrag->tier_conf.request_pause) { + gf_msg ("tier", GF_LOG_INFO, 0, + DHT_MSG_TIER_PAUSED, + "Migrate file paused"); + ret = -1; + } + + if (ret < 0) { + break; + } + offset += ret; + total += ret; + + GF_FREE (vector); + if (iobref) + iobref_unref (iobref); + iobref = NULL; + vector = NULL; + } + if (iobref) + iobref_unref (iobref); + GF_FREE (vector); + + if (ret >= 0) + ret = 0; + else + ret = -1; + + return ret; +} + static inline int __dht_rebalance_open_src_file (xlator_t *from, xlator_t *to, loc_t *loc, @@ -1255,8 +1317,14 @@ dht_migrate_file (xlator_t *this, loc_t *loc, xlator_t *from, xlator_t *to, /* All I/O happens in this function */ - ret = __dht_rebalance_migrate_data (from, to, src_fd, dst_fd, - stbuf.ia_size, file_has_holes); + if (defrag->cmd == GF_DEFRAG_CMD_START_TIER) { + ret = __tier_migrate_data (defrag, from, to, src_fd, dst_fd, + stbuf.ia_size, file_has_holes); + } else { + ret = __dht_rebalance_migrate_data (from, to, src_fd, dst_fd, + stbuf.ia_size, file_has_holes); + } + if (ret) { gf_msg (this->name, GF_LOG_ERROR, 0, DHT_MSG_MIGRATE_FILE_FAILED, @@ -3419,6 +3487,57 @@ out: return 0; } +int +gf_defrag_pause_tier (xlator_t *this, gf_defrag_info_t *defrag) +{ + int poll = 0; + int ret = 0; + int usec_sleep = 100000; /* 1/10th of a sec */ + int poll_max = 15; /* 15 times = wait at most 3/2 sec */ + + if (defrag->defrag_status != GF_DEFRAG_STATUS_STARTED) + goto out; + + /* + * Set flag requesting to pause tiering. Wait a finite time for + * tiering to actually stop as indicated by the "paused" boolean, + * before returning success or failure. + */ + defrag->tier_conf.request_pause = 1; + + for (poll = 0; poll < poll_max; poll++) { + if ((defrag->tier_conf.paused == _gf_true) || + (defrag->defrag_status != GF_DEFRAG_STATUS_STARTED)) { + goto out; + } + + usleep (usec_sleep); + } + + ret = -1; + +out: + + gf_msg (this->name, GF_LOG_DEBUG, 0, + DHT_MSG_TIER_PAUSED, + "Pause tiering ret=%d", ret); + + return ret; +} + +int +gf_defrag_resume_tier (xlator_t *this, gf_defrag_info_t *defrag) +{ + gf_msg (this->name, GF_LOG_DEBUG, 0, + DHT_MSG_TIER_RESUME, + "Resume tiering"); + + defrag->tier_conf.request_pause = 0; + defrag->tier_conf.paused = _gf_false; + + return 0; +} + int gf_defrag_start_detach_tier (gf_defrag_info_t *defrag) { -- cgit