summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2019-08-30 15:45:08 -0700
committerDarrick J. Wong <darrick.wong@oracle.com>2019-10-09 09:39:23 -0700
commit3cb42a52ee325fdc86c9fbacd48559f4ae5f5cf5 (patch)
treea269762f9600eaa9e051076795cb57293e9fe0ef
parentc1b09a5ec47bc2759be2d43537ec1c190fb3c874 (diff)
xfs: track unlinked inactive inode quota counters
Set up quota counters to track the number of inodes and blocks that will be freed from inactivating unlinked inodes. We'll use this in the deferred inactivation patch to hide the effects of deferred processing. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
-rw-r--r--fs/xfs/xfs_dquot.c45
-rw-r--r--fs/xfs/xfs_dquot.h4
-rw-r--r--fs/xfs/xfs_inode.c4
-rw-r--r--fs/xfs/xfs_qm.c13
-rw-r--r--fs/xfs/xfs_qm_syscalls.c7
-rw-r--r--fs/xfs/xfs_quota.h4
-rw-r--r--fs/xfs/xfs_trace.h1
7 files changed, 74 insertions, 4 deletions
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
index aeb95e7391c1..8d655e9b75ed 100644
--- a/fs/xfs/xfs_dquot.c
+++ b/fs/xfs/xfs_dquot.c
@@ -1267,3 +1267,48 @@ xfs_qm_dqiterate(
return error;
}
+
+/* Update dquot pending-inactivation counters. */
+STATIC void
+xfs_dquot_adjust(
+ struct xfs_dquot *dqp,
+ int direction,
+ int64_t inodes,
+ int64_t dblocks,
+ int64_t rblocks)
+{
+ xfs_dqlock(dqp);
+ dqp->q_ina_total += direction;
+ dqp->q_ina_icount += inodes;
+ dqp->q_ina_bcount += dblocks;
+ dqp->q_ina_rtbcount += rblocks;
+ xfs_dqunlock(dqp);
+}
+
+/* Update pending-inactivation counters for all dquots attach to inode. */
+void
+xfs_qm_iadjust(
+ struct xfs_inode *ip,
+ int direction,
+ int64_t inodes,
+ int64_t dblocks,
+ int64_t rblocks)
+{
+ struct xfs_mount *mp = ip->i_mount;
+
+ if (!XFS_IS_QUOTA_RUNNING(mp) || !XFS_IS_QUOTA_ON(mp) ||
+ xfs_is_quota_inode(&mp->m_sb, ip->i_ino))
+ return;
+
+ if (XFS_IS_UQUOTA_ON(mp) && ip->i_udquot)
+ xfs_dquot_adjust(ip->i_udquot, direction, inodes, dblocks,
+ rblocks);
+
+ if (XFS_IS_GQUOTA_ON(mp) && ip->i_gdquot)
+ xfs_dquot_adjust(ip->i_gdquot, direction, inodes, dblocks,
+ rblocks);
+
+ if (XFS_IS_PQUOTA_ON(mp) && ip->i_pdquot)
+ xfs_dquot_adjust(ip->i_pdquot, direction, inodes, dblocks,
+ rblocks);
+}
diff --git a/fs/xfs/xfs_dquot.h b/fs/xfs/xfs_dquot.h
index 4fe85709d55d..3401c4ad9f12 100644
--- a/fs/xfs/xfs_dquot.h
+++ b/fs/xfs/xfs_dquot.h
@@ -44,6 +44,10 @@ typedef struct xfs_dquot {
xfs_qcnt_t q_res_bcount; /* total regular nblks used+reserved */
xfs_qcnt_t q_res_icount; /* total inos allocd+reserved */
xfs_qcnt_t q_res_rtbcount;/* total realtime blks used+reserved */
+ uint64_t q_ina_total; /* inactive inodes attached here */
+ xfs_qcnt_t q_ina_bcount; /* inactive regular nblks used+reserved */
+ xfs_qcnt_t q_ina_icount; /* inactive inos allocd+reserved */
+ xfs_qcnt_t q_ina_rtbcount;/* inactive realtime blks used+reserved */
xfs_qcnt_t q_prealloc_lo_wmark;/* prealloc throttle wmark */
xfs_qcnt_t q_prealloc_hi_wmark;/* prealloc disabled wmark */
int64_t q_low_space[XFS_QLOWSP_MAX];
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index f7b7115b9de5..8587bfb5a51b 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -35,6 +35,8 @@
#include "xfs_log.h"
#include "xfs_bmap_btree.h"
#include "xfs_reflink.h"
+#include "xfs_dquot_item.h"
+#include "xfs_dquot.h"
kmem_zone_t *xfs_inode_zone;
@@ -1849,6 +1851,8 @@ xfs_inode_iadjust(
percpu_counter_add(&mp->m_iinactive, inodes);
percpu_counter_add(&mp->m_dinactive, dblocks);
percpu_counter_add(&mp->m_rinactive, rblocks);
+
+ xfs_qm_iadjust(ip, direction, inodes, dblocks, rblocks);
}
/*
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index ecd8ce152ab1..ada1889acb9f 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -423,6 +423,19 @@ xfs_qm_dquot_isolate(
goto out_miss_busy;
/*
+ * An inode is on the inactive list waiting to release its resources,
+ * so remove this dquot from the freelist and try again. We detached
+ * the dquot from the NEEDS_INACTIVE inode so that quotaoff won't
+ * deadlock on inactive inodes holding dquots.
+ */
+ if (dqp->q_ina_total > 0) {
+ xfs_dqunlock(dqp);
+ trace_xfs_dqreclaim_inactive(dqp);
+ list_lru_isolate(lru, &dqp->q_lru);
+ return LRU_REMOVED;
+ }
+
+ /*
* This dquot has acquired a reference in the meantime remove it from
* the freelist and try again.
*/
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
index fcdcb029da4f..072595ab512f 100644
--- a/fs/xfs/xfs_qm_syscalls.c
+++ b/fs/xfs/xfs_qm_syscalls.c
@@ -621,8 +621,8 @@ xfs_qm_scall_getquota_fill_qc(
XFS_FSB_TO_B(mp, be64_to_cpu(dqp->q_core.d_blk_softlimit));
dst->d_ino_hardlimit = be64_to_cpu(dqp->q_core.d_ino_hardlimit);
dst->d_ino_softlimit = be64_to_cpu(dqp->q_core.d_ino_softlimit);
- dst->d_space = XFS_FSB_TO_B(mp, dqp->q_res_bcount);
- dst->d_ino_count = dqp->q_res_icount;
+ dst->d_space = XFS_FSB_TO_B(mp, dqp->q_res_bcount - dqp->q_ina_bcount);
+ dst->d_ino_count = dqp->q_res_icount - dqp->q_ina_icount;
dst->d_spc_timer = be32_to_cpu(dqp->q_core.d_btimer);
dst->d_ino_timer = be32_to_cpu(dqp->q_core.d_itimer);
dst->d_ino_warns = be16_to_cpu(dqp->q_core.d_iwarns);
@@ -631,7 +631,8 @@ xfs_qm_scall_getquota_fill_qc(
XFS_FSB_TO_B(mp, be64_to_cpu(dqp->q_core.d_rtb_hardlimit));
dst->d_rt_spc_softlimit =
XFS_FSB_TO_B(mp, be64_to_cpu(dqp->q_core.d_rtb_softlimit));
- dst->d_rt_space = XFS_FSB_TO_B(mp, dqp->q_res_rtbcount);
+ dst->d_rt_space =
+ XFS_FSB_TO_B(mp, dqp->q_res_rtbcount - dqp->q_ina_rtbcount);
dst->d_rt_spc_timer = be32_to_cpu(dqp->q_core.d_rtbtimer);
dst->d_rt_spc_warns = be16_to_cpu(dqp->q_core.d_rtbwarns);
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
index efe42ae7a2f3..c354f01dae7b 100644
--- a/fs/xfs/xfs_quota.h
+++ b/fs/xfs/xfs_quota.h
@@ -106,7 +106,8 @@ extern int xfs_qm_newmount(struct xfs_mount *, uint *, uint *);
extern void xfs_qm_mount_quotas(struct xfs_mount *);
extern void xfs_qm_unmount(struct xfs_mount *);
extern void xfs_qm_unmount_quotas(struct xfs_mount *);
-
+extern void xfs_qm_iadjust(struct xfs_inode *ip, int direction, int64_t inodes,
+ int64_t dblocks, int64_t rblocks);
#else
static inline int
xfs_qm_vop_dqalloc(struct xfs_inode *ip, xfs_dqid_t uid, xfs_dqid_t gid,
@@ -148,6 +149,7 @@ static inline int xfs_trans_reserve_quota_bydquots(struct xfs_trans *tp,
#define xfs_qm_mount_quotas(mp)
#define xfs_qm_unmount(mp)
#define xfs_qm_unmount_quotas(mp)
+#define xfs_qm_iadjust(ip, dir, inodes, dblocks, rblocks)
#endif /* CONFIG_XFS_QUOTA */
#define xfs_trans_unreserve_quota_nblks(tp, ip, nblks, ninos, flags) \
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
index 096fd8618f32..45ca7cbfe0c1 100644
--- a/fs/xfs/xfs_trace.h
+++ b/fs/xfs/xfs_trace.h
@@ -908,6 +908,7 @@ DEFINE_EVENT(xfs_dquot_class, name, \
TP_PROTO(struct xfs_dquot *dqp), \
TP_ARGS(dqp))
DEFINE_DQUOT_EVENT(xfs_dqadjust);
+DEFINE_DQUOT_EVENT(xfs_dqreclaim_inactive);
DEFINE_DQUOT_EVENT(xfs_dqreclaim_want);
DEFINE_DQUOT_EVENT(xfs_dqreclaim_dirty);
DEFINE_DQUOT_EVENT(xfs_dqreclaim_busy);