]> git.ipfire.org Git - people/stevee/ipfire-3.x.git/blob - multipath-tools/patches/0104-RHBZ-631009-deferred-remove.patch
glibc: Disable multilib support on X86_64
[people/stevee/ipfire-3.x.git] / multipath-tools / patches / 0104-RHBZ-631009-deferred-remove.patch
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