summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/xfs_file.c14
-rw-r--r--fs/xfs/xfs_inode.c9
-rw-r--r--fs/xfs/xfs_inode.h2
3 files changed, 18 insertions, 7 deletions
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index f251965e8781..95d0e5d40100 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 81e611488bfe..077acfaf8e1d 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1192,10 +1192,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;
@@ -1237,7 +1238,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 186d20fb5747..8dac6fd2760a 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -415,7 +415,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);