aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/rgrp.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/gfs2/rgrp.c')
-rw-r--r--fs/gfs2/rgrp.c87
1 files changed, 70 insertions, 17 deletions
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 027f6ec5b0d9..fd3fd9074779 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -28,6 +28,7 @@
28#include "ops_file.h" 28#include "ops_file.h"
29#include "util.h" 29#include "util.h"
30#include "log.h" 30#include "log.h"
31#include "inode.h"
31 32
32#define BFITNOENT ((u32)~0) 33#define BFITNOENT ((u32)~0)
33 34
@@ -50,6 +51,9 @@ static const char valid_change[16] = {
50 1, 0, 0, 0 51 1, 0, 0, 0
51}; 52};
52 53
54static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
55 unsigned char old_state, unsigned char new_state);
56
53/** 57/**
54 * gfs2_setbit - Set a bit in the bitmaps 58 * gfs2_setbit - Set a bit in the bitmaps
55 * @buffer: the buffer that holds the bitmaps 59 * @buffer: the buffer that holds the bitmaps
@@ -531,6 +535,7 @@ static int read_rindex_entry(struct gfs2_inode *ip,
531 535
532 rgd->rd_gl->gl_object = rgd; 536 rgd->rd_gl->gl_object = rgd;
533 rgd->rd_rg_vn = rgd->rd_gl->gl_vn - 1; 537 rgd->rd_rg_vn = rgd->rd_gl->gl_vn - 1;
538 rgd->rd_flags |= GFS2_RDF_CHECK;
534 return error; 539 return error;
535} 540}
536 541
@@ -846,6 +851,37 @@ static int try_rgrp_fit(struct gfs2_rgrpd *rgd, struct gfs2_alloc *al)
846} 851}
847 852
848/** 853/**
854 * try_rgrp_unlink - Look for any unlinked, allocated, but unused inodes
855 * @rgd: The rgrp
856 *
857 * Returns: The inode, if one has been found
858 */
859
860static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked)
861{
862 struct inode *inode;
863 u32 goal = 0;
864 u64 ino;
865
866 for(;;) {
867 goal = rgblk_search(rgd, goal, GFS2_BLKST_UNLINKED,
868 GFS2_BLKST_UNLINKED);
869 if (goal == 0)
870 return 0;
871 ino = goal + rgd->rd_data0;
872 if (ino <= *last_unlinked)
873 continue;
874 *last_unlinked = ino;
875 inode = gfs2_inode_lookup(rgd->rd_sbd->sd_vfs, ino, DT_UNKNOWN);
876 if (!IS_ERR(inode))
877 return inode;
878 }
879
880 rgd->rd_flags &= ~GFS2_RDF_CHECK;
881 return NULL;
882}
883
884/**
849 * recent_rgrp_first - get first RG from "recent" list 885 * recent_rgrp_first - get first RG from "recent" list
850 * @sdp: The GFS2 superblock 886 * @sdp: The GFS2 superblock
851 * @rglast: address of the rgrp used last 887 * @rglast: address of the rgrp used last
@@ -1006,8 +1042,9 @@ static void forward_rgrp_set(struct gfs2_sbd *sdp, struct gfs2_rgrpd *rgd)
1006 * Returns: errno 1042 * Returns: errno
1007 */ 1043 */
1008 1044
1009static int get_local_rgrp(struct gfs2_inode *ip) 1045static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked)
1010{ 1046{
1047 struct inode *inode = NULL;
1011 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); 1048 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
1012 struct gfs2_rgrpd *rgd, *begin = NULL; 1049 struct gfs2_rgrpd *rgd, *begin = NULL;
1013 struct gfs2_alloc *al = &ip->i_alloc; 1050 struct gfs2_alloc *al = &ip->i_alloc;
@@ -1027,7 +1064,11 @@ static int get_local_rgrp(struct gfs2_inode *ip)
1027 case 0: 1064 case 0:
1028 if (try_rgrp_fit(rgd, al)) 1065 if (try_rgrp_fit(rgd, al))
1029 goto out; 1066 goto out;
1067 if (rgd->rd_flags & GFS2_RDF_CHECK)
1068 inode = try_rgrp_unlink(rgd, last_unlinked);
1030 gfs2_glock_dq_uninit(&al->al_rgd_gh); 1069 gfs2_glock_dq_uninit(&al->al_rgd_gh);
1070 if (inode)
1071 return inode;
1031 rgd = recent_rgrp_next(rgd, 1); 1072 rgd = recent_rgrp_next(rgd, 1);
1032 break; 1073 break;
1033 1074
@@ -1036,7 +1077,7 @@ static int get_local_rgrp(struct gfs2_inode *ip)
1036 break; 1077 break;
1037 1078
1038 default: 1079 default:
1039 return error; 1080 return ERR_PTR(error);
1040 } 1081 }
1041 } 1082 }
1042 1083
@@ -1051,7 +1092,11 @@ static int get_local_rgrp(struct gfs2_inode *ip)
1051 case 0: 1092 case 0:
1052 if (try_rgrp_fit(rgd, al)) 1093 if (try_rgrp_fit(rgd, al))
1053 goto out; 1094 goto out;
1095 if (rgd->rd_flags & GFS2_RDF_CHECK)
1096 inode = try_rgrp_unlink(rgd, last_unlinked);
1054 gfs2_glock_dq_uninit(&al->al_rgd_gh); 1097 gfs2_glock_dq_uninit(&al->al_rgd_gh);
1098 if (inode)
1099 return inode;
1055 break; 1100 break;
1056 1101
1057 case GLR_TRYFAILED: 1102 case GLR_TRYFAILED:
@@ -1059,7 +1104,7 @@ static int get_local_rgrp(struct gfs2_inode *ip)
1059 break; 1104 break;
1060 1105
1061 default: 1106 default:
1062 return error; 1107 return ERR_PTR(error);
1063 } 1108 }
1064 1109
1065 rgd = gfs2_rgrpd_get_next(rgd); 1110 rgd = gfs2_rgrpd_get_next(rgd);
@@ -1068,7 +1113,7 @@ static int get_local_rgrp(struct gfs2_inode *ip)
1068 1113
1069 if (rgd == begin) { 1114 if (rgd == begin) {
1070 if (++loops >= 3) 1115 if (++loops >= 3)
1071 return -ENOSPC; 1116 return ERR_PTR(-ENOSPC);
1072 if (!skipped) 1117 if (!skipped)
1073 loops++; 1118 loops++;
1074 flags = 0; 1119 flags = 0;
@@ -1088,7 +1133,7 @@ out:
1088 forward_rgrp_set(sdp, rgd); 1133 forward_rgrp_set(sdp, rgd);
1089 } 1134 }
1090 1135
1091 return 0; 1136 return NULL;
1092} 1137}
1093 1138
1094/** 1139/**
@@ -1102,11 +1147,14 @@ int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, unsigned int line)
1102{ 1147{
1103 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); 1148 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
1104 struct gfs2_alloc *al = &ip->i_alloc; 1149 struct gfs2_alloc *al = &ip->i_alloc;
1150 struct inode *inode;
1105 int error = 0; 1151 int error = 0;
1152 u64 last_unlinked = 0;
1106 1153
1107 if (gfs2_assert_warn(sdp, al->al_requested)) 1154 if (gfs2_assert_warn(sdp, al->al_requested))
1108 return -EINVAL; 1155 return -EINVAL;
1109 1156
1157try_again:
1110 /* We need to hold the rindex unless the inode we're using is 1158 /* We need to hold the rindex unless the inode we're using is
1111 the rindex itself, in which case it's already held. */ 1159 the rindex itself, in which case it's already held. */
1112 if (ip != GFS2_I(sdp->sd_rindex)) 1160 if (ip != GFS2_I(sdp->sd_rindex))
@@ -1117,11 +1165,15 @@ int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, unsigned int line)
1117 if (error) 1165 if (error)
1118 return error; 1166 return error;
1119 1167
1120 error = get_local_rgrp(ip); 1168 inode = get_local_rgrp(ip, &last_unlinked);
1121 if (error) { 1169 if (inode) {
1122 if (ip != GFS2_I(sdp->sd_rindex)) 1170 if (ip != GFS2_I(sdp->sd_rindex))
1123 gfs2_glock_dq_uninit(&al->al_ri_gh); 1171 gfs2_glock_dq_uninit(&al->al_ri_gh);
1124 return error; 1172 if (IS_ERR(inode))
1173 return PTR_ERR(inode);
1174 iput(inode);
1175 gfs2_log_flush(sdp, NULL);
1176 goto try_again;
1125 } 1177 }
1126 1178
1127 al->al_file = file; 1179 al->al_file = file;
@@ -1209,7 +1261,7 @@ unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block)
1209 */ 1261 */
1210 1262
1211static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal, 1263static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
1212 unsigned char old_state, unsigned char new_state) 1264 unsigned char old_state, unsigned char new_state)
1213{ 1265{
1214 struct gfs2_bitmap *bi = NULL; 1266 struct gfs2_bitmap *bi = NULL;
1215 u32 length = rgd->rd_length; 1267 u32 length = rgd->rd_length;
@@ -1250,17 +1302,18 @@ static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
1250 goal = 0; 1302 goal = 0;
1251 } 1303 }
1252 1304
1253 if (gfs2_assert_withdraw(rgd->rd_sbd, x <= length)) 1305 if (old_state != new_state) {
1254 blk = 0; 1306 gfs2_assert_withdraw(rgd->rd_sbd, blk != BFITNOENT);
1255 1307
1256 gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1); 1308 gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1);
1257 gfs2_setbit(rgd, bi->bi_bh->b_data + bi->bi_offset, 1309 gfs2_setbit(rgd, bi->bi_bh->b_data + bi->bi_offset,
1258 bi->bi_len, blk, new_state);
1259 if (bi->bi_clone)
1260 gfs2_setbit(rgd, bi->bi_clone + bi->bi_offset,
1261 bi->bi_len, blk, new_state); 1310 bi->bi_len, blk, new_state);
1311 if (bi->bi_clone)
1312 gfs2_setbit(rgd, bi->bi_clone + bi->bi_offset,
1313 bi->bi_len, blk, new_state);
1314 }
1262 1315
1263 return bi->bi_start * GFS2_NBBY + blk; 1316 return (blk == BFITNOENT) ? 0 : (bi->bi_start * GFS2_NBBY) + blk;
1264} 1317}
1265 1318
1266/** 1319/**