aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/extents.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4/extents.c')
-rw-r--r--fs/ext4/extents.c59
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
352static void ext4_ext_drop_refs(struct ext4_ext_path *path) 358void 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 */
2283int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, 2307int 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);
2627retry: 2651retry:
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}