diff options
Diffstat (limited to 'fs/gfs2')
-rw-r--r-- | fs/gfs2/rgrp.c | 76 |
1 files changed, 51 insertions, 25 deletions
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index f1d19603d237..6b6cc096756a 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c | |||
@@ -65,8 +65,8 @@ static const char valid_change[16] = { | |||
65 | }; | 65 | }; |
66 | 66 | ||
67 | static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal, | 67 | static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal, |
68 | unsigned char old_state, bool dinode, | 68 | unsigned char old_state, bool dinode, |
69 | unsigned int *ndata); | 69 | struct gfs2_bitmap **rbi); |
70 | 70 | ||
71 | /** | 71 | /** |
72 | * gfs2_setbit - Set a bit in the bitmaps | 72 | * gfs2_setbit - Set a bit in the bitmaps |
@@ -899,6 +899,11 @@ static int try_rgrp_fit(const struct gfs2_rgrpd *rgd, const struct gfs2_inode *i | |||
899 | return 0; | 899 | return 0; |
900 | } | 900 | } |
901 | 901 | ||
902 | static inline u32 gfs2_bi2rgd_blk(struct gfs2_bitmap *bi, u32 blk) | ||
903 | { | ||
904 | return (bi->bi_start * GFS2_NBBY) + blk; | ||
905 | } | ||
906 | |||
902 | /** | 907 | /** |
903 | * try_rgrp_unlink - Look for any unlinked, allocated, but unused inodes | 908 | * try_rgrp_unlink - Look for any unlinked, allocated, but unused inodes |
904 | * @rgd: The rgrp | 909 | * @rgd: The rgrp |
@@ -912,19 +917,20 @@ static void try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, u64 skip | |||
912 | u32 goal = 0, block; | 917 | u32 goal = 0, block; |
913 | u64 no_addr; | 918 | u64 no_addr; |
914 | struct gfs2_sbd *sdp = rgd->rd_sbd; | 919 | struct gfs2_sbd *sdp = rgd->rd_sbd; |
915 | unsigned int n; | ||
916 | struct gfs2_glock *gl; | 920 | struct gfs2_glock *gl; |
917 | struct gfs2_inode *ip; | 921 | struct gfs2_inode *ip; |
918 | int error; | 922 | int error; |
919 | int found = 0; | 923 | int found = 0; |
924 | struct gfs2_bitmap *bi; | ||
920 | 925 | ||
921 | while (goal < rgd->rd_data) { | 926 | while (goal < rgd->rd_data) { |
922 | down_write(&sdp->sd_log_flush_lock); | 927 | down_write(&sdp->sd_log_flush_lock); |
923 | n = 1; | 928 | block = rgblk_search(rgd, goal, GFS2_BLKST_UNLINKED, 0, &bi); |
924 | block = rgblk_search(rgd, goal, GFS2_BLKST_UNLINKED, 0, &n); | ||
925 | up_write(&sdp->sd_log_flush_lock); | 929 | up_write(&sdp->sd_log_flush_lock); |
926 | if (block == BFITNOENT) | 930 | if (block == BFITNOENT) |
927 | break; | 931 | break; |
932 | |||
933 | block = gfs2_bi2rgd_blk(bi, block); | ||
928 | /* rgblk_search can return a block < goal, so we need to | 934 | /* rgblk_search can return a block < goal, so we need to |
929 | keep it marching forward. */ | 935 | keep it marching forward. */ |
930 | no_addr = block + rgd->rd_data0; | 936 | no_addr = block + rgd->rd_data0; |
@@ -1109,38 +1115,35 @@ static unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block) | |||
1109 | } | 1115 | } |
1110 | 1116 | ||
1111 | /** | 1117 | /** |
1112 | * rgblk_search - find a block in @old_state, change allocation | 1118 | * rgblk_search - find a block in @old_state |
1113 | * state to @new_state | ||
1114 | * @rgd: the resource group descriptor | 1119 | * @rgd: the resource group descriptor |
1115 | * @goal: the goal block within the RG (start here to search for avail block) | 1120 | * @goal: the goal block within the RG (start here to search for avail block) |
1116 | * @old_state: GFS2_BLKST_XXX the before-allocation state to find | 1121 | * @old_state: GFS2_BLKST_XXX the before-allocation state to find |
1117 | * @dinode: TRUE if the first block we allocate is for a dinode | 1122 | * @dinode: TRUE if the first block we allocate is for a dinode |
1118 | * @n: The extent length | 1123 | * @rbi: address of the pointer to the bitmap containing the block found |
1119 | * | 1124 | * |
1120 | * Walk rgrp's bitmap to find bits that represent a block in @old_state. | 1125 | * Walk rgrp's bitmap to find bits that represent a block in @old_state. |
1121 | * Add the found bitmap buffer to the transaction. | ||
1122 | * Set the found bits to @new_state to change block's allocation state. | ||
1123 | * | 1126 | * |
1124 | * This function never fails, because we wouldn't call it unless we | 1127 | * This function never fails, because we wouldn't call it unless we |
1125 | * know (from reservation results, etc.) that a block is available. | 1128 | * know (from reservation results, etc.) that a block is available. |
1126 | * | 1129 | * |
1127 | * Scope of @goal and returned block is just within rgrp, not the whole | 1130 | * Scope of @goal is just within rgrp, not the whole filesystem. |
1128 | * filesystem. | 1131 | * Scope of @returned block is just within bitmap, not the whole filesystem. |
1129 | * | 1132 | * |
1130 | * Returns: the block number allocated | 1133 | * Returns: the block number found relative to the bitmap rbi |
1131 | */ | 1134 | */ |
1132 | 1135 | ||
1133 | static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal, | 1136 | static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal, |
1134 | unsigned char old_state, bool dinode, unsigned int *n) | 1137 | unsigned char old_state, bool dinode, |
1138 | struct gfs2_bitmap **rbi) | ||
1135 | { | 1139 | { |
1136 | struct gfs2_bitmap *bi = NULL; | 1140 | struct gfs2_bitmap *bi = NULL; |
1137 | const u32 length = rgd->rd_length; | 1141 | const u32 length = rgd->rd_length; |
1138 | u32 blk = BFITNOENT; | 1142 | u32 blk = BFITNOENT; |
1139 | unsigned int buf, x; | 1143 | unsigned int buf, x; |
1140 | const unsigned int elen = *n; | ||
1141 | const u8 *buffer = NULL; | 1144 | const u8 *buffer = NULL; |
1142 | 1145 | ||
1143 | *n = 0; | 1146 | *rbi = NULL; |
1144 | /* Find bitmap block that contains bits for goal block */ | 1147 | /* Find bitmap block that contains bits for goal block */ |
1145 | for (buf = 0; buf < length; buf++) { | 1148 | for (buf = 0; buf < length; buf++) { |
1146 | bi = rgd->rd_bits + buf; | 1149 | bi = rgd->rd_bits + buf; |
@@ -1187,12 +1190,32 @@ skip: | |||
1187 | goal = 0; | 1190 | goal = 0; |
1188 | } | 1191 | } |
1189 | 1192 | ||
1190 | if (blk == BFITNOENT) | 1193 | if (blk != BFITNOENT) |
1191 | return blk; | 1194 | *rbi = bi; |
1192 | 1195 | ||
1193 | if (old_state == GFS2_BLKST_UNLINKED) | 1196 | return blk; |
1194 | goto out; | 1197 | } |
1195 | 1198 | ||
1199 | /** | ||
1200 | * gfs2_alloc_extent - allocate an extent from a given bitmap | ||
1201 | * @rgd: the resource group descriptor | ||
1202 | * @bi: the bitmap within the rgrp | ||
1203 | * @blk: the block within the bitmap | ||
1204 | * @dinode: TRUE if the first block we allocate is for a dinode | ||
1205 | * @n: The extent length | ||
1206 | * | ||
1207 | * Add the found bitmap buffer to the transaction. | ||
1208 | * Set the found bits to @new_state to change block's allocation state. | ||
1209 | * Returns: starting block number of the extent (fs scope) | ||
1210 | */ | ||
1211 | static u64 gfs2_alloc_extent(struct gfs2_rgrpd *rgd, struct gfs2_bitmap *bi, | ||
1212 | u32 blk, bool dinode, unsigned int *n) | ||
1213 | { | ||
1214 | const unsigned int elen = *n; | ||
1215 | u32 goal; | ||
1216 | const u8 *buffer = NULL; | ||
1217 | |||
1218 | buffer = bi->bi_bh->b_data + bi->bi_offset; | ||
1196 | gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1); | 1219 | gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1); |
1197 | gfs2_setbit(rgd, bi->bi_bh->b_data, bi->bi_clone, bi->bi_offset, | 1220 | gfs2_setbit(rgd, bi->bi_bh->b_data, bi->bi_clone, bi->bi_offset, |
1198 | bi, blk, dinode ? GFS2_BLKST_DINODE : GFS2_BLKST_USED); | 1221 | bi, blk, dinode ? GFS2_BLKST_DINODE : GFS2_BLKST_USED); |
@@ -1210,8 +1233,9 @@ skip: | |||
1210 | bi, goal, GFS2_BLKST_USED); | 1233 | bi, goal, GFS2_BLKST_USED); |
1211 | (*n)++; | 1234 | (*n)++; |
1212 | } | 1235 | } |
1213 | out: | 1236 | blk = gfs2_bi2rgd_blk(bi, blk); |
1214 | return (bi->bi_start * GFS2_NBBY) + blk; | 1237 | rgd->rd_last_alloc = blk; |
1238 | return rgd->rd_data0 + blk; | ||
1215 | } | 1239 | } |
1216 | 1240 | ||
1217 | /** | 1241 | /** |
@@ -1319,6 +1343,7 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *ndata, | |||
1319 | u32 goal, extlen, blk; /* block, within the rgrp scope */ | 1343 | u32 goal, extlen, blk; /* block, within the rgrp scope */ |
1320 | u64 block; /* block, within the file system scope */ | 1344 | u64 block; /* block, within the file system scope */ |
1321 | int error; | 1345 | int error; |
1346 | struct gfs2_bitmap *bi; | ||
1322 | 1347 | ||
1323 | /* Only happens if there is a bug in gfs2, return something distinctive | 1348 | /* Only happens if there is a bug in gfs2, return something distinctive |
1324 | * to ensure that it is noticed. | 1349 | * to ensure that it is noticed. |
@@ -1333,14 +1358,15 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *ndata, | |||
1333 | else | 1358 | else |
1334 | goal = rgd->rd_last_alloc; | 1359 | goal = rgd->rd_last_alloc; |
1335 | 1360 | ||
1336 | blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, dinode, ndata); | 1361 | blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, dinode, &bi); |
1337 | 1362 | ||
1363 | *ndata = 0; | ||
1338 | /* Since all blocks are reserved in advance, this shouldn't happen */ | 1364 | /* Since all blocks are reserved in advance, this shouldn't happen */ |
1339 | if (blk == BFITNOENT) | 1365 | if (blk == BFITNOENT) |
1340 | goto rgrp_error; | 1366 | goto rgrp_error; |
1341 | 1367 | ||
1342 | rgd->rd_last_alloc = blk; | 1368 | block = gfs2_alloc_extent(rgd, bi, blk, dinode, ndata); |
1343 | block = rgd->rd_data0 + blk; | 1369 | |
1344 | if (!dinode) { | 1370 | if (!dinode) { |
1345 | ip->i_goal = block + *ndata - 1; | 1371 | ip->i_goal = block + *ndata - 1; |
1346 | error = gfs2_meta_inode_buffer(ip, &dibh); | 1372 | error = gfs2_meta_inode_buffer(ip, &dibh); |