Fix hole instantiating and new API ntfs_rl_fill_zero

Thanks to Szaka for finding this bug and idea of factoring out zero filling code.
edge.strict_endians
Yura Pakhuchiy 2007-09-05 16:33:59 +03:00
parent 219d353226
commit 4679daa0af
3 changed files with 56 additions and 53 deletions

View File

@ -56,6 +56,9 @@ extern s64 ntfs_rl_pread(const ntfs_volume *vol, const runlist_element *rl,
extern s64 ntfs_rl_pwrite(const ntfs_volume *vol, const runlist_element *rl,
const s64 pos, s64 count, void *b);
extern int ntfs_rl_fill_zero(const ntfs_volume *vol, const runlist *rl,
s64 pos, const s64 count);
extern runlist_element *ntfs_runlists_merge(runlist_element *drl,
runlist_element *srl);

View File

@ -1119,32 +1119,11 @@ s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 count, const void *b)
0, NULL, 0, ctx))
goto err_out;
/* If write starts beyond initialized_size, zero the gap. */
if (pos > na->initialized_size) {
char *buf;
if (pos > na->initialized_size && ntfs_rl_fill_zero(vol,
na->rl, na->initialized_size,
pos - na->initialized_size))
goto err_out;
buf = ntfs_malloc(NTFS_BUF_SIZE);
if (!buf)
goto err_out;
memset(buf, 0, NTFS_BUF_SIZE);
ofs = na->initialized_size;
while (ofs < pos) {
to_write = min(pos - ofs, NTFS_BUF_SIZE);
written = ntfs_rl_pwrite(vol, na->rl, ofs,
to_write, buf);
if (written <= 0) {
int err = errno;
ntfs_log_trace("Failed to zero space "
"between initialized "
"size and @pos.\n");
free(buf);
errno = err;
goto err_out;
}
ofs += written;
}
free(buf);
}
ctx->attr->initialized_size = cpu_to_sle64(pos + count);
if (ntfs_mft_record_write(vol, ctx->ntfs_ino->mft_no,
ctx->mrec)) {
@ -1321,34 +1300,6 @@ s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 count, const void *b)
errno = EIO;
goto err_out;
}
if (ofs) {
/*
* Need to clear region between start of
* @cur_vcn cluster and @ofs.
*/
char *buf;
buf = malloc(ofs);
if (!buf) {
ntfs_log_trace("Not enough memory to "
"allocate %lld "
"bytes.\n", ofs);
errno = ENOMEM;
goto err_out;
}
memset(buf, 0, ofs);
if (ntfs_rl_pwrite(vol, na->rl, cur_vcn <<
vol->cluster_size_bits,
ofs, buf) < 0) {
eo = errno;
ntfs_log_trace("Failed to zero "
"area.\n");
free(buf);
errno = eo;
goto err_out;
}
free(buf);
}
if (rl->vcn < cur_vcn) {
/*
* Clusters that replaced hole are merged with
@ -1365,6 +1316,13 @@ s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 count, const void *b)
ofs -= (rl->vcn - cur_vcn) <<
vol->cluster_size_bits;
}
/*
* Clear region between start of @rl->vcn cluster and
* @ofs if necessary.
*/
if (ofs && ntfs_rl_fill_zero(vol, na->rl, rl->vcn <<
vol->cluster_size_bits, ofs))
goto err_out;
}
/* It is a real lcn, write it to the volume. */
to_write = min(count, (rl->length << vol->cluster_size_bits) -

View File

@ -1208,6 +1208,48 @@ rl_err_out:
return -1;
}
/**
* ntfs_rl_fill_zero - fill given region with zeroes
* @vol: ntfs volume to write to
* @rl: runlist specifying where to write zeroes to
* @pos: byte position within runlist @rl at which to begin the zeroing
* @count: number of bytes to fill with zeros
*
* Return 0 on success and -1 on error with errno set to the error code.
*/
int ntfs_rl_fill_zero(const ntfs_volume *vol, const runlist *rl, s64 pos,
const s64 count)
{
char *buf;
s64 written, size, end = pos + count;
int ret = 0;
ntfs_log_trace("pos %lld, count %lld\n", (long long)pos,
(long long)count);
if (!vol || !rl || pos < 0 || count < 0) {
errno = EINVAL;
return -1;
}
buf = ntfs_calloc(NTFS_BUF_SIZE);
if (!buf)
return -1;
while (pos < end) {
size = min(end - pos, NTFS_BUF_SIZE);
written = ntfs_rl_pwrite(vol, rl, pos, size, buf);
if (written <= 0) {
ntfs_log_perror("Failed to zero space");
ret = -1;
break;
}
pos += written;
}
free(buf);
return ret;
}
/**
* ntfs_get_nr_significant_bytes - get number of bytes needed to store a number
* @n: number for which to get the number of bytes for