FAQ Search Today's Posts Mark Forums Read
» Video Reviews

» Linux Archive

Linux-archive is a website aiming to archive linux email lists and to make them easily accessible for linux users/developers.


» Sponsor

» Partners

» Sponsor

Go Back   Linux Archive > Redhat > Device-mapper Development

 
 
LinkBack Thread Tools
 
Old 03-24-2009, 02:24 PM
Konrad Rzeszutek
 
Default Fix race-condition when reading sysfs attributes.

This fix re-introduces a wait loop when reading sysfs attributes.
The reason a wait is necessary is due to the way the kernel
sends the event. When a SCSI device is added the SCSI subsystem
pursues this path:

_sysfs_add_sdev:
calls device_add ...
[ '/devices/platform/host16/session6/target16:0:0/16:0:0:17'] uevent
bus_attach_device
bus_for_each_drv
driver_probe_device
sd_probe
['/class/scsi_disk/16:0:0:17' ] uevent
add_disk
['/block/sdai'] [ Here multipath starts its job ]

calls class_device_add ...
[ '/class/scsi_device/16:0:0:17' ] uevent
sg_add:
[ '/class/scsi_generic/sg35' ] uevent

done with device_add, and now the kernel adds the attributes:
scsi_sysfs_sdev_attrs[i].vendor, model, rev

There are four uevents sent from the kernel in the creation of
a SysFS representation of the device. After the last event, the
SysFs entries for vendor,model, rev are populated. The window
time between the uevent with /block/sdX sent and the sysfs
attributes being populated is small. But it is possible (with
a slow serial link, slow SCSI target), to get us in a race
condition where multipath investigates the new block device and
finds it can't read the vendor, and the block device ends up
being discarded and never added to the device mapper multipath map.
---
libmultipath/discovery.c | 38 ++++++++++++++++++++++++++++++++++++++
1 files changed, 38 insertions(+), 0 deletions(-)

diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
index 9ae2b8f..1d2c396 100644
--- a/libmultipath/discovery.c
+++ b/libmultipath/discovery.c
@@ -124,11 +124,49 @@ path_discovery (vector pathvec, struct config * conf, int flag)
return r;
}

+
+#define WAIT_MAX_SECONDS 5
+#define WAIT_LOOP_PER_SECOND 5
+
+static int
+wait_for_file (char * filename)
+{
+ int loop;
+ struct stat stats;
+ /*
+ * the daemon can race udev upon path add,
+ * not multipath(8), if ran by udev
+ */
+
+ if (!conf->daemon)
+ return 0;
+
+ loop = WAIT_MAX_SECONDS * WAIT_LOOP_PER_SECOND;
+
+ while (--loop) {
+ if (stat(filename, &stats) == 0)
+ return 0;
+
+ if (errno != ENOENT)
+ return 1;
+
+ usleep(1000 * 1000 / WAIT_LOOP_PER_SECOND);
+ }
+ return 1;
+}
+
#define declare_sysfs_get_str(fname)
extern int
sysfs_get_##fname (struct sysfs_device * dev, char * buff, size_t len)
{
char *attr;
+ char attr_path[SYSFS_PATH_SIZE];
+
+ if (safe_sprintf(attr_path, "%s/%s/%s", sysfs_path, dev->devpath, #fname))
+ return 1;
+
+ if (wait_for_file(attr_path))
+ return 1;

attr = sysfs_attr_get_value(dev->devpath, #fname);
if (!attr)
--
1.5.4.1

--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
 

Thread Tools




All times are GMT. The time now is 08:32 AM.

VBulletin, Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
Content Relevant URLs by vBSEO ©2007, Crawlability, Inc.
Copyright 2007 - 2008, www.linux-archive.org