| ntfsextents: fix incorrect handling of merged runs | |
| After the filesystem is defragmented, ntfsextents produced suspicious output | |
| like the following: | |
| ... | |
| 47934664704 292540416 | |
| 47934664704 930017280 | |
| 47934664704 2045247488 | |
| ... | |
| where a section of the disk repeats. This corresponds to the LCN_RL_NOT_MAPPED | |
| case: it seems that a series of contiguous extents can be represented by more | |
| than one runlist element referencing the same base VCN. The correct mapping | |
| for the example above is: | |
| ... | |
| 47934664704 292540416 | |
| 48227205120 637476864 | |
| 48864681984 1115230208 | |
| ... | |
| which is what we produce with this patch, which is derived from the | |
| corresponding logic in ntfs_attr_pread_i(). | |
| The following equivalent, more aesthetically-pleasing output is not worth the | |
| hassle to produce: | |
| ... | |
| 47934664704 2045247488 | |
| ... | |
| https://phabricator.endlessm.com/T13743 | |
| Index: ntfs-3g-2014.2.15AR.2/ntfsprogs/ntfsextents.c | |
| =================================================================== | |
| --- ntfs-3g-2014.2.15AR.2.orig/ntfsprogs/ntfsextents.c | |
| +++ ntfs-3g-2014.2.15AR.2/ntfsprogs/ntfsextents.c | |
| @@ -42,7 +42,7 @@ int main(int argc, const char *argv[]) | |
| ntfs_inode *ni; | |
| ntfs_attr *na = NULL; | |
| runlist_element *rl; | |
| - s64 remaining; | |
| + s64 ofs, total, remaining; | |
| ntfs_log_set_handler(ntfs_log_handler_stderr); | |
| @@ -100,7 +100,8 @@ int main(int argc, const char *argv[]) | |
| goto out; | |
| } | |
| - for (remaining = na->data_size; remaining; rl++) { | |
| + ofs = - (rl->vcn << vol->cluster_size_bits); | |
| + for (total = 0, remaining = na->data_size; remaining; rl++, ofs = 0) { | |
| unsigned long data_size; | |
| if (rl->lcn == LCN_RL_NOT_MAPPED) { | |
| @@ -110,6 +111,8 @@ int main(int argc, const char *argv[]) | |
| ntfs_log_error("ERROR: Failed to find VCN #2\n"); | |
| goto out; | |
| } | |
| + /* Needed for case when runs merged. */ | |
| + ofs = total - (rl->vcn << vol->cluster_size_bits); | |
| } | |
| if (!rl->length) { | |
| ntfs_log_error("ERROR: Zero run length\n"); | |
| @@ -123,8 +126,9 @@ int main(int argc, const char *argv[]) | |
| ntfs_log_error("ERROR: File has hole\n"); | |
| goto out; | |
| } | |
| - data_size = min(remaining, rl->length << vol->cluster_size_bits); | |
| - printf("%ld %ld\n", rl->lcn << vol->cluster_size_bits, data_size); | |
| + data_size = min(remaining, (rl->length << vol->cluster_size_bits) - ofs); | |
| + printf("%ld %ld\n", (rl->lcn << vol->cluster_size_bits) + ofs, data_size); | |
| + total += data_size; | |
| remaining -= data_size; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment