From 8e2e00473598dd5379d8408cb974dade000acafc Mon Sep 17 00:00:00 2001 From: Bob Peterson Date: Thu, 19 Jul 2012 08:12:40 -0400 Subject: 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 Signed-off-by: Steven Whitehouse --- fs/gfs2/file.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) (limited to 'fs/gfs2/file.c') diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index 6fbf3cbd974d..9f94832cefec 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c @@ -383,6 +383,9 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) 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 @@ fail: 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 @@ static ssize_t gfs2_file_aio_write(struct kiocb *iocb, const struct iovec *iov, 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 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset, 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 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset, offset += bytes; continue; } - error = gfs2_rindex_update(sdp); - if (error) - goto out_unlock; - error = gfs2_quota_lock_check(ip); if (error) goto out_unlock; -- cgit v1.2.3