Branch data Line data Source code
1 : : /*
2 : : * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
3 : : * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
4 : : *
5 : : * This file is part of LVM2.
6 : : *
7 : : * This copyrighted material is made available to anyone wishing to use,
8 : : * modify, copy, or redistribute it subject to the terms and conditions
9 : : * of the GNU Lesser General Public License v.2.1.
10 : : *
11 : : * You should have received a copy of the GNU Lesser General Public License
12 : : * along with this program; if not, write to the Free Software Foundation,
13 : : * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14 : : */
15 : :
16 : : #include "lib.h"
17 : : #include "lvm-types.h"
18 : : #include "device.h"
19 : : #include "metadata.h"
20 : : #include "lvmcache.h"
21 : : #include "memlock.h"
22 : : #include "locking.h"
23 : :
24 : : #include <limits.h>
25 : : #include <sys/stat.h>
26 : : #include <fcntl.h>
27 : : #include <unistd.h>
28 : : #include <sys/ioctl.h>
29 : :
30 : : #ifdef linux
31 : : # define u64 uint64_t /* Missing without __KERNEL__ */
32 : : # undef WNOHANG /* Avoid redefinition */
33 : : # undef WUNTRACED /* Avoid redefinition */
34 : : # include <linux/fs.h> /* For block ioctl definitions */
35 : : # define BLKSIZE_SHIFT SECTOR_SHIFT
36 : : # ifndef BLKGETSIZE64 /* fs.h out-of-date */
37 : : # define BLKGETSIZE64 _IOR(0x12, 114, size_t)
38 : : # endif /* BLKGETSIZE64 */
39 : : #else
40 : : # include <sys/disk.h>
41 : : # define BLKBSZGET DKIOCGETBLOCKSIZE
42 : : # define BLKSSZGET DKIOCGETBLOCKSIZE
43 : : # define BLKGETSIZE64 DKIOCGETBLOCKCOUNT
44 : : # define BLKFLSBUF DKIOCSYNCHRONIZECACHE
45 : : # define BLKSIZE_SHIFT 0
46 : : #endif
47 : :
48 : : #ifdef O_DIRECT_SUPPORT
49 : : # ifndef O_DIRECT
50 : : # error O_DIRECT support configured but O_DIRECT definition not found in headers
51 : : # endif
52 : : #endif
53 : :
54 : : static DM_LIST_INIT(_open_devices);
55 : :
56 : : /*-----------------------------------------------------------------
57 : : * The standard io loop that keeps submitting an io until it's
58 : : * all gone.
59 : : *---------------------------------------------------------------*/
60 : 0 : static int _io(struct device_area *where, void *buffer, int should_write)
61 : : {
62 : 0 : int fd = dev_fd(where->dev);
63 : 0 : ssize_t n = 0;
64 : 0 : size_t total = 0;
65 : :
66 [ # # ]: 0 : if (fd < 0) {
67 : 0 : log_error("Attempt to read an unopened device (%s).",
68 : : dev_name(where->dev));
69 : 0 : return 0;
70 : : }
71 : :
72 : : /*
73 : : * Skip all writes in test mode.
74 : : */
75 [ # # ][ # # ]: 0 : if (should_write && test_mode())
76 : 0 : return 1;
77 : :
78 [ # # ]: 0 : if (where->size > SSIZE_MAX) {
79 : 0 : log_error("Read size too large: %" PRIu64, where->size);
80 : 0 : return 0;
81 : : }
82 : :
83 [ # # ]: 0 : if (lseek(fd, (off_t) where->start, SEEK_SET) < 0) {
84 : 0 : log_error("%s: lseek %" PRIu64 " failed: %s",
85 : : dev_name(where->dev), (uint64_t) where->start,
86 : : strerror(errno));
87 : 0 : return 0;
88 : : }
89 : :
90 [ # # ]: 0 : while (total < (size_t) where->size) {
91 : : do
92 [ # # ]: 0 : n = should_write ?
93 : 0 : write(fd, buffer, (size_t) where->size - total) :
94 : 0 : read(fd, buffer, (size_t) where->size - total);
95 [ # # ][ # # ]: 0 : while ((n < 0) && ((errno == EINTR) || (errno == EAGAIN)));
[ # # ]
96 : :
97 [ # # ]: 0 : if (n < 0)
98 [ # # ]: 0 : log_error("%s: %s failed after %" PRIu64 " of %" PRIu64
99 : : " at %" PRIu64 ": %s", dev_name(where->dev),
100 : : should_write ? "write" : "read",
101 : : (uint64_t) total,
102 : : (uint64_t) where->size,
103 : : (uint64_t) where->start, strerror(errno));
104 : :
105 [ # # ]: 0 : if (n <= 0)
106 : 0 : break;
107 : :
108 : 0 : total += n;
109 : 0 : buffer += n;
110 : : }
111 : :
112 : 0 : return (total == (size_t) where->size);
113 : : }
114 : :
115 : : /*-----------------------------------------------------------------
116 : : * LVM2 uses O_DIRECT when performing metadata io, which requires
117 : : * block size aligned accesses. If any io is not aligned we have
118 : : * to perform the io via a bounce buffer, obviously this is quite
119 : : * inefficient.
120 : : *---------------------------------------------------------------*/
121 : :
122 : : /*
123 : : * Get the sector size from an _open_ device.
124 : : */
125 : 0 : static int _get_block_size(struct device *dev, unsigned int *size)
126 : : {
127 : 0 : const char *name = dev_name(dev);
128 : :
129 [ # # ]: 0 : if ((dev->block_size == -1)) {
130 [ # # ]: 0 : if (ioctl(dev_fd(dev), BLKBSZGET, &dev->block_size) < 0) {
131 : 0 : log_sys_error("ioctl BLKBSZGET", name);
132 : 0 : return 0;
133 : : }
134 : 0 : log_debug("%s: block size is %u bytes", name, dev->block_size);
135 : : }
136 : :
137 : 0 : *size = (unsigned int) dev->block_size;
138 : :
139 : 0 : return 1;
140 : : }
141 : :
142 : : /*
143 : : * Widens a region to be an aligned region.
144 : : */
145 : 0 : static void _widen_region(unsigned int block_size, struct device_area *region,
146 : : struct device_area *result)
147 : : {
148 : 0 : uint64_t mask = block_size - 1, delta;
149 : 0 : memcpy(result, region, sizeof(*result));
150 : :
151 : : /* adjust the start */
152 : 0 : delta = result->start & mask;
153 [ # # ]: 0 : if (delta) {
154 : 0 : result->start -= delta;
155 : 0 : result->size += delta;
156 : : }
157 : :
158 : : /* adjust the end */
159 : 0 : delta = (result->start + result->size) & mask;
160 [ # # ]: 0 : if (delta)
161 : 0 : result->size += block_size - delta;
162 : 0 : }
163 : :
164 : 0 : static int _aligned_io(struct device_area *where, void *buffer,
165 : : int should_write)
166 : : {
167 : : void *bounce;
168 : 0 : unsigned int block_size = 0;
169 : : uintptr_t mask;
170 : : struct device_area widened;
171 : :
172 [ # # # # ]: 0 : if (!(where->dev->flags & DEV_REGULAR) &&
173 : 0 : !_get_block_size(where->dev, &block_size))
174 : 0 : return_0;
175 : :
176 [ # # ]: 0 : if (!block_size)
177 : 0 : block_size = lvm_getpagesize();
178 : :
179 : 0 : _widen_region(block_size, where, &widened);
180 : :
181 : : /* Do we need to use a bounce buffer? */
182 : 0 : mask = block_size - 1;
183 [ # # # # ]: 0 : if (!memcmp(where, &widened, sizeof(widened)) &&
184 : 0 : !((uintptr_t) buffer & mask))
185 : 0 : return _io(where, buffer, should_write);
186 : :
187 : : /* Allocate a bounce buffer with an extra block */
188 : 0 : if (!(bounce = alloca((size_t) widened.size + block_size))) {
189 : : log_error("Bounce buffer alloca failed");
190 : : return 0;
191 : : }
192 : :
193 : : /*
194 : : * Realign start of bounce buffer (using the extra sector)
195 : : */
196 [ # # ]: 0 : if (((uintptr_t) bounce) & mask)
197 : 0 : bounce = (void *) ((((uintptr_t) bounce) + mask) & ~mask);
198 : :
199 : : /* channel the io through the bounce buffer */
200 [ # # ]: 0 : if (!_io(&widened, bounce, 0)) {
201 [ # # ]: 0 : if (!should_write)
202 : 0 : return_0;
203 : : /* FIXME pre-extend the file */
204 : 0 : memset(bounce, '\n', widened.size);
205 : : }
206 : :
207 [ # # ]: 0 : if (should_write) {
208 : 0 : memcpy(bounce + (where->start - widened.start), buffer,
209 : : (size_t) where->size);
210 : :
211 : : /* ... then we write */
212 : 0 : return _io(&widened, bounce, 1);
213 : : }
214 : :
215 : 0 : memcpy(buffer, bounce + (where->start - widened.start),
216 : : (size_t) where->size);
217 : :
218 : 0 : return 1;
219 : : }
220 : :
221 : 0 : static int _dev_get_size_file(const struct device *dev, uint64_t *size)
222 : : {
223 : 0 : const char *name = dev_name(dev);
224 : : struct stat info;
225 : :
226 [ # # ]: 0 : if (stat(name, &info)) {
227 : 0 : log_sys_error("stat", name);
228 : 0 : return 0;
229 : : }
230 : :
231 : 0 : *size = info.st_size;
232 : 0 : *size >>= SECTOR_SHIFT; /* Convert to sectors */
233 : :
234 : 0 : log_very_verbose("%s: size is %" PRIu64 " sectors", name, *size);
235 : :
236 : 0 : return 1;
237 : : }
238 : :
239 : 0 : static int _dev_get_size_dev(const struct device *dev, uint64_t *size)
240 : : {
241 : : int fd;
242 : 0 : const char *name = dev_name(dev);
243 : :
244 [ # # ]: 0 : if ((fd = open(name, O_RDONLY)) < 0) {
245 : 0 : log_sys_error("open", name);
246 : 0 : return 0;
247 : : }
248 : :
249 [ # # ]: 0 : if (ioctl(fd, BLKGETSIZE64, size) < 0) {
250 : 0 : log_sys_error("ioctl BLKGETSIZE64", name);
251 [ # # ]: 0 : if (close(fd))
252 : 0 : log_sys_error("close", name);
253 : 0 : return 0;
254 : : }
255 : :
256 : 0 : *size >>= BLKSIZE_SHIFT; /* Convert to sectors */
257 [ # # ]: 0 : if (close(fd))
258 : 0 : log_sys_error("close", name);
259 : :
260 : 0 : log_very_verbose("%s: size is %" PRIu64 " sectors", name, *size);
261 : :
262 : 0 : return 1;
263 : : }
264 : :
265 : 0 : static int _dev_read_ahead_dev(struct device *dev, uint32_t *read_ahead)
266 : : {
267 : : long read_ahead_long;
268 : :
269 [ # # ]: 0 : if (dev->read_ahead != -1) {
270 : 0 : *read_ahead = (uint32_t) dev->read_ahead;
271 : 0 : return 1;
272 : : }
273 : :
274 [ # # ]: 0 : if (!dev_open(dev))
275 : 0 : return_0;
276 : :
277 [ # # ]: 0 : if (ioctl(dev->fd, BLKRAGET, &read_ahead_long) < 0) {
278 : 0 : log_sys_error("ioctl BLKRAGET", dev_name(dev));
279 [ # # ]: 0 : if (!dev_close(dev))
280 : 0 : stack;
281 : 0 : return 0;
282 : : }
283 : :
284 [ # # ]: 0 : if (!dev_close(dev))
285 : 0 : stack;
286 : :
287 : 0 : *read_ahead = (uint32_t) read_ahead_long;
288 : 0 : dev->read_ahead = read_ahead_long;
289 : :
290 : 0 : log_very_verbose("%s: read_ahead is %u sectors",
291 : : dev_name(dev), *read_ahead);
292 : :
293 : 0 : return 1;
294 : : }
295 : :
296 : : /*-----------------------------------------------------------------
297 : : * Public functions
298 : : *---------------------------------------------------------------*/
299 : :
300 : 0 : int dev_get_size(const struct device *dev, uint64_t *size)
301 : : {
302 [ # # ]: 0 : if (!dev)
303 : 0 : return 0;
304 : :
305 [ # # ]: 0 : if ((dev->flags & DEV_REGULAR))
306 : 0 : return _dev_get_size_file(dev, size);
307 : : else
308 : 0 : return _dev_get_size_dev(dev, size);
309 : : }
310 : :
311 : 0 : int dev_get_read_ahead(struct device *dev, uint32_t *read_ahead)
312 : : {
313 [ # # ]: 0 : if (!dev)
314 : 0 : return 0;
315 : :
316 [ # # ]: 0 : if (dev->flags & DEV_REGULAR) {
317 : 0 : *read_ahead = 0;
318 : 0 : return 1;
319 : : }
320 : :
321 : 0 : return _dev_read_ahead_dev(dev, read_ahead);
322 : : }
323 : :
324 : : /* FIXME Unused
325 : : int dev_get_sectsize(struct device *dev, uint32_t *size)
326 : : {
327 : : int fd;
328 : : int s;
329 : : const char *name = dev_name(dev);
330 : :
331 : : if ((fd = open(name, O_RDONLY)) < 0) {
332 : : log_sys_error("open", name);
333 : : return 0;
334 : : }
335 : :
336 : : if (ioctl(fd, BLKSSZGET, &s) < 0) {
337 : : log_sys_error("ioctl BLKSSZGET", name);
338 : : if (close(fd))
339 : : log_sys_error("close", name);
340 : : return 0;
341 : : }
342 : :
343 : : if (close(fd))
344 : : log_sys_error("close", name);
345 : :
346 : : *size = (uint32_t) s;
347 : :
348 : : log_very_verbose("%s: sector size is %" PRIu32 " bytes", name, *size);
349 : :
350 : : return 1;
351 : : }
352 : : */
353 : :
354 : 0 : void dev_flush(struct device *dev)
355 : : {
356 [ # # ][ # # ]: 0 : if (!(dev->flags & DEV_REGULAR) && ioctl(dev->fd, BLKFLSBUF, 0) >= 0)
357 : 0 : return;
358 : :
359 [ # # ]: 0 : if (fsync(dev->fd) >= 0)
360 : 0 : return;
361 : :
362 : 0 : sync();
363 : : }
364 : :
365 : 4 : int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
366 : : {
367 : : struct stat buf;
368 : : const char *name;
369 : 4 : int need_excl = 0, need_rw = 0;
370 : :
371 [ - + ]: 4 : if ((flags & O_ACCMODE) == O_RDWR)
372 : 0 : need_rw = 1;
373 : :
374 [ - + ]: 4 : if ((flags & O_EXCL))
375 : 0 : need_excl = 1;
376 : :
377 [ - + ]: 4 : if (dev->fd >= 0) {
378 [ # # ][ # # ]: 0 : if (((dev->flags & DEV_OPENED_RW) || !need_rw) &&
[ # # ][ # # ]
379 : 0 : ((dev->flags & DEV_OPENED_EXCL) || !need_excl)) {
380 : 0 : dev->open_count++;
381 : 0 : return 1;
382 : : }
383 : :
384 [ # # ][ # # ]: 0 : if (dev->open_count && !need_excl) {
385 : : /* FIXME Ensure we never get here */
386 : 0 : log_error(INTERNAL_ERROR "%s already opened read-only",
387 : : dev_name(dev));
388 : 0 : dev->open_count++;
389 : : }
390 : :
391 : 0 : dev_close_immediate(dev);
392 : : }
393 : :
394 [ - + ]: 4 : if (memlock())
395 : : /* FIXME Make this log_error */
396 : 0 : log_verbose("dev_open(%s) called while suspended",
397 : : dev_name(dev));
398 : :
399 [ + - ]: 4 : if (dev->flags & DEV_REGULAR)
400 : 4 : name = dev_name(dev);
401 [ # # ]: 0 : else if (!(name = dev_name_confirmed(dev, quiet)))
402 : 0 : return_0;
403 : :
404 [ - + ]: 4 : if (!(dev->flags & DEV_REGULAR)) {
405 [ # # ]: 0 : if (stat(name, &buf) < 0) {
406 : 0 : log_sys_error("%s: stat failed", name);
407 : 0 : return 0;
408 : : }
409 [ # # ]: 0 : if (buf.st_rdev != dev->dev) {
410 : 0 : log_error("%s: device changed", name);
411 : 0 : return 0;
412 : : }
413 : : }
414 : :
415 : : #ifdef O_DIRECT_SUPPORT
416 [ - + ]: 4 : if (direct) {
417 [ # # ]: 0 : if (!(dev->flags & DEV_O_DIRECT_TESTED))
418 : 0 : dev->flags |= DEV_O_DIRECT;
419 : :
420 [ # # ]: 0 : if ((dev->flags & DEV_O_DIRECT))
421 : 0 : flags |= O_DIRECT;
422 : : }
423 : : #endif
424 : :
425 : : #ifdef O_NOATIME
426 : : /* Don't update atime on device inodes */
427 [ - + ]: 4 : if (!(dev->flags & DEV_REGULAR))
428 : 0 : flags |= O_NOATIME;
429 : : #endif
430 : :
431 [ - + ]: 4 : if ((dev->fd = open(name, flags, 0777)) < 0) {
432 : : #ifdef O_DIRECT_SUPPORT
433 [ # # ][ # # ]: 0 : if (direct && !(dev->flags & DEV_O_DIRECT_TESTED)) {
434 : 0 : flags &= ~O_DIRECT;
435 [ # # ]: 0 : if ((dev->fd = open(name, flags, 0777)) >= 0) {
436 : 0 : dev->flags &= ~DEV_O_DIRECT;
437 : 0 : log_debug("%s: Not using O_DIRECT", name);
438 : 0 : goto opened;
439 : : }
440 : : }
441 : : #endif
442 [ # # ]: 0 : if (quiet)
443 : 0 : log_sys_debug("open", name);
444 : : else
445 : 0 : log_sys_error("open", name);
446 : 0 : return 0;
447 : : }
448 : :
449 : : #ifdef O_DIRECT_SUPPORT
450 : : opened:
451 [ - + ]: 4 : if (direct)
452 : 0 : dev->flags |= DEV_O_DIRECT_TESTED;
453 : : #endif
454 : 4 : dev->open_count++;
455 : 4 : dev->flags &= ~DEV_ACCESSED_W;
456 : :
457 [ - + ]: 4 : if (need_rw)
458 : 0 : dev->flags |= DEV_OPENED_RW;
459 : : else
460 : 4 : dev->flags &= ~DEV_OPENED_RW;
461 : :
462 [ - + ]: 4 : if (need_excl)
463 : 0 : dev->flags |= DEV_OPENED_EXCL;
464 : : else
465 : 4 : dev->flags &= ~DEV_OPENED_EXCL;
466 : :
467 [ - + # # ]: 4 : if (!(dev->flags & DEV_REGULAR) &&
[ # # ]
468 : 0 : ((fstat(dev->fd, &buf) < 0) || (buf.st_rdev != dev->dev))) {
469 : 0 : log_error("%s: fstat failed: Has device name changed?", name);
470 : 0 : dev_close_immediate(dev);
471 : 0 : return 0;
472 : : }
473 : :
474 : : #ifndef O_DIRECT_SUPPORT
475 : : if (!(dev->flags & DEV_REGULAR))
476 : : dev_flush(dev);
477 : : #endif
478 : :
479 [ - + ][ # # ]: 4 : if ((flags & O_CREAT) && !(flags & O_TRUNC))
480 : 0 : dev->end = lseek(dev->fd, (off_t) 0, SEEK_END);
481 : :
482 : 4 : dm_list_add(&_open_devices, &dev->open_list);
483 : :
484 [ - + ][ - + ]: 4 : log_debug("Opened %s %s%s%s", dev_name(dev),
[ - + ]
485 : : dev->flags & DEV_OPENED_RW ? "RW" : "RO",
486 : : dev->flags & DEV_OPENED_EXCL ? " O_EXCL" : "",
487 : : dev->flags & DEV_O_DIRECT ? " O_DIRECT" : "");
488 : :
489 : 4 : return 1;
490 : : }
491 : :
492 : 0 : int dev_open_quiet(struct device *dev)
493 : : {
494 : : int flags;
495 : :
496 [ # # ]: 0 : flags = vg_write_lock_held() ? O_RDWR : O_RDONLY;
497 : :
498 : 0 : return dev_open_flags(dev, flags, 1, 1);
499 : : }
500 : :
501 : 0 : int dev_open(struct device *dev)
502 : : {
503 : : int flags;
504 : :
505 [ # # ]: 0 : flags = vg_write_lock_held() ? O_RDWR : O_RDONLY;
506 : :
507 : 0 : return dev_open_flags(dev, flags, 1, 0);
508 : : }
509 : :
510 : 0 : int dev_test_excl(struct device *dev)
511 : : {
512 : : int flags;
513 : : int r;
514 : :
515 [ # # ]: 0 : flags = vg_write_lock_held() ? O_RDWR : O_RDONLY;
516 : 0 : flags |= O_EXCL;
517 : :
518 : 0 : r = dev_open_flags(dev, flags, 1, 1);
519 [ # # ]: 0 : if (r)
520 : 0 : dev_close_immediate(dev);
521 : :
522 : 0 : return r;
523 : : }
524 : :
525 : 4 : static void _close(struct device *dev)
526 : : {
527 [ - + ]: 4 : if (close(dev->fd))
528 : 0 : log_sys_error("close", dev_name(dev));
529 : 4 : dev->fd = -1;
530 : 4 : dev->block_size = -1;
531 : 4 : dm_list_del(&dev->open_list);
532 : :
533 : 4 : log_debug("Closed %s", dev_name(dev));
534 : :
535 [ + - ]: 4 : if (dev->flags & DEV_ALLOCED) {
536 : 4 : dm_free((void *) dm_list_item(dev->aliases.n, struct str_list)->
537 : : str);
538 : 4 : dm_free(dev->aliases.n);
539 : 4 : dm_free(dev);
540 : : }
541 : 4 : }
542 : :
543 : 4 : static int _dev_close(struct device *dev, int immediate)
544 : : {
545 : : struct lvmcache_info *info;
546 : :
547 [ - + ]: 4 : if (dev->fd < 0) {
548 : 0 : log_error("Attempt to close device '%s' "
549 : : "which is not open.", dev_name(dev));
550 : 0 : return 0;
551 : : }
552 : :
553 : : #ifndef O_DIRECT_SUPPORT
554 : : if (dev->flags & DEV_ACCESSED_W)
555 : : dev_flush(dev);
556 : : #endif
557 : :
558 [ + - ]: 4 : if (dev->open_count > 0)
559 : 4 : dev->open_count--;
560 : :
561 [ - + ][ # # ]: 4 : if (immediate && dev->open_count)
562 : 0 : log_debug("%s: Immediate close attempt while still referenced",
563 : : dev_name(dev));
564 : :
565 : : /* Close unless device is known to belong to a locked VG */
566 [ + - ]: 8 : if (immediate ||
[ + - - + ]
[ # # # # ]
567 : 4 : (dev->open_count < 1 &&
568 : 4 : (!(info = info_from_pvid(dev->pvid, 0)) ||
569 : 0 : !info->vginfo ||
570 : 0 : !vgname_is_locked(info->vginfo->vgname))))
571 : 4 : _close(dev);
572 : :
573 : 4 : return 1;
574 : : }
575 : :
576 : 4 : int dev_close(struct device *dev)
577 : : {
578 : 4 : return _dev_close(dev, 0);
579 : : }
580 : :
581 : 0 : int dev_close_immediate(struct device *dev)
582 : : {
583 : 0 : return _dev_close(dev, 1);
584 : : }
585 : :
586 : 0 : void dev_close_all(void)
587 : : {
588 : : struct dm_list *doh, *doht;
589 : : struct device *dev;
590 : :
591 [ # # ]: 0 : dm_list_iterate_safe(doh, doht, &_open_devices) {
592 : 0 : dev = dm_list_struct_base(doh, struct device, open_list);
593 [ # # ]: 0 : if (dev->open_count < 1)
594 : 0 : _close(dev);
595 : : }
596 : 0 : }
597 : :
598 : 0 : int dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer)
599 : : {
600 : : struct device_area where;
601 : :
602 [ # # ]: 0 : if (!dev->open_count)
603 : 0 : return_0;
604 : :
605 : 0 : where.dev = dev;
606 : 0 : where.start = offset;
607 : 0 : where.size = len;
608 : :
609 : 0 : return _aligned_io(&where, buffer, 0);
610 : : }
611 : :
612 : : /*
613 : : * Read from 'dev' into 'buf', possibly in 2 distinct regions, denoted
614 : : * by (offset,len) and (offset2,len2). Thus, the total size of
615 : : * 'buf' should be len+len2.
616 : : */
617 : 0 : int dev_read_circular(struct device *dev, uint64_t offset, size_t len,
618 : : uint64_t offset2, size_t len2, void *buf)
619 : : {
620 [ # # ]: 0 : if (!dev_read(dev, offset, len, buf)) {
621 : 0 : log_error("Read from %s failed", dev_name(dev));
622 : 0 : return 0;
623 : : }
624 : :
625 : : /*
626 : : * The second region is optional, and allows for
627 : : * a circular buffer on the device.
628 : : */
629 [ # # ]: 0 : if (!len2)
630 : 0 : return 1;
631 : :
632 [ # # ]: 0 : if (!dev_read(dev, offset2, len2, buf + len)) {
633 : 0 : log_error("Circular read from %s failed",
634 : : dev_name(dev));
635 : 0 : return 0;
636 : : }
637 : :
638 : 0 : return 1;
639 : : }
640 : :
641 : : /* FIXME If O_DIRECT can't extend file, dev_extend first; dev_truncate after.
642 : : * But fails if concurrent processes writing
643 : : */
644 : :
645 : : /* FIXME pre-extend the file */
646 : 0 : int dev_append(struct device *dev, size_t len, void *buffer)
647 : : {
648 : : int r;
649 : :
650 [ # # ]: 0 : if (!dev->open_count)
651 : 0 : return_0;
652 : :
653 : 0 : r = dev_write(dev, dev->end, len, buffer);
654 : 0 : dev->end += (uint64_t) len;
655 : :
656 : : #ifndef O_DIRECT_SUPPORT
657 : : dev_flush(dev);
658 : : #endif
659 : 0 : return r;
660 : : }
661 : :
662 : 0 : int dev_write(struct device *dev, uint64_t offset, size_t len, void *buffer)
663 : : {
664 : : struct device_area where;
665 : :
666 [ # # ]: 0 : if (!dev->open_count)
667 : 0 : return_0;
668 : :
669 : 0 : where.dev = dev;
670 : 0 : where.start = offset;
671 : 0 : where.size = len;
672 : :
673 : 0 : dev->flags |= DEV_ACCESSED_W;
674 : :
675 : 0 : return _aligned_io(&where, buffer, 1);
676 : : }
677 : :
678 : 0 : int dev_set(struct device *dev, uint64_t offset, size_t len, int value)
679 : : {
680 : : size_t s;
681 : : char buffer[4096] __attribute((aligned(8)));
682 : :
683 [ # # ]: 0 : if (!dev_open(dev))
684 : 0 : return_0;
685 : :
686 [ # # ][ # # ]: 0 : if ((offset % SECTOR_SIZE) || (len % SECTOR_SIZE))
687 : 0 : log_debug("Wiping %s at %" PRIu64 " length %" PRIsize_t,
688 : : dev_name(dev), offset, len);
689 : : else
690 : 0 : log_debug("Wiping %s at sector %" PRIu64 " length %" PRIsize_t
691 : : " sectors", dev_name(dev), offset >> SECTOR_SHIFT,
692 : : len >> SECTOR_SHIFT);
693 : :
694 : 0 : memset(buffer, value, sizeof(buffer));
695 : : while (1) {
696 : 0 : s = len > sizeof(buffer) ? sizeof(buffer) : len;
697 [ # # ]: 0 : if (!dev_write(dev, offset, s, buffer))
698 : 0 : break;
699 : :
700 : 0 : len -= s;
701 [ # # ]: 0 : if (!len)
702 : 0 : break;
703 : :
704 : 0 : offset += s;
705 : 0 : }
706 : :
707 : 0 : dev->flags |= DEV_ACCESSED_W;
708 : :
709 [ # # ]: 0 : if (!dev_close(dev))
710 : 0 : stack;
711 : :
712 : 0 : return (len == 0);
713 : : }
|