GFS2: Reduce file fragmentation
This patch reduces GFS2 file fragmentation by pre-reserving blocks. The
resulting improved on disk layout greatly speeds up operations in cases
which would have resulted in interlaced allocation of blocks previously.
A typical example of this is 10 parallel dd processes, each writing to a
file in a common dirctory.
The implementation uses an rbtree of reservations attached to each
resource group (and each inode).
Signed-off-by: Bob Peterson <rpeterso@redhat.com>
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
index 6fbf3cb..9f94832 100644
--- a/fs/gfs2/file.c
+++ b/fs/gfs2/file.c
@@ -383,6 +383,9 @@
if (ret)
return ret;
+ atomic_set(&ip->i_res->rs_sizehint,
+ PAGE_CACHE_SIZE / sdp->sd_sb.sb_bsize);
+
gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
ret = gfs2_glock_nq(&gh);
if (ret)
@@ -571,22 +574,15 @@
static int gfs2_release(struct inode *inode, struct file *file)
{
- struct gfs2_sbd *sdp = inode->i_sb->s_fs_info;
- struct gfs2_file *fp;
struct gfs2_inode *ip = GFS2_I(inode);
- fp = file->private_data;
+ kfree(file->private_data);
file->private_data = NULL;
- if ((file->f_mode & FMODE_WRITE) && ip->i_res &&
+ if ((file->f_mode & FMODE_WRITE) &&
(atomic_read(&inode->i_writecount) == 1))
gfs2_rs_delete(ip);
- if (gfs2_assert_warn(sdp, fp))
- return -EIO;
-
- kfree(fp);
-
return 0;
}
@@ -662,14 +658,18 @@
unsigned long nr_segs, loff_t pos)
{
struct file *file = iocb->ki_filp;
+ size_t writesize = iov_length(iov, nr_segs);
struct dentry *dentry = file->f_dentry;
struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
+ struct gfs2_sbd *sdp;
int ret;
+ sdp = GFS2_SB(file->f_mapping->host);
ret = gfs2_rs_alloc(ip);
if (ret)
return ret;
+ atomic_set(&ip->i_res->rs_sizehint, writesize / sdp->sd_sb.sb_bsize);
if (file->f_flags & O_APPEND) {
struct gfs2_holder gh;
@@ -795,6 +795,8 @@
if (unlikely(error))
goto out_uninit;
+ atomic_set(&ip->i_res->rs_sizehint, len / sdp->sd_sb.sb_bsize);
+
while (len > 0) {
if (len < bytes)
bytes = len;
@@ -803,10 +805,6 @@
offset += bytes;
continue;
}
- error = gfs2_rindex_update(sdp);
- if (error)
- goto out_unlock;
-
error = gfs2_quota_lock_check(ip);
if (error)
goto out_unlock;