Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 54 additions & 3 deletions fiemap.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,24 @@ static unsigned int fiemap_count_extents(int fd)
return fiemap.fm_mapped_extents;
}

static unsigned int fiemap_count_extents_range(int fd, uint64_t start,
uint64_t length)
{
struct fiemap fiemap = {0,};
int err;

fiemap.fm_start = start;
fiemap.fm_length = length;

err = ioctl(fd, FS_IOC_FIEMAP, &fiemap);
if (err < 0) {
perror("fiemap_count_extents_range");
return 0;
}

return fiemap.fm_mapped_extents;
}

struct fiemap_extent *get_extent(struct fiemap *fiemap, size_t loff,
unsigned int *index)
{
Expand Down Expand Up @@ -98,6 +116,37 @@ struct fiemap *do_fiemap(int fd)
return fiemap;
}

struct fiemap *do_fiemap_range(int fd, uint64_t start, uint64_t length)
{
int err;
struct fiemap *fiemap = NULL;
unsigned int count = fiemap_count_extents_range(fd, start, length);

if (count == 0)
return NULL;

fiemap = calloc(1, sizeof(struct fiemap) +
count * sizeof(struct fiemap_extent));
if (!fiemap)
return NULL;

fiemap->fm_start = start;
fiemap->fm_length = length;
fiemap->fm_extent_count = count;

err = ioctl(fd, FS_IOC_FIEMAP, fiemap);
if (err < 0) {
perror("do_fiemap_range");
free(fiemap);
return NULL;
}

if (fiemap->fm_mapped_extents != count)
dprintf("do_fiemap_range: file changed between fiemap calls\n");

return fiemap;
}

int fiemap_count_shared(int fd, size_t start_off, size_t end_off, uint64_t *shared)
{
_cleanup_(freep) struct fiemap *fiemap = NULL;
Expand All @@ -108,9 +157,11 @@ int fiemap_count_shared(int fd, size_t start_off, size_t end_off, uint64_t *shar

abort_on(start_off >= end_off);

fiemap = do_fiemap(fd);
if (!fiemap)
return 1;
fiemap = do_fiemap_range(fd, start_off, end_off - start_off);
if (!fiemap) {
*shared = 0;
return 0;
}

*shared = 0;

Expand Down
6 changes: 6 additions & 0 deletions fiemap.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ struct fiemap_extent *get_extent(struct fiemap *fiemap, size_t loff,
*/
struct fiemap *do_fiemap(int fd);

/*
* Extract extents mapping for a specific byte range.
* Only returns extents overlapping [start, start+length).
*/
struct fiemap *do_fiemap_range(int fd, uint64_t start, uint64_t length);

/*
* Count how much of the area between start_off and end_off is shared.
*/
Expand Down
14 changes: 4 additions & 10 deletions filerec.c
Original file line number Diff line number Diff line change
Expand Up @@ -316,25 +316,19 @@ int fiemap_scan_extent(struct extent *extent)
{
int ret = 0;
_cleanup_(freep) struct fiemap *fiemap = NULL;
struct fiemap_extent *result;

ret = filerec_open(extent->e_file, true);
if (ret)
return ret;

fiemap = do_fiemap(extent->e_file->fd);
if (!fiemap) {
fiemap = do_fiemap_range(extent->e_file->fd, extent->e_loff,
extent_len(extent));
if (!fiemap || fiemap->fm_mapped_extents == 0) {
filerec_close(extent->e_file);
return -1;
}

result = get_extent(fiemap, extent->e_loff, NULL);
if (!result) {
filerec_close(extent->e_file);
return -1;
}

extent->e_poff = result->fe_physical;
extent->e_poff = fiemap->fm_extents[0].fe_physical;
filerec_close(extent->e_file);
return ret;
}
3 changes: 0 additions & 3 deletions run_dedupe.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,6 @@ static void add_shared_extents(struct dupe_extents *dext, uint64_t *shared)

/*
* Fiemap the file and get our post-dedupe extent state.
*
* XXX: We're running fiemap too much for this. At the least we should
* shoot for one fiemap call(s) per filerec.
*/
static void add_shared_extents_post(struct dupe_extents *dext, uint64_t *shared)
{
Expand Down