From aab15415eddbfa800031cb9f6273ca8fcf59efb7 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 24 Sep 2012 12:26:03 +1000 Subject: Manage: fix checks for removal from a container. We must only remove from a container if the device isn't a member of any member array. To check we look at the 'holders' directory in sysfs. We currently skip that check if ->devname is "detached", however that can never be true since the change that introduced add_detached(). Also sysfs_unique_holder returns status in 'errno' which isn't entirely safe as e.g. closedir() is probably allowed to clear it. So make sysfs_unique_holder return an unambigious value, and us it to decide what to report. Signed-off-by: NeilBrown --- sysfs.c | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) (limited to 'sysfs.c') diff --git a/sysfs.c b/sysfs.c index 0043d272..47294556 100644 --- a/sysfs.c +++ b/sysfs.c @@ -778,18 +778,22 @@ int sysfs_unique_holder(int devnum, long rdev) * and is the only holder. * we should be locked against races by * an O_EXCL on devnum + * Return values: + * 0 - not unique, not even a holder + * 1 - unique, this is the only holder. + * 2/3 - not unique, there is another holder + * -1 - error, cannot find the holders */ DIR *dir; struct dirent *de; char dirname[100]; char l; - int found = 0; + int ret = 0; sprintf(dirname, "/sys/dev/block/%d:%d/holders", major(rdev), minor(rdev)); dir = opendir(dirname); - errno = ENOENT; if (!dir) - return 0; + return -1; l = strlen(dirname); while ((de = readdir(dir)) != NULL) { char buf[10]; @@ -807,8 +811,8 @@ int sysfs_unique_holder(int devnum, long rdev) strcat(dirname+l, "/dev"); fd = open(dirname, O_RDONLY); if (fd < 0) { - errno = ENOENT; - break; + /* Probably a race, just ignore this */ + continue; } n = read(fd, buf, sizeof(buf)-1); close(fd); @@ -816,24 +820,18 @@ int sysfs_unique_holder(int devnum, long rdev) continue; buf[n] = 0; if (sscanf(buf, "%d:%d%c", &mj, &mn, &c) != 3 || - c != '\n') { - errno = ENOENT; - break; - } + c != '\n') + continue; if (mj != MD_MAJOR) mn = -1-(mn>>6); - if (devnum != mn) { - errno = EEXIST; - break; - } - found = 1; + if (devnum == mn) + ret |= 1; + else + ret |= 2; } closedir(dir); - if (de) - return 0; - else - return found; + return ret; } int sysfs_freeze_array(struct mdinfo *sra) -- cgit v1.2.3