diff options
Diffstat (limited to 'fs/ext4/inode.c')
-rw-r--r-- | fs/ext4/inode.c | 256 |
1 files changed, 161 insertions, 95 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 8ca2763df091..59fbbe899acc 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -191,6 +191,7 @@ static int ext4_journal_test_restart(handle_t *handle, struct inode *inode) | |||
191 | void ext4_delete_inode (struct inode * inode) | 191 | void ext4_delete_inode (struct inode * inode) |
192 | { | 192 | { |
193 | handle_t *handle; | 193 | handle_t *handle; |
194 | int err; | ||
194 | 195 | ||
195 | if (ext4_should_order_data(inode)) | 196 | if (ext4_should_order_data(inode)) |
196 | ext4_begin_ordered_truncate(inode, 0); | 197 | ext4_begin_ordered_truncate(inode, 0); |
@@ -199,8 +200,9 @@ void ext4_delete_inode (struct inode * inode) | |||
199 | if (is_bad_inode(inode)) | 200 | if (is_bad_inode(inode)) |
200 | goto no_delete; | 201 | goto no_delete; |
201 | 202 | ||
202 | handle = start_transaction(inode); | 203 | handle = ext4_journal_start(inode, blocks_for_truncate(inode)+3); |
203 | if (IS_ERR(handle)) { | 204 | if (IS_ERR(handle)) { |
205 | ext4_std_error(inode->i_sb, PTR_ERR(handle)); | ||
204 | /* | 206 | /* |
205 | * If we're going to skip the normal cleanup, we still need to | 207 | * If we're going to skip the normal cleanup, we still need to |
206 | * make sure that the in-core orphan linked list is properly | 208 | * make sure that the in-core orphan linked list is properly |
@@ -213,8 +215,34 @@ void ext4_delete_inode (struct inode * inode) | |||
213 | if (IS_SYNC(inode)) | 215 | if (IS_SYNC(inode)) |
214 | handle->h_sync = 1; | 216 | handle->h_sync = 1; |
215 | inode->i_size = 0; | 217 | inode->i_size = 0; |
218 | err = ext4_mark_inode_dirty(handle, inode); | ||
219 | if (err) { | ||
220 | ext4_warning(inode->i_sb, __func__, | ||
221 | "couldn't mark inode dirty (err %d)", err); | ||
222 | goto stop_handle; | ||
223 | } | ||
216 | if (inode->i_blocks) | 224 | if (inode->i_blocks) |
217 | ext4_truncate(inode); | 225 | ext4_truncate(inode); |
226 | |||
227 | /* | ||
228 | * ext4_ext_truncate() doesn't reserve any slop when it | ||
229 | * restarts journal transactions; therefore there may not be | ||
230 | * enough credits left in the handle to remove the inode from | ||
231 | * the orphan list and set the dtime field. | ||
232 | */ | ||
233 | if (handle->h_buffer_credits < 3) { | ||
234 | err = ext4_journal_extend(handle, 3); | ||
235 | if (err > 0) | ||
236 | err = ext4_journal_restart(handle, 3); | ||
237 | if (err != 0) { | ||
238 | ext4_warning(inode->i_sb, __func__, | ||
239 | "couldn't extend journal (err %d)", err); | ||
240 | stop_handle: | ||
241 | ext4_journal_stop(handle); | ||
242 | goto no_delete; | ||
243 | } | ||
244 | } | ||
245 | |||
218 | /* | 246 | /* |
219 | * Kill off the orphan record which ext4_truncate created. | 247 | * Kill off the orphan record which ext4_truncate created. |
220 | * AKPM: I think this can be inside the above `if'. | 248 | * AKPM: I think this can be inside the above `if'. |
@@ -952,6 +980,67 @@ out: | |||
952 | return err; | 980 | return err; |
953 | } | 981 | } |
954 | 982 | ||
983 | /* | ||
984 | * Calculate the number of metadata blocks need to reserve | ||
985 | * to allocate @blocks for non extent file based file | ||
986 | */ | ||
987 | static int ext4_indirect_calc_metadata_amount(struct inode *inode, int blocks) | ||
988 | { | ||
989 | int icap = EXT4_ADDR_PER_BLOCK(inode->i_sb); | ||
990 | int ind_blks, dind_blks, tind_blks; | ||
991 | |||
992 | /* number of new indirect blocks needed */ | ||
993 | ind_blks = (blocks + icap - 1) / icap; | ||
994 | |||
995 | dind_blks = (ind_blks + icap - 1) / icap; | ||
996 | |||
997 | tind_blks = 1; | ||
998 | |||
999 | return ind_blks + dind_blks + tind_blks; | ||
1000 | } | ||
1001 | |||
1002 | /* | ||
1003 | * Calculate the number of metadata blocks need to reserve | ||
1004 | * to allocate given number of blocks | ||
1005 | */ | ||
1006 | static int ext4_calc_metadata_amount(struct inode *inode, int blocks) | ||
1007 | { | ||
1008 | if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) | ||
1009 | return ext4_ext_calc_metadata_amount(inode, blocks); | ||
1010 | |||
1011 | return ext4_indirect_calc_metadata_amount(inode, blocks); | ||
1012 | } | ||
1013 | |||
1014 | static void ext4_da_update_reserve_space(struct inode *inode, int used) | ||
1015 | { | ||
1016 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); | ||
1017 | int total, mdb, mdb_free; | ||
1018 | |||
1019 | spin_lock(&EXT4_I(inode)->i_block_reservation_lock); | ||
1020 | /* recalculate the number of metablocks still need to be reserved */ | ||
1021 | total = EXT4_I(inode)->i_reserved_data_blocks - used; | ||
1022 | mdb = ext4_calc_metadata_amount(inode, total); | ||
1023 | |||
1024 | /* figure out how many metablocks to release */ | ||
1025 | BUG_ON(mdb > EXT4_I(inode)->i_reserved_meta_blocks); | ||
1026 | mdb_free = EXT4_I(inode)->i_reserved_meta_blocks - mdb; | ||
1027 | |||
1028 | /* Account for allocated meta_blocks */ | ||
1029 | mdb_free -= EXT4_I(inode)->i_allocated_meta_blocks; | ||
1030 | |||
1031 | /* update fs free blocks counter for truncate case */ | ||
1032 | percpu_counter_add(&sbi->s_freeblocks_counter, mdb_free); | ||
1033 | |||
1034 | /* update per-inode reservations */ | ||
1035 | BUG_ON(used > EXT4_I(inode)->i_reserved_data_blocks); | ||
1036 | EXT4_I(inode)->i_reserved_data_blocks -= used; | ||
1037 | |||
1038 | BUG_ON(mdb > EXT4_I(inode)->i_reserved_meta_blocks); | ||
1039 | EXT4_I(inode)->i_reserved_meta_blocks = mdb; | ||
1040 | EXT4_I(inode)->i_allocated_meta_blocks = 0; | ||
1041 | spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); | ||
1042 | } | ||
1043 | |||
955 | /* Maximum number of blocks we map for direct IO at once. */ | 1044 | /* Maximum number of blocks we map for direct IO at once. */ |
956 | #define DIO_MAX_BLOCKS 4096 | 1045 | #define DIO_MAX_BLOCKS 4096 |
957 | /* | 1046 | /* |
@@ -965,10 +1054,9 @@ out: | |||
965 | 1054 | ||
966 | 1055 | ||
967 | /* | 1056 | /* |
1057 | * The ext4_get_blocks_wrap() function try to look up the requested blocks, | ||
1058 | * and returns if the blocks are already mapped. | ||
968 | * | 1059 | * |
969 | * | ||
970 | * ext4_ext4 get_block() wrapper function | ||
971 | * It will do a look up first, and returns if the blocks already mapped. | ||
972 | * Otherwise it takes the write lock of the i_data_sem and allocate blocks | 1060 | * Otherwise it takes the write lock of the i_data_sem and allocate blocks |
973 | * and store the allocated blocks in the result buffer head and mark it | 1061 | * and store the allocated blocks in the result buffer head and mark it |
974 | * mapped. | 1062 | * mapped. |
@@ -1069,7 +1157,7 @@ int ext4_get_blocks_wrap(handle_t *handle, struct inode *inode, sector_t block, | |||
1069 | * which were deferred till now | 1157 | * which were deferred till now |
1070 | */ | 1158 | */ |
1071 | if ((retval > 0) && buffer_delay(bh)) | 1159 | if ((retval > 0) && buffer_delay(bh)) |
1072 | ext4_da_release_space(inode, retval, 0); | 1160 | ext4_da_update_reserve_space(inode, retval); |
1073 | } | 1161 | } |
1074 | 1162 | ||
1075 | up_write((&EXT4_I(inode)->i_data_sem)); | 1163 | up_write((&EXT4_I(inode)->i_data_sem)); |
@@ -1336,12 +1424,8 @@ static int ext4_ordered_write_end(struct file *file, | |||
1336 | { | 1424 | { |
1337 | handle_t *handle = ext4_journal_current_handle(); | 1425 | handle_t *handle = ext4_journal_current_handle(); |
1338 | struct inode *inode = mapping->host; | 1426 | struct inode *inode = mapping->host; |
1339 | unsigned from, to; | ||
1340 | int ret = 0, ret2; | 1427 | int ret = 0, ret2; |
1341 | 1428 | ||
1342 | from = pos & (PAGE_CACHE_SIZE - 1); | ||
1343 | to = from + len; | ||
1344 | |||
1345 | ret = ext4_jbd2_file_inode(handle, inode); | 1429 | ret = ext4_jbd2_file_inode(handle, inode); |
1346 | 1430 | ||
1347 | if (ret == 0) { | 1431 | if (ret == 0) { |
@@ -1437,36 +1521,6 @@ static int ext4_journalled_write_end(struct file *file, | |||
1437 | 1521 | ||
1438 | return ret ? ret : copied; | 1522 | return ret ? ret : copied; |
1439 | } | 1523 | } |
1440 | /* | ||
1441 | * Calculate the number of metadata blocks need to reserve | ||
1442 | * to allocate @blocks for non extent file based file | ||
1443 | */ | ||
1444 | static int ext4_indirect_calc_metadata_amount(struct inode *inode, int blocks) | ||
1445 | { | ||
1446 | int icap = EXT4_ADDR_PER_BLOCK(inode->i_sb); | ||
1447 | int ind_blks, dind_blks, tind_blks; | ||
1448 | |||
1449 | /* number of new indirect blocks needed */ | ||
1450 | ind_blks = (blocks + icap - 1) / icap; | ||
1451 | |||
1452 | dind_blks = (ind_blks + icap - 1) / icap; | ||
1453 | |||
1454 | tind_blks = 1; | ||
1455 | |||
1456 | return ind_blks + dind_blks + tind_blks; | ||
1457 | } | ||
1458 | |||
1459 | /* | ||
1460 | * Calculate the number of metadata blocks need to reserve | ||
1461 | * to allocate given number of blocks | ||
1462 | */ | ||
1463 | static int ext4_calc_metadata_amount(struct inode *inode, int blocks) | ||
1464 | { | ||
1465 | if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) | ||
1466 | return ext4_ext_calc_metadata_amount(inode, blocks); | ||
1467 | |||
1468 | return ext4_indirect_calc_metadata_amount(inode, blocks); | ||
1469 | } | ||
1470 | 1524 | ||
1471 | static int ext4_da_reserve_space(struct inode *inode, int nrblocks) | 1525 | static int ext4_da_reserve_space(struct inode *inode, int nrblocks) |
1472 | { | 1526 | { |
@@ -1490,7 +1544,6 @@ static int ext4_da_reserve_space(struct inode *inode, int nrblocks) | |||
1490 | spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); | 1544 | spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); |
1491 | return -ENOSPC; | 1545 | return -ENOSPC; |
1492 | } | 1546 | } |
1493 | |||
1494 | /* reduce fs free blocks counter */ | 1547 | /* reduce fs free blocks counter */ |
1495 | percpu_counter_sub(&sbi->s_freeblocks_counter, total); | 1548 | percpu_counter_sub(&sbi->s_freeblocks_counter, total); |
1496 | 1549 | ||
@@ -1501,35 +1554,31 @@ static int ext4_da_reserve_space(struct inode *inode, int nrblocks) | |||
1501 | return 0; /* success */ | 1554 | return 0; /* success */ |
1502 | } | 1555 | } |
1503 | 1556 | ||
1504 | void ext4_da_release_space(struct inode *inode, int used, int to_free) | 1557 | static void ext4_da_release_space(struct inode *inode, int to_free) |
1505 | { | 1558 | { |
1506 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); | 1559 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); |
1507 | int total, mdb, mdb_free, release; | 1560 | int total, mdb, mdb_free, release; |
1508 | 1561 | ||
1509 | spin_lock(&EXT4_I(inode)->i_block_reservation_lock); | 1562 | spin_lock(&EXT4_I(inode)->i_block_reservation_lock); |
1510 | /* recalculate the number of metablocks still need to be reserved */ | 1563 | /* recalculate the number of metablocks still need to be reserved */ |
1511 | total = EXT4_I(inode)->i_reserved_data_blocks - used - to_free; | 1564 | total = EXT4_I(inode)->i_reserved_data_blocks - to_free; |
1512 | mdb = ext4_calc_metadata_amount(inode, total); | 1565 | mdb = ext4_calc_metadata_amount(inode, total); |
1513 | 1566 | ||
1514 | /* figure out how many metablocks to release */ | 1567 | /* figure out how many metablocks to release */ |
1515 | BUG_ON(mdb > EXT4_I(inode)->i_reserved_meta_blocks); | 1568 | BUG_ON(mdb > EXT4_I(inode)->i_reserved_meta_blocks); |
1516 | mdb_free = EXT4_I(inode)->i_reserved_meta_blocks - mdb; | 1569 | mdb_free = EXT4_I(inode)->i_reserved_meta_blocks - mdb; |
1517 | 1570 | ||
1518 | /* Account for allocated meta_blocks */ | ||
1519 | mdb_free -= EXT4_I(inode)->i_allocated_meta_blocks; | ||
1520 | |||
1521 | release = to_free + mdb_free; | 1571 | release = to_free + mdb_free; |
1522 | 1572 | ||
1523 | /* update fs free blocks counter for truncate case */ | 1573 | /* update fs free blocks counter for truncate case */ |
1524 | percpu_counter_add(&sbi->s_freeblocks_counter, release); | 1574 | percpu_counter_add(&sbi->s_freeblocks_counter, release); |
1525 | 1575 | ||
1526 | /* update per-inode reservations */ | 1576 | /* update per-inode reservations */ |
1527 | BUG_ON(used + to_free > EXT4_I(inode)->i_reserved_data_blocks); | 1577 | BUG_ON(to_free > EXT4_I(inode)->i_reserved_data_blocks); |
1528 | EXT4_I(inode)->i_reserved_data_blocks -= (used + to_free); | 1578 | EXT4_I(inode)->i_reserved_data_blocks -= to_free; |
1529 | 1579 | ||
1530 | BUG_ON(mdb > EXT4_I(inode)->i_reserved_meta_blocks); | 1580 | BUG_ON(mdb > EXT4_I(inode)->i_reserved_meta_blocks); |
1531 | EXT4_I(inode)->i_reserved_meta_blocks = mdb; | 1581 | EXT4_I(inode)->i_reserved_meta_blocks = mdb; |
1532 | EXT4_I(inode)->i_allocated_meta_blocks = 0; | ||
1533 | spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); | 1582 | spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); |
1534 | } | 1583 | } |
1535 | 1584 | ||
@@ -1551,7 +1600,7 @@ static void ext4_da_page_release_reservation(struct page *page, | |||
1551 | } | 1600 | } |
1552 | curr_off = next_off; | 1601 | curr_off = next_off; |
1553 | } while ((bh = bh->b_this_page) != head); | 1602 | } while ((bh = bh->b_this_page) != head); |
1554 | ext4_da_release_space(page->mapping->host, 0, to_release); | 1603 | ext4_da_release_space(page->mapping->host, to_release); |
1555 | } | 1604 | } |
1556 | 1605 | ||
1557 | /* | 1606 | /* |
@@ -2280,8 +2329,11 @@ retry: | |||
2280 | } | 2329 | } |
2281 | 2330 | ||
2282 | page = __grab_cache_page(mapping, index); | 2331 | page = __grab_cache_page(mapping, index); |
2283 | if (!page) | 2332 | if (!page) { |
2284 | return -ENOMEM; | 2333 | ext4_journal_stop(handle); |
2334 | ret = -ENOMEM; | ||
2335 | goto out; | ||
2336 | } | ||
2285 | *pagep = page; | 2337 | *pagep = page; |
2286 | 2338 | ||
2287 | ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata, | 2339 | ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata, |
@@ -2806,59 +2858,63 @@ static int ext4_journalled_set_page_dirty(struct page *page) | |||
2806 | } | 2858 | } |
2807 | 2859 | ||
2808 | static const struct address_space_operations ext4_ordered_aops = { | 2860 | static const struct address_space_operations ext4_ordered_aops = { |
2809 | .readpage = ext4_readpage, | 2861 | .readpage = ext4_readpage, |
2810 | .readpages = ext4_readpages, | 2862 | .readpages = ext4_readpages, |
2811 | .writepage = ext4_normal_writepage, | 2863 | .writepage = ext4_normal_writepage, |
2812 | .sync_page = block_sync_page, | 2864 | .sync_page = block_sync_page, |
2813 | .write_begin = ext4_write_begin, | 2865 | .write_begin = ext4_write_begin, |
2814 | .write_end = ext4_ordered_write_end, | 2866 | .write_end = ext4_ordered_write_end, |
2815 | .bmap = ext4_bmap, | 2867 | .bmap = ext4_bmap, |
2816 | .invalidatepage = ext4_invalidatepage, | 2868 | .invalidatepage = ext4_invalidatepage, |
2817 | .releasepage = ext4_releasepage, | 2869 | .releasepage = ext4_releasepage, |
2818 | .direct_IO = ext4_direct_IO, | 2870 | .direct_IO = ext4_direct_IO, |
2819 | .migratepage = buffer_migrate_page, | 2871 | .migratepage = buffer_migrate_page, |
2872 | .is_partially_uptodate = block_is_partially_uptodate, | ||
2820 | }; | 2873 | }; |
2821 | 2874 | ||
2822 | static const struct address_space_operations ext4_writeback_aops = { | 2875 | static const struct address_space_operations ext4_writeback_aops = { |
2823 | .readpage = ext4_readpage, | 2876 | .readpage = ext4_readpage, |
2824 | .readpages = ext4_readpages, | 2877 | .readpages = ext4_readpages, |
2825 | .writepage = ext4_normal_writepage, | 2878 | .writepage = ext4_normal_writepage, |
2826 | .sync_page = block_sync_page, | 2879 | .sync_page = block_sync_page, |
2827 | .write_begin = ext4_write_begin, | 2880 | .write_begin = ext4_write_begin, |
2828 | .write_end = ext4_writeback_write_end, | 2881 | .write_end = ext4_writeback_write_end, |
2829 | .bmap = ext4_bmap, | 2882 | .bmap = ext4_bmap, |
2830 | .invalidatepage = ext4_invalidatepage, | 2883 | .invalidatepage = ext4_invalidatepage, |
2831 | .releasepage = ext4_releasepage, | 2884 | .releasepage = ext4_releasepage, |
2832 | .direct_IO = ext4_direct_IO, | 2885 | .direct_IO = ext4_direct_IO, |
2833 | .migratepage = buffer_migrate_page, | 2886 | .migratepage = buffer_migrate_page, |
2887 | .is_partially_uptodate = block_is_partially_uptodate, | ||
2834 | }; | 2888 | }; |
2835 | 2889 | ||
2836 | static const struct address_space_operations ext4_journalled_aops = { | 2890 | static const struct address_space_operations ext4_journalled_aops = { |
2837 | .readpage = ext4_readpage, | 2891 | .readpage = ext4_readpage, |
2838 | .readpages = ext4_readpages, | 2892 | .readpages = ext4_readpages, |
2839 | .writepage = ext4_journalled_writepage, | 2893 | .writepage = ext4_journalled_writepage, |
2840 | .sync_page = block_sync_page, | 2894 | .sync_page = block_sync_page, |
2841 | .write_begin = ext4_write_begin, | 2895 | .write_begin = ext4_write_begin, |
2842 | .write_end = ext4_journalled_write_end, | 2896 | .write_end = ext4_journalled_write_end, |
2843 | .set_page_dirty = ext4_journalled_set_page_dirty, | 2897 | .set_page_dirty = ext4_journalled_set_page_dirty, |
2844 | .bmap = ext4_bmap, | 2898 | .bmap = ext4_bmap, |
2845 | .invalidatepage = ext4_invalidatepage, | 2899 | .invalidatepage = ext4_invalidatepage, |
2846 | .releasepage = ext4_releasepage, | 2900 | .releasepage = ext4_releasepage, |
2901 | .is_partially_uptodate = block_is_partially_uptodate, | ||
2847 | }; | 2902 | }; |
2848 | 2903 | ||
2849 | static const struct address_space_operations ext4_da_aops = { | 2904 | static const struct address_space_operations ext4_da_aops = { |
2850 | .readpage = ext4_readpage, | 2905 | .readpage = ext4_readpage, |
2851 | .readpages = ext4_readpages, | 2906 | .readpages = ext4_readpages, |
2852 | .writepage = ext4_da_writepage, | 2907 | .writepage = ext4_da_writepage, |
2853 | .writepages = ext4_da_writepages, | 2908 | .writepages = ext4_da_writepages, |
2854 | .sync_page = block_sync_page, | 2909 | .sync_page = block_sync_page, |
2855 | .write_begin = ext4_da_write_begin, | 2910 | .write_begin = ext4_da_write_begin, |
2856 | .write_end = ext4_da_write_end, | 2911 | .write_end = ext4_da_write_end, |
2857 | .bmap = ext4_bmap, | 2912 | .bmap = ext4_bmap, |
2858 | .invalidatepage = ext4_da_invalidatepage, | 2913 | .invalidatepage = ext4_da_invalidatepage, |
2859 | .releasepage = ext4_releasepage, | 2914 | .releasepage = ext4_releasepage, |
2860 | .direct_IO = ext4_direct_IO, | 2915 | .direct_IO = ext4_direct_IO, |
2861 | .migratepage = buffer_migrate_page, | 2916 | .migratepage = buffer_migrate_page, |
2917 | .is_partially_uptodate = block_is_partially_uptodate, | ||
2862 | }; | 2918 | }; |
2863 | 2919 | ||
2864 | void ext4_set_aops(struct inode *inode) | 2920 | void ext4_set_aops(struct inode *inode) |
@@ -3586,6 +3642,16 @@ static int __ext4_get_inode_loc(struct inode *inode, | |||
3586 | } | 3642 | } |
3587 | if (!buffer_uptodate(bh)) { | 3643 | if (!buffer_uptodate(bh)) { |
3588 | lock_buffer(bh); | 3644 | lock_buffer(bh); |
3645 | |||
3646 | /* | ||
3647 | * If the buffer has the write error flag, we have failed | ||
3648 | * to write out another inode in the same block. In this | ||
3649 | * case, we don't have to read the block because we may | ||
3650 | * read the old inode data successfully. | ||
3651 | */ | ||
3652 | if (buffer_write_io_error(bh) && !buffer_uptodate(bh)) | ||
3653 | set_buffer_uptodate(bh); | ||
3654 | |||
3589 | if (buffer_uptodate(bh)) { | 3655 | if (buffer_uptodate(bh)) { |
3590 | /* someone brought it uptodate while we waited */ | 3656 | /* someone brought it uptodate while we waited */ |
3591 | unlock_buffer(bh); | 3657 | unlock_buffer(bh); |