提交 a636b1d1 编写于 作者: D Darrick J. Wong

xfs: trigger all block gc scans when low on quota space

The functions to run an eof/cowblocks scan to try to reduce quota usage
are kind of a mess -- the logic repeatedly initializes an eofb structure
and there are logic bugs in the code that result in the cowblocks scan
never actually happening.

Replace all three functions with a single function that fills out an
eofb and runs both eof and cowblocks scans.
Signed-off-by: NDarrick J. Wong <djwong@kernel.org>
Reviewed-by: NChristoph Hellwig <hch@lst.de>
Reviewed-by: NBrian Foster <bfoster@redhat.com>
上级 2a4bdfa8
...@@ -672,7 +672,7 @@ xfs_file_buffered_aio_write( ...@@ -672,7 +672,7 @@ xfs_file_buffered_aio_write(
struct inode *inode = mapping->host; struct inode *inode = mapping->host;
struct xfs_inode *ip = XFS_I(inode); struct xfs_inode *ip = XFS_I(inode);
ssize_t ret; ssize_t ret;
int enospc = 0; bool cleared_space = false;
int iolock; int iolock;
if (iocb->ki_flags & IOCB_NOWAIT) if (iocb->ki_flags & IOCB_NOWAIT)
...@@ -704,19 +704,16 @@ xfs_file_buffered_aio_write( ...@@ -704,19 +704,16 @@ xfs_file_buffered_aio_write(
* also behaves as a filter to prevent too many eofblocks scans from * also behaves as a filter to prevent too many eofblocks scans from
* running at the same time. * running at the same time.
*/ */
if (ret == -EDQUOT && !enospc) { if (ret == -EDQUOT && !cleared_space) {
xfs_iunlock(ip, iolock); xfs_iunlock(ip, iolock);
enospc = xfs_inode_free_quota_eofblocks(ip); cleared_space = xfs_inode_free_quota_blocks(ip);
if (enospc) if (cleared_space)
goto write_retry;
enospc = xfs_inode_free_quota_cowblocks(ip);
if (enospc)
goto write_retry; goto write_retry;
iolock = 0; iolock = 0;
} else if (ret == -ENOSPC && !enospc) { } else if (ret == -ENOSPC && !cleared_space) {
struct xfs_eofblocks eofb = {0}; struct xfs_eofblocks eofb = {0};
enospc = 1; cleared_space = true;
xfs_flush_inodes(ip->i_mount); xfs_flush_inodes(ip->i_mount);
xfs_iunlock(ip, iolock); xfs_iunlock(ip, iolock);
......
...@@ -1397,33 +1397,31 @@ xfs_icache_free_eofblocks( ...@@ -1397,33 +1397,31 @@ xfs_icache_free_eofblocks(
} }
/* /*
* Run eofblocks scans on the quotas applicable to the inode. For inodes with * Run cow/eofblocks scans on the quotas applicable to the inode. For inodes
* multiple quotas, we don't know exactly which quota caused an allocation * with multiple quotas, we don't know exactly which quota caused an allocation
* failure. We make a best effort by including each quota under low free space * failure. We make a best effort by including each quota under low free space
* conditions (less than 1% free space) in the scan. * conditions (less than 1% free space) in the scan.
*/ */
static int bool
__xfs_inode_free_quota_eofblocks( xfs_inode_free_quota_blocks(
struct xfs_inode *ip, struct xfs_inode *ip)
int (*execute)(struct xfs_mount *mp,
struct xfs_eofblocks *eofb))
{ {
int scan = 0;
struct xfs_eofblocks eofb = {0}; struct xfs_eofblocks eofb = {0};
struct xfs_dquot *dq; struct xfs_dquot *dq;
bool do_work = false;
/* /*
* Run a sync scan to increase effectiveness and use the union filter to * Run a sync scan to increase effectiveness and use the union filter to
* cover all applicable quotas in a single scan. * cover all applicable quotas in a single scan.
*/ */
eofb.eof_flags = XFS_EOF_FLAGS_UNION|XFS_EOF_FLAGS_SYNC; eofb.eof_flags = XFS_EOF_FLAGS_UNION | XFS_EOF_FLAGS_SYNC;
if (XFS_IS_UQUOTA_ENFORCED(ip->i_mount)) { if (XFS_IS_UQUOTA_ENFORCED(ip->i_mount)) {
dq = xfs_inode_dquot(ip, XFS_DQTYPE_USER); dq = xfs_inode_dquot(ip, XFS_DQTYPE_USER);
if (dq && xfs_dquot_lowsp(dq)) { if (dq && xfs_dquot_lowsp(dq)) {
eofb.eof_uid = VFS_I(ip)->i_uid; eofb.eof_uid = VFS_I(ip)->i_uid;
eofb.eof_flags |= XFS_EOF_FLAGS_UID; eofb.eof_flags |= XFS_EOF_FLAGS_UID;
scan = 1; do_work = true;
} }
} }
...@@ -1432,21 +1430,16 @@ __xfs_inode_free_quota_eofblocks( ...@@ -1432,21 +1430,16 @@ __xfs_inode_free_quota_eofblocks(
if (dq && xfs_dquot_lowsp(dq)) { if (dq && xfs_dquot_lowsp(dq)) {
eofb.eof_gid = VFS_I(ip)->i_gid; eofb.eof_gid = VFS_I(ip)->i_gid;
eofb.eof_flags |= XFS_EOF_FLAGS_GID; eofb.eof_flags |= XFS_EOF_FLAGS_GID;
scan = 1; do_work = true;
} }
} }
if (scan) if (!do_work)
execute(ip->i_mount, &eofb); return false;
return scan;
}
int xfs_icache_free_eofblocks(ip->i_mount, &eofb);
xfs_inode_free_quota_eofblocks( xfs_icache_free_cowblocks(ip->i_mount, &eofb);
struct xfs_inode *ip) return true;
{
return __xfs_inode_free_quota_eofblocks(ip, xfs_icache_free_eofblocks);
} }
static inline unsigned long static inline unsigned long
...@@ -1646,13 +1639,6 @@ xfs_icache_free_cowblocks( ...@@ -1646,13 +1639,6 @@ xfs_icache_free_cowblocks(
XFS_ICI_COWBLOCKS_TAG); XFS_ICI_COWBLOCKS_TAG);
} }
int
xfs_inode_free_quota_cowblocks(
struct xfs_inode *ip)
{
return __xfs_inode_free_quota_eofblocks(ip, xfs_icache_free_cowblocks);
}
void void
xfs_inode_set_cowblocks_tag( xfs_inode_set_cowblocks_tag(
xfs_inode_t *ip) xfs_inode_t *ip)
......
...@@ -54,17 +54,17 @@ long xfs_reclaim_inodes_nr(struct xfs_mount *mp, int nr_to_scan); ...@@ -54,17 +54,17 @@ long xfs_reclaim_inodes_nr(struct xfs_mount *mp, int nr_to_scan);
void xfs_inode_set_reclaim_tag(struct xfs_inode *ip); void xfs_inode_set_reclaim_tag(struct xfs_inode *ip);
bool xfs_inode_free_quota_blocks(struct xfs_inode *ip);
void xfs_inode_set_eofblocks_tag(struct xfs_inode *ip); void xfs_inode_set_eofblocks_tag(struct xfs_inode *ip);
void xfs_inode_clear_eofblocks_tag(struct xfs_inode *ip); void xfs_inode_clear_eofblocks_tag(struct xfs_inode *ip);
int xfs_icache_free_eofblocks(struct xfs_mount *, struct xfs_eofblocks *); int xfs_icache_free_eofblocks(struct xfs_mount *, struct xfs_eofblocks *);
int xfs_inode_free_quota_eofblocks(struct xfs_inode *ip);
void xfs_eofblocks_worker(struct work_struct *); void xfs_eofblocks_worker(struct work_struct *);
void xfs_queue_eofblocks(struct xfs_mount *); void xfs_queue_eofblocks(struct xfs_mount *);
void xfs_inode_set_cowblocks_tag(struct xfs_inode *ip); void xfs_inode_set_cowblocks_tag(struct xfs_inode *ip);
void xfs_inode_clear_cowblocks_tag(struct xfs_inode *ip); void xfs_inode_clear_cowblocks_tag(struct xfs_inode *ip);
int xfs_icache_free_cowblocks(struct xfs_mount *, struct xfs_eofblocks *); int xfs_icache_free_cowblocks(struct xfs_mount *, struct xfs_eofblocks *);
int xfs_inode_free_quota_cowblocks(struct xfs_inode *ip);
void xfs_cowblocks_worker(struct work_struct *); void xfs_cowblocks_worker(struct work_struct *);
void xfs_queue_cowblocks(struct xfs_mount *); void xfs_queue_cowblocks(struct xfs_mount *);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册