aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/bmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/gfs2/bmap.c')
-rw-r--r--fs/gfs2/bmap.c78
1 files changed, 77 insertions, 1 deletions
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 72b19c5d7807..d20d41e1c028 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -22,12 +22,12 @@
22#include "glock.h" 22#include "glock.h"
23#include "inode.h" 23#include "inode.h"
24#include "meta_io.h" 24#include "meta_io.h"
25#include "page.h"
26#include "quota.h" 25#include "quota.h"
27#include "rgrp.h" 26#include "rgrp.h"
28#include "trans.h" 27#include "trans.h"
29#include "dir.h" 28#include "dir.h"
30#include "util.h" 29#include "util.h"
30#include "ops_address.h"
31 31
32/* This doesn't need to be that large as max 64 bit pointers in a 4k 32/* This doesn't need to be that large as max 64 bit pointers in a 4k
33 * block is 512, so __u16 is fine for that. It saves stack space to 33 * block is 512, so __u16 is fine for that. It saves stack space to
@@ -885,6 +885,82 @@ static int do_grow(struct gfs2_inode *ip, uint64_t size)
885 return error; 885 return error;
886} 886}
887 887
888
889/**
890 * gfs2_block_truncate_page - Deal with zeroing out data for truncate
891 *
892 * This is partly borrowed from ext3.
893 */
894static int gfs2_block_truncate_page(struct address_space *mapping)
895{
896 struct inode *inode = mapping->host;
897 struct gfs2_inode *ip = GFS2_I(inode);
898 struct gfs2_sbd *sdp = GFS2_SB(inode);
899 loff_t from = inode->i_size;
900 unsigned long index = from >> PAGE_CACHE_SHIFT;
901 unsigned offset = from & (PAGE_CACHE_SIZE-1);
902 unsigned blocksize, iblock, length, pos;
903 struct buffer_head *bh;
904 struct page *page;
905 void *kaddr;
906 int err;
907
908 page = grab_cache_page(mapping, index);
909 if (!page)
910 return 0;
911
912 blocksize = inode->i_sb->s_blocksize;
913 length = blocksize - (offset & (blocksize - 1));
914 iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits);
915
916 if (!page_has_buffers(page))
917 create_empty_buffers(page, blocksize, 0);
918
919 /* Find the buffer that contains "offset" */
920 bh = page_buffers(page);
921 pos = blocksize;
922 while (offset >= pos) {
923 bh = bh->b_this_page;
924 iblock++;
925 pos += blocksize;
926 }
927
928 err = 0;
929
930 if (!buffer_mapped(bh)) {
931 gfs2_get_block(inode, iblock, bh, 0);
932 /* unmapped? It's a hole - nothing to do */
933 if (!buffer_mapped(bh))
934 goto unlock;
935 }
936
937 /* Ok, it's mapped. Make sure it's up-to-date */
938 if (PageUptodate(page))
939 set_buffer_uptodate(bh);
940
941 if (!buffer_uptodate(bh)) {
942 err = -EIO;
943 ll_rw_block(READ, 1, &bh);
944 wait_on_buffer(bh);
945 /* Uhhuh. Read error. Complain and punt. */
946 if (!buffer_uptodate(bh))
947 goto unlock;
948 }
949
950 if (sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip))
951 gfs2_trans_add_bh(ip->i_gl, bh, 0);
952
953 kaddr = kmap_atomic(page, KM_USER0);
954 memset(kaddr + offset, 0, length);
955 flush_dcache_page(page);
956 kunmap_atomic(kaddr, KM_USER0);
957
958unlock:
959 unlock_page(page);
960 page_cache_release(page);
961 return err;
962}
963
888static int trunc_start(struct gfs2_inode *ip, uint64_t size) 964static int trunc_start(struct gfs2_inode *ip, uint64_t size)
889{ 965{
890 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); 966 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);