From 6deecb26de80907cfbd4dfb78205261a9217ab92 Mon Sep 17 00:00:00 2001 From: Andrea Mazzoleni Date: Sat, 28 Sep 2013 15:33:56 +0200 Subject: [PATCH] Detects the case of physical offsets not reported beucase the file doesn't have one. --- HISTORY | 7 +++++++ configure.ac | 2 +- mingw.c | 9 ++++++--- portable.h | 16 ++++++++++++++++ scan.c | 2 +- unix.c | 10 +++++----- 6 files changed, 36 insertions(+), 10 deletions(-) diff --git a/HISTORY b/HISTORY index 3720ce55..fff25da1 100644 --- a/HISTORY +++ b/HISTORY @@ -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, diff --git a/configure.ac b/configure.ac index 8d622376..859b7b98 100644 --- a/configure.ac +++ b/configure.ac @@ -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]) diff --git a/mingw.c b/mingw.c index 7057ee11..4ccc6a1e 100644 --- a/mingw.c +++ b/mingw.c @@ -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; } diff --git a/portable.h b/portable.h index 4922d2f0..ccaa34fa 100644 --- a/portable.h +++ b/portable.h @@ -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. diff --git a/scan.c b/scan.c index 8b17ddda..4b1d961d 100644 --- a/scan.c +++ b/scan.c @@ -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; diff --git a/unix.c b/unix.c index a775b9da..f6c646a1 100644 --- a/unix.c +++ b/unix.c @@ -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;