From mboxrd@z Thu Jan 1 00:00:00 1970 From: Daniel Stekloff Date: Tue, 23 Mar 2004 19:19:10 +0000 Subject: Re: libsysfs/udev hang Message-Id: <200403231119.10323.dsteklof@us.ibm.com> List-Id: References: <4060259D.4000905@gmx.net> In-Reply-To: <4060259D.4000905@gmx.net> MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable To: linux-hotplug@vger.kernel.org Hi Carl-Daniel, On Tuesday 23 March 2004 03:55 am, Carl-Daniel Hailfinger wrote: > Hi, > > while writing an ataraid replacement on top of device mapper, I stumbled > upon a freeze in sysfs_close_device which only happens if udev is NOT > compiled with DEBUG=3Dtrue. > > Test routine (modified udevinfo function) follows: > static int print_device_chain(const char *path) > { > struct sysfs_class_device *class_dev; > struct sysfs_class_device *class_dev_parent; > struct sysfs_attribute *attr; > struct sysfs_device *sysfs_dev; > struct sysfs_device *sysfs_dev_parent; > struct dlist *cur_attrs; > int retval =3D 0; > unsigned int vendor,device,subsystem_vendor,subsystem_device; > unsigned long devsize; > unsigned char *buf; > > /* get the class dev */ > class_dev =3D sysfs_open_class_device_path(path); > if (class_dev =3D NULL) { > printf("couldn't get the class device\n"); > return -1; > } > > cur_attrs =3D sysfs_get_classdev_attributes(class_dev); > > /* get device size in 512 byte blocks from 'size' */ > buf =3D sysfs_get_value_from_attributes(cur_attrs, "size"); > devsize =3D strtoul(buf, NULL, 10); > > /* read the 'dev' file for major/minor*/ > buf =3D sysfs_get_value_from_attributes(cur_attrs, "dev"); > printf("device '%s' has size %lu blocks and major:minor %s\n", > class_dev->path, devsize, buf); > > sysfs_close_list(cur_attrs); > > /* get the device link (if parent exists look here) */ > class_dev_parent =3D sysfs_get_classdev_parent(class_dev); > if (class_dev_parent !=3D NULL) { > class_dev =3D class_dev_parent; > } First of all, you've opened a class_dev with an "open" call ->=20 sysfs_open_class_device_path. This should have a matching "close" call to=20 clean up the class device you've created. Instead, you assign the parent=20 reference that's returned from a "get" call to class_dev. This isn't a good= =20 idea. Second, you use a "get" function to retrieve a reference to the class_dev's= =20 attributes -> sysfs_get_classdev_attributes. Then you close the list using = sysfs_close_list() rather than leaving that to the sysfs_close_classdev()=20 function.=20 Open functions in libsysfs create a device - and the memory for it - and=20 return you the structure. These "open" functions must be followed with a=20 "close" function to clean everything up. Get functions are used on opened structures to return references to what yo= u'd=20 like to see like attributes or devices. They don't need to be "closed".=20 > sysfs_dev =3D sysfs_get_classdev_device(class_dev); > if (sysfs_dev !=3D NULL) > printf("follow the class device's \"device\"\n"); > > /* look the device chain upwards */ > while (sysfs_dev !=3D NULL) { > > printf("point1\n"); > /* open sysfs device directory and print all attributes */ > if (strcmp(sysfs_dev->bus, "pci") =3D 0) { > cur_attrs =3D sysfs_get_device_attributes(sysfs_d= ev); > buf =3D sysfs_get_value_from_attributes(cur_attrs, > "vendor"); > vendor =3D (unsigned int)strtoul(buf + 2, NULL, 1= 6); > buf =3D sysfs_get_value_from_attributes(cur_attrs, > "device"); > device =3D (unsigned int)strtoul(buf + 2, NULL, 1= 6); > buf =3D sysfs_get_value_from_attributes(cur_attrs, > "subsystem_vendor"); > subsystem_vendor =3D (unsigned int)strtoul(buf + = 2, > NULL, 16); > buf =3D sysfs_get_value_from_attributes(cur_attrs, > "subsystem_device"); > subsystem_device =3D (unsigned int)strtoul(buf + = 2, > NULL, 16); > sysfs_close_list(cur_attrs); Here's where you close a list that you received through a "get" call. You=20 shouldn't call close on references you receive with "get" functions. > printf("device '%s' has vendor %x device %x > subvendor %x subdevice %x\n", > class_dev->path, vendor, device, > subsystem_vendor, subsystem_device); > printf("point2\n"); > break; > } > printf("point3\n"); > > sysfs_dev_parent =3D sysfs_get_device_parent(sysfs_dev); > printf("point4\n"); > if (sysfs_dev_parent =3D NULL) > break; > printf("point5\n"); > > sysfs_dev =3D sysfs_dev_parent; > printf("point6\n"); > } > printf("point7\n"); > sysfs_close_device(sysfs_dev); Here's where you close a reference you received through a "get" call.=20 > printf("point8\n"); > exit: > return retval; > } > > > And if I compile udev with DEBUG=3Dtrue, it works perfectly. If I compile > udev without debugging, it hangs between point7 and point8. > > Did I make any mistakes in the above routine which trigger the hang? I ask > here because the libsysfs version in udev differs from libsysfs 1.0.0. I will create a similar routine, using correct libsysfs formats, and see if= I=20 run into a race. Please let me know if this helps or if I can explain further.=20 Thanks, Dan > Regards, > Carl-Daniel ------------------------------------------------------- This SF.Net email is sponsored by: IBM Linux Tutorials Free Linux tutorial presented by Daniel Robbins, President and CEO of GenToo technologies. Learn everything from fundamentals to system administration.http://ads.osdn.com/?ad_id=1470&alloc_id638&op=CCk _______________________________________________ Linux-hotplug-devel mailing list http://linux-hotplug.sourceforge.net Linux-hotplug-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-hotplug-devel