52 |
52 |
#include <sys/param.h>
|
53 |
53 |
#include <linux/cdrom.h>
|
54 |
54 |
#include <linux/fd.h>
|
|
55 |
#include <linux/fs.h>
|
|
56 |
#endif
|
|
57 |
#ifdef CONFIG_FIEMAP
|
|
58 |
#include <linux/fiemap.h>
|
55 |
59 |
#endif
|
56 |
60 |
#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
|
57 |
61 |
#include <sys/disk.h>
|
... | ... | |
583 |
587 |
return result;
|
584 |
588 |
}
|
585 |
589 |
|
|
590 |
/*
|
|
591 |
* Returns true iff the specified sector is present in the disk image. Drivers
|
|
592 |
* not implementing the functionality are assumed to not support backing files,
|
|
593 |
* hence all their sectors are reported as allocated.
|
|
594 |
*
|
|
595 |
* If 'sector_num' is beyond the end of the disk image the return value is 0
|
|
596 |
* and 'pnum' is set to 0.
|
|
597 |
*
|
|
598 |
* 'pnum' is set to the number of sectors (including and immediately following
|
|
599 |
* the specified sector) that are known to be in the same
|
|
600 |
* allocated/unallocated state.
|
|
601 |
*
|
|
602 |
* 'nb_sectors' is the max value 'pnum' should be set to. If nb_sectors goes
|
|
603 |
* beyond the end of the disk image it will be clamped.
|
|
604 |
*/
|
|
605 |
static int coroutine_fn raw_co_is_allocated(BlockDriverState *bs,
|
|
606 |
int64_t sector_num,
|
|
607 |
int nb_sectors, int *pnum)
|
|
608 |
{
|
|
609 |
BDRVRawState *s = bs->opaque;
|
|
610 |
off_t start, data, hole;
|
|
611 |
int ret;
|
|
612 |
|
|
613 |
ret = fd_open(bs);
|
|
614 |
if (ret < 0) {
|
|
615 |
return ret;
|
|
616 |
}
|
|
617 |
|
|
618 |
start = sector_num * BDRV_SECTOR_SIZE;
|
|
619 |
#ifdef CONFIG_FIEMAP
|
|
620 |
struct {
|
|
621 |
struct fiemap fm;
|
|
622 |
struct fiemap_extent fe;
|
|
623 |
} f;
|
|
624 |
f.fm.fm_start = start;
|
|
625 |
f.fm.fm_length = (int64_t)nb_sectors * BDRV_SECTOR_SIZE;
|
|
626 |
f.fm.fm_flags = 0;
|
|
627 |
f.fm.fm_extent_count = 1;
|
|
628 |
f.fm.fm_reserved = 0;
|
|
629 |
if (ioctl(s->fd, FS_IOC_FIEMAP, &f) == -1) {
|
|
630 |
/* Assume everything is allocated. */
|
|
631 |
*pnum = nb_sectors;
|
|
632 |
return 1;
|
|
633 |
}
|
|
634 |
|
|
635 |
if (f.fm.fm_mapped_extents == 0) {
|
|
636 |
/* No extents found, data is beyond f.fm.fm_start + f.fm.fm_length.
|
|
637 |
* f.fm.fm_start + f.fm.fm_length must be clamped to the file size!
|
|
638 |
*/
|
|
639 |
off_t length = lseek(s->fd, 0, SEEK_END);
|
|
640 |
hole = f.fm.fm_start;
|
|
641 |
data = MIN(f.fm.fm_start + f.fm.fm_length, length);
|
|
642 |
} else {
|
|
643 |
data = f.fe.fe_logical;
|
|
644 |
hole = f.fe.fe_logical + f.fe.fe_length;
|
|
645 |
}
|
|
646 |
#elif defined SEEK_HOLE && defined SEEK_DATA
|
|
647 |
hole = lseek(s->fd, start, SEEK_HOLE);
|
|
648 |
if (hole == -1) {
|
|
649 |
/* -ENXIO indicates that sector_num was past the end of the file.
|
|
650 |
* There is a virtual hole there. */
|
|
651 |
assert(errno != -ENXIO);
|
|
652 |
|
|
653 |
/* Most likely EINVAL. Assume everything is allocated. */
|
|
654 |
*pnum = nb_sectors;
|
|
655 |
return 1;
|
|
656 |
}
|
|
657 |
|
|
658 |
if (hole > start) {
|
|
659 |
data = start;
|
|
660 |
} else {
|
|
661 |
/* On a hole. We need another syscall to find its end. */
|
|
662 |
data = lseek(s->fd, start, SEEK_DATA);
|
|
663 |
if (data == -1) {
|
|
664 |
data = lseek(s->fd, 0, SEEK_END);
|
|
665 |
}
|
|
666 |
}
|
|
667 |
#else
|
|
668 |
*pnum = nb_sectors;
|
|
669 |
return 1;
|
|
670 |
#endif
|
|
671 |
|
|
672 |
if (data <= start) {
|
|
673 |
/* On a data extent, compute sectors to the end of the extent. */
|
|
674 |
*pnum = MIN(nb_sectors, (hole - start) / BDRV_SECTOR_SIZE);
|
|
675 |
return 1;
|
|
676 |
} else {
|
|
677 |
/* On a hole, compute sectors to the beginning of the next extent. */
|
|
678 |
*pnum = MIN(nb_sectors, (data - start) / BDRV_SECTOR_SIZE);
|
|
679 |
return 0;
|
|
680 |
}
|
|
681 |
}
|
|
682 |
|
586 |
683 |
#ifdef CONFIG_XFS
|
587 |
684 |
static int xfs_discard(BDRVRawState *s, int64_t sector_num, int nb_sectors)
|
588 |
685 |
{
|
... | ... | |
634 |
731 |
.bdrv_close = raw_close,
|
635 |
732 |
.bdrv_create = raw_create,
|
636 |
733 |
.bdrv_co_discard = raw_co_discard,
|
|
734 |
.bdrv_co_is_allocated = raw_co_is_allocated,
|
637 |
735 |
|
638 |
736 |
.bdrv_aio_readv = raw_aio_readv,
|
639 |
737 |
.bdrv_aio_writev = raw_aio_writev,
|