diff options
author | Alex Tomas <alex@clusterfs.com> | 2008-01-29 00:19:52 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2008-01-29 00:19:52 -0500 |
commit | c9de560ded61faa5b754137b7753da252391c55a (patch) | |
tree | 2c4311377c4aa72450e27f531e198fe3e1c67db0 /fs/ext4/extents.c | |
parent | 1988b51e476bd097d910c9245b53f2e38aedaf0d (diff) |
ext4: Add multi block allocator for ext4
Signed-off-by: Alex Tomas <alex@clusterfs.com>
Signed-off-by: Andreas Dilger <adilger@clusterfs.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/extents.c')
-rw-r--r-- | fs/ext4/extents.c | 45 |
1 files changed, 36 insertions, 9 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index f5cf2a94b6fc..0cffb59fff46 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -853,7 +853,7 @@ cleanup: | |||
853 | for (i = 0; i < depth; i++) { | 853 | for (i = 0; i < depth; i++) { |
854 | if (!ablocks[i]) | 854 | if (!ablocks[i]) |
855 | continue; | 855 | continue; |
856 | ext4_free_blocks(handle, inode, ablocks[i], 1); | 856 | ext4_free_blocks(handle, inode, ablocks[i], 1, 1); |
857 | } | 857 | } |
858 | } | 858 | } |
859 | kfree(ablocks); | 859 | kfree(ablocks); |
@@ -1698,7 +1698,7 @@ static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode, | |||
1698 | ext_debug("index is empty, remove it, free block %llu\n", leaf); | 1698 | ext_debug("index is empty, remove it, free block %llu\n", leaf); |
1699 | bh = sb_find_get_block(inode->i_sb, leaf); | 1699 | bh = sb_find_get_block(inode->i_sb, leaf); |
1700 | ext4_forget(handle, 1, inode, bh, leaf); | 1700 | ext4_forget(handle, 1, inode, bh, leaf); |
1701 | ext4_free_blocks(handle, inode, leaf, 1); | 1701 | ext4_free_blocks(handle, inode, leaf, 1, 1); |
1702 | return err; | 1702 | return err; |
1703 | } | 1703 | } |
1704 | 1704 | ||
@@ -1759,8 +1759,10 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode, | |||
1759 | { | 1759 | { |
1760 | struct buffer_head *bh; | 1760 | struct buffer_head *bh; |
1761 | unsigned short ee_len = ext4_ext_get_actual_len(ex); | 1761 | unsigned short ee_len = ext4_ext_get_actual_len(ex); |
1762 | int i; | 1762 | int i, metadata = 0; |
1763 | 1763 | ||
1764 | if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) | ||
1765 | metadata = 1; | ||
1764 | #ifdef EXTENTS_STATS | 1766 | #ifdef EXTENTS_STATS |
1765 | { | 1767 | { |
1766 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); | 1768 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); |
@@ -1789,7 +1791,7 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode, | |||
1789 | bh = sb_find_get_block(inode->i_sb, start + i); | 1791 | bh = sb_find_get_block(inode->i_sb, start + i); |
1790 | ext4_forget(handle, 0, inode, bh, start + i); | 1792 | ext4_forget(handle, 0, inode, bh, start + i); |
1791 | } | 1793 | } |
1792 | ext4_free_blocks(handle, inode, start, num); | 1794 | ext4_free_blocks(handle, inode, start, num, metadata); |
1793 | } else if (from == le32_to_cpu(ex->ee_block) | 1795 | } else if (from == le32_to_cpu(ex->ee_block) |
1794 | && to <= le32_to_cpu(ex->ee_block) + ee_len - 1) { | 1796 | && to <= le32_to_cpu(ex->ee_block) + ee_len - 1) { |
1795 | printk(KERN_INFO "strange request: removal %u-%u from %u:%u\n", | 1797 | printk(KERN_INFO "strange request: removal %u-%u from %u:%u\n", |
@@ -2287,6 +2289,7 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, | |||
2287 | ext4_fsblk_t goal, newblock; | 2289 | ext4_fsblk_t goal, newblock; |
2288 | int err = 0, depth, ret; | 2290 | int err = 0, depth, ret; |
2289 | unsigned long allocated = 0; | 2291 | unsigned long allocated = 0; |
2292 | struct ext4_allocation_request ar; | ||
2290 | 2293 | ||
2291 | __clear_bit(BH_New, &bh_result->b_state); | 2294 | __clear_bit(BH_New, &bh_result->b_state); |
2292 | ext_debug("blocks %u/%lu requested for inode %u\n", | 2295 | ext_debug("blocks %u/%lu requested for inode %u\n", |
@@ -2397,8 +2400,15 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, | |||
2397 | if (S_ISREG(inode->i_mode) && (!EXT4_I(inode)->i_block_alloc_info)) | 2400 | if (S_ISREG(inode->i_mode) && (!EXT4_I(inode)->i_block_alloc_info)) |
2398 | ext4_init_block_alloc_info(inode); | 2401 | ext4_init_block_alloc_info(inode); |
2399 | 2402 | ||
2400 | /* allocate new block */ | 2403 | /* find neighbour allocated blocks */ |
2401 | goal = ext4_ext_find_goal(inode, path, iblock); | 2404 | ar.lleft = iblock; |
2405 | err = ext4_ext_search_left(inode, path, &ar.lleft, &ar.pleft); | ||
2406 | if (err) | ||
2407 | goto out2; | ||
2408 | ar.lright = iblock; | ||
2409 | err = ext4_ext_search_right(inode, path, &ar.lright, &ar.pright); | ||
2410 | if (err) | ||
2411 | goto out2; | ||
2402 | 2412 | ||
2403 | /* | 2413 | /* |
2404 | * See if request is beyond maximum number of blocks we can have in | 2414 | * See if request is beyond maximum number of blocks we can have in |
@@ -2421,7 +2431,18 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, | |||
2421 | allocated = le16_to_cpu(newex.ee_len); | 2431 | allocated = le16_to_cpu(newex.ee_len); |
2422 | else | 2432 | else |
2423 | allocated = max_blocks; | 2433 | allocated = max_blocks; |
2424 | newblock = ext4_new_blocks(handle, inode, goal, &allocated, &err); | 2434 | |
2435 | /* allocate new block */ | ||
2436 | ar.inode = inode; | ||
2437 | ar.goal = ext4_ext_find_goal(inode, path, iblock); | ||
2438 | ar.logical = iblock; | ||
2439 | ar.len = allocated; | ||
2440 | if (S_ISREG(inode->i_mode)) | ||
2441 | ar.flags = EXT4_MB_HINT_DATA; | ||
2442 | else | ||
2443 | /* disable in-core preallocation for non-regular files */ | ||
2444 | ar.flags = 0; | ||
2445 | newblock = ext4_mb_new_blocks(handle, &ar, &err); | ||
2425 | if (!newblock) | 2446 | if (!newblock) |
2426 | goto out2; | 2447 | goto out2; |
2427 | ext_debug("allocate new block: goal %llu, found %llu/%lu\n", | 2448 | ext_debug("allocate new block: goal %llu, found %llu/%lu\n", |
@@ -2429,14 +2450,17 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, | |||
2429 | 2450 | ||
2430 | /* try to insert new extent into found leaf and return */ | 2451 | /* try to insert new extent into found leaf and return */ |
2431 | ext4_ext_store_pblock(&newex, newblock); | 2452 | ext4_ext_store_pblock(&newex, newblock); |
2432 | newex.ee_len = cpu_to_le16(allocated); | 2453 | newex.ee_len = cpu_to_le16(ar.len); |
2433 | if (create == EXT4_CREATE_UNINITIALIZED_EXT) /* Mark uninitialized */ | 2454 | if (create == EXT4_CREATE_UNINITIALIZED_EXT) /* Mark uninitialized */ |
2434 | ext4_ext_mark_uninitialized(&newex); | 2455 | ext4_ext_mark_uninitialized(&newex); |
2435 | err = ext4_ext_insert_extent(handle, inode, path, &newex); | 2456 | err = ext4_ext_insert_extent(handle, inode, path, &newex); |
2436 | if (err) { | 2457 | if (err) { |
2437 | /* free data blocks we just allocated */ | 2458 | /* free data blocks we just allocated */ |
2459 | /* not a good idea to call discard here directly, | ||
2460 | * but otherwise we'd need to call it every free() */ | ||
2461 | ext4_mb_discard_inode_preallocations(inode); | ||
2438 | ext4_free_blocks(handle, inode, ext_pblock(&newex), | 2462 | ext4_free_blocks(handle, inode, ext_pblock(&newex), |
2439 | le16_to_cpu(newex.ee_len)); | 2463 | le16_to_cpu(newex.ee_len), 0); |
2440 | goto out2; | 2464 | goto out2; |
2441 | } | 2465 | } |
2442 | 2466 | ||
@@ -2445,6 +2469,7 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, | |||
2445 | 2469 | ||
2446 | /* previous routine could use block we allocated */ | 2470 | /* previous routine could use block we allocated */ |
2447 | newblock = ext_pblock(&newex); | 2471 | newblock = ext_pblock(&newex); |
2472 | allocated = le16_to_cpu(newex.ee_len); | ||
2448 | outnew: | 2473 | outnew: |
2449 | __set_bit(BH_New, &bh_result->b_state); | 2474 | __set_bit(BH_New, &bh_result->b_state); |
2450 | 2475 | ||
@@ -2496,6 +2521,8 @@ void ext4_ext_truncate(struct inode * inode, struct page *page) | |||
2496 | down_write(&EXT4_I(inode)->i_data_sem); | 2521 | down_write(&EXT4_I(inode)->i_data_sem); |
2497 | ext4_ext_invalidate_cache(inode); | 2522 | ext4_ext_invalidate_cache(inode); |
2498 | 2523 | ||
2524 | ext4_mb_discard_inode_preallocations(inode); | ||
2525 | |||
2499 | /* | 2526 | /* |
2500 | * TODO: optimization is possible here. | 2527 | * TODO: optimization is possible here. |
2501 | * Probably we need not scan at all, | 2528 | * Probably we need not scan at all, |