extent_posix.cc (fstransform-0.9.3-src) | : | extent_posix.cc (fstransform-0.9.4) | ||
---|---|---|---|---|
skipping to change at line 74 | skipping to change at line 74 | |||
#include "extent_posix.hh" // for ff_read_extents_posix() */ | #include "extent_posix.hh" // for ff_read_extents_posix() */ | |||
#include "util_posix.hh" // for ff_posix_ioctl(), ff_posix_size() */ | #include "util_posix.hh" // for ff_posix_ioctl(), ff_posix_size() */ | |||
FT_IO_NAMESPACE_BEGIN | FT_IO_NAMESPACE_BEGIN | |||
/** | /** | |||
* retrieves file blocks allocation map (extents) for specified file descriptor | * retrieves file blocks allocation map (extents) for specified file descriptor | |||
* and appends them to ret_vector (with user_data = FC_DEFAULT_USER_DATA). | * and appends them to ret_vector (with user_data = FC_DEFAULT_USER_DATA). | |||
* in case of failure returns errno-compatible error code, and ret_vector conten ts will be UNDEFINED. | * in case of failure returns errno-compatible error code, and ret_vector conten ts will be UNDEFINED. | |||
* | * | |||
* must (and will) also check that device blocks count can be represented by ret | * must (and will) also check that device size can be represented by ret_list, | |||
_list, | ||||
* by calling ret_list.extent_set_range(block_size, block_count) | ||||
* | * | |||
* implementation: calls ioctl(FIBMAP) | * implementation: calls ioctl(FIBMAP) | |||
*/ | */ | |||
static int ff_posix_fibmap(int fd, ft_uoff dev_length, fr_vector<ft_uoff> & ret_ list, ft_uoff & ret_block_size_bitmask) | static int ff_posix_fibmap(int fd, ft_uoff dev_length, fr_vector<ft_uoff> & ret_ list, ft_uoff & ret_block_size_bitmask) | |||
{ | { | |||
#ifdef FIBMAP | #ifdef FIBMAP | |||
ft_uoff file_length, file_block_count, dev_block_count; | ft_uoff file_length, file_block_count, dev_block_count; | |||
ft_uoff block_size, logical_uoff, physical_uoff, block_size_bitmask = ret_bl | ft_uoff ioctl_n = 0, block_size = 0, logical_uoff, physical_uoff; | |||
ock_size_bitmask; | ||||
ft_size extent_n = ret_list.size(); | ||||
/* lower-level API ff_posix_ioctl(FIGETBSZ) and ff_posix_ioctl(FIBMAP) need these to be int */ | /* lower-level API ff_posix_ioctl(FIGETBSZ) and ff_posix_ioctl(FIBMAP) need these to be int */ | |||
int err = 0, block_size_int, logical, physical; | int err = 0, block_size_int, logical, physical; | |||
do { | do { | |||
if ((err = ff_posix_ioctl(fd, FIGETBSZ, & block_size_int))) { | if ((err = ff_posix_ioctl(fd, FIGETBSZ, & block_size_int))) { | |||
err = ff_log(FC_ERROR, err, "ff_posix_fibmap(): error in ioctl(%d, F IGETBSZ)", fd); | err = ff_log(FC_ERROR, err, "ff_posix_fibmap(): error in ioctl(%d, F IGETBSZ)", fd); | |||
break; | break; | |||
} | } | |||
block_size = (ft_uoff) block_size_int; | block_size = (ft_uoff) block_size_int; | |||
// ft_uoff is expected to be unsigned and wider than int, | // ft_uoff is expected to be wider than int, | |||
// but explicitly checking for overflow is always safer than "expecting" | // but explicitly checking for overflow is always safer than "expecting" | |||
if (block_size < 0 || block_size_int != (int) block_size) { | if ((int) block_size != block_size_int) { | |||
/* overflow! give up. */ | /* overflow! give up. */ | |||
err = ff_log(FC_ERROR, EFBIG, "ff_posix_fibmap(): error, block_size = %"FT_ULL" overflows type (ft_uoff)", (ft_ull) block_size_int); | err = ff_log(FC_ERROR, EFBIG, "ff_posix_fibmap(): error, block_size = %" FT_ULL " overflows type (ft_uoff)", (ft_ull) block_size_int); | |||
break; | break; | |||
} | } | |||
/* keep track of bits used by extents. needed to compute effective block | ||||
size */ | ||||
block_size_bitmask |= block_size; | ||||
if ((err = ff_posix_size(fd, & file_length))) { | if ((err = ff_posix_size(fd, & file_length))) { | |||
err = ff_log(FC_ERROR, err, "ff_posix_fibmap(): error in stat(%d)", fd); | err = ff_log(FC_ERROR, err, "ff_posix_fibmap(): error in stat(%d)", fd); | |||
break; | break; | |||
} | } | |||
// number of blocks in the device | // number of blocks in the device | |||
dev_block_count = (dev_length + block_size - 1) / block_size; | dev_block_count = (dev_length + block_size - 1) / block_size; | |||
// number of blocks in the file | // number of blocks in the file | |||
skipping to change at line 125 | skipping to change at line 124 | |||
// ioctl(FIBMAP) wants an (int logical) and returns an (int physical) | // ioctl(FIBMAP) wants an (int logical) and returns an (int physical) | |||
// in units of one block, so we must check for overflow! | // in units of one block, so we must check for overflow! | |||
int n = (int) file_block_count; | int n = (int) file_block_count; | |||
int m = (int) dev_block_count; | int m = (int) dev_block_count; | |||
if (m < 0 || dev_block_count != (ft_uoff) m | if (m < 0 || dev_block_count != (ft_uoff) m | |||
|| n < 0 || file_block_count != (ft_uoff) n) | || n < 0 || file_block_count != (ft_uoff) n) | |||
{ | { | |||
/* overflow! give up. */ | /* overflow! give up. */ | |||
err = ff_log(FC_ERROR, EFBIG, "ff_posix_fibmap(): error, dev_block_c | err = ff_log(FC_ERROR, EFBIG, "ff_posix_fibmap(): error, dev_block_c | |||
ount = %"FT_ULL", file_block_count = %"FT_ULL" overflow type (int)", | ount = %" FT_ULL ", file_block_count = %" FT_ULL " overflow type (int)", | |||
fd, (ft_ull) dev_block_count, (ft_ull) file_block_count | (ft_ull) dev_block_count, (ft_ull) file_block_count); | |||
); | ||||
break; | break; | |||
} | } | |||
for (logical = 0; logical < n; logical++) { | for (logical = 0; logical < n; logical++) { | |||
physical = logical; | physical = logical; | |||
ioctl_n++; | ||||
if ((err = ff_posix_ioctl(fd, FIBMAP, & physical))) { | if ((err = ff_posix_ioctl(fd, FIBMAP, & physical))) { | |||
err = ff_log(FC_ERROR, err, "ff_posix_fibmap(): error in ioctl(% d, FIBMAP, %"FT_ULL")", fd, (ft_ull) logical); | err = ff_log(FC_ERROR, err, "ff_posix_fibmap(): error in ioctl(% d, FIBMAP, %" FT_ULL ")", fd, (ft_ull) logical); | |||
break; | break; | |||
} | } | |||
/* FIBMAP reports holes (i.e. unallocated blocks in the file) as phy sical == 0. ugly */ | /* FIBMAP reports holes (i.e. unallocated blocks in the file) as phy sical == 0. ugly */ | |||
if (physical != 0) { | if (physical != 0) { | |||
physical_uoff = (ft_uoff) physical * block_size; | physical_uoff = (ft_uoff) physical * block_size; | |||
logical_uoff = (ft_uoff) logical * block_size; | logical_uoff = (ft_uoff) logical * block_size; | |||
/* keep track of bits used by extents. needed to compute effecti | ||||
ve block size */ | ||||
ret_block_size_bitmask |= physical_uoff | logical_uoff; | ||||
/* this is painful... FIBMAP reports one block per call */ | /* this is painful... FIBMAP reports one block per call */ | |||
ret_list.append(physical_uoff, logical_uoff, block_size, FC_DEFA ULT_USER_DATA); | ret_list.append(physical_uoff, logical_uoff, block_size, FC_DEFA ULT_USER_DATA); | |||
} | } | |||
} | } | |||
} while (0); | } while (0); | |||
if (err == 0) { | if (err == 0) { | |||
ff_log(FC_DEBUG, 0, "ioctl(%d, FIBMAP) succeeded", fd); | static ft_ull log_count = 0; | |||
ret_block_size_bitmask = block_size_bitmask; | ||||
if (log_count++ == 5) | ||||
ff_log(FC_DEBUG, 0, "decreasing to level TRACE any further DEBUG mes | ||||
sage 'ioctl(FIBMAP) successful'"); | ||||
extent_n = ret_list.size() - extent_n; | ||||
ff_log(log_count < 5 ? FC_DEBUG : FC_TRACE, 0, "ioctl(%d, FIBMAP) succes | ||||
sful: retrieved %" FT_ULL " extent%s in %" FT_ULL " call%s", | ||||
fd, (ft_ull) extent_n, extent_n == 1 ? "" : "s", (ft_ull) ioctl_ | ||||
n, ioctl_n == 1 ? "" : "s"); | ||||
/* keep track of bits used by extents. needed to compute effective block | ||||
size */ | ||||
ret_block_size_bitmask |= block_size; | ||||
} | } | |||
return err; | return err; | |||
#else | #else | |||
return ENOSYS; | return ENOSYS; | |||
#endif /* FIBMAP */ | #endif /* FIBMAP */ | |||
} | } | |||
#ifdef FS_IOC_FIEMAP | #ifdef FS_IOC_FIEMAP | |||
static int ff_linux_fiemap_ioctl(int fd, ft_uoff file_length, ft_u32 extent_n, s | static int ff_linux_fiemap(int fd, ft_uoff file_start, ft_uoff file_end, ft_u32 | |||
truct fiemap ** ret_k_map) { | extent_n, struct fiemap * k_map) | |||
struct fiemap * k_map; | { | |||
ft_size k_len = sizeof(struct fiemap) + extent_n * sizeof(struct fiemap_exte nt); | ft_size k_len = sizeof(struct fiemap) + extent_n * sizeof(struct fiemap_exte nt); | |||
int err = 0; | ||||
do { | memset(k_map, 0, k_len); | |||
k_map = (struct fiemap *) malloc(k_len); | ||||
if (k_map == NULL) { | ||||
err = ENOMEM; /* Out of memory */ | ||||
/* do not mark the error as reported, this is just a DEBUG message * | ||||
/ | ||||
ff_log(FC_DEBUG, 0, "malloc(%"FT_ULL") failed (%s), falling back on | ||||
ioctl(FIBMAP) ...", (ft_ull) k_len, strerror(err)); | ||||
break; | ||||
} | ||||
memset(k_map, 0, k_len); | ||||
k_map->fm_start = 0L; | k_map->fm_start = (ft_u64) file_start; | |||
k_map->fm_length = (ft_u64) file_length; | k_map->fm_length = (ft_u64) (file_end - file_start); | |||
k_map->fm_flags = FIEMAP_FLAG_SYNC; | k_map->fm_flags = FIEMAP_FLAG_SYNC; | |||
k_map->fm_extent_count = extent_n; | k_map->fm_extent_count = extent_n; | |||
if ((err = ff_posix_ioctl(fd, FS_IOC_FIEMAP, k_map)) != 0) { | ||||
/* do not mark the error as reported, this is just a DEBUG message * | ||||
/ | ||||
ff_log(FC_DEBUG, 0, "ioctl(%d, FS_IOC_FIEMAP, extents[%"FT_ULL"]) fa | ||||
iled (%s), falling back on ioctl(FIBMAP) ...", fd, (ft_ull) extent_n, strerror(e | ||||
rr)); | ||||
} | ||||
} while (0); | ||||
if (err != 0) { | int err = 0; | |||
if (k_map != NULL) { | if ((err = ff_posix_ioctl(fd, FS_IOC_FIEMAP, k_map)) != 0) { | |||
free(k_map); | static ft_ull log_count = 0; | |||
k_map = NULL; | if (log_count++ == 5) | |||
} | ff_log(FC_DEBUG, 0, "decreasing to level TRACE any further DEBUG mes | |||
sage 'ioctl(FIEMAP) failed'"); | ||||
/* do not mark the error as reported, this is just a DEBUG message */ | ||||
ff_log(log_count < 5 ? FC_DEBUG : FC_TRACE, 0, | ||||
"ioctl(%d, FIEMAP, extents[%" FT_ULL "]) failed (%s), falling ba | ||||
ck on ioctl(FIBMAP) ...", | ||||
fd, (ft_ull) extent_n, strerror(err)); | ||||
} | } | |||
* ret_k_map = k_map; | ||||
return err; | return err; | |||
} | } | |||
#endif /* FS_IOC_FIEMAP */ | #endif /* FS_IOC_FIEMAP */ | |||
/* | /* | |||
* retrieves file blocks allocation map (extents) for specified file descriptor | * retrieves file blocks allocation map (extents) for specified file descriptor | |||
* and appends them to ret_vector (with user_data = FC_DEFAULT_USER_DATA). | * and appends them to ret_vector (with user_data = FC_DEFAULT_USER_DATA). | |||
* in case of failure returns errno-compatible error code and ret_vector content s will be UNCHANGED. | * in case of failure returns errno-compatible error code and ret_vector content s will be UNCHANGED. | |||
* | * | |||
* must (and will) also check that device blocks count can be represented by ret | * must (and will) also check that device size can be represented by ret_list | |||
_list, | ||||
* by calling ret_list.extent_set_range(block_size, block_count) | ||||
* | * | |||
* implementation: calls ioctl(FS_IOC_FIEMAP) | * implementation: calls ioctl(FS_IOC_FIEMAP) | |||
*/ | */ | |||
static int ff_linux_fiemap(int fd, fr_vector<ft_uoff> & ret_list, ft_uoff & ret_ block_size_bitmask) | static int ff_linux_fiemap(int fd, fr_vector<ft_uoff> & ret_list, ft_uoff & ret_ block_size_bitmask) | |||
{ | { | |||
#ifdef FS_IOC_FIEMAP | #ifdef FS_IOC_FIEMAP | |||
struct fiemap * k_map = NULL; | ft_uoff file_start = 0, file_size; | |||
struct fiemap_extent * k_extent; | ||||
ft_uoff file_length, block_size_bitmask = ret_block_size_bitmask; | ||||
ft_u32 i, extent_n = 0; | ||||
int err; | int err; | |||
do { | if ((err = ff_posix_size(fd, & file_size)) || file_size == 0) | |||
if ((err = ff_posix_size(fd, & file_length)) || file_length == 0) | return err; | |||
break; | ||||
/* | fr_vector<ft_uoff> tmp_list; | |||
* first pass: call ioctl() and ask how many extents are needed | ||||
* | ||||
* second and further passes: allocate enough extents and call ioctl() | ||||
* with progressively larger buffers until we retrieve all extents | ||||
*/ | ||||
while ((err = ff_linux_fiemap_ioctl(fd, file_length, extent_n, & k_map)) | ||||
== 0) { | ||||
ft_u32 ret_extent_n = k_map->fm_mapped_extents; | ||||
if (ret_extent_n != 0 && extent_n != 0 && k_map->fm_extent_count != 0) { | ||||
k_extent = k_map->fm_extents; | ||||
if (k_extent[ret_extent_n - 1].fe_flags & FIEMAP_EXTENT_LAST) { | ||||
/* ok, we really got all the extents */ | ||||
break; | ||||
} | ||||
} | ||||
/* | ||||
* no FIEMAP_EXTENT_LAST found, we did not get all the extents :( | ||||
* | ||||
* enlarge the array and try again. | ||||
* if extent_n == 0 (first pass), use kernel-suggested length k_map- | ||||
>fm_mapped_extents | ||||
* otherwise increase extent_n exponentially. | ||||
*/ | ||||
free(k_map); | ||||
k_map = NULL; | ||||
if (extent_n == 0) { | enum { | |||
if ((extent_n = ret_extent_n) <= 1024) | K_EXTENT_N = 1024, | |||
extent_n = 1024; | K_SIZEOF_FIEMAP = sizeof(struct fiemap) + K_EXTENT_N * sizeof(struct fie | |||
} else if (ret_extent_n < extent_n) { | map_extent) | |||
ff_log(FC_WARN, 0, "ioctl(%d, FS_IOC_FIEMAP) is refusing to retu | }; | |||
rn more than %"FT_ULL" extents in a single call, falling back on ioctl(FIBMAP) . | char buf[K_SIZEOF_FIEMAP]; | |||
..", fd, (ft_ull) ret_extent_n); | struct fiemap * k_map = (struct fiemap *) buf; | |||
/* mark the error as reported, WARN is quite a severe level */ | ft_uoff ioctl_n = 0, block_size_bitmask = ret_block_size_bitmask; | |||
err = -ENOSYS; /* ioctl(FS_IOC_FIEMAP) not working as expected.. | ||||
. */ | // call ioctl() repeatedly until we retrieve all extents | |||
break; | while (ioctl_n++, (err = ff_linux_fiemap(fd, file_start, file_size, K_EXTENT | |||
} else if (extent_n <= ((ft_u32)-1) >> 1) | _N, k_map)) == 0) { | |||
extent_n <<= 1; | ||||
else if (extent_n < (ft_u32)-1) | ft_u32 i, extent_n = k_map->fm_mapped_extents; | |||
extent_n = (ft_u32)-1; | const struct fiemap_extent * extents = k_map->fm_extents; | |||
else { | ||||
ff_log(FC_DEBUG, 0, "tried ioctl(%d, FS_IOC_FIEMAP) with [MAX_UI | if (extent_n == 0) { | |||
NT32_T-1] extents but it was not enough, falling back on ioctl(FIBMAP) ...", fd) | /* we did not get any extent... bail out */ | |||
; | ff_log(FC_WARN, 0, "ioctl(%d, FS_IOC_FIEMAP) is refusing to return a | |||
/* do not mark the error as reported, this is just a DEBUG messa | ny extent after file offset = %" FT_ULL | |||
ge */ | ", falling back on ioctl(FIBMAP) ...", fd, (ft_ull) file_sta | |||
err = ENOMEM; /* Out of memory */ | rt); | |||
break; | /* mark the error as reported, WARN is quite a severe level */ | |||
} | err = -ENOSYS; /* ioctl(FS_IOC_FIEMAP) not working as expected... */ | |||
/* keep trying */ | break; | |||
} | } | |||
if (err) | ||||
const struct fiemap_extent & last_e = extents[extent_n - 1]; | ||||
const ft_uoff new_file_start = (ft_uoff) last_e.fe_logical + (ft_uoff) l | ||||
ast_e.fe_length; | ||||
if (new_file_start <= file_start) { | ||||
ff_log(FC_WARN, 0, "ioctl(%d, FS_IOC_FIEMAP) returned extents ending | ||||
at %" FT_ULL ", i.e. _before_ start of requested range [%" FT_ULL ", %" FT_ULL | ||||
"]" | ||||
", falling back on ioctl(FIBMAP) ...", fd, (ft_ull) new_file | ||||
_start, (ft_ull) file_start, (ft_ull) file_size); | ||||
/* mark the error as reported, WARN is quite a severe level */ | ||||
err = -ENOSYS; /* ioctl(FS_IOC_FIEMAP) not working as expected... */ | ||||
break; | break; | |||
} | ||||
extent_n = k_map->fm_mapped_extents; | tmp_list.reserve(tmp_list.size() + extent_n); | |||
k_extent = k_map->fm_extents; | ||||
/* | ||||
* perform a first loop, checking for unsupported extents | ||||
* and computing an effective block size | ||||
*/ | ||||
for (i = 0; i < extent_n; i++) { | for (i = 0; i < extent_n; i++) { | |||
ft_u32 flag = k_extent[i].fe_flags & (FIEMAP_EXTENT_UNKNOWN | FIEMAP | const struct fiemap_extent & e = extents[i]; | |||
_EXTENT_ENCODED); | ||||
ft_u32 flag = e.fe_flags & (FIEMAP_EXTENT_UNKNOWN | FIEMAP_EXTENT_EN | ||||
CODED); | ||||
if (flag) { | if (flag) { | |||
ff_log(FC_DEBUG, 0, "ioctl(%d, FIEMAP, extents[%"FT_ULL"]) retur | ff_log(FC_DEBUG, 0, "ioctl(%d, FS_IOC_FIEMAP, extents[%" FT_ULL | |||
ned unsupported %s%s%s extents, falling back on ioctl(FIBMAP) ...", | "]) returned unsupported %s%s%s extents, falling back on ioctl(FIBMAP) ...", | |||
fd, (ft_ull)extent_n, | fd, (ft_ull) extent_n, | |||
(flag & FIEMAP_EXTENT_UNKNOWN ? "UNKNOWN" : ""), | (flag & FIEMAP_EXTENT_UNKNOWN ? "UNKNOWN" : ""), | |||
(flag == (FIEMAP_EXTENT_UNKNOWN|FIEMAP_EXTENT_ENCODED) ? " + " : ""), | (flag == (FIEMAP_EXTENT_UNKNOWN|FIEMAP_EXTENT_ENCODED) ? "+" : ""), | |||
(flag & FIEMAP_EXTENT_ENCODED ? "ENCODED" : "") | (flag & FIEMAP_EXTENT_ENCODED ? "ENCODED" : "") | |||
); | ); | |||
/* do not mark the error as reported, this is just a DEBUG messa ge */ | // do not mark the error as reported, this is just a DEBUG messa ge | |||
err = ENOSYS; | err = ENOSYS; | |||
break; | break; | |||
} | } | |||
/* keep track of bits used by all physical, logical and lengths. | /* | |||
* needed to check against block size */ | * keep track of bits used by all physical, logical and lengths. | |||
block_size_bitmask |= k_extent[i].fe_physical | k_extent[i].fe_logic | * needed to check against block size | |||
al | k_extent[i].fe_length; | */ | |||
block_size_bitmask |= e.fe_physical | e.fe_logical | e.fe_length; | ||||
// save what we retrieved | ||||
tmp_list.append((ft_uoff) e.fe_physical, | ||||
(ft_uoff) e.fe_logical, | ||||
(ft_uoff) e.fe_length, | ||||
(e.fe_flags & FIEMAP_EXTENT_UNWRITTEN) ? FC_EXTENT_Z | ||||
EROED : FC_DEFAULT_USER_DATA); | ||||
} | } | |||
if (err != 0) | if (err != 0 || (last_e.fe_flags & FIEMAP_EXTENT_LAST)) | |||
break; | break; | |||
ret_list.reserve(ret_list.size() + extent_n); | ||||
/* ok, no strange extents: we can now add them to ret_list */ | // no FIEMAP_EXTENT_LAST found, we did not get all the extents. keep try | |||
for (i = 0; i < extent_n; i++) { | ing... | |||
ret_list.append((ft_uoff) k_extent[i].fe_physical, | if (new_file_start >= file_size) | |||
(ft_uoff) k_extent[i].fe_logical, | // should not happen, but not too dangerous | |||
(ft_uoff) k_extent[i].fe_length, | file_size = new_file_start + 1; | |||
(k_extent[i].fe_flags & FIEMAP_EXTENT_UNWRITTEN) ? F | file_start = new_file_start; | |||
C_EXTENT_ZEROED : FC_DEFAULT_USER_DATA); | } | |||
} | if (err != 0) | |||
} while (0); | return err; | |||
if (k_map != NULL) | ft_size extent_n = tmp_list.size(); | |||
free(k_map); | ||||
if (err == 0) { | /* ok, no strange extents: we can now add them to ret_list */ | |||
ff_log(FC_DEBUG, 0, "ioctl(%d, FS_IOC_FIEMAP, extents[%"FT_ULL"]) succee | ret_list.reserve(ret_list.size() + extent_n); | |||
ded", fd, (ft_ull)extent_n); | ret_list.append_all(tmp_list); | |||
ret_block_size_bitmask = block_size_bitmask; | ||||
} | static ft_ull log_count = 0; | |||
if (log_count++ == 5) | ||||
ff_log(FC_DEBUG, 0, "decreasing to level TRACE any further DEBUG message | ||||
'ioctl(FIEMAP) successful'"); | ||||
ff_log(log_count < 5 ? FC_DEBUG : FC_TRACE, 0, "ioctl(%d, FIEMAP) successful | ||||
: retrieved %" FT_ULL " extent%s in %" FT_ULL " call%s", | ||||
fd, (ft_ull) extent_n, extent_n == 1 ? "" : "s", (ft_ull) ioctl_n, i | ||||
octl_n == 1 ? "" : "s"); | ||||
ret_block_size_bitmask = block_size_bitmask; | ||||
return err; | return err; | |||
#else | #else | |||
return ENOSYS; | return ENOSYS; | |||
#endif /* FS_IOC_FIEMAP */ | #endif /* FS_IOC_FIEMAP */ | |||
} | } | |||
/** | /** | |||
* retrieves file blocks allocation map (extents) for specified file descriptor | * retrieves file blocks allocation map (extents) for specified file descriptor | |||
* and appends them to ret_vector (with user_data = FC_DEFAULT_USER_DATA) | * and appends them to ret_vector (with user_data = FC_DEFAULT_USER_DATA) sorted by ->logical | |||
* in case of failure returns errno-compatible error code, and ret_vector conten ts will be UNDEFINED. | * in case of failure returns errno-compatible error code, and ret_vector conten ts will be UNDEFINED. | |||
* | * | |||
* implementation: calls ioctl(FS_IOC_FIEMAP) and if it fails, tries with ioctl( FIBMAP) | * implementation: calls ioctl(FS_IOC_FIEMAP) and if it fails, tries with ioctl( FIBMAP) | |||
*/ | */ | |||
int ff_read_extents_posix(int fd, ft_uoff dev_length, fr_vector<ft_uoff> & ret_l ist, ft_uoff & ret_block_size_bitmask) | int ff_read_extents_posix(int fd, ft_uoff dev_length, fr_vector<ft_uoff> & ret_l ist, ft_uoff & ret_block_size_bitmask) | |||
{ | { | |||
int err; | int err; | |||
do { | do { | |||
err = ff_linux_fiemap(fd, ret_list, ret_block_size_bitmask); | err = ff_linux_fiemap(fd, ret_list, ret_block_size_bitmask); | |||
if (err != 0) { | if (err != 0) { | |||
End of changes. 37 change blocks. | ||||
157 lines changed or deleted | 138 lines changed or added |