mirror of
https://git.code.sf.net/p/ntfs-3g/ntfs-3g.git
synced 2024-11-27 12:03:42 +08:00
We do not need to map whole runlist in this case, only until @pos. Introduce ntfs_attr_map_runlist_range to implement this.
This commit is contained in:
parent
e404ce8203
commit
b99d331f78
@ -279,6 +279,7 @@ extern s64 ntfs_attr_mst_pwrite(ntfs_attr *na, const s64 pos,
|
|||||||
s64 bk_cnt, const u32 bk_size, void *src);
|
s64 bk_cnt, const u32 bk_size, void *src);
|
||||||
|
|
||||||
extern int ntfs_attr_map_runlist(ntfs_attr *na, VCN vcn);
|
extern int ntfs_attr_map_runlist(ntfs_attr *na, VCN vcn);
|
||||||
|
extern int ntfs_attr_map_runlist_range(ntfs_attr *na, VCN from_vcn, VCN to_vcn);
|
||||||
extern int ntfs_attr_map_whole_runlist(ntfs_attr *na);
|
extern int ntfs_attr_map_whole_runlist(ntfs_attr *na);
|
||||||
|
|
||||||
extern LCN ntfs_attr_vcn_to_lcn(ntfs_attr *na, const VCN vcn);
|
extern LCN ntfs_attr_vcn_to_lcn(ntfs_attr *na, const VCN vcn);
|
||||||
|
@ -459,7 +459,7 @@ void ntfs_attr_close(ntfs_attr *na)
|
|||||||
* @na: ntfs attribute for which to map (part of) a runlist
|
* @na: ntfs attribute for which to map (part of) a runlist
|
||||||
* @vcn: map runlist part containing this vcn
|
* @vcn: map runlist part containing this vcn
|
||||||
*
|
*
|
||||||
* Map the part of a runlist containing the @vcn of an the ntfs attribute @na.
|
* Map the part of a runlist containing the @vcn of the ntfs attribute @na.
|
||||||
*
|
*
|
||||||
* Return 0 on success and -1 on error with errno set to the error code.
|
* Return 0 on success and -1 on error with errno set to the error code.
|
||||||
*/
|
*/
|
||||||
@ -467,7 +467,6 @@ int ntfs_attr_map_runlist(ntfs_attr *na, VCN vcn)
|
|||||||
{
|
{
|
||||||
LCN lcn;
|
LCN lcn;
|
||||||
ntfs_attr_search_ctx *ctx;
|
ntfs_attr_search_ctx *ctx;
|
||||||
int err;
|
|
||||||
|
|
||||||
ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, vcn 0x%llx.\n",
|
ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, vcn 0x%llx.\n",
|
||||||
(unsigned long long)na->ni->mft_no, na->type, (long long)vcn);
|
(unsigned long long)na->ni->mft_no, na->type, (long long)vcn);
|
||||||
@ -490,14 +489,84 @@ int ntfs_attr_map_runlist(ntfs_attr *na, VCN vcn)
|
|||||||
na->rl);
|
na->rl);
|
||||||
if (rl) {
|
if (rl) {
|
||||||
na->rl = rl;
|
na->rl = rl;
|
||||||
|
|
||||||
ntfs_attr_put_search_ctx(ctx);
|
ntfs_attr_put_search_ctx(ctx);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err = errno;
|
|
||||||
ntfs_attr_put_search_ctx(ctx);
|
ntfs_attr_put_search_ctx(ctx);
|
||||||
errno = err;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ntfs_attr_map_runlist_range - map (a part of) a runlist of an ntfs attribute
|
||||||
|
* @na: ntfs attribute for which to map (part of) a runlist
|
||||||
|
* @from_vcn: map runlist part starting this vcn
|
||||||
|
* @to_vcn: map runlist part ending this vcn
|
||||||
|
*
|
||||||
|
* Map the part of a runlist from containing the @from_vcn to containing the
|
||||||
|
* @to_vcn of an ntfs attribute @na. It is OK for @to_vcn to be beyond last run.
|
||||||
|
*
|
||||||
|
* Return 0 on success and -1 on error with errno set to the error code.
|
||||||
|
*/
|
||||||
|
int ntfs_attr_map_runlist_range(ntfs_attr *na, VCN from_vcn, VCN to_vcn)
|
||||||
|
{
|
||||||
|
ntfs_attr_search_ctx *ctx = NULL;
|
||||||
|
runlist *rl;
|
||||||
|
|
||||||
|
ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, "
|
||||||
|
"from_vcn 0x%llx, to_vcn 0x%llx.\n",
|
||||||
|
(unsigned long long)na->ni->mft_no, na->type,
|
||||||
|
(long long)from_vcn, (long long)to_vcn);
|
||||||
|
|
||||||
|
/* Map extent with @from_vcn. */
|
||||||
|
if (ntfs_attr_map_runlist(na, from_vcn))
|
||||||
|
goto err_out;
|
||||||
|
|
||||||
|
for (rl = na->rl; rl->vcn <= to_vcn;) {
|
||||||
|
/* Skip not interesting to us runs. */
|
||||||
|
if (rl->lcn >= 0 || rl->lcn == LCN_HOLE || (rl->vcn +
|
||||||
|
rl->length < from_vcn &&
|
||||||
|
rl->lcn == LCN_RL_NOT_MAPPED)) {
|
||||||
|
rl++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We reached the end of runlist, just exit. */
|
||||||
|
if (rl->lcn == LCN_ENOENT)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Check for errors. */
|
||||||
|
if (rl->lcn < 0 && rl->lcn != LCN_RL_NOT_MAPPED) {
|
||||||
|
errno = EIO;
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Runlist is not mapped here. */
|
||||||
|
if (!ctx) {
|
||||||
|
ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
|
||||||
|
if (!ctx)
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
|
/* Find the attribute in the mft record. */
|
||||||
|
if (ntfs_attr_lookup(na->type, na->name, na->name_len,
|
||||||
|
CASE_SENSITIVE, rl->vcn, NULL, 0,
|
||||||
|
ctx))
|
||||||
|
goto err_out;
|
||||||
|
|
||||||
|
/* Decode the runlist. */
|
||||||
|
rl = ntfs_mapping_pairs_decompress(na->ni->vol, ctx->attr,
|
||||||
|
na->rl);
|
||||||
|
if (!rl)
|
||||||
|
goto err_out;
|
||||||
|
na->rl = rl;
|
||||||
|
}
|
||||||
|
|
||||||
|
ntfs_attr_put_search_ctx(ctx);
|
||||||
|
ntfs_log_trace("Done.\n");
|
||||||
|
return 0;
|
||||||
|
err_out:
|
||||||
|
ntfs_attr_put_search_ctx(ctx);
|
||||||
|
ntfs_log_trace("Failed.\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -505,8 +574,8 @@ int ntfs_attr_map_runlist(ntfs_attr *na, VCN vcn)
|
|||||||
* ntfs_attr_map_whole_runlist - map the whole runlist of an ntfs attribute
|
* ntfs_attr_map_whole_runlist - map the whole runlist of an ntfs attribute
|
||||||
* @na: ntfs attribute for which to map the runlist
|
* @na: ntfs attribute for which to map the runlist
|
||||||
*
|
*
|
||||||
* Map the whole runlist of an the ntfs attribute @na. For an attribute made
|
* Map the whole runlist of the ntfs attribute @na. For an attribute made up
|
||||||
* up of only one attribute extent this is the same as calling
|
* of only one attribute extent this is the same as calling
|
||||||
* ntfs_attr_map_runlist(na, 0) but for an attribute with multiple extents this
|
* ntfs_attr_map_runlist(na, 0) but for an attribute with multiple extents this
|
||||||
* will map the runlist fragments from each of the extents thus giving access
|
* will map the runlist fragments from each of the extents thus giving access
|
||||||
* to the entirety of the disk allocation of an attribute.
|
* to the entirety of the disk allocation of an attribute.
|
||||||
@ -1030,7 +1099,13 @@ s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 count, const void *b)
|
|||||||
total = 0;
|
total = 0;
|
||||||
/* Handle writes beyond initialized_size. */
|
/* Handle writes beyond initialized_size. */
|
||||||
if (pos + count > na->initialized_size) {
|
if (pos + count > na->initialized_size) {
|
||||||
if (ntfs_attr_map_whole_runlist(na))
|
/*
|
||||||
|
* Map runlist between initialized size and place we start
|
||||||
|
* writing at.
|
||||||
|
*/
|
||||||
|
if (ntfs_attr_map_runlist_range(na, na->initialized_size >>
|
||||||
|
vol->cluster_size_bits,
|
||||||
|
pos >> vol->cluster_size_bits))
|
||||||
goto err_out;
|
goto err_out;
|
||||||
/* Set initialized_size to @pos + @count. */
|
/* Set initialized_size to @pos + @count. */
|
||||||
ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
|
ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
|
||||||
@ -2301,7 +2376,8 @@ ntfs_attr_search_ctx *ntfs_attr_get_search_ctx(ntfs_inode *ni, MFT_RECORD *mrec)
|
|||||||
* ntfs_attr_put_search_ctx - release an attribute search context
|
* ntfs_attr_put_search_ctx - release an attribute search context
|
||||||
* @ctx: attribute search context to free
|
* @ctx: attribute search context to free
|
||||||
*
|
*
|
||||||
* Release the attribute search context @ctx.
|
* Release the attribute search context @ctx. This function does not change
|
||||||
|
* errno and doing nothing if NULL passed to it.
|
||||||
*/
|
*/
|
||||||
void ntfs_attr_put_search_ctx(ntfs_attr_search_ctx *ctx)
|
void ntfs_attr_put_search_ctx(ntfs_attr_search_ctx *ctx)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user