Fixed dealing with holes when expanding an attribute

This commit is contained in:
Jean-Pierre André 2011-02-16 12:22:30 +01:00
parent 8034e9be25
commit 30c06f9092
2 changed files with 25 additions and 15 deletions

View File

@ -58,6 +58,12 @@ typedef enum {
LCN_EIO = -5, LCN_EIO = -5,
} ntfs_lcn_special_values; } ntfs_lcn_special_values;
typedef enum { /* ways of processing holes when expanding */
HOLES_NO,
HOLES_OK,
HOLES_DELAY
} hole_type;
/** /**
* struct ntfs_attr_search_ctx - search context used in attribute search functions * struct ntfs_attr_search_ctx - search context used in attribute search functions
* @mrec: buffer containing mft record to search * @mrec: buffer containing mft record to search

View File

@ -1726,7 +1726,8 @@ static int borrow_from_hole(ntfs_attr *na, runlist_element **prl,
return (compressed_part); return (compressed_part);
} }
static int ntfs_attr_truncate_i(ntfs_attr *na, const s64 newsize, BOOL holes); static int ntfs_attr_truncate_i(ntfs_attr *na, const s64 newsize,
hole_type holes);
/** /**
* ntfs_attr_pwrite - positioned write to an ntfs attribute * ntfs_attr_pwrite - positioned write to an ntfs attribute
@ -1835,7 +1836,8 @@ s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 count, const void *b)
* we avoid sparse testing until the data is filled in. * we avoid sparse testing until the data is filled in.
*/ */
if (ntfs_attr_truncate_i(na, pos + count, if (ntfs_attr_truncate_i(na, pos + count,
!NAttrDataAppending(na))) { (NAttrDataAppending(na) ?
HOLES_DELAY : HOLES_OK))) {
ntfs_log_perror("Failed to enlarge attribute"); ntfs_log_perror("Failed to enlarge attribute");
goto errno_set; goto errno_set;
} }
@ -5364,7 +5366,7 @@ static int ntfs_attr_make_resident(ntfs_attr *na, ntfs_attr_search_ctx *ctx)
* update allocated and compressed size. * update allocated and compressed size.
*/ */
static int ntfs_attr_update_meta(ATTR_RECORD *a, ntfs_attr *na, MFT_RECORD *m, static int ntfs_attr_update_meta(ATTR_RECORD *a, ntfs_attr *na, MFT_RECORD *m,
BOOL holes, ntfs_attr_search_ctx *ctx) hole_type holes, ntfs_attr_search_ctx *ctx)
{ {
int sparse, ret = 0; int sparse, ret = 0;
@ -5377,7 +5379,7 @@ static int ntfs_attr_update_meta(ATTR_RECORD *a, ntfs_attr *na, MFT_RECORD *m,
a->allocated_size = cpu_to_sle64(na->allocated_size); a->allocated_size = cpu_to_sle64(na->allocated_size);
/* Update sparse bit, unless this is an intermediate state */ /* Update sparse bit, unless this is an intermediate state */
if (!holes) if (holes == HOLES_DELAY)
sparse = (a->flags & ATTR_IS_SPARSE) != const_cpu_to_le16(0); sparse = (a->flags & ATTR_IS_SPARSE) != const_cpu_to_le16(0);
else { else {
sparse = ntfs_rl_sparse(na->rl); sparse = ntfs_rl_sparse(na->rl);
@ -5388,7 +5390,7 @@ static int ntfs_attr_update_meta(ATTR_RECORD *a, ntfs_attr *na, MFT_RECORD *m,
} }
/* Check whether attribute becomes sparse, unless check is delayed. */ /* Check whether attribute becomes sparse, unless check is delayed. */
if (holes if ((holes != HOLES_DELAY)
&& sparse && sparse
&& !(a->flags & (ATTR_IS_SPARSE | ATTR_IS_COMPRESSED))) { && !(a->flags & (ATTR_IS_SPARSE | ATTR_IS_COMPRESSED))) {
/* /*
@ -5491,7 +5493,7 @@ error: ret = -3; goto out;
* ntfs_attr_update_mapping_pairs_i - see ntfs_attr_update_mapping_pairs * ntfs_attr_update_mapping_pairs_i - see ntfs_attr_update_mapping_pairs
*/ */
static int ntfs_attr_update_mapping_pairs_i(ntfs_attr *na, VCN from_vcn, static int ntfs_attr_update_mapping_pairs_i(ntfs_attr *na, VCN from_vcn,
BOOL holes) hole_type holes)
{ {
ntfs_attr_search_ctx *ctx; ntfs_attr_search_ctx *ctx;
ntfs_inode *ni, *base_ni; ntfs_inode *ni, *base_ni;
@ -5527,7 +5529,7 @@ retry:
* Same if the file was sparse and is not any more. * Same if the file was sparse and is not any more.
* Note : not needed if the full runlist is to be processed * Note : not needed if the full runlist is to be processed
*/ */
if (holes if ((holes != HOLES_DELAY)
&& (!NAttrFullyMapped(na) || from_vcn) && (!NAttrFullyMapped(na) || from_vcn)
&& !(na->data_flags & ATTR_IS_COMPRESSED)) { && !(na->data_flags & ATTR_IS_COMPRESSED)) {
BOOL changed; BOOL changed;
@ -5929,7 +5931,7 @@ int ntfs_attr_update_mapping_pairs(ntfs_attr *na, VCN from_vcn)
int ret; int ret;
ntfs_log_enter("Entering\n"); ntfs_log_enter("Entering\n");
ret = ntfs_attr_update_mapping_pairs_i(na, from_vcn, TRUE); ret = ntfs_attr_update_mapping_pairs_i(na, from_vcn, HOLES_OK);
ntfs_log_leave("\n"); ntfs_log_leave("\n");
return ret; return ret;
} }
@ -6100,7 +6102,7 @@ put_err_out:
* ENOSPC - There is no enough space in base mft to resize $ATTRIBUTE_LIST. * ENOSPC - There is no enough space in base mft to resize $ATTRIBUTE_LIST.
*/ */
static int ntfs_non_resident_attr_expand_i(ntfs_attr *na, const s64 newsize, static int ntfs_non_resident_attr_expand_i(ntfs_attr *na, const s64 newsize,
BOOL holes) hole_type holes)
{ {
LCN lcn_seek_from; LCN lcn_seek_from;
VCN first_free_vcn; VCN first_free_vcn;
@ -6164,7 +6166,8 @@ static int ntfs_non_resident_attr_expand_i(ntfs_attr *na, const s64 newsize,
* If we extend $DATA attribute on NTFS 3+ volume, we can add * If we extend $DATA attribute on NTFS 3+ volume, we can add
* sparse runs instead of real allocation of clusters. * sparse runs instead of real allocation of clusters.
*/ */
if ((na->type == AT_DATA) && (vol->major_ver >= 3) && holes) { if ((na->type == AT_DATA) && (vol->major_ver >= 3)
&& (holes != HOLES_NO)) {
rl = ntfs_malloc(0x1000); rl = ntfs_malloc(0x1000);
if (!rl) if (!rl)
return -1; return -1;
@ -6325,7 +6328,7 @@ put_err_out:
static int ntfs_non_resident_attr_expand(ntfs_attr *na, const s64 newsize, static int ntfs_non_resident_attr_expand(ntfs_attr *na, const s64 newsize,
BOOL holes) hole_type holes)
{ {
int ret; int ret;
@ -6339,7 +6342,7 @@ static int ntfs_non_resident_attr_expand(ntfs_attr *na, const s64 newsize,
* ntfs_attr_truncate - resize an ntfs attribute * ntfs_attr_truncate - resize an ntfs attribute
* @na: open ntfs attribute to resize * @na: open ntfs attribute to resize
* @newsize: new size (in bytes) to which to resize the attribute * @newsize: new size (in bytes) to which to resize the attribute
* @holes: try creating a hole if expanding * @holes: how to create a hole if expanding
* *
* Change the size of an open ntfs attribute @na to @newsize bytes. If the * Change the size of an open ntfs attribute @na to @newsize bytes. If the
* attribute is made bigger and the attribute is resident the newly * attribute is made bigger and the attribute is resident the newly
@ -6356,7 +6359,8 @@ static int ntfs_non_resident_attr_expand(ntfs_attr *na, const s64 newsize,
* EOPNOTSUPP - The desired resize is not implemented yet. * EOPNOTSUPP - The desired resize is not implemented yet.
* EACCES - Encrypted attribute. * EACCES - Encrypted attribute.
*/ */
static int ntfs_attr_truncate_i(ntfs_attr *na, const s64 newsize, BOOL holes) static int ntfs_attr_truncate_i(ntfs_attr *na, const s64 newsize,
hole_type holes)
{ {
int ret = STATUS_ERROR; int ret = STATUS_ERROR;
s64 fullsize; s64 fullsize;
@ -6438,7 +6442,7 @@ out:
int ntfs_attr_truncate(ntfs_attr *na, const s64 newsize) int ntfs_attr_truncate(ntfs_attr *na, const s64 newsize)
{ {
return (ntfs_attr_truncate_i(na, newsize, TRUE)); return (ntfs_attr_truncate_i(na, newsize, HOLES_OK));
} }
/* /*
@ -6447,7 +6451,7 @@ int ntfs_attr_truncate(ntfs_attr *na, const s64 newsize)
int ntfs_attr_truncate_solid(ntfs_attr *na, const s64 newsize) int ntfs_attr_truncate_solid(ntfs_attr *na, const s64 newsize)
{ {
return (ntfs_attr_truncate_i(na, newsize, FALSE)); return (ntfs_attr_truncate_i(na, newsize, HOLES_NO));
} }
/* /*