diff options
Diffstat (limited to 'fs/ext4/extents.c')
-rw-r--r-- | fs/ext4/extents.c | 59 |
1 files changed, 40 insertions, 19 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index bc7081f1fbe8..9ae6e67090cd 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -148,6 +148,7 @@ static ext4_fsblk_t ext4_ext_find_goal(struct inode *inode, | |||
148 | { | 148 | { |
149 | struct ext4_inode_info *ei = EXT4_I(inode); | 149 | struct ext4_inode_info *ei = EXT4_I(inode); |
150 | ext4_fsblk_t bg_start; | 150 | ext4_fsblk_t bg_start; |
151 | ext4_fsblk_t last_block; | ||
151 | ext4_grpblk_t colour; | 152 | ext4_grpblk_t colour; |
152 | int depth; | 153 | int depth; |
153 | 154 | ||
@@ -169,8 +170,13 @@ static ext4_fsblk_t ext4_ext_find_goal(struct inode *inode, | |||
169 | /* OK. use inode's group */ | 170 | /* OK. use inode's group */ |
170 | bg_start = (ei->i_block_group * EXT4_BLOCKS_PER_GROUP(inode->i_sb)) + | 171 | bg_start = (ei->i_block_group * EXT4_BLOCKS_PER_GROUP(inode->i_sb)) + |
171 | le32_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_first_data_block); | 172 | le32_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_first_data_block); |
172 | colour = (current->pid % 16) * | 173 | last_block = ext4_blocks_count(EXT4_SB(inode->i_sb)->s_es) - 1; |
174 | |||
175 | if (bg_start + EXT4_BLOCKS_PER_GROUP(inode->i_sb) <= last_block) | ||
176 | colour = (current->pid % 16) * | ||
173 | (EXT4_BLOCKS_PER_GROUP(inode->i_sb) / 16); | 177 | (EXT4_BLOCKS_PER_GROUP(inode->i_sb) / 16); |
178 | else | ||
179 | colour = (current->pid % 16) * ((last_block - bg_start) / 16); | ||
174 | return bg_start + colour + block; | 180 | return bg_start + colour + block; |
175 | } | 181 | } |
176 | 182 | ||
@@ -349,7 +355,7 @@ static void ext4_ext_show_leaf(struct inode *inode, struct ext4_ext_path *path) | |||
349 | #define ext4_ext_show_leaf(inode,path) | 355 | #define ext4_ext_show_leaf(inode,path) |
350 | #endif | 356 | #endif |
351 | 357 | ||
352 | static void ext4_ext_drop_refs(struct ext4_ext_path *path) | 358 | void ext4_ext_drop_refs(struct ext4_ext_path *path) |
353 | { | 359 | { |
354 | int depth = path->p_depth; | 360 | int depth = path->p_depth; |
355 | int i; | 361 | int i; |
@@ -2168,6 +2174,10 @@ static int ext4_ext_convert_to_initialized(handle_t *handle, | |||
2168 | newblock = iblock - ee_block + ext_pblock(ex); | 2174 | newblock = iblock - ee_block + ext_pblock(ex); |
2169 | ex2 = ex; | 2175 | ex2 = ex; |
2170 | 2176 | ||
2177 | err = ext4_ext_get_access(handle, inode, path + depth); | ||
2178 | if (err) | ||
2179 | goto out; | ||
2180 | |||
2171 | /* ex1: ee_block to iblock - 1 : uninitialized */ | 2181 | /* ex1: ee_block to iblock - 1 : uninitialized */ |
2172 | if (iblock > ee_block) { | 2182 | if (iblock > ee_block) { |
2173 | ex1 = ex; | 2183 | ex1 = ex; |
@@ -2200,16 +2210,20 @@ static int ext4_ext_convert_to_initialized(handle_t *handle, | |||
2200 | newdepth = ext_depth(inode); | 2210 | newdepth = ext_depth(inode); |
2201 | if (newdepth != depth) { | 2211 | if (newdepth != depth) { |
2202 | depth = newdepth; | 2212 | depth = newdepth; |
2203 | path = ext4_ext_find_extent(inode, iblock, NULL); | 2213 | ext4_ext_drop_refs(path); |
2214 | path = ext4_ext_find_extent(inode, iblock, path); | ||
2204 | if (IS_ERR(path)) { | 2215 | if (IS_ERR(path)) { |
2205 | err = PTR_ERR(path); | 2216 | err = PTR_ERR(path); |
2206 | path = NULL; | ||
2207 | goto out; | 2217 | goto out; |
2208 | } | 2218 | } |
2209 | eh = path[depth].p_hdr; | 2219 | eh = path[depth].p_hdr; |
2210 | ex = path[depth].p_ext; | 2220 | ex = path[depth].p_ext; |
2211 | if (ex2 != &newex) | 2221 | if (ex2 != &newex) |
2212 | ex2 = ex; | 2222 | ex2 = ex; |
2223 | |||
2224 | err = ext4_ext_get_access(handle, inode, path + depth); | ||
2225 | if (err) | ||
2226 | goto out; | ||
2213 | } | 2227 | } |
2214 | allocated = max_blocks; | 2228 | allocated = max_blocks; |
2215 | } | 2229 | } |
@@ -2230,9 +2244,6 @@ static int ext4_ext_convert_to_initialized(handle_t *handle, | |||
2230 | ex2->ee_len = cpu_to_le16(allocated); | 2244 | ex2->ee_len = cpu_to_le16(allocated); |
2231 | if (ex2 != ex) | 2245 | if (ex2 != ex) |
2232 | goto insert; | 2246 | goto insert; |
2233 | err = ext4_ext_get_access(handle, inode, path + depth); | ||
2234 | if (err) | ||
2235 | goto out; | ||
2236 | /* | 2247 | /* |
2237 | * New (initialized) extent starts from the first block | 2248 | * New (initialized) extent starts from the first block |
2238 | * in the current extent. i.e., ex2 == ex | 2249 | * in the current extent. i.e., ex2 == ex |
@@ -2276,9 +2287,22 @@ out: | |||
2276 | } | 2287 | } |
2277 | 2288 | ||
2278 | /* | 2289 | /* |
2290 | * Block allocation/map/preallocation routine for extents based files | ||
2291 | * | ||
2292 | * | ||
2279 | * Need to be called with | 2293 | * Need to be called with |
2280 | * down_read(&EXT4_I(inode)->i_data_sem) if not allocating file system block | 2294 | * down_read(&EXT4_I(inode)->i_data_sem) if not allocating file system block |
2281 | * (ie, create is zero). Otherwise down_write(&EXT4_I(inode)->i_data_sem) | 2295 | * (ie, create is zero). Otherwise down_write(&EXT4_I(inode)->i_data_sem) |
2296 | * | ||
2297 | * return > 0, number of of blocks already mapped/allocated | ||
2298 | * if create == 0 and these are pre-allocated blocks | ||
2299 | * buffer head is unmapped | ||
2300 | * otherwise blocks are mapped | ||
2301 | * | ||
2302 | * return = 0, if plain look up failed (blocks have not been allocated) | ||
2303 | * buffer head is unmapped | ||
2304 | * | ||
2305 | * return < 0, error case. | ||
2282 | */ | 2306 | */ |
2283 | int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, | 2307 | int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, |
2284 | ext4_lblk_t iblock, | 2308 | ext4_lblk_t iblock, |
@@ -2623,7 +2647,7 @@ long ext4_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len) | |||
2623 | * modify 1 super block, 1 block bitmap and 1 group descriptor. | 2647 | * modify 1 super block, 1 block bitmap and 1 group descriptor. |
2624 | */ | 2648 | */ |
2625 | credits = EXT4_DATA_TRANS_BLOCKS(inode->i_sb) + 3; | 2649 | credits = EXT4_DATA_TRANS_BLOCKS(inode->i_sb) + 3; |
2626 | down_write((&EXT4_I(inode)->i_data_sem)); | 2650 | mutex_lock(&inode->i_mutex); |
2627 | retry: | 2651 | retry: |
2628 | while (ret >= 0 && ret < max_blocks) { | 2652 | while (ret >= 0 && ret < max_blocks) { |
2629 | block = block + ret; | 2653 | block = block + ret; |
@@ -2634,16 +2658,17 @@ retry: | |||
2634 | break; | 2658 | break; |
2635 | } | 2659 | } |
2636 | 2660 | ||
2637 | ret = ext4_ext_get_blocks(handle, inode, block, | 2661 | ret = ext4_get_blocks_wrap(handle, inode, block, |
2638 | max_blocks, &map_bh, | 2662 | max_blocks, &map_bh, |
2639 | EXT4_CREATE_UNINITIALIZED_EXT, 0); | 2663 | EXT4_CREATE_UNINITIALIZED_EXT, 0); |
2640 | WARN_ON(ret <= 0); | ||
2641 | if (ret <= 0) { | 2664 | if (ret <= 0) { |
2642 | ext4_error(inode->i_sb, "ext4_fallocate", | 2665 | #ifdef EXT4FS_DEBUG |
2643 | "ext4_ext_get_blocks returned error: " | 2666 | WARN_ON(ret <= 0); |
2644 | "inode#%lu, block=%u, max_blocks=%lu", | 2667 | printk(KERN_ERR "%s: ext4_ext_get_blocks " |
2668 | "returned error inode#%lu, block=%u, " | ||
2669 | "max_blocks=%lu", __func__, | ||
2645 | inode->i_ino, block, max_blocks); | 2670 | inode->i_ino, block, max_blocks); |
2646 | ret = -EIO; | 2671 | #endif |
2647 | ext4_mark_inode_dirty(handle, inode); | 2672 | ext4_mark_inode_dirty(handle, inode); |
2648 | ret2 = ext4_journal_stop(handle); | 2673 | ret2 = ext4_journal_stop(handle); |
2649 | break; | 2674 | break; |
@@ -2680,7 +2705,6 @@ retry: | |||
2680 | if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) | 2705 | if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) |
2681 | goto retry; | 2706 | goto retry; |
2682 | 2707 | ||
2683 | up_write((&EXT4_I(inode)->i_data_sem)); | ||
2684 | /* | 2708 | /* |
2685 | * Time to update the file size. | 2709 | * Time to update the file size. |
2686 | * Update only when preallocation was requested beyond the file size. | 2710 | * Update only when preallocation was requested beyond the file size. |
@@ -2692,21 +2716,18 @@ retry: | |||
2692 | * if no error, we assume preallocation succeeded | 2716 | * if no error, we assume preallocation succeeded |
2693 | * completely | 2717 | * completely |
2694 | */ | 2718 | */ |
2695 | mutex_lock(&inode->i_mutex); | ||
2696 | i_size_write(inode, offset + len); | 2719 | i_size_write(inode, offset + len); |
2697 | EXT4_I(inode)->i_disksize = i_size_read(inode); | 2720 | EXT4_I(inode)->i_disksize = i_size_read(inode); |
2698 | mutex_unlock(&inode->i_mutex); | ||
2699 | } else if (ret < 0 && nblocks) { | 2721 | } else if (ret < 0 && nblocks) { |
2700 | /* Handle partial allocation scenario */ | 2722 | /* Handle partial allocation scenario */ |
2701 | loff_t newsize; | 2723 | loff_t newsize; |
2702 | 2724 | ||
2703 | mutex_lock(&inode->i_mutex); | ||
2704 | newsize = (nblocks << blkbits) + i_size_read(inode); | 2725 | newsize = (nblocks << blkbits) + i_size_read(inode); |
2705 | i_size_write(inode, EXT4_BLOCK_ALIGN(newsize, blkbits)); | 2726 | i_size_write(inode, EXT4_BLOCK_ALIGN(newsize, blkbits)); |
2706 | EXT4_I(inode)->i_disksize = i_size_read(inode); | 2727 | EXT4_I(inode)->i_disksize = i_size_read(inode); |
2707 | mutex_unlock(&inode->i_mutex); | ||
2708 | } | 2728 | } |
2709 | } | 2729 | } |
2710 | 2730 | ||
2731 | mutex_unlock(&inode->i_mutex); | ||
2711 | return ret > 0 ? ret2 : ret; | 2732 | return ret > 0 ? ret2 : ret; |
2712 | } | 2733 | } |