aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/extents.c
diff options
context:
space:
mode:
authorAlex Tomas <alex@clusterfs.com>2008-01-29 00:19:52 -0500
committerTheodore Ts'o <tytso@mit.edu>2008-01-29 00:19:52 -0500
commitc9de560ded61faa5b754137b7753da252391c55a (patch)
tree2c4311377c4aa72450e27f531e198fe3e1c67db0 /fs/ext4/extents.c
parent1988b51e476bd097d910c9245b53f2e38aedaf0d (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.c45
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);
2448outnew: 2473outnew:
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,