summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Gruenbacher <agruenba@redhat.com>2017-12-12 16:47:20 +0100
committerBob Peterson <rpeterso@redhat.com>2018-01-17 14:35:47 +0100
commite7fdf0040660c2fa184ef176c02907a98bb6f5f5 (patch)
treeccad68cc5cc6cb7c9406f9b46125f2455ec0b18b
parentgfs2: truncate: Remove unnecessary oldsize parameters (diff)
downloadlinux-e7fdf0040660c2fa184ef176c02907a98bb6f5f5.tar.xz
linux-e7fdf0040660c2fa184ef176c02907a98bb6f5f5.zip
gfs2: Remove minor gfs2_journaled_truncate inefficiencies
First, this function truncates the file in chunks. When the original file size isn't block aligned, each chunk that is truncated will remain be misaligned. This is inefficient. Second, this function doesn't recognize where holes are, so it loops through them. For each chunk of a hole, it creates a new transaction. At least avoid creating another transactions whe the current one is still empty. (An better fix would be to skip large holes, of course.) Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> Signed-off-by: Bob Peterson <rpeterso@redhat.com>
-rw-r--r--fs/gfs2/bmap.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 963117f704bf..de0c3e3c1374 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -1003,11 +1003,24 @@ static int gfs2_journaled_truncate(struct inode *inode, u64 oldsize, u64 newsize
int error;
while (oldsize != newsize) {
+ struct gfs2_trans *tr;
+ unsigned int offs;
+
chunk = oldsize - newsize;
if (chunk > max_chunk)
chunk = max_chunk;
+
+ offs = oldsize & ~PAGE_MASK;
+ if (offs && chunk > PAGE_SIZE)
+ chunk = offs + ((chunk - offs) & PAGE_MASK);
+
truncate_pagecache(inode, oldsize - chunk);
oldsize -= chunk;
+
+ tr = current->journal_info;
+ if (!test_bit(TR_TOUCHED, &tr->tr_flags))
+ continue;
+
gfs2_trans_end(sdp);
error = gfs2_trans_begin(sdp, RES_DINODE, GFS2_JTRUNC_REVOKES);
if (error)