Detects the case of physical offsets not reported beucase the file doesn't have one.

This commit is contained in:
Andrea Mazzoleni 2013-09-28 15:33:56 +02:00
parent cffbba8aee
commit 6deecb26de
6 changed files with 36 additions and 10 deletions

View file

@ -1,6 +1,13 @@
SnapRAID HISTORY
================
4.2 2013/9
==========
* Fixed the wrong warning about physical offsets not supported caused
by files not having a real offset because too small.
For example, in NTFS it's possible to store such files in the MFT.
It's just a cosmetic change, and not a functional one.
4.1 2013/9
==========
* If the underline filesystem doesn't support the FIEMAP command,

View file

@ -1,6 +1,6 @@
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ([2.65])
AC_INIT([snapraid], [4.1], [], [], [http://snapraid.sourceforge.net])
AC_INIT([snapraid], [4.2], [], [], [http://snapraid.sourceforge.net])
AM_INIT_AUTOMAKE([foreign no-dependencies -Wall])
AC_CONFIG_SRCDIR([snapraid.c])
AC_CONFIG_HEADER([config.h])

View file

@ -1130,7 +1130,10 @@ int filephy(const char* file, struct stat* st, uint64_t* physical)
} else if (error == ERROR_HANDLE_EOF) {
/* if the file is small, it can be stored in the Master File Table (MFT) */
/* and then it doesn't have a physical address */
rpb->ExtentCount = 0;
/* In such case we report a specific fake address, to report this special condition */
/* that it's different from the 0 offset reported by the underline file system */
rpb->ExtentCount = 1;
rpb->Extents[0].Lcn.QuadPart = FILEPHY_WITHOUT_OFFSET;
} else {
windows_errno(error);
CloseHandle(h);
@ -1141,9 +1144,9 @@ int filephy(const char* file, struct stat* st, uint64_t* physical)
CloseHandle(h);
if (rpb->ExtentCount < 1)
*physical = 0;
*physical = FILEPHY_UNREPORTED_OFFSET;
else
*physical = rpb->Extents[0].Lcn.QuadPart;
*physical = rpb->Extents[0].Lcn.QuadPart + FILEPHY_REAL_OFFSET;
return 0;
}

View file

@ -187,6 +187,22 @@ static inline int hardlink(const char* a, const char* b)
*/
int devuuid(uint64_t device, char* uuid, size_t size);
/**
* Special value returned when the file doesn't have a real offset.
* For example, because it's stored in the NTFS MFT.
*/
#define FILEPHY_WITHOUT_OFFSET 0
/**
* Special value returned when the filesystem doesn't report any offset for unknown reason.
*/
#define FILEPHY_UNREPORTED_OFFSET 1
/**
* Value indicating real offsets. All offsets greater or equal at this one are real.
*/
#define FILEPHY_REAL_OFFSET 2
/**
* Get the physcal address of the specified file.
* This is expected to be just a hint and not necessarely correct or unique.

2
scan.c
View file

@ -974,7 +974,7 @@ void state_scan(struct snapraid_state* state, int output)
/* if the file is not empty, count duplicate physical offsets */
if (state->opt.force_order == SORT_PHYSICAL && file->size != 0) {
if (phy_count > 0 && file->physical == phy_last)
if (phy_count > 0 && file->physical == phy_last && phy_last != FILEPHY_WITHOUT_OFFSET)
++phy_dup;
phy_last = file->physical;
++phy_count;

10
unix.c
View file

@ -149,7 +149,7 @@ int filephy(const char* path, struct stat* st, uint64_t* physical)
fm.fiemap.fm_extent_count = 1; /* we are interested only at the first block */
if (ioctl(f, FS_IOC_FIEMAP, &fm) != -1) {
*physical = fm.fiemap.fm_extents[0].fe_physical;
*physical = fm.fiemap.fm_extents[0].fe_physical + FILEPHY_REAL_OFFSET;
if (close(f) == -1)
return -1;
return 0;
@ -157,7 +157,7 @@ int filephy(const char* path, struct stat* st, uint64_t* physical)
/* if empty, FIBMAP doesn't work */
if (st->st_size == 0) {
*physical = 0;
*physical = FILEPHY_WITHOUT_OFFSET;
if (close(f) == -1)
return -1;
return 0;
@ -168,7 +168,7 @@ int filephy(const char* path, struct stat* st, uint64_t* physical)
/* in exfat it always returns 0, that it's anyway better than the fake inodes */
blknum = 0; /* first block */
if (ioctl(f, FIBMAP, &blknum) != -1) {
*physical = blknum;
*physical = blknum + FILEPHY_REAL_OFFSET;
if (close(f) == -1)
return -1;
return 0;
@ -177,13 +177,13 @@ int filephy(const char* path, struct stat* st, uint64_t* physical)
/* otherwise don't use anything, and keep the existing order */
/* at now this should happen only for vfat */
/* and it's surely better than using fake inodes */
*physical = 0;
*physical = FILEPHY_UNREPORTED_OFFSET;
if (close(f) == -1)
return -1;
#else
/* In a generic Unix use a dummy value for all the files */
/* We don't want to risk to use the inode without knowing if it really improves performance */
*physical = 0;
*physical = FILEPHY_UNREPORTED_OFFSET;
(void)path; /* not used here */
(void)st;