~smb/ubuntu/lucid/initramfs-tools/proposed

« back to all changes in this revision

Viewing changes to src/wait-for-root.c

  • Committer: Bazaar Package Importer
  • Author(s): Scott James Remnant
  • Date: 2009-12-18 03:18:28 UTC
  • Revision ID: james.westby@ubuntu.com-20091218031828-5gec09e8vq3hia2s
Tags: 0.92bubuntu58
* Add new initramfs-tools-bin package containing a binary that uses
  libudev to wait for udev to create the udev device, or wait for udev
  to finish processing if we catch it in the act, and returns the
  filesystem type as already probed by udev.
  - This avoids calls to udevadm settle, which make us wait for irrelevant
    modules that we don't need.
  - This avoids duplicate calls to blkid, which since they probe the block
    device directly, are expensive
  - This does not use fstype; which avoids issues with that and blkid
    returning different answers (since everything else throughout the
    entire system now uses blkid)
* scripts/local: Rewrite to use wait-for-root rather than looping over
  our own shell attempts to do the same.
* mkinitramfs:
  - include wait-for-root
  - mkinitramfs: Don't quote modules.*map, so we actually expand it.
* hooks/thermal:
  - don't force load fan or thermal, they're generally built-in and if not
    will be loaded by udev anyway
* scripts/panic/keymap:
  - auto-generated from the init-top keymap file, with the OPTION= removed,
    so keymap will always be set on panic

* Remove accidentally included test initramfs.  :-)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <libudev.h>
 
2
 
 
3
#include <sys/types.h>
 
4
#include <sys/stat.h>
 
5
 
 
6
#include <time.h>
 
7
#include <stdio.h>
 
8
#include <signal.h>
 
9
#include <stdlib.h>
 
10
#include <string.h>
 
11
#include <unistd.h>
 
12
 
 
13
 
 
14
static int matching_device (struct udev_device *device, const char *path);
 
15
 
 
16
static void alarm_handler (int signum);
 
17
 
 
18
 
 
19
int
 
20
main (int   argc,
 
21
      char *argv[])
 
22
{
 
23
        const char *         devpath;
 
24
        const char *         rootdelay;
 
25
        int                  timeout;
 
26
        struct udev *        udev;
 
27
        struct udev_monitor *udev_monitor;
 
28
        struct stat          devstat;
 
29
        struct udev_device * udev_device = NULL;
 
30
 
 
31
        if (argc != 2) {
 
32
                fprintf (stderr, "Usage: %s DEVICE\n", argv[0]);
 
33
                exit (2);
 
34
        }
 
35
 
 
36
        devpath = argv[1];
 
37
 
 
38
        rootdelay = getenv ("ROOTDELAY");
 
39
        if (rootdelay) {
 
40
                timeout = atoi (rootdelay) ?: 30;
 
41
        } else {
 
42
                timeout = 30;
 
43
        }
 
44
 
 
45
        signal (SIGALRM, alarm_handler);
 
46
        alarm (timeout);
 
47
 
 
48
        /* Connect to the udev monitor first; if we stat() first, the
 
49
         * event might happen between the stat() and the time we actually
 
50
         * get hooked up.
 
51
         */
 
52
        udev = udev_new ();
 
53
        udev_monitor = udev_monitor_new_from_netlink (udev, "udev");
 
54
 
 
55
        udev_monitor_filter_add_match_subsystem_devtype (udev_monitor, "block", NULL);
 
56
        udev_monitor_enable_receiving (udev_monitor);
 
57
 
 
58
        /* Check whether or not the device already exists */
 
59
        if ((stat (devpath, &devstat) == 0)
 
60
            && S_ISBLK (devstat.st_mode)) {
 
61
                struct udev_queue *     udev_queue;
 
62
                struct udev_list_entry *queue_entry;
 
63
 
 
64
                /* Make sure that the device is not currently queued */
 
65
                udev_queue = udev_queue_new (udev);
 
66
 
 
67
                for (queue_entry = udev_queue_get_queued_list_entry (udev_queue);
 
68
                     queue_entry != NULL;
 
69
                     queue_entry = udev_list_entry_get_next (queue_entry)) {
 
70
                        const char *syspath;
 
71
 
 
72
                        syspath = udev_list_entry_get_name (queue_entry);
 
73
                        udev_device = udev_device_new_from_syspath (udev, syspath);
 
74
 
 
75
                        /* If the device exists, we wait for it to leave
 
76
                         * the queue.
 
77
                         */
 
78
                        if (udev_device
 
79
                            && matching_device (udev_device, devpath)) {
 
80
                                struct timespec    time;
 
81
                                unsigned long long seqnum;
 
82
 
 
83
                                sscanf (udev_list_entry_get_value (queue_entry),
 
84
                                        "%llu", &seqnum);
 
85
 
 
86
                                time.tv_sec = 0;
 
87
                                time.tv_nsec = 100000000;
 
88
 
 
89
                                while (! udev_queue_get_seqnum_is_finished (udev_queue, seqnum))
 
90
                                        nanosleep (&time, NULL);
 
91
 
 
92
                                break;
 
93
                        } else
 
94
                                udev_device_unref (udev_device);
 
95
                }
 
96
 
 
97
                udev_queue_unref (udev_queue);
 
98
 
 
99
                /* If the device exists but isn't queued, look it up in the
 
100
                 * udevdb by major/minor number (since udev must have created
 
101
                 * it).
 
102
                 */
 
103
                if (! udev_device)
 
104
                        udev_device = udev_device_new_from_devnum (udev, 'b', devstat.st_rdev);
 
105
 
 
106
        } else {
 
107
                while ((udev_device = udev_monitor_receive_device (udev_monitor)) != NULL) {
 
108
                        if (matching_device (udev_device, devpath))
 
109
                                break;
 
110
 
 
111
                        udev_device_unref (udev_device);
 
112
                }
 
113
        }
 
114
 
 
115
 
 
116
        if (udev_device) {
 
117
                const char *type;
 
118
 
 
119
                type = udev_device_get_property_value (udev_device, "ID_FS_TYPE");
 
120
                if (type) {
 
121
                        printf ("%s\n", udev_device_get_property_value (udev_device, "ID_FS_TYPE"));
 
122
                        udev_device_unref (udev_device);
 
123
                } else {
 
124
                        udev_device_unref (udev_device);
 
125
                        udev_device = NULL;
 
126
                }
 
127
        }
 
128
 
 
129
 
 
130
        udev_monitor_unref (udev_monitor);
 
131
        udev_unref (udev);
 
132
 
 
133
        exit (udev_device ? 0 : 1);
 
134
}
 
135
 
 
136
 
 
137
static int
 
138
matching_device (struct udev_device *device,
 
139
                 const char *        path)
 
140
{
 
141
        const char *            fs_type;
 
142
        struct udev_list_entry *devlinks_entry;
 
143
 
 
144
        fs_type = udev_device_get_property_value (device, "ID_FS_TYPE");
 
145
        if (! fs_type)
 
146
                return 0;
 
147
 
 
148
        /* Match by name */
 
149
        if (! strcmp (path, udev_device_get_devnode (device)))
 
150
                return 1;
 
151
 
 
152
        /* Match by UUID */
 
153
        if (! strncmp (path, "UUID=", 5)) {
 
154
                const char *uuid;
 
155
 
 
156
                uuid = udev_device_get_property_value (device, "ID_FS_UUID");
 
157
                if (uuid && (! strcmp (path + 5, uuid)))
 
158
                        return 1;
 
159
        }
 
160
 
 
161
        /* Match by LABEL */
 
162
        if (! strncmp (path, "LABEL=", 6)) {
 
163
                const char *label;
 
164
 
 
165
                label = udev_device_get_property_value (device, "ID_FS_LABEL");
 
166
                if (label && (! strcmp (path + 6, label)))
 
167
                        return 1;
 
168
        }
 
169
 
 
170
        /* Match by symlink */
 
171
        for (devlinks_entry = udev_device_get_devlinks_list_entry (device);
 
172
             devlinks_entry != NULL;
 
173
             devlinks_entry = udev_list_entry_get_next (devlinks_entry))
 
174
                if (! strcmp (path, udev_list_entry_get_name (devlinks_entry)))
 
175
                        return 1;
 
176
 
 
177
        return 0;
 
178
}
 
179
 
 
180
 
 
181
static void
 
182
alarm_handler (int signum)
 
183
{
 
184
        exit (1);
 
185
}