]> git.ipfire.org Git - ipfire-3.x.git/blob - multipath-tools/patches/0057-UP-fix-tmo.patch
0bfc46bc2006ee0a2a2d497f0401917135c30555
[ipfire-3.x.git] / multipath-tools / patches / 0057-UP-fix-tmo.patch
1 ---
2 libmultipath/discovery.c | 109 +++++++++++++++++++++++++++++++++++++----------
3 libmultipath/sysfs.c | 86 +++++++++++++++++++++++++++++++------
4 libmultipath/sysfs.h | 2
5 3 files changed, 161 insertions(+), 36 deletions(-)
6
7 Index: multipath-tools-130222/libmultipath/discovery.c
8 ===================================================================
9 --- multipath-tools-130222.orig/libmultipath/discovery.c
10 +++ multipath-tools-130222/libmultipath/discovery.c
11 @@ -162,7 +162,6 @@ declare_sysfs_get_str(cutype);
12 declare_sysfs_get_str(vendor);
13 declare_sysfs_get_str(model);
14 declare_sysfs_get_str(rev);
15 -declare_sysfs_get_str(state);
16 declare_sysfs_get_str(dev);
17
18 int
19 @@ -315,9 +314,14 @@ static void
20 sysfs_set_rport_tmo(struct multipath *mpp, struct path *pp)
21 {
22 struct udev_device *rport_dev = NULL;
23 - char value[11];
24 + char value[16];
25 char rport_id[32];
26 + int delay_fast_io_fail = 0;
27 + int current_dev_loss = 0;
28 + int ret;
29
30 + if (!mpp->dev_loss && mpp->fast_io_fail == MP_FAST_IO_FAIL_UNSET)
31 + return;
32 sprintf(rport_id, "rport-%d:%d-%d",
33 pp->sg_id.host_no, pp->sg_id.channel, pp->sg_id.transport_id);
34 rport_dev = udev_device_new_from_subsystem_sysname(conf->udev,
35 @@ -330,33 +334,85 @@ sysfs_set_rport_tmo(struct multipath *mp
36 condlog(4, "target%d:%d:%d -> %s", pp->sg_id.host_no,
37 pp->sg_id.channel, pp->sg_id.scsi_id, rport_id);
38
39 - snprintf(value, 11, "%u", mpp->dev_loss);
40 - if (mpp->dev_loss &&
41 - sysfs_attr_set_value(rport_dev, "dev_loss_tmo", value, 11) <= 0) {
42 - if ((mpp->fast_io_fail == MP_FAST_IO_FAIL_UNSET ||
43 - mpp->fast_io_fail == MP_FAST_IO_FAIL_OFF)
44 - && mpp->dev_loss > 600) {
45 - condlog(3, "%s: limiting dev_loss_tmo to 600, since "
46 - "fast_io_fail is not set", mpp->alias);
47 - snprintf(value, 11, "%u", 600);
48 - if (sysfs_attr_set_value(rport_dev, "dev_loss_tmo",
49 - value, 11) <= 0)
50 - condlog(0, "%s failed to set dev_loss_tmo",
51 - mpp->alias);
52 + memset(value, 0, 16);
53 + if (mpp->fast_io_fail != MP_FAST_IO_FAIL_UNSET) {
54 + ret = sysfs_attr_get_value(rport_dev, "dev_loss_tmo",
55 + value, 16);
56 + if (ret <= 0) {
57 + condlog(0, "%s: failed to read dev_loss_tmo value, "
58 + "error %d", rport_id, -ret);
59 goto out;
60 }
61 + if (sscanf(value, "%u\n", &current_dev_loss) != 1) {
62 + condlog(0, "%s: Cannot parse dev_loss_tmo "
63 + "attribute '%s'", rport_id, value);
64 + goto out;
65 + }
66 + if ((mpp->dev_loss &&
67 + mpp->fast_io_fail >= (int)mpp->dev_loss) ||
68 + (!mpp->dev_loss &&
69 + mpp->fast_io_fail >= (int)current_dev_loss)) {
70 + condlog(3, "%s: limiting fast_io_fail_tmo to %d, since "
71 + "it must be less than dev_loss_tmo",
72 + rport_id, mpp->dev_loss - 1);
73 + if (mpp->dev_loss)
74 + mpp->fast_io_fail = mpp->dev_loss - 1;
75 + else
76 + mpp->fast_io_fail = current_dev_loss - 1;
77 + }
78 + if (mpp->fast_io_fail >= (int)current_dev_loss)
79 + delay_fast_io_fail = 1;
80 + }
81 + if (mpp->dev_loss > 600 &&
82 + (mpp->fast_io_fail == MP_FAST_IO_FAIL_OFF ||
83 + mpp->fast_io_fail == MP_FAST_IO_FAIL_UNSET)) {
84 + condlog(3, "%s: limiting dev_loss_tmo to 600, since "
85 + "fast_io_fail is unset or off", rport_id);
86 + mpp->dev_loss = 600;
87 }
88 - if (mpp->fast_io_fail != MP_FAST_IO_FAIL_UNSET){
89 + if (mpp->fast_io_fail != MP_FAST_IO_FAIL_UNSET) {
90 if (mpp->fast_io_fail == MP_FAST_IO_FAIL_OFF)
91 sprintf(value, "off");
92 else if (mpp->fast_io_fail == MP_FAST_IO_FAIL_ZERO)
93 sprintf(value, "0");
94 + else if (delay_fast_io_fail)
95 + snprintf(value, 16, "%u", current_dev_loss - 1);
96 else
97 - snprintf(value, 11, "%u", mpp->fast_io_fail);
98 - if (sysfs_attr_set_value(rport_dev, "fast_io_fail_tmo",
99 - value, 11) <= 0) {
100 - condlog(0, "%s failed to set fast_io_fail_tmo",
101 - mpp->alias);
102 + snprintf(value, 16, "%u", mpp->fast_io_fail);
103 + ret = sysfs_attr_set_value(rport_dev, "fast_io_fail_tmo",
104 + value, strlen(value));
105 + if (ret <= 0) {
106 + if (ret == -EBUSY)
107 + condlog(3, "%s: rport blocked", rport_id);
108 + else
109 + condlog(0, "%s: failed to set fast_io_fail_tmo to %s, error %d",
110 + rport_id, value, -ret);
111 + goto out;
112 + }
113 + }
114 + if (mpp->dev_loss) {
115 + snprintf(value, 16, "%u", mpp->dev_loss);
116 + ret = sysfs_attr_set_value(rport_dev, "dev_loss_tmo",
117 + value, strlen(value));
118 + if (ret <= 0) {
119 + if (ret == -EBUSY)
120 + condlog(3, "%s: rport blocked", rport_id);
121 + else
122 + condlog(0, "%s: failed to set dev_loss_tmo to %s, error %d",
123 + rport_id, value, -ret);
124 + goto out;
125 + }
126 + }
127 + if (delay_fast_io_fail) {
128 + snprintf(value, 16, "%u", mpp->fast_io_fail);
129 + ret = sysfs_attr_set_value(rport_dev, "fast_io_fail_tmo",
130 + value, strlen(value));
131 + if (ret <= 0) {
132 + if (ret == -EBUSY)
133 + condlog(3, "%s: rport blocked", rport_id);
134 + else
135 + condlog(0, "%s: failed to set fast_io_fail_tmo to %s, error %d",
136 + rport_id, value, -ret);
137 }
138 }
139 out:
140 @@ -394,7 +450,7 @@ sysfs_set_session_tmo(struct multipath *
141 } else {
142 snprintf(value, 11, "%u", mpp->fast_io_fail);
143 if (sysfs_attr_set_value(session_dev, "recovery_tmo",
144 - value, 11)) {
145 + value, 11) <= 0) {
146 condlog(3, "%s: Failed to set recovery_tmo, "
147 " error %d", pp->dev, errno);
148 }
149 @@ -752,6 +808,9 @@ cciss_sysfs_pathinfo (struct path * pp)
150 static int
151 common_sysfs_pathinfo (struct path * pp)
152 {
153 + if (!pp)
154 + return 1;
155 +
156 if (!pp->udev) {
157 condlog(4, "%s: udev not initialised", pp->dev);
158 return 1;
159 @@ -793,7 +852,8 @@ path_offline (struct path * pp)
160 return PATH_DOWN;
161 }
162
163 - if (sysfs_get_state(parent, buff, SCSI_STATE_SIZE))
164 + memset(buff, 0x0, SCSI_STATE_SIZE);
165 + if (sysfs_attr_get_value(parent, "state", buff, SCSI_STATE_SIZE) <= 0)
166 return PATH_DOWN;
167
168 condlog(3, "%s: path state = %s", pp->dev, buff);
169 @@ -983,6 +1043,9 @@ pathinfo (struct path *pp, vector hwtabl
170 {
171 int path_state;
172
173 + if (!pp)
174 + return 1;
175 +
176 condlog(3, "%s: mask = 0x%x", pp->dev, mask);
177
178 /*
179 Index: multipath-tools-130222/libmultipath/sysfs.c
180 ===================================================================
181 --- multipath-tools-130222.orig/libmultipath/sysfs.c
182 +++ multipath-tools-130222/libmultipath/sysfs.c
183 @@ -38,7 +38,12 @@
184 #include "debug.h"
185 #include "devmapper.h"
186
187 -ssize_t sysfs_attr_set_value(struct udev_device *dev, const char *attr_name,
188 +/*
189 + * When we modify an attribute value we cannot rely on libudev for now,
190 + * as libudev lacks the capability to update an attribute value.
191 + * So for modified attributes we need to implement our own function.
192 + */
193 +ssize_t sysfs_attr_get_value(struct udev_device *dev, const char *attr_name,
194 char * value, size_t value_len)
195 {
196 char devpath[PATH_SIZE];
197 @@ -54,28 +59,83 @@ ssize_t sysfs_attr_set_value(struct udev
198 condlog(4, "open '%s'", devpath);
199 if (stat(devpath, &statbuf) != 0) {
200 condlog(4, "stat '%s' failed: %s", devpath, strerror(errno));
201 - return 0;
202 + return -errno;
203 }
204
205 /* skip directories */
206 - if (S_ISDIR(statbuf.st_mode))
207 - return 0;
208 + if (S_ISDIR(statbuf.st_mode)) {
209 + condlog(4, "%s is a directory", devpath);
210 + return -EISDIR;
211 + }
212
213 /* skip non-writeable files */
214 - if ((statbuf.st_mode & S_IWUSR) == 0)
215 + if ((statbuf.st_mode & S_IRUSR) == 0) {
216 + condlog(4, "%s is not readable", devpath);
217 + return -EPERM;
218 + }
219 +
220 + /* read attribute value */
221 + fd = open(devpath, O_RDONLY);
222 + if (fd < 0) {
223 + condlog(4, "attribute '%s' can not be opened: %s",
224 + devpath, strerror(errno));
225 + return -errno;
226 + }
227 + size = read(fd, value, value_len);
228 + if (size < 0) {
229 + condlog(4, "read from %s failed: %s", devpath, strerror(errno));
230 + size = -errno;
231 + } else if (size == value_len) {
232 + condlog(4, "overflow while reading from %s", devpath);
233 + size = 0;
234 + }
235 +
236 + close(fd);
237 + return size;
238 +}
239 +
240 +ssize_t sysfs_attr_set_value(struct udev_device *dev, const char *attr_name,
241 + char * value, size_t value_len)
242 +{
243 + char devpath[PATH_SIZE];
244 + struct stat statbuf;
245 + int fd;
246 + ssize_t size = -1;
247 +
248 + if (!dev || !attr_name || !value || !value_len)
249 return 0;
250
251 + snprintf(devpath, PATH_SIZE, "%s/%s", udev_device_get_syspath(dev),
252 + attr_name);
253 + condlog(4, "open '%s'", devpath);
254 + if (stat(devpath, &statbuf) != 0) {
255 + condlog(4, "stat '%s' failed: %s", devpath, strerror(errno));
256 + return -errno;
257 + }
258 +
259 + /* skip directories */
260 + if (S_ISDIR(statbuf.st_mode)) {
261 + condlog(4, "%s is a directory", devpath);
262 + return -EISDIR;
263 + }
264 +
265 + /* skip non-writeable files */
266 + if ((statbuf.st_mode & S_IWUSR) == 0) {
267 + condlog(4, "%s is not writeable", devpath);
268 + return -EPERM;
269 + }
270 +
271 /* write attribute value */
272 fd = open(devpath, O_WRONLY);
273 if (fd < 0) {
274 condlog(4, "attribute '%s' can not be opened: %s",
275 devpath, strerror(errno));
276 - return 0;
277 + return -errno;
278 }
279 size = write(fd, value, value_len);
280 if (size < 0) {
281 condlog(4, "write to %s failed: %s", devpath, strerror(errno));
282 - size = 0;
283 + size = -errno;
284 } else if (size < value_len) {
285 condlog(4, "tried to write %ld to %s. Wrote %ld",
286 (long)value_len, devpath, (long)size);
287 @@ -89,14 +149,14 @@ ssize_t sysfs_attr_set_value(struct udev
288 int
289 sysfs_get_size (struct path *pp, unsigned long long * size)
290 {
291 - const char * attr;
292 + char attr[255];
293 int r;
294
295 - if (!pp->udev)
296 + if (!pp->udev || !size)
297 return 1;
298
299 - attr = udev_device_get_sysattr_value(pp->udev, "size");
300 - if (!attr) {
301 + attr[0] = '\0';
302 + if (sysfs_attr_get_value(pp->udev, "size", attr, 255) == 0) {
303 condlog(3, "%s: No size attribute in sysfs", pp->dev);
304 return 1;
305 }
306 @@ -104,8 +164,8 @@ sysfs_get_size (struct path *pp, unsigne
307 r = sscanf(attr, "%llu\n", size);
308
309 if (r != 1) {
310 - condlog(3, "%s: Cannot parse size attribute '%s'",
311 - pp->dev, attr);
312 + condlog(3, "%s: Cannot parse size attribute", pp->dev);
313 + *size = 0;
314 return 1;
315 }
316
317 Index: multipath-tools-130222/libmultipath/sysfs.h
318 ===================================================================
319 --- multipath-tools-130222.orig/libmultipath/sysfs.h
320 +++ multipath-tools-130222/libmultipath/sysfs.h
321 @@ -7,6 +7,8 @@
322
323 ssize_t sysfs_attr_set_value(struct udev_device *dev, const char *attr_name,
324 char * value, size_t value_len);
325 +ssize_t sysfs_attr_get_value(struct udev_device *dev, const char *attr_name,
326 + char * value, size_t value_len);
327 int sysfs_get_size (struct path *pp, unsigned long long * size);
328 int sysfs_check_holders(char * check_devt, char * new_devt);
329 #endif