@@ -1367,12 +1367,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
@@ -1137,10 +1137,11 @@ xfs_itruncate_extents_flags(
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;
@@ -1182,7 +1183,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)) {
@@ -525,7 +525,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 want_free_eofblocks);
int xfs_inactive(struct xfs_inode *ip);
int xfs_lookup(struct xfs_inode *dp, const struct xfs_name *name,
struct xfs_inode **ipp, struct xfs_name *ci_name);