Revision 5500316d

b/block/raw-posix.c
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,
b/block/raw.c
25 25
{
26 26
}
27 27

  
28
static int coroutine_fn raw_co_is_allocated(BlockDriverState *bs,
29
                                            int64_t sector_num,
30
                                            int nb_sectors, int *pnum)
31
{
32
    return bdrv_co_is_allocated(bs->file, sector_num, nb_sectors, pnum);
33
}
34

  
28 35
static int64_t raw_getlength(BlockDriverState *bs)
29 36
{
30 37
    return bdrv_getlength(bs->file);
......
108 115

  
109 116
    .bdrv_co_readv          = raw_co_readv,
110 117
    .bdrv_co_writev         = raw_co_writev,
118
    .bdrv_co_is_allocated   = raw_co_is_allocated,
111 119
    .bdrv_co_discard        = raw_co_discard,
112 120

  
113 121
    .bdrv_probe         = raw_probe,

Also available in: Unified diff