diff options
-rw-r--r-- | fs/xfs/xfs_file.c | 14 | ||||
-rw-r--r-- | fs/xfs/xfs_inode.c | 9 | ||||
-rw-r--r-- | fs/xfs/xfs_inode.h | 2 |
3 files changed, 18 insertions, 7 deletions
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index cea3c14e3ba0..11f57c73f748 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -1413,12 +1413,22 @@ xfs_dir_open( return error; } +/* + * When we release the file, we don't want it to trim EOF blocks if it is a + * readonly context. This avoids open/read/close workloads from removing + * EOF blocks that other writers depend upon to reduce fragmentation. + */ STATIC int xfs_file_release( struct inode *inode, - struct file *filp) + struct file *file) { - return xfs_release(XFS_I(inode)); + bool free_eof_blocks = true; + + if ((file->f_mode & (FMODE_WRITE | FMODE_READ)) == FMODE_READ) + free_eof_blocks = false; + + return xfs_release(XFS_I(inode), free_eof_blocks); } STATIC int diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index f0d63dab19e1..80f9fb2a7799 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1198,10 +1198,11 @@ out: int xfs_release( - xfs_inode_t *ip) + struct xfs_inode *ip, + bool want_free_eofblocks) { - xfs_mount_t *mp = ip->i_mount; - int error = 0; + struct xfs_mount *mp = ip->i_mount; + int error = 0; if (!S_ISREG(VFS_I(ip)->i_mode) || (VFS_I(ip)->i_mode == 0)) return 0; @@ -1243,7 +1244,7 @@ xfs_release( * another chance to drop them once the last reference to the inode is * dropped, so we'll never leak blocks permanently. */ - if (!xfs_ilock_nowait(ip, XFS_IOLOCK_EXCL)) + if (!want_free_eofblocks || !xfs_ilock_nowait(ip, XFS_IOLOCK_EXCL)) return 0; if (xfs_can_free_eofblocks(ip, false)) { diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 979699248635..3a1321b8f1c8 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -416,7 +416,7 @@ enum layout_break_reason { #define XFS_INHERIT_GID(pip) \ (xfs_has_grpid((pip)->i_mount) || (VFS_I(pip)->i_mode & S_ISGID)) -int xfs_release(struct xfs_inode *ip); +int xfs_release(struct xfs_inode *ip, bool can_free_eofblocks); void xfs_inactive(struct xfs_inode *ip); int xfs_lookup(struct xfs_inode *dp, struct xfs_name *name, struct xfs_inode **ipp, struct xfs_name *ci_name); |