summaryrefslogtreecommitdiffstats
path: root/sysfs.c
diff options
context:
space:
mode:
authorNeil Brown <neilb@suse.de>2008-07-12 20:27:40 +1000
committerNeil Brown <neilb@suse.de>2008-07-12 20:27:40 +1000
commitf94d52f43ea70665f0293de0fe8940d64931e893 (patch)
tree935d0b7e1ace033e64d2f276175e15373268a5fc /sysfs.c
parentd4da74fc9c5b9f63bb6e4c8e00d1d871ea7174a3 (diff)
downloadmdadm-f94d52f43ea70665f0293de0fe8940d64931e893.tar.gz
mdadm-f94d52f43ea70665f0293de0fe8940d64931e893.tar.xz
mdadm-f94d52f43ea70665f0293de0fe8940d64931e893.zip
Handle device removal from container
This really should be done in mdadm, not mdmon. We ensure the device won't be suddenly commited as a hot-spare using O_EXCL, then check the 'holders' sysfs directory to make sure it is only in use once.
Diffstat (limited to 'sysfs.c')
-rw-r--r--sysfs.c63
1 files changed, 63 insertions, 0 deletions
diff --git a/sysfs.c b/sysfs.c
index ae10b1e..a284421 100644
--- a/sysfs.c
+++ b/sysfs.c
@@ -515,3 +515,66 @@ int sysfs_disk_to_scsi_id(int fd, __u32 *id)
return 0;
}
+
+
+int sysfs_unique_holder(int devnum, long rdev)
+{
+ /* Check that devnum is a holder of rdev,
+ * and is the only holder.
+ * we should be locked against races by
+ * an O_EXCL on devnum
+ */
+ DIR *dir;
+ struct dirent *de;
+ char dirname[100];
+ char l;
+ int found = 0;
+ sprintf(dirname, "/sys/dev/block/%d:%d/holders",
+ major(rdev), minor(rdev));
+ dir = opendir(dirname);
+ errno = ENOENT;
+ if (!dir)
+ return 0;
+ l = strlen(dirname);
+ while ((de = readdir(dir)) != NULL) {
+ char buf[10];
+ int n;
+ int mj, mn;
+ char c;
+ int fd;
+
+ if (de->d_ino == 0)
+ continue;
+ if (de->d_name[0] == '.')
+ continue;
+ strcpy(dirname+l, "/");
+ strcat(dirname+l, de->d_name);
+ strcat(dirname+l, "/dev");
+ fd = open(dirname, O_RDONLY);
+ if (fd < 0) {
+ errno = ENOENT;
+ break;
+ }
+ n = read(fd, buf, sizeof(buf)-1);
+ close(fd);
+ buf[n] = 0;
+ if (sscanf(buf, "%d:%d%c", &mj, &mn, &c) != 3 ||
+ c != '\n') {
+ errno = ENOENT;
+ break;
+ }
+ if (mj != MD_MAJOR)
+ mn = -1-(mn>>6);
+
+ if (devnum != mn) {
+ errno = EEXIST;
+ break;
+ }
+ found = 1;
+ }
+ closedir(dir);
+ if (de)
+ return 0;
+ else
+ return found;
+}