aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2009-11-23 07:17:05 -0500
committerTheodore Ts'o <tytso@mit.edu>2009-11-23 07:17:05 -0500
commite6362609b6c71c5b802026be9cf263bbdd67a50e (patch)
treebe908b6b0566f70d31378bf11b548a0d59ae0218 /fs
parent4433871130f36585fde38e7dd817433296648945 (diff)
ext4: call ext4_forget() from ext4_free_blocks()
Add the facility for ext4_forget() to be called from ext4_free_blocks(). This simplifies the code in a large number of places, and centralizes most of the work of calling ext4_forget() into a single place. Also fix a bug in the extents migration code; it wasn't calling ext4_forget() when releasing the indirect blocks during the conversion. As a result, if the system cashed during or shortly after the extents migration, and the released indirect blocks get reused as data blocks, the journal replay would corrupt the data blocks. With this new patch, fixing this bug was as simple as adding the EXT4_FREE_BLOCKS_FORGET flags to the call to ext4_free_blocks(). Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/ext4/ext4.h10
-rw-r--r--fs/ext4/extents.c24
-rw-r--r--fs/ext4/inode.c67
-rw-r--r--fs/ext4/mballoc.c49
-rw-r--r--fs/ext4/migrate.c23
-rw-r--r--fs/ext4/xattr.c8
6 files changed, 100 insertions, 81 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 210e1b53e91..4cfc2f0edb3 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -376,6 +376,12 @@ struct ext4_new_group_data {
376 EXT4_GET_BLOCKS_DIO_CREATE_EXT) 376 EXT4_GET_BLOCKS_DIO_CREATE_EXT)
377 377
378/* 378/*
379 * Flags used by ext4_free_blocks
380 */
381#define EXT4_FREE_BLOCKS_METADATA 0x0001
382#define EXT4_FREE_BLOCKS_FORGET 0x0002
383
384/*
379 * ioctl commands 385 * ioctl commands
380 */ 386 */
381#define EXT4_IOC_GETFLAGS FS_IOC_GETFLAGS 387#define EXT4_IOC_GETFLAGS FS_IOC_GETFLAGS
@@ -1384,8 +1390,8 @@ extern void ext4_discard_preallocations(struct inode *);
1384extern int __init init_ext4_mballoc(void); 1390extern int __init init_ext4_mballoc(void);
1385extern void exit_ext4_mballoc(void); 1391extern void exit_ext4_mballoc(void);
1386extern void ext4_free_blocks(handle_t *handle, struct inode *inode, 1392extern void ext4_free_blocks(handle_t *handle, struct inode *inode,
1387 ext4_fsblk_t block, unsigned long count, 1393 struct buffer_head *bh, ext4_fsblk_t block,
1388 int metadata); 1394 unsigned long count, int flags);
1389extern int ext4_mb_add_groupinfo(struct super_block *sb, 1395extern int ext4_mb_add_groupinfo(struct super_block *sb,
1390 ext4_group_t i, struct ext4_group_desc *desc); 1396 ext4_group_t i, struct ext4_group_desc *desc);
1391extern int ext4_mb_get_buddy_cache_lock(struct super_block *, ext4_group_t); 1397extern int ext4_mb_get_buddy_cache_lock(struct super_block *, ext4_group_t);
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 74dcff84c3a..2c4a9321fb1 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -1007,7 +1007,8 @@ cleanup:
1007 for (i = 0; i < depth; i++) { 1007 for (i = 0; i < depth; i++) {
1008 if (!ablocks[i]) 1008 if (!ablocks[i])
1009 continue; 1009 continue;
1010 ext4_free_blocks(handle, inode, ablocks[i], 1, 1); 1010 ext4_free_blocks(handle, inode, 0, ablocks[i], 1,
1011 EXT4_FREE_BLOCKS_METADATA);
1011 } 1012 }
1012 } 1013 }
1013 kfree(ablocks); 1014 kfree(ablocks);
@@ -1957,7 +1958,6 @@ errout:
1957static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode, 1958static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode,
1958 struct ext4_ext_path *path) 1959 struct ext4_ext_path *path)
1959{ 1960{
1960 struct buffer_head *bh;
1961 int err; 1961 int err;
1962 ext4_fsblk_t leaf; 1962 ext4_fsblk_t leaf;
1963 1963
@@ -1973,9 +1973,8 @@ static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode,
1973 if (err) 1973 if (err)
1974 return err; 1974 return err;
1975 ext_debug("index is empty, remove it, free block %llu\n", leaf); 1975 ext_debug("index is empty, remove it, free block %llu\n", leaf);
1976 bh = sb_find_get_block(inode->i_sb, leaf); 1976 ext4_free_blocks(handle, inode, 0, leaf, 1,
1977 ext4_forget(handle, 1, inode, bh, leaf); 1977 EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET);
1978 ext4_free_blocks(handle, inode, leaf, 1, 1);
1979 return err; 1978 return err;
1980} 1979}
1981 1980
@@ -2042,12 +2041,11 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode,
2042 struct ext4_extent *ex, 2041 struct ext4_extent *ex,
2043 ext4_lblk_t from, ext4_lblk_t to) 2042 ext4_lblk_t from, ext4_lblk_t to)
2044{ 2043{
2045 struct buffer_head *bh;
2046 unsigned short ee_len = ext4_ext_get_actual_len(ex); 2044 unsigned short ee_len = ext4_ext_get_actual_len(ex);
2047 int i, metadata = 0; 2045 int flags = EXT4_FREE_BLOCKS_FORGET;
2048 2046
2049 if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) 2047 if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
2050 metadata = 1; 2048 flags |= EXT4_FREE_BLOCKS_METADATA;
2051#ifdef EXTENTS_STATS 2049#ifdef EXTENTS_STATS
2052 { 2050 {
2053 struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); 2051 struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
@@ -2072,11 +2070,7 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode,
2072 num = le32_to_cpu(ex->ee_block) + ee_len - from; 2070 num = le32_to_cpu(ex->ee_block) + ee_len - from;
2073 start = ext_pblock(ex) + ee_len - num; 2071 start = ext_pblock(ex) + ee_len - num;
2074 ext_debug("free last %u blocks starting %llu\n", num, start); 2072 ext_debug("free last %u blocks starting %llu\n", num, start);
2075 for (i = 0; i < num; i++) { 2073 ext4_free_blocks(handle, inode, 0, start, num, flags);
2076 bh = sb_find_get_block(inode->i_sb, start + i);
2077 ext4_forget(handle, metadata, inode, bh, start + i);
2078 }
2079 ext4_free_blocks(handle, inode, start, num, metadata);
2080 } else if (from == le32_to_cpu(ex->ee_block) 2074 } else if (from == le32_to_cpu(ex->ee_block)
2081 && to <= le32_to_cpu(ex->ee_block) + ee_len - 1) { 2075 && to <= le32_to_cpu(ex->ee_block) + ee_len - 1) {
2082 printk(KERN_INFO "strange request: removal %u-%u from %u:%u\n", 2076 printk(KERN_INFO "strange request: removal %u-%u from %u:%u\n",
@@ -3319,8 +3313,8 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
3319 /* not a good idea to call discard here directly, 3313 /* not a good idea to call discard here directly,
3320 * but otherwise we'd need to call it every free() */ 3314 * but otherwise we'd need to call it every free() */
3321 ext4_discard_preallocations(inode); 3315 ext4_discard_preallocations(inode);
3322 ext4_free_blocks(handle, inode, ext_pblock(&newex), 3316 ext4_free_blocks(handle, inode, 0, ext_pblock(&newex),
3323 ext4_ext_get_actual_len(&newex), 0); 3317 ext4_ext_get_actual_len(&newex), 0);
3324 goto out2; 3318 goto out2;
3325 } 3319 }
3326 3320
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 72c69432349..3b28e1fbfc9 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -669,7 +669,7 @@ allocated:
669 return ret; 669 return ret;
670failed_out: 670failed_out:
671 for (i = 0; i < index; i++) 671 for (i = 0; i < index; i++)
672 ext4_free_blocks(handle, inode, new_blocks[i], 1, 0); 672 ext4_free_blocks(handle, inode, 0, new_blocks[i], 1, 0);
673 return ret; 673 return ret;
674} 674}
675 675
@@ -765,20 +765,20 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
765 return err; 765 return err;
766failed: 766failed:
767 /* Allocation failed, free what we already allocated */ 767 /* Allocation failed, free what we already allocated */
768 ext4_free_blocks(handle, inode, 0, new_blocks[0], 1, 0);
768 for (i = 1; i <= n ; i++) { 769 for (i = 1; i <= n ; i++) {
769 BUFFER_TRACE(branch[i].bh, "call jbd2_journal_forget");
770 /* 770 /*
771 * Note: is_metadata is 0 because branch[i].bh is 771 * branch[i].bh is newly allocated, so there is no
772 * newly allocated, so there is no need to revoke the 772 * need to revoke the block, which is why we don't
773 * block. If we do, it's harmless, but not necessary. 773 * need to set EXT4_FREE_BLOCKS_METADATA.
774 */ 774 */
775 ext4_forget(handle, 0, inode, branch[i].bh, 775 ext4_free_blocks(handle, inode, 0, new_blocks[i], 1,
776 branch[i].bh->b_blocknr); 776 EXT4_FREE_BLOCKS_FORGET);
777 } 777 }
778 for (i = 0; i < indirect_blks; i++) 778 for (i = n+1; i < indirect_blks; i++)
779 ext4_free_blocks(handle, inode, new_blocks[i], 1, 0); 779 ext4_free_blocks(handle, inode, 0, new_blocks[i], 1, 0);
780 780
781 ext4_free_blocks(handle, inode, new_blocks[i], num, 0); 781 ext4_free_blocks(handle, inode, 0, new_blocks[i], num, 0);
782 782
783 return err; 783 return err;
784} 784}
@@ -857,18 +857,16 @@ static int ext4_splice_branch(handle_t *handle, struct inode *inode,
857 857
858err_out: 858err_out:
859 for (i = 1; i <= num; i++) { 859 for (i = 1; i <= num; i++) {
860 BUFFER_TRACE(where[i].bh, "call jbd2_journal_forget");
861 /* 860 /*
862 * Note: is_metadata is 0 because branch[i].bh is 861 * branch[i].bh is newly allocated, so there is no
863 * newly allocated, so there is no need to revoke the 862 * need to revoke the block, which is why we don't
864 * block. If we do, it's harmless, but not necessary. 863 * need to set EXT4_FREE_BLOCKS_METADATA.
865 */ 864 */
866 ext4_forget(handle, 0, inode, where[i].bh, 865 ext4_free_blocks(handle, inode, where[i].bh, 0, 1,
867 where[i].bh->b_blocknr); 866 EXT4_FREE_BLOCKS_FORGET);
868 ext4_free_blocks(handle, inode,
869 le32_to_cpu(where[i-1].key), 1, 0);
870 } 867 }
871 ext4_free_blocks(handle, inode, le32_to_cpu(where[num].key), blks, 0); 868 ext4_free_blocks(handle, inode, 0, le32_to_cpu(where[num].key),
869 blks, 0);
872 870
873 return err; 871 return err;
874} 872}
@@ -4080,7 +4078,10 @@ static void ext4_clear_blocks(handle_t *handle, struct inode *inode,
4080 __le32 *last) 4078 __le32 *last)
4081{ 4079{
4082 __le32 *p; 4080 __le32 *p;
4083 int is_metadata = S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode); 4081 int flags = EXT4_FREE_BLOCKS_FORGET;
4082
4083 if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
4084 flags |= EXT4_FREE_BLOCKS_METADATA;
4084 4085
4085 if (try_to_extend_transaction(handle, inode)) { 4086 if (try_to_extend_transaction(handle, inode)) {
4086 if (bh) { 4087 if (bh) {
@@ -4096,27 +4097,10 @@ static void ext4_clear_blocks(handle_t *handle, struct inode *inode,
4096 } 4097 }
4097 } 4098 }
4098 4099
4099 /* 4100 for (p = first; p < last; p++)
4100 * Any buffers which are on the journal will be in memory. We 4101 *p = 0;
4101 * find them on the hash table so jbd2_journal_revoke() will
4102 * run jbd2_journal_forget() on them. We've already detached
4103 * each block from the file, so bforget() in
4104 * jbd2_journal_forget() should be safe.
4105 *
4106 * AKPM: turn on bforget in jbd2_journal_forget()!!!
4107 */
4108 for (p = first; p < last; p++) {
4109 u32 nr = le32_to_cpu(*p);
4110 if (nr) {
4111 struct buffer_head *tbh;
4112
4113 *p = 0;
4114 tbh = sb_find_get_block(inode->i_sb, nr);
4115 ext4_forget(handle, is_metadata, inode, tbh, nr);
4116 }
4117 }
4118 4102
4119 ext4_free_blocks(handle, inode, block_to_free, count, is_metadata); 4103 ext4_free_blocks(handle, inode, 0, block_to_free, count, flags);
4120} 4104}
4121 4105
4122/** 4106/**
@@ -4304,7 +4288,8 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode,
4304 blocks_for_truncate(inode)); 4288 blocks_for_truncate(inode));
4305 } 4289 }
4306 4290
4307 ext4_free_blocks(handle, inode, nr, 1, 1); 4291 ext4_free_blocks(handle, inode, 0, nr, 1,
4292 EXT4_FREE_BLOCKS_METADATA);
4308 4293
4309 if (parent_bh) { 4294 if (parent_bh) {
4310 /* 4295 /*
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 0dca90be1af..78de5d3c5dc 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -4436,8 +4436,8 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
4436 * @metadata: Are these metadata blocks 4436 * @metadata: Are these metadata blocks
4437 */ 4437 */
4438void ext4_free_blocks(handle_t *handle, struct inode *inode, 4438void ext4_free_blocks(handle_t *handle, struct inode *inode,
4439 ext4_fsblk_t block, unsigned long count, 4439 struct buffer_head *bh, ext4_fsblk_t block,
4440 int metadata) 4440 unsigned long count, int flags)
4441{ 4441{
4442 struct buffer_head *bitmap_bh = NULL; 4442 struct buffer_head *bitmap_bh = NULL;
4443 struct super_block *sb = inode->i_sb; 4443 struct super_block *sb = inode->i_sb;
@@ -4454,15 +4454,12 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
4454 int err = 0; 4454 int err = 0;
4455 int ret; 4455 int ret;
4456 4456
4457 /* 4457 if (bh) {
4458 * We need to make sure we don't reuse the freed block until 4458 if (block)
4459 * after the transaction is committed, which we can do by 4459 BUG_ON(block != bh->b_blocknr);
4460 * treating the block as metadata, below. We make an 4460 else
4461 * exception if the inode is to be written in writeback mode 4461 block = bh->b_blocknr;
4462 * since writeback mode has weak data consistency guarantees. 4462 }
4463 */
4464 if (!ext4_should_writeback_data(inode))
4465 metadata = 1;
4466 4463
4467 sbi = EXT4_SB(sb); 4464 sbi = EXT4_SB(sb);
4468 es = EXT4_SB(sb)->s_es; 4465 es = EXT4_SB(sb)->s_es;
@@ -4476,7 +4473,32 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
4476 } 4473 }
4477 4474
4478 ext4_debug("freeing block %llu\n", block); 4475 ext4_debug("freeing block %llu\n", block);
4479 trace_ext4_free_blocks(inode, block, count, metadata); 4476 trace_ext4_free_blocks(inode, block, count, flags);
4477
4478 if (flags & EXT4_FREE_BLOCKS_FORGET) {
4479 struct buffer_head *tbh = bh;
4480 int i;
4481
4482 BUG_ON(bh && (count > 1));
4483
4484 for (i = 0; i < count; i++) {
4485 if (!bh)
4486 tbh = sb_find_get_block(inode->i_sb,
4487 block + i);
4488 ext4_forget(handle, flags & EXT4_FREE_BLOCKS_METADATA,
4489 inode, tbh, block + i);
4490 }
4491 }
4492
4493 /*
4494 * We need to make sure we don't reuse the freed block until
4495 * after the transaction is committed, which we can do by
4496 * treating the block as metadata, below. We make an
4497 * exception if the inode is to be written in writeback mode
4498 * since writeback mode has weak data consistency guarantees.
4499 */
4500 if (!ext4_should_writeback_data(inode))
4501 flags |= EXT4_FREE_BLOCKS_METADATA;
4480 4502
4481 ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS); 4503 ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
4482 if (ac) { 4504 if (ac) {
@@ -4552,7 +4574,8 @@ do_more:
4552 err = ext4_mb_load_buddy(sb, block_group, &e4b); 4574 err = ext4_mb_load_buddy(sb, block_group, &e4b);
4553 if (err) 4575 if (err)
4554 goto error_return; 4576 goto error_return;
4555 if (metadata && ext4_handle_valid(handle)) { 4577
4578 if ((flags & EXT4_FREE_BLOCKS_METADATA) && ext4_handle_valid(handle)) {
4556 struct ext4_free_data *new_entry; 4579 struct ext4_free_data *new_entry;
4557 /* 4580 /*
4558 * blocks being freed are metadata. these blocks shouldn't 4581 * blocks being freed are metadata. these blocks shouldn't
diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c
index a93d5b80f3e..d641e13e740 100644
--- a/fs/ext4/migrate.c
+++ b/fs/ext4/migrate.c
@@ -262,13 +262,17 @@ static int free_dind_blocks(handle_t *handle,
262 for (i = 0; i < max_entries; i++) { 262 for (i = 0; i < max_entries; i++) {
263 if (tmp_idata[i]) { 263 if (tmp_idata[i]) {
264 extend_credit_for_blkdel(handle, inode); 264 extend_credit_for_blkdel(handle, inode);
265 ext4_free_blocks(handle, inode, 265 ext4_free_blocks(handle, inode, 0,
266 le32_to_cpu(tmp_idata[i]), 1, 1); 266 le32_to_cpu(tmp_idata[i]), 1,
267 EXT4_FREE_BLOCKS_METADATA |
268 EXT4_FREE_BLOCKS_FORGET);
267 } 269 }
268 } 270 }
269 put_bh(bh); 271 put_bh(bh);
270 extend_credit_for_blkdel(handle, inode); 272 extend_credit_for_blkdel(handle, inode);
271 ext4_free_blocks(handle, inode, le32_to_cpu(i_data), 1, 1); 273 ext4_free_blocks(handle, inode, 0, le32_to_cpu(i_data), 1,
274 EXT4_FREE_BLOCKS_METADATA |
275 EXT4_FREE_BLOCKS_FORGET);
272 return 0; 276 return 0;
273} 277}
274 278
@@ -297,7 +301,9 @@ static int free_tind_blocks(handle_t *handle,
297 } 301 }
298 put_bh(bh); 302 put_bh(bh);
299 extend_credit_for_blkdel(handle, inode); 303 extend_credit_for_blkdel(handle, inode);
300 ext4_free_blocks(handle, inode, le32_to_cpu(i_data), 1, 1); 304 ext4_free_blocks(handle, inode, 0, le32_to_cpu(i_data), 1,
305 EXT4_FREE_BLOCKS_METADATA |
306 EXT4_FREE_BLOCKS_FORGET);
301 return 0; 307 return 0;
302} 308}
303 309
@@ -308,8 +314,10 @@ static int free_ind_block(handle_t *handle, struct inode *inode, __le32 *i_data)
308 /* ei->i_data[EXT4_IND_BLOCK] */ 314 /* ei->i_data[EXT4_IND_BLOCK] */
309 if (i_data[0]) { 315 if (i_data[0]) {
310 extend_credit_for_blkdel(handle, inode); 316 extend_credit_for_blkdel(handle, inode);
311 ext4_free_blocks(handle, inode, 317 ext4_free_blocks(handle, inode, 0,
312 le32_to_cpu(i_data[0]), 1, 1); 318 le32_to_cpu(i_data[0]), 1,
319 EXT4_FREE_BLOCKS_METADATA |
320 EXT4_FREE_BLOCKS_FORGET);
313 } 321 }
314 322
315 /* ei->i_data[EXT4_DIND_BLOCK] */ 323 /* ei->i_data[EXT4_DIND_BLOCK] */
@@ -419,7 +427,8 @@ static int free_ext_idx(handle_t *handle, struct inode *inode,
419 } 427 }
420 put_bh(bh); 428 put_bh(bh);
421 extend_credit_for_blkdel(handle, inode); 429 extend_credit_for_blkdel(handle, inode);
422 ext4_free_blocks(handle, inode, block, 1, 1); 430 ext4_free_blocks(handle, inode, 0, block, 1,
431 EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET);
423 return retval; 432 return retval;
424} 433}
425 434
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index 025701926f9..910bf9a59cb 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -482,9 +482,10 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode,
482 ea_bdebug(bh, "refcount now=0; freeing"); 482 ea_bdebug(bh, "refcount now=0; freeing");
483 if (ce) 483 if (ce)
484 mb_cache_entry_free(ce); 484 mb_cache_entry_free(ce);
485 ext4_free_blocks(handle, inode, bh->b_blocknr, 1, 1);
486 get_bh(bh); 485 get_bh(bh);
487 ext4_forget(handle, 1, inode, bh, bh->b_blocknr); 486 ext4_free_blocks(handle, inode, bh, 0, 1,
487 EXT4_FREE_BLOCKS_METADATA |
488 EXT4_FREE_BLOCKS_FORGET);
488 } else { 489 } else {
489 le32_add_cpu(&BHDR(bh)->h_refcount, -1); 490 le32_add_cpu(&BHDR(bh)->h_refcount, -1);
490 error = ext4_handle_dirty_metadata(handle, inode, bh); 491 error = ext4_handle_dirty_metadata(handle, inode, bh);
@@ -832,7 +833,8 @@ inserted:
832 new_bh = sb_getblk(sb, block); 833 new_bh = sb_getblk(sb, block);
833 if (!new_bh) { 834 if (!new_bh) {
834getblk_failed: 835getblk_failed:
835 ext4_free_blocks(handle, inode, block, 1, 1); 836 ext4_free_blocks(handle, inode, 0, block, 1,
837 EXT4_FREE_BLOCKS_METADATA);
836 error = -EIO; 838 error = -EIO;
837 goto cleanup; 839 goto cleanup;
838 } 840 }