aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorBrian Foster <bfoster@redhat.com>2013-03-18 10:51:46 -0400
committerBen Myers <bpm@sgi.com>2013-03-22 17:06:30 -0400
commitb136645116e5471cf0b037a1759dc83620236631 (patch)
tree9b9bfaa822d88585f4fa670a10b8f54a09584372 /fs/xfs
parent4b6eae2e6ac8a6671839ccaea1c2e3dd5684f5df (diff)
xfs: xfs_dquot prealloc throttling watermarks and low free space
Enable tracking of high and low watermarks for preallocation throttling of files under quota restrictions. These values are calculated when the quota limit is read from disk or modified and cached for later use by the throttling algorithm. The high watermark specifies when preallocation is disabled, the low watermark specifies when throttling is enabled and the low free space data structure contains precalculated low free space limits to serve as input to determine the level of throttling required. Note that the low free space data structure is based on the existing global low free space data structure with the exception of using three stages (5%, 3% and 1%) rather than five to reduce the impact of xfs_dquot memory overhead. Signed-off-by: Brian Foster <bfoster@redhat.com> Reviewed-by: Mark Tinguely <tinguely@sgi.com> Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_dquot.c41
-rw-r--r--fs/xfs/xfs_dquot.h12
-rw-r--r--fs/xfs/xfs_qm.h2
-rw-r--r--fs/xfs/xfs_qm_syscalls.c9
4 files changed, 57 insertions, 7 deletions
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
index 9c5869e60f97..45bb08f6ba17 100644
--- a/fs/xfs/xfs_dquot.c
+++ b/fs/xfs/xfs_dquot.c
@@ -90,13 +90,18 @@ xfs_qm_adjust_dqlimits(
90{ 90{
91 struct xfs_quotainfo *q = mp->m_quotainfo; 91 struct xfs_quotainfo *q = mp->m_quotainfo;
92 struct xfs_disk_dquot *d = &dq->q_core; 92 struct xfs_disk_dquot *d = &dq->q_core;
93 int prealloc = 0;
93 94
94 ASSERT(d->d_id); 95 ASSERT(d->d_id);
95 96
96 if (q->qi_bsoftlimit && !d->d_blk_softlimit) 97 if (q->qi_bsoftlimit && !d->d_blk_softlimit) {
97 d->d_blk_softlimit = cpu_to_be64(q->qi_bsoftlimit); 98 d->d_blk_softlimit = cpu_to_be64(q->qi_bsoftlimit);
98 if (q->qi_bhardlimit && !d->d_blk_hardlimit) 99 prealloc = 1;
100 }
101 if (q->qi_bhardlimit && !d->d_blk_hardlimit) {
99 d->d_blk_hardlimit = cpu_to_be64(q->qi_bhardlimit); 102 d->d_blk_hardlimit = cpu_to_be64(q->qi_bhardlimit);
103 prealloc = 1;
104 }
100 if (q->qi_isoftlimit && !d->d_ino_softlimit) 105 if (q->qi_isoftlimit && !d->d_ino_softlimit)
101 d->d_ino_softlimit = cpu_to_be64(q->qi_isoftlimit); 106 d->d_ino_softlimit = cpu_to_be64(q->qi_isoftlimit);
102 if (q->qi_ihardlimit && !d->d_ino_hardlimit) 107 if (q->qi_ihardlimit && !d->d_ino_hardlimit)
@@ -105,6 +110,9 @@ xfs_qm_adjust_dqlimits(
105 d->d_rtb_softlimit = cpu_to_be64(q->qi_rtbsoftlimit); 110 d->d_rtb_softlimit = cpu_to_be64(q->qi_rtbsoftlimit);
106 if (q->qi_rtbhardlimit && !d->d_rtb_hardlimit) 111 if (q->qi_rtbhardlimit && !d->d_rtb_hardlimit)
107 d->d_rtb_hardlimit = cpu_to_be64(q->qi_rtbhardlimit); 112 d->d_rtb_hardlimit = cpu_to_be64(q->qi_rtbhardlimit);
113
114 if (prealloc)
115 xfs_dquot_set_prealloc_limits(dq);
108} 116}
109 117
110/* 118/*
@@ -249,6 +257,32 @@ xfs_qm_init_dquot_blk(
249 xfs_trans_log_buf(tp, bp, 0, BBTOB(q->qi_dqchunklen) - 1); 257 xfs_trans_log_buf(tp, bp, 0, BBTOB(q->qi_dqchunklen) - 1);
250} 258}
251 259
260/*
261 * Initialize the dynamic speculative preallocation thresholds. The lo/hi
262 * watermarks correspond to the soft and hard limits by default. If a soft limit
263 * is not specified, we use 95% of the hard limit.
264 */
265void
266xfs_dquot_set_prealloc_limits(struct xfs_dquot *dqp)
267{
268 __uint64_t space;
269
270 dqp->q_prealloc_hi_wmark = be64_to_cpu(dqp->q_core.d_blk_hardlimit);
271 dqp->q_prealloc_lo_wmark = be64_to_cpu(dqp->q_core.d_blk_softlimit);
272 if (!dqp->q_prealloc_lo_wmark) {
273 dqp->q_prealloc_lo_wmark = dqp->q_prealloc_hi_wmark;
274 do_div(dqp->q_prealloc_lo_wmark, 100);
275 dqp->q_prealloc_lo_wmark *= 95;
276 }
277
278 space = dqp->q_prealloc_hi_wmark;
279
280 do_div(space, 100);
281 dqp->q_low_space[XFS_QLOWSP_1_PCNT] = space;
282 dqp->q_low_space[XFS_QLOWSP_3_PCNT] = space * 3;
283 dqp->q_low_space[XFS_QLOWSP_5_PCNT] = space * 5;
284}
285
252static void 286static void
253xfs_dquot_buf_verify( 287xfs_dquot_buf_verify(
254 struct xfs_buf *bp) 288 struct xfs_buf *bp)
@@ -649,6 +683,9 @@ xfs_qm_dqread(
649 dqp->q_res_icount = be64_to_cpu(ddqp->d_icount); 683 dqp->q_res_icount = be64_to_cpu(ddqp->d_icount);
650 dqp->q_res_rtbcount = be64_to_cpu(ddqp->d_rtbcount); 684 dqp->q_res_rtbcount = be64_to_cpu(ddqp->d_rtbcount);
651 685
686 /* initialize the dquot speculative prealloc thresholds */
687 xfs_dquot_set_prealloc_limits(dqp);
688
652 /* Mark the buf so that this will stay incore a little longer */ 689 /* Mark the buf so that this will stay incore a little longer */
653 xfs_buf_set_ref(bp, XFS_DQUOT_REF); 690 xfs_buf_set_ref(bp, XFS_DQUOT_REF);
654 691
diff --git a/fs/xfs/xfs_dquot.h b/fs/xfs/xfs_dquot.h
index f77b711455b1..4f0ebfc43cc9 100644
--- a/fs/xfs/xfs_dquot.h
+++ b/fs/xfs/xfs_dquot.h
@@ -32,6 +32,13 @@
32struct xfs_mount; 32struct xfs_mount;
33struct xfs_trans; 33struct xfs_trans;
34 34
35enum {
36 XFS_QLOWSP_1_PCNT = 0,
37 XFS_QLOWSP_3_PCNT,
38 XFS_QLOWSP_5_PCNT,
39 XFS_QLOWSP_MAX
40};
41
35/* 42/*
36 * The incore dquot structure 43 * The incore dquot structure
37 */ 44 */
@@ -51,6 +58,9 @@ typedef struct xfs_dquot {
51 xfs_qcnt_t q_res_bcount; /* total regular nblks used+reserved */ 58 xfs_qcnt_t q_res_bcount; /* total regular nblks used+reserved */
52 xfs_qcnt_t q_res_icount; /* total inos allocd+reserved */ 59 xfs_qcnt_t q_res_icount; /* total inos allocd+reserved */
53 xfs_qcnt_t q_res_rtbcount;/* total realtime blks used+reserved */ 60 xfs_qcnt_t q_res_rtbcount;/* total realtime blks used+reserved */
61 xfs_qcnt_t q_prealloc_lo_wmark;/* prealloc throttle wmark */
62 xfs_qcnt_t q_prealloc_hi_wmark;/* prealloc disabled wmark */
63 int64_t q_low_space[XFS_QLOWSP_MAX];
54 struct mutex q_qlock; /* quota lock */ 64 struct mutex q_qlock; /* quota lock */
55 struct completion q_flush; /* flush completion queue */ 65 struct completion q_flush; /* flush completion queue */
56 atomic_t q_pincount; /* dquot pin count */ 66 atomic_t q_pincount; /* dquot pin count */
@@ -153,6 +163,8 @@ extern void xfs_qm_dqput(xfs_dquot_t *);
153 163
154extern void xfs_dqlock2(struct xfs_dquot *, struct xfs_dquot *); 164extern void xfs_dqlock2(struct xfs_dquot *, struct xfs_dquot *);
155 165
166extern void xfs_dquot_set_prealloc_limits(struct xfs_dquot *);
167
156static inline struct xfs_dquot *xfs_qm_dqhold(struct xfs_dquot *dqp) 168static inline struct xfs_dquot *xfs_qm_dqhold(struct xfs_dquot *dqp)
157{ 169{
158 xfs_dqlock(dqp); 170 xfs_dqlock(dqp);
diff --git a/fs/xfs/xfs_qm.h b/fs/xfs/xfs_qm.h
index 44b858b79d71..82c21084587b 100644
--- a/fs/xfs/xfs_qm.h
+++ b/fs/xfs/xfs_qm.h
@@ -116,7 +116,7 @@ extern void xfs_qm_dqrele_all_inodes(xfs_mount_t *, uint);
116extern int xfs_qm_scall_trunc_qfiles(xfs_mount_t *, uint); 116extern int xfs_qm_scall_trunc_qfiles(xfs_mount_t *, uint);
117extern int xfs_qm_scall_getquota(xfs_mount_t *, xfs_dqid_t, uint, 117extern int xfs_qm_scall_getquota(xfs_mount_t *, xfs_dqid_t, uint,
118 fs_disk_quota_t *); 118 fs_disk_quota_t *);
119extern int xfs_qm_scall_setqlim(xfs_mount_t *, xfs_dqid_t, uint, 119extern int xfs_qm_scall_setqlim(struct xfs_mount *, xfs_dqid_t, uint,
120 fs_disk_quota_t *); 120 fs_disk_quota_t *);
121extern int xfs_qm_scall_getqstat(xfs_mount_t *, fs_quota_stat_t *); 121extern int xfs_qm_scall_getqstat(xfs_mount_t *, fs_quota_stat_t *);
122extern int xfs_qm_scall_quotaon(xfs_mount_t *, uint); 122extern int xfs_qm_scall_quotaon(xfs_mount_t *, uint);
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
index cf9a34051e07..c41190cad6e9 100644
--- a/fs/xfs/xfs_qm_syscalls.c
+++ b/fs/xfs/xfs_qm_syscalls.c
@@ -472,15 +472,15 @@ xfs_qm_scall_getqstat(
472 */ 472 */
473int 473int
474xfs_qm_scall_setqlim( 474xfs_qm_scall_setqlim(
475 xfs_mount_t *mp, 475 struct xfs_mount *mp,
476 xfs_dqid_t id, 476 xfs_dqid_t id,
477 uint type, 477 uint type,
478 fs_disk_quota_t *newlim) 478 fs_disk_quota_t *newlim)
479{ 479{
480 struct xfs_quotainfo *q = mp->m_quotainfo; 480 struct xfs_quotainfo *q = mp->m_quotainfo;
481 xfs_disk_dquot_t *ddq; 481 struct xfs_disk_dquot *ddq;
482 xfs_dquot_t *dqp; 482 struct xfs_dquot *dqp;
483 xfs_trans_t *tp; 483 struct xfs_trans *tp;
484 int error; 484 int error;
485 xfs_qcnt_t hard, soft; 485 xfs_qcnt_t hard, soft;
486 486
@@ -529,6 +529,7 @@ xfs_qm_scall_setqlim(
529 if (hard == 0 || hard >= soft) { 529 if (hard == 0 || hard >= soft) {
530 ddq->d_blk_hardlimit = cpu_to_be64(hard); 530 ddq->d_blk_hardlimit = cpu_to_be64(hard);
531 ddq->d_blk_softlimit = cpu_to_be64(soft); 531 ddq->d_blk_softlimit = cpu_to_be64(soft);
532 xfs_dquot_set_prealloc_limits(dqp);
532 if (id == 0) { 533 if (id == 0) {
533 q->qi_bhardlimit = hard; 534 q->qi_bhardlimit = hard;
534 q->qi_bsoftlimit = soft; 535 q->qi_bsoftlimit = soft;