mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 19:01:57 -04:00
Fallback to FIBMAP if FIEMAP doesn't work.
This commit is contained in:
parent
90b4efdbba
commit
ef969263cd
2 changed files with 35 additions and 14 deletions
4
HISTORY
4
HISTORY
|
|
@ -4,8 +4,8 @@ SnapRAID HISTORY
|
|||
4.1 2013/9
|
||||
==========
|
||||
* If the underline filesystem doesn't support the FIEMAP command,
|
||||
automatically fallback to use the inode number for sorting files.
|
||||
This happens with reiserfs and FUSE in Linux.
|
||||
automatically fallback to use FIBMAP and then the inode number for sorting
|
||||
files.
|
||||
* Fixes the import of content files from previous version of SnapRAID that
|
||||
are the result of an incomplete sync.
|
||||
* Added a new -C, --gen-conf option to generate a dummy configuration
|
||||
|
|
|
|||
45
unix.c
45
unix.c
|
|
@ -129,43 +129,64 @@ int filephy(const char* path, struct stat* st, uint64_t* physical)
|
|||
/* In Linux gets the real physical address of the file */
|
||||
/* Note that FIEMAP doesn't require root permission */
|
||||
int f;
|
||||
|
||||
struct {
|
||||
struct fiemap fiemap;
|
||||
struct fiemap_extent extent;
|
||||
} fm;
|
||||
unsigned int blknum;
|
||||
|
||||
f = open(path, O_RDONLY);
|
||||
if (f == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* first try with FIEMAP */
|
||||
memset(&fm, 0, sizeof(fm));
|
||||
fm.fiemap.fm_start = 0;
|
||||
fm.fiemap.fm_length = ~0ULL;
|
||||
fm.fiemap.fm_flags = FIEMAP_FLAG_SYNC; /* required to ensure that just created files report a valid address and not 0 */
|
||||
fm.fiemap.fm_extent_count = 1; /* we are interested only at the first block */
|
||||
|
||||
if (ioctl(f, FS_IOC_FIEMAP, &fm) == -1) {
|
||||
/* if the underline filesystem doesn't support FS_IOC_FIEMAP */
|
||||
/* fallback to use the inode */
|
||||
if (errno == ENOTSUP) {
|
||||
close(f);
|
||||
*physical = st->st_ino;
|
||||
return 0;
|
||||
}
|
||||
if (ioctl(f, FS_IOC_FIEMAP, &fm) == 0) {
|
||||
*physical = fm.fiemap.fm_extents[0].fe_physical;
|
||||
if (close(f) == -1)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if it's an unexpected error fails */
|
||||
if (errno != ENOTSUP) {
|
||||
close(f);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*physical = fm.fiemap.fm_extents[0].fe_physical;
|
||||
/* if empty, FIBMAP doesn't work */
|
||||
if (st->st_size == 0) {
|
||||
*physical = 0;
|
||||
if (close(f) == -1)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (close(f) == -1) {
|
||||
/* then try with FIBMAP */
|
||||
blknum = 0; /* first block */
|
||||
if (ioctl(f, FIBMAP, &blknum) == 0) {
|
||||
*physical = blknum;
|
||||
if (close(f) == -1)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if it's an unexpected error fails */
|
||||
if (errno != ENOTSUP && errno != EPERM) {
|
||||
close(f);
|
||||
return -1;
|
||||
}
|
||||
|
||||
(void)st; /* not used here */
|
||||
/* otherwise uses the inode */
|
||||
*physical = st->st_ino;
|
||||
if (close(f) == -1)
|
||||
return -1;
|
||||
#else
|
||||
/* In a generic Unix uses the inode as fake physical address */
|
||||
*physical = st->st_ino;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue