File: checkers.h

package info (click to toggle)
multipath-tools 0.14.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 4,088 kB
  • sloc: ansic: 64,885; perl: 1,622; makefile: 742; sh: 732; pascal: 155
file content (221 lines) | stat: -rw-r--r-- 7,269 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
#ifndef CHECKERS_H_INCLUDED
#define CHECKERS_H_INCLUDED

#include <pthread.h>
#include <stdbool.h>
#include "list.h"
#include "defaults.h"

/*
 *
 * Userspace (multipath/multipathd) path states
 *
 * PATH_WILD:
 * - Use: Any checker
 * - Description: Corner case where "fd < 0" for path fd (see checker_check()),
 *   or where a checker detects an unsupported device
 *   (e.g. wrong checker configured for a given device).
 *
 * PATH_UNCHECKED:
 * - Use: Only in directio checker
 * - Description: set when fcntl(F_GETFL) fails to return flags or O_DIRECT
 *   not include in flags, or O_DIRECT read fails
 * - Notes:
 *   - multipathd: uses it to skip over paths in sync_map_state()
 *   - multipath: used in update_paths(); if state==PATH_UNCHECKED, call
 *     pathinfo()
 *
 * PATH_DOWN:
 * - Use: All checkers (directio, emc_clariion, hp_sw, readsector0, tur)
 * - Description: Either a) SG_IO ioctl failed, or b) check condition on some
 *   SG_IO ioctls that succeed (tur, readsector0 checkers); path is down and
 *   you shouldn't try to send commands to it
 *
 * PATH_UP:
 * - Use: All checkers (directio, emc_clariion, hp_sw, readsector0, tur)
 * - Description: Path is up and I/O can be sent to it
 *
 * PATH_SHAKY:
 * - Use: Only emc_clariion
 * - Description: Indicates path not available for "normal" operations
 *
 * PATH_GHOST:
 * - Use: Only hp_sw and rdac
 * - Description: Indicates a "passive/standby" path on active/passive HP
 *   arrays.  These paths will return valid answers to certain SCSI commands
 *   (tur, read_capacity, inquiry, start_stop), but will fail I/O commands.
 *   The path needs an initialization command to be sent to it in order for
 *   I/Os to succeed.
 *
 * PATH_PENDING:
 * - Use: All async checkers
 * - Description: Indicates a check IO is in flight.
 *
 * PATH_TIMEOUT:
 * - Use: Only tur checker
 * - Description: Command timed out
 *
 * PATH REMOVED:
 * - Use: All checkers
 * - Description: Device has been removed from the system
 *
 * PATH_DELAYED:
 * - Use: None of the checkers (returned if the path is being delayed before
 *   reintegration.
 * - Description: If a path fails after being up for less than
 *   delay_watch_checks checks, when it comes back up again, it will not
 *   be marked as up until it has been up for delay_wait_checks checks.
 *   During this time, it is marked as "delayed"
 *
 * PATH_DISCONNECTED is a special ephemeral state used to signal that a path
 * has been disconnected at the storage target (e.g., LUN unmapped). When a
 * checker returns PATH_DISCONNECTED:
 *   1. The path's pp->disconnected field is set to track purge state
 *   2. The state is immediately converted to PATH_DOWN for normal processing
 *   3. If purge_disconnected is enabled, the path will be removed via sysfs
 * This state should never be stored in pp->state or pp->chkrstate; it exists
 * only as a transient return value from checkers to trigger special handling.
 */
enum path_check_state {
	PATH_WILD = 0,
	PATH_UNCHECKED,
	PATH_DOWN,
	PATH_UP,
	PATH_SHAKY,
	PATH_GHOST,
	PATH_PENDING,
	PATH_TIMEOUT,
	PATH_REMOVED,
	PATH_DELAYED,
	PATH_DISCONNECTED, /* Ephemeral: mapped to PATH_DOWN */
	PATH_MAX_STATE
};

#define DIRECTIO     "directio"
#define TUR          "tur"
#define HP_SW        "hp_sw"
#define RDAC         "rdac"
#define EMC_CLARIION "emc_clariion"
#define READSECTOR0  "readsector0"
#define CCISS_TUR    "cciss_tur"
#define NONE         "none"
#define INVALID      "invalid"

#define ASYNC_TIMEOUT_SEC	30

/*
 * strings lengths
 */
#define CHECKER_NAME_LEN 16
#define CHECKER_MSG_LEN 256
#define CHECKER_DEV_LEN 256
#define LIB_CHECKER_NAMELEN 256

/*
 * Generic message IDs for use in checkers.
 */
enum {
	CHECKER_MSGID_NONE = 0,
	CHECKER_MSGID_DISABLED,
	CHECKER_MSGID_NO_FD,
	CHECKER_MSGID_INVALID,
	CHECKER_MSGID_UP,
	CHECKER_MSGID_DOWN,
	CHECKER_MSGID_GHOST,
	CHECKER_MSGID_UNSUPPORTED,
	CHECKER_MSGID_DISCONNECTED,
	CHECKER_GENERIC_MSGTABLE_SIZE,
	CHECKER_FIRST_MSGID = 100,   /* lowest msgid for checkers */
	CHECKER_MSGTABLE_SIZE = 100, /* max msg table size for checkers */
};

struct checker_class;
struct checker {
	struct checker_class *cls;
	int fd;
	unsigned int timeout;
	int disable;
	int path_state;
	short msgid;		             /* checker-internal extra status */
	void * context;                      /* store for persistent data */
	void ** mpcontext;                   /* store for persistent data shared
						multipath-wide. */
};

static inline int checker_selected(const struct checker *c)
{
	return c != NULL && c->cls != NULL;
}

const char *checker_state_name(int);
int init_checkers(void);
void cleanup_checkers (void);
int checker_init (struct checker *, void **);
int checker_mp_init(struct checker *, void **);
void checker_clear (struct checker *);
void checker_put (struct checker *);
void checker_reset (struct checker *);
void checker_set_sync (struct checker *);
void checker_set_async (struct checker *);
void checker_set_fd (struct checker *, int);
void checker_enable (struct checker *);
void checker_disable (struct checker *);
/*
 * start_checker_thread(): start async path checker thread
 *
 * This function provides a wrapper around pthread_create().
 * The created thread will call the DSO's "libcheck_thread" function with the
 * checker context as argument.
 *
 * Rationale:
 * Path checkers that do I/O may hang forever. To avoid blocking, some
 * checkers therefore use asynchronous, detached threads for checking
 * the paths. These threads may continue hanging if multipathd is stopped.
 * In this case, we can't unload the checker DSO at exit. In order to
 * avoid race conditions and crashes, the entry point of the thread
 * needs to be in libmultipath, not in the DSO itself.
 *
 * @param arg: pointer to struct checker_context.
 */
struct checker_context {
	struct checker_class *cls;
};
int start_checker_thread (pthread_t *thread, const pthread_attr_t *attr,
			  struct checker_context *ctx);
int checker_get_state(struct checker *c);
bool checker_need_wait(struct checker *c);
void checker_check (struct checker *, int);
int checker_is_sync(const struct checker *);
const char *checker_name (const struct checker *);
void reset_checker_classes(void);
/*
 * This returns a string that's best prepended with "$NAME checker",
 * where $NAME is the return value of checker_name().
 */
const char *checker_message(const struct checker *);
void checker_clear_message (struct checker *c);
void checker_get(struct checker *, const char *);

/* Prototypes for symbols exported by path checker dynamic libraries (.so) */
int libcheck_check(struct checker *);
int libcheck_init(struct checker *);
void libcheck_free(struct checker *);
void *libcheck_thread(struct checker_context *ctx);
void libcheck_reset(void);
int libcheck_mp_init(struct checker *);
int libcheck_pending(struct checker *c);
bool libcheck_need_wait(struct checker *c);

/*
 * msgid => message map.
 *
 * It only needs to be provided if the checker defines specific
 * message IDs.
 * Message IDs available to checkers start at CHECKER_FIRST_MSG.
 * The msgtable array is 0-based, i.e. msgtable[0] is the message
 * for msgid == CHECKER_FIRST_MSG.
 * The table ends with a NULL element.
 */
extern const char *libcheck_msgtable[];

#endif /* CHECKERS_H_INCLUDED */