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 * If the 'integrated_flush' directive is present in the constructor 205 * table, the payload is as same as DM_ULOG_MARK_REGION: 206 * uint64_t [] - region(s) to mark 207 * else 208 * None 209 * Payload-to-kernel: 210 * None. 211 * 212 * If the 'integrated_flush' option was used during the creation of the 213 * log, mark region requests are carried as payload in the flush request. 214 * Piggybacking the mark requests in this way allows for fewer communications 215 * between kernel and userspace. 216 * 217 * When the request has been processed, user-space must return the 218 * dm_ulog_request to the kernel - setting the 'error' field and clearing 219 * 'data_size' appropriately. 220 */ 221 #define DM_ULOG_FLUSH 9 222 223 /* 224 * DM_ULOG_MARK_REGION corresponds to (found in dm-dirty-log.h): 225 * void (*mark_region)(struct dm_dirty_log *log, region_t region); 226 * 227 * Payload-to-userspace: 228 * uint64_t [] - region(s) to mark 229 * Payload-to-kernel: 230 * None. 231 * 232 * Incoming payload contains the one or more regions to mark dirty. 233 * The number of regions contained in the payload can be determined from 234 * 'data_size/sizeof(uint64_t)'. 235 * 236 * When the request has been processed, user-space must return the 237 * dm_ulog_request to the kernel - setting the 'error' field and clearing 238 * 'data_size' appropriately. 239 */ 240 #define DM_ULOG_MARK_REGION 10 241 242 /* 243 * DM_ULOG_CLEAR_REGION corresponds to (found in dm-dirty-log.h): 244 * void (*clear_region)(struct dm_dirty_log *log, region_t region); 245 * 246 * Payload-to-userspace: 247 * uint64_t [] - region(s) to clear 248 * Payload-to-kernel: 249 * None. 250 * 251 * Incoming payload contains the one or more regions to mark clean. 252 * The number of regions contained in the payload can be determined from 253 * 'data_size/sizeof(uint64_t)'. 254 * 255 * When the request has been processed, user-space must return the 256 * dm_ulog_request to the kernel - setting the 'error' field and clearing 257 * 'data_size' appropriately. 258 */ 259 #define DM_ULOG_CLEAR_REGION 11 260 261 /* 262 * DM_ULOG_GET_RESYNC_WORK corresponds to (found in dm-dirty-log.h): 263 * int (*get_resync_work)(struct dm_dirty_log *log, region_t *region); 264 * 265 * Payload-to-userspace: 266 * None. 267 * Payload-to-kernel: 268 * { 269 * int64_t i; -- 1 if recovery necessary, 0 otherwise 270 * uint64_t r; -- The region to recover if i=1 271 * } 272 * 'data_size' should be set appropriately. 273 * 274 * When the request has been processed, user-space must return the 275 * dm_ulog_request to the kernel - setting the 'error' field appropriately. 276 */ 277 #define DM_ULOG_GET_RESYNC_WORK 12 278 279 /* 280 * DM_ULOG_SET_REGION_SYNC corresponds to (found in dm-dirty-log.h): 281 * void (*set_region_sync)(struct dm_dirty_log *log, 282 * region_t region, int in_sync); 283 * 284 * Payload-to-userspace: 285 * { 286 * uint64_t - region to set sync state on 287 * int64_t - 0 if not-in-sync, 1 if in-sync 288 * } 289 * Payload-to-kernel: 290 * None. 291 * 292 * When the request has been processed, user-space must return the 293 * dm_ulog_request to the kernel - setting the 'error' field and clearing 294 * 'data_size' appropriately. 295 */ 296 #define DM_ULOG_SET_REGION_SYNC 13 297 298 /* 299 * DM_ULOG_GET_SYNC_COUNT corresponds to (found in dm-dirty-log.h): 300 * region_t (*get_sync_count)(struct dm_dirty_log *log); 301 * 302 * Payload-to-userspace: 303 * None. 304 * Payload-to-kernel: 305 * uint64_t - the number of in-sync regions 306 * 307 * No incoming payload. Kernel-bound payload contains the number of 308 * regions that are in-sync (in a size_t). 309 * 310 * When the request has been processed, user-space must return the 311 * dm_ulog_request to the kernel - setting the 'error' field and 312 * 'data_size' appropriately. 313 */ 314 #define DM_ULOG_GET_SYNC_COUNT 14 315 316 /* 317 * DM_ULOG_STATUS_INFO corresponds to (found in dm-dirty-log.h): 318 * int (*status)(struct dm_dirty_log *log, STATUSTYPE_INFO, 319 * char *result, unsigned maxlen); 320 * 321 * Payload-to-userspace: 322 * None. 323 * Payload-to-kernel: 324 * Character string containing STATUSTYPE_INFO 325 * 326 * When the request has been processed, user-space must return the 327 * dm_ulog_request to the kernel - setting the 'error' field and 328 * 'data_size' appropriately. 329 */ 330 #define DM_ULOG_STATUS_INFO 15 331 332 /* 333 * DM_ULOG_STATUS_TABLE corresponds to (found in dm-dirty-log.h): 334 * int (*status)(struct dm_dirty_log *log, STATUSTYPE_TABLE, 335 * char *result, unsigned maxlen); 336 * 337 * Payload-to-userspace: 338 * None. 339 * Payload-to-kernel: 340 * Character string containing STATUSTYPE_TABLE 341 * 342 * When the request has been processed, user-space must return the 343 * dm_ulog_request to the kernel - setting the 'error' field and 344 * 'data_size' appropriately. 345 */ 346 #define DM_ULOG_STATUS_TABLE 16 347 348 /* 349 * DM_ULOG_IS_REMOTE_RECOVERING corresponds to (found in dm-dirty-log.h): 350 * int (*is_remote_recovering)(struct dm_dirty_log *log, region_t region); 351 * 352 * Payload-to-userspace: 353 * uint64_t - region to determine recovery status on 354 * Payload-to-kernel: 355 * { 356 * int64_t is_recovering; -- 0 if no, 1 if yes 357 * uint64_t in_sync_hint; -- lowest region still needing resync 358 * } 359 * 360 * When the request has been processed, user-space must return the 361 * dm_ulog_request to the kernel - setting the 'error' field and 362 * 'data_size' appropriately. 363 */ 364 #define DM_ULOG_IS_REMOTE_RECOVERING 17 365 366 /* 367 * (DM_ULOG_REQUEST_MASK & request_type) to get the request type 368 * 369 * Payload-to-userspace: 370 * A single string containing all the argv arguments separated by ' 's 371 * Payload-to-kernel: 372 * None. ('data_size' in the dm_ulog_request struct should be 0.) 373 * 374 * We are reserving 8 bits of the 32-bit 'request_type' field for the 375 * various request types above. The remaining 24-bits are currently 376 * set to zero and are reserved for future use and compatibility concerns. 377 * 378 * User-space should always use DM_ULOG_REQUEST_TYPE to acquire the 379 * request type from the 'request_type' field to maintain forward compatibility. 380 */ 381 #define DM_ULOG_REQUEST_MASK 0xFF 382 #define DM_ULOG_REQUEST_TYPE(request_type) \ 383 (DM_ULOG_REQUEST_MASK & (request_type)) 384 385 /* 386 * DM_ULOG_REQUEST_VERSION is incremented when there is a 387 * change to the way information is passed between kernel 388 * and userspace. This could be a structure change of 389 * dm_ulog_request or a change in the way requests are 390 * issued/handled. Changes are outlined here: 391 * version 1: Initial implementation 392 * version 2: DM_ULOG_CTR allowed to return a string containing a 393 * device name that is to be registered with DM via 394 * 'dm_get_device'. 395 * version 3: DM_ULOG_FLUSH is capable of carrying payload for marking 396 * regions. This "integrated flush" reduces the number of 397 * requests between the kernel and userspace by effectively 398 * merging 'mark' and 'flush' requests. A constructor table 399 * argument ('integrated_flush') is required to turn this 400 * feature on, so it is backwards compatible with older 401 * userspace versions. 402 */ 403 #define DM_ULOG_REQUEST_VERSION 3 404 405 struct dm_ulog_request { 406 /* 407 * The local unique identifier (luid) and the universally unique 408 * identifier (uuid) are used to tie a request to a specific 409 * mirror log. A single machine log could probably make due with 410 * just the 'luid', but a cluster-aware log must use the 'uuid' and 411 * the 'luid'. The uuid is what is required for node to node 412 * communication concerning a particular log, but the 'luid' helps 413 * differentiate between logs that are being swapped and have the 414 * same 'uuid'. (Think "live" and "inactive" device-mapper tables.) 415 */ 416 uint64_t luid; 417 char uuid[DM_UUID_LEN]; 418 char padding[3]; /* Padding because DM_UUID_LEN = 129 */ 419 420 uint32_t version; /* See DM_ULOG_REQUEST_VERSION */ 421 int32_t error; /* Used to report back processing errors */ 422 423 uint32_t seq; /* Sequence number for request */ 424 uint32_t request_type; /* DM_ULOG_* defined above */ 425 uint32_t data_size; /* How much data (not including this struct) */ 426 427 char data[0]; 428 }; 429 430 #endif /* __DM_LOG_USERSPACE_H__ */ 431