summaryrefslogtreecommitdiffstats
path: root/fs/gfs2/aops.c
diff options
context:
space:
mode:
authorSteven Whitehouse2010-03-25 15:32:43 +0100
committerSteven Whitehouse2010-03-29 15:29:17 +0200
commit602c89d2e3e8652f94a697c9a919be739b9bcdd5 (patch)
tree791c0f4ea2b1f9028f7fdf60dbedd42fa0f8ce06 /fs/gfs2/aops.c
parentGFS2: docs update (diff)
downloadkernel-qcow2-linux-602c89d2e3e8652f94a697c9a919be739b9bcdd5.tar.gz
kernel-qcow2-linux-602c89d2e3e8652f94a697c9a919be739b9bcdd5.tar.xz
kernel-qcow2-linux-602c89d2e3e8652f94a697c9a919be739b9bcdd5.zip
GFS2: Clean up stuffed file copying
If the inode size was corrupt for stuffed files, it was possible for the copying of data to overrun the block and/or page. This patch checks for that condition so that this is no longer possible. This is also preparation for the new truncate sequence patch which requires the ability to have stuffed files with larger sizes than (disk block size - sizeof(on disk inode)) with the restriction that only the initial part of the file may be non-zero. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/aops.c')
-rw-r--r--fs/gfs2/aops.c8
1 files changed, 5 insertions, 3 deletions
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index 0c1d0b82dcf1..a739a0a48067 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -418,6 +418,7 @@ static int gfs2_jdata_writepages(struct address_space *mapping,
static int stuffed_readpage(struct gfs2_inode *ip, struct page *page)
{
struct buffer_head *dibh;
+ u64 dsize = i_size_read(&ip->i_inode);
void *kaddr;
int error;
@@ -437,9 +438,10 @@ static int stuffed_readpage(struct gfs2_inode *ip, struct page *page)
return error;
kaddr = kmap_atomic(page, KM_USER0);
- memcpy(kaddr, dibh->b_data + sizeof(struct gfs2_dinode),
- ip->i_disksize);
- memset(kaddr + ip->i_disksize, 0, PAGE_CACHE_SIZE - ip->i_disksize);
+ if (dsize > (dibh->b_size - sizeof(struct gfs2_dinode)))
+ dsize = (dibh->b_size - sizeof(struct gfs2_dinode));
+ memcpy(kaddr, dibh->b_data + sizeof(struct gfs2_dinode), dsize);
+ memset(kaddr + dsize, 0, PAGE_CACHE_SIZE - dsize);
kunmap_atomic(kaddr, KM_USER0);
flush_dcache_page(page);
brelse(dibh);