aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2010-10-21 18:30:26 -0400
committerJan Kara <jack@suse.cz>2011-02-23 05:00:37 -0500
commit7e49b6f2480cb9a9e7322a91592e56a5c85361f5 (patch)
tree52a4966f5f1a93506a9a6604a9dfd2c390795cf0
parent4a508dd259f5995b8d31c576b894263f5947d654 (diff)
udf: Convert UDF to new truncate calling sequence
Use new truncation sequence in UDF and fix up error handling in the code. Signed-off-by: Jan Kara <jack@suse.cz>
-rw-r--r--fs/udf/file.c7
-rw-r--r--fs/udf/inode.c239
-rw-r--r--fs/udf/truncate.c146
-rw-r--r--fs/udf/udfdecl.h12
4 files changed, 234 insertions, 170 deletions
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
250const struct inode_operations udf_file_inode_operations = { 250const 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
142void udf_expand_file_adinicb(struct inode *inode, int newsize, int *err) 149int 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
191struct buffer_head *udf_expand_dir_adinicb(struct inode *inode, int *block, 212struct 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 */
351int udf_extend_file(struct inode *inode, struct extent_position *last_pos, 372static 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
439out: 465out:
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
488static 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;
540out:
541 brelse(epos.bh);
542 return err;
543}
544
461static struct buffer_head *inode_getblk(struct inode *inode, sector_t block, 545static 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
1008void udf_truncate(struct inode *inode) 1090int 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 1143update_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
1056static void __udf_read_inode(struct inode *inode) 1152static 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
1640int8_t udf_add_aext(struct inode *inode, struct extent_position *epos, 1736int 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
1770int8_t udf_write_aext(struct inode *inode, struct extent_position *epos, 1865void 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
1824int8_t udf_next_aext(struct inode *inode, struct extent_position *epos, 1917int8_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 */
200void udf_truncate_extents(struct inode *inode) 205void 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 *,
136extern long udf_ioctl(struct file *, unsigned int, unsigned long); 136extern long udf_ioctl(struct file *, unsigned int, unsigned long);
137/* inode.c */ 137/* inode.c */
138extern struct inode *udf_iget(struct super_block *, struct kernel_lb_addr *); 138extern struct inode *udf_iget(struct super_block *, struct kernel_lb_addr *);
139extern void udf_expand_file_adinicb(struct inode *, int, int *); 139extern int udf_expand_file_adinicb(struct inode *);
140extern struct buffer_head *udf_expand_dir_adinicb(struct inode *, int *, int *); 140extern struct buffer_head *udf_expand_dir_adinicb(struct inode *, int *, int *);
141extern struct buffer_head *udf_bread(struct inode *, int, int, int *); 141extern struct buffer_head *udf_bread(struct inode *, int, int, int *);
142extern void udf_truncate(struct inode *); 142extern int udf_setsize(struct inode *, loff_t);
143extern void udf_read_inode(struct inode *); 143extern void udf_read_inode(struct inode *);
144extern void udf_evict_inode(struct inode *); 144extern void udf_evict_inode(struct inode *);
145extern int udf_write_inode(struct inode *, struct writeback_control *wbc); 145extern int udf_write_inode(struct inode *, struct writeback_control *wbc);
146extern long udf_block_map(struct inode *, sector_t); 146extern long udf_block_map(struct inode *, sector_t);
147extern int udf_extend_file(struct inode *, struct extent_position *,
148 struct kernel_long_ad *, sector_t);
149extern int8_t inode_bmap(struct inode *, sector_t, struct extent_position *, 147extern 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 *);
151extern int8_t udf_add_aext(struct inode *, struct extent_position *, 149extern int udf_add_aext(struct inode *, struct extent_position *,
150 struct kernel_lb_addr *, uint32_t, int);
151extern 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);
153extern int8_t udf_write_aext(struct inode *, struct extent_position *,
154 struct kernel_lb_addr *, uint32_t, int);
155extern int8_t udf_delete_aext(struct inode *, struct extent_position, 153extern int8_t udf_delete_aext(struct inode *, struct extent_position,
156 struct kernel_lb_addr, uint32_t); 154 struct kernel_lb_addr, uint32_t);
157extern int8_t udf_next_aext(struct inode *, struct extent_position *, 155extern int8_t udf_next_aext(struct inode *, struct extent_position *,