grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH]: grub: Don't hold raw device open when iterating down into parti


From: David Miller
Subject: [PATCH]: grub: Don't hold raw device open when iterating down into partitions.
Date: Thu, 23 Apr 2009 03:33:14 -0700 (PDT)

This is the first part in fixing FS_UUID on sparc64.  As explained
in some of my previous patch descriptions, you cannot open the
same device node multiple times concurrently in OpenBoot.

The two cases in grub2 which cause this situation were module
dependency handling (already fixed by me a week or so ago) and
FS_UUID.

There are a few layers involved here to get this right.

The first part we handle here is making the core grub device iterator
make a list of partitions to iterate hooks over.  Once it builds the
list, it invokes the hook until non-zero is returned, freeing up
all the resources along the way.

2009-04-23  David S. Miller  <address@hidden>

        Avoiding openning same device multiple times in device iterator.

        * kern/device.c (grub_device_iterate): Define struct part_ent,
        and use it to build a list of partitions in interate_disk() and
        iterate_partition().
---
 kern/device.c |   58 ++++++++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 43 insertions(+), 15 deletions(-)

diff --git a/kern/device.c b/kern/device.c
index 60f25c1..184c3a2 100644
--- a/kern/device.c
+++ b/kern/device.c
@@ -83,6 +83,12 @@ grub_device_iterate (int (*hook) (const char *name))
   auto int iterate_partition (grub_disk_t disk,
                              const grub_partition_t partition);
   
+  struct part_ent
+  {
+    struct part_ent *next;
+    char *name;
+  } *ents = NULL;
+
   int iterate_disk (const char *disk_name)
     {
       grub_device_t dev;
@@ -95,11 +101,28 @@ grub_device_iterate (int (*hook) (const char *name))
        return 0;
       
       if (dev->disk && dev->disk->has_partitions)
-       if (grub_partition_iterate (dev->disk, iterate_partition))
-         {
-           grub_device_close (dev);
-           return 1;
-         }
+       {
+         struct part_ent *p;
+         int ret = 0;
+
+         (void) grub_partition_iterate (dev->disk, iterate_partition);
+         grub_device_close (dev);
+
+         p = ents;
+         ents = NULL;
+         while (p != NULL)
+           {
+             struct part_ent *next = p->next;
+
+             if (!ret)
+               ret = hook (p->name);
+             grub_free (p->name);
+             grub_free (p);
+             p = next;
+           }
+
+         return ret;
+       }
 
       grub_device_close (dev);
       return 0;
@@ -108,27 +131,32 @@ grub_device_iterate (int (*hook) (const char *name))
   int iterate_partition (grub_disk_t disk, const grub_partition_t partition)
     {
       char *partition_name;
-      char *device_name;
-      int ret;
+      struct part_ent *p;
       
       partition_name = grub_partition_get_name (partition);
       if (! partition_name)
        return 1;
-      
-      device_name = grub_malloc (grub_strlen (disk->name) + 1
-                                + grub_strlen (partition_name) + 1);
-      if (! device_name)
+
+      p = grub_malloc (sizeof (*p));
+      if (!p)
+       return 1;
+
+      p->name = grub_malloc (grub_strlen (disk->name) + 1
+                            + grub_strlen (partition_name) + 1);
+      if (! p->name)
        {
+         grub_free (p);
          grub_free (partition_name);
          return 1;
        }
 
-      grub_sprintf (device_name, "%s,%s", disk->name, partition_name);
+      grub_sprintf (p->name, "%s,%s", disk->name, partition_name);
       grub_free (partition_name);
 
-      ret = hook (device_name);
-      grub_free (device_name);
-      return ret;
+      p->next = ents;
+      ents = p;
+
+      return 0;
     }
 
   /* Only disk devices are supported at the moment.  */
-- 
1.6.2.4





reply via email to

[Prev in Thread] Current Thread [Next in Thread]