Skip to content

Commit 6b0a70e

Browse files
author
Robert Baldyga
authored
Merge pull request #7 from jfckm/live-recovery
Live recovery
2 parents ad58e49 + fb4f707 commit 6b0a70e

File tree

4 files changed

+227
-5
lines changed

4 files changed

+227
-5
lines changed

module/bdev/ocf/ctx.c

+202
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@
3030
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3131
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3232
*/
33+
34+
#include <sys/mman.h>
35+
#include <sys/stat.h>
36+
#include <sys/types.h>
37+
#include <fcntl.h>
38+
3339
#include <ocf/ocf.h>
3440
#include <execinfo.h>
3541

@@ -590,6 +596,195 @@ vbdev_ocf_ctx_log_printf(ocf_logger_t logger, ocf_logger_lvl_t lvl,
590596
return 0;
591597
}
592598

599+
struct ocf_cache_persistent_meta_segment_descriptor {
600+
int id;
601+
602+
bool valid;
603+
size_t size;
604+
size_t offset;
605+
};
606+
607+
#define MAX_SEGMENTS 20
608+
struct shm_superblock {
609+
struct ocf_cache_persistent_meta_segment_descriptor segments[MAX_SEGMENTS];
610+
};
611+
612+
613+
static ocf_persistent_meta_zone_t
614+
vbdev_ocf_persistent_meta_init(ocf_cache_t cache, size_t size, bool *load)
615+
{
616+
struct vbdev_ocf_cache_ctx *ctx = ocf_cache_get_priv(cache);
617+
struct ocf_persistent_meta_zone *pmeta;
618+
struct stat stat_buf;
619+
void *shm;
620+
struct shm_superblock *shm_sb;
621+
int zone;
622+
623+
size += sizeof(struct shm_superblock);
624+
625+
if (!ctx->create && ctx->force)
626+
return NULL;
627+
628+
for (zone = 0; zone < MAX_PERSISTENT_ZONES; zone++) {
629+
if (!ctx->persistent_meta[zone].fd)
630+
break;
631+
}
632+
633+
if (zone >= MAX_PERSISTENT_ZONES)
634+
return NULL;
635+
636+
637+
pmeta = &ctx->persistent_meta[zone];
638+
*load = false;
639+
640+
snprintf(pmeta->name, NAME_MAX, "/ocf.%s.%u", ctx->cache_name, zone);
641+
642+
pmeta->fd = shm_open(pmeta->name, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
643+
if (pmeta->fd < 0) {
644+
SPDK_ERRLOG("Can't open SHM %s\n", pmeta->name);
645+
return NULL;
646+
}
647+
648+
if (ctx->force) {
649+
SPDK_NOTICELOG("Using force, truncating SHM %s\n",
650+
pmeta->name);
651+
if (ftruncate(pmeta->fd, 0) < 0) {
652+
SPDK_ERRLOG("Failed to truncate\n");
653+
goto err_stat;
654+
}
655+
656+
} else if (fstat(pmeta->fd, &stat_buf) < 0) {
657+
SPDK_ERRLOG("Can't stat SHM %s\n", pmeta->name);
658+
goto err_stat;
659+
}
660+
661+
if (!ctx->force && stat_buf.st_size != 0) {
662+
if (ctx->create) {
663+
SPDK_ERRLOG("SHM %s found, but no force specified!\n",
664+
pmeta->name);
665+
goto err_stat;
666+
}
667+
668+
*load = true;
669+
SPDK_NOTICELOG("Loading from SHM\n");
670+
if (stat_buf.st_size < size) {
671+
if (ftruncate(pmeta->fd, size) < 0) {
672+
SPDK_ERRLOG("Failed to extend SHM\n");
673+
goto err_stat;
674+
}
675+
pmeta->size = size;
676+
} else if (stat_buf.st_size == size) {
677+
pmeta->size = size;
678+
} else {
679+
SPDK_NOTICELOG("Refusing to shrink SHM\n");
680+
pmeta->size = stat_buf.st_size;
681+
}
682+
} else {
683+
SPDK_NOTICELOG("Set SHM size\n");
684+
if (ftruncate(pmeta->fd, size) < 0) {
685+
SPDK_ERRLOG("Failed to truncate\n");
686+
goto err_stat;
687+
}
688+
689+
pmeta->size = size;
690+
}
691+
692+
shm = mmap(NULL, pmeta->size, PROT_READ | PROT_WRITE, MAP_SHARED, pmeta->fd, 0);
693+
if (shm == MAP_FAILED) {
694+
SPDK_ERRLOG("Failed to map shm\n");
695+
goto err_stat;
696+
}
697+
698+
pmeta->data = shm;
699+
shm_sb = shm;
700+
701+
if (mlock(shm, pmeta->size)) {
702+
SPDK_ERRLOG("Failed to mlock\n");
703+
704+
goto err_mlock;
705+
}
706+
707+
708+
if (!*load) {
709+
shm_sb->segments[0].size = sizeof(struct shm_superblock);
710+
shm_sb->segments[0].offset = 0;
711+
shm_sb->segments[0].id = -1;
712+
shm_sb->segments[0].valid = true;
713+
}
714+
715+
return pmeta;
716+
717+
err_mlock:
718+
munmap(pmeta->data, pmeta->size);
719+
err_stat:
720+
close(pmeta->fd);
721+
shm_unlink(pmeta->name);
722+
723+
return NULL;
724+
}
725+
726+
static int
727+
vbdev_ocf_persistent_meta_deinit(struct ocf_persistent_meta_zone *zone)
728+
{
729+
/*
730+
munmap(zone->data, zone->size);
731+
close(zone->fd);
732+
shm_unlink(zone->name);
733+
*/
734+
735+
return 0;
736+
}
737+
738+
static void *
739+
vbdev_ocf_persistent_meta_alloc(struct ocf_persistent_meta_zone *zone, size_t size,
740+
int alloc_id, bool *load)
741+
{
742+
int i;
743+
size_t sum = 0;
744+
struct shm_superblock *shm_sb = zone->data;
745+
struct ocf_cache_persistent_meta_segment_descriptor *desc =
746+
shm_sb->segments;
747+
748+
alloc_id++;
749+
*load = false;
750+
751+
for (i = 0; i < MAX_SEGMENTS; i++) {
752+
/* assume no fragmentation */
753+
if (!desc[i].valid)
754+
break;
755+
756+
sum += desc[i].size;
757+
758+
/* assume no size change */
759+
if (desc[i].id == alloc_id) {
760+
*load = true;
761+
return zone->data + desc[i].offset;
762+
}
763+
}
764+
765+
if (i == MAX_SEGMENTS)
766+
return NULL;
767+
768+
/* TODO: align */
769+
770+
if (sum + size > zone->size)
771+
return NULL;
772+
773+
desc[i].id = alloc_id;
774+
desc[i].offset = sum;
775+
desc[i].size = size;
776+
desc[i].valid = true;
777+
778+
return zone->data + desc[i].offset;
779+
}
780+
781+
static int
782+
vbdev_ocf_persistent_meta_free(struct ocf_persistent_meta_zone *zone, int alloc_id,
783+
void *ptr)
784+
{
785+
return 0;
786+
}
787+
593788
static const struct ocf_ctx_config vbdev_ocf_ctx_cfg = {
594789
.name = "OCF SPDK",
595790

@@ -613,6 +808,13 @@ static const struct ocf_ctx_config vbdev_ocf_ctx_cfg = {
613808
.kick = vbdev_ocf_volume_updater_kick,
614809
},
615810

811+
.persistent_meta = {
812+
.init = vbdev_ocf_persistent_meta_init,
813+
.deinit = vbdev_ocf_persistent_meta_deinit,
814+
.alloc = vbdev_ocf_persistent_meta_alloc,
815+
.free = vbdev_ocf_persistent_meta_free,
816+
},
817+
616818
.cleaner = {
617819
.init = vbdev_ocf_ctx_cleaner_init,
618820
.stop = vbdev_ocf_ctx_cleaner_stop,

module/bdev/ocf/ctx.h

+13
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,15 @@ extern ocf_ctx_t vbdev_ocf_ctx;
4444

4545
#define SPDK_OBJECT 1
4646

47+
struct ocf_persistent_meta_zone {
48+
int fd;
49+
size_t size;
50+
char name[NAME_MAX];
51+
void *data;
52+
};
53+
54+
#define MAX_PERSISTENT_ZONES 2
55+
4756
/* Context of cache instance */
4857
struct vbdev_ocf_cache_ctx {
4958
struct vbdev_ocf *vbdev;
@@ -55,6 +64,10 @@ struct vbdev_ocf_cache_ctx {
5564
/* Channels for cleaner */
5665
struct spdk_io_channel *cleaner_cache_channel;
5766
struct spdk_io_channel *cleaner_core_channel;
67+
bool create;
68+
bool force;
69+
char cache_name[OCF_CACHE_NAME_SIZE];
70+
struct ocf_persistent_meta_zone persistent_meta[MAX_PERSISTENT_ZONES];
5871
};
5972

6073
void vbdev_ocf_cache_ctx_put(struct vbdev_ocf_cache_ctx *ctx);

module/bdev/ocf/vbdev_ocf.c

+11-4
Original file line numberDiff line numberDiff line change
@@ -746,12 +746,12 @@ vbdev_ocf_dump_info_json(void *opaque, struct spdk_json_write_ctx *w)
746746
ocf_get_cache_modename(ocf_cache_get_mode(vbdev->ocf_cache)));
747747
spdk_json_write_named_uint32(w, "cache_line_size",
748748
ocf_get_cache_line_size(vbdev->ocf_cache));
749-
spdk_json_write_named_bool(w, "metadata_volatile",
750-
vbdev->cfg.cache.metadata_volatile);
751749
if (vbdev->cpu_mask)
752750
{
753751
spdk_json_write_named_string(w, "cpu_mask", vbdev->cpu_mask);
754752
}
753+
spdk_json_write_named_uint32(w, "metadata_persistence_mode",
754+
vbdev->cfg.cache.persistence_mode);
755755

756756
return 0;
757757
}
@@ -1170,11 +1170,18 @@ start_cache(struct vbdev_ocf *vbdev)
11701170
return;
11711171
}
11721172

1173+
vbdev->cache_ctx->create = !vbdev->cfg.loadq;
1174+
vbdev->cache_ctx->force = vbdev->cfg.device.force;
1175+
11731176
vbdev_ocf_cache_ctx_get(vbdev->cache_ctx);
11741177
vbdev->cache_ctx->vbdev = vbdev;
11751178
pthread_mutex_init(&vbdev->cache_ctx->lock, NULL);
11761179

1177-
rc = ocf_mngt_cache_start(vbdev_ocf_ctx, &vbdev->ocf_cache, &vbdev->cfg.cache, vbdev->cache_ctx);
1180+
env_strncpy(vbdev->cache_ctx->cache_name, OCF_CACHE_NAME_SIZE,
1181+
vbdev->cfg.cache.name, OCF_CACHE_NAME_SIZE);
1182+
1183+
rc = ocf_mngt_cache_start(vbdev_ocf_ctx, &vbdev->ocf_cache,
1184+
&vbdev->cfg.cache, vbdev->cache_ctx);
11781185
if (rc) {
11791186
SPDK_ERRLOG("Could not start cache %s: %d\n", vbdev->name, rc);
11801187
vbdev_ocf_mngt_exit(vbdev, unregister_path_dirty, rc);
@@ -1237,7 +1244,7 @@ init_vbdev_config(struct vbdev_ocf *vbdev)
12371244

12381245
/* TODO [metadata]: make configurable with persistent
12391246
* metadata support */
1240-
cfg->cache.metadata_volatile = false;
1247+
cfg->cache.persistence_mode = ocf_metadata_persistence_persistent;
12411248

12421249
/* This are suggested values that
12431250
* should be sufficient for most use cases */

0 commit comments

Comments
 (0)