debuggers.hg

view tools/blktap2/control/tap-ctl-allocate.c @ 22848:6341fe0f4e5a

Added tag 4.1.0-rc2 for changeset 9dca60d88c63
author Keir Fraser <keir@xen.org>
date Tue Jan 25 14:06:55 2011 +0000 (2011-01-25)
parents 63d0f5348af2
children
line source
1 /*
2 * Copyright (c) 2008, XenSource Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of XenSource Inc. nor the names of its contributors
13 * may be used to endorse or promote products derived from this software
14 * without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
20 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28 #include <stdio.h>
29 #include <errno.h>
30 #include <fcntl.h>
31 #include <stdlib.h>
32 #include <unistd.h>
33 #include <string.h>
34 #include <getopt.h>
35 #include <libgen.h>
36 #include <sys/stat.h>
37 #include <sys/types.h>
38 #include <sys/ioctl.h>
39 #include <linux/major.h>
41 #include "tap-ctl.h"
42 #include "blktap2.h"
44 static int
45 tap_ctl_prepare_directory(const char *dir)
46 {
47 int err;
48 char *ptr, *name, *start;
50 err = access(dir, W_OK | R_OK);
51 if (!err)
52 return 0;
54 name = strdup(dir);
55 if (!name)
56 return ENOMEM;
58 start = name;
60 for (;;) {
61 ptr = strchr(start + 1, '/');
62 if (ptr)
63 *ptr = '\0';
65 err = mkdir(name, 0755);
66 if (err && errno != EEXIST) {
67 PERROR("mkdir %s", name);
68 err = errno;
69 break;
70 }
72 if (!ptr)
73 break;
74 else {
75 *ptr = '/';
76 start = ptr + 1;
77 }
78 }
80 free(name);
81 return err;
82 }
84 static int
85 tap_ctl_make_device(const char *devname, const int major,
86 const int minor, const int perm)
87 {
88 int err;
89 char *copy, *dir;
91 copy = strdup(devname);
92 if (!copy)
93 return ENOMEM;
95 dir = dirname(copy);
97 err = tap_ctl_prepare_directory(dir);
98 free(copy);
100 if (err)
101 return err;
103 if (!access(devname, F_OK))
104 if (unlink(devname)) {
105 PERROR("unlink %s", devname);
106 return errno;
107 }
109 err = mknod(devname, perm, makedev(major, minor));
110 if (err) {
111 PERROR("mknod %s", devname);
112 return errno;
113 }
115 return 0;
116 }
118 static int
119 tap_ctl_check_environment(void)
120 {
121 FILE *f;
122 int err, minor;
123 char name[256];
125 err = tap_ctl_prepare_directory(BLKTAP2_CONTROL_DIR);
126 if (err)
127 return err;
129 if (!access(BLKTAP2_CONTROL_DEVICE, R_OK | W_OK))
130 return 0;
132 memset(name, 0, sizeof(name));
134 f = fopen("/proc/misc", "r");
135 if (!f) {
136 EPRINTF("failed to open /proc/misc: %d\n", errno);
137 return errno;
138 }
140 while (fscanf(f, "%d %256s", &minor, name) == 2)
141 if (!strcmp(name, BLKTAP2_CONTROL_NAME)) {
142 err = tap_ctl_make_device(BLKTAP2_CONTROL_DEVICE,
143 MISC_MAJOR,
144 minor, S_IFCHR | 0600);
145 goto out;
146 }
148 err = ENOSYS;
149 EPRINTF("didn't find %s in /proc/misc\n", BLKTAP2_CONTROL_NAME);
151 out:
152 fclose(f);
153 return err;
154 }
156 static int
157 tap_ctl_allocate_device(int *minor, char **devname)
158 {
159 char *name;
160 int fd, err;
161 struct blktap2_handle handle;
163 *minor = -1;
164 if (!devname)
165 return EINVAL;
167 fd = open(BLKTAP2_CONTROL_DEVICE, O_RDONLY);
168 if (fd == -1) {
169 EPRINTF("failed to open control device: %d\n", errno);
170 return errno;
171 }
173 err = ioctl(fd, BLKTAP2_IOCTL_ALLOC_TAP, &handle);
174 close(fd);
175 if (err == -1) {
176 EPRINTF("failed to allocate new device: %d\n", errno);
177 return errno;
178 }
180 err = asprintf(&name, "%s%d", BLKTAP2_RING_DEVICE, handle.minor);
181 if (err == -1) {
182 err = ENOMEM;
183 goto fail;
184 }
186 err = tap_ctl_make_device(name, handle.ring,
187 handle.minor, S_IFCHR | 0600);
188 free(name);
189 if (err) {
190 EPRINTF("creating ring device for %d failed: %d\n",
191 handle.minor, err);
192 goto fail;
193 }
195 if (*devname)
196 name = *devname;
197 else {
198 err = asprintf(&name, "%s%d",
199 BLKTAP2_IO_DEVICE, handle.minor);
200 if (err == -1) {
201 err = ENOMEM;
202 goto fail;
203 }
204 *devname = name;
205 }
207 err = tap_ctl_make_device(name, handle.device,
208 handle.minor, S_IFBLK | 0600);
209 if (err) {
210 EPRINTF("creating IO device for %d failed: %d\n",
211 handle.minor, err);
212 goto fail;
213 }
215 DBG("new interface: ring: %u, device: %u, minor: %u\n",
216 handle.ring, handle.device, handle.minor);
218 *minor = handle.minor;
219 return 0;
221 fail:
222 tap_ctl_free(handle.minor);
223 return err;
224 }
226 int
227 tap_ctl_allocate(int *minor, char **devname)
228 {
229 int err;
231 *minor = -1;
233 err = tap_ctl_check_environment();
234 if (err)
235 return err;
237 err = tap_ctl_allocate_device(minor, devname);
238 if (err)
239 return err;
241 return 0;
242 }