diff options
author | Alexander Motin <mav@FreeBSD.org> | 2015-09-10 12:40:31 +0000 |
---|---|---|
committer | Alexander Motin <mav@FreeBSD.org> | 2015-09-10 12:40:31 +0000 |
commit | 7ac58230ea37d1b0a2095ff19bea8e928fd79bfc (patch) | |
tree | 21fdd7752fb9d89cacedc1ad0f81075a34353a18 /sys/cam/ctl/ctl_backend_block.c | |
parent | fb606ebabc5ead6411f33056f830fa3c9131a83c (diff) | |
download | src-7ac58230ea37d1b0a2095ff19bea8e928fd79bfc.tar.gz src-7ac58230ea37d1b0a2095ff19bea8e928fd79bfc.zip |
Reimplement CTL High Availability.
CTL HA functionality was originally implemented by Copan many years ago,
but large part of the sources was never published. This change includes
clean room implementation of the missing code and fixes for many bugs.
This code supports dual-node HA with ALUA in four modes:
- Active/Unavailable without interlink between nodes;
- Active/Standby with second node handling only basic LUN discovery and
reservation, synchronizing with the first node through the interlink;
- Active/Active with both nodes processing commands and accessing the
backing storage, synchronizing with the first node through the interlink;
- Active/Active with second node working as proxy, transfering all
commands to the first node for execution through the interlink.
Unlike original Copan's implementation, depending on specific hardware,
this code uses simple custom TCP-based protocol for interlink. It has
no authentication, so it should never be enabled on public interfaces.
The code may still need some polishing, but generally it is functional.
Relnotes: yes
Sponsored by: iXsystems, Inc.
Notes
Notes:
svn path=/head/; revision=287621
Diffstat (limited to 'sys/cam/ctl/ctl_backend_block.c')
-rw-r--r-- | sys/cam/ctl/ctl_backend_block.c | 80 |
1 files changed, 61 insertions, 19 deletions
diff --git a/sys/cam/ctl/ctl_backend_block.c b/sys/cam/ctl/ctl_backend_block.c index 799f74273ace..33e9cbed6b10 100644 --- a/sys/cam/ctl/ctl_backend_block.c +++ b/sys/cam/ctl/ctl_backend_block.c @@ -85,7 +85,9 @@ __FBSDID("$FreeBSD$"); #include <cam/ctl/ctl.h> #include <cam/ctl/ctl_backend.h> #include <cam/ctl/ctl_ioctl.h> +#include <cam/ctl/ctl_ha.h> #include <cam/ctl/ctl_scsi_all.h> +#include <cam/ctl/ctl_private.h> #include <cam/ctl/ctl_error.h> /* @@ -217,6 +219,8 @@ struct ctl_be_block_io { void (*beio_cont)(struct ctl_be_block_io *beio); /* to continue processing */ }; +extern struct ctl_softc *control_softc; + static int cbb_num_threads = 14; SYSCTL_NODE(_kern_cam_ctl, OID_AUTO, block, CTLFLAG_RD, 0, "CAM Target Layer Block Backend"); @@ -2214,7 +2218,13 @@ ctl_be_block_create(struct ctl_be_block_softc *softc, struct ctl_lun_req *req) else cbe_lun->lun_type = T_DIRECT; be_lun->flags = CTL_BE_BLOCK_LUN_UNCONFIGURED; - cbe_lun->flags = CTL_LUN_FLAG_PRIMARY; + cbe_lun->flags = 0; + value = ctl_get_opt(&cbe_lun->options, "ha_role"); + if (value != NULL) { + if (strcmp(value, "primary") == 0) + cbe_lun->flags |= CTL_LUN_FLAG_PRIMARY; + } else if (control_softc->flags & CTL_FLAG_ACTIVE_SHELF) + cbe_lun->flags |= CTL_LUN_FLAG_PRIMARY; if (cbe_lun->lun_type == T_DIRECT) { be_lun->size_bytes = params->lun_size_bytes; @@ -2226,10 +2236,13 @@ ctl_be_block_create(struct ctl_be_block_softc *softc, struct ctl_lun_req *req) cbe_lun->maxlba = (be_lun->size_blocks == 0) ? 0 : (be_lun->size_blocks - 1); - retval = ctl_be_block_open(softc, be_lun, req); - if (retval != 0) { - retval = 0; - req->status = CTL_LUN_WARNING; + if ((cbe_lun->flags & CTL_LUN_FLAG_PRIMARY) || + control_softc->ha_mode == CTL_HA_MODE_SER_ONLY) { + retval = ctl_be_block_open(softc, be_lun, req); + if (retval != 0) { + retval = 0; + req->status = CTL_LUN_WARNING; + } } num_threads = cbb_num_threads; } else { @@ -2587,8 +2600,9 @@ ctl_be_block_modify(struct ctl_be_block_softc *softc, struct ctl_lun_req *req) struct ctl_lun_modify_params *params; struct ctl_be_block_lun *be_lun; struct ctl_be_lun *cbe_lun; + char *value; uint64_t oldsize; - int error; + int error, wasprim; params = &req->reqdata.modify; @@ -2611,23 +2625,51 @@ ctl_be_block_modify(struct ctl_be_block_softc *softc, struct ctl_lun_req *req) be_lun->params.lun_size_bytes = params->lun_size_bytes; ctl_update_opts(&cbe_lun->options, req->num_be_args, req->kern_be_args); - oldsize = be_lun->size_blocks; - if (be_lun->vn == NULL) - error = ctl_be_block_open(softc, be_lun, req); - else if (vn_isdisk(be_lun->vn, &error)) - error = ctl_be_block_modify_dev(be_lun, req); - else if (be_lun->vn->v_type == VREG) - error = ctl_be_block_modify_file(be_lun, req); + wasprim = (cbe_lun->flags & CTL_LUN_FLAG_PRIMARY); + value = ctl_get_opt(&cbe_lun->options, "ha_role"); + if (value != NULL) { + if (strcmp(value, "primary") == 0) + cbe_lun->flags |= CTL_LUN_FLAG_PRIMARY; + else + cbe_lun->flags &= ~CTL_LUN_FLAG_PRIMARY; + } else if (control_softc->flags & CTL_FLAG_ACTIVE_SHELF) + cbe_lun->flags |= CTL_LUN_FLAG_PRIMARY; else - error = EINVAL; + cbe_lun->flags &= ~CTL_LUN_FLAG_PRIMARY; + if (wasprim != (cbe_lun->flags & CTL_LUN_FLAG_PRIMARY)) { + if (cbe_lun->flags & CTL_LUN_FLAG_PRIMARY) + ctl_lun_primary(cbe_lun); + else + ctl_lun_secondary(cbe_lun); + } + oldsize = be_lun->size_blocks; + if ((cbe_lun->flags & CTL_LUN_FLAG_PRIMARY) || + control_softc->ha_mode == CTL_HA_MODE_SER_ONLY) { + if (be_lun->vn == NULL) + error = ctl_be_block_open(softc, be_lun, req); + else if (vn_isdisk(be_lun->vn, &error)) + error = ctl_be_block_modify_dev(be_lun, req); + else if (be_lun->vn->v_type == VREG) + error = ctl_be_block_modify_file(be_lun, req); + else + error = EINVAL; + if ((cbe_lun->flags & CTL_LUN_FLAG_OFFLINE) && + be_lun->vn != NULL) { + cbe_lun->flags &= ~CTL_LUN_FLAG_OFFLINE; + ctl_lun_online(cbe_lun); + } + } else { + if (be_lun->vn != NULL) { + cbe_lun->flags |= CTL_LUN_FLAG_OFFLINE; + ctl_lun_offline(cbe_lun); + pause("CTL LUN offline", hz / 8); // XXX + error = ctl_be_block_close(be_lun); + } else + error = 0; + } if (be_lun->size_blocks != oldsize) ctl_lun_capacity_changed(cbe_lun); - if ((cbe_lun->flags & CTL_LUN_FLAG_OFFLINE) && - be_lun->vn != NULL) { - cbe_lun->flags &= ~CTL_LUN_FLAG_OFFLINE; - ctl_lun_online(cbe_lun); - } /* Tell the user the exact size we ended up using */ params->lun_size_bytes = be_lun->size_bytes; |