2 * Copyright (C) 2005-2006 Kay Sievers <kay.sievers@vrfy.org>
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation version 2 of the License.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
39 #include "devmapper.h"
42 * When we modify an attribute value we cannot rely on libudev for now,
43 * as libudev lacks the capability to update an attribute value.
44 * So for modified attributes we need to implement our own function.
46 ssize_t sysfs_attr_get_value(struct udev_device *dev, const char *attr_name,
47 char * value, size_t value_len)
49 char devpath[PATH_SIZE];
54 if (!dev || !attr_name || !value)
57 snprintf(devpath, PATH_SIZE, "%s/%s", udev_device_get_syspath(dev),
59 condlog(4, "open '%s'", devpath);
60 if (stat(devpath, &statbuf) != 0) {
61 condlog(4, "stat '%s' failed: %s", devpath, strerror(errno));
65 /* skip directories */
66 if (S_ISDIR(statbuf.st_mode)) {
67 condlog(4, "%s is a directory", devpath);
71 /* skip non-writeable files */
72 if ((statbuf.st_mode & S_IRUSR) == 0) {
73 condlog(4, "%s is not readable", devpath);
77 /* read attribute value */
78 fd = open(devpath, O_RDONLY);
80 condlog(4, "attribute '%s' can not be opened: %s",
81 devpath, strerror(errno));
84 size = read(fd, value, value_len);
86 condlog(4, "read from %s failed: %s", devpath, strerror(errno));
88 } else if (size == value_len) {
89 condlog(4, "overflow while reading from %s", devpath);
97 ssize_t sysfs_attr_set_value(struct udev_device *dev, const char *attr_name,
98 char * value, size_t value_len)
100 char devpath[PATH_SIZE];
105 if (!dev || !attr_name || !value || !value_len)
108 snprintf(devpath, PATH_SIZE, "%s/%s", udev_device_get_syspath(dev),
110 condlog(4, "open '%s'", devpath);
111 if (stat(devpath, &statbuf) != 0) {
112 condlog(4, "stat '%s' failed: %s", devpath, strerror(errno));
116 /* skip directories */
117 if (S_ISDIR(statbuf.st_mode)) {
118 condlog(4, "%s is a directory", devpath);
122 /* skip non-writeable files */
123 if ((statbuf.st_mode & S_IWUSR) == 0) {
124 condlog(4, "%s is not writeable", devpath);
128 /* write attribute value */
129 fd = open(devpath, O_WRONLY);
131 condlog(4, "attribute '%s' can not be opened: %s",
132 devpath, strerror(errno));
135 size = write(fd, value, value_len);
137 condlog(4, "write to %s failed: %s", devpath, strerror(errno));
139 } else if (size < value_len) {
140 condlog(4, "tried to write %ld to %s. Wrote %ld",
141 (long)value_len, devpath, (long)size);
150 sysfs_get_size (struct path *pp, unsigned long long * size)
155 if (!pp->udev || !size)
159 if (sysfs_attr_get_value(pp->udev, "size", attr, 255) == 0) {
160 condlog(3, "%s: No size attribute in sysfs", pp->dev);
164 r = sscanf(attr, "%llu\n", size);
167 condlog(3, "%s: Cannot parse size attribute", pp->dev);
175 int sysfs_check_holders(char * check_devt, char * new_devt)
177 unsigned int major, new_minor, table_minor;
178 char path[PATH_SIZE], check_dev[PATH_SIZE];
181 struct dirent *holder;
183 if (sscanf(new_devt,"%d:%d", &major, &new_minor) != 2) {
184 condlog(1, "invalid device number %s", new_devt);
188 if (devt2devname(check_dev, PATH_SIZE, check_devt)) {
189 condlog(1, "can't get devname for %s", check_devt);
193 condlog(3, "%s: checking holder", check_dev);
195 snprintf(path, PATH_SIZE, "/sys/block/%s/holders", check_dev);
196 dirfd = opendir(path);
198 condlog(3, "%s: failed to open directory %s (%d)",
199 check_dev, path, errno);
202 while ((holder = readdir(dirfd)) != NULL) {
203 if ((strcmp(holder->d_name,".") == 0) ||
204 (strcmp(holder->d_name,"..") == 0))
207 if (sscanf(holder->d_name, "dm-%d", &table_minor) != 1) {
208 condlog(3, "%s: %s is not a dm-device",
209 check_dev, holder->d_name);
212 if (table_minor == new_minor) {
213 condlog(3, "%s: holder already correct", check_dev);
216 table_name = dm_mapname(major, table_minor);
218 condlog(0, "%s: reassign table %s old %s new %s", check_dev,
219 table_name, check_devt, new_devt);
221 dm_reassign_table(table_name, check_devt, new_devt);