1 /* 2 * Copyright (C) 2006-2009 Red Hat, Inc. 3 * 4 * This file is released under the LGPL. 5 */ 6 7 #ifndef __DM_LOG_USERSPACE_H__ 8 #define __DM_LOG_USERSPACE_H__ 9 10 #include <linux/dm-ioctl.h> /* For DM_UUID_LEN */ 11 12 /* 13 * The device-mapper userspace log module consists of a kernel component and 14 * a user-space component. The kernel component implements the API defined 15 * in dm-dirty-log.h. Its purpose is simply to pass the parameters and 16 * return values of those API functions between kernel and user-space. 17 * 18 * Below are defined the 'request_types' - DM_ULOG_CTR, DM_ULOG_DTR, etc. 19 * These request types represent the different functions in the device-mapper 20 * dirty log API. Each of these is described in more detail below. 21 * 22 * The user-space program must listen for requests from the kernel (representing 23 * the various API functions) and process them. 24 * 25 * User-space begins by setting up the communication link (error checking 26 * removed for clarity): 27 * fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); 28 * addr.nl_family = AF_NETLINK; 29 * addr.nl_groups = CN_IDX_DM; 30 * addr.nl_pid = 0; 31 * r = bind(fd, (struct sockaddr *) &addr, sizeof(addr)); 32 * opt = addr.nl_groups; 33 * setsockopt(fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &opt, sizeof(opt)); 34 * 35 * User-space will then wait to receive requests form the kernel, which it 36 * will process as described below. The requests are received in the form, 37 * ((struct dm_ulog_request) + (additional data)). Depending on the request 38 * type, there may or may not be 'additional data'. In the descriptions below, 39 * you will see 'Payload-to-userspace' and 'Payload-to-kernel'. The 40 * 'Payload-to-userspace' is what the kernel sends in 'additional data' as 41 * necessary parameters to complete the request. The 'Payload-to-kernel' is 42 * the 'additional data' returned to the kernel that contains the necessary 43 * results of the request. The 'data_size' field in the dm_ulog_request 44 * structure denotes the availability and amount of payload data. 45 */ 46 47 /* 48 * DM_ULOG_CTR corresponds to (found in dm-dirty-log.h): 49 * int (*ctr)(struct dm_dirty_log *log, struct dm_target *ti, 50 * unsigned argc, char **argv); 51 * 52 * Payload-to-userspace: 53 * A single string containing all the argv arguments separated by ' 's 54 * Payload-to-kernel: 55 * A NUL-terminated string that is the name of the device that is used 56 * as the backing store for the log data. 'dm_get_device' will be called 57 * on this device. ('dm_put_device' will be called on this device 58 * automatically after calling DM_ULOG_DTR.) If there is no device needed 59 * for log data, 'data_size' in the dm_ulog_request struct should be 0. 60 * 61 * The UUID contained in the dm_ulog_request structure is the reference that 62 * will be used by all request types to a specific log. The constructor must 63 * record this association with the instance created. 64 * 65 * When the request has been processed, user-space must return the 66 * dm_ulog_request to the kernel - setting the 'error' field, filling the 67 * data field with the log device if necessary, and setting 'data_size' 68 * appropriately. 69 */ 70 #define DM_ULOG_CTR 1 71 72 /* 73 * DM_ULOG_DTR corresponds to (found in dm-dirty-log.h): 74 * void (*dtr)(struct dm_dirty_log *log); 75 * 76 * Payload-to-userspace: 77 * A single string containing all the argv arguments separated by ' 's 78 * Payload-to-kernel: 79 * None. ('data_size' in the dm_ulog_request struct should be 0.) 80 * 81 * The UUID contained in the dm_ulog_request structure is all that is 82 * necessary to identify the log instance being destroyed. There is no 83 * payload data. 84 * 85 * When the request has been processed, user-space must return the 86 * dm_ulog_request to the kernel - setting the 'error' field and clearing 87 * 'data_size' appropriately. 88 */ 89 #define DM_ULOG_DTR 2 90 91 /* 92 * DM_ULOG_PRESUSPEND corresponds to (found in dm-dirty-log.h): 93 * int (*presuspend)(struct dm_dirty_log *log); 94 * 95 * Payload-to-userspace: 96 * None. 97 * Payload-to-kernel: 98 * None. 99 * 100 * The UUID contained in the dm_ulog_request structure is all that is 101 * necessary to identify the log instance being presuspended. There is no 102 * payload data. 103 * 104 * When the request has been processed, user-space must return the 105 * dm_ulog_request to the kernel - setting the 'error' field and 106 * 'data_size' appropriately. 107 */ 108 #define DM_ULOG_PRESUSPEND 3 109 110 /* 111 * DM_ULOG_POSTSUSPEND corresponds to (found in dm-dirty-log.h): 112 * int (*postsuspend)(struct dm_dirty_log *log); 113 * 114 * Payload-to-userspace: 115 * None. 116 * Payload-to-kernel: 117 * None. 118 * 119 * The UUID contained in the dm_ulog_request structure is all that is 120 * necessary to identify the log instance being postsuspended. There is no 121 * payload data. 122 * 123 * When the request has been processed, user-space must return the 124 * dm_ulog_request to the kernel - setting the 'error' field and 125 * 'data_size' appropriately. 126 */ 127 #define DM_ULOG_POSTSUSPEND 4 128 129 /* 130 * DM_ULOG_RESUME corresponds to (found in dm-dirty-log.h): 131 * int (*resume)(struct dm_dirty_log *log); 132 * 133 * Payload-to-userspace: 134 * None. 135 * Payload-to-kernel: 136 * None. 137 * 138 * The UUID contained in the dm_ulog_request structure is all that is 139 * necessary to identify the log instance being resumed. There is no 140 * payload data. 141 * 142 * When the request has been processed, user-space must return the 143 * dm_ulog_request to the kernel - setting the 'error' field and 144 * 'data_size' appropriately. 145 */ 146 #define DM_ULOG_RESUME 5 147 148 /* 149 * DM_ULOG_GET_REGION_SIZE corresponds to (found in dm-dirty-log.h): 150 * uint32_t (*get_region_size)(struct dm_dirty_log *log); 151 * 152 * Payload-to-userspace: 153 * None. 154 * Payload-to-kernel: 155 * uint64_t - contains the region size 156 * 157 * The region size is something that was determined at constructor time. 158 * It is returned in the payload area and 'data_size' is set to 159 * reflect this. 160 * 161 * When the request has been processed, user-space must return the 162 * dm_ulog_request to the kernel - setting the 'error' field appropriately. 163 */ 164 #define DM_ULOG_GET_REGION_SIZE 6 165 166 /* 167 * DM_ULOG_IS_CLEAN corresponds to (found in dm-dirty-log.h): 168 * int (*is_clean)(struct dm_dirty_log *log, region_t region); 169 * 170 * Payload-to-userspace: 171 * uint64_t - the region to get clean status on 172 * Payload-to-kernel: 173 * int64_t - 1 if clean, 0 otherwise 174 * 175 * Payload is sizeof(uint64_t) and contains the region for which the clean 176 * status is being made. 177 * 178 * When the request has been processed, user-space must return the 179 * dm_ulog_request to the kernel - filling the payload with 0 (not clean) or 180 * 1 (clean), setting 'data_size' and 'error' appropriately. 181 */ 182 #define DM_ULOG_IS_CLEAN 7 183 184 /* 185 * DM_ULOG_IN_SYNC corresponds to (found in dm-dirty-log.h): 186 * int (*in_sync)(struct dm_dirty_log *log, region_t region, 187 * int can_block); 188 * 189 * Payload-to-userspace: 190 * uint64_t - the region to get sync status on 191 * Payload-to-kernel: 192 * int64_t - 1 if in-sync, 0 otherwise 193 * 194 * Exactly the same as 'is_clean' above, except this time asking "has the 195 * region been recovered?" vs. "is the region not being modified?" 196 */ 197 #define DM_ULOG_IN_SYNC 8 198 199 /* 200 * DM_ULOG_FLUSH corresponds to (found in dm-dirty-log.h): 201 * int (*flush)(struct dm_dirty_log *log); 202 * 203 * Payload-to-userspace: 204 * None. 205 * Payload-to-kernel: 206 * None. 207 * 208 * No incoming or outgoing payload. Simply flush log state to disk. 209 * 210 * When the request has been processed, user-space must return the 211 * dm_ulog_request to the kernel - setting the 'error' field and clearing 212 * 'data_size' appropriately. 213 */ 214 #define DM_ULOG_FLUSH 9 215 216 /* 217 * DM_ULOG_MARK_REGION corresponds to (found in dm-dirty-log.h): 218 * void (*mark_region)(struct dm_dirty_log *log, region_t region); 219 * 220 * Payload-to-userspace: 221 * uint64_t [] - region(s) to mark 222 * Payload-to-kernel: 223 * None. 224 * 225 * Incoming payload contains the one or more regions to mark dirty. 226 * The number of regions contained in the payload can be determined from 227 * 'data_size/sizeof(uint64_t)'. 228 * 229 * When the request has been processed, user-space must return the 230 * dm_ulog_request to the kernel - setting the 'error' field and clearing 231 * 'data_size' appropriately. 232 */ 233 #define DM_ULOG_MARK_REGION 10 234 235 /* 236 * DM_ULOG_CLEAR_REGION corresponds to (found in dm-dirty-log.h): 237 * void (*clear_region)(struct dm_dirty_log *log, region_t region); 238 * 239 * Payload-to-userspace: 240 * uint64_t [] - region(s) to clear 241 * Payload-to-kernel: 242 * None. 243 * 244 * Incoming payload contains the one or more regions to mark clean. 245 * The number of regions contained in the payload can be determined from 246 * 'data_size/sizeof(uint64_t)'. 247 * 248 * When the request has been processed, user-space must return the 249 * dm_ulog_request to the kernel - setting the 'error' field and clearing 250 * 'data_size' appropriately. 251 */ 252 #define DM_ULOG_CLEAR_REGION 11 253 254 /* 255 * DM_ULOG_GET_RESYNC_WORK corresponds to (found in dm-dirty-log.h): 256 * int (*get_resync_work)(struct dm_dirty_log *log, region_t *region); 257 * 258 * Payload-to-userspace: 259 * None. 260 * Payload-to-kernel: 261 * { 262 * int64_t i; -- 1 if recovery necessary, 0 otherwise 263 * uint64_t r; -- The region to recover if i=1 264 * } 265 * 'data_size' should be set appropriately. 266 * 267 * When the request has been processed, user-space must return the 268 * dm_ulog_request to the kernel - setting the 'error' field appropriately. 269 */ 270 #define DM_ULOG_GET_RESYNC_WORK 12 271 272 /* 273 * DM_ULOG_SET_REGION_SYNC corresponds to (found in dm-dirty-log.h): 274 * void (*set_region_sync)(struct dm_dirty_log *log, 275 * region_t region, int in_sync); 276 * 277 * Payload-to-userspace: 278 * { 279 * uint64_t - region to set sync state on 280 * int64_t - 0 if not-in-sync, 1 if in-sync 281 * } 282 * Payload-to-kernel: 283 * None. 284 * 285 * When the request has been processed, user-space must return the 286 * dm_ulog_request to the kernel - setting the 'error' field and clearing 287 * 'data_size' appropriately. 288 */ 289 #define DM_ULOG_SET_REGION_SYNC 13 290 291 /* 292 * DM_ULOG_GET_SYNC_COUNT corresponds to (found in dm-dirty-log.h): 293 * region_t (*get_sync_count)(struct dm_dirty_log *log); 294 * 295 * Payload-to-userspace: 296 * None. 297 * Payload-to-kernel: 298 * uint64_t - the number of in-sync regions 299 * 300 * No incoming payload. Kernel-bound payload contains the number of 301 * regions that are in-sync (in a size_t). 302 * 303 * When the request has been processed, user-space must return the 304 * dm_ulog_request to the kernel - setting the 'error' field and 305 * 'data_size' appropriately. 306 */ 307 #define DM_ULOG_GET_SYNC_COUNT 14 308 309 /* 310 * DM_ULOG_STATUS_INFO corresponds to (found in dm-dirty-log.h): 311 * int (*status)(struct dm_dirty_log *log, STATUSTYPE_INFO, 312 * char *result, unsigned maxlen); 313 * 314 * Payload-to-userspace: 315 * None. 316 * Payload-to-kernel: 317 * Character string containing STATUSTYPE_INFO 318 * 319 * When the request has been processed, user-space must return the 320 * dm_ulog_request to the kernel - setting the 'error' field and 321 * 'data_size' appropriately. 322 */ 323 #define DM_ULOG_STATUS_INFO 15 324 325 /* 326 * DM_ULOG_STATUS_TABLE corresponds to (found in dm-dirty-log.h): 327 * int (*status)(struct dm_dirty_log *log, STATUSTYPE_TABLE, 328 * char *result, unsigned maxlen); 329 * 330 * Payload-to-userspace: 331 * None. 332 * Payload-to-kernel: 333 * Character string containing STATUSTYPE_TABLE 334 * 335 * When the request has been processed, user-space must return the 336 * dm_ulog_request to the kernel - setting the 'error' field and 337 * 'data_size' appropriately. 338 */ 339 #define DM_ULOG_STATUS_TABLE 16 340 341 /* 342 * DM_ULOG_IS_REMOTE_RECOVERING corresponds to (found in dm-dirty-log.h): 343 * int (*is_remote_recovering)(struct dm_dirty_log *log, region_t region); 344 * 345 * Payload-to-userspace: 346 * uint64_t - region to determine recovery status on 347 * Payload-to-kernel: 348 * { 349 * int64_t is_recovering; -- 0 if no, 1 if yes 350 * uint64_t in_sync_hint; -- lowest region still needing resync 351 * } 352 * 353 * When the request has been processed, user-space must return the 354 * dm_ulog_request to the kernel - setting the 'error' field and 355 * 'data_size' appropriately. 356 */ 357 #define DM_ULOG_IS_REMOTE_RECOVERING 17 358 359 /* 360 * (DM_ULOG_REQUEST_MASK & request_type) to get the request type 361 * 362 * Payload-to-userspace: 363 * A single string containing all the argv arguments separated by ' 's 364 * Payload-to-kernel: 365 * None. ('data_size' in the dm_ulog_request struct should be 0.) 366 * 367 * We are reserving 8 bits of the 32-bit 'request_type' field for the 368 * various request types above. The remaining 24-bits are currently 369 * set to zero and are reserved for future use and compatibility concerns. 370 * 371 * User-space should always use DM_ULOG_REQUEST_TYPE to acquire the 372 * request type from the 'request_type' field to maintain forward compatibility. 373 */ 374 #define DM_ULOG_REQUEST_MASK 0xFF 375 #define DM_ULOG_REQUEST_TYPE(request_type) \ 376 (DM_ULOG_REQUEST_MASK & (request_type)) 377 378 /* 379 * DM_ULOG_REQUEST_VERSION is incremented when there is a 380 * change to the way information is passed between kernel 381 * and userspace. This could be a structure change of 382 * dm_ulog_request or a change in the way requests are 383 * issued/handled. Changes are outlined here: 384 * version 1: Initial implementation 385 * version 2: DM_ULOG_CTR allowed to return a string containing a 386 * device name that is to be registered with DM via 387 * 'dm_get_device'. 388 */ 389 #define DM_ULOG_REQUEST_VERSION 2 390 391 struct dm_ulog_request { 392 /* 393 * The local unique identifier (luid) and the universally unique 394 * identifier (uuid) are used to tie a request to a specific 395 * mirror log. A single machine log could probably make due with 396 * just the 'luid', but a cluster-aware log must use the 'uuid' and 397 * the 'luid'. The uuid is what is required for node to node 398 * communication concerning a particular log, but the 'luid' helps 399 * differentiate between logs that are being swapped and have the 400 * same 'uuid'. (Think "live" and "inactive" device-mapper tables.) 401 */ 402 uint64_t luid; 403 char uuid[DM_UUID_LEN]; 404 char padding[3]; /* Padding because DM_UUID_LEN = 129 */ 405 406 uint32_t version; /* See DM_ULOG_REQUEST_VERSION */ 407 int32_t error; /* Used to report back processing errors */ 408 409 uint32_t seq; /* Sequence number for request */ 410 uint32_t request_type; /* DM_ULOG_* defined above */ 411 uint32_t data_size; /* How much data (not including this struct) */ 412 413 char data[0]; 414 }; 415 416 #endif /* __DM_LOG_USERSPACE_H__ */ 417