diff options
author | NeilBrown <neilb@suse.de> | 2012-09-24 04:26:03 +0200 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2012-09-24 04:26:03 +0200 |
commit | aab15415eddbfa800031cb9f6273ca8fcf59efb7 (patch) | |
tree | 63ebdc4928cf9b175f59324be96bb559c5f9e514 /sysfs.c | |
parent | fix: imsm: do not accept too small sizes (diff) | |
download | mdadm-aab15415eddbfa800031cb9f6273ca8fcf59efb7.tar.xz mdadm-aab15415eddbfa800031cb9f6273ca8fcf59efb7.zip |
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 <neilb@suse.de>
Diffstat (limited to 'sysfs.c')
-rw-r--r-- | sysfs.c | 34 |
1 files changed, 16 insertions, 18 deletions
@@ -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) |