aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2
diff options
context:
space:
mode:
Diffstat (limited to 'fs/gfs2')
-rw-r--r--fs/gfs2/ops_address.c29
-rw-r--r--fs/gfs2/ops_address.h5
-rw-r--r--fs/gfs2/rgrp.c60
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 */
456static 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;
18extern int gfs2_get_block(struct inode *inode, sector_t lblock, 18extern 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);
20extern int gfs2_releasepage(struct page *page, gfp_t gfp_mask); 20extern int gfs2_releasepage(struct page *page, gfp_t gfp_mask);
21extern u64 gfs2_ri_total(struct gfs2_sbd *sdp);
22extern 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 */
437u64 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/**