diff options
Diffstat (limited to 'fs/ext4/inode.c')
| -rw-r--r-- | fs/ext4/inode.c | 102 |
1 files changed, 58 insertions, 44 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 830336d3911b..ff2f5fd681b5 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
| @@ -149,7 +149,7 @@ int ext4_truncate_restart_trans(handle_t *handle, struct inode *inode, | |||
| 149 | int ret; | 149 | int ret; |
| 150 | 150 | ||
| 151 | /* | 151 | /* |
| 152 | * Drop i_data_sem to avoid deadlock with ext4_get_blocks At this | 152 | * Drop i_data_sem to avoid deadlock with ext4_map_blocks. At this |
| 153 | * moment, get_block can be called only for blocks inside i_size since | 153 | * moment, get_block can be called only for blocks inside i_size since |
| 154 | * page cache has been already dropped and writes are blocked by | 154 | * page cache has been already dropped and writes are blocked by |
| 155 | * i_mutex. So we can safely drop the i_data_sem here. | 155 | * i_mutex. So we can safely drop the i_data_sem here. |
| @@ -890,9 +890,9 @@ err_out: | |||
| 890 | } | 890 | } |
| 891 | 891 | ||
| 892 | /* | 892 | /* |
| 893 | * The ext4_ind_get_blocks() function handles non-extents inodes | 893 | * The ext4_ind_map_blocks() function handles non-extents inodes |
| 894 | * (i.e., using the traditional indirect/double-indirect i_blocks | 894 | * (i.e., using the traditional indirect/double-indirect i_blocks |
| 895 | * scheme) for ext4_get_blocks(). | 895 | * scheme) for ext4_map_blocks(). |
| 896 | * | 896 | * |
| 897 | * Allocation strategy is simple: if we have to allocate something, we will | 897 | * Allocation strategy is simple: if we have to allocate something, we will |
| 898 | * have to go the whole way to leaf. So let's do it before attaching anything | 898 | * have to go the whole way to leaf. So let's do it before attaching anything |
| @@ -917,9 +917,8 @@ err_out: | |||
| 917 | * down_read(&EXT4_I(inode)->i_data_sem) if not allocating file system | 917 | * down_read(&EXT4_I(inode)->i_data_sem) if not allocating file system |
| 918 | * blocks. | 918 | * blocks. |
| 919 | */ | 919 | */ |
| 920 | static int ext4_ind_get_blocks(handle_t *handle, struct inode *inode, | 920 | static int ext4_ind_map_blocks(handle_t *handle, struct inode *inode, |
| 921 | ext4_lblk_t iblock, unsigned int maxblocks, | 921 | struct ext4_map_blocks *map, |
| 922 | struct buffer_head *bh_result, | ||
| 923 | int flags) | 922 | int flags) |
| 924 | { | 923 | { |
| 925 | int err = -EIO; | 924 | int err = -EIO; |
| @@ -935,7 +934,7 @@ static int ext4_ind_get_blocks(handle_t *handle, struct inode *inode, | |||
| 935 | 934 | ||
| 936 | J_ASSERT(!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)); | 935 | J_ASSERT(!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)); |
| 937 | J_ASSERT(handle != NULL || (flags & EXT4_GET_BLOCKS_CREATE) == 0); | 936 | J_ASSERT(handle != NULL || (flags & EXT4_GET_BLOCKS_CREATE) == 0); |
| 938 | depth = ext4_block_to_path(inode, iblock, offsets, | 937 | depth = ext4_block_to_path(inode, map->m_lblk, offsets, |
| 939 | &blocks_to_boundary); | 938 | &blocks_to_boundary); |
| 940 | 939 | ||
| 941 | if (depth == 0) | 940 | if (depth == 0) |
| @@ -946,10 +945,9 @@ static int ext4_ind_get_blocks(handle_t *handle, struct inode *inode, | |||
| 946 | /* Simplest case - block found, no allocation needed */ | 945 | /* Simplest case - block found, no allocation needed */ |
| 947 | if (!partial) { | 946 | if (!partial) { |
| 948 | first_block = le32_to_cpu(chain[depth - 1].key); | 947 | first_block = le32_to_cpu(chain[depth - 1].key); |
| 949 | clear_buffer_new(bh_result); | ||
| 950 | count++; | 948 | count++; |
| 951 | /*map more blocks*/ | 949 | /*map more blocks*/ |
| 952 | while (count < maxblocks && count <= blocks_to_boundary) { | 950 | while (count < map->m_len && count <= blocks_to_boundary) { |
| 953 | ext4_fsblk_t blk; | 951 | ext4_fsblk_t blk; |
| 954 | 952 | ||
| 955 | blk = le32_to_cpu(*(chain[depth-1].p + count)); | 953 | blk = le32_to_cpu(*(chain[depth-1].p + count)); |
| @@ -969,7 +967,7 @@ static int ext4_ind_get_blocks(handle_t *handle, struct inode *inode, | |||
| 969 | /* | 967 | /* |
| 970 | * Okay, we need to do block allocation. | 968 | * Okay, we need to do block allocation. |
| 971 | */ | 969 | */ |
| 972 | goal = ext4_find_goal(inode, iblock, partial); | 970 | goal = ext4_find_goal(inode, map->m_lblk, partial); |
| 973 | 971 | ||
| 974 | /* the number of blocks need to allocate for [d,t]indirect blocks */ | 972 | /* the number of blocks need to allocate for [d,t]indirect blocks */ |
| 975 | indirect_blks = (chain + depth) - partial - 1; | 973 | indirect_blks = (chain + depth) - partial - 1; |
| @@ -979,11 +977,11 @@ static int ext4_ind_get_blocks(handle_t *handle, struct inode *inode, | |||
| 979 | * direct blocks to allocate for this branch. | 977 | * direct blocks to allocate for this branch. |
| 980 | */ | 978 | */ |
| 981 | count = ext4_blks_to_allocate(partial, indirect_blks, | 979 | count = ext4_blks_to_allocate(partial, indirect_blks, |
| 982 | maxblocks, blocks_to_boundary); | 980 | map->m_len, blocks_to_boundary); |
| 983 | /* | 981 | /* |
| 984 | * Block out ext4_truncate while we alter the tree | 982 | * Block out ext4_truncate while we alter the tree |
| 985 | */ | 983 | */ |
| 986 | err = ext4_alloc_branch(handle, inode, iblock, indirect_blks, | 984 | err = ext4_alloc_branch(handle, inode, map->m_lblk, indirect_blks, |
| 987 | &count, goal, | 985 | &count, goal, |
| 988 | offsets + (partial - chain), partial); | 986 | offsets + (partial - chain), partial); |
| 989 | 987 | ||
| @@ -995,18 +993,20 @@ static int ext4_ind_get_blocks(handle_t *handle, struct inode *inode, | |||
| 995 | * may need to return -EAGAIN upwards in the worst case. --sct | 993 | * may need to return -EAGAIN upwards in the worst case. --sct |
| 996 | */ | 994 | */ |
| 997 | if (!err) | 995 | if (!err) |
| 998 | err = ext4_splice_branch(handle, inode, iblock, | 996 | err = ext4_splice_branch(handle, inode, map->m_lblk, |
| 999 | partial, indirect_blks, count); | 997 | partial, indirect_blks, count); |
| 1000 | if (err) | 998 | if (err) |
| 1001 | goto cleanup; | 999 | goto cleanup; |
| 1002 | 1000 | ||
| 1003 | set_buffer_new(bh_result); | 1001 | map->m_flags |= EXT4_MAP_NEW; |
| 1004 | 1002 | ||
| 1005 | ext4_update_inode_fsync_trans(handle, inode, 1); | 1003 | ext4_update_inode_fsync_trans(handle, inode, 1); |
| 1006 | got_it: | 1004 | got_it: |
| 1007 | map_bh(bh_result, inode->i_sb, le32_to_cpu(chain[depth-1].key)); | 1005 | map->m_flags |= EXT4_MAP_MAPPED; |
| 1006 | map->m_pblk = le32_to_cpu(chain[depth-1].key); | ||
| 1007 | map->m_len = count; | ||
| 1008 | if (count > blocks_to_boundary) | 1008 | if (count > blocks_to_boundary) |
| 1009 | set_buffer_boundary(bh_result); | 1009 | map->m_flags |= EXT4_MAP_BOUNDARY; |
| 1010 | err = count; | 1010 | err = count; |
| 1011 | /* Clean up and exit */ | 1011 | /* Clean up and exit */ |
| 1012 | partial = chain + depth - 1; /* the whole chain */ | 1012 | partial = chain + depth - 1; /* the whole chain */ |
| @@ -1016,7 +1016,6 @@ cleanup: | |||
| 1016 | brelse(partial->bh); | 1016 | brelse(partial->bh); |
| 1017 | partial--; | 1017 | partial--; |
| 1018 | } | 1018 | } |
| 1019 | BUFFER_TRACE(bh_result, "returned"); | ||
| 1020 | out: | 1019 | out: |
| 1021 | return err; | 1020 | return err; |
| 1022 | } | 1021 | } |
| @@ -1203,15 +1202,15 @@ static pgoff_t ext4_num_dirty_pages(struct inode *inode, pgoff_t idx, | |||
| 1203 | } | 1202 | } |
| 1204 | 1203 | ||
| 1205 | /* | 1204 | /* |
| 1206 | * The ext4_get_blocks() function tries to look up the requested blocks, | 1205 | * The ext4_map_blocks() function tries to look up the requested blocks, |
| 1207 | * and returns if the blocks are already mapped. | 1206 | * and returns if the blocks are already mapped. |
| 1208 | * | 1207 | * |
| 1209 | * Otherwise it takes the write lock of the i_data_sem and allocate blocks | 1208 | * Otherwise it takes the write lock of the i_data_sem and allocate blocks |
| 1210 | * and store the allocated blocks in the result buffer head and mark it | 1209 | * and store the allocated blocks in the result buffer head and mark it |
| 1211 | * mapped. | 1210 | * mapped. |
| 1212 | * | 1211 | * |
| 1213 | * If file type is extents based, it will call ext4_ext_get_blocks(), | 1212 | * If file type is extents based, it will call ext4_ext_map_blocks(), |
| 1214 | * Otherwise, call with ext4_ind_get_blocks() to handle indirect mapping | 1213 | * Otherwise, call with ext4_ind_map_blocks() to handle indirect mapping |
| 1215 | * based files | 1214 | * based files |
| 1216 | * | 1215 | * |
| 1217 | * On success, it returns the number of blocks being mapped or allocate. | 1216 | * On success, it returns the number of blocks being mapped or allocate. |
| @@ -1224,35 +1223,30 @@ static pgoff_t ext4_num_dirty_pages(struct inode *inode, pgoff_t idx, | |||
| 1224 | * | 1223 | * |
| 1225 | * It returns the error in case of allocation failure. | 1224 | * It returns the error in case of allocation failure. |
| 1226 | */ | 1225 | */ |
| 1227 | int ext4_get_blocks(handle_t *handle, struct inode *inode, sector_t block, | 1226 | int ext4_map_blocks(handle_t *handle, struct inode *inode, |
| 1228 | unsigned int max_blocks, struct buffer_head *bh, | 1227 | struct ext4_map_blocks *map, int flags) |
| 1229 | int flags) | ||
| 1230 | { | 1228 | { |
| 1231 | int retval; | 1229 | int retval; |
| 1232 | 1230 | ||
| 1233 | clear_buffer_mapped(bh); | 1231 | map->m_flags = 0; |
| 1234 | clear_buffer_unwritten(bh); | 1232 | ext_debug("ext4_map_blocks(): inode %lu, flag %d, max_blocks %u," |
| 1235 | 1233 | "logical block %lu\n", inode->i_ino, flags, map->m_len, | |
| 1236 | ext_debug("ext4_get_blocks(): inode %lu, flag %d, max_blocks %u," | 1234 | (unsigned long) map->m_lblk); |
| 1237 | "logical block %lu\n", inode->i_ino, flags, max_blocks, | ||
| 1238 | (unsigned long)block); | ||
| 1239 | /* | 1235 | /* |
| 1240 | * Try to see if we can get the block without requesting a new | 1236 | * Try to see if we can get the block without requesting a new |
| 1241 | * file system block. | 1237 | * file system block. |
| 1242 | */ | 1238 | */ |
| 1243 | down_read((&EXT4_I(inode)->i_data_sem)); | 1239 | down_read((&EXT4_I(inode)->i_data_sem)); |
| 1244 | if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) { | 1240 | if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) { |
| 1245 | retval = ext4_ext_get_blocks(handle, inode, block, max_blocks, | 1241 | retval = ext4_ext_map_blocks(handle, inode, map, 0); |
| 1246 | bh, 0); | ||
| 1247 | } else { | 1242 | } else { |
| 1248 | retval = ext4_ind_get_blocks(handle, inode, block, max_blocks, | 1243 | retval = ext4_ind_map_blocks(handle, inode, map, 0); |
| 1249 | bh, 0); | ||
| 1250 | } | 1244 | } |
| 1251 | up_read((&EXT4_I(inode)->i_data_sem)); | 1245 | up_read((&EXT4_I(inode)->i_data_sem)); |
| 1252 | 1246 | ||
| 1253 | if (retval > 0 && buffer_mapped(bh)) { | 1247 | if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) { |
| 1254 | int ret = check_block_validity(inode, "file system corruption", | 1248 | int ret = check_block_validity(inode, "file system corruption", |
| 1255 | block, bh->b_blocknr, retval); | 1249 | map->m_lblk, map->m_pblk, retval); |
| 1256 | if (ret != 0) | 1250 | if (ret != 0) |
| 1257 | return ret; | 1251 | return ret; |
| 1258 | } | 1252 | } |
| @@ -1268,7 +1262,7 @@ int ext4_get_blocks(handle_t *handle, struct inode *inode, sector_t block, | |||
| 1268 | * ext4_ext_get_block() returns th create = 0 | 1262 | * ext4_ext_get_block() returns th create = 0 |
| 1269 | * with buffer head unmapped. | 1263 | * with buffer head unmapped. |
| 1270 | */ | 1264 | */ |
| 1271 | if (retval > 0 && buffer_mapped(bh)) | 1265 | if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) |
| 1272 | return retval; | 1266 | return retval; |
| 1273 | 1267 | ||
| 1274 | /* | 1268 | /* |
| @@ -1281,7 +1275,7 @@ int ext4_get_blocks(handle_t *handle, struct inode *inode, sector_t block, | |||
| 1281 | * of BH_Unwritten and BH_Mapped flags being simultaneously | 1275 | * of BH_Unwritten and BH_Mapped flags being simultaneously |
| 1282 | * set on the buffer_head. | 1276 | * set on the buffer_head. |
| 1283 | */ | 1277 | */ |
| 1284 | clear_buffer_unwritten(bh); | 1278 | map->m_flags &= ~EXT4_MAP_UNWRITTEN; |
| 1285 | 1279 | ||
| 1286 | /* | 1280 | /* |
| 1287 | * New blocks allocate and/or writing to uninitialized extent | 1281 | * New blocks allocate and/or writing to uninitialized extent |
| @@ -1304,13 +1298,11 @@ int ext4_get_blocks(handle_t *handle, struct inode *inode, sector_t block, | |||
| 1304 | * could have changed the inode type in between | 1298 | * could have changed the inode type in between |
| 1305 | */ | 1299 | */ |
| 1306 | if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) { | 1300 | if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) { |
| 1307 | retval = ext4_ext_get_blocks(handle, inode, block, max_blocks, | 1301 | retval = ext4_ext_map_blocks(handle, inode, map, flags); |
| 1308 | bh, flags); | ||
| 1309 | } else { | 1302 | } else { |
| 1310 | retval = ext4_ind_get_blocks(handle, inode, block, | 1303 | retval = ext4_ind_map_blocks(handle, inode, map, flags); |
| 1311 | max_blocks, bh, flags); | ||
| 1312 | 1304 | ||
| 1313 | if (retval > 0 && buffer_new(bh)) { | 1305 | if (retval > 0 && map->m_flags & EXT4_MAP_NEW) { |
| 1314 | /* | 1306 | /* |
| 1315 | * We allocated new blocks which will result in | 1307 | * We allocated new blocks which will result in |
| 1316 | * i_data's format changing. Force the migrate | 1308 | * i_data's format changing. Force the migrate |
| @@ -1333,16 +1325,38 @@ int ext4_get_blocks(handle_t *handle, struct inode *inode, sector_t block, | |||
| 1333 | EXT4_I(inode)->i_delalloc_reserved_flag = 0; | 1325 | EXT4_I(inode)->i_delalloc_reserved_flag = 0; |
| 1334 | 1326 | ||
| 1335 | up_write((&EXT4_I(inode)->i_data_sem)); | 1327 | up_write((&EXT4_I(inode)->i_data_sem)); |
| 1336 | if (retval > 0 && buffer_mapped(bh)) { | 1328 | if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) { |
| 1337 | int ret = check_block_validity(inode, "file system " | 1329 | int ret = check_block_validity(inode, "file system " |
| 1338 | "corruption after allocation", | 1330 | "corruption after allocation", |
| 1339 | block, bh->b_blocknr, retval); | 1331 | map->m_lblk, map->m_pblk, |
| 1332 | retval); | ||
| 1340 | if (ret != 0) | 1333 | if (ret != 0) |
| 1341 | return ret; | 1334 | return ret; |
| 1342 | } | 1335 | } |
| 1343 | return retval; | 1336 | return retval; |
| 1344 | } | 1337 | } |
| 1345 | 1338 | ||
| 1339 | int ext4_get_blocks(handle_t *handle, struct inode *inode, sector_t block, | ||
| 1340 | unsigned int max_blocks, struct buffer_head *bh, | ||
| 1341 | int flags) | ||
| 1342 | { | ||
| 1343 | struct ext4_map_blocks map; | ||
| 1344 | int ret; | ||
| 1345 | |||
| 1346 | map.m_lblk = block; | ||
| 1347 | map.m_len = max_blocks; | ||
| 1348 | |||
| 1349 | ret = ext4_map_blocks(handle, inode, &map, flags); | ||
| 1350 | if (ret < 0) | ||
| 1351 | return ret; | ||
| 1352 | |||
| 1353 | bh->b_blocknr = map.m_pblk; | ||
| 1354 | bh->b_size = inode->i_sb->s_blocksize * map.m_len; | ||
| 1355 | bh->b_bdev = inode->i_sb->s_bdev; | ||
| 1356 | bh->b_state = (bh->b_state & ~EXT4_MAP_FLAGS) | map.m_flags; | ||
| 1357 | return ret; | ||
| 1358 | } | ||
| 1359 | |||
| 1346 | /* Maximum number of blocks we map for direct IO at once. */ | 1360 | /* Maximum number of blocks we map for direct IO at once. */ |
| 1347 | #define DIO_MAX_BLOCKS 4096 | 1361 | #define DIO_MAX_BLOCKS 4096 |
| 1348 | 1362 | ||
