8 #include <linux/slab.h>
12 #include <linux/module.h>
16 #define DM_LOG_USERSPACE_VSN "1.1.0"
30 #define MAX_FLUSH_GROUP_COUNT 32
65 static void *flush_entry_alloc(
gfp_t gfp_mask,
void *pool_data)
70 static void flush_entry_free(
void *
element,
void *pool_data)
75 static int userspace_do_request(
struct log_c *
lc,
const char *
uuid,
77 char *rdata,
size_t *rdata_size)
88 data_size, rdata, rdata_size);
93 DMERR(
" Userspace log server not found.");
97 DMWARN(
"Attempting to contact userspace log server...");
105 DMINFO(
"Reconnected to userspace log server... DM_ULOG_CTR complete");
111 DMERR(
"Error trying to resume userspace log: %d", r);
116 static int build_constructor_string(
struct dm_target *ti,
117 unsigned argc,
char **argv,
125 for (i = 0, str_size = 0; i <
argc; i++)
126 str_size +=
strlen(argv[i]) + 1;
132 DMWARN(
"Unable to allocate memory for constructor string");
136 str_size =
sprintf(str,
"%llu", (
unsigned long long)ti->
len);
137 for (i = 0; i <
argc; i++)
138 str_size +=
sprintf(str + str_size,
" %s", argv[i]);
157 static int userspace_ctr(
struct dm_dirty_log *
log,
struct dm_target *ti,
158 unsigned argc,
char **argv)
162 char *ctr_str =
NULL;
165 size_t rdata_size =
sizeof(rdata);
166 char *devices_rdata =
NULL;
170 DMWARN(
"Too few arguments to userspace dirty log");
176 DMWARN(
"Unable to allocate userspace log context.");
186 DMWARN(
"UUID argument too long.");
196 str_size = build_constructor_string(ti, argc - 1, argv + 1, &ctr_str);
202 devices_rdata = kzalloc(devices_rdata_size,
GFP_KERNEL);
203 if (!devices_rdata) {
204 DMERR(
"Failed to allocate memory for device information");
214 devices_rdata, &devices_rdata_size);
218 DMERR(
"Userspace log server not found");
220 DMERR(
"Userspace log server failed to create log");
225 rdata_size =
sizeof(rdata);
227 NULL, 0, (
char *)&rdata, &rdata_size);
230 DMERR(
"Failed to get region size of dirty log");
237 if (devices_rdata_size) {
238 if (devices_rdata[devices_rdata_size - 1] !=
'\0') {
239 DMERR(
"DM_ULOG_CTR device return string not properly terminated");
246 DMERR(
"Failed to register %s with device-mapper",
250 kfree(devices_rdata);
263 static void userspace_dtr(
struct dm_dirty_log *log)
265 struct log_c *lc = log->context;
280 static int userspace_presuspend(
struct dm_dirty_log *log)
283 struct log_c *lc = log->context;
292 static int userspace_postsuspend(
struct dm_dirty_log *log)
295 struct log_c *lc = log->context;
304 static int userspace_resume(
struct dm_dirty_log *log)
307 struct log_c *lc = log->context;
317 static uint32_t userspace_get_region_size(
struct dm_dirty_log *log)
319 struct log_c *lc = log->context;
332 static int userspace_is_clean(
struct dm_dirty_log *log,
region_t region)
338 struct log_c *lc = log->context;
340 rdata_size =
sizeof(is_clean);
342 (
char *)®ion64,
sizeof(region64),
343 (
char *)&is_clean, &rdata_size);
345 return (r) ? 0 : (
int)is_clean;
359 static int userspace_in_sync(
struct dm_dirty_log *log,
region_t region,
366 struct log_c *lc = log->context;
384 rdata_size =
sizeof(in_sync);
386 (
char *)®ion64,
sizeof(region64),
387 (
char *)&in_sync, &rdata_size);
388 return (r) ? 0 : (
int)in_sync;
391 static int flush_one_by_one(
struct log_c *lc,
struct list_head *flush_list)
397 r = userspace_do_request(lc, lc->
uuid, fe->
type,
408 static int flush_by_group(
struct log_c *lc,
struct list_head *flush_list)
420 while (!list_empty(flush_list)) {
427 list_move(&fe->
list, &tmp_list);
434 r = userspace_do_request(lc, lc->
uuid, type,
440 list_splice_init(&tmp_list, flush_list);
441 r = flush_one_by_one(lc, flush_list);
450 list_splice_init(&tmp_list, flush_list);
472 static int userspace_flush(
struct dm_dirty_log *log)
476 struct log_c *lc = log->context;
482 list_splice_init(&lc->
mark_list, &mark_list);
483 list_splice_init(&lc->
clear_list, &clear_list);
484 spin_unlock_irqrestore(&lc->
flush_lock, flags);
486 if (list_empty(&mark_list) && list_empty(&clear_list))
489 r = flush_by_group(lc, &mark_list);
493 r = flush_by_group(lc, &clear_list);
527 static void userspace_mark_region(
struct dm_dirty_log *log,
region_t region)
530 struct log_c *lc = log->context;
541 spin_unlock_irqrestore(&lc->
flush_lock, flags);
556 static void userspace_clear_region(
struct dm_dirty_log *log,
region_t region)
559 struct log_c *lc = log->context;
570 DMERR(
"Failed to allocate memory to clear region.");
578 spin_unlock_irqrestore(&lc->
flush_lock, flags);
591 static int userspace_get_resync_work(
struct dm_dirty_log *log,
region_t *region)
595 struct log_c *lc = log->context;
604 rdata_size =
sizeof(pkg);
607 (
char *)&pkg, &rdata_size);
610 return (r) ? r : (
int)pkg.i;
619 static void userspace_set_region_sync(
struct dm_dirty_log *log,
623 struct log_c *lc = log->context;
630 pkg.i = (int64_t)in_sync;
633 (
char *)&pkg,
sizeof(pkg),
651 static region_t userspace_get_sync_count(
struct dm_dirty_log *log)
656 struct log_c *lc = log->context;
661 (
char *)&sync_count, &rdata_size);
678 char *
result,
unsigned maxlen)
682 size_t sz = (
size_t)maxlen;
683 struct log_c *lc = log->context;
685 switch (status_type) {
693 DMEMIT(
"%s 1 COM_FAILURE", log->type->name);
703 lc->
uuid, table_args);
706 return (r) ? 0 : (
int)sz;
714 static int userspace_is_remote_recovering(
struct dm_dirty_log *log,
719 struct log_c *lc = log->context;
720 static unsigned long long limit;
722 int64_t is_recovering;
725 size_t rdata_size =
sizeof(pkg);
736 else if (jiffies < limit)
741 (
char *)®ion64,
sizeof(region64),
742 (
char *)&pkg, &rdata_size);
748 return (
int)pkg.is_recovering;
751 static struct dm_dirty_log_type _userspace_type = {
754 .ctr = userspace_ctr,
755 .dtr = userspace_dtr,
756 .presuspend = userspace_presuspend,
757 .postsuspend = userspace_postsuspend,
758 .resume = userspace_resume,
759 .get_region_size = userspace_get_region_size,
760 .is_clean = userspace_is_clean,
761 .in_sync = userspace_in_sync,
762 .flush = userspace_flush,
763 .mark_region = userspace_mark_region,
764 .clear_region = userspace_clear_region,
765 .get_resync_work = userspace_get_resync_work,
766 .set_region_sync = userspace_set_region_sync,
767 .get_sync_count = userspace_get_sync_count,
768 .status = userspace_status,
769 .is_remote_recovering = userspace_is_remote_recovering,
772 static int __init userspace_dirty_log_init(
void)
777 flush_entry_free,
NULL);
779 if (!flush_entry_pool) {
780 DMWARN(
"Unable to create flush_entry_pool: No memory.");
786 DMWARN(
"Unable to initialize userspace log communications");
793 DMWARN(
"Couldn't register userspace dirty log type");
803 static void __exit userspace_dirty_log_exit(
void)