~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to fs/udf/truncate.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
197
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
205
void udf_truncate_extents(struct inode *inode)
201
206
{
202
207
        struct extent_position epos;
219
224
        etype = inode_bmap(inode, first_block, &epos, &eloc, &elen, &offset);
220
225
        byte_offset = (offset << sb->s_blocksize_bits) +
221
226
                (inode->i_size & (sb->s_blocksize - 1));
222
 
        if (etype != -1) {
223
 
                epos.offset -= adsize;
224
 
                extent_trunc(inode, &epos, &eloc, etype, elen, byte_offset);
225
 
                epos.offset += adsize;
226
 
                if (byte_offset)
227
 
                        lenalloc = epos.offset;
228
 
                else
229
 
                        lenalloc = epos.offset - adsize;
230
 
 
231
 
                if (!epos.bh)
232
 
                        lenalloc -= udf_file_entry_alloc_offset(inode);
233
 
                else
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
 
 
270
 
                if (indirect_ext_len) {
271
 
                        BUG_ON(!epos.bh);
272
 
                        udf_free_blocks(sb, inode, &epos.block, 0,
273
 
                                        indirect_ext_len);
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
 
 
283
 
                        /*
284
 
                         *  OK, there is not extent covering inode->i_size and
285
 
                         *  no extent above inode->i_size => truncate is
286
 
                         *  extending the file by 'offset' blocks.
287
 
                         */
288
 
                        if ((!epos.bh &&
289
 
                             epos.offset ==
290
 
                                        udf_file_entry_alloc_offset(inode)) ||
291
 
                            (epos.bh && epos.offset ==
292
 
                                                sizeof(struct allocExtDesc))) {
293
 
                                /* File has no extents at all or has empty last
294
 
                                 * indirect extent! Create a fake extent... */
295
 
                                extent.extLocation.logicalBlockNum = 0;
296
 
                                extent.extLocation.partitionReferenceNum = 0;
297
 
                                extent.extLength =
298
 
                                        EXT_NOT_RECORDED_NOT_ALLOCATED;
299
 
                        } else {
300
 
                                epos.offset -= adsize;
301
 
                                etype = udf_next_aext(inode, &epos,
302
 
                                                      &extent.extLocation,
303
 
                                                      &extent.extLength, 0);
304
 
                                extent.extLength |= etype << 30;
305
 
                        }
306
 
                        udf_extend_file(inode, &epos, &extent,
307
 
                                        offset +
308
 
                                        ((inode->i_size &
309
 
                                                (sb->s_blocksize - 1)) != 0));
310
 
                }
311
 
        }
 
227
        if (etype == -1) {
 
228
                /* We should extend the file? */
 
229
                WARN_ON(byte_offset);
 
230
                return;
 
231
        }
 
232
        epos.offset -= adsize;
 
233
        extent_trunc(inode, &epos, &eloc, etype, elen, byte_offset);
 
234
        epos.offset += adsize;
 
235
        if (byte_offset)
 
236
                lenalloc = epos.offset;
 
237
        else
 
238
                lenalloc = epos.offset - adsize;
 
239
 
 
240
        if (!epos.bh)
 
241
                lenalloc -= udf_file_entry_alloc_offset(inode);
 
242
        else
 
243
                lenalloc -= sizeof(struct allocExtDesc);
 
244
 
 
245
        while ((etype = udf_current_aext(inode, &epos, &eloc,
 
246
                                         &elen, 0)) != -1) {
 
247
                if (etype == (EXT_NEXT_EXTENT_ALLOCDECS >> 30)) {
 
248
                        udf_write_aext(inode, &epos, &neloc, nelen, 0);
 
249
                        if (indirect_ext_len) {
 
250
                                /* We managed to free all extents in the
 
251
                                 * indirect extent - free it too */
 
252
                                BUG_ON(!epos.bh);
 
253
                                udf_free_blocks(sb, inode, &epos.block,
 
254
                                                0, indirect_ext_len);
 
255
                        } else if (!epos.bh) {
 
256
                                iinfo->i_lenAlloc = lenalloc;
 
257
                                mark_inode_dirty(inode);
 
258
                        } else
 
259
                                udf_update_alloc_ext_desc(inode,
 
260
                                                &epos, lenalloc);
 
261
                        brelse(epos.bh);
 
262
                        epos.offset = sizeof(struct allocExtDesc);
 
263
                        epos.block = eloc;
 
264
                        epos.bh = udf_tread(sb,
 
265
                                        udf_get_lb_pblock(sb, &eloc, 0));
 
266
                        if (elen)
 
267
                                indirect_ext_len =
 
268
                                        (elen + sb->s_blocksize - 1) >>
 
269
                                        sb->s_blocksize_bits;
 
270
                        else
 
271
                                indirect_ext_len = 1;
 
272
                } else {
 
273
                        extent_trunc(inode, &epos, &eloc, etype, elen, 0);
 
274
                        epos.offset += adsize;
 
275
                }
 
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
286
        iinfo->i_lenExtents = inode->i_size;
313
287
 
314
288
        brelse(epos.bh);