hal: Branch 'master'
David Zeuthen
david at kemper.freedesktop.org
Wed May 2 22:56:14 PDT 2007
hald/linux/blockdev.c | 89 +++++++++++++++++++++++++++-----------------------
1 files changed, 49 insertions(+), 40 deletions(-)
New commits:
diff-tree d3138a8f990e5d88c357d3a11841cc31aa40f6dd (from 504bbb362ceec73dc1bf1a4afee7a9ff32c74c70)
Author: Kay Sievers <kay.sievers at vrfy.org>
Date: Thu May 3 01:56:13 2007 -0400
creating link /dev/root to device / is mounted from
On 4/23/07, David Zeuthen <david at fubar.dk> wrote:
> On Sun, 2007-04-22 at 14:01 +0200, Kay Sievers wrote:
> > But we may just want to change HAL to handle mnt_dir == "/" as a
> > special case, instead of assuming the name to be a device-node. That
> > should solve the real problem we are seeing here.
>
> I'm fine taking a patch to do that. Thanks!
Does this work for you Doug?
Thanks,
Kay
diff --git a/hald/linux/blockdev.c b/hald/linux/blockdev.c
index a8e64f6..f0c6eba 100644
--- a/hald/linux/blockdev.c
+++ b/hald/linux/blockdev.c
@@ -165,9 +165,6 @@ blockdev_refresh_mount_state (HalDevice
struct mntent mnt;
struct mntent *mnte;
char buf[1024];
- unsigned int major;
- unsigned int minor;
- dev_t devt = makedev(0, 0);
GSList *volumes = NULL;
GSList *volume;
@@ -189,43 +186,53 @@ blockdev_refresh_mount_state (HalDevice
/* loop over /proc/mounts */
while ((mnte = getmntent_r (f, &mnt, buf, sizeof(buf))) != NULL) {
struct stat statbuf;
- gboolean use_device_name_for_match;
+ dev_t devt;
- /*HAL_INFO ((" * /proc/mounts contain dev %s - type %s", mnt.mnt_fsname, mnt.mnt_type));*/
+ /* HAL_INFO ((" * /proc/mounts contain dev %s - type %s", mnt.mnt_fsname, mnt.mnt_type)); */
- /* If this is a nfs mount (fstype == 'nfs') ignore the mount. Reason:
- * 1. we don't list nfs devices in HAL
- * 2. more problematic: stat on mountpoints with 'stale nfs handle' never come
- * back and block complete HAL and all applications using HAL fail.
+ /* We don't handle nfs mounts in HAL and stat() on mountpoints,
+ * and we would block on 'stale nfs handle'.
*/
if (strcmp(mnt.mnt_type, "nfs") == 0)
continue;
- use_device_name_for_match = FALSE;
- /* get major:minor of special device file */
- if (stat (mnt.mnt_fsname, &statbuf) != 0) {
- /* DING DING DING... device node may have been deleted by udev
- * but device is still mounted and we haven't processed the uevent
- * for that deletion from udev..
- *
- * So in this case... fall back to comparing on device names
- * rather than pretending the device is not mounted as that's
- * what will happen if we just skip this /proc/mounts entry.
- *
- * The reason it's nicer to compare on major:minor is that
- * /proc/mounts is broken - it contains the *device name*
- * passed to mount(2) which in some cases may be a symlink
- * (on many distros it's common to see /proc/mounts contain
- * /dev/root as the device for /). Sigh...
- */
- use_device_name_for_match = TRUE;
- } else {
+ /* skip plain names, we look for device nodes */
+ if (mnt.mnt_fsname[0] != '/')
+ continue;
+
+ /*
+ * We can't just stat() the mountpoint, because it breaks all sorts
+ * non-disk filesystems. So assume, that the names in /proc/mounts
+ * are existing device-files used to mount the filesystem.
+ */
+ devt = makedev(0, 0);
+ if (stat (mnt.mnt_fsname, &statbuf) == 0) {
+ /* not a device node */
if (major (statbuf.st_rdev) == 0)
continue;
+
+ /* found major/minor */
+ devt = statbuf.st_rdev;
+ } else {
+ /* The root filesystem may be mounted by a device name that doesn't
+ * exist in the real root, like /dev/root, which the kernel uses
+ * internally, when no initramfs image is used. For "/", it is safe
+ * to get the major/minor by stat()'ing the mount-point.
+ */
+ if (strcmp (mnt.mnt_dir, "/") == 0 && stat ("/", &statbuf) == 0)
+ devt = statbuf.st_dev;
+
+ /* DING DING DING... the device-node may not exist, or is
+ * already deleted, but the device may be still mounted.
+ *
+ * We will fall back to looking up the device-name, instead
+ * of using major/minor.
+ */
}
- /*HAL_INFO (("* found mounts dev %s (%i:%i)", mnt.mnt_fsname, major (statbuf.st_rdev), minor (statbuf.st_rdev)));*/
- /* match against all hal volumes */
+ /* HAL_INFO (("* found mounts dev %s (%i:%i)", mnt.mnt_fsname,
+ major (devt), minor (devt))); */
+
for (volume = volumes; volume != NULL; volume = g_slist_next (volume)) {
HalDevice *dev;
gboolean is_match;
@@ -233,7 +240,8 @@ blockdev_refresh_mount_state (HalDevice
is_match = FALSE;
dev = HAL_DEVICE (volume->data);
- if (use_device_name_for_match) {
+ /* lookup dev_t or devname of known hal devices */
+ if (major (devt) == 0) {
const char *device_name;
device_name = hal_device_property_get_string (dev, "block.device");
@@ -243,14 +251,16 @@ blockdev_refresh_mount_state (HalDevice
if (strcmp (device_name, mnt.mnt_fsname) == 0)
is_match = TRUE;
} else {
- major = hal_device_property_get_int (dev, "block.major");
- if (major == 0)
+ unsigned int majornum;
+ unsigned int minornum;
+
+ majornum = hal_device_property_get_int (dev, "block.major");
+ if (majornum == 0)
continue;
- minor = hal_device_property_get_int (dev, "block.minor");
- devt = makedev (major, minor);
- /*HAL_INFO ((" match %s (%i:%i)", hal_device_get_udi (dev), major, minor));*/
+ minornum = hal_device_property_get_int (dev, "block.minor");
+ /* HAL_INFO ((" match %s (%i:%i)", hal_device_get_udi (dev), majornum, minornum)); */
- if (statbuf.st_rdev == devt)
+ if (majornum == major (devt) && minornum == minor (devt))
is_match = TRUE;
}
@@ -262,9 +272,8 @@ blockdev_refresh_mount_state (HalDevice
hasmntopt (&mnt, MNTOPT_RO) ? TRUE : FALSE);
hal_device_property_set_string (dev, "volume.mount_point", mnt.mnt_dir);
device_property_atomic_update_end ();
- /*HAL_INFO ((" set %s to be mounted at %s (%s)",
- hal_device_get_udi (dev), mnt.mnt_dir,
- hasmntopt (&mnt, MNTOPT_RO) ? "ro" : "rw"));*/
+ /* HAL_INFO ((" set %s to be mounted at %s (%s)", hal_device_get_udi (dev),
+ mnt.mnt_dir, hasmntopt (&mnt, MNTOPT_RO) ? "ro" : "rw")); */
volumes = g_slist_delete_link (volumes, volume);
break;
}
More information about the hal-commit
mailing list