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[]; |
430 | }; |
431 | |
432 | #endif /* __DM_LOG_USERSPACE_H__ */ |
433 | |