20 * Copyright (c) 2010 Benjamin Marzinski, Redhat
24 lookup_wwid(FILE *f, char *wwid) {
29 while ((c = fgetc(f)) != EOF){
31 if (fgets(buf, LINE_MAX, f) == NULL)
37 while ((c = fgetc(f)) != '/') {
40 if (count >= WWID_SIZE - 1)
42 if (wwid[count] == '\0')
44 if (c != wwid[count++])
47 if (wwid[count] == '\0')
50 if (fgets(buf, LINE_MAX, f) == NULL)
57 write_out_wwid(int fd, char *wwid) {
60 char buf[WWID_SIZE + 3];
62 ret = snprintf(buf, WWID_SIZE + 3, "/%s/\n", wwid);
63 if (ret >= (WWID_SIZE + 3) || ret < 0){
64 condlog(0, "can't format wwid for writing (%d) : %s",
65 ret, strerror(errno));
68 offset = lseek(fd, 0, SEEK_END);
70 condlog(0, "can't seek to the end of wwids file : %s",
74 if (write_all(fd, buf, strlen(buf)) != strlen(buf)) {
75 condlog(0, "cannot write wwid to wwids file : %s",
77 if (ftruncate(fd, offset))
78 condlog(0, "cannot truncate failed wwid write : %s",
86 replace_wwids(vector mp)
89 struct multipath * mpp;
94 conf = get_multipath_config();
95 fd = open_file(conf->wwids_file, &can_write, WWIDS_FILE_HEADER);
96 put_multipath_config(conf);
100 condlog(0, "cannot replace wwids. wwids file is read-only");
103 if (ftruncate(fd, 0) < 0) {
104 condlog(0, "cannot truncate wwids file : %s", strerror(errno));
107 if (lseek(fd, 0, SEEK_SET) < 0) {
108 condlog(0, "cannot seek to the start of the file : %s",
112 len = strlen(WWIDS_FILE_HEADER);
113 if (write_all(fd, WWIDS_FILE_HEADER, len) != len) {
114 condlog(0, "Can't write wwid file header : %s",
116 /* cleanup partially written header */
117 if (ftruncate(fd, 0) < 0)
118 condlog(0, "Cannot truncate header : %s",
122 if (!mp || !mp->allocated) {
126 vector_foreach_slot(mp, mpp, i) {
127 if (write_out_wwid(fd, mpp->wwid) < 0)
138 do_remove_wwid(int fd, char *str) {
145 if (lseek(fd, start, SEEK_SET) < 0) {
146 condlog(0, "wwid file read lseek failed : %s",
150 bytes = read(fd, buf, 4096);
152 if (errno == EINTR || errno == EAGAIN)
154 condlog(0, "failed to read from wwids file : %s",
158 if (!bytes) /* didn't find wwid to remove */
161 ptr = strstr(buf, str);
163 condlog(3, "found '%s'", str);
164 if (lseek(fd, start + (ptr - buf), SEEK_SET) < 0) {
165 condlog(0, "write lseek failed : %s",
170 if (write(fd, "#", 1) < 0) {
171 if (errno == EINTR || errno == EAGAIN)
173 condlog(0, "failed to write to wwids file : %s", strerror(errno));
179 ptr = strrchr(buf, '\n');
180 if (ptr == NULL) { /* shouldn't happen, assume it is EOF */
181 condlog(4, "couldn't find newline, assuming end of file");
184 start = start + (ptr - buf) + 1;
190 remove_wwid(char *wwid) {
191 int fd, len, can_write;
196 len = strlen(wwid) + 4; /* two slashes the newline and a zero byte */
199 condlog(0, "can't allocate memory to remove wwid : %s",
203 if (snprintf(str, len, "/%s/\n", wwid) >= len) {
204 condlog(0, "string overflow trying to remove wwid");
207 condlog(3, "removing line '%s' from wwids file", str);
208 conf = get_multipath_config();
209 fd = open_file(conf->wwids_file, &can_write, WWIDS_FILE_HEADER);
210 put_multipath_config(conf);
214 condlog(0, "cannot remove wwid. wwids file is read-only");
217 ret = do_remove_wwid(fd, str);
227 check_wwids_file(char *wwid, int write_wwid)
229 int fd, can_write, found, ret;
233 conf = get_multipath_config();
234 fd = open_file(conf->wwids_file, &can_write, WWIDS_FILE_HEADER);
235 put_multipath_config(conf);
241 condlog(0,"can't fdopen wwids file : %s", strerror(errno));
245 found = lookup_wwid(f, wwid);
255 condlog(0, "wwids file is read-only. Can't write wwid");
260 if (fflush(f) != 0) {
261 condlog(0, "cannot fflush wwids file stream : %s",
267 ret = write_out_wwid(fd, wwid);
274 should_multipath(struct path *pp1, vector pathvec)
276 int i, ignore_new_devs;
280 conf = get_multipath_config();
281 ignore_new_devs = conf->ignore_new_devs;
282 if (!conf->find_multipaths && !ignore_new_devs) {
283 put_multipath_config(conf);
286 put_multipath_config(conf);
288 condlog(4, "checking if %s should be multipathed", pp1->dev);
289 if (!ignore_new_devs) {
290 vector_foreach_slot(pathvec, pp2, i) {
291 if (pp1->dev == pp2->dev)
293 if (strncmp(pp1->wwid, pp2->wwid, WWID_SIZE) == 0) {
294 condlog(3, "found multiple paths with wwid %s, "
295 "multipathing %s", pp1->wwid, pp1->dev);
300 if (check_wwids_file(pp1->wwid, 0) < 0) {
301 condlog(3, "wwid %s not in wwids file, skipping %s",
302 pp1->wwid, pp1->dev);
305 condlog(3, "found wwid %s in wwids file, multipathing %s", pp1->wwid,
311 remember_wwid(char *wwid)
313 int ret = check_wwids_file(wwid, 1);
315 condlog(3, "failed writing wwid %s to wwids file", wwid);
319 condlog(3, "wrote wwid %s to wwids file", wwid);
321 condlog(4, "wwid %s already in wwids file", wwid);