diff options
Diffstat (limited to 'fs/gfs2/rgrp.c')
-rw-r--r-- | fs/gfs2/rgrp.c | 50 |
1 files changed, 37 insertions, 13 deletions
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 171a744f8e45..fb67f593f408 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c | |||
@@ -500,7 +500,7 @@ u64 gfs2_ri_total(struct gfs2_sbd *sdp) | |||
500 | for (rgrps = 0;; rgrps++) { | 500 | for (rgrps = 0;; rgrps++) { |
501 | loff_t pos = rgrps * sizeof(struct gfs2_rindex); | 501 | loff_t pos = rgrps * sizeof(struct gfs2_rindex); |
502 | 502 | ||
503 | if (pos + sizeof(struct gfs2_rindex) >= ip->i_disksize) | 503 | if (pos + sizeof(struct gfs2_rindex) >= i_size_read(inode)) |
504 | break; | 504 | break; |
505 | error = gfs2_internal_read(ip, &ra_state, buf, &pos, | 505 | error = gfs2_internal_read(ip, &ra_state, buf, &pos, |
506 | sizeof(struct gfs2_rindex)); | 506 | sizeof(struct gfs2_rindex)); |
@@ -588,7 +588,9 @@ static int gfs2_ri_update(struct gfs2_inode *ip) | |||
588 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 588 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
589 | struct inode *inode = &ip->i_inode; | 589 | struct inode *inode = &ip->i_inode; |
590 | struct file_ra_state ra_state; | 590 | struct file_ra_state ra_state; |
591 | u64 rgrp_count = ip->i_disksize; | 591 | u64 rgrp_count = i_size_read(inode); |
592 | struct gfs2_rgrpd *rgd; | ||
593 | unsigned int max_data = 0; | ||
592 | int error; | 594 | int error; |
593 | 595 | ||
594 | do_div(rgrp_count, sizeof(struct gfs2_rindex)); | 596 | do_div(rgrp_count, sizeof(struct gfs2_rindex)); |
@@ -603,6 +605,10 @@ static int gfs2_ri_update(struct gfs2_inode *ip) | |||
603 | } | 605 | } |
604 | } | 606 | } |
605 | 607 | ||
608 | list_for_each_entry(rgd, &sdp->sd_rindex_list, rd_list) | ||
609 | if (rgd->rd_data > max_data) | ||
610 | max_data = rgd->rd_data; | ||
611 | sdp->sd_max_rg_data = max_data; | ||
606 | sdp->sd_rindex_uptodate = 1; | 612 | sdp->sd_rindex_uptodate = 1; |
607 | return 0; | 613 | return 0; |
608 | } | 614 | } |
@@ -622,13 +628,15 @@ static int gfs2_ri_update_special(struct gfs2_inode *ip) | |||
622 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 628 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
623 | struct inode *inode = &ip->i_inode; | 629 | struct inode *inode = &ip->i_inode; |
624 | struct file_ra_state ra_state; | 630 | struct file_ra_state ra_state; |
631 | struct gfs2_rgrpd *rgd; | ||
632 | unsigned int max_data = 0; | ||
625 | int error; | 633 | int error; |
626 | 634 | ||
627 | file_ra_state_init(&ra_state, inode->i_mapping); | 635 | file_ra_state_init(&ra_state, inode->i_mapping); |
628 | for (sdp->sd_rgrps = 0;; sdp->sd_rgrps++) { | 636 | for (sdp->sd_rgrps = 0;; sdp->sd_rgrps++) { |
629 | /* Ignore partials */ | 637 | /* Ignore partials */ |
630 | if ((sdp->sd_rgrps + 1) * sizeof(struct gfs2_rindex) > | 638 | if ((sdp->sd_rgrps + 1) * sizeof(struct gfs2_rindex) > |
631 | ip->i_disksize) | 639 | i_size_read(inode)) |
632 | break; | 640 | break; |
633 | error = read_rindex_entry(ip, &ra_state); | 641 | error = read_rindex_entry(ip, &ra_state); |
634 | if (error) { | 642 | if (error) { |
@@ -636,6 +644,10 @@ static int gfs2_ri_update_special(struct gfs2_inode *ip) | |||
636 | return error; | 644 | return error; |
637 | } | 645 | } |
638 | } | 646 | } |
647 | list_for_each_entry(rgd, &sdp->sd_rindex_list, rd_list) | ||
648 | if (rgd->rd_data > max_data) | ||
649 | max_data = rgd->rd_data; | ||
650 | sdp->sd_max_rg_data = max_data; | ||
639 | 651 | ||
640 | sdp->sd_rindex_uptodate = 1; | 652 | sdp->sd_rindex_uptodate = 1; |
641 | return 0; | 653 | return 0; |
@@ -1188,7 +1200,8 @@ out: | |||
1188 | * Returns: errno | 1200 | * Returns: errno |
1189 | */ | 1201 | */ |
1190 | 1202 | ||
1191 | int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, unsigned int line) | 1203 | int gfs2_inplace_reserve_i(struct gfs2_inode *ip, int hold_rindex, |
1204 | char *file, unsigned int line) | ||
1192 | { | 1205 | { |
1193 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 1206 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
1194 | struct gfs2_alloc *al = ip->i_alloc; | 1207 | struct gfs2_alloc *al = ip->i_alloc; |
@@ -1199,12 +1212,15 @@ int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, unsigned int line) | |||
1199 | return -EINVAL; | 1212 | return -EINVAL; |
1200 | 1213 | ||
1201 | try_again: | 1214 | try_again: |
1202 | /* We need to hold the rindex unless the inode we're using is | 1215 | if (hold_rindex) { |
1203 | the rindex itself, in which case it's already held. */ | 1216 | /* We need to hold the rindex unless the inode we're using is |
1204 | if (ip != GFS2_I(sdp->sd_rindex)) | 1217 | the rindex itself, in which case it's already held. */ |
1205 | error = gfs2_rindex_hold(sdp, &al->al_ri_gh); | 1218 | if (ip != GFS2_I(sdp->sd_rindex)) |
1206 | else if (!sdp->sd_rgrps) /* We may not have the rindex read in, so: */ | 1219 | error = gfs2_rindex_hold(sdp, &al->al_ri_gh); |
1207 | error = gfs2_ri_update_special(ip); | 1220 | else if (!sdp->sd_rgrps) /* We may not have the rindex read |
1221 | in, so: */ | ||
1222 | error = gfs2_ri_update_special(ip); | ||
1223 | } | ||
1208 | 1224 | ||
1209 | if (error) | 1225 | if (error) |
1210 | return error; | 1226 | return error; |
@@ -1215,7 +1231,7 @@ try_again: | |||
1215 | try to free it, and try the allocation again. */ | 1231 | try to free it, and try the allocation again. */ |
1216 | error = get_local_rgrp(ip, &unlinked, &last_unlinked); | 1232 | error = get_local_rgrp(ip, &unlinked, &last_unlinked); |
1217 | if (error) { | 1233 | if (error) { |
1218 | if (ip != GFS2_I(sdp->sd_rindex)) | 1234 | if (hold_rindex && ip != GFS2_I(sdp->sd_rindex)) |
1219 | gfs2_glock_dq_uninit(&al->al_ri_gh); | 1235 | gfs2_glock_dq_uninit(&al->al_ri_gh); |
1220 | if (error != -EAGAIN) | 1236 | if (error != -EAGAIN) |
1221 | return error; | 1237 | return error; |
@@ -1257,7 +1273,7 @@ void gfs2_inplace_release(struct gfs2_inode *ip) | |||
1257 | al->al_rgd = NULL; | 1273 | al->al_rgd = NULL; |
1258 | if (al->al_rgd_gh.gh_gl) | 1274 | if (al->al_rgd_gh.gh_gl) |
1259 | gfs2_glock_dq_uninit(&al->al_rgd_gh); | 1275 | gfs2_glock_dq_uninit(&al->al_rgd_gh); |
1260 | if (ip != GFS2_I(sdp->sd_rindex)) | 1276 | if (ip != GFS2_I(sdp->sd_rindex) && al->al_ri_gh.gh_gl) |
1261 | gfs2_glock_dq_uninit(&al->al_ri_gh); | 1277 | gfs2_glock_dq_uninit(&al->al_ri_gh); |
1262 | } | 1278 | } |
1263 | 1279 | ||
@@ -1496,11 +1512,19 @@ int gfs2_alloc_block(struct gfs2_inode *ip, u64 *bn, unsigned int *n) | |||
1496 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 1512 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
1497 | struct buffer_head *dibh; | 1513 | struct buffer_head *dibh; |
1498 | struct gfs2_alloc *al = ip->i_alloc; | 1514 | struct gfs2_alloc *al = ip->i_alloc; |
1499 | struct gfs2_rgrpd *rgd = al->al_rgd; | 1515 | struct gfs2_rgrpd *rgd; |
1500 | u32 goal, blk; | 1516 | u32 goal, blk; |
1501 | u64 block; | 1517 | u64 block; |
1502 | int error; | 1518 | int error; |
1503 | 1519 | ||
1520 | /* Only happens if there is a bug in gfs2, return something distinctive | ||
1521 | * to ensure that it is noticed. | ||
1522 | */ | ||
1523 | if (al == NULL) | ||
1524 | return -ECANCELED; | ||
1525 | |||
1526 | rgd = al->al_rgd; | ||
1527 | |||
1504 | if (rgrp_contains_block(rgd, ip->i_goal)) | 1528 | if (rgrp_contains_block(rgd, ip->i_goal)) |
1505 | goal = ip->i_goal - rgd->rd_data0; | 1529 | goal = ip->i_goal - rgd->rd_data0; |
1506 | else | 1530 | else |