]>
Commit | Line | Data |
---|---|---|
289c5516 MT |
1 | --- |
2 | libmultipath/Makefile | 6 ++ | |
3 | libmultipath/config.c | 3 + | |
4 | libmultipath/config.h | 3 + | |
5 | libmultipath/configure.c | 1 | |
6 | libmultipath/defaults.h | 1 | |
7 | libmultipath/devmapper.c | 130 +++++++++++++++++++++++++++++++++++++++------ | |
8 | libmultipath/devmapper.h | 12 ++-- | |
9 | libmultipath/dict.c | 116 +++++++++++++++++++++++++++++++++++++++- | |
10 | libmultipath/propsel.c | 28 +++++++++ | |
11 | libmultipath/propsel.h | 1 | |
12 | libmultipath/structs.h | 8 ++ | |
13 | libmultipath/structs_vec.c | 3 - | |
14 | multipath/multipath.conf.5 | 14 ++++ | |
15 | multipathd/main.c | 23 +++++-- | |
16 | 14 files changed, 322 insertions(+), 27 deletions(-) | |
17 | ||
18 | Index: multipath-tools-130222/libmultipath/config.c | |
19 | =================================================================== | |
20 | --- multipath-tools-130222.orig/libmultipath/config.c | |
21 | +++ multipath-tools-130222/libmultipath/config.c | |
22 | @@ -337,6 +337,7 @@ merge_hwe (struct hwentry * dst, struct | |
23 | merge_num(user_friendly_names); | |
24 | merge_num(retain_hwhandler); | |
25 | merge_num(detect_prio); | |
26 | + merge_num(deferred_remove); | |
27 | ||
28 | /* | |
29 | * Make sure features is consistent with | |
30 | @@ -394,6 +395,7 @@ overwrite_hwe (struct hwentry * dst, str | |
31 | overwrite_num(user_friendly_names); | |
32 | overwrite_num(retain_hwhandler); | |
33 | overwrite_num(detect_prio); | |
34 | + overwrite_num(deferred_remove); | |
35 | ||
36 | /* | |
37 | * Make sure features is consistent with | |
38 | @@ -617,6 +619,7 @@ load_config (char * file, struct udev *u | |
39 | conf->fast_io_fail = DEFAULT_FAST_IO_FAIL; | |
40 | conf->retain_hwhandler = DEFAULT_RETAIN_HWHANDLER; | |
41 | conf->detect_prio = DEFAULT_DETECT_PRIO; | |
42 | + conf->deferred_remove = DEFAULT_DEFERRED_REMOVE; | |
43 | conf->hw_strmatch = 0; | |
44 | conf->force_sync = 0; | |
45 | ||
46 | Index: multipath-tools-130222/libmultipath/config.h | |
47 | =================================================================== | |
48 | --- multipath-tools-130222.orig/libmultipath/config.h | |
49 | +++ multipath-tools-130222/libmultipath/config.h | |
50 | @@ -61,6 +61,7 @@ struct hwentry { | |
51 | int user_friendly_names; | |
52 | int retain_hwhandler; | |
53 | int detect_prio; | |
54 | + int deferred_remove; | |
55 | char * bl_product; | |
56 | }; | |
57 | ||
58 | @@ -84,6 +85,7 @@ struct mpentry { | |
59 | int flush_on_last_del; | |
60 | int attribute_flags; | |
61 | int user_friendly_names; | |
62 | + int deferred_remove; | |
63 | uid_t uid; | |
64 | gid_t gid; | |
65 | mode_t mode; | |
66 | @@ -128,6 +130,7 @@ struct config { | |
67 | int retain_hwhandler; | |
68 | int detect_prio; | |
69 | int force_sync; | |
70 | + int deferred_remove; | |
71 | unsigned int version[3]; | |
72 | ||
73 | char * dev; | |
74 | Index: multipath-tools-130222/libmultipath/configure.c | |
75 | =================================================================== | |
76 | --- multipath-tools-130222.orig/libmultipath/configure.c | |
77 | +++ multipath-tools-130222/libmultipath/configure.c | |
78 | @@ -290,6 +290,7 @@ setup_map (struct multipath * mpp, char | |
79 | select_dev_loss(mpp); | |
80 | select_reservation_key(mpp); | |
81 | select_retain_hwhandler(mpp); | |
82 | + select_deferred_remove(mpp); | |
83 | ||
84 | sysfs_set_scsi_tmo(mpp); | |
85 | /* | |
86 | Index: multipath-tools-130222/libmultipath/defaults.h | |
87 | =================================================================== | |
88 | --- multipath-tools-130222.orig/libmultipath/defaults.h | |
89 | +++ multipath-tools-130222/libmultipath/defaults.h | |
90 | @@ -19,6 +19,7 @@ | |
91 | #define DEFAULT_FAST_IO_FAIL 5 | |
92 | #define DEFAULT_RETAIN_HWHANDLER RETAIN_HWHANDLER_OFF | |
93 | #define DEFAULT_DETECT_PRIO DETECT_PRIO_OFF | |
94 | +#define DEFAULT_DEFERRED_REMOVE DEFERRED_REMOVE_OFF | |
95 | ||
96 | #define DEFAULT_CHECKINT 5 | |
97 | #define MAX_CHECKINT(a) (a << 2) | |
98 | Index: multipath-tools-130222/libmultipath/devmapper.c | |
99 | =================================================================== | |
100 | --- multipath-tools-130222.orig/libmultipath/devmapper.c | |
101 | +++ multipath-tools-130222/libmultipath/devmapper.c | |
102 | @@ -103,7 +103,9 @@ dm_lib_prereq (void) | |
103 | { | |
104 | char version[64]; | |
105 | int v[3]; | |
106 | -#if defined(DM_SUBSYSTEM_UDEV_FLAG0) | |
107 | +#if defined(LIBDM_API_DEFERRED) | |
108 | + int minv[3] = {1, 2, 89}; | |
109 | +#elif defined(DM_SUBSYSTEM_UDEV_FLAG0) | |
110 | int minv[3] = {1, 2, 82}; | |
111 | #elif defined(LIBDM_API_COOKIE) | |
112 | int minv[3] = {1, 2, 38}; | |
113 | @@ -202,7 +204,7 @@ dm_prereq (void) | |
114 | } | |
115 | ||
116 | static int | |
117 | -dm_simplecmd (int task, const char *name, int no_flush, int need_sync, uint16_t udev_flags) { | |
118 | +dm_simplecmd (int task, const char *name, int no_flush, int need_sync, uint16_t udev_flags, int deferred_remove) { | |
119 | int r = 0; | |
120 | int udev_wait_flag = (need_sync && (task == DM_DEVICE_RESUME || | |
121 | task == DM_DEVICE_REMOVE)); | |
122 | @@ -220,7 +222,10 @@ dm_simplecmd (int task, const char *name | |
123 | if (no_flush) | |
124 | dm_task_no_flush(dmt); /* for DM_DEVICE_SUSPEND/RESUME */ | |
125 | #endif | |
126 | - | |
127 | +#ifdef LIBDM_API_DEFERRED | |
128 | + if (deferred_remove) | |
129 | + dm_task_deferred_remove(dmt); | |
130 | +#endif | |
131 | if (udev_wait_flag && !dm_task_set_cookie(dmt, &conf->cookie, ((conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0) | udev_flags)) | |
132 | goto out; | |
133 | r = dm_task_run (dmt); | |
134 | @@ -232,12 +237,18 @@ dm_simplecmd (int task, const char *name | |
135 | ||
136 | extern int | |
137 | dm_simplecmd_flush (int task, const char *name, int needsync, uint16_t udev_flags) { | |
138 | - return dm_simplecmd(task, name, 0, needsync, udev_flags); | |
139 | + return dm_simplecmd(task, name, 0, needsync, udev_flags, 0); | |
140 | } | |
141 | ||
142 | extern int | |
143 | dm_simplecmd_noflush (int task, const char *name, uint16_t udev_flags) { | |
144 | - return dm_simplecmd(task, name, 1, 1, udev_flags); | |
145 | + return dm_simplecmd(task, name, 1, 1, udev_flags, 0); | |
146 | +} | |
147 | + | |
148 | +extern int | |
149 | +dm_device_remove (const char *name, int needsync, int deferred_remove) { | |
150 | + return dm_simplecmd(DM_DEVICE_REMOVE, name, 0, needsync, 0, | |
151 | + deferred_remove); | |
152 | } | |
153 | ||
154 | extern int | |
155 | @@ -653,7 +664,7 @@ out: | |
156 | } | |
157 | ||
158 | extern int | |
159 | -_dm_flush_map (const char * mapname, int need_sync) | |
160 | +_dm_flush_map (const char * mapname, int need_sync, int deferred_remove) | |
161 | { | |
162 | int r; | |
163 | ||
164 | @@ -663,23 +674,46 @@ _dm_flush_map (const char * mapname, int | |
165 | if (dm_type(mapname, TGT_MPATH) <= 0) | |
166 | return 0; /* nothing to do */ | |
167 | ||
168 | - if (dm_remove_partmaps(mapname, need_sync)) | |
169 | + if (dm_remove_partmaps(mapname, need_sync, deferred_remove)) | |
170 | return 1; | |
171 | ||
172 | - if (dm_get_opencount(mapname)) { | |
173 | + if (!deferred_remove && dm_get_opencount(mapname)) { | |
174 | condlog(2, "%s: map in use", mapname); | |
175 | return 1; | |
176 | } | |
177 | ||
178 | - r = dm_simplecmd_flush(DM_DEVICE_REMOVE, mapname, need_sync, 0); | |
179 | + r = dm_device_remove(mapname, need_sync, deferred_remove); | |
180 | ||
181 | if (r) { | |
182 | + if (deferred_remove && dm_map_present(mapname)) { | |
183 | + condlog(4, "multipath map %s remove deferred", | |
184 | + mapname); | |
185 | + return 2; | |
186 | + } | |
187 | condlog(4, "multipath map %s removed", mapname); | |
188 | return 0; | |
189 | } | |
190 | return 1; | |
191 | } | |
192 | ||
193 | +#ifdef LIBDM_API_DEFERRED | |
194 | + | |
195 | +int | |
196 | +dm_flush_map_nopaths(const char * mapname, int deferred_remove) | |
197 | +{ | |
198 | + return _dm_flush_map(mapname, 1, deferred_remove); | |
199 | +} | |
200 | + | |
201 | +#else | |
202 | + | |
203 | +int | |
204 | +dm_flush_map_nopaths(const char * mapname, int deferred_remove) | |
205 | +{ | |
206 | + return _dm_flush_map(mapname, 1, 0); | |
207 | +} | |
208 | + | |
209 | +#endif | |
210 | + | |
211 | extern int | |
212 | dm_suspend_and_flush_map (const char * mapname) | |
213 | { | |
214 | @@ -1076,6 +1110,7 @@ out: | |
215 | ||
216 | struct remove_data { | |
217 | int need_sync; | |
218 | + int deferred_remove; | |
219 | }; | |
220 | ||
221 | static int | |
222 | @@ -1084,25 +1119,90 @@ remove_partmap(char *name, void *data) | |
223 | struct remove_data *rd = (struct remove_data *)data; | |
224 | ||
225 | if (dm_get_opencount(name)) { | |
226 | - dm_remove_partmaps(name, rd->need_sync); | |
227 | - if (dm_get_opencount(name)) { | |
228 | + dm_remove_partmaps(name, rd->need_sync, rd->deferred_remove); | |
229 | + if (!rd->deferred_remove && dm_get_opencount(name)) { | |
230 | condlog(2, "%s: map in use", name); | |
231 | return 1; | |
232 | } | |
233 | } | |
234 | condlog(4, "partition map %s removed", name); | |
235 | - dm_simplecmd_flush(DM_DEVICE_REMOVE, name, | |
236 | - rd->need_sync, 0); | |
237 | + dm_device_remove(name, rd->need_sync, rd->deferred_remove); | |
238 | return 0; | |
239 | } | |
240 | ||
241 | int | |
242 | -dm_remove_partmaps (const char * mapname, int need_sync) | |
243 | +dm_remove_partmaps (const char * mapname, int need_sync, int deferred_remove) | |
244 | { | |
245 | - struct remove_data rd = { need_sync }; | |
246 | + struct remove_data rd = { need_sync, deferred_remove }; | |
247 | return do_foreach_partmaps(mapname, remove_partmap, &rd); | |
248 | } | |
249 | ||
250 | +#ifdef LIBDM_API_DEFERRED | |
251 | + | |
252 | +static int | |
253 | +cancel_remove_partmap (char *name, void *unused) | |
254 | +{ | |
255 | + if (dm_message(name, "@cancel_deferred_remove") != 0) | |
256 | + condlog(0, "%s: can't cancel deferred remove: %s", name, | |
257 | + strerror(errno)); | |
258 | + return 0; | |
259 | +} | |
260 | + | |
261 | +static int | |
262 | +dm_get_deferred_remove (char * mapname) | |
263 | +{ | |
264 | + int r = -1; | |
265 | + struct dm_task *dmt; | |
266 | + struct dm_info info; | |
267 | + | |
268 | + if (!(dmt = dm_task_create(DM_DEVICE_INFO))) | |
269 | + return -1; | |
270 | + | |
271 | + if (!dm_task_set_name(dmt, mapname)) | |
272 | + goto out; | |
273 | + | |
274 | + if (!dm_task_run(dmt)) | |
275 | + goto out; | |
276 | + | |
277 | + if (!dm_task_get_info(dmt, &info)) | |
278 | + goto out; | |
279 | + | |
280 | + r = info.deferred_remove; | |
281 | +out: | |
282 | + dm_task_destroy(dmt); | |
283 | + return r; | |
284 | +} | |
285 | + | |
286 | +int | |
287 | +dm_cancel_deferred_remove (struct multipath *mpp) | |
288 | +{ | |
289 | + int r = 0; | |
290 | + | |
291 | + if (!dm_get_deferred_remove(mpp->alias)) | |
292 | + return 0; | |
293 | + if (mpp->deferred_remove == DEFERRED_REMOVE_IN_PROGRESS) | |
294 | + mpp->deferred_remove = DEFERRED_REMOVE_ON; | |
295 | + | |
296 | + do_foreach_partmaps(mpp->alias, cancel_remove_partmap, NULL); | |
297 | + r = dm_message(mpp->alias, "@cancel_deferred_remove"); | |
298 | + if (r) | |
299 | + condlog(0, "%s: can't cancel deferred remove: %s", mpp->alias, | |
300 | + strerror(errno)); | |
301 | + else | |
302 | + condlog(2, "%s: canceled deferred remove", mpp->alias); | |
303 | + return r; | |
304 | +} | |
305 | + | |
306 | +#else | |
307 | + | |
308 | +int | |
309 | +dm_cancel_deferred_remove (struct multipath *mpp) | |
310 | +{ | |
311 | + return 0; | |
312 | +} | |
313 | + | |
314 | +#endif | |
315 | + | |
316 | static struct dm_info * | |
317 | alloc_dminfo (void) | |
318 | { | |
319 | Index: multipath-tools-130222/libmultipath/devmapper.h | |
320 | =================================================================== | |
321 | --- multipath-tools-130222.orig/libmultipath/devmapper.h | |
322 | +++ multipath-tools-130222/libmultipath/devmapper.h | |
323 | @@ -17,15 +17,18 @@ int dm_prereq (void); | |
324 | int dm_drv_version (unsigned int * version, char * str); | |
325 | int dm_simplecmd_flush (int, const char *, int, uint16_t); | |
326 | int dm_simplecmd_noflush (int, const char *, uint16_t); | |
327 | +int dm_device_remove (const char *, int, int); | |
328 | int dm_addmap_create (struct multipath *mpp, char *params); | |
329 | int dm_addmap_reload (struct multipath *mpp, char *params); | |
330 | int dm_map_present (const char *); | |
331 | int dm_get_map(const char *, unsigned long long *, char *); | |
332 | int dm_get_status(char *, char *); | |
333 | int dm_type(const char *, char *); | |
334 | -int _dm_flush_map (const char *, int); | |
335 | -#define dm_flush_map(mapname) _dm_flush_map(mapname, 1) | |
336 | -#define dm_flush_map_nosync(mapname) _dm_flush_map(mapname, 0) | |
337 | +int _dm_flush_map (const char *, int, int); | |
338 | +int dm_flush_map_nopaths(const char * mapname, int deferred_remove); | |
339 | +#define dm_flush_map(mapname) _dm_flush_map(mapname, 1, 0) | |
340 | +#define dm_flush_map_nosync(mapname) _dm_flush_map(mapname, 0, 0) | |
341 | +int dm_cancel_deferred_remove(struct multipath *mpp); | |
342 | int dm_suspend_and_flush_map(const char * mapname); | |
343 | int dm_flush_maps (void); | |
344 | int dm_fail_path(char * mapname, char * path); | |
345 | @@ -40,7 +43,8 @@ int dm_geteventnr (char *name); | |
346 | int dm_get_major (char *name); | |
347 | int dm_get_minor (char *name); | |
348 | char * dm_mapname(int major, int minor); | |
349 | -int dm_remove_partmaps (const char * mapname, int need_sync); | |
350 | +int dm_remove_partmaps (const char * mapname, int need_sync, | |
351 | + int deferred_remove); | |
352 | int dm_get_uuid(char *name, char *uuid); | |
353 | int dm_get_info (char * mapname, struct dm_info ** dmi); | |
354 | int dm_rename (char * old, char * new); | |
355 | Index: multipath-tools-130222/libmultipath/dict.c | |
356 | =================================================================== | |
357 | --- multipath-tools-130222.orig/libmultipath/dict.c | |
358 | +++ multipath-tools-130222/libmultipath/dict.c | |
359 | @@ -738,6 +738,29 @@ def_force_sync_handler(vector strvec) | |
360 | return 0; | |
361 | } | |
362 | ||
363 | +static int | |
364 | +def_deferred_remove_handler(vector strvec) | |
365 | +{ | |
366 | + char * buff; | |
367 | + | |
368 | + buff = set_value(strvec); | |
369 | + | |
370 | + if (!buff) | |
371 | + return 1; | |
372 | + | |
373 | + if ((strlen(buff) == 2 && !strcmp(buff, "no")) || | |
374 | + (strlen(buff) == 1 && !strcmp(buff, "0"))) | |
375 | + conf->deferred_remove = DEFERRED_REMOVE_OFF; | |
376 | + else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) || | |
377 | + (strlen(buff) == 1 && !strcmp(buff, "1"))) | |
378 | + conf->deferred_remove = DEFERRED_REMOVE_ON; | |
379 | + else | |
380 | + conf->deferred_remove = DEFAULT_DEFERRED_REMOVE; | |
381 | + | |
382 | + FREE(buff); | |
383 | + return 0; | |
384 | +} | |
385 | + | |
386 | /* | |
387 | * blacklist block handlers | |
388 | */ | |
389 | @@ -1445,6 +1468,33 @@ hw_detect_prio_handler(vector strvec) | |
390 | return 0; | |
391 | } | |
392 | ||
393 | +static int | |
394 | +hw_deferred_remove_handler(vector strvec) | |
395 | +{ | |
396 | + struct hwentry *hwe = VECTOR_LAST_SLOT(conf->hwtable); | |
397 | + char * buff; | |
398 | + | |
399 | + if (!hwe) | |
400 | + return 1; | |
401 | + | |
402 | + buff = set_value(strvec); | |
403 | + | |
404 | + if (!buff) | |
405 | + return 1; | |
406 | + | |
407 | + if ((strlen(buff) == 2 && !strcmp(buff, "no")) || | |
408 | + (strlen(buff) == 1 && !strcmp(buff, "0"))) | |
409 | + hwe->deferred_remove = DEFERRED_REMOVE_OFF; | |
410 | + else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) || | |
411 | + (strlen(buff) == 1 && !strcmp(buff, "1"))) | |
412 | + hwe->deferred_remove = DEFERRED_REMOVE_ON; | |
413 | + else | |
414 | + hwe->deferred_remove = DEFERRED_REMOVE_UNDEF; | |
415 | + | |
416 | + FREE(buff); | |
417 | + return 0; | |
418 | +} | |
419 | + | |
420 | /* | |
421 | * multipaths block handlers | |
422 | */ | |
423 | @@ -1920,6 +1970,32 @@ mp_names_handler(vector strvec) | |
424 | return 0; | |
425 | } | |
426 | ||
427 | +static int | |
428 | +mp_deferred_remove_handler(vector strvec) | |
429 | +{ | |
430 | + struct mpentry *mpe = VECTOR_LAST_SLOT(conf->mptable); | |
431 | + char * buff; | |
432 | + | |
433 | + if (!mpe) | |
434 | + return 1; | |
435 | + | |
436 | + buff = set_value(strvec); | |
437 | + if (!buff) | |
438 | + return 1; | |
439 | + | |
440 | + if ((strlen(buff) == 2 && strcmp(buff, "no") == 0) || | |
441 | + (strlen(buff) == 1 && strcmp(buff, "0") == 0)) | |
442 | + mpe->deferred_remove = DEFERRED_REMOVE_OFF; | |
443 | + else if ((strlen(buff) == 3 && strcmp(buff, "yes") == 0) || | |
444 | + (strlen(buff) == 1 && strcmp(buff, "1") == 0)) | |
445 | + mpe->deferred_remove = DEFERRED_REMOVE_ON; | |
446 | + else | |
447 | + mpe->deferred_remove = DEFERRED_REMOVE_UNDEF; | |
448 | + | |
449 | + FREE(buff); | |
450 | + return 0; | |
451 | +} | |
452 | + | |
453 | /* | |
454 | * config file keywords printing | |
455 | */ | |
456 | @@ -2165,7 +2241,7 @@ snprint_mp_reservation_key (char * buff, | |
457 | return snprintf(buff, len, "0x%" PRIx64, prkey); | |
458 | } | |
459 | ||
460 | - static int | |
461 | +static int | |
462 | snprint_mp_user_friendly_names (char * buff, int len, void * data) | |
463 | { | |
464 | struct mpentry * mpe = (struct mpentry *)data; | |
465 | @@ -2179,6 +2255,19 @@ snprint_mp_user_friendly_names (char * b | |
466 | } | |
467 | ||
468 | static int | |
469 | +snprint_mp_deferred_remove (char * buff, int len, void * data) | |
470 | +{ | |
471 | + struct mpentry * mpe = (struct mpentry *)data; | |
472 | + | |
473 | + if (mpe->deferred_remove == DEFERRED_REMOVE_UNDEF) | |
474 | + return 0; | |
475 | + else if (mpe->deferred_remove == DEFERRED_REMOVE_OFF) | |
476 | + return snprintf(buff, len, "no"); | |
477 | + else | |
478 | + return snprintf(buff, len, "yes"); | |
479 | +} | |
480 | + | |
481 | +static int | |
482 | snprint_hw_fast_io_fail(char * buff, int len, void * data) | |
483 | { | |
484 | struct hwentry * hwe = (struct hwentry *)data; | |
485 | @@ -2507,6 +2596,19 @@ snprint_hw_retain_hwhandler_handler(char | |
486 | } | |
487 | ||
488 | static int | |
489 | +snprint_hw_deferred_remove(char * buff, int len, void * data) | |
490 | +{ | |
491 | + struct hwentry * hwe = (struct hwentry *)data; | |
492 | + | |
493 | + if (hwe->deferred_remove == DEFERRED_REMOVE_ON) | |
494 | + return snprintf(buff, len, "yes"); | |
495 | + else if (hwe->deferred_remove == DEFERRED_REMOVE_OFF) | |
496 | + return snprintf(buff, len, "no"); | |
497 | + else | |
498 | + return 0; | |
499 | +} | |
500 | + | |
501 | +static int | |
502 | snprint_detect_prio(char * buff, int len, void * data) | |
503 | { | |
504 | struct hwentry * hwe = (struct hwentry *)data; | |
505 | @@ -2900,6 +3002,15 @@ snprint_def_force_sync(char * buff, int | |
506 | } | |
507 | ||
508 | static int | |
509 | +snprint_def_deferred_remove(char * buff, int len, void * data) | |
510 | +{ | |
511 | + if (conf->deferred_remove == DEFERRED_REMOVE_ON) | |
512 | + return snprintf(buff, len, "yes"); | |
513 | + else | |
514 | + return snprintf(buff, len, "no"); | |
515 | +} | |
516 | + | |
517 | +static int | |
518 | snprint_ble_simple (char * buff, int len, void * data) | |
519 | { | |
520 | struct blentry * ble = (struct blentry *)data; | |
521 | @@ -2968,6 +3079,7 @@ init_keywords(void) | |
522 | install_keyword("detect_prio", &def_detect_prio_handler, &snprint_def_detect_prio); | |
523 | install_keyword("hw_str_match", &def_hw_strmatch_handler, &snprint_def_hw_strmatch); | |
524 | install_keyword("force_sync", &def_force_sync_handler, &snprint_def_force_sync); | |
525 | + install_keyword("deferred_remove", &def_deferred_remove_handler, &snprint_def_deferred_remove); | |
526 | __deprecated install_keyword("default_selector", &def_selector_handler, NULL); | |
527 | __deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL); | |
528 | __deprecated install_keyword("default_uid_attribute", &def_uid_attribute_handler, NULL); | |
529 | @@ -3032,6 +3144,7 @@ init_keywords(void) | |
530 | install_keyword("user_friendly_names", &hw_names_handler, &snprint_hw_user_friendly_names); | |
531 | install_keyword("retain_attached_hw_handler", &hw_retain_hwhandler_handler, &snprint_hw_retain_hwhandler_handler); | |
532 | install_keyword("detect_prio", &hw_detect_prio_handler, &snprint_detect_prio); | |
533 | + install_keyword("deferred_remove", &hw_deferred_remove_handler, &snprint_hw_deferred_remove); | |
534 | install_sublevel_end(); | |
535 | ||
536 | install_keyword_root("multipaths", &multipaths_handler); | |
537 | @@ -3056,5 +3169,6 @@ init_keywords(void) | |
538 | install_keyword("gid", &mp_gid_handler, &snprint_mp_gid); | |
539 | install_keyword("reservation_key", &mp_reservation_key_handler, &snprint_mp_reservation_key); | |
540 | install_keyword("user_friendly_names", &mp_names_handler, &snprint_mp_user_friendly_names); | |
541 | + install_keyword("deferred_remove", &mp_deferred_remove_handler, &snprint_mp_deferred_remove); | |
542 | install_sublevel_end(); | |
543 | } | |
544 | Index: multipath-tools-130222/libmultipath/propsel.c | |
545 | =================================================================== | |
546 | --- multipath-tools-130222.orig/libmultipath/propsel.c | |
547 | +++ multipath-tools-130222/libmultipath/propsel.c | |
548 | @@ -744,6 +744,34 @@ select_retain_hwhandler (struct multipat | |
549 | } | |
550 | ||
551 | extern int | |
552 | +select_deferred_remove (struct multipath *mp) | |
553 | +{ | |
554 | + if (mp->deferred_remove == DEFERRED_REMOVE_IN_PROGRESS) { | |
555 | + condlog(3, "%s: deferred_remove in progress", mp->alias); | |
556 | + return 0; | |
557 | + } | |
558 | + if (mp->mpe && mp->mpe->deferred_remove) { | |
559 | + mp->deferred_remove = mp->mpe->deferred_remove; | |
560 | + condlog(3, "%s: deferred_remove = %i (multipath setting)", | |
561 | + mp->alias, mp->deferred_remove); | |
562 | + return 0; | |
563 | + } | |
564 | + if (mp->hwe && mp->hwe->deferred_remove) { | |
565 | + mp->deferred_remove = mp->hwe->deferred_remove; | |
566 | + condlog(3, "%s: deferred_remove = %d (controller default)", mp->alias, mp->deferred_remove); | |
567 | + return 0; | |
568 | + } | |
569 | + if (conf->deferred_remove) { | |
570 | + mp->deferred_remove = conf->deferred_remove; | |
571 | + condlog(3, "%s: deferred_remove = %d (config file default)", mp->alias, mp->deferred_remove); | |
572 | + return 0; | |
573 | + } | |
574 | + mp->deferred_remove = DEFAULT_DEFERRED_REMOVE; | |
575 | + condlog(3, "%s: deferred_remove = %d (compiled in default)", mp->alias, mp->deferred_remove); | |
576 | + return 0; | |
577 | +} | |
578 | + | |
579 | +extern int | |
580 | select_detect_prio (struct path * pp) | |
581 | { | |
582 | if (pp->hwe && pp->hwe->detect_prio) { | |
583 | Index: multipath-tools-130222/libmultipath/propsel.h | |
584 | =================================================================== | |
585 | --- multipath-tools-130222.orig/libmultipath/propsel.h | |
586 | +++ multipath-tools-130222/libmultipath/propsel.h | |
587 | @@ -20,3 +20,4 @@ int select_dev_loss(struct multipath *mp | |
588 | int select_reservation_key(struct multipath *mp); | |
589 | int select_retain_hwhandler (struct multipath * mp); | |
590 | int select_detect_prio(struct path * pp); | |
591 | +int select_deferred_remove(struct multipath *mp); | |
592 | Index: multipath-tools-130222/libmultipath/structs.h | |
593 | =================================================================== | |
594 | --- multipath-tools-130222.orig/libmultipath/structs.h | |
595 | +++ multipath-tools-130222/libmultipath/structs.h | |
596 | @@ -114,6 +114,13 @@ enum detect_prio_states { | |
597 | DETECT_PRIO_ON, | |
598 | }; | |
599 | ||
600 | +enum deferred_remove_states { | |
601 | + DEFERRED_REMOVE_UNDEF, | |
602 | + DEFERRED_REMOVE_OFF, | |
603 | + DEFERRED_REMOVE_ON, | |
604 | + DEFERRED_REMOVE_IN_PROGRESS, | |
605 | +}; | |
606 | + | |
607 | enum scsi_protocol { | |
608 | SCSI_PROTOCOL_FCP = 0, /* Fibre Channel */ | |
609 | SCSI_PROTOCOL_SPI = 1, /* parallel SCSI */ | |
610 | @@ -207,6 +214,7 @@ struct multipath { | |
611 | int attribute_flags; | |
612 | int fast_io_fail; | |
613 | int retain_hwhandler; | |
614 | + int deferred_remove; | |
615 | unsigned int dev_loss; | |
616 | uid_t uid; | |
617 | gid_t gid; | |
618 | Index: multipath-tools-130222/multipathd/main.c | |
619 | =================================================================== | |
620 | --- multipath-tools-130222.orig/multipathd/main.c | |
621 | +++ multipath-tools-130222/multipathd/main.c | |
622 | @@ -214,19 +214,30 @@ sync_maps_state(vector mpvec) | |
623 | } | |
624 | ||
625 | static int | |
626 | -flush_map(struct multipath * mpp, struct vectors * vecs) | |
627 | +flush_map(struct multipath * mpp, struct vectors * vecs, int nopaths) | |
628 | { | |
629 | + int r; | |
630 | + | |
631 | + if (nopaths) | |
632 | + r = dm_flush_map_nopaths(mpp->alias, mpp->deferred_remove); | |
633 | + else | |
634 | + r = dm_flush_map(mpp->alias); | |
635 | /* | |
636 | * clear references to this map before flushing so we can ignore | |
637 | * the spurious uevent we may generate with the dm_flush_map call below | |
638 | */ | |
639 | - if (dm_flush_map(mpp->alias)) { | |
640 | + if (r) { | |
641 | /* | |
642 | * May not really be an error -- if the map was already flushed | |
643 | * from the device mapper by dmsetup(8) for instance. | |
644 | */ | |
645 | - condlog(0, "%s: can't flush", mpp->alias); | |
646 | - return 1; | |
647 | + if (r == 1) | |
648 | + condlog(0, "%s: can't flush", mpp->alias); | |
649 | + else { | |
650 | + condlog(2, "%s: devmap deferred remove", mpp->alias); | |
651 | + mpp->deferred_remove = DEFERRED_REMOVE_IN_PROGRESS; | |
652 | + } | |
653 | + return r; | |
654 | } | |
655 | else { | |
656 | dm_lib_release(); | |
657 | @@ -372,7 +383,7 @@ ev_remove_map (char * devname, char * al | |
658 | mpp->alias, mpp->dmi->minor, minor); | |
659 | return 0; | |
660 | } | |
661 | - return flush_map(mpp, vecs); | |
662 | + return flush_map(mpp, vecs, 0); | |
663 | } | |
664 | ||
665 | static int | |
666 | @@ -628,7 +639,7 @@ ev_remove_path (struct path *pp, struct | |
667 | mpp->flush_on_last_del = FLUSH_IN_PROGRESS; | |
668 | dm_queue_if_no_path(mpp->alias, 0); | |
669 | } | |
670 | - if (!flush_map(mpp, vecs)) { | |
671 | + if (!flush_map(mpp, vecs, 1)) { | |
672 | condlog(2, "%s: removed map after" | |
673 | " removing all paths", | |
674 | alias); | |
675 | Index: multipath-tools-130222/libmultipath/structs_vec.c | |
676 | =================================================================== | |
677 | --- multipath-tools-130222.orig/libmultipath/structs_vec.c | |
678 | +++ multipath-tools-130222/libmultipath/structs_vec.c | |
679 | @@ -392,6 +392,8 @@ __setup_multipath (struct vectors * vecs | |
680 | set_no_path_retry(mpp); | |
681 | select_pg_timeout(mpp); | |
682 | select_flush_on_last_del(mpp); | |
683 | + if (VECTOR_SIZE(mpp->paths) != 0) | |
684 | + dm_cancel_deferred_remove(mpp); | |
685 | } | |
686 | ||
687 | return 0; | |
688 | @@ -565,7 +567,6 @@ int update_multipath (struct vectors *ve | |
689 | } | |
690 | } | |
691 | } | |
692 | - | |
693 | return 0; | |
694 | } | |
695 | ||
696 | Index: multipath-tools-130222/multipath/multipath.conf.5 | |
697 | =================================================================== | |
698 | --- multipath-tools-130222.orig/multipath/multipath.conf.5 | |
699 | +++ multipath-tools-130222/multipath/multipath.conf.5 | |
700 | @@ -420,6 +420,16 @@ only one checker will run at a time. Th | |
701 | multipathd checkers running in parallel causes significant CPU pressure. The | |
702 | Default is | |
703 | .I no | |
704 | +.TP | |
705 | +.B deferred_remove | |
706 | +If set to | |
707 | +.I yes | |
708 | +, multipathd will do a deferred remove instead of a regular remove when the | |
709 | +last path device has been deleted. This means that if the multipath device is | |
710 | +still in use, it will be freed when the last user closes it. If path is added | |
711 | +to the multipath device before the last user closes it, the deferred remove | |
712 | +will be canceled. Default is | |
713 | +.I no | |
714 | . | |
715 | .SH "blacklist section" | |
716 | The | |
717 | @@ -521,6 +531,8 @@ section: | |
718 | .B features | |
719 | .TP | |
720 | .B reservation_key | |
721 | +.TP | |
722 | +.B deferred_remove | |
723 | .RE | |
724 | .PD | |
725 | .LP | |
726 | @@ -611,6 +623,8 @@ section: | |
727 | .B retain_attached_hw_handler | |
728 | .TP | |
729 | .B detect_prio | |
730 | +.TP | |
731 | +.B deferred_remove | |
732 | .RE | |
733 | .PD | |
734 | .LP | |
735 | Index: multipath-tools-130222/libmultipath/Makefile | |
736 | =================================================================== | |
737 | --- multipath-tools-130222.orig/libmultipath/Makefile | |
738 | +++ multipath-tools-130222/libmultipath/Makefile | |
739 | @@ -36,6 +36,12 @@ ifneq ($(strip $(LIBUDEV_API_RECVBUF)),0 | |
740 | CFLAGS += -DLIBUDEV_API_RECVBUF | |
741 | endif | |
742 | ||
743 | +LIBDM_API_DEFERRED = $(shell grep -Ecs '^[a-z]*[[:space:]]+dm_task_deferred_remove' /usr/include/libdevmapper.h) | |
744 | + | |
745 | +ifneq ($(strip $(LIBDM_API_DEFERRED)),0) | |
746 | + CFLAGS += -DLIBDM_API_DEFERRED | |
747 | +endif | |
748 | + | |
749 | ||
750 | all: $(LIBS) | |
751 |