root / control / tap-ctl-allocate.c @ abdb293f
History | View | Annotate | Download (5.2 kB)
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 |
|
29 |
#ifdef HAVE_CONFIG_H
|
30 |
#include "config.h" |
31 |
#endif
|
32 |
|
33 |
#include <stdio.h> |
34 |
#include <errno.h> |
35 |
#include <fcntl.h> |
36 |
#include <stdlib.h> |
37 |
#include <unistd.h> |
38 |
#include <string.h> |
39 |
#include <getopt.h> |
40 |
#include <libgen.h> |
41 |
#include <sys/stat.h> |
42 |
#include <sys/types.h> |
43 |
#include <sys/ioctl.h> |
44 |
#include <linux/major.h> |
45 |
|
46 |
#include "tap-ctl.h" |
47 |
#include "blktap2.h" |
48 |
|
49 |
static int |
50 |
tap_ctl_prepare_directory(const char *dir) |
51 |
{ |
52 |
int err;
|
53 |
char *ptr, *name, *start;
|
54 |
|
55 |
err = access(dir, W_OK | R_OK); |
56 |
if (!err)
|
57 |
return 0; |
58 |
|
59 |
name = strdup(dir); |
60 |
if (!name)
|
61 |
return ENOMEM;
|
62 |
|
63 |
start = name; |
64 |
|
65 |
for (;;) {
|
66 |
ptr = strchr(start + 1, '/'); |
67 |
if (ptr)
|
68 |
*ptr = '\0';
|
69 |
|
70 |
err = mkdir(name, 0755);
|
71 |
if (err && errno != EEXIST) {
|
72 |
PERROR("mkdir %s", name);
|
73 |
err = errno; |
74 |
break;
|
75 |
} |
76 |
|
77 |
if (!ptr)
|
78 |
break;
|
79 |
else {
|
80 |
*ptr = '/';
|
81 |
start = ptr + 1;
|
82 |
} |
83 |
} |
84 |
|
85 |
free(name); |
86 |
return err;
|
87 |
} |
88 |
|
89 |
static int |
90 |
tap_ctl_make_device(const char *devname, const int major, |
91 |
const int minor, const int perm) |
92 |
{ |
93 |
int err;
|
94 |
char *copy, *dir;
|
95 |
|
96 |
copy = strdup(devname); |
97 |
if (!copy)
|
98 |
return ENOMEM;
|
99 |
|
100 |
dir = dirname(copy); |
101 |
|
102 |
err = tap_ctl_prepare_directory(dir); |
103 |
free(copy); |
104 |
|
105 |
if (err)
|
106 |
return err;
|
107 |
|
108 |
if (!access(devname, F_OK))
|
109 |
if (unlink(devname)) {
|
110 |
PERROR("unlink %s", devname);
|
111 |
return errno;
|
112 |
} |
113 |
|
114 |
err = mknod(devname, perm, makedev(major, minor)); |
115 |
if (err) {
|
116 |
PERROR("mknod %s", devname);
|
117 |
return errno;
|
118 |
} |
119 |
|
120 |
return 0; |
121 |
} |
122 |
|
123 |
static int |
124 |
tap_ctl_check_environment(void)
|
125 |
{ |
126 |
FILE *f; |
127 |
int err, minor;
|
128 |
char name[256]; |
129 |
|
130 |
err = tap_ctl_prepare_directory(BLKTAP2_CONTROL_DIR); |
131 |
if (err)
|
132 |
return err;
|
133 |
|
134 |
if (!access(BLKTAP2_CONTROL_DEVICE, R_OK | W_OK))
|
135 |
return 0; |
136 |
|
137 |
memset(name, 0, sizeof(name)); |
138 |
|
139 |
f = fopen("/proc/misc", "r"); |
140 |
if (!f) {
|
141 |
EPRINTF("failed to open /proc/misc: %d\n", errno);
|
142 |
return errno;
|
143 |
} |
144 |
|
145 |
while (fscanf(f, "%d %256s", &minor, name) == 2) |
146 |
if (!strcmp(name, BLKTAP2_CONTROL_NAME)) {
|
147 |
err = tap_ctl_make_device(BLKTAP2_CONTROL_DEVICE, |
148 |
MISC_MAJOR, |
149 |
minor, S_IFCHR | 0600);
|
150 |
goto out;
|
151 |
} |
152 |
|
153 |
err = ENOSYS; |
154 |
EPRINTF("didn't find %s in /proc/misc\n", BLKTAP2_CONTROL_NAME);
|
155 |
|
156 |
out:
|
157 |
fclose(f); |
158 |
return err;
|
159 |
} |
160 |
|
161 |
static int |
162 |
tap_ctl_allocate_device(int *minor, char **devname) |
163 |
{ |
164 |
char *name;
|
165 |
int fd, err;
|
166 |
struct blktap2_handle handle;
|
167 |
|
168 |
*minor = -1;
|
169 |
if (!devname)
|
170 |
return EINVAL;
|
171 |
|
172 |
fd = open(BLKTAP2_CONTROL_DEVICE, O_RDONLY); |
173 |
if (fd == -1) { |
174 |
EPRINTF("failed to open control device: %d\n", errno);
|
175 |
return errno;
|
176 |
} |
177 |
|
178 |
err = ioctl(fd, BLKTAP2_IOCTL_ALLOC_TAP, &handle); |
179 |
close(fd); |
180 |
if (err == -1) { |
181 |
EPRINTF("failed to allocate new device: %d\n", errno);
|
182 |
return errno;
|
183 |
} |
184 |
|
185 |
err = asprintf(&name, "%s%d", BLKTAP2_RING_DEVICE, handle.minor);
|
186 |
if (err == -1) { |
187 |
err = ENOMEM; |
188 |
goto fail;
|
189 |
} |
190 |
|
191 |
err = tap_ctl_make_device(name, handle.ring, |
192 |
handle.minor, S_IFCHR | 0600);
|
193 |
free(name); |
194 |
if (err) {
|
195 |
EPRINTF("creating ring device for %d failed: %d\n",
|
196 |
handle.minor, err); |
197 |
goto fail;
|
198 |
} |
199 |
|
200 |
if (*devname)
|
201 |
name = *devname; |
202 |
else {
|
203 |
err = asprintf(&name, "%s%d",
|
204 |
BLKTAP2_IO_DEVICE, handle.minor); |
205 |
if (err == -1) { |
206 |
err = ENOMEM; |
207 |
goto fail;
|
208 |
} |
209 |
*devname = name; |
210 |
} |
211 |
|
212 |
err = tap_ctl_make_device(name, handle.device, |
213 |
handle.minor, S_IFBLK | 0600);
|
214 |
if (err) {
|
215 |
EPRINTF("creating IO device for %d failed: %d\n",
|
216 |
handle.minor, err); |
217 |
goto fail;
|
218 |
} |
219 |
|
220 |
DBG("new interface: ring: %u, device: %u, minor: %u\n",
|
221 |
handle.ring, handle.device, handle.minor); |
222 |
|
223 |
*minor = handle.minor; |
224 |
return 0; |
225 |
|
226 |
fail:
|
227 |
tap_ctl_free(handle.minor); |
228 |
return err;
|
229 |
} |
230 |
|
231 |
int
|
232 |
tap_ctl_allocate(int *minor, char **devname) |
233 |
{ |
234 |
int err;
|
235 |
|
236 |
*minor = -1;
|
237 |
|
238 |
err = tap_ctl_check_environment(); |
239 |
if (err)
|
240 |
return err;
|
241 |
|
242 |
err = tap_ctl_allocate_device(minor, devname); |
243 |
if (err)
|
244 |
return err;
|
245 |
|
246 |
return 0; |
247 |
} |