diff options
Diffstat (limited to 'fs/gfs2/rgrp.c')
-rw-r--r-- | fs/gfs2/rgrp.c | 293 |
1 files changed, 161 insertions, 132 deletions
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 96bd6d759f29..22234627f684 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, unsigned char new_state, | 68 | unsigned char old_state, |
69 | unsigned int *n); | 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 |
@@ -860,22 +860,36 @@ fail: | |||
860 | } | 860 | } |
861 | 861 | ||
862 | /** | 862 | /** |
863 | * gfs2_alloc_get - get the struct gfs2_alloc structure for an inode | 863 | * gfs2_qadata_get - get the struct gfs2_qadata structure for an inode |
864 | * @ip: the incore GFS2 inode structure | 864 | * @ip: the incore GFS2 inode structure |
865 | * | 865 | * |
866 | * Returns: the struct gfs2_alloc | 866 | * Returns: the struct gfs2_qadata |
867 | */ | 867 | */ |
868 | 868 | ||
869 | struct gfs2_alloc *gfs2_alloc_get(struct gfs2_inode *ip) | 869 | struct gfs2_qadata *gfs2_qadata_get(struct gfs2_inode *ip) |
870 | { | 870 | { |
871 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 871 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
872 | int error; | 872 | int error; |
873 | BUG_ON(ip->i_alloc != NULL); | 873 | BUG_ON(ip->i_qadata != NULL); |
874 | ip->i_alloc = kzalloc(sizeof(struct gfs2_alloc), GFP_NOFS); | 874 | ip->i_qadata = kzalloc(sizeof(struct gfs2_qadata), GFP_NOFS); |
875 | error = gfs2_rindex_update(sdp); | 875 | error = gfs2_rindex_update(sdp); |
876 | if (error) | 876 | if (error) |
877 | fs_warn(sdp, "rindex update returns %d\n", error); | 877 | fs_warn(sdp, "rindex update returns %d\n", error); |
878 | return ip->i_alloc; | 878 | return ip->i_qadata; |
879 | } | ||
880 | |||
881 | /** | ||
882 | * gfs2_blkrsv_get - get the struct gfs2_blkreserv structure for an inode | ||
883 | * @ip: the incore GFS2 inode structure | ||
884 | * | ||
885 | * Returns: the struct gfs2_qadata | ||
886 | */ | ||
887 | |||
888 | static struct gfs2_blkreserv *gfs2_blkrsv_get(struct gfs2_inode *ip) | ||
889 | { | ||
890 | BUG_ON(ip->i_res != NULL); | ||
891 | ip->i_res = kzalloc(sizeof(struct gfs2_blkreserv), GFP_NOFS); | ||
892 | return ip->i_res; | ||
879 | } | 893 | } |
880 | 894 | ||
881 | /** | 895 | /** |
@@ -890,15 +904,20 @@ struct gfs2_alloc *gfs2_alloc_get(struct gfs2_inode *ip) | |||
890 | 904 | ||
891 | static int try_rgrp_fit(const struct gfs2_rgrpd *rgd, const struct gfs2_inode *ip) | 905 | static int try_rgrp_fit(const struct gfs2_rgrpd *rgd, const struct gfs2_inode *ip) |
892 | { | 906 | { |
893 | const struct gfs2_alloc *al = ip->i_alloc; | 907 | const struct gfs2_blkreserv *rs = ip->i_res; |
894 | 908 | ||
895 | if (rgd->rd_flags & (GFS2_RGF_NOALLOC | GFS2_RDF_ERROR)) | 909 | if (rgd->rd_flags & (GFS2_RGF_NOALLOC | GFS2_RDF_ERROR)) |
896 | return 0; | 910 | return 0; |
897 | if (rgd->rd_free_clone >= al->al_requested) | 911 | if (rgd->rd_free_clone >= rs->rs_requested) |
898 | return 1; | 912 | return 1; |
899 | return 0; | 913 | return 0; |
900 | } | 914 | } |
901 | 915 | ||
916 | static inline u32 gfs2_bi2rgd_blk(struct gfs2_bitmap *bi, u32 blk) | ||
917 | { | ||
918 | return (bi->bi_start * GFS2_NBBY) + blk; | ||
919 | } | ||
920 | |||
902 | /** | 921 | /** |
903 | * try_rgrp_unlink - Look for any unlinked, allocated, but unused inodes | 922 | * try_rgrp_unlink - Look for any unlinked, allocated, but unused inodes |
904 | * @rgd: The rgrp | 923 | * @rgd: The rgrp |
@@ -912,20 +931,20 @@ static void try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, u64 skip | |||
912 | u32 goal = 0, block; | 931 | u32 goal = 0, block; |
913 | u64 no_addr; | 932 | u64 no_addr; |
914 | struct gfs2_sbd *sdp = rgd->rd_sbd; | 933 | struct gfs2_sbd *sdp = rgd->rd_sbd; |
915 | unsigned int n; | ||
916 | struct gfs2_glock *gl; | 934 | struct gfs2_glock *gl; |
917 | struct gfs2_inode *ip; | 935 | struct gfs2_inode *ip; |
918 | int error; | 936 | int error; |
919 | int found = 0; | 937 | int found = 0; |
938 | struct gfs2_bitmap *bi; | ||
920 | 939 | ||
921 | while (goal < rgd->rd_data) { | 940 | while (goal < rgd->rd_data) { |
922 | down_write(&sdp->sd_log_flush_lock); | 941 | down_write(&sdp->sd_log_flush_lock); |
923 | n = 1; | 942 | block = rgblk_search(rgd, goal, GFS2_BLKST_UNLINKED, &bi); |
924 | block = rgblk_search(rgd, goal, GFS2_BLKST_UNLINKED, | ||
925 | GFS2_BLKST_UNLINKED, &n); | ||
926 | up_write(&sdp->sd_log_flush_lock); | 943 | up_write(&sdp->sd_log_flush_lock); |
927 | if (block == BFITNOENT) | 944 | if (block == BFITNOENT) |
928 | break; | 945 | break; |
946 | |||
947 | block = gfs2_bi2rgd_blk(bi, block); | ||
929 | /* rgblk_search can return a block < goal, so we need to | 948 | /* rgblk_search can return a block < goal, so we need to |
930 | keep it marching forward. */ | 949 | keep it marching forward. */ |
931 | no_addr = block + rgd->rd_data0; | 950 | no_addr = block + rgd->rd_data0; |
@@ -977,8 +996,8 @@ static int get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) | |||
977 | { | 996 | { |
978 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 997 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
979 | struct gfs2_rgrpd *rgd, *begin = NULL; | 998 | struct gfs2_rgrpd *rgd, *begin = NULL; |
980 | struct gfs2_alloc *al = ip->i_alloc; | 999 | struct gfs2_blkreserv *rs = ip->i_res; |
981 | int error, rg_locked; | 1000 | int error, rg_locked, flags = LM_FLAG_TRY; |
982 | int loops = 0; | 1001 | int loops = 0; |
983 | 1002 | ||
984 | if (ip->i_rgd && rgrp_contains_block(ip->i_rgd, ip->i_goal)) | 1003 | if (ip->i_rgd && rgrp_contains_block(ip->i_rgd, ip->i_goal)) |
@@ -997,7 +1016,7 @@ static int get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) | |||
997 | error = 0; | 1016 | error = 0; |
998 | } else { | 1017 | } else { |
999 | error = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_EXCLUSIVE, | 1018 | error = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_EXCLUSIVE, |
1000 | LM_FLAG_TRY, &al->al_rgd_gh); | 1019 | flags, &rs->rs_rgd_gh); |
1001 | } | 1020 | } |
1002 | switch (error) { | 1021 | switch (error) { |
1003 | case 0: | 1022 | case 0: |
@@ -1008,12 +1027,14 @@ static int get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) | |||
1008 | if (rgd->rd_flags & GFS2_RDF_CHECK) | 1027 | if (rgd->rd_flags & GFS2_RDF_CHECK) |
1009 | try_rgrp_unlink(rgd, last_unlinked, ip->i_no_addr); | 1028 | try_rgrp_unlink(rgd, last_unlinked, ip->i_no_addr); |
1010 | if (!rg_locked) | 1029 | if (!rg_locked) |
1011 | gfs2_glock_dq_uninit(&al->al_rgd_gh); | 1030 | gfs2_glock_dq_uninit(&rs->rs_rgd_gh); |
1012 | /* fall through */ | 1031 | /* fall through */ |
1013 | case GLR_TRYFAILED: | 1032 | case GLR_TRYFAILED: |
1014 | rgd = gfs2_rgrpd_get_next(rgd); | 1033 | rgd = gfs2_rgrpd_get_next(rgd); |
1015 | if (rgd == begin) | 1034 | if (rgd == begin) { |
1035 | flags = 0; | ||
1016 | loops++; | 1036 | loops++; |
1037 | } | ||
1017 | break; | 1038 | break; |
1018 | default: | 1039 | default: |
1019 | return error; | 1040 | return error; |
@@ -1023,6 +1044,13 @@ static int get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) | |||
1023 | return -ENOSPC; | 1044 | return -ENOSPC; |
1024 | } | 1045 | } |
1025 | 1046 | ||
1047 | static void gfs2_blkrsv_put(struct gfs2_inode *ip) | ||
1048 | { | ||
1049 | BUG_ON(ip->i_res == NULL); | ||
1050 | kfree(ip->i_res); | ||
1051 | ip->i_res = NULL; | ||
1052 | } | ||
1053 | |||
1026 | /** | 1054 | /** |
1027 | * gfs2_inplace_reserve - Reserve space in the filesystem | 1055 | * gfs2_inplace_reserve - Reserve space in the filesystem |
1028 | * @ip: the inode to reserve space for | 1056 | * @ip: the inode to reserve space for |
@@ -1030,16 +1058,23 @@ static int get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) | |||
1030 | * Returns: errno | 1058 | * Returns: errno |
1031 | */ | 1059 | */ |
1032 | 1060 | ||
1033 | int gfs2_inplace_reserve(struct gfs2_inode *ip) | 1061 | int gfs2_inplace_reserve(struct gfs2_inode *ip, u32 requested) |
1034 | { | 1062 | { |
1035 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 1063 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
1036 | struct gfs2_alloc *al = ip->i_alloc; | 1064 | struct gfs2_blkreserv *rs; |
1037 | int error = 0; | 1065 | int error = 0; |
1038 | u64 last_unlinked = NO_BLOCK; | 1066 | u64 last_unlinked = NO_BLOCK; |
1039 | int tries = 0; | 1067 | int tries = 0; |
1040 | 1068 | ||
1041 | if (gfs2_assert_warn(sdp, al->al_requested)) | 1069 | rs = gfs2_blkrsv_get(ip); |
1042 | return -EINVAL; | 1070 | if (!rs) |
1071 | return -ENOMEM; | ||
1072 | |||
1073 | rs->rs_requested = requested; | ||
1074 | if (gfs2_assert_warn(sdp, requested)) { | ||
1075 | error = -EINVAL; | ||
1076 | goto out; | ||
1077 | } | ||
1043 | 1078 | ||
1044 | do { | 1079 | do { |
1045 | error = get_local_rgrp(ip, &last_unlinked); | 1080 | error = get_local_rgrp(ip, &last_unlinked); |
@@ -1056,6 +1091,9 @@ int gfs2_inplace_reserve(struct gfs2_inode *ip) | |||
1056 | gfs2_log_flush(sdp, NULL); | 1091 | gfs2_log_flush(sdp, NULL); |
1057 | } while (tries++ < 3); | 1092 | } while (tries++ < 3); |
1058 | 1093 | ||
1094 | out: | ||
1095 | if (error) | ||
1096 | gfs2_blkrsv_put(ip); | ||
1059 | return error; | 1097 | return error; |
1060 | } | 1098 | } |
1061 | 1099 | ||
@@ -1068,10 +1106,11 @@ int gfs2_inplace_reserve(struct gfs2_inode *ip) | |||
1068 | 1106 | ||
1069 | void gfs2_inplace_release(struct gfs2_inode *ip) | 1107 | void gfs2_inplace_release(struct gfs2_inode *ip) |
1070 | { | 1108 | { |
1071 | struct gfs2_alloc *al = ip->i_alloc; | 1109 | struct gfs2_blkreserv *rs = ip->i_res; |
1072 | 1110 | ||
1073 | if (al->al_rgd_gh.gh_gl) | 1111 | gfs2_blkrsv_put(ip); |
1074 | gfs2_glock_dq_uninit(&al->al_rgd_gh); | 1112 | if (rs->rs_rgd_gh.gh_gl) |
1113 | gfs2_glock_dq_uninit(&rs->rs_rgd_gh); | ||
1075 | } | 1114 | } |
1076 | 1115 | ||
1077 | /** | 1116 | /** |
@@ -1108,39 +1147,35 @@ static unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block) | |||
1108 | } | 1147 | } |
1109 | 1148 | ||
1110 | /** | 1149 | /** |
1111 | * rgblk_search - find a block in @old_state, change allocation | 1150 | * rgblk_search - find a block in @state |
1112 | * state to @new_state | ||
1113 | * @rgd: the resource group descriptor | 1151 | * @rgd: the resource group descriptor |
1114 | * @goal: the goal block within the RG (start here to search for avail block) | 1152 | * @goal: the goal block within the RG (start here to search for avail block) |
1115 | * @old_state: GFS2_BLKST_XXX the before-allocation state to find | 1153 | * @state: GFS2_BLKST_XXX the before-allocation state to find |
1116 | * @new_state: GFS2_BLKST_XXX the after-allocation block state | 1154 | * @dinode: TRUE if the first block we allocate is for a dinode |
1117 | * @n: The extent length | 1155 | * @rbi: address of the pointer to the bitmap containing the block found |
1118 | * | 1156 | * |
1119 | * Walk rgrp's bitmap to find bits that represent a block in @old_state. | 1157 | * Walk rgrp's bitmap to find bits that represent a block in @state. |
1120 | * Add the found bitmap buffer to the transaction. | ||
1121 | * Set the found bits to @new_state to change block's allocation state. | ||
1122 | * | 1158 | * |
1123 | * This function never fails, because we wouldn't call it unless we | 1159 | * This function never fails, because we wouldn't call it unless we |
1124 | * know (from reservation results, etc.) that a block is available. | 1160 | * know (from reservation results, etc.) that a block is available. |
1125 | * | 1161 | * |
1126 | * Scope of @goal and returned block is just within rgrp, not the whole | 1162 | * Scope of @goal is just within rgrp, not the whole filesystem. |
1127 | * filesystem. | 1163 | * Scope of @returned block is just within bitmap, not the whole filesystem. |
1128 | * | 1164 | * |
1129 | * Returns: the block number allocated | 1165 | * Returns: the block number found relative to the bitmap rbi |
1130 | */ | 1166 | */ |
1131 | 1167 | ||
1132 | static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal, | 1168 | static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal, |
1133 | unsigned char old_state, unsigned char new_state, | 1169 | unsigned char state, |
1134 | unsigned int *n) | 1170 | struct gfs2_bitmap **rbi) |
1135 | { | 1171 | { |
1136 | struct gfs2_bitmap *bi = NULL; | 1172 | struct gfs2_bitmap *bi = NULL; |
1137 | const u32 length = rgd->rd_length; | 1173 | const u32 length = rgd->rd_length; |
1138 | u32 blk = BFITNOENT; | 1174 | u32 blk = BFITNOENT; |
1139 | unsigned int buf, x; | 1175 | unsigned int buf, x; |
1140 | const unsigned int elen = *n; | ||
1141 | const u8 *buffer = NULL; | 1176 | const u8 *buffer = NULL; |
1142 | 1177 | ||
1143 | *n = 0; | 1178 | *rbi = NULL; |
1144 | /* Find bitmap block that contains bits for goal block */ | 1179 | /* Find bitmap block that contains bits for goal block */ |
1145 | for (buf = 0; buf < length; buf++) { | 1180 | for (buf = 0; buf < length; buf++) { |
1146 | bi = rgd->rd_bits + buf; | 1181 | bi = rgd->rd_bits + buf; |
@@ -1163,21 +1198,21 @@ do_search: | |||
1163 | bi = rgd->rd_bits + buf; | 1198 | bi = rgd->rd_bits + buf; |
1164 | 1199 | ||
1165 | if (test_bit(GBF_FULL, &bi->bi_flags) && | 1200 | if (test_bit(GBF_FULL, &bi->bi_flags) && |
1166 | (old_state == GFS2_BLKST_FREE)) | 1201 | (state == GFS2_BLKST_FREE)) |
1167 | goto skip; | 1202 | goto skip; |
1168 | 1203 | ||
1169 | /* The GFS2_BLKST_UNLINKED state doesn't apply to the clone | 1204 | /* The GFS2_BLKST_UNLINKED state doesn't apply to the clone |
1170 | bitmaps, so we must search the originals for that. */ | 1205 | bitmaps, so we must search the originals for that. */ |
1171 | buffer = bi->bi_bh->b_data + bi->bi_offset; | 1206 | buffer = bi->bi_bh->b_data + bi->bi_offset; |
1172 | WARN_ON(!buffer_uptodate(bi->bi_bh)); | 1207 | WARN_ON(!buffer_uptodate(bi->bi_bh)); |
1173 | if (old_state != GFS2_BLKST_UNLINKED && bi->bi_clone) | 1208 | if (state != GFS2_BLKST_UNLINKED && bi->bi_clone) |
1174 | buffer = bi->bi_clone + bi->bi_offset; | 1209 | buffer = bi->bi_clone + bi->bi_offset; |
1175 | 1210 | ||
1176 | blk = gfs2_bitfit(buffer, bi->bi_len, goal, old_state); | 1211 | blk = gfs2_bitfit(buffer, bi->bi_len, goal, state); |
1177 | if (blk != BFITNOENT) | 1212 | if (blk != BFITNOENT) |
1178 | break; | 1213 | break; |
1179 | 1214 | ||
1180 | if ((goal == 0) && (old_state == GFS2_BLKST_FREE)) | 1215 | if ((goal == 0) && (state == GFS2_BLKST_FREE)) |
1181 | set_bit(GBF_FULL, &bi->bi_flags); | 1216 | set_bit(GBF_FULL, &bi->bi_flags); |
1182 | 1217 | ||
1183 | /* Try next bitmap block (wrap back to rgrp header if at end) */ | 1218 | /* Try next bitmap block (wrap back to rgrp header if at end) */ |
@@ -1187,16 +1222,37 @@ skip: | |||
1187 | goal = 0; | 1222 | goal = 0; |
1188 | } | 1223 | } |
1189 | 1224 | ||
1190 | if (blk == BFITNOENT) | 1225 | if (blk != BFITNOENT) |
1191 | return blk; | 1226 | *rbi = bi; |
1192 | 1227 | ||
1193 | *n = 1; | 1228 | return blk; |
1194 | if (old_state == new_state) | 1229 | } |
1195 | goto out; | 1230 | |
1231 | /** | ||
1232 | * gfs2_alloc_extent - allocate an extent from a given bitmap | ||
1233 | * @rgd: the resource group descriptor | ||
1234 | * @bi: the bitmap within the rgrp | ||
1235 | * @blk: the block within the bitmap | ||
1236 | * @dinode: TRUE if the first block we allocate is for a dinode | ||
1237 | * @n: The extent length | ||
1238 | * | ||
1239 | * Add the found bitmap buffer to the transaction. | ||
1240 | * Set the found bits to @new_state to change block's allocation state. | ||
1241 | * Returns: starting block number of the extent (fs scope) | ||
1242 | */ | ||
1243 | static u64 gfs2_alloc_extent(struct gfs2_rgrpd *rgd, struct gfs2_bitmap *bi, | ||
1244 | u32 blk, bool dinode, unsigned int *n) | ||
1245 | { | ||
1246 | const unsigned int elen = *n; | ||
1247 | u32 goal; | ||
1248 | const u8 *buffer = NULL; | ||
1196 | 1249 | ||
1250 | *n = 0; | ||
1251 | buffer = bi->bi_bh->b_data + bi->bi_offset; | ||
1197 | gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1); | 1252 | gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1); |
1198 | gfs2_setbit(rgd, bi->bi_bh->b_data, bi->bi_clone, bi->bi_offset, | 1253 | gfs2_setbit(rgd, bi->bi_bh->b_data, bi->bi_clone, bi->bi_offset, |
1199 | bi, blk, new_state); | 1254 | bi, blk, dinode ? GFS2_BLKST_DINODE : GFS2_BLKST_USED); |
1255 | (*n)++; | ||
1200 | goal = blk; | 1256 | goal = blk; |
1201 | while (*n < elen) { | 1257 | while (*n < elen) { |
1202 | goal++; | 1258 | goal++; |
@@ -1206,11 +1262,12 @@ skip: | |||
1206 | GFS2_BLKST_FREE) | 1262 | GFS2_BLKST_FREE) |
1207 | break; | 1263 | break; |
1208 | gfs2_setbit(rgd, bi->bi_bh->b_data, bi->bi_clone, bi->bi_offset, | 1264 | gfs2_setbit(rgd, bi->bi_bh->b_data, bi->bi_clone, bi->bi_offset, |
1209 | bi, goal, new_state); | 1265 | bi, goal, GFS2_BLKST_USED); |
1210 | (*n)++; | 1266 | (*n)++; |
1211 | } | 1267 | } |
1212 | out: | 1268 | blk = gfs2_bi2rgd_blk(bi, blk); |
1213 | return (bi->bi_start * GFS2_NBBY) + blk; | 1269 | rgd->rd_last_alloc = blk + *n - 1; |
1270 | return rgd->rd_data0 + blk; | ||
1214 | } | 1271 | } |
1215 | 1272 | ||
1216 | /** | 1273 | /** |
@@ -1298,121 +1355,93 @@ static void gfs2_rgrp_error(struct gfs2_rgrpd *rgd) | |||
1298 | } | 1355 | } |
1299 | 1356 | ||
1300 | /** | 1357 | /** |
1301 | * gfs2_alloc_block - Allocate one or more blocks | 1358 | * gfs2_alloc_blocks - Allocate one or more blocks of data and/or a dinode |
1302 | * @ip: the inode to allocate the block for | 1359 | * @ip: the inode to allocate the block for |
1303 | * @bn: Used to return the starting block number | 1360 | * @bn: Used to return the starting block number |
1304 | * @n: requested number of blocks/extent length (value/result) | 1361 | * @ndata: requested number of blocks/extent length (value/result) |
1362 | * @dinode: 1 if we're allocating a dinode block, else 0 | ||
1363 | * @generation: the generation number of the inode | ||
1305 | * | 1364 | * |
1306 | * Returns: 0 or error | 1365 | * Returns: 0 or error |
1307 | */ | 1366 | */ |
1308 | 1367 | ||
1309 | int gfs2_alloc_block(struct gfs2_inode *ip, u64 *bn, unsigned int *n) | 1368 | int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks, |
1369 | bool dinode, u64 *generation) | ||
1310 | { | 1370 | { |
1311 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 1371 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
1312 | struct buffer_head *dibh; | 1372 | struct buffer_head *dibh; |
1313 | struct gfs2_alloc *al = ip->i_alloc; | ||
1314 | struct gfs2_rgrpd *rgd; | 1373 | struct gfs2_rgrpd *rgd; |
1315 | u32 goal, blk; | 1374 | unsigned int ndata; |
1316 | u64 block; | 1375 | u32 goal, blk; /* block, within the rgrp scope */ |
1376 | u64 block; /* block, within the file system scope */ | ||
1317 | int error; | 1377 | int error; |
1378 | struct gfs2_bitmap *bi; | ||
1318 | 1379 | ||
1319 | /* Only happens if there is a bug in gfs2, return something distinctive | 1380 | /* Only happens if there is a bug in gfs2, return something distinctive |
1320 | * to ensure that it is noticed. | 1381 | * to ensure that it is noticed. |
1321 | */ | 1382 | */ |
1322 | if (al == NULL) | 1383 | if (ip->i_res == NULL) |
1323 | return -ECANCELED; | 1384 | return -ECANCELED; |
1324 | 1385 | ||
1325 | rgd = ip->i_rgd; | 1386 | rgd = ip->i_rgd; |
1326 | 1387 | ||
1327 | if (rgrp_contains_block(rgd, ip->i_goal)) | 1388 | if (!dinode && rgrp_contains_block(rgd, ip->i_goal)) |
1328 | goal = ip->i_goal - rgd->rd_data0; | 1389 | goal = ip->i_goal - rgd->rd_data0; |
1329 | else | 1390 | else |
1330 | goal = rgd->rd_last_alloc; | 1391 | goal = rgd->rd_last_alloc; |
1331 | 1392 | ||
1332 | blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED, n); | 1393 | blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, &bi); |
1333 | 1394 | ||
1334 | /* Since all blocks are reserved in advance, this shouldn't happen */ | 1395 | /* Since all blocks are reserved in advance, this shouldn't happen */ |
1335 | if (blk == BFITNOENT) | 1396 | if (blk == BFITNOENT) |
1336 | goto rgrp_error; | 1397 | goto rgrp_error; |
1337 | 1398 | ||
1338 | rgd->rd_last_alloc = blk; | 1399 | block = gfs2_alloc_extent(rgd, bi, blk, dinode, nblocks); |
1339 | block = rgd->rd_data0 + blk; | 1400 | ndata = *nblocks; |
1340 | ip->i_goal = block + *n - 1; | 1401 | if (dinode) |
1341 | error = gfs2_meta_inode_buffer(ip, &dibh); | 1402 | ndata--; |
1342 | if (error == 0) { | 1403 | |
1343 | struct gfs2_dinode *di = (struct gfs2_dinode *)dibh->b_data; | 1404 | if (!dinode) { |
1344 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | 1405 | ip->i_goal = block + ndata - 1; |
1345 | di->di_goal_meta = di->di_goal_data = cpu_to_be64(ip->i_goal); | 1406 | error = gfs2_meta_inode_buffer(ip, &dibh); |
1346 | brelse(dibh); | 1407 | if (error == 0) { |
1408 | struct gfs2_dinode *di = | ||
1409 | (struct gfs2_dinode *)dibh->b_data; | ||
1410 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | ||
1411 | di->di_goal_meta = di->di_goal_data = | ||
1412 | cpu_to_be64(ip->i_goal); | ||
1413 | brelse(dibh); | ||
1414 | } | ||
1347 | } | 1415 | } |
1348 | if (rgd->rd_free < *n) | 1416 | if (rgd->rd_free < *nblocks) |
1349 | goto rgrp_error; | 1417 | goto rgrp_error; |
1350 | 1418 | ||
1351 | rgd->rd_free -= *n; | 1419 | rgd->rd_free -= *nblocks; |
1352 | 1420 | if (dinode) { | |
1353 | gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1); | 1421 | rgd->rd_dinodes++; |
1354 | gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data); | ||
1355 | |||
1356 | al->al_alloced += *n; | ||
1357 | |||
1358 | gfs2_statfs_change(sdp, 0, -(s64)*n, 0); | ||
1359 | gfs2_quota_change(ip, *n, ip->i_inode.i_uid, ip->i_inode.i_gid); | ||
1360 | |||
1361 | rgd->rd_free_clone -= *n; | ||
1362 | trace_gfs2_block_alloc(ip, block, *n, GFS2_BLKST_USED); | ||
1363 | *bn = block; | ||
1364 | return 0; | ||
1365 | |||
1366 | rgrp_error: | ||
1367 | gfs2_rgrp_error(rgd); | ||
1368 | return -EIO; | ||
1369 | } | ||
1370 | |||
1371 | /** | ||
1372 | * gfs2_alloc_di - Allocate a dinode | ||
1373 | * @dip: the directory that the inode is going in | ||
1374 | * @bn: the block number which is allocated | ||
1375 | * @generation: the generation number of the inode | ||
1376 | * | ||
1377 | * Returns: 0 on success or error | ||
1378 | */ | ||
1379 | |||
1380 | int gfs2_alloc_di(struct gfs2_inode *dip, u64 *bn, u64 *generation) | ||
1381 | { | ||
1382 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); | ||
1383 | struct gfs2_alloc *al = dip->i_alloc; | ||
1384 | struct gfs2_rgrpd *rgd = dip->i_rgd; | ||
1385 | u32 blk; | ||
1386 | u64 block; | ||
1387 | unsigned int n = 1; | ||
1388 | |||
1389 | blk = rgblk_search(rgd, rgd->rd_last_alloc, | ||
1390 | GFS2_BLKST_FREE, GFS2_BLKST_DINODE, &n); | ||
1391 | |||
1392 | /* Since all blocks are reserved in advance, this shouldn't happen */ | ||
1393 | if (blk == BFITNOENT) | ||
1394 | goto rgrp_error; | ||
1395 | |||
1396 | rgd->rd_last_alloc = blk; | ||
1397 | block = rgd->rd_data0 + blk; | ||
1398 | if (rgd->rd_free == 0) | ||
1399 | goto rgrp_error; | ||
1400 | |||
1401 | rgd->rd_free--; | ||
1402 | rgd->rd_dinodes++; | ||
1403 | *generation = rgd->rd_igeneration++; | ||
1404 | if (*generation == 0) | ||
1405 | *generation = rgd->rd_igeneration++; | 1422 | *generation = rgd->rd_igeneration++; |
1423 | if (*generation == 0) | ||
1424 | *generation = rgd->rd_igeneration++; | ||
1425 | } | ||
1426 | |||
1406 | gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1); | 1427 | gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1); |
1407 | gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data); | 1428 | gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data); |
1408 | 1429 | ||
1409 | al->al_alloced++; | 1430 | gfs2_statfs_change(sdp, 0, -(s64)*nblocks, dinode ? 1 : 0); |
1431 | if (dinode) | ||
1432 | gfs2_trans_add_unrevoke(sdp, block, 1); | ||
1410 | 1433 | ||
1411 | gfs2_statfs_change(sdp, 0, -1, +1); | 1434 | /* |
1412 | gfs2_trans_add_unrevoke(sdp, block, 1); | 1435 | * This needs reviewing to see why we cannot do the quota change |
1436 | * at this point in the dinode case. | ||
1437 | */ | ||
1438 | if (ndata) | ||
1439 | gfs2_quota_change(ip, ndata, ip->i_inode.i_uid, | ||
1440 | ip->i_inode.i_gid); | ||
1413 | 1441 | ||
1414 | rgd->rd_free_clone--; | 1442 | rgd->rd_free_clone -= *nblocks; |
1415 | trace_gfs2_block_alloc(dip, block, 1, GFS2_BLKST_DINODE); | 1443 | trace_gfs2_block_alloc(ip, block, *nblocks, |
1444 | dinode ? GFS2_BLKST_DINODE : GFS2_BLKST_USED); | ||
1416 | *bn = block; | 1445 | *bn = block; |
1417 | return 0; | 1446 | return 0; |
1418 | 1447 | ||