Whamcloud - gitweb
ChangeLog, get_device_by_label.c:
authorTheodore Ts'o <tytso@mit.edu>
Thu, 27 Jul 2000 02:45:55 +0000 (02:45 +0000)
committerTheodore Ts'o <tytso@mit.edu>
Thu, 27 Jul 2000 02:45:55 +0000 (02:45 +0000)
  get_device_by_label.c: Improve /proc/partitions parsing in fsck, and
   speed up fsck -a.

misc/ChangeLog
misc/get_device_by_label.c

index 4f9a728..56273d4 100644 (file)
@@ -1,3 +1,8 @@
+2000-07-26    <tytso@valinux.com>
+
+       * get_device_by_label.c: Improve /proc/partitions parsing in
+               fsck, and speed up fsck -a.
+
 2000-07-13    <tytso@valinux.com>
 
        * Release of E2fsprogs 1.19
index e03e0f1..7a1a4bd 100644 (file)
@@ -7,6 +7,7 @@
  * License.
  *
  * Taken from aeb's mount, 990619
+ * Updated from aeb's mount, 20000725
  */
 
 #include <stdio.h>
@@ -30,104 +31,147 @@ struct ext2_super_block {
 };
 #define ext2magic(s)    ((unsigned int) s.s_magic[0] + (((unsigned int) s.s_magic[1]) << 8))
 
-
-static FILE *procpt;
-
-static void
-procptclose(void) {
-    if (procpt)
-        fclose (procpt);
-    procpt = 0;
-}
-
-static int
-procptopen(void) {
-    return ((procpt = fopen(PROC_PARTITIONS, "r")) != NULL);
-}
-
-static char *
-procptnext(void) {
-   char line[100];
-   char *s;
-   int ma, mi, sz;
-   static char ptname[100];
-
-   while (fgets(line, sizeof(line), procpt)) {
-      if (sscanf (line, " %d %d %d %[^\n]\n", &ma, &mi, &sz, ptname) != 4)
-             continue;
-
-      /* skip extended partitions (heuristic: size 1) */
-      if (sz == 1)
-             continue;
-
-      /* skip entire disk (minor 0, 64, ... on ide; 0, 16, ... on sd) */
-      /* heuristic: partition name ends in a digit */
-      for(s = ptname; *s; s++);
-      if (isdigit(s[-1]))
-             return ptname;
-   }
-   return 0;
-}
-
-#define UUID   1
-#define VOL    2
+static struct uuidCache_s {
+       struct uuidCache_s *next;
+       char uuid[16];
+       char *label;
+       char *device;
+} *uuidCache = NULL;
 
 /* for now, only ext2 is supported */
 static int
-has_right_label(const char *device, int n, const void *label) {
+get_label_uuid(const char *device, char **label, char *uuid) {
 
        /* start with a test for ext2, taken from mount_guess_fstype */
+       /* should merge these later */
        int fd;
        struct ext2_super_block e2sb;
 
        fd = open(device, O_RDONLY);
        if (fd < 0)
-               return 0;
+               return 1;
 
        if (lseek(fd, 1024, SEEK_SET) != 1024
            || read(fd, (char *) &e2sb, sizeof(e2sb)) != sizeof(e2sb)
            || (ext2magic(e2sb) != EXT2_SUPER_MAGIC)) {
                close(fd);
-               return 0;
+               return 1;
        }
 
        close(fd);
 
        /* superblock is ext2 - now what is its label? */
-       if (n == UUID)
-               return (memcmp(e2sb.s_uuid, label, 16) == 0);
-       else
-               return (strncmp(e2sb.s_volume_name,
-                               (const char *) label, 16) == 0);
+       memcpy(uuid, e2sb.s_uuid, sizeof(e2sb.s_uuid));
+       *label = strdup(e2sb.s_volume_name);
+
+       return 0;
 }
 
-static char *
-get_spec_by_x(int n, const void *t) {
-       char *pt;
+static void
+uuidcache_addentry(char *device, char *label, char *uuid) {
+       struct uuidCache_s *last;
+
+       if (!uuidCache) {
+               last = uuidCache = malloc(sizeof(*uuidCache));
+       } else {
+               for (last = uuidCache; last->next; last = last->next) ;
+               last->next = malloc(sizeof(*uuidCache));
+               last = last->next;
+       }
+       last->next = NULL;
+       last->device = device;
+       last->label = label;
+       memcpy(last->uuid, uuid, sizeof(last->uuid));
+}
+
+static void
+uuidcache_init(void) {
+       char line[100];
+       char *s;
+       int ma, mi, sz;
+       static char ptname[100];
+       FILE *procpt;
+       char uuid[16], *label;
        char device[110];
+       int firstPass;
+       int handleOnFirst;
+
+       if (uuidCache)
+               return;
+
+       procpt = fopen(PROC_PARTITIONS, "r");
+       if (!procpt)
+               return;
+
+       for (firstPass = 1; firstPass >= 0; firstPass--) {
+           fseek(procpt, 0, SEEK_SET);
+
+           while (fgets(line, sizeof(line), procpt)) {
+               if (sscanf (line, " %d %d %d %[^\n ]",
+                           &ma, &mi, &sz, ptname) != 4)
+                       continue;
+
+               /* skip extended partitions (heuristic: size 1) */
+               if (sz == 1)
+                       continue;
+
+               /* look only at md devices on first pass */
+               handleOnFirst = !strncmp(ptname, "md", 2);
+               if (firstPass != handleOnFirst)
+                       continue;
+
+               /* skip entire disk (minor 0, 64, ... on ide;
+                  0, 16, ... on sd) */
+               /* heuristic: partition name ends in a digit */
+
+               for(s = ptname; *s; s++);
+               if (isdigit(s[-1])) {
+               /*
+                * Note: this is a heuristic only - there is no reason
+                * why these devices should live in /dev.
+                * Perhaps this directory should be specifiable by option.
+                * One might for example have /devlabel with links to /dev
+                * for the devices that may be accessed in this way.
+                * (This is useful, if the cdrom on /dev/hdc must not
+                * be accessed.)
+                */
+                       sprintf(device, "%s/%s", DEVLABELDIR, ptname);
+                       if (!get_label_uuid(device, &label, uuid))
+                               uuidcache_addentry(strdup(device), label, uuid);
+               }
+           }
+       }
+
+       fclose(procpt);
+}
+
+#define UUID   1
+#define VOL    2
 
-       if(!procptopen())
-               return NULL;
-       while((pt = procptnext()) != NULL) {
-               /* Note: this is a heuristic only - there is no reason
-                  why these devices should live in /dev.
-                  Perhaps this directory should be specifiable by option.
-                  One might for example have /devlabel with links to /dev
-                  for the devices that may be accessed in this way.
-                  (This is useful, if the cdrom on /dev/hdc must not
-                  be accessed.)
-               */
-               sprintf(device, "%s/%s", DEVLABELDIR, pt);
-               if (has_right_label(device, n, t)) {
-                       procptclose();
-                       return strdup(device);
+static char *
+get_spec_by_x(int n, const char *t) {
+       struct uuidCache_s *uc;
+
+       uuidcache_init();
+       uc = uuidCache;
+
+       while(uc) {
+               switch (n) {
+               case UUID:
+                       if (!memcmp(t, uc->uuid, sizeof(uc->uuid)))
+                               return strdup(uc->device);
+                       break;
+               case VOL:
+                       if (!strcmp(t, uc->label))
+                               return strdup(uc->device);
+                       break;
                }
+               uc = uc->next;
        }
-       procptclose();
        return NULL;
 }
 
-static unsigned char
+static u_char
 fromhex(char c) {
        if (isdigit(c))
                return (c - '0');
@@ -138,10 +182,9 @@ fromhex(char c) {
 }
 
 char *
-get_spec_by_uuid(const char *s0) {
-       unsigned char uuid[16];
+get_spec_by_uuid(const char *s) {
+       u_char uuid[16];
        int i;
-       const char *s = s0;
 
        if (strlen(s) != 36 ||
            s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-')
@@ -156,7 +199,7 @@ get_spec_by_uuid(const char *s0) {
        return get_spec_by_x(UUID, uuid);
 
  bad_uuid:
-       fprintf(stderr, _("WARNING: %s: bad UUID"), s0);
+       fprintf(stderr, _("WARNING: %s: bad UUID"), s);
        return NULL;
 }
 
@@ -164,3 +207,18 @@ char *
 get_spec_by_volume_label(const char *s) {
        return get_spec_by_x(VOL, s);
 }
+
+const char *
+get_volume_label_by_spec(const char *spec) {
+        struct uuidCache_s *uc;
+
+        uuidcache_init();
+        uc = uuidCache;
+
+       while(uc) {
+               if (!strcmp(spec, uc->device))
+                       return uc->label;
+               uc = uc->next;
+       }
+       return NULL;
+}