Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2016, Citrix Systems, Inc.
3 : : *
4 : : * All rights reserved.
5 : : *
6 : : * Redistribution and use in source and binary forms, with or without
7 : : * modification, are permitted provided that the following conditions are met:
8 : : *
9 : : * 1. Redistributions of source code must retain the above copyright
10 : : * notice, this list of conditions and the following disclaimer.
11 : : * 2. Redistributions in binary form must reproduce the above copyright
12 : : * notice, this list of conditions and the following disclaimer in the
13 : : * documentation and/or other materials provided with the distribution.
14 : : * 3. Neither the name of the copyright holder nor the names of its
15 : : * contributors may be used to endorse or promote products derived from
16 : : * this software without specific prior written permission.
17 : : *
18 : : * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 : : * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 : : * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 : : * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
22 : : * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 : : * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 : : * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25 : : * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26 : : * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 : : * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 : : * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 : : */
30 : :
31 : : #include <sys/types.h>
32 : : #include <fcntl.h>
33 : : #include <unistd.h>
34 : : #include <stdio.h>
35 : : #include <dirent.h>
36 : : #include <sys/stat.h>
37 : : #include <stdlib.h>
38 : : #include <errno.h>
39 : : #include <string.h>
40 : :
41 : : #include "tapdisk-metrics.h"
42 : : #include "tapdisk-log.h"
43 : : #include "debug.h"
44 : : #include "td-req.h"
45 : :
46 : : #define VBD_STATS_VERSION 0x00000001
47 : :
48 : : /* make a static metrics struct, so it only exists in the context of this file */
49 : : static td_metrics_t td_metrics;
50 : :
51 : : /* Returns 0 in case there were no problems while emptying the folder */
52 : : static int
53 : 0 : empty_folder(char *path)
54 : : {
55 : : DIR *dir;
56 : : struct dirent *direntry;
57 : : struct stat statbuf;
58 : 0 : char *file = NULL;
59 : 0 : int err = 0;
60 : :
61 : 0 : dir = opendir(path);
62 [ # # ]: 0 : if (!dir){
63 : 0 : err = errno;
64 : 0 : EPRINTF("failed to open directory: %s\n", strerror(err));
65 : : goto out;
66 : : }
67 : :
68 [ # # ]: 0 : while((direntry = readdir(dir)) != NULL){
69 [ # # ][ # # ]: 0 : if(!strcmp(direntry->d_name, ".") || !strcmp(direntry->d_name, ".."))
[ # # ][ # # ]
[ # # ]
70 : 0 : continue;
71 : :
72 : 0 : err = asprintf(&file, "%s/%s", path, direntry->d_name);
73 [ # # ]: 0 : if (unlikely(err == -1)) {
74 : 0 : free(file);
75 : 0 : file = NULL;
76 : 0 : err = errno;
77 : 0 : EPRINTF("failed to allocate file path name in memory to delete: %s\n",
78 : : strerror(err));
79 : : goto out;
80 : : }
81 : 0 : stat(file, &statbuf);
82 [ # # ]: 0 : if(statbuf.st_mode & S_IFREG){
83 : 0 : unlink(file);
84 : : }else{
85 : 0 : empty_folder(file);
86 : 0 : rmdir(file);
87 : : }
88 : 0 : free(file);
89 : 0 : file = NULL;
90 : : }
91 : :
92 : : out:
93 [ # # ]: 0 : if (dir)
94 : 0 : closedir(dir);
95 : :
96 : 0 : return err;
97 : : }
98 : :
99 : : int
100 : 0 : td_metrics_start()
101 : : {
102 : 0 : int err = 0;
103 : :
104 : 0 : err = asprintf(&td_metrics.path, TAPDISK_METRICS_PATHF, getpid());
105 [ # # ]: 0 : if (unlikely(err == -1)) {
106 : 0 : err = errno;
107 : 0 : EPRINTF("failed to allocate metric's folder path name in memory: %s\n",
108 : : strerror(err));
109 : 0 : td_metrics.path = NULL;
110 : 0 : goto out;
111 : : }
112 : :
113 : 0 : err = mkdir(td_metrics.path, S_IRWXU);
114 [ # # ]: 0 : if (unlikely(err == -1)) {
115 [ # # ]: 0 : if (errno == EEXIST) {
116 : : /* In case there is a previous folder with the same pid,
117 : : * we empty it and use it for the new tapdisk instance.
118 : : */
119 : 0 : err = 0;
120 : 0 : empty_folder(td_metrics.path);
121 : : }else{
122 : 0 : EPRINTF("failed to create folder to store metrics: %s\n", strerror(err));
123 : : }
124 : : }
125 : :
126 : : out:
127 : 0 : return err;
128 : : }
129 : :
130 : : void
131 : 0 : td_metrics_stop()
132 : : {
133 [ # # ]: 0 : if (!td_metrics.path)
134 : : goto out;
135 : :
136 : 0 : empty_folder(td_metrics.path);
137 : :
138 [ # # ]: 0 : if (rmdir(td_metrics.path) == -1){
139 : 0 : EPRINTF("failed to delete metrics folder: %s\n", strerror(errno));
140 : : goto out;
141 : : }
142 : :
143 : 0 : free(td_metrics.path);
144 : 0 : td_metrics.path = NULL;
145 : :
146 : : out:
147 : 0 : return;
148 : : }
149 : :
150 : : int
151 : 0 : td_metrics_vdi_start(int minor, stats_t *vdi_stats)
152 : : {
153 : 0 : int err = 0;
154 : :
155 [ # # ]: 0 : if(!td_metrics.path)
156 : : goto out;
157 : :
158 : 0 : shm_init(&vdi_stats->shm);
159 : :
160 : 0 : err = asprintf(&vdi_stats->shm.path, TAPDISK_METRICS_VDI_PATHF,
161 : : td_metrics.path, minor);
162 : :
163 [ # # ]: 0 : if(unlikely(err == -1)){
164 : 0 : err = errno;
165 : 0 : EPRINTF("failed to allocate memory to store vdi metrics path: %s\n",
166 : : strerror(err));
167 : 0 : vdi_stats->shm.path = NULL;
168 : 0 : goto out;
169 : : }
170 : :
171 : 0 : vdi_stats->shm.size = PAGE_SIZE;
172 : :
173 : 0 : err = shm_create(&vdi_stats->shm);
174 [ # # ]: 0 : if (unlikely(err)) {
175 : 0 : err = errno;
176 : 0 : EPRINTF("failed to create shm ring stats file: %s\n", strerror(err));
177 : : goto out;
178 : : }
179 : :
180 : 0 : vdi_stats->stats = vdi_stats->shm.mem;
181 : :
182 : : out:
183 : 0 : return err;
184 : : }
185 : :
186 : : int
187 : 0 : td_metrics_vdi_stop(stats_t *vdi_stats)
188 : : {
189 : 0 : int err = 0;
190 : :
191 [ # # ]: 0 : if(!vdi_stats->shm.path)
192 : : goto end;
193 : :
194 : 0 : err = shm_destroy(&vdi_stats->shm);
195 [ # # ]: 0 : if (unlikely(err)) {
196 : 0 : err = errno;
197 : 0 : EPRINTF("failed to destroy vdi metrics file: %s\n", strerror(err));
198 : : }
199 : :
200 : 0 : free(vdi_stats->shm.path);
201 : 0 : vdi_stats->shm.path = NULL;
202 : :
203 : : end:
204 : 0 : return err;
205 : : }
206 : : int
207 : 0 : td_metrics_vbd_start(int domain, int id, stats_t *vbd_stats)
208 : : {
209 : 0 : int err = 0;
210 : :
211 [ # # ]: 0 : if(!td_metrics.path)
212 : : goto out;
213 : :
214 : 0 : shm_init(&vbd_stats->shm);
215 : :
216 : 0 : err = asprintf(&vbd_stats->shm.path, TAPDISK_METRICS_VBD_PATHF,
217 : : td_metrics.path, domain, id);
218 [ # # ]: 0 : if(unlikely(err == -1)){
219 : 0 : err = errno;
220 : 0 : EPRINTF("failed to allocate memory to store vbd metrics path: %s\n",
221 : : strerror(err));
222 : 0 : vbd_stats->shm.path = NULL;
223 : 0 : goto out;
224 : : }
225 : :
226 : 0 : vbd_stats->shm.size = PAGE_SIZE;
227 : :
228 : 0 : err = shm_create(&vbd_stats->shm);
229 [ # # ]: 0 : if (unlikely(err)) {
230 : 0 : err = errno;
231 : 0 : EPRINTF("failed to create shm ring stats file: %s\n", strerror(err));
232 : : goto out;
233 : : }
234 : 0 : vbd_stats->stats = vbd_stats->shm.mem;
235 : 0 : vbd_stats->stats->version = VBD_STATS_VERSION;
236 : : out:
237 : 0 : return err;
238 : :
239 : : }
240 : :
241 : : int
242 : 0 : td_metrics_vbd_stop(stats_t *vbd_stats)
243 : : {
244 : 0 : int err = 0;
245 : :
246 [ # # ]: 0 : if(!vbd_stats->shm.path)
247 : : goto end;
248 : :
249 : 0 : err = shm_destroy(&vbd_stats->shm);
250 [ # # ]: 0 : if (unlikely(err)) {
251 : 0 : err = errno;
252 : 0 : EPRINTF("failed to destroy vbd metrics file: %s\n", strerror(err));
253 : : }
254 : :
255 : 0 : free(vbd_stats->shm.path);
256 : 0 : vbd_stats->shm.path = NULL;
257 : 0 : vbd_stats->stats = NULL;
258 : :
259 : : end:
260 : 0 : return err;
261 : : }
262 : :
263 : : int
264 : 0 : td_metrics_blktap_start(int minor, stats_t *blktap_stats)
265 : : {
266 : :
267 : 0 : int err = 0;
268 : :
269 [ # # ]: 0 : if(!td_metrics.path)
270 : : goto out;
271 : :
272 : 0 : shm_init(&blktap_stats->shm);
273 : :
274 : 0 : err = asprintf(&blktap_stats->shm.path, TAPDISK_METRICS_BLKTAP_PATHF, td_metrics.path, minor);
275 [ # # ]: 0 : if(unlikely(err == -1)){
276 : 0 : err = errno;
277 : 0 : EPRINTF("failed to allocate memory to store blktap metrics path: %s\n",strerror(err));
278 : 0 : blktap_stats->shm.path = NULL;
279 : 0 : goto out;
280 : : }
281 : :
282 : 0 : blktap_stats->shm.size = PAGE_SIZE;
283 : :
284 : 0 : err = shm_create(&blktap_stats->shm);
285 [ # # ]: 0 : if (unlikely(err)) {
286 : 0 : err = errno;
287 : 0 : EPRINTF("failed to create blktap shm ring stats file: %s\n", strerror(err));
288 : : goto out;
289 : : }
290 : 0 : blktap_stats->stats = blktap_stats->shm.mem;
291 : : out:
292 : 0 : return err;
293 : : }
294 : :
295 : : int
296 : 0 : td_metrics_blktap_stop(stats_t *blktap_stats)
297 : : {
298 : 0 : int err = 0;
299 : :
300 [ # # ]: 0 : if(!blktap_stats->shm.path)
301 : : goto end;
302 : :
303 : 0 : err = shm_destroy(&blktap_stats->shm);
304 [ # # ]: 0 : if (unlikely(err)) {
305 : 0 : err = errno;
306 : 0 : EPRINTF("failed to destroy blktap metrics file: %s\n", strerror(err));
307 : : }
308 : :
309 : 0 : free(blktap_stats->shm.path);
310 : 0 : blktap_stats->shm.path = NULL;
311 : :
312 : : end:
313 : 0 : return err;
314 : :
315 : : }
316 : :
317 : : static int
318 : 0 : td_metrics_nbd_start(stats_t *nbd_stats, int minor, const char *pathf)
319 : : {
320 : 0 : int err = 0;
321 : :
322 [ # # ][ # # ]: 0 : if(!td_metrics.path || nbd_stats->shm.path != NULL)
323 : : goto out;
324 : :
325 : 0 : shm_init(&nbd_stats->shm);
326 : :
327 : 0 : err = asprintf(&nbd_stats->shm.path, pathf, td_metrics.path, minor);
328 [ # # ]: 0 : if(unlikely(err == -1)){
329 : 0 : err = errno;
330 : 0 : EPRINTF("failed to allocate memory to store NBD metrics path: %s\n",strerror(err));
331 : 0 : nbd_stats->shm.path = NULL;
332 : 0 : goto out;
333 : : }
334 : :
335 : 0 : nbd_stats->shm.size = PAGE_SIZE;
336 : :
337 : 0 : err = shm_create(&nbd_stats->shm);
338 [ # # ]: 0 : if (unlikely(err)) {
339 : 0 : err = errno;
340 : 0 : EPRINTF("failed to create NBD shm ring stats file: %s\n", strerror(err));
341 : : goto out;
342 : : }
343 : 0 : nbd_stats->stats = nbd_stats->shm.mem;
344 : : out:
345 : 0 : return err;
346 : : }
347 : :
348 : : int
349 : 0 : td_metrics_nbd_start_old(stats_t *nbd_stats, int minor)
350 : : {
351 : 0 : return td_metrics_nbd_start(nbd_stats, minor, TAPDISK_METRICS_NBD_PATHF_OLD);
352 : : }
353 : :
354 : : int
355 : 0 : td_metrics_nbd_start_new(stats_t *nbd_stats, int minor)
356 : : {
357 : 0 : return td_metrics_nbd_start(nbd_stats, minor, TAPDISK_METRICS_NBD_PATHF_NEW);
358 : : }
359 : :
360 : : int
361 : 0 : td_metrics_nbd_stop(stats_t *nbd_stats)
362 : : {
363 : 0 : int err = 0;
364 : :
365 [ # # ]: 0 : if(!nbd_stats->shm.path)
366 : : goto end;
367 : 0 : err = shm_destroy(&nbd_stats->shm);
368 [ # # ]: 0 : if (unlikely(err)) {
369 : 0 : err = errno;
370 : 0 : EPRINTF("failed to destroy NBD metrics file: %s\n", strerror(err));
371 : : }
372 : :
373 : 0 : free(nbd_stats->shm.path);
374 : 0 : nbd_stats->shm.path = NULL;
375 : :
376 : : end:
377 : 0 : return err;
378 : : }
|