2 * sysfs - extract md related information from sysfs. Part of:
3 * mdadm - manage Linux "md" devices aka RAID arrays.
5 * Copyright (C) 2006-2009 Neil Brown <neilb@suse.de>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * Email: <neilb@suse.de>
33 #define MAX_SYSFS_PATH_LEN 120
35 struct dev_sysfs_rule
{
36 struct dev_sysfs_rule
*next
;
41 struct sysfs_entry
*next
;
47 int load_sys(char *path
, char *buf
, int len
)
49 int fd
= open(path
, O_RDONLY
);
53 n
= read(fd
, buf
, len
);
58 if (n
&& buf
[n
-1] == '\n')
63 void sysfs_free(struct mdinfo
*sra
)
66 struct mdinfo
*sra2
= sra
->next
;
68 struct mdinfo
*d
= sra
->devs
;
73 free(sra
->bb
.entries
);
79 mapping_t sysfs_memb_states
[] = {
80 {"external_bbl", MEMB_STATE_EXTERNAL_BBL
},
81 {"blocked", MEMB_STATE_BLOCKED
},
82 {"spare", MEMB_STATE_SPARE
},
83 {"write_mostly", MEMB_STATE_WRITE_MOSTLY
},
84 {"in_sync", MEMB_STATE_IN_SYNC
},
85 {"faulty", MEMB_STATE_FAULTY
},
86 {"remove", MEMB_STATE_REMOVE
},
87 {NULL
, MEMB_STATE_UNKNOWN
}
90 char *map_memb_state(memb_state_t state
)
92 return map_num_s(sysfs_memb_states
, state
);
96 * write_attr() - write value to fd, don't check errno.
97 * @attr: value to write.
98 * @fd: file descriptor write to.
100 * Size to write is calculated by strlen().
102 mdadm_status_t
write_attr(const char *value
, const int fd
)
104 return sysfs_write_descriptor(fd
, value
, strlen(value
), NULL
);
108 * sysfs_write_descriptor()- wrapper for write(), projected to be used with sysfs.
109 * @fd: file descriptor.
110 * @value: value to set.
111 * @len: length of the value.
112 * @errno_p: On write() failure, buffer to copy errno value, might be NULL.
114 * Errors are differentiated, because (at least theoretically) kernel may not process whole string
115 * and it may or may not be a problem (it depends on implementation in kernel). Decision belongs to
117 * Generally, it should be safe to check if @errno_p changed to determine if error occurred.
119 mdadm_status_t
sysfs_write_descriptor(const int fd
, const char *value
, const ssize_t len
,
124 ret
= write(fd
, value
, len
);
128 return MDADM_STATUS_ERROR
;
132 return MDADM_STATUS_UNDEF
;
134 return MDADM_STATUS_SUCCESS
;
138 * sysfs_set_memb_state_fd() - write to md/<memb>/state file.
139 * @fd: open file descriptor to the file.
140 * @state: enum value describing value to write
141 * @err: errno value pointer in case of error.
143 * This is helper to avoid inlining values, they are extracted from map now.
145 mdadm_status_t
sysfs_set_memb_state_fd(int fd
, memb_state_t state
, int *err
)
147 const char *val
= map_memb_state(state
);
149 return sysfs_write_descriptor(fd
, val
, strlen(val
), err
);
153 * sysfs_set_memb_state() - write to member disk state file.
154 * @array_devnm: kernel name of the array.
155 * @memb_devnm: kernel name of member device.
156 * @state: value to write.
158 * Function expects that the device exists, error is unconditionally printed.
160 mdadm_status_t
sysfs_set_memb_state(char *array_devnm
, char *memb_devnm
, memb_state_t state
)
162 int state_fd
= sysfs_open_memb_attr(array_devnm
, memb_devnm
, "state", O_RDWR
);
164 if (!is_fd_valid(state_fd
)) {
165 pr_err("Cannot open file descriptor to %s in array %s, aborting.\n",
166 memb_devnm
, array_devnm
);
167 return MDADM_STATUS_ERROR
;
170 return sysfs_set_memb_state_fd(state_fd
, state
, NULL
);
176 * sysfs_get_container_devnm() - extract container device name.
177 * @mdi: md_info describes member array, with GET_VERSION option.
178 * @buf: buf to fill, must be MD_NAME_MAX.
180 * External array version is in format {/,-}<container_devnm>/<array_index>
181 * Extract container_devnm from it and safe it in @buf.
183 void sysfs_get_container_devnm(struct mdinfo
*mdi
, char *buf
)
187 assert(is_subarray(mdi
->text_version
));
189 /* Skip first special sign */
190 snprintf(buf
, MD_NAME_MAX
, "%s", mdi
->text_version
+ 1);
192 /* Remove array index */
193 p
= strchr(buf
, '/');
199 * sysfs_open_memb_attr() - helper to get sysfs attr descriptor for member device.
200 * @array_devnm: array kernel device name.
201 * @memb_devnm: member device kernel device name.
202 * @attr: requested sysfs attribute.
203 * @oflag: open() flags.
205 * To refer member device directory, we need to append "dev-" before the member device name.
207 int sysfs_open_memb_attr(char *array_devnm
, char *memb_devnm
, char *attr
, int oflag
)
211 snprintf(path
, PATH_MAX
, "/sys/block/%s/md/dev-%s/%s", array_devnm
, memb_devnm
, attr
);
213 return open(path
, oflag
);
216 int sysfs_open(char *devnm
, char *devname
, char *attr
)
218 char fname
[MAX_SYSFS_PATH_LEN
];
221 snprintf(fname
, MAX_SYSFS_PATH_LEN
, "/sys/block/%s/md/", devnm
);
223 strncat(fname
, devname
, MAX_SYSFS_PATH_LEN
- strlen(fname
));
224 strncat(fname
, "/", MAX_SYSFS_PATH_LEN
- strlen(fname
));
226 strncat(fname
, attr
, MAX_SYSFS_PATH_LEN
- strlen(fname
));
227 fd
= open(fname
, O_RDWR
);
228 if (fd
< 0 && errno
== EACCES
)
229 fd
= open(fname
, O_RDONLY
);
233 void sysfs_init_dev(struct mdinfo
*mdi
, dev_t devid
)
235 snprintf(mdi
->sys_name
,
236 sizeof(mdi
->sys_name
), "dev-%s", devid2kname(devid
));
239 int sysfs_init(struct mdinfo
*mdi
, int fd
, char *devnm
)
242 char fname
[MAX_SYSFS_PATH_LEN
];
243 int retval
= -ENODEV
;
245 mdi
->sys_name
[0] = 0;
247 devnm
= fd2devnm(fd
);
252 snprintf(fname
, MAX_SYSFS_PATH_LEN
, "/sys/block/%s/md", devnm
);
254 if (stat(fname
, &stb
))
256 if (!S_ISDIR(stb
.st_mode
))
258 strncpy(mdi
->sys_name
, devnm
, sizeof(mdi
->sys_name
) - 1);
265 /* If fd >= 0, get the array it is open on, else use devnm. */
266 struct mdinfo
*sysfs_read(int fd
, char *devnm
, unsigned long options
)
268 char fname
[PATH_MAX
];
273 struct mdinfo
*dev
, **devp
;
277 sra
= xcalloc(1, sizeof(*sra
));
278 if (sysfs_init(sra
, fd
, devnm
)) {
283 sprintf(fname
, "/sys/block/%s/md/", sra
->sys_name
);
284 base
= fname
+ strlen(fname
);
287 if (options
& GET_VERSION
) {
288 strcpy(base
, "metadata_version");
289 if (load_sys(fname
, buf
, sizeof(buf
)))
291 if (str_is_none(buf
) == true) {
292 sra
->array
.major_version
=
293 sra
->array
.minor_version
= -1;
294 strcpy(sra
->text_version
, "");
295 } else if (strncmp(buf
, "external:", 9) == 0) {
296 sra
->array
.major_version
= -1;
297 sra
->array
.minor_version
= -2;
298 strcpy(sra
->text_version
, buf
+9);
299 sra
->text_version
[sizeof(sra
->text_version
) - 1] = '\0';
302 &sra
->array
.major_version
,
303 &sra
->array
.minor_version
);
304 strcpy(sra
->text_version
, buf
);
307 if (options
& GET_LEVEL
) {
308 strcpy(base
, "level");
309 if (load_sys(fname
, buf
, sizeof(buf
)))
311 sra
->array
.level
= map_name(pers
, buf
);
313 if (options
& GET_LAYOUT
) {
314 strcpy(base
, "layout");
315 if (load_sys(fname
, buf
, sizeof(buf
)))
317 sra
->array
.layout
= strtoul(buf
, NULL
, 0);
319 if (options
& (GET_DISKS
|GET_STATE
)) {
320 strcpy(base
, "raid_disks");
321 if (load_sys(fname
, buf
, sizeof(buf
)))
323 sra
->array
.raid_disks
= strtoul(buf
, NULL
, 0);
325 if (options
& GET_COMPONENT
) {
326 strcpy(base
, "component_size");
327 if (load_sys(fname
, buf
, sizeof(buf
)))
329 sra
->component_size
= strtoull(buf
, NULL
, 0);
330 /* sysfs reports "K", but we want sectors */
331 sra
->component_size
*= 2;
333 if (options
& GET_CHUNK
) {
334 strcpy(base
, "chunk_size");
335 if (load_sys(fname
, buf
, sizeof(buf
)))
337 sra
->array
.chunk_size
= strtoul(buf
, NULL
, 0);
339 if (options
& GET_CACHE
) {
340 strcpy(base
, "stripe_cache_size");
341 if (load_sys(fname
, buf
, sizeof(buf
)))
342 /* Probably level doesn't support it */
345 sra
->cache_size
= strtoul(buf
, NULL
, 0);
347 if (options
& GET_MISMATCH
) {
348 strcpy(base
, "mismatch_cnt");
349 if (load_sys(fname
, buf
, sizeof(buf
)))
351 sra
->mismatch_cnt
= strtoul(buf
, NULL
, 0);
353 if (options
& GET_SAFEMODE
) {
360 strcpy(base
, "safe_mode_delay");
361 if (load_sys(fname
, buf
, sizeof(buf
)))
364 /* remove a period, and count digits after it */
366 for (i
= 0; i
< len
; i
++) {
368 if (isdigit(buf
[i
])) {
373 } else if (buf
[i
] == '.') {
378 msec
= strtoul(buf
, NULL
, 10);
379 msec
= (msec
* 1000) / scale
;
380 sra
->safe_mode_delay
= msec
;
382 if (options
& GET_BITMAP_LOCATION
) {
383 strcpy(base
, "bitmap/location");
384 if (load_sys(fname
, buf
, sizeof(buf
)))
386 if (strncmp(buf
, "file", 4) == 0)
387 sra
->bitmap_offset
= 1;
388 else if (str_is_none(buf
) == true)
389 sra
->bitmap_offset
= 0;
390 else if (buf
[0] == '+')
391 sra
->bitmap_offset
= strtol(buf
+1, NULL
, 10);
396 if (options
& GET_ARRAY_STATE
) {
397 strcpy(base
, "array_state");
398 if (load_sys(fname
, buf
, sizeof(buf
)))
400 sra
->array_state
= map_name(sysfs_array_states
, buf
);
403 if (options
& GET_CONSISTENCY_POLICY
) {
404 strcpy(base
, "consistency_policy");
405 if (load_sys(fname
, buf
, sizeof(buf
)))
406 sra
->consistency_policy
= CONSISTENCY_POLICY_UNKNOWN
;
408 sra
->consistency_policy
= map_name(consistency_policies
,
412 if (! (options
& GET_DEVS
))
415 /* Get all the devices as well */
417 dir
= opendir(fname
);
420 sra
->array
.spare_disks
= 0;
421 sra
->array
.active_disks
= 0;
422 sra
->array
.failed_disks
= 0;
423 sra
->array
.working_disks
= 0;
427 while ((de
= readdir(dir
)) != NULL
) {
429 if (de
->d_ino
== 0 ||
430 strncmp(de
->d_name
, "dev-", 4) != 0)
432 strcpy(base
, de
->d_name
);
433 dbase
= base
+ strlen(base
);
436 dev
= xcalloc(1, sizeof(*dev
));
438 /* Always get slot, major, minor */
439 strcpy(dbase
, "slot");
440 if (load_sys(fname
, buf
, sizeof(buf
))) {
441 /* hmm... unable to read 'slot' maybe the device
444 strcpy(dbase
, "block");
445 if (readlink(fname
, buf
, sizeof(buf
)) < 0 &&
446 errno
!= ENAMETOOLONG
) {
447 /* ...yup device is gone */
451 /* slot is unreadable but 'block' link
452 * still intact... something bad is happening
460 strcpy(dev
->sys_name
, de
->d_name
);
461 dev
->sys_name
[sizeof(dev
->sys_name
) - 1] = '\0';
462 dev
->disk
.raid_disk
= strtoul(buf
, &ep
, 10);
463 if (*ep
) dev
->disk
.raid_disk
= -1;
465 sra
->array
.nr_disks
++;
466 strcpy(dbase
, "block/dev");
467 if (load_sys(fname
, buf
, sizeof(buf
))) {
468 /* assume this is a stale reference to a hot
471 if (!(options
& GET_DEVS_ALL
)) {
476 sscanf(buf
, "%d:%d", &dev
->disk
.major
, &dev
->disk
.minor
);
479 if (!(options
& GET_DEVS_ALL
)) {
480 /* special case check for block devices that can go 'offline' */
481 strcpy(dbase
, "block/device/state");
482 if (load_sys(fname
, buf
, sizeof(buf
)) == 0 &&
483 strncmp(buf
, "offline", 7) == 0) {
489 /* finally add this disk to the array */
494 if (options
& GET_OFFSET
) {
495 strcpy(dbase
, "offset");
496 if (load_sys(fname
, buf
, sizeof(buf
)))
498 dev
->data_offset
= strtoull(buf
, NULL
, 0);
499 strcpy(dbase
, "new_offset");
500 if (load_sys(fname
, buf
, sizeof(buf
)) == 0)
501 dev
->new_data_offset
= strtoull(buf
, NULL
, 0);
503 dev
->new_data_offset
= dev
->data_offset
;
505 if (options
& GET_SIZE
) {
506 strcpy(dbase
, "size");
507 if (load_sys(fname
, buf
, sizeof(buf
)))
509 dev
->component_size
= strtoull(buf
, NULL
, 0) * 2;
511 if (options
& GET_STATE
) {
513 strcpy(dbase
, "state");
514 if (load_sys(fname
, buf
, sizeof(buf
)))
516 if (strstr(buf
, "faulty"))
517 dev
->disk
.state
|= (1<<MD_DISK_FAULTY
);
519 sra
->array
.working_disks
++;
520 if (strstr(buf
, "in_sync")) {
521 dev
->disk
.state
|= (1<<MD_DISK_SYNC
);
522 sra
->array
.active_disks
++;
524 if (dev
->disk
.state
== 0)
525 sra
->array
.spare_disks
++;
528 if (options
& GET_ERROR
) {
529 strcpy(buf
, "errors");
530 if (load_sys(fname
, buf
, sizeof(buf
)))
532 dev
->errors
= strtoul(buf
, NULL
, 0);
536 if ((options
& GET_STATE
) && sra
->array
.raid_disks
)
537 sra
->array
.failed_disks
= sra
->array
.raid_disks
-
538 sra
->array
.active_disks
- sra
->array
.spare_disks
;
550 int sysfs_attr_match(const char *attr
, const char *str
)
552 /* See if attr, read from a sysfs file, matches
553 * str. They must either be the same, or attr can
554 * have a trailing newline or comma
556 while (*attr
&& *str
&& *attr
== *str
) {
561 if (*str
|| (*attr
&& *attr
!= ',' && *attr
!= '\n'))
566 int sysfs_match_word(const char *word
, char **list
)
569 for (n
=0; list
[n
]; n
++)
570 if (sysfs_attr_match(word
, list
[n
]))
575 unsigned long long get_component_size(int fd
)
577 /* Find out the component size of the array.
578 * We cannot trust GET_ARRAY_INFO ioctl as it's
579 * size field is only 32bits.
580 * So look in /sys/block/mdXXX/md/component_size
582 * This returns in units of sectors.
585 char fname
[MAX_SYSFS_PATH_LEN
];
589 snprintf(fname
, MAX_SYSFS_PATH_LEN
,
590 "/sys/block/%s/md/component_size", stat2devnm(&stb
));
591 fd
= open(fname
, O_RDONLY
);
594 n
= read(fd
, fname
, sizeof(fname
));
596 if (n
< 0 || n
== sizeof(fname
))
599 return strtoull(fname
, NULL
, 10) * 2;
602 int sysfs_set_str(struct mdinfo
*sra
, struct mdinfo
*dev
,
603 char *name
, char *val
)
605 char fname
[MAX_SYSFS_PATH_LEN
];
608 snprintf(fname
, MAX_SYSFS_PATH_LEN
, "/sys/block/%s/md/%s/%s",
609 sra
->sys_name
, dev
?dev
->sys_name
:"", name
);
610 fd
= open(fname
, O_WRONLY
);
614 if (write_attr(val
, fd
)) {
615 pr_err("failed to write '%s' to '%s' (%s)\n", val
, fname
, strerror(errno
));
624 int sysfs_set_num(struct mdinfo
*sra
, struct mdinfo
*dev
,
625 char *name
, unsigned long long val
)
628 sprintf(valstr
, "%llu", val
);
629 return sysfs_set_str(sra
, dev
, name
, valstr
);
632 int sysfs_set_num_signed(struct mdinfo
*sra
, struct mdinfo
*dev
,
633 char *name
, long long val
)
636 sprintf(valstr
, "%lli", val
);
637 return sysfs_set_str(sra
, dev
, name
, valstr
);
640 int sysfs_uevent(struct mdinfo
*sra
, char *event
)
642 char fname
[MAX_SYSFS_PATH_LEN
];
645 snprintf(fname
, MAX_SYSFS_PATH_LEN
, "/sys/block/%s/uevent",
647 fd
= open(fname
, O_WRONLY
);
651 if (write_attr(event
, fd
)) {
652 pr_err("failed to write '%s' to '%s' (%s)\n", event
, fname
, strerror(errno
));
661 int sysfs_attribute_available(struct mdinfo
*sra
, struct mdinfo
*dev
, char *name
)
663 char fname
[MAX_SYSFS_PATH_LEN
];
666 snprintf(fname
, MAX_SYSFS_PATH_LEN
, "/sys/block/%s/md/%s/%s",
667 sra
->sys_name
, dev
?dev
->sys_name
:"", name
);
669 return stat(fname
, &st
) == 0;
672 int sysfs_get_fd(struct mdinfo
*sra
, struct mdinfo
*dev
,
675 char fname
[MAX_SYSFS_PATH_LEN
];
678 snprintf(fname
, MAX_SYSFS_PATH_LEN
, "/sys/block/%s/md/%s/%s",
679 sra
->sys_name
, dev
?dev
->sys_name
:"", name
);
680 fd
= open(fname
, O_RDWR
);
682 fd
= open(fname
, O_RDONLY
);
686 int sysfs_fd_get_ll(int fd
, unsigned long long *val
)
693 n
= read(fd
, buf
, sizeof(buf
));
694 if (n
<= 0 || n
== sizeof(buf
))
697 *val
= strtoull(buf
, &ep
, 0);
698 if (ep
== buf
|| (*ep
!= 0 && *ep
!= '\n' && *ep
!= ' '))
703 int sysfs_get_ll(struct mdinfo
*sra
, struct mdinfo
*dev
,
704 char *name
, unsigned long long *val
)
709 fd
= sysfs_get_fd(sra
, dev
, name
);
712 n
= sysfs_fd_get_ll(fd
, val
);
717 int sysfs_fd_get_two(int fd
, unsigned long long *v1
, unsigned long long *v2
)
719 /* two numbers in this sysfs file, either
729 n
= read(fd
, buf
, sizeof(buf
));
730 if (n
<= 0 || n
== sizeof(buf
))
733 *v1
= strtoull(buf
, &ep
, 0);
734 if (ep
== buf
|| (*ep
!= 0 && *ep
!= '\n' && *ep
!= ' '))
736 while (*ep
== ' ' || *ep
== '/' || *ep
== '(')
738 *v2
= strtoull(ep
, &ep2
, 0);
739 if (ep2
== ep
|| (*ep2
!= 0 && *ep2
!= '\n' && *ep2
!= ' ' && *ep2
!= ')')) {
746 int sysfs_get_two(struct mdinfo
*sra
, struct mdinfo
*dev
,
747 char *name
, unsigned long long *v1
, unsigned long long *v2
)
752 fd
= sysfs_get_fd(sra
, dev
, name
);
755 n
= sysfs_fd_get_two(fd
, v1
, v2
);
760 int sysfs_fd_get_str(int fd
, char *val
, int size
)
765 n
= read(fd
, val
, size
);
766 if (n
<= 0 || n
== size
)
772 int sysfs_get_str(struct mdinfo
*sra
, struct mdinfo
*dev
,
773 char *name
, char *val
, int size
)
778 fd
= sysfs_get_fd(sra
, dev
, name
);
781 n
= sysfs_fd_get_str(fd
, val
, size
);
786 int sysfs_set_safemode(struct mdinfo
*sra
, unsigned long ms
)
795 sprintf(delay
, "%ld.%03ld\n", sec
, msec
);
796 /* this '\n' ^ needed for kernels older than 2.6.28 */
797 return sysfs_set_str(sra
, NULL
, "safe_mode_delay", delay
);
800 int sysfs_set_array(struct mdinfo
*info
)
804 int raid_disks
= info
->array
.raid_disks
;
807 if (info
->array
.major_version
== -1 &&
808 info
->array
.minor_version
== -2) {
809 char buf
[SYSFS_MAX_BUF_SIZE
];
811 strcat(strcpy(ver
, "external:"), info
->text_version
);
813 /* meta version might already be set if we are setting
814 * new geometry for a reshape. In that case we don't
815 * want to over-write the 'readonly' flag that is
816 * stored in the metadata version. So read the current
817 * version first, and preserve the flag
819 if (sysfs_get_str(info
, NULL
, "metadata_version",
820 buf
, sizeof(buf
)) > 0)
821 if (strlen(buf
) >= 9 && buf
[9] == '-')
824 if (sysfs_set_str(info
, NULL
, "metadata_version", ver
) < 0) {
825 pr_err("This kernel does not support external metadata.\n");
829 if (info
->array
.level
< 0)
830 return 0; /* FIXME */
831 rv
|= sysfs_set_str(info
, NULL
, "level",
832 map_num_s(pers
, info
->array
.level
));
833 if (info
->reshape_active
&& info
->delta_disks
!= UnSet
)
834 raid_disks
-= info
->delta_disks
;
835 rv
|= sysfs_set_num(info
, NULL
, "raid_disks", raid_disks
);
836 rv
|= sysfs_set_num(info
, NULL
, "chunk_size", info
->array
.chunk_size
);
837 rv
|= sysfs_set_num(info
, NULL
, "layout", info
->array
.layout
);
838 rv
|= sysfs_set_num(info
, NULL
, "component_size", info
->component_size
/2);
839 if (info
->custom_array_size
) {
842 rc
= sysfs_set_num(info
, NULL
, "array_size",
843 info
->custom_array_size
/2);
844 if (rc
&& errno
== ENOENT
) {
845 pr_err("This kernel does not have the md/array_size attribute, the array may be larger than expected\n");
851 if (info
->array
.level
> 0)
852 rv
|= sysfs_set_num(info
, NULL
, "resync_start", info
->resync_start
);
854 if (info
->reshape_active
) {
855 rv
|= sysfs_set_num(info
, NULL
, "reshape_position",
856 info
->reshape_progress
);
857 rv
|= sysfs_set_num(info
, NULL
, "chunk_size", info
->new_chunk
);
858 rv
|= sysfs_set_num(info
, NULL
, "layout", info
->new_layout
);
859 rv
|= sysfs_set_num(info
, NULL
, "raid_disks",
860 info
->array
.raid_disks
);
861 /* We don't set 'new_level' here. That can only happen
862 * once the reshape completes.
866 if (info
->consistency_policy
== CONSISTENCY_POLICY_PPL
) {
867 char *policy
= map_num_s(consistency_policies
,
868 info
->consistency_policy
);
870 if (sysfs_set_str(info
, NULL
, "consistency_policy", policy
)) {
871 pr_err("This kernel does not support PPL. Falling back to consistency-policy=resync.\n");
872 info
->consistency_policy
= CONSISTENCY_POLICY_RESYNC
;
879 int sysfs_add_disk(struct mdinfo
*sra
, struct mdinfo
*sd
, int resume
)
887 sprintf(dv
, "%d:%d", sd
->disk
.major
, sd
->disk
.minor
);
888 rv
= sysfs_set_str(sra
, NULL
, "new_dev", dv
);
892 memset(nm
, 0, sizeof(nm
));
893 dname
= devid2kname(makedev(sd
->disk
.major
, sd
->disk
.minor
));
895 snprintf(sd
->sys_name
, sizeof(sd
->sys_name
), "dev-%s", dname
);
897 /* test write to see if 'recovery_start' is available */
898 if (resume
&& sd
->recovery_start
< MaxSector
&&
899 sysfs_set_num(sra
, sd
, "recovery_start", 0)) {
900 sysfs_set_str(sra
, sd
, "state", "remove");
904 rv
= sysfs_set_num(sra
, sd
, "offset", sd
->data_offset
);
905 rv
|= sysfs_set_num(sra
, sd
, "size", (sd
->component_size
+1) / 2);
906 if (!is_container(sra
->array
.level
)) {
907 if (sra
->consistency_policy
== CONSISTENCY_POLICY_PPL
) {
908 rv
|= sysfs_set_num(sra
, sd
, "ppl_sector", sd
->ppl_sector
);
909 rv
|= sysfs_set_num(sra
, sd
, "ppl_size", sd
->ppl_size
);
911 if (sd
->recovery_start
== MaxSector
)
912 /* This can correctly fail if array isn't started,
913 * yet, so just ignore status for now.
915 sysfs_set_str(sra
, sd
, "state", "insync");
916 if (sd
->disk
.raid_disk
>= 0)
917 rv
|= sysfs_set_num(sra
, sd
, "slot", sd
->disk
.raid_disk
);
919 sysfs_set_num(sra
, sd
, "recovery_start", sd
->recovery_start
);
921 if (sd
->bb
.supported
) {
922 if (sysfs_set_str(sra
, sd
, "state", "external_bbl")) {
924 * backward compatibility - if kernel doesn't support
925 * bad blocks for external metadata, let it continue
926 * as long as there are none known so far
929 pr_err("The kernel has no support for bad blocks in external metadata\n");
934 for (i
= 0; i
< sd
->bb
.count
; i
++) {
936 const struct md_bb_entry
*entry
= &sd
->bb
.entries
[i
];
938 snprintf(s
, sizeof(s
) - 1, "%llu %d\n", entry
->sector
,
940 rv
|= sysfs_set_str(sra
, sd
, "bad_blocks", s
);
946 int sysfs_disk_to_scsi_id(int fd
, __u32
*id
)
948 /* from an open block device, try to retrieve it scsi_id */
953 int host
, bus
, target
, lun
;
958 snprintf(path
, sizeof(path
), "/sys/dev/block/%d:%d/device/scsi_device",
959 major(st
.st_rdev
), minor(st
.st_rdev
));
965 for (de
= readdir(dir
); de
; de
= readdir(dir
)) {
968 if (de
->d_type
!= DT_DIR
)
971 count
= sscanf(de
->d_name
, "%d:%d:%d:%d", &host
, &bus
, &target
, &lun
);
980 *id
= (host
<< 24) | (bus
<< 16) | (target
<< 8) | (lun
<< 0);
984 int sysfs_unique_holder(char *devnm
, long rdev
)
986 /* Check that devnm is a holder of rdev,
987 * and is the only holder.
988 * we should be locked against races by
991 * 0 - not unique, not even a holder
992 * 1 - unique, this is the only holder.
993 * 2/3 - not unique, there is another holder
994 * -1 - error, cannot find the holders
1001 sprintf(dirname
, "/sys/dev/block/%d:%d/holders",
1002 major(rdev
), minor(rdev
));
1003 dir
= opendir(dirname
);
1006 l
= strlen(dirname
);
1007 while ((de
= readdir(dir
)) != NULL
) {
1014 if (de
->d_name
[0] == '.')
1016 strcpy(dirname
+l
, "/");
1017 strcat(dirname
+l
, de
->d_name
);
1018 n
= readlink(dirname
, buf
, sizeof(buf
)-1);
1022 sl
= strrchr(buf
, '/');
1027 if (strcmp(devnm
, sl
) == 0)
1036 int sysfs_freeze_array(struct mdinfo
*sra
)
1038 /* Try to freeze resync/rebuild on this array/container.
1039 * Return -1 if the array is busy,
1040 * return 0 if this kernel doesn't support 'frozen'
1041 * return 1 if it worked.
1043 char buf
[SYSFS_MAX_BUF_SIZE
];
1045 if (!sysfs_attribute_available(sra
, NULL
, "sync_action"))
1046 return 1; /* no sync_action == frozen */
1047 if (sysfs_get_str(sra
, NULL
, "sync_action", buf
, sizeof(buf
)) <= 0)
1049 if (strcmp(buf
, "frozen\n") == 0)
1050 /* Already frozen */
1052 if (strcmp(buf
, "idle\n") != 0 && strcmp(buf
, "recover\n") != 0)
1054 if (sysfs_set_str(sra
, NULL
, "sync_action", "frozen") < 0)
1059 int sysfs_wait(int fd
, int *msec
)
1061 /* Wait up to '*msec' for fd to have an exception condition.
1062 * if msec == NULL, wait indefinitely.
1069 n
= select(fd
+1, NULL
, NULL
, &fds
, NULL
);
1073 struct timeval start
, end
, tv
;
1074 gettimeofday(&start
, NULL
);
1077 tv
.tv_usec
= (*msec
)*1000;
1079 tv
.tv_sec
= (*msec
)/1000;
1082 n
= select(fd
+1, NULL
, NULL
, &fds
, &tv
);
1083 gettimeofday(&end
, NULL
);
1084 end
.tv_sec
-= start
.tv_sec
;
1085 *msec
-= (end
.tv_sec
* 1000 + end
.tv_usec
/1000
1086 - start
.tv_usec
/1000) + 1;
1091 int sysfs_rules_apply_check(const struct mdinfo
*sra
,
1092 const struct sysfs_entry
*ent
)
1094 /* Check whether parameter is regular file,
1095 * exists and is under specified directory.
1097 char fname
[MAX_SYSFS_PATH_LEN
];
1098 char dname
[MAX_SYSFS_PATH_LEN
];
1099 char resolved_path
[PATH_MAX
];
1100 char resolved_dir
[PATH_MAX
];
1103 if (sra
== NULL
|| ent
== NULL
)
1106 result
= snprintf(dname
, MAX_SYSFS_PATH_LEN
,
1107 "/sys/block/%s/md/", sra
->sys_name
);
1108 if (result
< 0 || result
>= MAX_SYSFS_PATH_LEN
)
1111 result
= snprintf(fname
, MAX_SYSFS_PATH_LEN
,
1112 "%s/%s", dname
, ent
->name
);
1113 if (result
< 0 || result
>= MAX_SYSFS_PATH_LEN
)
1116 if (realpath(fname
, resolved_path
) == NULL
||
1117 realpath(dname
, resolved_dir
) == NULL
)
1120 if (strncmp(resolved_dir
, resolved_path
,
1121 strnlen(resolved_dir
, PATH_MAX
)) != 0)
1127 static struct dev_sysfs_rule
*sysfs_rules
;
1129 void sysfs_rules_apply(char *devnm
, struct mdinfo
*dev
)
1131 struct dev_sysfs_rule
*rules
= sysfs_rules
;
1134 struct sysfs_entry
*ent
= rules
->entry
;
1137 if (!rules
->uuid_set
) {
1139 match
= strcmp(devnm
, rules
->devname
) == 0;
1141 match
= memcmp(dev
->uuid
, rules
->uuid
,
1142 sizeof(int[4])) == 0;
1145 while (match
&& ent
) {
1146 if (sysfs_rules_apply_check(dev
, ent
) < 0)
1147 pr_err("SYSFS: failed to write '%s' to '%s'\n",
1148 ent
->value
, ent
->name
);
1150 sysfs_set_str(dev
, NULL
, ent
->name
, ent
->value
);
1153 rules
= rules
->next
;
1157 static void sysfs_rule_free(struct dev_sysfs_rule
*rule
)
1159 struct sysfs_entry
*entry
;
1162 struct dev_sysfs_rule
*tmp
= rule
->next
;
1164 entry
= rule
->entry
;
1166 struct sysfs_entry
*tmp
= entry
->next
;
1175 free(rule
->devname
);
1181 void sysfsline(char *line
)
1183 struct dev_sysfs_rule
*sr
;
1186 sr
= xcalloc(1, sizeof(*sr
));
1187 for (w
= dl_next(line
); w
!= line
; w
= dl_next(w
)) {
1188 if (strncasecmp(w
, "name=", 5) == 0) {
1189 char *devname
= w
+ 5;
1191 if (strncmp(devname
, DEV_MD_DIR
, DEV_MD_DIR_LEN
) == 0) {
1193 pr_err("Only give one device per SYSFS line: %s\n",
1196 sr
->devname
= xstrdup(devname
);
1198 pr_err("%s is an invalid name for an md device - ignored.\n",
1201 } else if (strncasecmp(w
, "uuid=", 5) == 0) {
1205 pr_err("Only give one uuid per SYSFS line: %s\n",
1208 if (parse_uuid(w
+ 5, sr
->uuid
) &&
1209 memcmp(sr
->uuid
, uuid_zero
,
1210 sizeof(int[4])) != 0)
1213 pr_err("Invalid uuid: %s\n", uuid
);
1216 struct sysfs_entry
*prop
;
1218 char *sep
= strchr(w
, '=');
1220 if (sep
== NULL
|| *(sep
+ 1) == 0) {
1221 pr_err("Cannot parse \"%s\" - ignoring.\n", w
);
1225 prop
= xmalloc(sizeof(*prop
));
1226 prop
->value
= xstrdup(sep
+ 1);
1228 prop
->name
= xstrdup(w
);
1229 prop
->next
= sr
->entry
;
1234 if (!sr
->devname
&& !sr
->uuid_set
) {
1235 pr_err("Device name not found in sysfs config entry - ignoring.\n");
1236 sysfs_rule_free(sr
);
1240 sr
->next
= sysfs_rules
;
1245 * sysfs_is_libata_allow_tpm_enabled() - check if libata allow_tmp is enabled.
1246 * @verbose: verbose flag.
1248 * Check if libata allow_tmp flag is set, this is required for SATA Opal Security commands to work.
1250 * Return: true if allow_tpm enable, false otherwise.
1252 bool sysfs_is_libata_allow_tpm_enabled(const int verbose
)
1254 const char *path
= "/sys/module/libata/parameters/allow_tpm";
1255 const char *expected_value
= "1";
1256 int fd
= open(path
, O_RDONLY
);
1259 if (!is_fd_valid(fd
)) {
1260 pr_vrb("Failed open file descriptor to %s. Cannot check libata allow_tpm param.\n",
1265 sysfs_fd_get_str(fd
, buf
, sizeof(buf
));
1268 if (strncmp(buf
, expected_value
, 1) == 0)