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