diff options
Diffstat (limited to 'fs/gfs2/ops_address.c')
-rw-r--r-- | fs/gfs2/ops_address.c | 69 |
1 files changed, 60 insertions, 9 deletions
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c index 30c15622174f..26c888890c24 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 |
@@ -32,6 +32,7 @@ | |||
32 | #include "trans.h" | 32 | #include "trans.h" |
33 | #include "rgrp.h" | 33 | #include "rgrp.h" |
34 | #include "ops_file.h" | 34 | #include "ops_file.h" |
35 | #include "super.h" | ||
35 | #include "util.h" | 36 | #include "util.h" |
36 | #include "glops.h" | 37 | #include "glops.h" |
37 | 38 | ||
@@ -49,6 +50,8 @@ static void gfs2_page_add_databufs(struct gfs2_inode *ip, struct page *page, | |||
49 | end = start + bsize; | 50 | end = start + bsize; |
50 | if (end <= from || start >= to) | 51 | if (end <= from || start >= to) |
51 | continue; | 52 | continue; |
53 | if (gfs2_is_jdata(ip)) | ||
54 | set_buffer_uptodate(bh); | ||
52 | gfs2_trans_add_bh(ip->i_gl, bh, 0); | 55 | gfs2_trans_add_bh(ip->i_gl, bh, 0); |
53 | } | 56 | } |
54 | } | 57 | } |
@@ -134,7 +137,9 @@ static int gfs2_writepage(struct page *page, struct writeback_control *wbc) | |||
134 | return 0; /* don't care */ | 137 | return 0; /* don't care */ |
135 | } | 138 | } |
136 | 139 | ||
137 | if (sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip)) { | 140 | if ((sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip)) && |
141 | PageChecked(page)) { | ||
142 | ClearPageChecked(page); | ||
138 | error = gfs2_trans_begin(sdp, RES_DINODE + 1, 0); | 143 | error = gfs2_trans_begin(sdp, RES_DINODE + 1, 0); |
139 | if (error) | 144 | if (error) |
140 | goto out_ignore; | 145 | goto out_ignore; |
@@ -203,11 +208,7 @@ static int stuffed_readpage(struct gfs2_inode *ip, struct page *page) | |||
203 | * so we need to supply one here. It doesn't happen often. | 208 | * so we need to supply one here. It doesn't happen often. |
204 | */ | 209 | */ |
205 | if (unlikely(page->index)) { | 210 | if (unlikely(page->index)) { |
206 | kaddr = kmap_atomic(page, KM_USER0); | 211 | zero_user_page(page, 0, PAGE_CACHE_SIZE, KM_USER0); |
207 | memset(kaddr, 0, PAGE_CACHE_SIZE); | ||
208 | kunmap_atomic(kaddr, KM_USER0); | ||
209 | flush_dcache_page(page); | ||
210 | SetPageUptodate(page); | ||
211 | return 0; | 212 | return 0; |
212 | } | 213 | } |
213 | 214 | ||
@@ -450,6 +451,31 @@ out_uninit: | |||
450 | } | 451 | } |
451 | 452 | ||
452 | /** | 453 | /** |
454 | * adjust_fs_space - Adjusts the free space available due to gfs2_grow | ||
455 | * @inode: the rindex inode | ||
456 | */ | ||
457 | static void adjust_fs_space(struct inode *inode) | ||
458 | { | ||
459 | struct gfs2_sbd *sdp = inode->i_sb->s_fs_info; | ||
460 | struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master; | ||
461 | struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local; | ||
462 | u64 fs_total, new_free; | ||
463 | |||
464 | /* Total up the file system space, according to the latest rindex. */ | ||
465 | fs_total = gfs2_ri_total(sdp); | ||
466 | |||
467 | spin_lock(&sdp->sd_statfs_spin); | ||
468 | if (fs_total > (m_sc->sc_total + l_sc->sc_total)) | ||
469 | new_free = fs_total - (m_sc->sc_total + l_sc->sc_total); | ||
470 | else | ||
471 | new_free = 0; | ||
472 | spin_unlock(&sdp->sd_statfs_spin); | ||
473 | fs_warn(sdp, "File system extended by %llu blocks.\n", | ||
474 | (unsigned long long)new_free); | ||
475 | gfs2_statfs_change(sdp, new_free, new_free, 0); | ||
476 | } | ||
477 | |||
478 | /** | ||
453 | * gfs2_commit_write - Commit write to a file | 479 | * gfs2_commit_write - Commit write to a file |
454 | * @file: The file to write to | 480 | * @file: The file to write to |
455 | * @page: The page containing the data | 481 | * @page: The page containing the data |
@@ -511,6 +537,9 @@ static int gfs2_commit_write(struct file *file, struct page *page, | |||
511 | di->di_size = cpu_to_be64(inode->i_size); | 537 | di->di_size = cpu_to_be64(inode->i_size); |
512 | } | 538 | } |
513 | 539 | ||
540 | if (inode == sdp->sd_rindex) | ||
541 | adjust_fs_space(inode); | ||
542 | |||
514 | brelse(dibh); | 543 | brelse(dibh); |
515 | gfs2_trans_end(sdp); | 544 | gfs2_trans_end(sdp); |
516 | if (al->al_requested) { | 545 | if (al->al_requested) { |
@@ -543,6 +572,23 @@ fail_nounlock: | |||
543 | } | 572 | } |
544 | 573 | ||
545 | /** | 574 | /** |
575 | * gfs2_set_page_dirty - Page dirtying function | ||
576 | * @page: The page to dirty | ||
577 | * | ||
578 | * Returns: 1 if it dirtyed the page, or 0 otherwise | ||
579 | */ | ||
580 | |||
581 | static int gfs2_set_page_dirty(struct page *page) | ||
582 | { | ||
583 | struct gfs2_inode *ip = GFS2_I(page->mapping->host); | ||
584 | struct gfs2_sbd *sdp = GFS2_SB(page->mapping->host); | ||
585 | |||
586 | if (sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip)) | ||
587 | SetPageChecked(page); | ||
588 | return __set_page_dirty_buffers(page); | ||
589 | } | ||
590 | |||
591 | /** | ||
546 | * gfs2_bmap - Block map function | 592 | * gfs2_bmap - Block map function |
547 | * @mapping: Address space info | 593 | * @mapping: Address space info |
548 | * @lblock: The block to map | 594 | * @lblock: The block to map |
@@ -578,6 +624,8 @@ static void discard_buffer(struct gfs2_sbd *sdp, struct buffer_head *bh) | |||
578 | if (bd) { | 624 | if (bd) { |
579 | bd->bd_bh = NULL; | 625 | bd->bd_bh = NULL; |
580 | bh->b_private = NULL; | 626 | bh->b_private = NULL; |
627 | if (!bd->bd_ail && list_empty(&bd->bd_le.le_list)) | ||
628 | kmem_cache_free(gfs2_bufdata_cachep, bd); | ||
581 | } | 629 | } |
582 | gfs2_log_unlock(sdp); | 630 | gfs2_log_unlock(sdp); |
583 | 631 | ||
@@ -598,6 +646,8 @@ static void gfs2_invalidatepage(struct page *page, unsigned long offset) | |||
598 | unsigned int curr_off = 0; | 646 | unsigned int curr_off = 0; |
599 | 647 | ||
600 | BUG_ON(!PageLocked(page)); | 648 | BUG_ON(!PageLocked(page)); |
649 | if (offset == 0) | ||
650 | ClearPageChecked(page); | ||
601 | if (!page_has_buffers(page)) | 651 | if (!page_has_buffers(page)) |
602 | return; | 652 | return; |
603 | 653 | ||
@@ -728,8 +778,8 @@ static unsigned limit = 0; | |||
728 | return; | 778 | return; |
729 | 779 | ||
730 | fs_warn(sdp, "ip = %llu %llu\n", | 780 | fs_warn(sdp, "ip = %llu %llu\n", |
731 | (unsigned long long)ip->i_num.no_formal_ino, | 781 | (unsigned long long)ip->i_no_formal_ino, |
732 | (unsigned long long)ip->i_num.no_addr); | 782 | (unsigned long long)ip->i_no_addr); |
733 | 783 | ||
734 | for (x = 0; x < GFS2_MAX_META_HEIGHT; x++) | 784 | for (x = 0; x < GFS2_MAX_META_HEIGHT; x++) |
735 | fs_warn(sdp, "ip->i_cache[%u] = %s\n", | 785 | fs_warn(sdp, "ip->i_cache[%u] = %s\n", |
@@ -810,6 +860,7 @@ const struct address_space_operations gfs2_file_aops = { | |||
810 | .sync_page = block_sync_page, | 860 | .sync_page = block_sync_page, |
811 | .prepare_write = gfs2_prepare_write, | 861 | .prepare_write = gfs2_prepare_write, |
812 | .commit_write = gfs2_commit_write, | 862 | .commit_write = gfs2_commit_write, |
863 | .set_page_dirty = gfs2_set_page_dirty, | ||
813 | .bmap = gfs2_bmap, | 864 | .bmap = gfs2_bmap, |
814 | .invalidatepage = gfs2_invalidatepage, | 865 | .invalidatepage = gfs2_invalidatepage, |
815 | .releasepage = gfs2_releasepage, | 866 | .releasepage = gfs2_releasepage, |