1 /*	$NetBSD: dm-log-userspace.h,v 1.1.1.1 2009/12/02 00:25:40 haad Exp $	*/
2 
3 /*
4  * Copyright (C) 2006-2009 Red Hat, Inc.
5  *
6  * This file is released under the LGPL.
7  */
8 
9 #ifndef __DM_LOG_USERSPACE_H__
10 #define __DM_LOG_USERSPACE_H__
11 
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  *	None.  ('data_size' in the dm_ulog_request struct should be 0.)
58  *
59  * The UUID contained in the dm_ulog_request structure is the reference that
60  * will be used by all request types to a specific log.  The constructor must
61  * record this assotiation with instance created.
62  *
63  * When the request has been processed, user-space must return the
64  * dm_ulog_request to the kernel - setting the 'error' field and
65  * 'data_size' appropriately.
66  */
67 #define DM_ULOG_CTR                    1
68 
69 /*
70  * DM_ULOG_DTR corresponds to (found in dm-dirty-log.h):
71  * void (*dtr)(struct dm_dirty_log *log);
72  *
73  * Payload-to-userspace:
74  *	A single string containing all the argv arguments separated by ' 's
75  * Payload-to-kernel:
76  *	None.  ('data_size' in the dm_ulog_request struct should be 0.)
77  *
78  * The UUID contained in the dm_ulog_request structure is all that is
79  * necessary to identify the log instance being destroyed.  There is no
80  * payload data.
81  *
82  * When the request has been processed, user-space must return the
83  * dm_ulog_request to the kernel - setting the 'error' field and clearing
84  * 'data_size' appropriately.
85  */
86 #define DM_ULOG_DTR                    2
87 
88 /*
89  * DM_ULOG_PRESUSPEND corresponds to (found in dm-dirty-log.h):
90  * int (*presuspend)(struct dm_dirty_log *log);
91  *
92  * Payload-to-userspace:
93  *	None.
94  * Payload-to-kernel:
95  *	None.
96  *
97  * The UUID contained in the dm_ulog_request structure is all that is
98  * necessary to identify the log instance being presuspended.  There is no
99  * payload data.
100  *
101  * When the request has been processed, user-space must return the
102  * dm_ulog_request to the kernel - setting the 'error' field and
103  * 'data_size' appropriately.
104  */
105 #define DM_ULOG_PRESUSPEND             3
106 
107 /*
108  * DM_ULOG_POSTSUSPEND corresponds to (found in dm-dirty-log.h):
109  * int (*postsuspend)(struct dm_dirty_log *log);
110  *
111  * Payload-to-userspace:
112  *	None.
113  * Payload-to-kernel:
114  *	None.
115  *
116  * The UUID contained in the dm_ulog_request structure is all that is
117  * necessary to identify the log instance being postsuspended.  There is no
118  * payload data.
119  *
120  * When the request has been processed, user-space must return the
121  * dm_ulog_request to the kernel - setting the 'error' field and
122  * 'data_size' appropriately.
123  */
124 #define DM_ULOG_POSTSUSPEND            4
125 
126 /*
127  * DM_ULOG_RESUME corresponds to (found in dm-dirty-log.h):
128  * int (*resume)(struct dm_dirty_log *log);
129  *
130  * Payload-to-userspace:
131  *	None.
132  * Payload-to-kernel:
133  *	None.
134  *
135  * The UUID contained in the dm_ulog_request structure is all that is
136  * necessary to identify the log instance being resumed.  There is no
137  * payload data.
138  *
139  * When the request has been processed, user-space must return the
140  * dm_ulog_request to the kernel - setting the 'error' field and
141  * 'data_size' appropriately.
142  */
143 #define DM_ULOG_RESUME                 5
144 
145 /*
146  * DM_ULOG_GET_REGION_SIZE corresponds to (found in dm-dirty-log.h):
147  * uint32_t (*get_region_size)(struct dm_dirty_log *log);
148  *
149  * Payload-to-userspace:
150  *	None.
151  * Payload-to-kernel:
152  *	uint64_t - contains the region size
153  *
154  * The region size is something that was determined at constructor time.
155  * It is returned in the payload area and 'data_size' is set to
156  * reflect this.
157  *
158  * When the request has been processed, user-space must return the
159  * dm_ulog_request to the kernel - setting the 'error' field appropriately.
160  */
161 #define DM_ULOG_GET_REGION_SIZE        6
162 
163 /*
164  * DM_ULOG_IS_CLEAN corresponds to (found in dm-dirty-log.h):
165  * int (*is_clean)(struct dm_dirty_log *log, region_t region);
166  *
167  * Payload-to-userspace:
168  *	uint64_t - the region to get clean status on
169  * Payload-to-kernel:
170  *	int64_t  - 1 if clean, 0 otherwise
171  *
172  * Payload is sizeof(uint64_t) and contains the region for which the clean
173  * status is being made.
174  *
175  * When the request has been processed, user-space must return the
176  * dm_ulog_request to the kernel - filling the payload with 0 (not clean) or
177  * 1 (clean), setting 'data_size' and 'error' appropriately.
178  */
179 #define DM_ULOG_IS_CLEAN               7
180 
181 /*
182  * DM_ULOG_IN_SYNC corresponds to (found in dm-dirty-log.h):
183  * int (*in_sync)(struct dm_dirty_log *log, region_t region,
184  *		  int can_block);
185  *
186  * Payload-to-userspace:
187  *	uint64_t - the region to get sync status on
188  * Payload-to-kernel:
189  *	int64_t - 1 if in-sync, 0 otherwise
190  *
191  * Exactly the same as 'is_clean' above, except this time asking "has the
192  * region been recovered?" vs. "is the region not being modified?"
193  */
194 #define DM_ULOG_IN_SYNC                8
195 
196 /*
197  * DM_ULOG_FLUSH corresponds to (found in dm-dirty-log.h):
198  * int (*flush)(struct dm_dirty_log *log);
199  *
200  * Payload-to-userspace:
201  *	None.
202  * Payload-to-kernel:
203  *	None.
204  *
205  * No incoming or outgoing payload.  Simply flush log state to disk.
206  *
207  * When the request has been processed, user-space must return the
208  * dm_ulog_request to the kernel - setting the 'error' field and clearing
209  * 'data_size' appropriately.
210  */
211 #define DM_ULOG_FLUSH                  9
212 
213 /*
214  * DM_ULOG_MARK_REGION corresponds to (found in dm-dirty-log.h):
215  * void (*mark_region)(struct dm_dirty_log *log, region_t region);
216  *
217  * Payload-to-userspace:
218  *	uint64_t [] - region(s) to mark
219  * Payload-to-kernel:
220  *	None.
221  *
222  * Incoming payload contains the one or more regions to mark dirty.
223  * The number of regions contained in the payload can be determined from
224  * 'data_size/sizeof(uint64_t)'.
225  *
226  * When the request has been processed, user-space must return the
227  * dm_ulog_request to the kernel - setting the 'error' field and clearing
228  * 'data_size' appropriately.
229  */
230 #define DM_ULOG_MARK_REGION           10
231 
232 /*
233  * DM_ULOG_CLEAR_REGION corresponds to (found in dm-dirty-log.h):
234  * void (*clear_region)(struct dm_dirty_log *log, region_t region);
235  *
236  * Payload-to-userspace:
237  *	uint64_t [] - region(s) to clear
238  * Payload-to-kernel:
239  *	None.
240  *
241  * Incoming payload contains the one or more regions to mark clean.
242  * The number of regions contained in the payload can be determined from
243  * 'data_size/sizeof(uint64_t)'.
244  *
245  * When the request has been processed, user-space must return the
246  * dm_ulog_request to the kernel - setting the 'error' field and clearing
247  * 'data_size' appropriately.
248  */
249 #define DM_ULOG_CLEAR_REGION          11
250 
251 /*
252  * DM_ULOG_GET_RESYNC_WORK corresponds to (found in dm-dirty-log.h):
253  * int (*get_resync_work)(struct dm_dirty_log *log, region_t *region);
254  *
255  * Payload-to-userspace:
256  *	None.
257  * Payload-to-kernel:
258  *	{
259  *		int64_t i; -- 1 if recovery necessary, 0 otherwise
260  *		uint64_t r; -- The region to recover if i=1
261  *	}
262  * 'data_size' should be set appropriately.
263  *
264  * When the request has been processed, user-space must return the
265  * dm_ulog_request to the kernel - setting the 'error' field appropriately.
266  */
267 #define DM_ULOG_GET_RESYNC_WORK       12
268 
269 /*
270  * DM_ULOG_SET_REGION_SYNC corresponds to (found in dm-dirty-log.h):
271  * void (*set_region_sync)(struct dm_dirty_log *log,
272  *			   region_t region, int in_sync);
273  *
274  * Payload-to-userspace:
275  *	{
276  *		uint64_t - region to set sync state on
277  *		int64_t  - 0 if not-in-sync, 1 if in-sync
278  *	}
279  * Payload-to-kernel:
280  *	None.
281  *
282  * When the request has been processed, user-space must return the
283  * dm_ulog_request to the kernel - setting the 'error' field and clearing
284  * 'data_size' appropriately.
285  */
286 #define DM_ULOG_SET_REGION_SYNC       13
287 
288 /*
289  * DM_ULOG_GET_SYNC_COUNT corresponds to (found in dm-dirty-log.h):
290  * region_t (*get_sync_count)(struct dm_dirty_log *log);
291  *
292  * Payload-to-userspace:
293  *	None.
294  * Payload-to-kernel:
295  *	uint64_t - the number of in-sync regions
296  *
297  * No incoming payload.  Kernel-bound payload contains the number of
298  * regions that are in-sync (in a size_t).
299  *
300  * When the request has been processed, user-space must return the
301  * dm_ulog_request to the kernel - setting the 'error' field and
302  * 'data_size' appropriately.
303  */
304 #define DM_ULOG_GET_SYNC_COUNT        14
305 
306 /*
307  * DM_ULOG_STATUS_INFO corresponds to (found in dm-dirty-log.h):
308  * int (*status)(struct dm_dirty_log *log, STATUSTYPE_INFO,
309  *		 char *result, unsigned maxlen);
310  *
311  * Payload-to-userspace:
312  *	None.
313  * Payload-to-kernel:
314  *	Character string containing STATUSTYPE_INFO
315  *
316  * When the request has been processed, user-space must return the
317  * dm_ulog_request to the kernel - setting the 'error' field and
318  * 'data_size' appropriately.
319  */
320 #define DM_ULOG_STATUS_INFO           15
321 
322 /*
323  * DM_ULOG_STATUS_TABLE corresponds to (found in dm-dirty-log.h):
324  * int (*status)(struct dm_dirty_log *log, STATUSTYPE_TABLE,
325  *		 char *result, unsigned maxlen);
326  *
327  * Payload-to-userspace:
328  *	None.
329  * Payload-to-kernel:
330  *	Character string containing STATUSTYPE_TABLE
331  *
332  * When the request has been processed, user-space must return the
333  * dm_ulog_request to the kernel - setting the 'error' field and
334  * 'data_size' appropriately.
335  */
336 #define DM_ULOG_STATUS_TABLE          16
337 
338 /*
339  * DM_ULOG_IS_REMOTE_RECOVERING corresponds to (found in dm-dirty-log.h):
340  * int (*is_remote_recovering)(struct dm_dirty_log *log, region_t region);
341  *
342  * Payload-to-userspace:
343  *	uint64_t - region to determine recovery status on
344  * Payload-to-kernel:
345  *	{
346  *		int64_t is_recovering;  -- 0 if no, 1 if yes
347  *		uint64_t in_sync_hint;  -- lowest region still needing resync
348  *	}
349  *
350  * When the request has been processed, user-space must return the
351  * dm_ulog_request to the kernel - setting the 'error' field and
352  * 'data_size' appropriately.
353  */
354 #define DM_ULOG_IS_REMOTE_RECOVERING  17
355 
356 /*
357  * (DM_ULOG_REQUEST_MASK & request_type) to get the request type
358  *
359  * Payload-to-userspace:
360  *	A single string containing all the argv arguments separated by ' 's
361  * Payload-to-kernel:
362  *	None.  ('data_size' in the dm_ulog_request struct should be 0.)
363  *
364  * We are reserving 8 bits of the 32-bit 'request_type' field for the
365  * various request types above.  The remaining 24-bits are currently
366  * set to zero and are reserved for future use and compatibility concerns.
367  *
368  * User-space should always use DM_ULOG_REQUEST_TYPE to aquire the
369  * request type from the 'request_type' field to maintain forward compatibility.
370  */
371 #define DM_ULOG_REQUEST_MASK 0xFF
372 #define DM_ULOG_REQUEST_TYPE(request_type) \
373 	(DM_ULOG_REQUEST_MASK & (request_type))
374 
375 struct dm_ulog_request {
376 	/*
377 	 * The local unique identifier (luid) and the universally unique
378 	 * identifier (uuid) are used to tie a request to a specific
379 	 * mirror log.  A single machine log could probably make due with
380 	 * just the 'luid', but a cluster-aware log must use the 'uuid' and
381 	 * the 'luid'.  The uuid is what is required for node to node
382 	 * communication concerning a particular log, but the 'luid' helps
383 	 * differentiate between logs that are being swapped and have the
384 	 * same 'uuid'.  (Think "live" and "inactive" device-mapper tables.)
385 	 */
386 	uint64_t luid;
387 	char uuid[DM_UUID_LEN];
388 	char padding[7];        /* Padding because DM_UUID_LEN = 129 */
389 
390 	int32_t error;          /* Used to report back processing errors */
391 
392 	uint32_t seq;           /* Sequence number for request */
393 	uint32_t request_type;  /* DM_ULOG_* defined above */
394 	uint32_t data_size;     /* How much data (not including this struct) */
395 
396 	char data[0];
397 };
398 
399 #endif /* __DM_LOG_USERSPACE_H__ */
400