diff options
| -rw-r--r-- | fs/udf/balloc.c | 4 | ||||
| -rw-r--r-- | fs/udf/file.c | 7 | ||||
| -rw-r--r-- | fs/udf/inode.c | 239 | ||||
| -rw-r--r-- | fs/udf/truncate.c | 146 | ||||
| -rw-r--r-- | fs/udf/udfdecl.h | 12 |
5 files changed, 236 insertions, 172 deletions
diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c index 306ee39ef2c3..8994dd041660 100644 --- a/fs/udf/balloc.c +++ b/fs/udf/balloc.c | |||
| @@ -31,7 +31,7 @@ | |||
| 31 | #define udf_set_bit(nr, addr) ext2_set_bit(nr, addr) | 31 | #define udf_set_bit(nr, addr) ext2_set_bit(nr, addr) |
| 32 | #define udf_test_bit(nr, addr) ext2_test_bit(nr, addr) | 32 | #define udf_test_bit(nr, addr) ext2_test_bit(nr, addr) |
| 33 | #define udf_find_next_one_bit(addr, size, offset) \ | 33 | #define udf_find_next_one_bit(addr, size, offset) \ |
| 34 | ext2_find_next_bit(addr, size, offset) | 34 | ext2_find_next_bit((unsigned long *)(addr), size, offset) |
| 35 | 35 | ||
| 36 | static int read_block_bitmap(struct super_block *sb, | 36 | static int read_block_bitmap(struct super_block *sb, |
| 37 | struct udf_bitmap *bitmap, unsigned int block, | 37 | struct udf_bitmap *bitmap, unsigned int block, |
| @@ -297,7 +297,7 @@ repeat: | |||
| 297 | break; | 297 | break; |
| 298 | } | 298 | } |
| 299 | } else { | 299 | } else { |
| 300 | bit = udf_find_next_one_bit((char *)bh->b_data, | 300 | bit = udf_find_next_one_bit(bh->b_data, |
| 301 | sb->s_blocksize << 3, | 301 | sb->s_blocksize << 3, |
| 302 | group_start << 3); | 302 | group_start << 3); |
| 303 | if (bit < sb->s_blocksize << 3) | 303 | if (bit < sb->s_blocksize << 3) |
diff --git a/fs/udf/file.c b/fs/udf/file.c index 89c78486cbbe..f391a2adc699 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c | |||
| @@ -123,8 +123,8 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov, | |||
| 123 | if (inode->i_sb->s_blocksize < | 123 | if (inode->i_sb->s_blocksize < |
| 124 | (udf_file_entry_alloc_offset(inode) + | 124 | (udf_file_entry_alloc_offset(inode) + |
| 125 | pos + count)) { | 125 | pos + count)) { |
| 126 | udf_expand_file_adinicb(inode, pos + count, &err); | 126 | err = udf_expand_file_adinicb(inode); |
| 127 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { | 127 | if (err) { |
| 128 | udf_debug("udf_expand_adinicb: err=%d\n", err); | 128 | udf_debug("udf_expand_adinicb: err=%d\n", err); |
| 129 | up_write(&iinfo->i_data_sem); | 129 | up_write(&iinfo->i_data_sem); |
| 130 | return err; | 130 | return err; |
| @@ -237,7 +237,7 @@ static int udf_setattr(struct dentry *dentry, struct iattr *attr) | |||
| 237 | 237 | ||
| 238 | if ((attr->ia_valid & ATTR_SIZE) && | 238 | if ((attr->ia_valid & ATTR_SIZE) && |
| 239 | attr->ia_size != i_size_read(inode)) { | 239 | attr->ia_size != i_size_read(inode)) { |
| 240 | error = vmtruncate(inode, attr->ia_size); | 240 | error = udf_setsize(inode, attr->ia_size); |
| 241 | if (error) | 241 | if (error) |
| 242 | return error; | 242 | return error; |
| 243 | } | 243 | } |
| @@ -249,5 +249,4 @@ static int udf_setattr(struct dentry *dentry, struct iattr *attr) | |||
| 249 | 249 | ||
| 250 | const struct inode_operations udf_file_inode_operations = { | 250 | const struct inode_operations udf_file_inode_operations = { |
| 251 | .setattr = udf_setattr, | 251 | .setattr = udf_setattr, |
| 252 | .truncate = udf_truncate, | ||
| 253 | }; | 252 | }; |
diff --git a/fs/udf/inode.c b/fs/udf/inode.c index c6a2e782b97b..ccc814321414 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c | |||
| @@ -73,14 +73,12 @@ void udf_evict_inode(struct inode *inode) | |||
| 73 | struct udf_inode_info *iinfo = UDF_I(inode); | 73 | struct udf_inode_info *iinfo = UDF_I(inode); |
| 74 | int want_delete = 0; | 74 | int want_delete = 0; |
| 75 | 75 | ||
| 76 | truncate_inode_pages(&inode->i_data, 0); | ||
| 77 | |||
| 78 | if (!inode->i_nlink && !is_bad_inode(inode)) { | 76 | if (!inode->i_nlink && !is_bad_inode(inode)) { |
| 79 | want_delete = 1; | 77 | want_delete = 1; |
| 80 | inode->i_size = 0; | 78 | udf_setsize(inode, 0); |
| 81 | udf_truncate(inode); | ||
| 82 | udf_update_inode(inode, IS_SYNC(inode)); | 79 | udf_update_inode(inode, IS_SYNC(inode)); |
| 83 | } | 80 | } else |
| 81 | truncate_inode_pages(&inode->i_data, 0); | ||
| 84 | invalidate_inode_buffers(inode); | 82 | invalidate_inode_buffers(inode); |
| 85 | end_writeback(inode); | 83 | end_writeback(inode); |
| 86 | if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB && | 84 | if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB && |
| @@ -117,9 +115,18 @@ static int udf_write_begin(struct file *file, struct address_space *mapping, | |||
| 117 | 115 | ||
| 118 | ret = block_write_begin(mapping, pos, len, flags, pagep, udf_get_block); | 116 | ret = block_write_begin(mapping, pos, len, flags, pagep, udf_get_block); |
| 119 | if (unlikely(ret)) { | 117 | if (unlikely(ret)) { |
| 120 | loff_t isize = mapping->host->i_size; | 118 | struct inode *inode = mapping->host; |
| 121 | if (pos + len > isize) | 119 | struct udf_inode_info *iinfo = UDF_I(inode); |
| 122 | vmtruncate(mapping->host, isize); | 120 | loff_t isize = inode->i_size; |
| 121 | |||
| 122 | if (pos + len > isize) { | ||
| 123 | truncate_pagecache(inode, pos + len, isize); | ||
| 124 | if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) { | ||
| 125 | down_write(&iinfo->i_data_sem); | ||
| 126 | udf_truncate_extents(inode); | ||
| 127 | up_write(&iinfo->i_data_sem); | ||
| 128 | } | ||
| 129 | } | ||
| 123 | } | 130 | } |
| 124 | 131 | ||
| 125 | return ret; | 132 | return ret; |
| @@ -139,30 +146,31 @@ const struct address_space_operations udf_aops = { | |||
| 139 | .bmap = udf_bmap, | 146 | .bmap = udf_bmap, |
| 140 | }; | 147 | }; |
| 141 | 148 | ||
| 142 | void udf_expand_file_adinicb(struct inode *inode, int newsize, int *err) | 149 | int udf_expand_file_adinicb(struct inode *inode) |
| 143 | { | 150 | { |
| 144 | struct page *page; | 151 | struct page *page; |
| 145 | char *kaddr; | 152 | char *kaddr; |
| 146 | struct udf_inode_info *iinfo = UDF_I(inode); | 153 | struct udf_inode_info *iinfo = UDF_I(inode); |
| 154 | int err; | ||
| 147 | struct writeback_control udf_wbc = { | 155 | struct writeback_control udf_wbc = { |
| 148 | .sync_mode = WB_SYNC_NONE, | 156 | .sync_mode = WB_SYNC_NONE, |
| 149 | .nr_to_write = 1, | 157 | .nr_to_write = 1, |
| 150 | }; | 158 | }; |
| 151 | 159 | ||
| 152 | /* from now on we have normal address_space methods */ | ||
| 153 | inode->i_data.a_ops = &udf_aops; | ||
| 154 | |||
| 155 | if (!iinfo->i_lenAlloc) { | 160 | if (!iinfo->i_lenAlloc) { |
| 156 | if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD)) | 161 | if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD)) |
| 157 | iinfo->i_alloc_type = ICBTAG_FLAG_AD_SHORT; | 162 | iinfo->i_alloc_type = ICBTAG_FLAG_AD_SHORT; |
| 158 | else | 163 | else |
| 159 | iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG; | 164 | iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG; |
| 165 | /* from now on we have normal address_space methods */ | ||
| 166 | inode->i_data.a_ops = &udf_aops; | ||
| 160 | mark_inode_dirty(inode); | 167 | mark_inode_dirty(inode); |
| 161 | return; | 168 | return 0; |
| 162 | } | 169 | } |
| 163 | 170 | ||
| 164 | page = grab_cache_page(inode->i_mapping, 0); | 171 | page = find_or_create_page(inode->i_mapping, 0, GFP_NOFS); |
| 165 | BUG_ON(!PageLocked(page)); | 172 | if (!page) |
| 173 | return -ENOMEM; | ||
| 166 | 174 | ||
| 167 | if (!PageUptodate(page)) { | 175 | if (!PageUptodate(page)) { |
| 168 | kaddr = kmap(page); | 176 | kaddr = kmap(page); |
| @@ -181,11 +189,24 @@ void udf_expand_file_adinicb(struct inode *inode, int newsize, int *err) | |||
| 181 | iinfo->i_alloc_type = ICBTAG_FLAG_AD_SHORT; | 189 | iinfo->i_alloc_type = ICBTAG_FLAG_AD_SHORT; |
| 182 | else | 190 | else |
| 183 | iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG; | 191 | iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG; |
| 184 | 192 | /* from now on we have normal address_space methods */ | |
| 185 | inode->i_data.a_ops->writepage(page, &udf_wbc); | 193 | inode->i_data.a_ops = &udf_aops; |
| 194 | err = inode->i_data.a_ops->writepage(page, &udf_wbc); | ||
| 195 | if (err) { | ||
| 196 | /* Restore everything back so that we don't lose data... */ | ||
| 197 | lock_page(page); | ||
| 198 | kaddr = kmap(page); | ||
| 199 | memcpy(iinfo->i_ext.i_data + iinfo->i_lenEAttr, kaddr, | ||
| 200 | inode->i_size); | ||
| 201 | kunmap(page); | ||
| 202 | unlock_page(page); | ||
| 203 | iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB; | ||
| 204 | inode->i_data.a_ops = &udf_adinicb_aops; | ||
| 205 | } | ||
| 186 | page_cache_release(page); | 206 | page_cache_release(page); |
| 187 | |||
| 188 | mark_inode_dirty(inode); | 207 | mark_inode_dirty(inode); |
| 208 | |||
| 209 | return err; | ||
| 189 | } | 210 | } |
| 190 | 211 | ||
| 191 | struct buffer_head *udf_expand_dir_adinicb(struct inode *inode, int *block, | 212 | struct buffer_head *udf_expand_dir_adinicb(struct inode *inode, int *block, |
| @@ -348,8 +369,10 @@ static struct buffer_head *udf_getblk(struct inode *inode, long block, | |||
| 348 | } | 369 | } |
| 349 | 370 | ||
| 350 | /* Extend the file by 'blocks' blocks, return the number of extents added */ | 371 | /* Extend the file by 'blocks' blocks, return the number of extents added */ |
| 351 | int udf_extend_file(struct inode *inode, struct extent_position *last_pos, | 372 | static int udf_do_extend_file(struct inode *inode, |
| 352 | struct kernel_long_ad *last_ext, sector_t blocks) | 373 | struct extent_position *last_pos, |
| 374 | struct kernel_long_ad *last_ext, | ||
| 375 | sector_t blocks) | ||
| 353 | { | 376 | { |
| 354 | sector_t add; | 377 | sector_t add; |
| 355 | int count = 0, fake = !(last_ext->extLength & UDF_EXTENT_LENGTH_MASK); | 378 | int count = 0, fake = !(last_ext->extLength & UDF_EXTENT_LENGTH_MASK); |
| @@ -357,6 +380,7 @@ int udf_extend_file(struct inode *inode, struct extent_position *last_pos, | |||
| 357 | struct kernel_lb_addr prealloc_loc = {}; | 380 | struct kernel_lb_addr prealloc_loc = {}; |
| 358 | int prealloc_len = 0; | 381 | int prealloc_len = 0; |
| 359 | struct udf_inode_info *iinfo; | 382 | struct udf_inode_info *iinfo; |
| 383 | int err; | ||
| 360 | 384 | ||
| 361 | /* The previous extent is fake and we should not extend by anything | 385 | /* The previous extent is fake and we should not extend by anything |
| 362 | * - there's nothing to do... */ | 386 | * - there's nothing to do... */ |
| @@ -422,26 +446,29 @@ int udf_extend_file(struct inode *inode, struct extent_position *last_pos, | |||
| 422 | /* Create enough extents to cover the whole hole */ | 446 | /* Create enough extents to cover the whole hole */ |
| 423 | while (blocks > add) { | 447 | while (blocks > add) { |
| 424 | blocks -= add; | 448 | blocks -= add; |
| 425 | if (udf_add_aext(inode, last_pos, &last_ext->extLocation, | 449 | err = udf_add_aext(inode, last_pos, &last_ext->extLocation, |
| 426 | last_ext->extLength, 1) == -1) | 450 | last_ext->extLength, 1); |
| 427 | return -1; | 451 | if (err) |
| 452 | return err; | ||
| 428 | count++; | 453 | count++; |
| 429 | } | 454 | } |
| 430 | if (blocks) { | 455 | if (blocks) { |
| 431 | last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED | | 456 | last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED | |
| 432 | (blocks << sb->s_blocksize_bits); | 457 | (blocks << sb->s_blocksize_bits); |
| 433 | if (udf_add_aext(inode, last_pos, &last_ext->extLocation, | 458 | err = udf_add_aext(inode, last_pos, &last_ext->extLocation, |
| 434 | last_ext->extLength, 1) == -1) | 459 | last_ext->extLength, 1); |
| 435 | return -1; | 460 | if (err) |
| 461 | return err; | ||
| 436 | count++; | 462 | count++; |
| 437 | } | 463 | } |
| 438 | 464 | ||
| 439 | out: | 465 | out: |
| 440 | /* Do we have some preallocated blocks saved? */ | 466 | /* Do we have some preallocated blocks saved? */ |
| 441 | if (prealloc_len) { | 467 | if (prealloc_len) { |
| 442 | if (udf_add_aext(inode, last_pos, &prealloc_loc, | 468 | err = udf_add_aext(inode, last_pos, &prealloc_loc, |
| 443 | prealloc_len, 1) == -1) | 469 | prealloc_len, 1); |
| 444 | return -1; | 470 | if (err) |
| 471 | return err; | ||
| 445 | last_ext->extLocation = prealloc_loc; | 472 | last_ext->extLocation = prealloc_loc; |
| 446 | last_ext->extLength = prealloc_len; | 473 | last_ext->extLength = prealloc_len; |
| 447 | count++; | 474 | count++; |
| @@ -453,11 +480,68 @@ out: | |||
| 453 | else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) | 480 | else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) |
| 454 | last_pos->offset -= sizeof(struct long_ad); | 481 | last_pos->offset -= sizeof(struct long_ad); |
| 455 | else | 482 | else |
| 456 | return -1; | 483 | return -EIO; |
| 457 | 484 | ||
| 458 | return count; | 485 | return count; |
| 459 | } | 486 | } |
| 460 | 487 | ||
| 488 | static int udf_extend_file(struct inode *inode, loff_t newsize) | ||
| 489 | { | ||
| 490 | |||
| 491 | struct extent_position epos; | ||
| 492 | struct kernel_lb_addr eloc; | ||
| 493 | uint32_t elen; | ||
| 494 | int8_t etype; | ||
| 495 | struct super_block *sb = inode->i_sb; | ||
| 496 | sector_t first_block = newsize >> sb->s_blocksize_bits, offset; | ||
| 497 | int adsize; | ||
| 498 | struct udf_inode_info *iinfo = UDF_I(inode); | ||
| 499 | struct kernel_long_ad extent; | ||
| 500 | int err; | ||
| 501 | |||
| 502 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) | ||
| 503 | adsize = sizeof(struct short_ad); | ||
| 504 | else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) | ||
| 505 | adsize = sizeof(struct long_ad); | ||
| 506 | else | ||
| 507 | BUG(); | ||
| 508 | |||
| 509 | etype = inode_bmap(inode, first_block, &epos, &eloc, &elen, &offset); | ||
| 510 | |||
| 511 | /* File has extent covering the new size (could happen when extending | ||
| 512 | * inside a block)? */ | ||
| 513 | if (etype != -1) | ||
| 514 | return 0; | ||
| 515 | if (newsize & (sb->s_blocksize - 1)) | ||
| 516 | offset++; | ||
| 517 | /* Extended file just to the boundary of the last file block? */ | ||
| 518 | if (offset == 0) | ||
| 519 | return 0; | ||
| 520 | |||
| 521 | /* Truncate is extending the file by 'offset' blocks */ | ||
| 522 | if ((!epos.bh && epos.offset == udf_file_entry_alloc_offset(inode)) || | ||
| 523 | (epos.bh && epos.offset == sizeof(struct allocExtDesc))) { | ||
| 524 | /* File has no extents at all or has empty last | ||
| 525 | * indirect extent! Create a fake extent... */ | ||
| 526 | extent.extLocation.logicalBlockNum = 0; | ||
| 527 | extent.extLocation.partitionReferenceNum = 0; | ||
| 528 | extent.extLength = EXT_NOT_RECORDED_NOT_ALLOCATED; | ||
| 529 | } else { | ||
| 530 | epos.offset -= adsize; | ||
| 531 | etype = udf_next_aext(inode, &epos, &extent.extLocation, | ||
| 532 | &extent.extLength, 0); | ||
| 533 | extent.extLength |= etype << 30; | ||
| 534 | } | ||
| 535 | err = udf_do_extend_file(inode, &epos, &extent, offset); | ||
| 536 | if (err < 0) | ||
| 537 | goto out; | ||
| 538 | err = 0; | ||
| 539 | iinfo->i_lenExtents = newsize; | ||
| 540 | out: | ||
| 541 | brelse(epos.bh); | ||
| 542 | return err; | ||
| 543 | } | ||
| 544 | |||
| 461 | static struct buffer_head *inode_getblk(struct inode *inode, sector_t block, | 545 | static struct buffer_head *inode_getblk(struct inode *inode, sector_t block, |
| 462 | int *err, sector_t *phys, int *new) | 546 | int *err, sector_t *phys, int *new) |
| 463 | { | 547 | { |
| @@ -540,7 +624,7 @@ static struct buffer_head *inode_getblk(struct inode *inode, sector_t block, | |||
| 540 | elen = EXT_RECORDED_ALLOCATED | | 624 | elen = EXT_RECORDED_ALLOCATED | |
| 541 | ((elen + inode->i_sb->s_blocksize - 1) & | 625 | ((elen + inode->i_sb->s_blocksize - 1) & |
| 542 | ~(inode->i_sb->s_blocksize - 1)); | 626 | ~(inode->i_sb->s_blocksize - 1)); |
| 543 | etype = udf_write_aext(inode, &cur_epos, &eloc, elen, 1); | 627 | udf_write_aext(inode, &cur_epos, &eloc, elen, 1); |
| 544 | } | 628 | } |
| 545 | brelse(prev_epos.bh); | 629 | brelse(prev_epos.bh); |
| 546 | brelse(cur_epos.bh); | 630 | brelse(cur_epos.bh); |
| @@ -564,19 +648,17 @@ static struct buffer_head *inode_getblk(struct inode *inode, sector_t block, | |||
| 564 | memset(&laarr[0].extLocation, 0x00, | 648 | memset(&laarr[0].extLocation, 0x00, |
| 565 | sizeof(struct kernel_lb_addr)); | 649 | sizeof(struct kernel_lb_addr)); |
| 566 | laarr[0].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED; | 650 | laarr[0].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED; |
| 567 | /* Will udf_extend_file() create real extent from | 651 | /* Will udf_do_extend_file() create real extent from |
| 568 | a fake one? */ | 652 | a fake one? */ |
| 569 | startnum = (offset > 0); | 653 | startnum = (offset > 0); |
| 570 | } | 654 | } |
| 571 | /* Create extents for the hole between EOF and offset */ | 655 | /* Create extents for the hole between EOF and offset */ |
| 572 | ret = udf_extend_file(inode, &prev_epos, laarr, offset); | 656 | ret = udf_do_extend_file(inode, &prev_epos, laarr, offset); |
| 573 | if (ret == -1) { | 657 | if (ret < 0) { |
| 574 | brelse(prev_epos.bh); | 658 | brelse(prev_epos.bh); |
| 575 | brelse(cur_epos.bh); | 659 | brelse(cur_epos.bh); |
| 576 | brelse(next_epos.bh); | 660 | brelse(next_epos.bh); |
| 577 | /* We don't really know the error here so we just make | 661 | *err = ret; |
| 578 | * something up */ | ||
| 579 | *err = -ENOSPC; | ||
| 580 | return NULL; | 662 | return NULL; |
| 581 | } | 663 | } |
| 582 | c = 0; | 664 | c = 0; |
| @@ -1005,52 +1087,66 @@ struct buffer_head *udf_bread(struct inode *inode, int block, | |||
| 1005 | return NULL; | 1087 | return NULL; |
| 1006 | } | 1088 | } |
| 1007 | 1089 | ||
| 1008 | void udf_truncate(struct inode *inode) | 1090 | int udf_setsize(struct inode *inode, loff_t newsize) |
| 1009 | { | 1091 | { |
| 1010 | int offset; | ||
| 1011 | int err; | 1092 | int err; |
| 1012 | struct udf_inode_info *iinfo; | 1093 | struct udf_inode_info *iinfo; |
| 1094 | int bsize = 1 << inode->i_blkbits; | ||
| 1013 | 1095 | ||
| 1014 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || | 1096 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || |
| 1015 | S_ISLNK(inode->i_mode))) | 1097 | S_ISLNK(inode->i_mode))) |
| 1016 | return; | 1098 | return -EINVAL; |
| 1017 | if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) | 1099 | if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) |
| 1018 | return; | 1100 | return -EPERM; |
| 1019 | 1101 | ||
| 1020 | iinfo = UDF_I(inode); | 1102 | iinfo = UDF_I(inode); |
| 1021 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { | 1103 | if (newsize > inode->i_size) { |
| 1022 | down_write(&iinfo->i_data_sem); | 1104 | down_write(&iinfo->i_data_sem); |
| 1023 | if (inode->i_sb->s_blocksize < | 1105 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { |
| 1024 | (udf_file_entry_alloc_offset(inode) + | 1106 | if (bsize < |
| 1025 | inode->i_size)) { | 1107 | (udf_file_entry_alloc_offset(inode) + newsize)) { |
| 1026 | udf_expand_file_adinicb(inode, inode->i_size, &err); | 1108 | err = udf_expand_file_adinicb(inode); |
| 1027 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { | 1109 | if (err) { |
| 1028 | inode->i_size = iinfo->i_lenAlloc; | 1110 | up_write(&iinfo->i_data_sem); |
| 1029 | up_write(&iinfo->i_data_sem); | 1111 | return err; |
| 1030 | return; | 1112 | } |
| 1031 | } else | 1113 | } else |
| 1032 | udf_truncate_extents(inode); | 1114 | iinfo->i_lenAlloc = newsize; |
| 1033 | } else { | 1115 | } |
| 1034 | offset = inode->i_size & (inode->i_sb->s_blocksize - 1); | 1116 | err = udf_extend_file(inode, newsize); |
| 1035 | memset(iinfo->i_ext.i_data + iinfo->i_lenEAttr + offset, | 1117 | if (err) { |
| 1036 | 0x00, inode->i_sb->s_blocksize - | 1118 | up_write(&iinfo->i_data_sem); |
| 1037 | offset - udf_file_entry_alloc_offset(inode)); | 1119 | return err; |
| 1038 | iinfo->i_lenAlloc = inode->i_size; | ||
| 1039 | } | 1120 | } |
| 1121 | truncate_setsize(inode, newsize); | ||
| 1040 | up_write(&iinfo->i_data_sem); | 1122 | up_write(&iinfo->i_data_sem); |
| 1041 | } else { | 1123 | } else { |
| 1042 | block_truncate_page(inode->i_mapping, inode->i_size, | 1124 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { |
| 1043 | udf_get_block); | 1125 | down_write(&iinfo->i_data_sem); |
| 1126 | memset(iinfo->i_ext.i_data + iinfo->i_lenEAttr + newsize, | ||
| 1127 | 0x00, bsize - newsize - | ||
| 1128 | udf_file_entry_alloc_offset(inode)); | ||
| 1129 | iinfo->i_lenAlloc = newsize; | ||
| 1130 | truncate_setsize(inode, newsize); | ||
| 1131 | up_write(&iinfo->i_data_sem); | ||
| 1132 | goto update_time; | ||
| 1133 | } | ||
| 1134 | err = block_truncate_page(inode->i_mapping, newsize, | ||
| 1135 | udf_get_block); | ||
| 1136 | if (err) | ||
| 1137 | return err; | ||
| 1044 | down_write(&iinfo->i_data_sem); | 1138 | down_write(&iinfo->i_data_sem); |
| 1139 | truncate_setsize(inode, newsize); | ||
| 1045 | udf_truncate_extents(inode); | 1140 | udf_truncate_extents(inode); |
| 1046 | up_write(&iinfo->i_data_sem); | 1141 | up_write(&iinfo->i_data_sem); |
| 1047 | } | 1142 | } |
| 1048 | 1143 | update_time: | |
| 1049 | inode->i_mtime = inode->i_ctime = current_fs_time(inode->i_sb); | 1144 | inode->i_mtime = inode->i_ctime = current_fs_time(inode->i_sb); |
| 1050 | if (IS_SYNC(inode)) | 1145 | if (IS_SYNC(inode)) |
| 1051 | udf_sync_inode(inode); | 1146 | udf_sync_inode(inode); |
| 1052 | else | 1147 | else |
| 1053 | mark_inode_dirty(inode); | 1148 | mark_inode_dirty(inode); |
| 1149 | return 0; | ||
| 1054 | } | 1150 | } |
| 1055 | 1151 | ||
| 1056 | static void __udf_read_inode(struct inode *inode) | 1152 | static void __udf_read_inode(struct inode *inode) |
| @@ -1637,14 +1733,13 @@ struct inode *udf_iget(struct super_block *sb, struct kernel_lb_addr *ino) | |||
| 1637 | return NULL; | 1733 | return NULL; |
| 1638 | } | 1734 | } |
| 1639 | 1735 | ||
| 1640 | int8_t udf_add_aext(struct inode *inode, struct extent_position *epos, | 1736 | int udf_add_aext(struct inode *inode, struct extent_position *epos, |
| 1641 | struct kernel_lb_addr *eloc, uint32_t elen, int inc) | 1737 | struct kernel_lb_addr *eloc, uint32_t elen, int inc) |
| 1642 | { | 1738 | { |
| 1643 | int adsize; | 1739 | int adsize; |
| 1644 | struct short_ad *sad = NULL; | 1740 | struct short_ad *sad = NULL; |
| 1645 | struct long_ad *lad = NULL; | 1741 | struct long_ad *lad = NULL; |
| 1646 | struct allocExtDesc *aed; | 1742 | struct allocExtDesc *aed; |
| 1647 | int8_t etype; | ||
| 1648 | uint8_t *ptr; | 1743 | uint8_t *ptr; |
| 1649 | struct udf_inode_info *iinfo = UDF_I(inode); | 1744 | struct udf_inode_info *iinfo = UDF_I(inode); |
| 1650 | 1745 | ||
| @@ -1660,7 +1755,7 @@ int8_t udf_add_aext(struct inode *inode, struct extent_position *epos, | |||
| 1660 | else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) | 1755 | else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) |
| 1661 | adsize = sizeof(struct long_ad); | 1756 | adsize = sizeof(struct long_ad); |
| 1662 | else | 1757 | else |
| 1663 | return -1; | 1758 | return -EIO; |
| 1664 | 1759 | ||
| 1665 | if (epos->offset + (2 * adsize) > inode->i_sb->s_blocksize) { | 1760 | if (epos->offset + (2 * adsize) > inode->i_sb->s_blocksize) { |
| 1666 | unsigned char *sptr, *dptr; | 1761 | unsigned char *sptr, *dptr; |
| @@ -1672,12 +1767,12 @@ int8_t udf_add_aext(struct inode *inode, struct extent_position *epos, | |||
| 1672 | obloc.partitionReferenceNum, | 1767 | obloc.partitionReferenceNum, |
| 1673 | obloc.logicalBlockNum, &err); | 1768 | obloc.logicalBlockNum, &err); |
| 1674 | if (!epos->block.logicalBlockNum) | 1769 | if (!epos->block.logicalBlockNum) |
| 1675 | return -1; | 1770 | return -ENOSPC; |
| 1676 | nbh = udf_tgetblk(inode->i_sb, udf_get_lb_pblock(inode->i_sb, | 1771 | nbh = udf_tgetblk(inode->i_sb, udf_get_lb_pblock(inode->i_sb, |
| 1677 | &epos->block, | 1772 | &epos->block, |
| 1678 | 0)); | 1773 | 0)); |
| 1679 | if (!nbh) | 1774 | if (!nbh) |
| 1680 | return -1; | 1775 | return -EIO; |
| 1681 | lock_buffer(nbh); | 1776 | lock_buffer(nbh); |
| 1682 | memset(nbh->b_data, 0x00, inode->i_sb->s_blocksize); | 1777 | memset(nbh->b_data, 0x00, inode->i_sb->s_blocksize); |
| 1683 | set_buffer_uptodate(nbh); | 1778 | set_buffer_uptodate(nbh); |
| @@ -1746,7 +1841,7 @@ int8_t udf_add_aext(struct inode *inode, struct extent_position *epos, | |||
| 1746 | epos->bh = nbh; | 1841 | epos->bh = nbh; |
| 1747 | } | 1842 | } |
| 1748 | 1843 | ||
| 1749 | etype = udf_write_aext(inode, epos, eloc, elen, inc); | 1844 | udf_write_aext(inode, epos, eloc, elen, inc); |
| 1750 | 1845 | ||
| 1751 | if (!epos->bh) { | 1846 | if (!epos->bh) { |
| 1752 | iinfo->i_lenAlloc += adsize; | 1847 | iinfo->i_lenAlloc += adsize; |
| @@ -1764,11 +1859,11 @@ int8_t udf_add_aext(struct inode *inode, struct extent_position *epos, | |||
| 1764 | mark_buffer_dirty_inode(epos->bh, inode); | 1859 | mark_buffer_dirty_inode(epos->bh, inode); |
| 1765 | } | 1860 | } |
| 1766 | 1861 | ||
| 1767 | return etype; | 1862 | return 0; |
| 1768 | } | 1863 | } |
| 1769 | 1864 | ||
| 1770 | int8_t udf_write_aext(struct inode *inode, struct extent_position *epos, | 1865 | void udf_write_aext(struct inode *inode, struct extent_position *epos, |
| 1771 | struct kernel_lb_addr *eloc, uint32_t elen, int inc) | 1866 | struct kernel_lb_addr *eloc, uint32_t elen, int inc) |
| 1772 | { | 1867 | { |
| 1773 | int adsize; | 1868 | int adsize; |
| 1774 | uint8_t *ptr; | 1869 | uint8_t *ptr; |
| @@ -1798,7 +1893,7 @@ int8_t udf_write_aext(struct inode *inode, struct extent_position *epos, | |||
| 1798 | adsize = sizeof(struct long_ad); | 1893 | adsize = sizeof(struct long_ad); |
| 1799 | break; | 1894 | break; |
| 1800 | default: | 1895 | default: |
| 1801 | return -1; | 1896 | return; |
| 1802 | } | 1897 | } |
| 1803 | 1898 | ||
| 1804 | if (epos->bh) { | 1899 | if (epos->bh) { |
| @@ -1817,8 +1912,6 @@ int8_t udf_write_aext(struct inode *inode, struct extent_position *epos, | |||
| 1817 | 1912 | ||
| 1818 | if (inc) | 1913 | if (inc) |
| 1819 | epos->offset += adsize; | 1914 | epos->offset += adsize; |
| 1820 | |||
| 1821 | return (elen >> 30); | ||
| 1822 | } | 1915 | } |
| 1823 | 1916 | ||
| 1824 | int8_t udf_next_aext(struct inode *inode, struct extent_position *epos, | 1917 | int8_t udf_next_aext(struct inode *inode, struct extent_position *epos, |
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); |
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h index eba48209f9f3..dbd52d4b5eed 100644 --- a/fs/udf/udfdecl.h +++ b/fs/udf/udfdecl.h | |||
| @@ -136,22 +136,20 @@ extern int udf_write_fi(struct inode *inode, struct fileIdentDesc *, | |||
| 136 | extern long udf_ioctl(struct file *, unsigned int, unsigned long); | 136 | extern long udf_ioctl(struct file *, unsigned int, unsigned long); |
| 137 | /* inode.c */ | 137 | /* inode.c */ |
| 138 | extern struct inode *udf_iget(struct super_block *, struct kernel_lb_addr *); | 138 | extern struct inode *udf_iget(struct super_block *, struct kernel_lb_addr *); |
| 139 | extern void udf_expand_file_adinicb(struct inode *, int, int *); | 139 | extern int udf_expand_file_adinicb(struct inode *); |
| 140 | extern struct buffer_head *udf_expand_dir_adinicb(struct inode *, int *, int *); | 140 | extern struct buffer_head *udf_expand_dir_adinicb(struct inode *, int *, int *); |
| 141 | extern struct buffer_head *udf_bread(struct inode *, int, int, int *); | 141 | extern struct buffer_head *udf_bread(struct inode *, int, int, int *); |
| 142 | extern void udf_truncate(struct inode *); | 142 | extern int udf_setsize(struct inode *, loff_t); |
| 143 | extern void udf_read_inode(struct inode *); | 143 | extern void udf_read_inode(struct inode *); |
| 144 | extern void udf_evict_inode(struct inode *); | 144 | extern void udf_evict_inode(struct inode *); |
| 145 | extern int udf_write_inode(struct inode *, struct writeback_control *wbc); | 145 | extern int udf_write_inode(struct inode *, struct writeback_control *wbc); |
| 146 | extern long udf_block_map(struct inode *, sector_t); | 146 | extern long udf_block_map(struct inode *, sector_t); |
| 147 | extern int udf_extend_file(struct inode *, struct extent_position *, | ||
| 148 | struct kernel_long_ad *, sector_t); | ||
| 149 | extern int8_t inode_bmap(struct inode *, sector_t, struct extent_position *, | 147 | extern int8_t inode_bmap(struct inode *, sector_t, struct extent_position *, |
| 150 | struct kernel_lb_addr *, uint32_t *, sector_t *); | 148 | struct kernel_lb_addr *, uint32_t *, sector_t *); |
| 151 | extern int8_t udf_add_aext(struct inode *, struct extent_position *, | 149 | extern int udf_add_aext(struct inode *, struct extent_position *, |
| 150 | struct kernel_lb_addr *, uint32_t, int); | ||
| 151 | extern void udf_write_aext(struct inode *, struct extent_position *, | ||
| 152 | struct kernel_lb_addr *, uint32_t, int); | 152 | struct kernel_lb_addr *, uint32_t, int); |
| 153 | extern int8_t udf_write_aext(struct inode *, struct extent_position *, | ||
| 154 | struct kernel_lb_addr *, uint32_t, int); | ||
| 155 | extern int8_t udf_delete_aext(struct inode *, struct extent_position, | 153 | extern int8_t udf_delete_aext(struct inode *, struct extent_position, |
| 156 | struct kernel_lb_addr, uint32_t); | 154 | struct kernel_lb_addr, uint32_t); |
| 157 | extern int8_t udf_next_aext(struct inode *, struct extent_position *, | 155 | extern int8_t udf_next_aext(struct inode *, struct extent_position *, |
