diff options
| -rw-r--r-- | Documentation/device-mapper/dm-log.txt | 54 | ||||
| -rw-r--r-- | drivers/md/Kconfig | 11 | ||||
| -rw-r--r-- | drivers/md/Makefile | 3 | ||||
| -rw-r--r-- | drivers/md/dm-log-userspace-base.c | 696 | ||||
| -rw-r--r-- | drivers/md/dm-log-userspace-transfer.c | 276 | ||||
| -rw-r--r-- | drivers/md/dm-log-userspace-transfer.h | 18 | ||||
| -rw-r--r-- | include/linux/Kbuild | 1 | ||||
| -rw-r--r-- | include/linux/connector.h | 4 | ||||
| -rw-r--r-- | include/linux/dm-log-userspace.h | 386 |
9 files changed, 1448 insertions, 1 deletions
diff --git a/Documentation/device-mapper/dm-log.txt b/Documentation/device-mapper/dm-log.txt new file mode 100644 index 000000000000..994dd75475a6 --- /dev/null +++ b/Documentation/device-mapper/dm-log.txt | |||
| @@ -0,0 +1,54 @@ | |||
| 1 | Device-Mapper Logging | ||
| 2 | ===================== | ||
| 3 | The device-mapper logging code is used by some of the device-mapper | ||
| 4 | RAID targets to track regions of the disk that are not consistent. | ||
| 5 | A region (or portion of the address space) of the disk may be | ||
| 6 | inconsistent because a RAID stripe is currently being operated on or | ||
| 7 | a machine died while the region was being altered. In the case of | ||
| 8 | mirrors, a region would be considered dirty/inconsistent while you | ||
| 9 | are writing to it because the writes need to be replicated for all | ||
| 10 | the legs of the mirror and may not reach the legs at the same time. | ||
| 11 | Once all writes are complete, the region is considered clean again. | ||
| 12 | |||
| 13 | There is a generic logging interface that the device-mapper RAID | ||
| 14 | implementations use to perform logging operations (see | ||
| 15 | dm_dirty_log_type in include/linux/dm-dirty-log.h). Various different | ||
| 16 | logging implementations are available and provide different | ||
| 17 | capabilities. The list includes: | ||
| 18 | |||
| 19 | Type Files | ||
| 20 | ==== ===== | ||
| 21 | disk drivers/md/dm-log.c | ||
| 22 | core drivers/md/dm-log.c | ||
| 23 | userspace drivers/md/dm-log-userspace* include/linux/dm-log-userspace.h | ||
| 24 | |||
| 25 | The "disk" log type | ||
| 26 | ------------------- | ||
| 27 | This log implementation commits the log state to disk. This way, the | ||
| 28 | logging state survives reboots/crashes. | ||
| 29 | |||
| 30 | The "core" log type | ||
| 31 | ------------------- | ||
| 32 | This log implementation keeps the log state in memory. The log state | ||
| 33 | will not survive a reboot or crash, but there may be a small boost in | ||
| 34 | performance. This method can also be used if no storage device is | ||
| 35 | available for storing log state. | ||
| 36 | |||
| 37 | The "userspace" log type | ||
| 38 | ------------------------ | ||
| 39 | This log type simply provides a way to export the log API to userspace, | ||
| 40 | so log implementations can be done there. This is done by forwarding most | ||
| 41 | logging requests to userspace, where a daemon receives and processes the | ||
| 42 | request. | ||
| 43 | |||
| 44 | The structure used for communication between kernel and userspace are | ||
| 45 | located in include/linux/dm-log-userspace.h. Due to the frequency, | ||
| 46 | diversity, and 2-way communication nature of the exchanges between | ||
| 47 | kernel and userspace, 'connector' is used as the interface for | ||
| 48 | communication. | ||
| 49 | |||
| 50 | There are currently two userspace log implementations that leverage this | ||
| 51 | framework - "clustered_disk" and "clustered_core". These implementations | ||
| 52 | provide a cluster-coherent log for shared-storage. Device-mapper mirroring | ||
| 53 | can be used in a shared-storage environment when the cluster log implementations | ||
| 54 | are employed. | ||
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig index 09f93fa68912..020f9573fd82 100644 --- a/drivers/md/Kconfig +++ b/drivers/md/Kconfig | |||
| @@ -231,6 +231,17 @@ config DM_MIRROR | |||
| 231 | Allow volume managers to mirror logical volumes, also | 231 | Allow volume managers to mirror logical volumes, also |
| 232 | needed for live data migration tools such as 'pvmove'. | 232 | needed for live data migration tools such as 'pvmove'. |
| 233 | 233 | ||
| 234 | config DM_LOG_USERSPACE | ||
| 235 | tristate "Mirror userspace logging (EXPERIMENTAL)" | ||
| 236 | depends on DM_MIRROR && EXPERIMENTAL && NET | ||
| 237 | select CONNECTOR | ||
| 238 | ---help--- | ||
| 239 | The userspace logging module provides a mechanism for | ||
| 240 | relaying the dm-dirty-log API to userspace. Log designs | ||
| 241 | which are more suited to userspace implementation (e.g. | ||
| 242 | shared storage logs) or experimental logs can be implemented | ||
| 243 | by leveraging this framework. | ||
| 244 | |||
| 234 | config DM_ZERO | 245 | config DM_ZERO |
| 235 | tristate "Zero target" | 246 | tristate "Zero target" |
| 236 | depends on BLK_DEV_DM | 247 | depends on BLK_DEV_DM |
diff --git a/drivers/md/Makefile b/drivers/md/Makefile index dade52f60733..1dc4185bd781 100644 --- a/drivers/md/Makefile +++ b/drivers/md/Makefile | |||
| @@ -8,6 +8,8 @@ dm-multipath-y += dm-path-selector.o dm-mpath.o | |||
| 8 | dm-snapshot-y += dm-snap.o dm-exception-store.o dm-snap-transient.o \ | 8 | dm-snapshot-y += dm-snap.o dm-exception-store.o dm-snap-transient.o \ |
| 9 | dm-snap-persistent.o | 9 | dm-snap-persistent.o |
| 10 | dm-mirror-y += dm-raid1.o | 10 | dm-mirror-y += dm-raid1.o |
| 11 | dm-log-userspace-y \ | ||
| 12 | += dm-log-userspace-base.o dm-log-userspace-transfer.o | ||
| 11 | md-mod-y += md.o bitmap.o | 13 | md-mod-y += md.o bitmap.o |
| 12 | raid456-y += raid5.o | 14 | raid456-y += raid5.o |
| 13 | raid6_pq-y += raid6algos.o raid6recov.o raid6tables.o \ | 15 | raid6_pq-y += raid6algos.o raid6recov.o raid6tables.o \ |
| @@ -40,6 +42,7 @@ obj-$(CONFIG_DM_MULTIPATH_QL) += dm-queue-length.o | |||
| 40 | obj-$(CONFIG_DM_MULTIPATH_ST) += dm-service-time.o | 42 | obj-$(CONFIG_DM_MULTIPATH_ST) += dm-service-time.o |
| 41 | obj-$(CONFIG_DM_SNAPSHOT) += dm-snapshot.o | 43 | obj-$(CONFIG_DM_SNAPSHOT) += dm-snapshot.o |
| 42 | obj-$(CONFIG_DM_MIRROR) += dm-mirror.o dm-log.o dm-region-hash.o | 44 | obj-$(CONFIG_DM_MIRROR) += dm-mirror.o dm-log.o dm-region-hash.o |
| 45 | obj-$(CONFIG_DM_LOG_USERSPACE) += dm-log-userspace.o | ||
| 43 | obj-$(CONFIG_DM_ZERO) += dm-zero.o | 46 | obj-$(CONFIG_DM_ZERO) += dm-zero.o |
| 44 | 47 | ||
| 45 | quiet_cmd_unroll = UNROLL $@ | 48 | quiet_cmd_unroll = UNROLL $@ |
diff --git a/drivers/md/dm-log-userspace-base.c b/drivers/md/dm-log-userspace-base.c new file mode 100644 index 000000000000..e69b96560997 --- /dev/null +++ b/drivers/md/dm-log-userspace-base.c | |||
| @@ -0,0 +1,696 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2006-2009 Red Hat, Inc. | ||
| 3 | * | ||
| 4 | * This file is released under the LGPL. | ||
| 5 | */ | ||
| 6 | |||
| 7 | #include <linux/bio.h> | ||
| 8 | #include <linux/dm-dirty-log.h> | ||
| 9 | #include <linux/device-mapper.h> | ||
| 10 | #include <linux/dm-log-userspace.h> | ||
| 11 | |||
| 12 | #include "dm-log-userspace-transfer.h" | ||
| 13 | |||
| 14 | struct flush_entry { | ||
| 15 | int type; | ||
| 16 | region_t region; | ||
| 17 | struct list_head list; | ||
| 18 | }; | ||
| 19 | |||
| 20 | struct log_c { | ||
| 21 | struct dm_target *ti; | ||
| 22 | uint32_t region_size; | ||
| 23 | region_t region_count; | ||
| 24 | char uuid[DM_UUID_LEN]; | ||
| 25 | |||
| 26 | char *usr_argv_str; | ||
| 27 | uint32_t usr_argc; | ||
| 28 | |||
| 29 | /* | ||
| 30 | * in_sync_hint gets set when doing is_remote_recovering. It | ||
| 31 | * represents the first region that needs recovery. IOW, the | ||
| 32 | * first zero bit of sync_bits. This can be useful for to limit | ||
| 33 | * traffic for calls like is_remote_recovering and get_resync_work, | ||
| 34 | * but be take care in its use for anything else. | ||
| 35 | */ | ||
| 36 | uint64_t in_sync_hint; | ||
| 37 | |||
| 38 | spinlock_t flush_lock; | ||
| 39 | struct list_head flush_list; /* only for clear and mark requests */ | ||
| 40 | }; | ||
| 41 | |||
| 42 | static mempool_t *flush_entry_pool; | ||
| 43 | |||
| 44 | static void *flush_entry_alloc(gfp_t gfp_mask, void *pool_data) | ||
| 45 | { | ||
| 46 | return kmalloc(sizeof(struct flush_entry), gfp_mask); | ||
| 47 | } | ||
| 48 | |||
| 49 | static void flush_entry_free(void *element, void *pool_data) | ||
| 50 | { | ||
| 51 | kfree(element); | ||
| 52 | } | ||
| 53 | |||
| 54 | static int userspace_do_request(struct log_c *lc, const char *uuid, | ||
| 55 | int request_type, char *data, size_t data_size, | ||
| 56 | char *rdata, size_t *rdata_size) | ||
| 57 | { | ||
| 58 | int r; | ||
| 59 | |||
| 60 | /* | ||
| 61 | * If the server isn't there, -ESRCH is returned, | ||
| 62 | * and we must keep trying until the server is | ||
| 63 | * restored. | ||
| 64 | */ | ||
| 65 | retry: | ||
| 66 | r = dm_consult_userspace(uuid, request_type, data, | ||
| 67 | data_size, rdata, rdata_size); | ||
| 68 | |||
| 69 | if (r != -ESRCH) | ||
| 70 | return r; | ||
| 71 | |||
| 72 | DMERR(" Userspace log server not found."); | ||
| 73 | while (1) { | ||
| 74 | set_current_state(TASK_INTERRUPTIBLE); | ||
| 75 | schedule_timeout(2*HZ); | ||
| 76 | DMWARN("Attempting to contact userspace log server..."); | ||
| 77 | r = dm_consult_userspace(uuid, DM_ULOG_CTR, lc->usr_argv_str, | ||
| 78 | strlen(lc->usr_argv_str) + 1, | ||
| 79 | NULL, NULL); | ||
| 80 | if (!r) | ||
| 81 | break; | ||
