Skip to content
Merged
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
32 changes: 32 additions & 0 deletions fiemap.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,38 @@ struct fiemap *do_fiemap_range(int fd, uint64_t start, uint64_t length)
return fiemap;
}

/*
* Physical offset of the first extent overlapping [start, start+length).
*
* The dedupe rescan only needs that one extent, so unlike do_fiemap_range()
* this issues a single ioctl (no separate count pass) into a one-extent buffer.
* Returns 0 and stores the offset in *poff on success, -1 on ioctl error or
* when the range maps no extents (a hole).
*/
int fiemap_first_extent_poff(int fd, uint64_t start, uint64_t length,
uint64_t *poff)
{
struct {
struct fiemap fiemap;
struct fiemap_extent extent;
} buf = {0,};

buf.fiemap.fm_start = start;
buf.fiemap.fm_length = length;
buf.fiemap.fm_extent_count = 1;

if (ioctl(fd, FS_IOC_FIEMAP, &buf.fiemap) < 0) {
perror("fiemap_first_extent_poff");
return -1;
}

if (buf.fiemap.fm_mapped_extents == 0)
return -1;

*poff = buf.fiemap.fm_extents[0].fe_physical;
return 0;
}

int fiemap_count_shared(int fd, size_t start_off, size_t end_off, uint64_t *shared)
{
_cleanup_(freep) struct fiemap *fiemap = NULL;
Expand Down
8 changes: 8 additions & 0 deletions fiemap.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ struct fiemap *do_fiemap(int fd);
*/
struct fiemap *do_fiemap_range(int fd, uint64_t start, uint64_t length);

/*
* Physical offset of the first extent overlapping [start, start+length), via a
* single fiemap ioctl. Returns 0 and sets *poff on success, -1 on error or when
* the range maps no extents.
*/
int fiemap_first_extent_poff(int fd, uint64_t start, uint64_t length,
uint64_t *poff);

/*
* Count how much of the area between start_off and end_off is shared.
*/
Expand Down
15 changes: 4 additions & 11 deletions filerec.c
Original file line number Diff line number Diff line change
Expand Up @@ -315,24 +315,17 @@ void filerec_close_open_list(struct open_once *open_files)
int fiemap_scan_extent(struct extent *extent)
{
int ret = 0;
_cleanup_(freep) struct fiemap *fiemap = NULL;

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

/*
* Only map the extent we care about. On a large/fragmented file,
* do_fiemap() would enumerate every extent just to fetch this one.
* We only need this one extent's physical offset. On a large/fragmented
* file, do_fiemap() would enumerate every extent just to fetch it.
*/
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;
}

extent->e_poff = fiemap->fm_extents[0].fe_physical;
ret = fiemap_first_extent_poff(extent->e_file->fd, extent->e_loff,
extent_len(extent), &extent->e_poff);
filerec_close(extent->e_file);
return ret;
}
Loading