898
static int ntfs_attr_fill_hole(ntfs_attr *na, s64 count, s64 *ofs,
899
runlist_element **rl, VCN *update_from)
902
ntfs_volume *vol = na->ni->vol;
905
LCN lcn_seek_from = -1;
906
VCN cur_vcn, from_vcn;
908
to_write = min(count, ((*rl)->length << vol->cluster_size_bits) - *ofs);
910
/* Instantiate the hole. */
911
cur_vcn = (*rl)->vcn;
912
from_vcn = (*rl)->vcn + (*ofs >> vol->cluster_size_bits);
913
ntfs_log_trace("Instantiate the hole with vcn 0x%llx.\n", cur_vcn);
915
* Map whole runlist to be able update mapping pairs
918
if (ntfs_attr_map_whole_runlist(na))
921
* Restore @*rl, it probably get lost during runlist
924
*rl = ntfs_attr_find_vcn(na, cur_vcn);
926
ntfs_log_error("Failed to find run after mapping runlist. "
927
"Please report to %s.\n", NTFS_DEV_LIST);
932
* Search backwards to find the best lcn to start
939
lcn_seek_from = rlc->lcn + (from_vcn - rlc->vcn);
943
if (lcn_seek_from == -1) {
944
/* Backwards search failed, search forwards. */
946
while (rlc->length) {
949
lcn_seek_from = rlc->lcn - (rlc->vcn - from_vcn);
954
/* Allocate clusters to instantiate the hole. */
955
rlc = ntfs_cluster_alloc(vol, from_vcn,
956
((*ofs + to_write - 1) >> vol->cluster_size_bits)
957
+ 1 + (*rl)->vcn - from_vcn,
958
lcn_seek_from, DATA_ZONE);
960
ntfs_log_perror("Hole filling cluster allocation failed");
963
/* Merge runlists. */
964
*rl = ntfs_runlists_merge(na->rl, rlc);
967
ntfs_log_perror("Failed to merge runlists");
968
if (ntfs_cluster_free_from_rl(vol, rlc)) {
969
ntfs_log_perror("Failed to free hot clusters. "
970
"Please run chkdsk /f");
976
if (*update_from == -1)
977
*update_from = from_vcn;
978
*rl = ntfs_attr_find_vcn(na, cur_vcn);
981
* It's definitely a BUG, if we failed to find @cur_vcn, because
982
* we missed it during instantiating of the hole.
984
ntfs_log_error("Failed to find run after hole instantiation. "
985
"Please report to %s.\n", NTFS_DEV_LIST);
989
/* If leaved part of the hole go to the next run. */
992
/* Now LCN shoudn't be less than 0. */
993
if ((*rl)->lcn < 0) {
994
ntfs_log_error("BUG! LCN is lesser than 0. "
995
"Please report to the %s.\n", NTFS_DEV_LIST);
1001
* Need to clear region between start of
1002
* @cur_vcn cluster and @*ofs.
1006
buf = ntfs_malloc(*ofs);
1010
memset(buf, 0, *ofs);
1011
if (ntfs_rl_pwrite(vol, na->rl, cur_vcn << vol->cluster_size_bits,
1013
ntfs_log_perror("Failed to zero area");
1019
if ((*rl)->vcn < cur_vcn) {
1021
* Clusters that replaced hole are merged with
1022
* previous run, so we need to update offset.
1024
*ofs += (cur_vcn - (*rl)->vcn) << vol->cluster_size_bits;
1026
if ((*rl)->vcn > cur_vcn) {
1028
* We left part of the hole, so we need to update offset
1030
*ofs -= ((*rl)->vcn - cur_vcn) << vol->cluster_size_bits;
900
1039
* ntfs_attr_pwrite - positioned write to an ntfs attribute
901
1040
* @na: ntfs attribute to write to
951
1090
// return ntfs_attr_pwrite_compressed(ntfs_attr *na,
952
1091
// const s64 pos, s64 count, void *b);
953
1092
errno = EOPNOTSUPP;
956
1095
/* Update access and change times if needed. */
957
1096
if (na->type == AT_DATA || na->type == AT_INDEX_ROOT ||
958
1097
na->type == AT_INDEX_ALLOCATION)
959
1098
ntfs_inode_update_time(na->ni);
962
1101
/* If the write reaches beyond the end, extend the attribute. */
963
1102
old_data_size = na->data_size;
964
1103
if (pos + count > na->data_size) {
965
1104
if (ntfs_attr_truncate(na, pos + count)) {
966
1105
ntfs_log_perror("Failed to enlarge attribute");
969
1108
need_to.undo_data_size = 1;
1096
1236
goto rl_err_out;
1098
1238
if (rl->lcn < (LCN)0) {
1099
LCN lcn_seek_from = -1;
1101
VCN cur_vcn, from_vcn;
1103
1240
if (rl->lcn != (LCN)LCN_HOLE) {
1105
1242
goto rl_err_out;
1108
to_write = min(count, (rl->length <<
1109
vol->cluster_size_bits) - ofs);
1111
/* Instantiate the hole. */
1113
from_vcn = rl->vcn + (ofs >> vol->cluster_size_bits);
1114
ntfs_log_trace("Instantiate the hole with vcn 0x%llx.\n",
1117
* Map whole runlist to be able update mapping pairs
1120
if (ntfs_attr_map_whole_runlist(na))
1123
* Restore @rl, it probably get lost during runlist
1126
rl = ntfs_attr_find_vcn(na, cur_vcn);
1128
ntfs_log_error("BUG! Failed to find run after "
1129
"mapping whole runlist. Please "
1130
"report to the %s.\n",
1136
* Search backwards to find the best lcn to start
1142
if (rlc->lcn >= 0) {
1143
lcn_seek_from = rlc->lcn +
1144
(from_vcn - rlc->vcn);
1148
if (lcn_seek_from == -1) {
1149
/* Backwards search failed, search forwards. */
1151
while (rlc->length) {
1153
if (rlc->lcn >= 0) {
1154
lcn_seek_from = rlc->lcn -
1155
(rlc->vcn - from_vcn);
1160
/* Allocate clusters to instantiate the hole. */
1161
rlc = ntfs_cluster_alloc(vol, from_vcn,
1162
((ofs + to_write - 1) >>
1163
vol->cluster_size_bits) + 1 +
1165
lcn_seek_from, DATA_ZONE);
1167
ntfs_log_perror("Failed to allocate clusters "
1168
"for hole instantiating");
1171
/* Merge runlists. */
1172
rl = ntfs_runlists_merge(na->rl, rlc);
1175
ntfs_log_perror("Failed to merge runlists");
1176
if (ntfs_cluster_free_from_rl(vol, rlc)) {
1177
ntfs_log_perror("Failed to free hot "
1178
"clusters. Please run "
1185
need_to.update_mapping_pairs = 1;
1186
if (update_from == -1)
1187
update_from = from_vcn;
1188
rl = ntfs_attr_find_vcn(na, cur_vcn);
1191
* It's definitely a BUG, if we failed to find
1192
* @cur_vcn, because we missed it during
1193
* instantiating of the hole.
1195
ntfs_log_error("BUG! Failed to find run after "
1196
"instantiating. Please report "
1197
"to the %s.\n", NTFS_DEV_LIST);
1201
/* If leaved part of the hole go to the next run. */
1204
/* Now LCN shoudn't be less than 0. */
1206
ntfs_log_error("BUG! LCN is lesser than 0. "
1207
"Please report to the %s.\n",
1214
* Need to clear region between start of
1215
* @cur_vcn cluster and @ofs.
1219
buf = ntfs_malloc(ofs);
1223
memset(buf, 0, ofs);
1224
if (ntfs_rl_pwrite(vol, na->rl, cur_vcn <<
1225
vol->cluster_size_bits,
1227
ntfs_log_perror("Failed to zero area");
1233
if (rl->vcn < cur_vcn) {
1235
* Clusters that replaced hole are merged with
1236
* previous run, so we need to update offset.
1238
ofs += (cur_vcn - rl->vcn) <<
1239
vol->cluster_size_bits;
1241
if (rl->vcn > cur_vcn) {
1243
* We left part of the hole, so update we need
1246
ofs -= (rl->vcn - cur_vcn) <<
1247
vol->cluster_size_bits;
1245
if (ntfs_attr_fill_hole(na, count, &ofs, &rl, &update_from))
1250
1248
/* It is a real lcn, write it to the volume. */
1251
to_write = min(count, (rl->length << vol->cluster_size_bits) -
1249
to_write = min(count, (rl->length << vol->cluster_size_bits) - ofs);
1254
ntfs_log_trace("Writing 0x%llx bytes to vcn 0x%llx, lcn 0x%llx,"
1255
" ofs 0x%llx.\n", to_write, rl->vcn, rl->lcn,
1251
ntfs_log_trace("Writing %lld bytes to vcn %lld, lcn %lld, ofs "
1252
"%lld.\n", to_write, rl->vcn, rl->lcn, ofs);
1257
1253
if (!NVolReadOnly(vol))
1258
1254
written = ntfs_pwrite(vol->dev, (rl->lcn <<
1259
1255
vol->cluster_size_bits) + ofs,