Improved computation of runlist for fragmented files O(n) instead of O(n*n)
parent
42968369c4
commit
2dc7362ba9
|
@ -65,14 +65,14 @@ extern runlist_element *ntfs_mapping_pairs_decompress(const ntfs_volume *vol,
|
|||
extern int ntfs_get_nr_significant_bytes(const s64 n);
|
||||
|
||||
extern int ntfs_get_size_for_mapping_pairs(const ntfs_volume *vol,
|
||||
const runlist_element *rl, const VCN start_vcn);
|
||||
const runlist_element *rl, const VCN start_vcn, int max_size);
|
||||
|
||||
extern int ntfs_write_significant_bytes(u8 *dst, const u8 *dst_max,
|
||||
const s64 n);
|
||||
|
||||
extern int ntfs_mapping_pairs_build(const ntfs_volume *vol, u8 *dst,
|
||||
const int dst_len, const runlist_element *rl,
|
||||
const VCN start_vcn, VCN *const stop_vcn);
|
||||
const VCN start_vcn, runlist_element const **stop_rl);
|
||||
|
||||
extern int ntfs_rl_truncate(runlist **arl, const VCN start_vcn);
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* Copyright (c) 2002-2005 Richard Russon
|
||||
* Copyright (c) 2002-2008 Szabolcs Szakacsits
|
||||
* Copyright (c) 2004-2007 Yura Pakhuchiy
|
||||
* Copyright (c) 2007-2008 Jean-Pierre Andre
|
||||
* Copyright (c) 2007-2009 Jean-Pierre Andre
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
|
@ -3690,7 +3690,7 @@ static int ntfs_attr_make_non_resident(ntfs_attr *na,
|
|||
}
|
||||
}
|
||||
/* Determine the size of the mapping pairs array. */
|
||||
mp_size = ntfs_get_size_for_mapping_pairs(vol, rl, 0);
|
||||
mp_size = ntfs_get_size_for_mapping_pairs(vol, rl, 0, INT_MAX);
|
||||
if (mp_size < 0) {
|
||||
err = errno;
|
||||
ntfs_log_debug("Eeek! Failed to get size for mapping pairs array. "
|
||||
|
@ -4278,6 +4278,7 @@ static int ntfs_attr_update_mapping_pairs_i(ntfs_attr *na, VCN from_vcn)
|
|||
MFT_RECORD *m;
|
||||
ATTR_RECORD *a;
|
||||
VCN stop_vcn;
|
||||
const runlist_element *stop_rl;
|
||||
int err, mp_size, cur_max_mp_size, exp_max_mp_size, ret = -1;
|
||||
BOOL finished_build;
|
||||
retry:
|
||||
|
@ -4307,6 +4308,7 @@ retry:
|
|||
|
||||
/* Fill attribute records with new mapping pairs. */
|
||||
stop_vcn = 0;
|
||||
stop_rl = na->rl;
|
||||
finished_build = FALSE;
|
||||
while (!ntfs_attr_lookup(na->type, na->name, na->name_len,
|
||||
CASE_SENSITIVE, from_vcn, NULL, 0, ctx)) {
|
||||
|
@ -4360,13 +4362,6 @@ retry:
|
|||
case -3: goto put_err_out;
|
||||
}
|
||||
|
||||
/* Get the size for the rest of mapping pairs array. */
|
||||
mp_size = ntfs_get_size_for_mapping_pairs(na->ni->vol, na->rl,
|
||||
stop_vcn);
|
||||
if (mp_size <= 0) {
|
||||
ntfs_log_perror("%s: get MP size failed", __FUNCTION__);
|
||||
goto put_err_out;
|
||||
}
|
||||
/*
|
||||
* Determine maximum possible length of mapping pairs,
|
||||
* if we shall *not* expand space for mapping pairs.
|
||||
|
@ -4380,6 +4375,17 @@ retry:
|
|||
*/
|
||||
exp_max_mp_size = le32_to_cpu(m->bytes_allocated) -
|
||||
le32_to_cpu(m->bytes_in_use) + cur_max_mp_size;
|
||||
/* Get the size for the rest of mapping pairs array. */
|
||||
/* old code equivalent
|
||||
mp_size = ntfs_get_size_for_mapping_pairs(na->ni->vol, na->rl,
|
||||
stop_vcn, INT_MAX);
|
||||
*/
|
||||
mp_size = ntfs_get_size_for_mapping_pairs(na->ni->vol, stop_rl,
|
||||
stop_vcn, exp_max_mp_size);
|
||||
if (mp_size <= 0) {
|
||||
ntfs_log_perror("%s: get MP size failed", __FUNCTION__);
|
||||
goto put_err_out;
|
||||
}
|
||||
/* Test mapping pairs for fitting in the current mft record. */
|
||||
if (mp_size > exp_max_mp_size) {
|
||||
/*
|
||||
|
@ -4444,8 +4450,12 @@ retry:
|
|||
*/
|
||||
if (!ntfs_mapping_pairs_build(na->ni->vol, (u8*)a + le16_to_cpu(
|
||||
a->mapping_pairs_offset), mp_size, na->rl,
|
||||
stop_vcn, &stop_vcn))
|
||||
stop_vcn, &stop_rl))
|
||||
finished_build = TRUE;
|
||||
if (stop_rl)
|
||||
stop_vcn = stop_rl->vcn;
|
||||
else
|
||||
stop_vcn = 0;
|
||||
if (!finished_build && errno != ENOSPC) {
|
||||
ntfs_log_perror("Failed to build mapping pairs");
|
||||
goto put_err_out;
|
||||
|
@ -4489,7 +4499,7 @@ retry:
|
|||
while (1) {
|
||||
/* Calculate size of rest mapping pairs. */
|
||||
mp_size = ntfs_get_size_for_mapping_pairs(na->ni->vol,
|
||||
na->rl, stop_vcn);
|
||||
na->rl, stop_vcn, INT_MAX);
|
||||
if (mp_size <= 0) {
|
||||
ntfs_log_perror("%s: get mp size failed", __FUNCTION__);
|
||||
goto put_err_out;
|
||||
|
@ -4528,7 +4538,11 @@ retry:
|
|||
|
||||
err = ntfs_mapping_pairs_build(na->ni->vol, (u8*)a +
|
||||
le16_to_cpu(a->mapping_pairs_offset), mp_size, na->rl,
|
||||
stop_vcn, &stop_vcn);
|
||||
stop_vcn, &stop_rl);
|
||||
if (stop_rl)
|
||||
stop_vcn = stop_rl->vcn;
|
||||
else
|
||||
stop_vcn = 0;
|
||||
if (err < 0 && errno != ENOSPC) {
|
||||
err = errno;
|
||||
ntfs_log_perror("Failed to build MP");
|
||||
|
|
|
@ -721,7 +721,7 @@ static int ntfs_mft_bitmap_extend_allocation_i(ntfs_volume *vol)
|
|||
goto undo_alloc;
|
||||
}
|
||||
/* Get the size for the new mapping pairs array for this extent. */
|
||||
mp_size = ntfs_get_size_for_mapping_pairs(vol, rl2, ll);
|
||||
mp_size = ntfs_get_size_for_mapping_pairs(vol, rl2, ll, INT_MAX);
|
||||
if (mp_size <= 0) {
|
||||
ntfs_log_error("Get size for mapping pairs failed for "
|
||||
"mft bitmap attribute extent.\n");
|
||||
|
@ -1070,7 +1070,7 @@ static int ntfs_mft_data_extend_allocation(ntfs_volume *vol)
|
|||
goto undo_alloc;
|
||||
}
|
||||
/* Get the size for the new mapping pairs array for this extent. */
|
||||
mp_size = ntfs_get_size_for_mapping_pairs(vol, rl2, ll);
|
||||
mp_size = ntfs_get_size_for_mapping_pairs(vol, rl2, ll, INT_MAX);
|
||||
if (mp_size <= 0) {
|
||||
ntfs_log_error("Get size for mapping pairs failed for "
|
||||
"mft data attribute extent.\n");
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* Copyright (c) 2002-2005 Richard Russon
|
||||
* Copyright (c) 2002-2008 Szabolcs Szakacsits
|
||||
* Copyright (c) 2004 Yura Pakhuchiy
|
||||
* Copyright (c) 2007-2009 Jean-Pierre Andre
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
|
@ -1219,19 +1220,18 @@ errno_set:
|
|||
*/
|
||||
int ntfs_get_nr_significant_bytes(const s64 n)
|
||||
{
|
||||
s64 l = n;
|
||||
u64 l;
|
||||
int i;
|
||||
s8 j;
|
||||
|
||||
i = 0;
|
||||
do {
|
||||
l >>= 8;
|
||||
i++;
|
||||
} while (l != 0LL && l != -1LL);
|
||||
j = (n >> 8 * (i - 1)) & 0xff;
|
||||
/* If the sign bit is wrong, we need an extra byte. */
|
||||
if ((n < 0LL && j >= 0) || (n > 0LL && j < 0))
|
||||
i++;
|
||||
l = (n < 0 ? ~n : n);
|
||||
i = 1;
|
||||
if (l >= 128) {
|
||||
l >>= 7;
|
||||
do {
|
||||
i++;
|
||||
l >>= 8;
|
||||
} while (l);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
|
@ -1256,7 +1256,7 @@ int ntfs_get_nr_significant_bytes(const s64 n)
|
|||
* EIO - The runlist is corrupt.
|
||||
*/
|
||||
int ntfs_get_size_for_mapping_pairs(const ntfs_volume *vol,
|
||||
const runlist_element *rl, const VCN start_vcn)
|
||||
const runlist_element *rl, const VCN start_vcn, int max_size)
|
||||
{
|
||||
LCN prev_lcn;
|
||||
int rls;
|
||||
|
@ -1315,7 +1315,7 @@ int ntfs_get_size_for_mapping_pairs(const ntfs_volume *vol,
|
|||
rl++;
|
||||
}
|
||||
/* Do the full runs. */
|
||||
for (; rl->length; rl++) {
|
||||
for (; rl->length && (rls < max_size); rl++) {
|
||||
if (rl->length < 0 || rl->lcn < LCN_HOLE)
|
||||
goto err_out;
|
||||
/* Header byte + length. */
|
||||
|
@ -1430,7 +1430,7 @@ err_out:
|
|||
*/
|
||||
int ntfs_mapping_pairs_build(const ntfs_volume *vol, u8 *dst,
|
||||
const int dst_len, const runlist_element *rl,
|
||||
const VCN start_vcn, VCN *const stop_vcn)
|
||||
const VCN start_vcn, runlist_element const **stop_rl)
|
||||
{
|
||||
LCN prev_lcn;
|
||||
u8 *dst_max, *dst_next;
|
||||
|
@ -1442,8 +1442,8 @@ int ntfs_mapping_pairs_build(const ntfs_volume *vol, u8 *dst,
|
|||
if (!rl) {
|
||||
if (start_vcn)
|
||||
goto val_err;
|
||||
if (stop_vcn)
|
||||
*stop_vcn = 0;
|
||||
if (stop_rl)
|
||||
*stop_rl = rl;
|
||||
if (dst_len < 1)
|
||||
goto nospc_err;
|
||||
goto ok;
|
||||
|
@ -1538,8 +1538,8 @@ int ntfs_mapping_pairs_build(const ntfs_volume *vol, u8 *dst,
|
|||
dst += 1 + len_len + lcn_len;
|
||||
}
|
||||
/* Set stop vcn. */
|
||||
if (stop_vcn)
|
||||
*stop_vcn = rl->vcn;
|
||||
if (stop_rl)
|
||||
*stop_rl = rl;
|
||||
ok:
|
||||
/* Add terminator byte. */
|
||||
*dst = 0;
|
||||
|
@ -1547,8 +1547,8 @@ out:
|
|||
return ret;
|
||||
size_err:
|
||||
/* Set stop vcn. */
|
||||
if (stop_vcn)
|
||||
*stop_vcn = rl->vcn;
|
||||
if (stop_rl)
|
||||
*stop_rl = rl;
|
||||
/* Add terminator byte. */
|
||||
*dst = 0;
|
||||
nospc_err:
|
||||
|
|
Loading…
Reference in New Issue