aboutsummaryrefslogtreecommitdiffstats
path: root/fs/udf/truncate.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/udf/truncate.c')
-rw-r--r--fs/udf/truncate.c209
1 files changed, 121 insertions, 88 deletions
diff --git a/fs/udf/truncate.c b/fs/udf/truncate.c
index 60d277644248..b2002da0a5c0 100644
--- a/fs/udf/truncate.c
+++ b/fs/udf/truncate.c
@@ -28,35 +28,38 @@
28#include "udf_i.h" 28#include "udf_i.h"
29#include "udf_sb.h" 29#include "udf_sb.h"
30 30
31static void extent_trunc(struct inode * inode, struct extent_position *epos, 31static void extent_trunc(struct inode *inode, struct extent_position *epos,
32 kernel_lb_addr eloc, int8_t etype, uint32_t elen, uint32_t nelen) 32 kernel_lb_addr eloc, int8_t etype, uint32_t elen,
33 uint32_t nelen)
33{ 34{
34 kernel_lb_addr neloc = { 0, 0 }; 35 kernel_lb_addr neloc = { 0, 0 };
35 int last_block = (elen + inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits; 36 int last_block =
36 int first_block = (nelen + inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits; 37 (elen + inode->i_sb->s_blocksize -
38 1) >> inode->i_sb->s_blocksize_bits;
39 int first_block =
40 (nelen + inode->i_sb->s_blocksize -
41 1) >> inode->i_sb->s_blocksize_bits;
37 42
38 if (nelen) 43 if (nelen) {
39 { 44 if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30)) {
40 if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30)) 45 udf_free_blocks(inode->i_sb, inode, eloc, 0,
41 { 46 last_block);
42 udf_free_blocks(inode->i_sb, inode, eloc, 0, last_block);
43 etype = (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30); 47 etype = (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30);
44 } 48 } else
45 else
46 neloc = eloc; 49 neloc = eloc;
47 nelen = (etype << 30) | nelen; 50 nelen = (etype << 30) | nelen;
48 } 51 }
49 52
50 if (elen != nelen) 53 if (elen != nelen) {
51 {
52 udf_write_aext(inode, epos, neloc, nelen, 0); 54 udf_write_aext(inode, epos, neloc, nelen, 0);
53 if (last_block - first_block > 0) 55 if (last_block - first_block > 0) {
54 {
55 if (etype == (EXT_RECORDED_ALLOCATED >> 30)) 56 if (etype == (EXT_RECORDED_ALLOCATED >> 30))
56 mark_inode_dirty(inode); 57 mark_inode_dirty(inode);
57 58
58 if (etype != (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30)) 59 if (etype != (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))
59 udf_free_blocks(inode->i_sb, inode, eloc, first_block, last_block - first_block); 60 udf_free_blocks(inode->i_sb, inode, eloc,
61 first_block,
62 last_block - first_block);
60 } 63 }
61 } 64 }
62} 65}
@@ -67,7 +70,7 @@ static void extent_trunc(struct inode * inode, struct extent_position *epos,
67 */ 70 */
68void udf_truncate_tail_extent(struct inode *inode) 71void udf_truncate_tail_extent(struct inode *inode)
69{ 72{
70 struct extent_position epos = { NULL, 0, {0, 0}}; 73 struct extent_position epos = { NULL, 0, {0, 0} };
71 kernel_lb_addr eloc; 74 kernel_lb_addr eloc;
72 uint32_t elen, nelen; 75 uint32_t elen, nelen;
73 uint64_t lbcount = 0; 76 uint64_t lbcount = 0;
@@ -89,8 +92,7 @@ void udf_truncate_tail_extent(struct inode *inode)
89 BUG(); 92 BUG();
90 93
91 /* Find the last extent in the file */ 94 /* Find the last extent in the file */
92 while ((netype = udf_next_aext(inode, &epos, &eloc, &elen, 1)) != -1) 95 while ((netype = udf_next_aext(inode, &epos, &eloc, &elen, 1)) != -1) {
93 {
94 etype = netype; 96 etype = netype;
95 lbcount += elen; 97 lbcount += elen;
96 if (lbcount > inode->i_size) { 98 if (lbcount > inode->i_size) {
@@ -123,7 +125,7 @@ void udf_truncate_tail_extent(struct inode *inode)
123 125
124void udf_discard_prealloc(struct inode *inode) 126void udf_discard_prealloc(struct inode *inode)
125{ 127{
126 struct extent_position epos = { NULL, 0, {0, 0}}; 128 struct extent_position epos = { NULL, 0, {0, 0} };
127 kernel_lb_addr eloc; 129 kernel_lb_addr eloc;
128 uint32_t elen; 130 uint32_t elen;
129 uint64_t lbcount = 0; 131 uint64_t lbcount = 0;
@@ -131,7 +133,7 @@ void udf_discard_prealloc(struct inode *inode)
131 int adsize; 133 int adsize;
132 134
133 if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB || 135 if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB ||
134 inode->i_size == UDF_I_LENEXTENTS(inode)) 136 inode->i_size == UDF_I_LENEXTENTS(inode))
135 return; 137 return;
136 138
137 if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT) 139 if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
@@ -153,15 +155,21 @@ void udf_discard_prealloc(struct inode *inode)
153 lbcount -= elen; 155 lbcount -= elen;
154 extent_trunc(inode, &epos, eloc, etype, elen, 0); 156 extent_trunc(inode, &epos, eloc, etype, elen, 0);
155 if (!epos.bh) { 157 if (!epos.bh) {
156 UDF_I_LENALLOC(inode) = epos.offset - udf_file_entry_alloc_offset(inode); 158 UDF_I_LENALLOC(inode) =
159 epos.offset - udf_file_entry_alloc_offset(inode);
157 mark_inode_dirty(inode); 160 mark_inode_dirty(inode);
158 } else { 161 } else {
159 struct allocExtDesc *aed = (struct allocExtDesc *)(epos.bh->b_data); 162 struct allocExtDesc *aed =
160 aed->lengthAllocDescs = cpu_to_le32(epos.offset - sizeof(struct allocExtDesc)); 163 (struct allocExtDesc *)(epos.bh->b_data);
161 if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201) 164 aed->lengthAllocDescs =
165 cpu_to_le32(epos.offset -
166 sizeof(struct allocExtDesc));
167 if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT)
168 || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
162 udf_update_tag(epos.bh->b_data, epos.offset); 169 udf_update_tag(epos.bh->b_data, epos.offset);
163 else 170 else
164 udf_update_tag(epos.bh->b_data, sizeof(struct allocExtDesc)); 171 udf_update_tag(epos.bh->b_data,
172 sizeof(struct allocExtDesc));
165 mark_buffer_dirty_inode(epos.bh, inode); 173 mark_buffer_dirty_inode(epos.bh, inode);
166 } 174 }
167 } 175 }
@@ -171,7 +179,7 @@ void udf_discard_prealloc(struct inode *inode)
171 brelse(epos.bh); 179 brelse(epos.bh);
172} 180}
173 181
174void udf_truncate_extents(struct inode * inode) 182void udf_truncate_extents(struct inode *inode)
175{ 183{
176 struct extent_position epos; 184 struct extent_position epos;
177 kernel_lb_addr eloc, neloc = { 0, 0 }; 185 kernel_lb_addr eloc, neloc = { 0, 0 };
@@ -190,9 +198,10 @@ void udf_truncate_extents(struct inode * inode)
190 BUG(); 198 BUG();
191 199
192 etype = inode_bmap(inode, first_block, &epos, &eloc, &elen, &offset); 200 etype = inode_bmap(inode, first_block, &epos, &eloc, &elen, &offset);
193 byte_offset = (offset << sb->s_blocksize_bits) + (inode->i_size & (sb->s_blocksize-1)); 201 byte_offset =
194 if (etype != -1) 202 (offset << sb->s_blocksize_bits) +
195 { 203 (inode->i_size & (sb->s_blocksize - 1));
204 if (etype != -1) {
196 epos.offset -= adsize; 205 epos.offset -= adsize;
197 extent_trunc(inode, &epos, eloc, etype, elen, byte_offset); 206 extent_trunc(inode, &epos, eloc, etype, elen, byte_offset);
198 epos.offset += adsize; 207 epos.offset += adsize;
@@ -206,86 +215,98 @@ void udf_truncate_extents(struct inode * inode)
206 else 215 else
207 lenalloc -= sizeof(struct allocExtDesc); 216 lenalloc -= sizeof(struct allocExtDesc);
208 217
209 while ((etype = udf_current_aext(inode, &epos, &eloc, &elen, 0)) != -1) 218 while ((etype =
210 { 219 udf_current_aext(inode, &epos, &eloc, &elen,
211 if (etype == (EXT_NEXT_EXTENT_ALLOCDECS >> 30)) 220 0)) != -1) {
212 { 221 if (etype == (EXT_NEXT_EXTENT_ALLOCDECS >> 30)) {
213 udf_write_aext(inode, &epos, neloc, nelen, 0); 222 udf_write_aext(inode, &epos, neloc, nelen, 0);
214 if (indirect_ext_len) 223 if (indirect_ext_len) {
215 {
216 /* We managed to free all extents in the 224 /* We managed to free all extents in the
217 * indirect extent - free it too */ 225 * indirect extent - free it too */
218 if (!epos.bh) 226 if (!epos.bh)
219 BUG(); 227 BUG();
220 udf_free_blocks(sb, inode, epos.block, 0, indirect_ext_len); 228 udf_free_blocks(sb, inode, epos.block,
221 } 229 0, indirect_ext_len);
222 else 230 } else {
223 { 231 if (!epos.bh) {
224 if (!epos.bh) 232 UDF_I_LENALLOC(inode) =
225 { 233 lenalloc;
226 UDF_I_LENALLOC(inode) = lenalloc;
227 mark_inode_dirty(inode); 234 mark_inode_dirty(inode);
228 } 235 } else {
229 else 236 struct allocExtDesc *aed =
230 { 237 (struct allocExtDesc
231 struct allocExtDesc *aed = (struct allocExtDesc *)(epos.bh->b_data); 238 *)(epos.bh->b_data);
232 aed->lengthAllocDescs = cpu_to_le32(lenalloc); 239 aed->lengthAllocDescs =
233 if (!UDF_QUERY_FLAG(sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(sb) >= 0x0201) 240 cpu_to_le32(lenalloc);
234 udf_update_tag(epos.bh->b_data, lenalloc + 241 if (!UDF_QUERY_FLAG
235 sizeof(struct allocExtDesc)); 242 (sb, UDF_FLAG_STRICT)
243 || UDF_SB_UDFREV(sb) >=
244 0x0201)
245 udf_update_tag(epos.bh->
246 b_data,
247 lenalloc
248 +
249 sizeof
250 (struct
251 allocExtDesc));
236 else 252 else
237 udf_update_tag(epos.bh->b_data, sizeof(struct allocExtDesc)); 253 udf_update_tag(epos.bh->
238 mark_buffer_dirty_inode(epos.bh, inode); 254 b_data,
255 sizeof
256 (struct
257 allocExtDesc));
258 mark_buffer_dirty_inode(epos.bh,
259 inode);
239 } 260 }
240 } 261 }
241 brelse(epos.bh); 262 brelse(epos.bh);
242 epos.offset = sizeof(struct allocExtDesc); 263 epos.offset = sizeof(struct allocExtDesc);
243 epos.block = eloc; 264 epos.block = eloc;
244 epos.bh = udf_tread(sb, udf_get_lb_pblock(sb, eloc, 0)); 265 epos.bh =
266 udf_tread(sb,
267 udf_get_lb_pblock(sb, eloc, 0));
245 if (elen) 268 if (elen)
246 indirect_ext_len = (elen + 269 indirect_ext_len = (elen +
247 sb->s_blocksize - 1) >> 270 sb->s_blocksize -
248 sb->s_blocksize_bits; 271 1) >> sb->
272 s_blocksize_bits;
249 else 273 else
250 indirect_ext_len = 1; 274 indirect_ext_len = 1;
251 } 275 } else {
252 else 276 extent_trunc(inode, &epos, eloc, etype, elen,
253 { 277 0);
254 extent_trunc(inode, &epos, eloc, etype, elen, 0);
255 epos.offset += adsize; 278 epos.offset += adsize;
256 } 279 }
257 } 280 }
258 281
259 if (indirect_ext_len) 282 if (indirect_ext_len) {
260 {
261 if (!epos.bh) 283 if (!epos.bh)
262 BUG(); 284 BUG();
263 udf_free_blocks(sb, inode, epos.block, 0, indirect_ext_len); 285 udf_free_blocks(sb, inode, epos.block, 0,
264 } 286 indirect_ext_len);
265 else 287 } else {
266 { 288 if (!epos.bh) {
267 if (!epos.bh)
268 {
269 UDF_I_LENALLOC(inode) = lenalloc; 289 UDF_I_LENALLOC(inode) = lenalloc;
270 mark_inode_dirty(inode); 290 mark_inode_dirty(inode);
271 } 291 } else {
272 else 292 struct allocExtDesc *aed =
273 { 293 (struct allocExtDesc *)(epos.bh->b_data);
274 struct allocExtDesc *aed = (struct allocExtDesc *)(epos.bh->b_data);
275 aed->lengthAllocDescs = cpu_to_le32(lenalloc); 294 aed->lengthAllocDescs = cpu_to_le32(lenalloc);
276 if (!UDF_QUERY_FLAG(sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(sb) >= 0x0201) 295 if (!UDF_QUERY_FLAG(sb, UDF_FLAG_STRICT)
277 udf_update_tag(epos.bh->b_data, lenalloc + 296 || UDF_SB_UDFREV(sb) >= 0x0201)
278 sizeof(struct allocExtDesc)); 297 udf_update_tag(epos.bh->b_data,
298 lenalloc +
299 sizeof(struct
300 allocExtDesc));
279 else 301 else
280 udf_update_tag(epos.bh->b_data, sizeof(struct allocExtDesc)); 302 udf_update_tag(epos.bh->b_data,
303 sizeof(struct
304 allocExtDesc));
281 mark_buffer_dirty_inode(epos.bh, inode); 305 mark_buffer_dirty_inode(epos.bh, inode);
282 } 306 }
283 } 307 }
284 } 308 } else if (inode->i_size) {
285 else if (inode->i_size) 309 if (byte_offset) {
286 {
287 if (byte_offset)
288 {
289 kernel_long_ad extent; 310 kernel_long_ad extent;
290 311
291 /* 312 /*
@@ -293,21 +314,33 @@ void udf_truncate_extents(struct inode * inode)
293 * no extent above inode->i_size => truncate is 314 * no extent above inode->i_size => truncate is
294 * extending the file by 'offset' blocks. 315 * extending the file by 'offset' blocks.
295 */ 316 */
296 if ((!epos.bh && epos.offset == udf_file_entry_alloc_offset(inode)) || 317 if ((!epos.bh
297 (epos.bh && epos.offset == sizeof(struct allocExtDesc))) { 318 && epos.offset ==
319 udf_file_entry_alloc_offset(inode)) || (epos.bh
320 && epos.
321 offset ==
322 sizeof
323 (struct
324 allocExtDesc)))
325 {
298 /* File has no extents at all or has empty last 326 /* File has no extents at all or has empty last
299 * indirect extent! Create a fake extent... */ 327 * indirect extent! Create a fake extent... */
300 extent.extLocation.logicalBlockNum = 0; 328 extent.extLocation.logicalBlockNum = 0;
301 extent.extLocation.partitionReferenceNum = 0; 329 extent.extLocation.partitionReferenceNum = 0;
302 extent.extLength = EXT_NOT_RECORDED_NOT_ALLOCATED; 330 extent.extLength =
303 } 331 EXT_NOT_RECORDED_NOT_ALLOCATED;
304 else { 332 } else {
305 epos.offset -= adsize; 333 epos.offset -= adsize;
306 etype = udf_next_aext(inode, &epos, 334 etype = udf_next_aext(inode, &epos,
307 &extent.extLocation, &extent.extLength, 0); 335 &extent.extLocation,
336 &extent.extLength, 0);
308 extent.extLength |= etype << 30; 337 extent.extLength |= etype << 30;
309 } 338 }
310 udf_extend_file(inode, &epos, &extent, offset+((inode->i_size & (sb->s_blocksize-1)) != 0)); 339 udf_extend_file(inode, &epos, &extent,
340 offset +
341 ((inode->
342 i_size & (sb->s_blocksize - 1)) !=
343 0));
311 } 344 }
312 } 345 }
313 UDF_I_LENEXTENTS(inode) = inode->i_size; 346 UDF_I_LENEXTENTS(inode) = inode->i_size;