diff options
Diffstat (limited to 'fs/gfs2/rgrp.c')
-rw-r--r-- | fs/gfs2/rgrp.c | 60 |
1 files changed, 54 insertions, 6 deletions
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 1727f5012efe..e857f405353b 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | 2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
3 | * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. | 3 | * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. |
4 | * | 4 | * |
5 | * This copyrighted material is made available to anyone wishing to use, | 5 | * This copyrighted material is made available to anyone wishing to use, |
6 | * modify, copy, or redistribute it subject to the terms and conditions | 6 | * modify, copy, or redistribute it subject to the terms and conditions |
@@ -431,6 +431,38 @@ static int compute_bitstructs(struct gfs2_rgrpd *rgd) | |||
431 | } | 431 | } |
432 | 432 | ||
433 | /** | 433 | /** |
434 | * gfs2_ri_total - Total up the file system space, according to the rindex. | ||
435 | * | ||
436 | */ | ||
437 | u64 gfs2_ri_total(struct gfs2_sbd *sdp) | ||
438 | { | ||
439 | u64 total_data = 0; | ||
440 | struct inode *inode = sdp->sd_rindex; | ||
441 | struct gfs2_inode *ip = GFS2_I(inode); | ||
442 | struct gfs2_rindex_host ri; | ||
443 | char buf[sizeof(struct gfs2_rindex)]; | ||
444 | struct file_ra_state ra_state; | ||
445 | int error, rgrps; | ||
446 | |||
447 | mutex_lock(&sdp->sd_rindex_mutex); | ||
448 | file_ra_state_init(&ra_state, inode->i_mapping); | ||
449 | for (rgrps = 0;; rgrps++) { | ||
450 | loff_t pos = rgrps * sizeof(struct gfs2_rindex); | ||
451 | |||
452 | if (pos + sizeof(struct gfs2_rindex) >= ip->i_di.di_size) | ||
453 | break; | ||
454 | error = gfs2_internal_read(ip, &ra_state, buf, &pos, | ||
455 | sizeof(struct gfs2_rindex)); | ||
456 | if (error != sizeof(struct gfs2_rindex)) | ||
457 | break; | ||
458 | gfs2_rindex_in(&ri, buf); | ||
459 | total_data += ri.ri_data; | ||
460 | } | ||
461 | mutex_unlock(&sdp->sd_rindex_mutex); | ||
462 | return total_data; | ||
463 | } | ||
464 | |||
465 | /** | ||
434 | * gfs2_ri_update - Pull in a new resource index from the disk | 466 | * gfs2_ri_update - Pull in a new resource index from the disk |
435 | * @gl: The glock covering the rindex inode | 467 | * @gl: The glock covering the rindex inode |
436 | * | 468 | * |
@@ -447,7 +479,12 @@ static int gfs2_ri_update(struct gfs2_inode *ip) | |||
447 | u64 junk = ip->i_di.di_size; | 479 | u64 junk = ip->i_di.di_size; |
448 | int error; | 480 | int error; |
449 | 481 | ||
450 | if (do_div(junk, sizeof(struct gfs2_rindex))) { | 482 | /* If someone is holding the rindex file with a glock, they must |
483 | be updating it, in which case we may have partial entries. | ||
484 | In this case, we ignore the partials. */ | ||
485 | if (!gfs2_glock_is_held_excl(ip->i_gl) && | ||
486 | !gfs2_glock_is_held_shrd(ip->i_gl) && | ||
487 | do_div(junk, sizeof(struct gfs2_rindex))) { | ||
451 | gfs2_consist_inode(ip); | 488 | gfs2_consist_inode(ip); |
452 | return -EIO; | 489 | return -EIO; |
453 | } | 490 | } |
@@ -457,6 +494,9 @@ static int gfs2_ri_update(struct gfs2_inode *ip) | |||
457 | file_ra_state_init(&ra_state, inode->i_mapping); | 494 | file_ra_state_init(&ra_state, inode->i_mapping); |
458 | for (sdp->sd_rgrps = 0;; sdp->sd_rgrps++) { | 495 | for (sdp->sd_rgrps = 0;; sdp->sd_rgrps++) { |
459 | loff_t pos = sdp->sd_rgrps * sizeof(struct gfs2_rindex); | 496 | loff_t pos = sdp->sd_rgrps * sizeof(struct gfs2_rindex); |
497 | |||
498 | if (pos + sizeof(struct gfs2_rindex) >= ip->i_di.di_size) | ||
499 | break; | ||
460 | error = gfs2_internal_read(ip, &ra_state, buf, &pos, | 500 | error = gfs2_internal_read(ip, &ra_state, buf, &pos, |
461 | sizeof(struct gfs2_rindex)); | 501 | sizeof(struct gfs2_rindex)); |
462 | if (!error) | 502 | if (!error) |
@@ -978,18 +1018,25 @@ int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, unsigned int line) | |||
978 | { | 1018 | { |
979 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 1019 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
980 | struct gfs2_alloc *al = &ip->i_alloc; | 1020 | struct gfs2_alloc *al = &ip->i_alloc; |
981 | int error; | 1021 | int error = 0; |
982 | 1022 | ||
983 | if (gfs2_assert_warn(sdp, al->al_requested)) | 1023 | if (gfs2_assert_warn(sdp, al->al_requested)) |
984 | return -EINVAL; | 1024 | return -EINVAL; |
985 | 1025 | ||
986 | error = gfs2_rindex_hold(sdp, &al->al_ri_gh); | 1026 | /* We need to hold the rindex unless the inode we're using is |
1027 | the rindex itself, in which case it's already held. */ | ||
1028 | if (ip != GFS2_I(sdp->sd_rindex)) | ||
1029 | error = gfs2_rindex_hold(sdp, &al->al_ri_gh); | ||
1030 | else if (!sdp->sd_rgrps) /* We may not have the rindex read in, so: */ | ||
1031 | error = gfs2_ri_update(ip); | ||
1032 | |||
987 | if (error) | 1033 | if (error) |
988 | return error; | 1034 | return error; |
989 | 1035 | ||
990 | error = get_local_rgrp(ip); | 1036 | error = get_local_rgrp(ip); |
991 | if (error) { | 1037 | if (error) { |
992 | gfs2_glock_dq_uninit(&al->al_ri_gh); | 1038 | if (ip != GFS2_I(sdp->sd_rindex)) |
1039 | gfs2_glock_dq_uninit(&al->al_ri_gh); | ||
993 | return error; | 1040 | return error; |
994 | } | 1041 | } |
995 | 1042 | ||
@@ -1019,7 +1066,8 @@ void gfs2_inplace_release(struct gfs2_inode *ip) | |||
1019 | 1066 | ||
1020 | al->al_rgd = NULL; | 1067 | al->al_rgd = NULL; |
1021 | gfs2_glock_dq_uninit(&al->al_rgd_gh); | 1068 | gfs2_glock_dq_uninit(&al->al_rgd_gh); |
1022 | gfs2_glock_dq_uninit(&al->al_ri_gh); | 1069 | if (ip != GFS2_I(sdp->sd_rindex)) |
1070 | gfs2_glock_dq_uninit(&al->al_ri_gh); | ||
1023 | } | 1071 | } |
1024 | 1072 | ||
1025 | /** | 1073 | /** |