diff options
-rw-r--r-- | fs/gfs2/ops_address.c | 29 | ||||
-rw-r--r-- | fs/gfs2/ops_address.h | 5 | ||||
-rw-r--r-- | fs/gfs2/rgrp.c | 60 |
3 files changed, 86 insertions, 8 deletions
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c index 30c15622174f..846c0ff75cff 100644 --- a/fs/gfs2/ops_address.c +++ b/fs/gfs2/ops_address.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 |
@@ -450,6 +450,30 @@ out_uninit: | |||
450 | } | 450 | } |
451 | 451 | ||
452 | /** | 452 | /** |
453 | * adjust_fs_space - Adjusts the free space available due to gfs2_grow | ||
454 | * @inode: the rindex inode | ||
455 | */ | ||
456 | static void adjust_fs_space(struct inode *inode) | ||
457 | { | ||
458 | struct gfs2_sbd *sdp = inode->i_sb->s_fs_info; | ||
459 | struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master; | ||
460 | struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local; | ||
461 | u64 fs_total, new_free; | ||
462 | |||
463 | /* Total up the file system space, according to the latest rindex. */ | ||
464 | fs_total = gfs2_ri_total(sdp); | ||
465 | |||
466 | spin_lock(&sdp->sd_statfs_spin); | ||
467 | if (fs_total > (m_sc->sc_total + l_sc->sc_total)) | ||
468 | new_free = fs_total - (m_sc->sc_total + l_sc->sc_total); | ||
469 | else | ||
470 | new_free = 0; | ||
471 | spin_unlock(&sdp->sd_statfs_spin); | ||
472 | fs_warn(sdp, "File system extended by %llu blocks.\n", new_free); | ||
473 | gfs2_statfs_change(sdp, new_free, new_free, 0); | ||
474 | } | ||
475 | |||
476 | /** | ||
453 | * gfs2_commit_write - Commit write to a file | 477 | * gfs2_commit_write - Commit write to a file |
454 | * @file: The file to write to | 478 | * @file: The file to write to |
455 | * @page: The page containing the data | 479 | * @page: The page containing the data |
@@ -511,6 +535,9 @@ static int gfs2_commit_write(struct file *file, struct page *page, | |||
511 | di->di_size = cpu_to_be64(inode->i_size); | 535 | di->di_size = cpu_to_be64(inode->i_size); |
512 | } | 536 | } |
513 | 537 | ||
538 | if (inode == sdp->sd_rindex) | ||
539 | adjust_fs_space(inode); | ||
540 | |||
514 | brelse(dibh); | 541 | brelse(dibh); |
515 | gfs2_trans_end(sdp); | 542 | gfs2_trans_end(sdp); |
516 | if (al->al_requested) { | 543 | if (al->al_requested) { |
diff --git a/fs/gfs2/ops_address.h b/fs/gfs2/ops_address.h index 35aaee4aa7e1..56c30daf895b 100644 --- a/fs/gfs2/ops_address.h +++ b/fs/gfs2/ops_address.h | |||
@@ -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 |
@@ -18,5 +18,8 @@ extern const struct address_space_operations gfs2_file_aops; | |||
18 | extern int gfs2_get_block(struct inode *inode, sector_t lblock, | 18 | extern int gfs2_get_block(struct inode *inode, sector_t lblock, |
19 | struct buffer_head *bh_result, int create); | 19 | struct buffer_head *bh_result, int create); |
20 | extern int gfs2_releasepage(struct page *page, gfp_t gfp_mask); | 20 | extern int gfs2_releasepage(struct page *page, gfp_t gfp_mask); |
21 | extern u64 gfs2_ri_total(struct gfs2_sbd *sdp); | ||
22 | extern void gfs2_statfs_change(struct gfs2_sbd *sdp, s64 total, s64 free, | ||
23 | s64 dinodes); | ||
21 | 24 | ||
22 | #endif /* __OPS_ADDRESS_DOT_H__ */ | 25 | #endif /* __OPS_ADDRESS_DOT_H__ */ |
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 | /** |