Skip to content

Commit cdcde84

Browse files
committed
Merge branch 'queue' into next
2 parents f9ffa87 + a038ae0 commit cdcde84

8 files changed

Lines changed: 103 additions & 81 deletions

File tree

NEWS.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ See [README.md](README.md) for additional information.
4444
set to `once`. Commit 8933b22.
4545
* Avoid potential buffer overflows in the iet and datacore prioritizers.
4646
Commit 4611f97.
47+
* iet prioritizer: avoid misleading error message with systemd 256 and
48+
newer, and properly use udev to derive path parameters. Commit c493f1f.
49+
Fixes [#145](https://github.com/opensvc/multipath-tools/issues/145).
50+
* An overlong partition delimiter (-p option) could cause kpartx to crash.
51+
Fix it. Commit a2f344a.
4752

4853
### Other changes
4954

kpartx/devmapper.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -644,18 +644,19 @@ int dm_find_part(const char *parent, const char *delim, int part,
644644
char dev_t[32];
645645

646646
if (!format_partname(name, namesiz, parent, delim, part)) {
647-
if (verbose)
648-
fprintf(stderr, "partname too small\n");
649-
return 0;
647+
fprintf(stderr, "partition name too long for partition %d\n", part);
648+
return DFP_ERR;
650649
}
651650

652651
r = dm_map_present(name, part_uuid);
653-
if (r == 1 || parent_uuid == NULL || *parent_uuid == '\0')
654-
return r;
652+
if (r == 1)
653+
return DFP_DEVICE_RELOAD;
654+
if (parent_uuid == NULL || *parent_uuid == '\0')
655+
return DFP_DEVICE_CREATE;
655656

656657
uuid = make_prefixed_uuid(part, parent_uuid);
657658
if (!uuid)
658-
return 0;
659+
return DFP_DEVICE_CREATE;
659660

660661
tmp = dm_find_uuid(uuid);
661662
if (tmp == NULL)
@@ -688,14 +689,14 @@ int dm_find_part(const char *parent, const char *delim, int part,
688689
if (r == 1) {
689690
free(tmp);
690691
*part_uuid = uuid;
691-
return 1;
692+
return DFP_DEVICE_RELOAD;
692693
}
693694
if (verbose)
694695
fprintf(stderr, "renaming %s->%s failed\n", tmp, name);
695696
out:
696697
free(uuid);
697698
free(tmp);
698-
return r;
699+
return DFP_DEVICE_CREATE;
699700
}
700701

701702
char *nondm_create_uuid(dev_t devt)

kpartx/devmapper.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#ifndef KPARTX_DEVMAPPER_H_INCLUDED
22
#define KPARTX_DEVMAPPER_H_INCLUDED
33

4+
#include <libdevmapper.h>
5+
46
#ifdef DM_SUBSYSTEM_UDEV_FLAG0
57
#define MPATH_UDEV_RELOAD_FLAG DM_SUBSYSTEM_UDEV_FLAG0
68
#else
@@ -18,6 +20,13 @@ dev_t dm_get_first_dep(char *devname);
1820
char * dm_mapuuid(const char *mapname);
1921
int dm_devn (const char * mapname, unsigned int *major, unsigned int *minor);
2022
int dm_remove_partmaps (char * mapname, char *uuid, dev_t devt, int verbose);
23+
24+
enum {
25+
DFP_DEVICE_CREATE = DM_DEVICE_CREATE,
26+
DFP_DEVICE_RELOAD = DM_DEVICE_RELOAD,
27+
DFP_ERR = -1
28+
};
29+
2130
int dm_find_part(const char *parent, const char *delim, int part,
2231
const char *parent_uuid,
2332
char *name, size_t namesiz, char **part_uuid, int verbose);

kpartx/kpartx.c

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,7 @@ main(int argc, char **argv){
437437
case UPDATE:
438438
/* ADD and UPDATE share the same code that adds new partitions. */
439439
for (j = 0, c = 0; j < n; j++) {
440-
char *part_uuid, *reason;
440+
char *part_uuid = NULL, *reason;
441441

442442
if (slices[j].size == 0)
443443
continue;
@@ -454,10 +454,13 @@ main(int argc, char **argv){
454454
exit(1);
455455
}
456456

457-
op = (dm_find_part(mapname, delim, j + 1, uuid,
458-
partname, sizeof(partname),
459-
&part_uuid, verbose) ?
460-
DM_DEVICE_RELOAD : DM_DEVICE_CREATE);
457+
op = dm_find_part(mapname, delim, j + 1, uuid,
458+
partname, sizeof(partname),
459+
&part_uuid, verbose);
460+
if (op == DFP_ERR) {
461+
r++;
462+
continue;
463+
}
461464

462465
if (part_uuid && uuid) {
463466
if (check_uuid(uuid, part_uuid, &reason) != 0) {
@@ -500,7 +503,7 @@ main(int argc, char **argv){
500503
d = c;
501504
while (c) {
502505
for (j = 0; j < n; j++) {
503-
char *part_uuid, *reason;
506+
char *part_uuid = NULL, *reason;
504507
int k = slices[j].container - 1;
505508

506509
if (slices[j].size == 0)
@@ -526,11 +529,14 @@ main(int argc, char **argv){
526529
exit(1);
527530
}
528531

529-
op = (dm_find_part(mapname, delim, j + 1, uuid,
530-
partname,
531-
sizeof(partname),
532-
&part_uuid, verbose) ?
533-
DM_DEVICE_RELOAD : DM_DEVICE_CREATE);
532+
op = dm_find_part(mapname, delim,
533+
j + 1, uuid, partname,
534+
sizeof(partname),
535+
&part_uuid, verbose);
536+
if (op == DFP_ERR) {
537+
r++;
538+
continue;
539+
}
534540

535541
if (part_uuid && uuid) {
536542
if (check_uuid(uuid, part_uuid, &reason) != 0) {
@@ -570,11 +576,11 @@ main(int argc, char **argv){
570576
}
571577

572578
for (j = MAXSLICES-1; j >= 0; j--) {
573-
char *part_uuid, *reason;
574-
if (slices[j].size ||
575-
!dm_find_part(mapname, delim, j + 1, uuid,
576-
partname, sizeof(partname),
577-
&part_uuid, verbose))
579+
char *part_uuid = NULL, *reason;
580+
int res = dm_find_part(mapname, delim, j + 1, uuid,
581+
partname, sizeof(partname),
582+
&part_uuid, verbose);
583+
if (slices[j].size || res != DFP_DEVICE_RELOAD)
578584
continue;
579585

580586
if (part_uuid && uuid) {

kpartx/test-kpartx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,4 +460,15 @@ $KPARTX -d $KPARTX_OPTS "$FILE4"
460460
# /dev/$loop is _not_ automatically deleted
461461
[[ -b "/dev/${loop}" ]]
462462

463+
step "test kpartx creation with very long partition separator"
464+
# Overlong, invalid partition separator
465+
LONG_SEP="part---01.part---02.part---03.part---04.part---05.part---06.part---07.part---08.part---09.part---10.part---11.part---12.part---13.part---14.part---15.part---16.part---17.part---18.part---19.part---20."
466+
ERR=0
467+
# This kpartx command should return with error 1 (for a single partitition!)
468+
# and print the error message below.
469+
# Without the fix for overlong partition separator, kpartx crashes.
470+
$KPARTX -a -p "$LONG_SEP" "$LO1" 2>"$WORKDIR/long_sep.out" || ERR=$?
471+
[[ $ERR = 1 ]]
472+
grep -q 'partition name too long for partition 1' "$WORKDIR/long_sep.out"
473+
463474
OK=yes

libmultipath/prioritizers/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ include ../../Makefile.inc
88
CPPFLAGS += -I$(multipathdir) -I$(mpathutildir)
99
CFLAGS += $(LIB_CFLAGS)
1010
LDFLAGS += -L$(multipathdir) -L$(mpathutildir)
11-
LIBDEPS = -lmultipath -lmpathutil -lm -lpthread -lrt
11+
LIBDEPS = -lmultipath -lmpathutil -ludev -lm -lpthread -lrt
1212

1313
# If you add or remove a prioritizer also update multipath/multipath.conf.5
1414
LIBS = \

libmultipath/prioritizers/iet.c

Lines changed: 44 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
#include <dirent.h>
21
#include <stdlib.h>
2+
#include <stdbool.h>
33
#include <sys/types.h>
44
#include <sys/stat.h>
55
#include <stdio.h>
66
#include <string.h>
77
#include <regex.h>
8+
#include <libudev.h>
89
#include "prio.h"
910
#include "debug.h"
1011
#include <unistd.h>
@@ -20,19 +21,19 @@
2021
// prio "iet"
2122
// prio_args "preferredip=10.11.12.13"
2223
//
23-
// Uses /dev/disk/by-path to find the IP of the device.
2424
// Assigns prio 20 (high) to the preferred IP and prio 10 (low) to the rest.
2525
//
2626
// by Olivier Lambert <lambert.olivier.gmail.com>
2727
//
2828

29-
#define dc_log(prio, msg) condlog(prio, "%s: iet prio: " msg, dev)
29+
#define dc_log(prio, msg) condlog(prio, "%s: iet prio: " msg, sysname)
30+
3031
//
3132
// name: find_regex
3233
// @param string: string you want to search into
3334
// @param regex: the pattern used
3435
// @return result: string found in string with regex, "none" if none
35-
char *find_regex(char * string, char * regex)
36+
char *find_regex(const char *string, const char *regex)
3637
{
3738
int err;
3839
regex_t preg;
@@ -73,75 +74,64 @@ char *find_regex(char * string, char * regex)
7374
// name: inet_prio
7475
// @param
7576
// @return prio
76-
int iet_prio(const char *dev, char * args)
77+
int iet_prio(struct udev_device *udev, char *args)
7778
{
7879
char preferredip_buff[255] = "";
7980
char *preferredip = &preferredip_buff[0];
81+
const char *by_path;
82+
char *ip;
83+
static bool arg_logged = false;
84+
int prio = 10;
85+
const char *sysname;
86+
87+
if (!udev)
88+
return 0;
89+
sysname = udev_device_get_sysname(udev);
90+
if (!sysname)
91+
sysname = "UNKNOWN";
92+
8093
// Phase 1 : checks. If anyone fails, return prio 0.
8194
// check if args exists
8295
if (!args) {
83-
dc_log(0, "need prio_args with preferredip set");
96+
if (!arg_logged) {
97+
dc_log(2, "need prio_args with preferredip set");
98+
arg_logged = true;
99+
}
84100
return 0;
85101
}
86102
// check if args format is OK
87-
if (sscanf(args, "preferredip=%254s", preferredip) == 1) {
88-
} else {
89-
dc_log(0, "unexpected prio_args format");
103+
if (sscanf(args, "preferredip=%254s", preferredip) != 1) {
104+
if (!arg_logged) {
105+
dc_log(2, "unexpected prio_args format");
106+
arg_logged = true;
107+
}
90108
return 0;
91109
}
92110
// check if ip is not too short
93111
if (strlen(preferredip) <= 7) {
94-
dc_log(0, "prio args: preferredip too short");
112+
if (!arg_logged) {
113+
dc_log(2, "prio args: preferredip too short");
114+
arg_logged = true;
115+
}
95116
return 0;
96117
}
97-
// Phase 2 : find device in /dev/disk/by-path to match device/ip
98-
DIR *dir_p;
99-
struct dirent *dir_entry_p;
100-
enum { BUFFERSIZE = 1024 };
101-
char buffer[BUFFERSIZE];
102-
char fullpath[BUFFERSIZE] = "/dev/disk/by-path/";
103-
dir_p = opendir(fullpath);
104-
if (!dir_p)
105-
goto out;
106118

107-
// loop to find device in /dev/disk/by-path
108-
while( NULL != (dir_entry_p = readdir(dir_p))) {
109-
if (dir_entry_p->d_name[0] != '.') {
110-
char path[BUFFERSIZE] = "/dev/disk/by-path/";
111-
strcat(path,dir_entry_p->d_name);
112-
ssize_t nchars = readlink(path, buffer, sizeof(buffer)-1);
113-
if (nchars != -1) {
114-
char *device;
115-
buffer[nchars] = '\0';
116-
device = find_regex(buffer,"(sd[a-z]+)");
117-
// if device parsed is the right one
118-
if (device!=NULL && strncmp(device, dev, strlen(device)) == 0) {
119-
char *ip;
120-
ip = find_regex(dir_entry_p->d_name,"([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3})");
121-
// if prefferedip and ip fetched matches
122-
if (ip!=NULL && strncmp(ip, preferredip, strlen(ip)) == 0) {
123-
// high prio
124-
free(ip);
125-
free(device);
126-
closedir(dir_p);
127-
return 20;
128-
}
129-
free(ip);
130-
}
131-
free(device);
132-
}
133-
else {
134-
printf("error\n");
135-
}
136-
}
119+
by_path = udev_device_get_property_value(udev, "ID_PATH");
120+
if (by_path == NULL) {
121+
dc_log(2, "failed to get BY_PATH property");
122+
return 0;
137123
}
138-
// nothing found, low prio
139-
closedir(dir_p);
140-
out:
141-
return 10;
124+
condlog(3, "%s: iet prio: by_path=%s", sysname, by_path);
125+
ip = find_regex(by_path,
126+
"([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3})");
127+
if (ip != NULL && strncmp(ip, preferredip, strlen(ip)) == 0)
128+
prio = 20;
129+
130+
free(ip);
131+
return prio;
142132
}
143133

144134
int getprio(struct path * pp, char * args)
145135
{
146-
return iet_prio(pp->dev, args);
136+
return iet_prio(pp->udev, args);
147137
}

libmultipath/version.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111
#ifndef VERSION_H_INCLUDED
1212
#define VERSION_H_INCLUDED
1313

14-
#define VERSION_CODE 0x000E03
14+
#define VERSION_CODE 0x000F00
1515
/* MMDDYY, in hex */
16-
#define DATE_CODE 0x02051A
16+
#define DATE_CODE 0x070D1A
1717

1818
#define PROG "multipath-tools"
1919

0 commit comments

Comments
 (0)