diff options
Diffstat (limited to 'fs/udf/truncate.c')
-rw-r--r-- | fs/udf/truncate.c | 146 |
1 files changed, 60 insertions, 86 deletions
diff --git a/fs/udf/truncate.c b/fs/udf/truncate.c index 225527cdc885..8424308db4b4 100644 --- a/fs/udf/truncate.c +++ b/fs/udf/truncate.c | |||
@@ -197,6 +197,11 @@ static void udf_update_alloc_ext_desc(struct inode *inode, | |||
197 | mark_buffer_dirty_inode(epos->bh, inode); | 197 | mark_buffer_dirty_inode(epos->bh, inode); |
198 | } | 198 | } |
199 | 199 | ||
200 | /* | ||
201 | * Truncate extents of inode to inode->i_size. This function can be used only | ||
202 | * for making file shorter. For making file longer, udf_extend_file() has to | ||
203 | * be used. | ||
204 | */ | ||
200 | void udf_truncate_extents(struct inode *inode) | 205 | void udf_truncate_extents(struct inode *inode) |
201 | { | 206 | { |
202 | struct extent_position epos; | 207 | struct extent_position epos; |
@@ -219,96 +224,65 @@ void udf_truncate_extents(struct inode *inode) | |||
219 | etype = inode_bmap(inode, first_block, &epos, &eloc, &elen, &offset); | 224 | etype = inode_bmap(inode, first_block, &epos, &eloc, &elen, &offset); |
220 | byte_offset = (offset << sb->s_blocksize_bits) + | 225 | byte_offset = (offset << sb->s_blocksize_bits) + |
221 | (inode->i_size & (sb->s_blocksize - 1)); | 226 | (inode->i_size & (sb->s_blocksize - 1)); |
222 | if (etype != -1) { | 227 | if (etype == -1) { |
223 | epos.offset -= adsize; | 228 | /* We should extend the file? */ |
224 | extent_trunc(inode, &epos, &eloc, etype, elen, byte_offset); | 229 | WARN_ON(byte_offset); |
225 | epos.offset += adsize; | 230 | return; |
226 | if (byte_offset) | 231 | } |
227 | lenalloc = epos.offset; | 232 | epos.offset -= adsize; |
228 | else | 233 | extent_trunc(inode, &epos, &eloc, etype, elen, byte_offset); |
229 | lenalloc = epos.offset - adsize; | 234 | epos.offset += adsize; |
230 | 235 | if (byte_offset) | |
231 | if (!epos.bh) | 236 | lenalloc = epos.offset; |
232 | lenalloc -= udf_file_entry_alloc_offset(inode); | 237 | else |
233 | else | 238 | lenalloc = epos.offset - adsize; |
234 | lenalloc -= sizeof(struct allocExtDesc); | ||
235 | |||
236 | while ((etype = udf_current_aext(inode, &epos, &eloc, | ||
237 | &elen, 0)) != -1) { | ||
238 | if (etype == (EXT_NEXT_EXTENT_ALLOCDECS >> 30)) { | ||
239 | udf_write_aext(inode, &epos, &neloc, nelen, 0); | ||
240 | if (indirect_ext_len) { | ||
241 | /* We managed to free all extents in the | ||
242 | * indirect extent - free it too */ | ||
243 | BUG_ON(!epos.bh); | ||
244 | udf_free_blocks(sb, inode, &epos.block, | ||
245 | 0, indirect_ext_len); | ||
246 | } else if (!epos.bh) { | ||
247 | iinfo->i_lenAlloc = lenalloc; | ||
248 | mark_inode_dirty(inode); | ||
249 | } else | ||
250 | udf_update_alloc_ext_desc(inode, | ||
251 | &epos, lenalloc); | ||
252 | brelse(epos.bh); | ||
253 | epos.offset = sizeof(struct allocExtDesc); | ||
254 | epos.block = eloc; | ||
255 | epos.bh = udf_tread(sb, | ||
256 | udf_get_lb_pblock(sb, &eloc, 0)); | ||
257 | if (elen) | ||
258 | indirect_ext_len = | ||
259 | (elen + sb->s_blocksize - 1) >> | ||
260 | sb->s_blocksize_bits; | ||
261 | else | ||
262 | indirect_ext_len = 1; | ||
263 | } else { | ||
264 | extent_trunc(inode, &epos, &eloc, etype, | ||
265 | elen, 0); | ||
266 | epos.offset += adsize; | ||
267 | } | ||
268 | } | ||
269 | 239 | ||
270 | if (indirect_ext_len) { | 240 | if (!epos.bh) |
271 | BUG_ON(!epos.bh); | 241 | lenalloc -= udf_file_entry_alloc_offset(inode); |
272 | udf_free_blocks(sb, inode, &epos.block, 0, | 242 | else |
273 | indirect_ext_len); | 243 | lenalloc -= sizeof(struct allocExtDesc); |
274 | } else if (!epos.bh) { | ||
275 | iinfo->i_lenAlloc = lenalloc; | ||
276 | mark_inode_dirty(inode); | ||
277 | } else | ||
278 | udf_update_alloc_ext_desc(inode, &epos, lenalloc); | ||
279 | } else if (inode->i_size) { | ||
280 | if (byte_offset) { | ||
281 | struct kernel_long_ad extent; | ||
282 | 244 | ||
283 | /* | 245 | while ((etype = udf_current_aext(inode, &epos, &eloc, |
284 | * OK, there is not extent covering inode->i_size and | 246 | &elen, 0)) != -1) { |
285 | * no extent above inode->i_size => truncate is | 247 | if (etype == (EXT_NEXT_EXTENT_ALLOCDECS >> 30)) { |
286 | * extending the file by 'offset' blocks. | 248 | udf_write_aext(inode, &epos, &neloc, nelen, 0); |
287 | */ | 249 | if (indirect_ext_len) { |
288 | if ((!epos.bh && | 250 | /* We managed to free all extents in the |
289 | epos.offset == | 251 | * indirect extent - free it too */ |
290 | udf_file_entry_alloc_offset(inode)) || | 252 | BUG_ON(!epos.bh); |
291 | (epos.bh && epos.offset == | 253 | udf_free_blocks(sb, inode, &epos.block, |
292 | sizeof(struct allocExtDesc))) { | 254 | 0, indirect_ext_len); |
293 | /* File has no extents at all or has empty last | 255 | } else if (!epos.bh) { |
294 | * indirect extent! Create a fake extent... */ | 256 | iinfo->i_lenAlloc = lenalloc; |
295 | extent.extLocation.logicalBlockNum = 0; | 257 | mark_inode_dirty(inode); |
296 | extent.extLocation.partitionReferenceNum = 0; | 258 | } else |
297 | extent.extLength = | 259 | udf_update_alloc_ext_desc(inode, |
298 | EXT_NOT_RECORDED_NOT_ALLOCATED; | 260 | &epos, lenalloc); |
299 | } else { | 261 | brelse(epos.bh); |
300 | epos.offset -= adsize; | 262 | epos.offset = sizeof(struct allocExtDesc); |
301 | etype = udf_next_aext(inode, &epos, | 263 | epos.block = eloc; |
302 | &extent.extLocation, | 264 | epos.bh = udf_tread(sb, |
303 | &extent.extLength, 0); | 265 | udf_get_lb_pblock(sb, &eloc, 0)); |
304 | extent.extLength |= etype << 30; | 266 | if (elen) |
305 | } | 267 | indirect_ext_len = |
306 | udf_extend_file(inode, &epos, &extent, | 268 | (elen + sb->s_blocksize - 1) >> |
307 | offset + | 269 | sb->s_blocksize_bits; |
308 | ((inode->i_size & | 270 | else |
309 | (sb->s_blocksize - 1)) != 0)); | 271 | indirect_ext_len = 1; |
272 | } else { | ||
273 | extent_trunc(inode, &epos, &eloc, etype, elen, 0); | ||
274 | epos.offset += adsize; | ||
310 | } | 275 | } |
311 | } | 276 | } |
277 | |||
278 | if (indirect_ext_len) { | ||
279 | BUG_ON(!epos.bh); | ||
280 | udf_free_blocks(sb, inode, &epos.block, 0, indirect_ext_len); | ||
281 | } else if (!epos.bh) { | ||
282 | iinfo->i_lenAlloc = lenalloc; | ||
283 | mark_inode_dirty(inode); | ||
284 | } else | ||
285 | udf_update_alloc_ext_desc(inode, &epos, lenalloc); | ||
312 | iinfo->i_lenExtents = inode->i_size; | 286 | iinfo->i_lenExtents = inode->i_size; |
313 | 287 | ||
314 | brelse(epos.bh); | 288 | brelse(epos.bh); |