All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/7] speculative preallocation quota throttling
@ 2013-02-19 16:37 Brian Foster
  2013-02-19 16:37 ` [PATCH v3 1/7] xfs: reorganize xfs_iomap_prealloc_size to remove indentation Brian Foster
                   ` (6 more replies)
  0 siblings, 7 replies; 14+ messages in thread
From: Brian Foster @ 2013-02-19 16:37 UTC (permalink / raw)
  To: xfs

Hi all,

This v3 speculative prealloc quota throttling set is a simple rebase of v2 on
top of the recent speculative prealloc algorithm update to support sparse files.
I carried over the reviewed-by tags from patches 1-2, as I didn't fundamentally
change that code. Those are the patches slightly affected by the rebase, however,
so a second look at those might be prudent.

I've run a 1TB limit uquota sanity check to verify behavior as described in v2.
The numbers change slightly due to the slightly altered behavior of the new
prealloc algorithm (e.g., switching from using the size of the previous extent to
the size of the file causes maximum extent allocations to kick in a bit later),
but otherwise the general behavior is the same. I'll run some tests with larger
files in parallel with review as well.

[Note that these tests also include the currently posted "xfs: increase prealloc
size to double ..." change to restore effectiveness of the prealloc algorithm
to my particular test case.]

Brian

v3:
- Rebased on top of updated speculative preallocation algorithm.
v2:
- Fix up xfs_iomap_prealloc_size() rounding (patch 2).
- Add pre-calculated fields to xfs_dquot to support throttling.
- Move to logarithmic (shift) throttler and finer tuned trigger/throttle logic.

Brian Foster (7):
  xfs: reorganize xfs_iomap_prealloc_size to remove indentation
  xfs: push rounddown_pow_of_two() to after prealloc throttle
  xfs: cap prealloc size to free space before shift
  xfs: pass xfs_dquot to xfs_qm_adjust_dqlimits() instead of
    xfs_disk_dquot_t
  xfs: xfs_dquot prealloc throttling watermarks and low free space
  xfs: add quota-driven speculative preallocation throttling
  xfs: xfs_iomap_prealloc_size() tracepoint

 fs/xfs/xfs_dquot.c       |   46 ++++++++++++-
 fs/xfs/xfs_dquot.h       |   15 ++++-
 fs/xfs/xfs_iomap.c       |  163 +++++++++++++++++++++++++++++++++++++---------
 fs/xfs/xfs_qm.c          |    2 +-
 fs/xfs/xfs_qm_syscalls.c |    1 +
 fs/xfs/xfs_trace.h       |   24 +++++++
 fs/xfs/xfs_trans_dquot.c |    2 +-
 7 files changed, 217 insertions(+), 36 deletions(-)

-- 
1.7.7.6

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v3 1/7] xfs: reorganize xfs_iomap_prealloc_size to remove indentation
  2013-02-19 16:37 [PATCH v3 0/7] speculative preallocation quota throttling Brian Foster
@ 2013-02-19 16:37 ` Brian Foster
  2013-02-19 16:37 ` [PATCH v3 2/7] xfs: push rounddown_pow_of_two() to after prealloc throttle Brian Foster
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 14+ messages in thread
From: Brian Foster @ 2013-02-19 16:37 UTC (permalink / raw)
  To: xfs

The majority of xfs_iomap_prealloc_size() executes within the
check for lack of default I/O size. Reverse the logic to remove the
extra indentation.

Signed-off-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Ben Myers <bpm@sgi.com>
---
 fs/xfs/xfs_iomap.c |   63 ++++++++++++++++++++++++++-------------------------
 1 files changed, 32 insertions(+), 31 deletions(-)

diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 912d83d..d914419 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -381,42 +381,43 @@ xfs_iomap_prealloc_size(
 	int			nimaps)
 {
 	xfs_fsblock_t		alloc_blocks = 0;
+	int			shift = 0;
+	int64_t			freesp;
 
 	alloc_blocks = xfs_iomap_eof_prealloc_initial_size(mp, ip, offset,
 							   imap, nimaps);
-	if (alloc_blocks > 0) {
-		int shift = 0;
-		int64_t freesp;
-
-		alloc_blocks = XFS_FILEOFF_MIN(MAXEXTLEN,
-					rounddown_pow_of_two(alloc_blocks));
-
-		xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT);
-		freesp = mp->m_sb.sb_fdblocks;
-		if (freesp < mp->m_low_space[XFS_LOWSP_5_PCNT]) {
-			shift = 2;
-			if (freesp < mp->m_low_space[XFS_LOWSP_4_PCNT])
-				shift++;
-			if (freesp < mp->m_low_space[XFS_LOWSP_3_PCNT])
-				shift++;
-			if (freesp < mp->m_low_space[XFS_LOWSP_2_PCNT])
-				shift++;
-			if (freesp < mp->m_low_space[XFS_LOWSP_1_PCNT])
-				shift++;
-		}
-		if (shift)
-			alloc_blocks >>= shift;
-
-		/*
-		 * If we are still trying to allocate more space than is
-		 * available, squash the prealloc hard. This can happen if we
-		 * have a large file on a small filesystem and the above
-		 * lowspace thresholds are smaller than MAXEXTLEN.
-		 */
-		while (alloc_blocks >= freesp)
-			alloc_blocks >>= 4;
+	if (!alloc_blocks)
+		goto check_writeio;
+
+	alloc_blocks = XFS_FILEOFF_MIN(MAXEXTLEN,
+				rounddown_pow_of_two(alloc_blocks));
+
+	xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT);
+	freesp = mp->m_sb.sb_fdblocks;
+	if (freesp < mp->m_low_space[XFS_LOWSP_5_PCNT]) {
+		shift = 2;
+		if (freesp < mp->m_low_space[XFS_LOWSP_4_PCNT])
+			shift++;
+		if (freesp < mp->m_low_space[XFS_LOWSP_3_PCNT])
+			shift++;
+		if (freesp < mp->m_low_space[XFS_LOWSP_2_PCNT])
+			shift++;
+		if (freesp < mp->m_low_space[XFS_LOWSP_1_PCNT])
+			shift++;
 	}
+	if (shift)
+		alloc_blocks >>= shift;
+
+	/*
+	 * If we are still trying to allocate more space than is
+	 * available, squash the prealloc hard. This can happen if we
+	 * have a large file on a small filesystem and the above
+	 * lowspace thresholds are smaller than MAXEXTLEN.
+	 */
+	while (alloc_blocks >= freesp)
+		alloc_blocks >>= 4;
 
+check_writeio:
 	if (alloc_blocks < mp->m_writeio_blocks)
 		alloc_blocks = mp->m_writeio_blocks;
 
-- 
1.7.7.6

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v3 2/7] xfs: push rounddown_pow_of_two() to after prealloc throttle
  2013-02-19 16:37 [PATCH v3 0/7] speculative preallocation quota throttling Brian Foster
  2013-02-19 16:37 ` [PATCH v3 1/7] xfs: reorganize xfs_iomap_prealloc_size to remove indentation Brian Foster
@ 2013-02-19 16:37 ` Brian Foster
  2013-02-19 16:37 ` [PATCH v3 3/7] xfs: cap prealloc size to free space before shift Brian Foster
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 14+ messages in thread
From: Brian Foster @ 2013-02-19 16:37 UTC (permalink / raw)
  To: xfs

The round down occurs towards the beginning of the function. Push
it down after throttling has occurred. This is to support adding
further transformations to 'alloc_blocks' that might not preserve
power-of-two alignment (and thus could lead to rounding down
multiple times).

Signed-off-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Ben Myers <bpm@sgi.com>
---
 fs/xfs/xfs_iomap.c |   19 +++++++++++++++++--
 1 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index d914419..daa08f6 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -389,8 +389,15 @@ xfs_iomap_prealloc_size(
 	if (!alloc_blocks)
 		goto check_writeio;
 
-	alloc_blocks = XFS_FILEOFF_MIN(MAXEXTLEN,
-				rounddown_pow_of_two(alloc_blocks));
+	/*
+	 * MAXEXTLEN is not a power of two value but we round the prealloc down
+	 * to the nearest power of two value after throttling. To prevent the
+	 * round down from unconditionally reducing the maximum supported prealloc
+	 * size, we round up first, apply appropriate throttling, round down and
+	 * cap the value to MAXEXTLEN.
+	 */
+	alloc_blocks = XFS_FILEOFF_MIN(roundup_pow_of_two(MAXEXTLEN),
+				       alloc_blocks);
 
 	xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT);
 	freesp = mp->m_sb.sb_fdblocks;
@@ -407,6 +414,14 @@ xfs_iomap_prealloc_size(
 	}
 	if (shift)
 		alloc_blocks >>= shift;
+	/*
+	 * rounddown_pow_of_two() returns an undefined result if we pass in
+	 * alloc_blocks = 0.
+	 */
+	if (alloc_blocks)
+		alloc_blocks = rounddown_pow_of_two(alloc_blocks);
+	if (alloc_blocks > MAXEXTLEN)
+		alloc_blocks = MAXEXTLEN;
 
 	/*
 	 * If we are still trying to allocate more space than is
-- 
1.7.7.6

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v3 3/7] xfs: cap prealloc size to free space before shift
  2013-02-19 16:37 [PATCH v3 0/7] speculative preallocation quota throttling Brian Foster
  2013-02-19 16:37 ` [PATCH v3 1/7] xfs: reorganize xfs_iomap_prealloc_size to remove indentation Brian Foster
  2013-02-19 16:37 ` [PATCH v3 2/7] xfs: push rounddown_pow_of_two() to after prealloc throttle Brian Foster
@ 2013-02-19 16:37 ` Brian Foster
  2013-02-19 21:48   ` Dave Chinner
  2013-02-19 16:37 ` [PATCH v3 4/7] xfs: pass xfs_dquot to xfs_qm_adjust_dqlimits() instead of xfs_disk_dquot_t Brian Foster
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 14+ messages in thread
From: Brian Foster @ 2013-02-19 16:37 UTC (permalink / raw)
  To: xfs

With the addition of quota preallocation throttling, we want to
support a general algorithm that considers the maximum allowable
prealloc size and recommended shift modifier from various sources
(i.e., global fs state and all applicable quotas for an inode).

Update the current global free space throttle algorithm to cap the
preallocation size to the free space available in the filesystem.

Signed-off-by: Brian Foster <bfoster@redhat.com>
---
 fs/xfs/xfs_iomap.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index daa08f6..3b41c18 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -412,6 +412,9 @@ xfs_iomap_prealloc_size(
 		if (freesp < mp->m_low_space[XFS_LOWSP_1_PCNT])
 			shift++;
 	}
+	if (alloc_blocks > freesp)
+		alloc_blocks = freesp;
+
 	if (shift)
 		alloc_blocks >>= shift;
 	/*
-- 
1.7.7.6

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v3 4/7] xfs: pass xfs_dquot to xfs_qm_adjust_dqlimits() instead of xfs_disk_dquot_t
  2013-02-19 16:37 [PATCH v3 0/7] speculative preallocation quota throttling Brian Foster
                   ` (2 preceding siblings ...)
  2013-02-19 16:37 ` [PATCH v3 3/7] xfs: cap prealloc size to free space before shift Brian Foster
@ 2013-02-19 16:37 ` Brian Foster
  2013-02-19 16:37 ` [PATCH v3 5/7] xfs: xfs_dquot prealloc throttling watermarks and low free space Brian Foster
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 14+ messages in thread
From: Brian Foster @ 2013-02-19 16:37 UTC (permalink / raw)
  To: xfs

Modify xfs_qm_adjust_dqlimits() to take the xfs_dquot as a
parameter instead of just the xfs_disk_dquot_t so we can update
in-memory fields if necessary.

Signed-off-by: Brian Foster <bfoster@redhat.com>
---
 fs/xfs/xfs_dquot.c       |    3 ++-
 fs/xfs/xfs_dquot.h       |    2 +-
 fs/xfs/xfs_qm.c          |    2 +-
 fs/xfs/xfs_trans_dquot.c |    2 +-
 4 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
index 8025eb2..e1833b9 100644
--- a/fs/xfs/xfs_dquot.c
+++ b/fs/xfs/xfs_dquot.c
@@ -86,9 +86,10 @@ xfs_qm_dqdestroy(
 void
 xfs_qm_adjust_dqlimits(
 	xfs_mount_t		*mp,
-	xfs_disk_dquot_t	*d)
+	struct xfs_dquot	*dq)
 {
 	xfs_quotainfo_t		*q = mp->m_quotainfo;
+	xfs_disk_dquot_t	*d = &dq->q_core;
 
 	ASSERT(d->d_id);
 
diff --git a/fs/xfs/xfs_dquot.h b/fs/xfs/xfs_dquot.h
index c694a84..69491b6 100644
--- a/fs/xfs/xfs_dquot.h
+++ b/fs/xfs/xfs_dquot.h
@@ -146,7 +146,7 @@ extern void		xfs_qm_dqunpin_wait(xfs_dquot_t *);
 extern void		xfs_qm_adjust_dqtimers(xfs_mount_t *,
 					xfs_disk_dquot_t *);
 extern void		xfs_qm_adjust_dqlimits(xfs_mount_t *,
-					xfs_disk_dquot_t *);
+					       struct xfs_dquot *);
 extern int		xfs_qm_dqget(xfs_mount_t *, xfs_inode_t *,
 					xfs_dqid_t, uint, uint, xfs_dquot_t **);
 extern void		xfs_qm_dqput(xfs_dquot_t *);
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index e5b5cf9..d0acb4e 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -1057,7 +1057,7 @@ xfs_qm_quotacheck_dqadjust(
 	 * There are no timers for the default values set in the root dquot.
 	 */
 	if (dqp->q_core.d_id) {
-		xfs_qm_adjust_dqlimits(mp, &dqp->q_core);
+		xfs_qm_adjust_dqlimits(mp, dqp);
 		xfs_qm_adjust_dqtimers(mp, &dqp->q_core);
 	}
 
diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c
index 642c2d6..22d3da3 100644
--- a/fs/xfs/xfs_trans_dquot.c
+++ b/fs/xfs/xfs_trans_dquot.c
@@ -412,7 +412,7 @@ xfs_trans_apply_dquot_deltas(
 			 * Start/reset the timer(s) if needed.
 			 */
 			if (d->d_id) {
-				xfs_qm_adjust_dqlimits(tp->t_mountp, d);
+				xfs_qm_adjust_dqlimits(tp->t_mountp, dqp);
 				xfs_qm_adjust_dqtimers(tp->t_mountp, d);
 			}
 
-- 
1.7.7.6

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v3 5/7] xfs: xfs_dquot prealloc throttling watermarks and low free space
  2013-02-19 16:37 [PATCH v3 0/7] speculative preallocation quota throttling Brian Foster
                   ` (3 preceding siblings ...)
  2013-02-19 16:37 ` [PATCH v3 4/7] xfs: pass xfs_dquot to xfs_qm_adjust_dqlimits() instead of xfs_disk_dquot_t Brian Foster
@ 2013-02-19 16:37 ` Brian Foster
  2013-02-19 23:08   ` Dave Chinner
  2013-02-19 16:37 ` [PATCH v3 6/7] xfs: add quota-driven speculative preallocation throttling Brian Foster
  2013-02-19 16:37 ` [PATCH v3 7/7] xfs: xfs_iomap_prealloc_size() tracepoint Brian Foster
  6 siblings, 1 reply; 14+ messages in thread
From: Brian Foster @ 2013-02-19 16:37 UTC (permalink / raw)
  To: xfs

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>
---
 fs/xfs/xfs_dquot.c       |   43 +++++++++++++++++++++++++++++++++++++++++--
 fs/xfs/xfs_dquot.h       |   13 +++++++++++++
 fs/xfs/xfs_qm_syscalls.c |    1 +
 3 files changed, 55 insertions(+), 2 deletions(-)

diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
index e1833b9..bd25be3 100644
--- a/fs/xfs/xfs_dquot.c
+++ b/fs/xfs/xfs_dquot.c
@@ -90,13 +90,18 @@ xfs_qm_adjust_dqlimits(
 {
 	xfs_quotainfo_t		*q = mp->m_quotainfo;
 	xfs_disk_dquot_t	*d = &dq->q_core;
+	int			prealloc = 0;
 
 	ASSERT(d->d_id);
 
-	if (q->qi_bsoftlimit && !d->d_blk_softlimit)
+	if (q->qi_bsoftlimit && !d->d_blk_softlimit) {
 		d->d_blk_softlimit = cpu_to_be64(q->qi_bsoftlimit);
-	if (q->qi_bhardlimit && !d->d_blk_hardlimit)
+		prealloc = 1;
+	}
+	if (q->qi_bhardlimit && !d->d_blk_hardlimit) {
 		d->d_blk_hardlimit = cpu_to_be64(q->qi_bhardlimit);
+		prealloc = 1;
+	}
 	if (q->qi_isoftlimit && !d->d_ino_softlimit)
 		d->d_ino_softlimit = cpu_to_be64(q->qi_isoftlimit);
 	if (q->qi_ihardlimit && !d->d_ino_hardlimit)
@@ -105,6 +110,9 @@ xfs_qm_adjust_dqlimits(
 		d->d_rtb_softlimit = cpu_to_be64(q->qi_rtbsoftlimit);
 	if (q->qi_rtbhardlimit && !d->d_rtb_hardlimit)
 		d->d_rtb_hardlimit = cpu_to_be64(q->qi_rtbhardlimit);
+
+	if (prealloc)
+		xfs_dquot_init_prealloc(dq);
 }
 
 /*
@@ -249,6 +257,34 @@ xfs_qm_init_dquot_blk(
 	xfs_trans_log_buf(tp, bp, 0, BBTOB(q->qi_dqchunklen) - 1);
 }
 
+/*
+ * Initialize the preallocation throttling watermarks and low free space table.
+ * The lo/hi watermarks correspond to the soft and hard limits by default. If a
+ * soft limit is not specified, we use 95% of the hard limit.
+ */
+void
+xfs_dquot_init_prealloc(struct xfs_dquot *dqp)
+{
+	int i;
+	int pct = 1;
+
+	dqp->q_prealloc_hi_wmark = be64_to_cpu(dqp->q_core.d_blk_hardlimit);
+	dqp->q_prealloc_lo_wmark = be64_to_cpu(dqp->q_core.d_blk_softlimit);
+	if (!dqp->q_prealloc_lo_wmark) {
+		dqp->q_prealloc_lo_wmark = dqp->q_prealloc_hi_wmark;
+		do_div(dqp->q_prealloc_lo_wmark, 100);
+		dqp->q_prealloc_lo_wmark *= 95;
+	}
+
+	for (i = 0; i < XFS_QLOWSP_MAX; i++) {
+		__uint64_t space = dqp->q_prealloc_hi_wmark;
+
+		do_div(space, 100);
+		dqp->q_low_space[i] = space * pct;
+		pct += XFS_QLOWSP_PCNT_INCR;
+	}
+}
+
 static void
 xfs_dquot_buf_verify(
 	struct xfs_buf		*bp)
@@ -649,6 +685,9 @@ xfs_qm_dqread(
 	dqp->q_res_icount = be64_to_cpu(ddqp->d_icount);
 	dqp->q_res_rtbcount = be64_to_cpu(ddqp->d_rtbcount);
 
+	/* initialize dquot prealloc throttling watermarks */
+	xfs_dquot_init_prealloc(dqp);
+
 	/* Mark the buf so that this will stay incore a little longer */
 	xfs_buf_set_ref(bp, XFS_DQUOT_REF);
 
diff --git a/fs/xfs/xfs_dquot.h b/fs/xfs/xfs_dquot.h
index 69491b6..7b026fe 100644
--- a/fs/xfs/xfs_dquot.h
+++ b/fs/xfs/xfs_dquot.h
@@ -32,6 +32,14 @@
 struct xfs_mount;
 struct xfs_trans;
 
+enum {
+	XFS_QLOWSP_1_PCNT = 0,
+	XFS_QLOWSP_3_PCNT,
+	XFS_QLOWSP_5_PCNT,
+	XFS_QLOWSP_MAX
+};
+#define XFS_QLOWSP_PCNT_INCR 2
+
 /*
  * The incore dquot structure
  */
@@ -51,6 +59,9 @@ 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 */
+	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];
 	struct mutex	 q_qlock;	/* quota lock */
 	struct completion q_flush;	/* flush completion queue */
 	atomic_t          q_pincount;	/* dquot pin count */
@@ -153,6 +164,8 @@ extern void		xfs_qm_dqput(xfs_dquot_t *);
 
 extern void		xfs_dqlock2(struct xfs_dquot *, struct xfs_dquot *);
 
+extern void		xfs_dquot_init_prealloc(struct xfs_dquot *);
+
 static inline struct xfs_dquot *xfs_qm_dqhold(struct xfs_dquot *dqp)
 {
 	xfs_dqlock(dqp);
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
index cf9a340..098ca3c 100644
--- a/fs/xfs/xfs_qm_syscalls.c
+++ b/fs/xfs/xfs_qm_syscalls.c
@@ -529,6 +529,7 @@ xfs_qm_scall_setqlim(
 	if (hard == 0 || hard >= soft) {
 		ddq->d_blk_hardlimit = cpu_to_be64(hard);
 		ddq->d_blk_softlimit = cpu_to_be64(soft);
+		xfs_dquot_init_prealloc(dqp);
 		if (id == 0) {
 			q->qi_bhardlimit = hard;
 			q->qi_bsoftlimit = soft;
-- 
1.7.7.6

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v3 6/7] xfs: add quota-driven speculative preallocation throttling
  2013-02-19 16:37 [PATCH v3 0/7] speculative preallocation quota throttling Brian Foster
                   ` (4 preceding siblings ...)
  2013-02-19 16:37 ` [PATCH v3 5/7] xfs: xfs_dquot prealloc throttling watermarks and low free space Brian Foster
@ 2013-02-19 16:37 ` Brian Foster
  2013-02-19 16:37 ` [PATCH v3 7/7] xfs: xfs_iomap_prealloc_size() tracepoint Brian Foster
  6 siblings, 0 replies; 14+ messages in thread
From: Brian Foster @ 2013-02-19 16:37 UTC (permalink / raw)
  To: xfs

Introduce the need_throttle() and calc_throttle() functions to
independently check whether throttling is required for a particular
dquot and if so, calculate the associated throttling metrics based
on the state of the quota. We use the same general algorithm to
calculate the throttle shift as for global free space with the
exception of using three stages rather than five.

Update xfs_iomap_prealloc_size() to use the smallest available
prealloc size based on each of the constraints and apply the
maximum shift to obtain the throttled preallocation size.

Signed-off-by: Brian Foster <bfoster@redhat.com>
---
 fs/xfs/xfs_iomap.c |   81 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 81 insertions(+), 0 deletions(-)

diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 3b41c18..6355e80 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -42,6 +42,8 @@
 #include "xfs_iomap.h"
 #include "xfs_trace.h"
 #include "xfs_icache.h"
+#include "xfs_dquot_item.h"
+#include "xfs_dquot.h"
 
 
 #define XFS_WRITEIO_ALIGN(mp,off)	(((off) >> mp->m_writeio_log) \
@@ -366,6 +368,61 @@ xfs_iomap_eof_prealloc_initial_size(
 	return XFS_B_TO_FSB(mp, offset);
 }
 
+STATIC bool
+xfs_quota_need_throttle(
+	struct xfs_inode *ip,
+	int type,
+	xfs_fsblock_t alloc_blocks)
+{
+	struct xfs_dquot *dq = xfs_inode_dquot(ip, type);
+
+	if (!dq || !xfs_this_quota_on(ip->i_mount, type))
+		return false;
+
+	/* no hi watermark, no throttle */
+	if (!dq->q_prealloc_hi_wmark)
+		return false;
+
+	/* under the lo watermark, no throttle */
+	if (dq->q_res_bcount + alloc_blocks < dq->q_prealloc_lo_wmark)
+		return false;
+
+	return true;
+}
+
+STATIC void
+xfs_quota_calc_throttle(
+	struct xfs_inode *ip,
+	int type,
+	xfs_fsblock_t *qblocks,
+	int *qshift)
+{
+	int64_t freesp;
+	int shift = 0;
+	struct xfs_dquot *dq = xfs_inode_dquot(ip, type);
+
+	/* over hi wmark, squash the prealloc completely */
+	if (dq->q_res_bcount >= dq->q_prealloc_hi_wmark) {
+		*qblocks = 0;
+		return;
+	}
+
+	freesp = dq->q_prealloc_hi_wmark - dq->q_res_bcount;
+	if (freesp < dq->q_low_space[XFS_QLOWSP_5_PCNT]) {
+		shift = 2;
+		if (freesp < dq->q_low_space[XFS_QLOWSP_3_PCNT])
+			shift += 2;
+		if (freesp < dq->q_low_space[XFS_QLOWSP_1_PCNT])
+			shift += 2;
+	}
+
+	/* only overwrite the throttle values if we are more aggressive */
+	if ((freesp >> shift) < (*qblocks >> *qshift)) {
+		*qblocks = freesp;
+		*qshift = shift;
+	}
+}
+
 /*
  * If we don't have a user specified preallocation size, dynamically increase
  * the preallocation size as the size of the file grows. Cap the maximum size
@@ -383,11 +440,14 @@ xfs_iomap_prealloc_size(
 	xfs_fsblock_t		alloc_blocks = 0;
 	int			shift = 0;
 	int64_t			freesp;
+	xfs_fsblock_t		qblocks;
+	int			qshift = 0;
 
 	alloc_blocks = xfs_iomap_eof_prealloc_initial_size(mp, ip, offset,
 							   imap, nimaps);
 	if (!alloc_blocks)
 		goto check_writeio;
+	qblocks = alloc_blocks;
 
 	/*
 	 * MAXEXTLEN is not a power of two value but we round the prealloc down
@@ -415,6 +475,27 @@ xfs_iomap_prealloc_size(
 	if (alloc_blocks > freesp)
 		alloc_blocks = freesp;
 
+	/*
+	 * Check each quota to cap the prealloc size and provide a shift
+	 * value to throttle with.
+	 */
+	if (xfs_quota_need_throttle(ip, XFS_DQ_USER, alloc_blocks))
+		xfs_quota_calc_throttle(ip, XFS_DQ_USER, &qblocks, &qshift);
+	if (xfs_quota_need_throttle(ip, XFS_DQ_GROUP, alloc_blocks))
+		xfs_quota_calc_throttle(ip, XFS_DQ_GROUP, &qblocks, &qshift);
+	if (xfs_quota_need_throttle(ip, XFS_DQ_PROJ, alloc_blocks))
+		xfs_quota_calc_throttle(ip, XFS_DQ_PROJ, &qblocks, &qshift);
+
+	/*
+	 * The final prealloc size is set to the minimum of free space available
+	 * in each of the quotas and the overall filesystem.
+	 *
+	 * The shift throttle value is set to the maximum value as determined by
+	 * the global low free space values and per-quota low free space values.
+	 */
+	alloc_blocks = MIN(alloc_blocks, qblocks);
+	shift = MAX(shift, qshift);
+
 	if (shift)
 		alloc_blocks >>= shift;
 	/*
-- 
1.7.7.6

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v3 7/7] xfs: xfs_iomap_prealloc_size() tracepoint
  2013-02-19 16:37 [PATCH v3 0/7] speculative preallocation quota throttling Brian Foster
                   ` (5 preceding siblings ...)
  2013-02-19 16:37 ` [PATCH v3 6/7] xfs: add quota-driven speculative preallocation throttling Brian Foster
@ 2013-02-19 16:37 ` Brian Foster
  6 siblings, 0 replies; 14+ messages in thread
From: Brian Foster @ 2013-02-19 16:37 UTC (permalink / raw)
  To: xfs

Add a tracepoint to provide some feedback on preallocation size
calculation.

Signed-off-by: Brian Foster <bfoster@redhat.com>
---
 fs/xfs/xfs_iomap.c |    3 +++
 fs/xfs/xfs_trace.h |   24 ++++++++++++++++++++++++
 2 files changed, 27 insertions(+), 0 deletions(-)

diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 6355e80..ebb62dc 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -520,6 +520,9 @@ check_writeio:
 	if (alloc_blocks < mp->m_writeio_blocks)
 		alloc_blocks = mp->m_writeio_blocks;
 
+	trace_xfs_iomap_prealloc_size(ip, alloc_blocks, shift,
+				      mp->m_writeio_blocks);
+
 	return alloc_blocks;
 }
 
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
index 16a8129..aa4db33 100644
--- a/fs/xfs/xfs_trace.h
+++ b/fs/xfs/xfs_trace.h
@@ -619,6 +619,30 @@ DECLARE_EVENT_CLASS(xfs_iref_class,
 		  (char *)__entry->caller_ip)
 )
 
+TRACE_EVENT(xfs_iomap_prealloc_size,
+	TP_PROTO(struct xfs_inode *ip, xfs_fsblock_t blocks, int shift,
+		 unsigned int writeio_blocks),
+	TP_ARGS(ip, blocks, shift, writeio_blocks),
+	TP_STRUCT__entry(
+		__field(dev_t, dev)
+		__field(xfs_ino_t, ino)
+		__field(xfs_fsblock_t, blocks)
+		__field(int, shift)
+		__field(unsigned int, writeio_blocks)
+	),
+	TP_fast_assign(
+		__entry->dev = VFS_I(ip)->i_sb->s_dev;
+		__entry->ino = ip->i_ino;
+		__entry->blocks = blocks;
+		__entry->shift = shift;
+		__entry->writeio_blocks = writeio_blocks;
+	),
+	TP_printk("dev %d:%d ino 0x%llx prealloc blocks %llu shift %d "
+		  "m_writeio_blocks %u",
+		  MAJOR(__entry->dev), MINOR(__entry->dev), __entry->ino,
+		  __entry->blocks, __entry->shift, __entry->writeio_blocks)
+)
+
 #define DEFINE_IREF_EVENT(name) \
 DEFINE_EVENT(xfs_iref_class, name, \
 	TP_PROTO(struct xfs_inode *ip, unsigned long caller_ip), \
-- 
1.7.7.6

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 3/7] xfs: cap prealloc size to free space before shift
  2013-02-19 16:37 ` [PATCH v3 3/7] xfs: cap prealloc size to free space before shift Brian Foster
@ 2013-02-19 21:48   ` Dave Chinner
  2013-02-19 22:29     ` Brian Foster
  0 siblings, 1 reply; 14+ messages in thread
From: Dave Chinner @ 2013-02-19 21:48 UTC (permalink / raw)
  To: Brian Foster; +Cc: xfs

On Tue, Feb 19, 2013 at 11:37:27AM -0500, Brian Foster wrote:
> With the addition of quota preallocation throttling, we want to
> support a general algorithm that considers the maximum allowable
> prealloc size and recommended shift modifier from various sources
> (i.e., global fs state and all applicable quotas for an inode).
> 
> Update the current global free space throttle algorithm to cap the
> preallocation size to the free space available in the filesystem.
> 
> Signed-off-by: Brian Foster <bfoster@redhat.com>
> ---
>  fs/xfs/xfs_iomap.c |    3 +++
>  1 files changed, 3 insertions(+), 0 deletions(-)
> 
> diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
> index daa08f6..3b41c18 100644
> --- a/fs/xfs/xfs_iomap.c
> +++ b/fs/xfs/xfs_iomap.c
> @@ -412,6 +412,9 @@ xfs_iomap_prealloc_size(
>  		if (freesp < mp->m_low_space[XFS_LOWSP_1_PCNT])
>  			shift++;
>  	}
> +	if (alloc_blocks > freesp)
> +		alloc_blocks = freesp;
> +
>  	if (shift)
>  		alloc_blocks >>= shift;

This is redundant with the previous additions of the trailing

	while (alloc_blocks >= freesp)
		alloc_blocks >>= 4;

code. Effectively adding the check will result in preventing the
existing loop from working as alloc_blocks will be brought down to
just under freespc by things like power of 2 rounding, rather than
being thottled to a small fraction of the remaining free space...

Cheers,

Dave.
-- 
Dave Chinner
david@fromorbit.com

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 3/7] xfs: cap prealloc size to free space before shift
  2013-02-19 21:48   ` Dave Chinner
@ 2013-02-19 22:29     ` Brian Foster
  2013-02-19 23:19       ` Dave Chinner
  0 siblings, 1 reply; 14+ messages in thread
From: Brian Foster @ 2013-02-19 22:29 UTC (permalink / raw)
  To: Dave Chinner; +Cc: xfs

On 02/19/2013 04:48 PM, Dave Chinner wrote:
> On Tue, Feb 19, 2013 at 11:37:27AM -0500, Brian Foster wrote:
>> With the addition of quota preallocation throttling, we want to
>> support a general algorithm that considers the maximum allowable
>> prealloc size and recommended shift modifier from various sources
>> (i.e., global fs state and all applicable quotas for an inode).
>>
>> Update the current global free space throttle algorithm to cap the
>> preallocation size to the free space available in the filesystem.
>>
>> Signed-off-by: Brian Foster <bfoster@redhat.com>
>> ---
>>  fs/xfs/xfs_iomap.c |    3 +++
>>  1 files changed, 3 insertions(+), 0 deletions(-)
>>
>> diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
>> index daa08f6..3b41c18 100644
>> --- a/fs/xfs/xfs_iomap.c
>> +++ b/fs/xfs/xfs_iomap.c
>> @@ -412,6 +412,9 @@ xfs_iomap_prealloc_size(
>>  		if (freesp < mp->m_low_space[XFS_LOWSP_1_PCNT])
>>  			shift++;
>>  	}
>> +	if (alloc_blocks > freesp)
>> +		alloc_blocks = freesp;
>> +
>>  	if (shift)
>>  		alloc_blocks >>= shift;
> 
> This is redundant with the previous additions of the trailing
> 
> 	while (alloc_blocks >= freesp)
> 		alloc_blocks >>= 4;
> 
> code. Effectively adding the check will result in preventing the
> existing loop from working as alloc_blocks will be brought down to
> just under freespc by things like power of 2 rounding, rather than
> being thottled to a small fraction of the remaining free space...
> 

Ah, yes. For starters, this set was more of a logical add-on to make the
throttling consistent between global free space and quota limits (e.g.,
start with free space available and throttle down) as opposed to a
functional dependency, so it should be safe to just drop this patch from
the set.

Tracking back to that discussion...

http://oss.sgi.com/archives/xfs/2013-01/msg00392.html

... my understanding is that at the moment, the condition addressed by
the previous change is not relevant to quota since we have no
flush/retry cycle (e.g., we just fail early). The intended follow up set
to this (eofblocks scan, retry) would introduce such a cycle. What I'm
wondering is if we'll need something similar longer term within the
quota throttling code.

In particular, is the "metadata overhead" referred to in your original
explanation accounted against an associated quota, such that it still
isn't enough to simply start the prealloc capped at the quota free space
limit? If so, perhaps as part of that set I'll need to modify this code
to carry a minimum 'qfreesp' through each of the quotas and add that to
the squashing loop...

Brian

> Cheers,
> 
> Dave.
> 

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 5/7] xfs: xfs_dquot prealloc throttling watermarks and low free space
  2013-02-19 16:37 ` [PATCH v3 5/7] xfs: xfs_dquot prealloc throttling watermarks and low free space Brian Foster
@ 2013-02-19 23:08   ` Dave Chinner
  2013-02-20 13:17     ` Brian Foster
  0 siblings, 1 reply; 14+ messages in thread
From: Dave Chinner @ 2013-02-19 23:08 UTC (permalink / raw)
  To: Brian Foster; +Cc: xfs

On Tue, Feb 19, 2013 at 11:37:29AM -0500, Brian Foster wrote:
> 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>
> ---
>  fs/xfs/xfs_dquot.c       |   43 +++++++++++++++++++++++++++++++++++++++++--
>  fs/xfs/xfs_dquot.h       |   13 +++++++++++++
>  fs/xfs/xfs_qm_syscalls.c |    1 +
>  3 files changed, 55 insertions(+), 2 deletions(-)
> 
> diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
> index e1833b9..bd25be3 100644
> --- a/fs/xfs/xfs_dquot.c
> +++ b/fs/xfs/xfs_dquot.c
> @@ -90,13 +90,18 @@ xfs_qm_adjust_dqlimits(
>  {
>  	xfs_quotainfo_t		*q = mp->m_quotainfo;
>  	xfs_disk_dquot_t	*d = &dq->q_core;
> +	int			prealloc = 0;
>  
>  	ASSERT(d->d_id);
>  
> -	if (q->qi_bsoftlimit && !d->d_blk_softlimit)
> +	if (q->qi_bsoftlimit && !d->d_blk_softlimit) {
>  		d->d_blk_softlimit = cpu_to_be64(q->qi_bsoftlimit);
> -	if (q->qi_bhardlimit && !d->d_blk_hardlimit)
> +		prealloc = 1;
> +	}
> +	if (q->qi_bhardlimit && !d->d_blk_hardlimit) {
>  		d->d_blk_hardlimit = cpu_to_be64(q->qi_bhardlimit);
> +		prealloc = 1;
> +	}
>  	if (q->qi_isoftlimit && !d->d_ino_softlimit)
>  		d->d_ino_softlimit = cpu_to_be64(q->qi_isoftlimit);
>  	if (q->qi_ihardlimit && !d->d_ino_hardlimit)
> @@ -105,6 +110,9 @@ xfs_qm_adjust_dqlimits(
>  		d->d_rtb_softlimit = cpu_to_be64(q->qi_rtbsoftlimit);
>  	if (q->qi_rtbhardlimit && !d->d_rtb_hardlimit)
>  		d->d_rtb_hardlimit = cpu_to_be64(q->qi_rtbhardlimit);
> +
> +	if (prealloc)
> +		xfs_dquot_init_prealloc(dq);

		xfs_dquot_set_prealloc_limits(dq);

Because it is used to overwrite existing limits here, not just
initialise them...

>  }
>  
>  /*
> @@ -249,6 +257,34 @@ xfs_qm_init_dquot_blk(
>  	xfs_trans_log_buf(tp, bp, 0, BBTOB(q->qi_dqchunklen) - 1);
>  }
>  
> +/*
> + * Initialize the preallocation throttling watermarks and low free space table.

"Initialise the dynamic speculative preallocation thresholds." 

> + * The lo/hi watermarks correspond to the soft and hard limits by default. If a
> + * soft limit is not specified, we use 95% of the hard limit.
> + */
> +void
> +xfs_dquot_init_prealloc(struct xfs_dquot *dqp)
> +{
> +	int i;
> +	int pct = 1;
> +
> +	dqp->q_prealloc_hi_wmark = be64_to_cpu(dqp->q_core.d_blk_hardlimit);
> +	dqp->q_prealloc_lo_wmark = be64_to_cpu(dqp->q_core.d_blk_softlimit);
> +	if (!dqp->q_prealloc_lo_wmark) {
> +		dqp->q_prealloc_lo_wmark = dqp->q_prealloc_hi_wmark;
> +		do_div(dqp->q_prealloc_lo_wmark, 100);
> +		dqp->q_prealloc_lo_wmark *= 95;
> +	}
> +
> +	for (i = 0; i < XFS_QLOWSP_MAX; i++) {
> +		__uint64_t space = dqp->q_prealloc_hi_wmark;
> +
> +		do_div(space, 100);
> +		dqp->q_low_space[i] = space * pct;
> +		pct += XFS_QLOWSP_PCNT_INCR;
> +	}

This seems kind of obscure. It's just a simple assignment of 3
values, so why not just unroll the loop like so:

	__uint64_t space = dqp->q_prealloc_hi_wmark;

	do_div(space, 100);
	dqp->q_low_space[XFS_QLOWSP_1_PCNT] = space;
	dqp->q_low_space[XFS_QLOWSP_3_PCNT] = space * 3
	dqp->q_low_space[XFS_QLOWSP_5_PCNT] = space * 5;

And it effectively documents itself.

I know the mount lowspace array is initialised in a loop, but it has
a fairly obvious per-iteration increment of 1 percent....

> --- a/fs/xfs/xfs_dquot.h
> +++ b/fs/xfs/xfs_dquot.h
> @@ -32,6 +32,14 @@
>  struct xfs_mount;
>  struct xfs_trans;
>  
> +enum {
> +	XFS_QLOWSP_1_PCNT = 0,
> +	XFS_QLOWSP_3_PCNT,
> +	XFS_QLOWSP_5_PCNT,
> +	XFS_QLOWSP_MAX
> +};
> +#define XFS_QLOWSP_PCNT_INCR 2

And gets rid of this strange vowel-challenged XFS_QLOWSP_PCNT_INCR
thingy....

Cheers,

Dave.
-- 
Dave Chinner
david@fromorbit.com

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 3/7] xfs: cap prealloc size to free space before shift
  2013-02-19 22:29     ` Brian Foster
@ 2013-02-19 23:19       ` Dave Chinner
  2013-02-20 13:17         ` Brian Foster
  0 siblings, 1 reply; 14+ messages in thread
From: Dave Chinner @ 2013-02-19 23:19 UTC (permalink / raw)
  To: Brian Foster; +Cc: xfs

On Tue, Feb 19, 2013 at 05:29:11PM -0500, Brian Foster wrote:
> On 02/19/2013 04:48 PM, Dave Chinner wrote:
> > On Tue, Feb 19, 2013 at 11:37:27AM -0500, Brian Foster wrote:
> >> With the addition of quota preallocation throttling, we want to
> >> support a general algorithm that considers the maximum allowable
> >> prealloc size and recommended shift modifier from various sources
> >> (i.e., global fs state and all applicable quotas for an inode).
> >>
> >> Update the current global free space throttle algorithm to cap the
> >> preallocation size to the free space available in the filesystem.
> >>
> >> Signed-off-by: Brian Foster <bfoster@redhat.com>
> >> ---
> >>  fs/xfs/xfs_iomap.c |    3 +++
> >>  1 files changed, 3 insertions(+), 0 deletions(-)
> >>
> >> diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
> >> index daa08f6..3b41c18 100644
> >> --- a/fs/xfs/xfs_iomap.c
> >> +++ b/fs/xfs/xfs_iomap.c
> >> @@ -412,6 +412,9 @@ xfs_iomap_prealloc_size(
> >>  		if (freesp < mp->m_low_space[XFS_LOWSP_1_PCNT])
> >>  			shift++;
> >>  	}
> >> +	if (alloc_blocks > freesp)
> >> +		alloc_blocks = freesp;
> >> +
> >>  	if (shift)
> >>  		alloc_blocks >>= shift;
> > 
> > This is redundant with the previous additions of the trailing
> > 
> > 	while (alloc_blocks >= freesp)
> > 		alloc_blocks >>= 4;
> > 
> > code. Effectively adding the check will result in preventing the
> > existing loop from working as alloc_blocks will be brought down to
> > just under freespc by things like power of 2 rounding, rather than
> > being thottled to a small fraction of the remaining free space...
> > 
> 
> Ah, yes. For starters, this set was more of a logical add-on to make the
> throttling consistent between global free space and quota limits (e.g.,
> start with free space available and throttle down) as opposed to a
> functional dependency, so it should be safe to just drop this patch from
> the set.
> 
> Tracking back to that discussion...
> 
> http://oss.sgi.com/archives/xfs/2013-01/msg00392.html
> 
> ... my understanding is that at the moment, the condition addressed by
> the previous change is not relevant to quota since we have no
> flush/retry cycle (e.g., we just fail early). The intended follow up set
> to this (eofblocks scan, retry) would introduce such a cycle. What I'm
> wondering is if we'll need something similar longer term within the
> quota throttling code.

There is a retry cycle for EDQUOT - we simply turn off preallocation
and try again. So, if we ask for all the free blocks in the
quota....

> 
> In particular, is the "metadata overhead" referred to in your original
> explanation accounted against an associated quota,

... this *may* trigger an EDQUOT and turn off preallocation.

> such that it still
> isn't enough to simply start the prealloc capped at the quota free space
> limit? If so, perhaps as part of that set I'll need to modify this code
> to carry a minimum 'qfreesp' through each of the quotas and add that to
> the squashing loop...

Probably.

i.e. it doesn't matter alloc_blocks is over freesp or dquot limits
at the end of the prealloc size calculation. If it is, we just keep
squashing it by >>= 4 until it is under all relevant thresholds...

Cheers,

Dave.
-- 
Dave Chinner
david@fromorbit.com

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 5/7] xfs: xfs_dquot prealloc throttling watermarks and low free space
  2013-02-19 23:08   ` Dave Chinner
@ 2013-02-20 13:17     ` Brian Foster
  0 siblings, 0 replies; 14+ messages in thread
From: Brian Foster @ 2013-02-20 13:17 UTC (permalink / raw)
  To: Dave Chinner; +Cc: xfs

On 02/19/2013 06:08 PM, Dave Chinner wrote:
> On Tue, Feb 19, 2013 at 11:37:29AM -0500, Brian Foster wrote:
>> 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>
>> ---
>>  fs/xfs/xfs_dquot.c       |   43 +++++++++++++++++++++++++++++++++++++++++--
>>  fs/xfs/xfs_dquot.h       |   13 +++++++++++++
>>  fs/xfs/xfs_qm_syscalls.c |    1 +
>>  3 files changed, 55 insertions(+), 2 deletions(-)
>>
>> diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
>> index e1833b9..bd25be3 100644
>> --- a/fs/xfs/xfs_dquot.c
>> +++ b/fs/xfs/xfs_dquot.c
...
>> +
>> +	if (prealloc)
>> +		xfs_dquot_init_prealloc(dq);
> 
> 		xfs_dquot_set_prealloc_limits(dq);
> 
> Because it is used to overwrite existing limits here, not just
> initialise them...
> 

Ok.

>>  }
>>  
>>  /*
>> @@ -249,6 +257,34 @@ xfs_qm_init_dquot_blk(
>>  	xfs_trans_log_buf(tp, bp, 0, BBTOB(q->qi_dqchunklen) - 1);
>>  }
>>  
>> +/*
>> + * Initialize the preallocation throttling watermarks and low free space table.
> 
> "Initialise the dynamic speculative preallocation thresholds." 
> 

Sounds good.

...
>> +	for (i = 0; i < XFS_QLOWSP_MAX; i++) {
>> +		__uint64_t space = dqp->q_prealloc_hi_wmark;
>> +
>> +		do_div(space, 100);
>> +		dqp->q_low_space[i] = space * pct;
>> +		pct += XFS_QLOWSP_PCNT_INCR;
>> +	}
> 
> This seems kind of obscure. It's just a simple assignment of 3
> values, so why not just unroll the loop like so:
> 
> 	__uint64_t space = dqp->q_prealloc_hi_wmark;
> 
> 	do_div(space, 100);
> 	dqp->q_low_space[XFS_QLOWSP_1_PCNT] = space;
> 	dqp->q_low_space[XFS_QLOWSP_3_PCNT] = space * 3
> 	dqp->q_low_space[XFS_QLOWSP_5_PCNT] = space * 5;
> 
> And it effectively documents itself.
> 
> I know the mount lowspace array is initialised in a loop, but it has
> a fairly obvious per-iteration increment of 1 percent....
> 

Yeah, I agree that is cleaner.

>> --- a/fs/xfs/xfs_dquot.h
>> +++ b/fs/xfs/xfs_dquot.h
>> @@ -32,6 +32,14 @@
>>  struct xfs_mount;
>>  struct xfs_trans;
>>  
>> +enum {
>> +	XFS_QLOWSP_1_PCNT = 0,
>> +	XFS_QLOWSP_3_PCNT,
>> +	XFS_QLOWSP_5_PCNT,
>> +	XFS_QLOWSP_MAX
>> +};
>> +#define XFS_QLOWSP_PCNT_INCR 2
> 
> And gets rid of this strange vowel-challenged XFS_QLOWSP_PCNT_INCR
> thingy....
> 

Snds gd. ;)

Brian

> Cheers,
> 
> Dave.
> 

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 3/7] xfs: cap prealloc size to free space before shift
  2013-02-19 23:19       ` Dave Chinner
@ 2013-02-20 13:17         ` Brian Foster
  0 siblings, 0 replies; 14+ messages in thread
From: Brian Foster @ 2013-02-20 13:17 UTC (permalink / raw)
  To: Dave Chinner; +Cc: xfs

On 02/19/2013 06:19 PM, Dave Chinner wrote:
> On Tue, Feb 19, 2013 at 05:29:11PM -0500, Brian Foster wrote:
>> On 02/19/2013 04:48 PM, Dave Chinner wrote:
>>> On Tue, Feb 19, 2013 at 11:37:27AM -0500, Brian Foster wrote:
...
>> Tracking back to that discussion...
>>
>> http://oss.sgi.com/archives/xfs/2013-01/msg00392.html
>>
>> ... my understanding is that at the moment, the condition addressed by
>> the previous change is not relevant to quota since we have no
>> flush/retry cycle (e.g., we just fail early). The intended follow up set
>> to this (eofblocks scan, retry) would introduce such a cycle. What I'm
>> wondering is if we'll need something similar longer term within the
>> quota throttling code.
> 
> There is a retry cycle for EDQUOT - we simply turn off preallocation
> and try again. So, if we ask for all the free blocks in the
> quota....
> 
>>
>> In particular, is the "metadata overhead" referred to in your original
>> explanation accounted against an associated quota,
> 
> ... this *may* trigger an EDQUOT and turn off preallocation.
> 

Good point. I guess I was more thinking about the severity of the
effective "sync write" mode caused by the flush and retry cycle, as
opposed to the loss of prealloc and hit of the retry. The eofblocks scan
shouldn't be as heavy weight as a flush, but that kind of cycle is
undesirable nonetheless.

>> such that it still
>> isn't enough to simply start the prealloc capped at the quota free space
>> limit? If so, perhaps as part of that set I'll need to modify this code
>> to carry a minimum 'qfreesp' through each of the quotas and add that to
>> the squashing loop...
> 
> Probably.
> 
> i.e. it doesn't matter alloc_blocks is over freesp or dquot limits
> at the end of the prealloc size calculation. If it is, we just keep
> squashing it by >>= 4 until it is under all relevant thresholds...
> 

Yeah, that's pretty much what I was thinking. I'll plan to include that
as part of the follow on work that introduces the eofblocks scan. Thanks.

Brian

> Cheers,
> 
> Dave.
> 

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2013-02-20 13:15 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-02-19 16:37 [PATCH v3 0/7] speculative preallocation quota throttling Brian Foster
2013-02-19 16:37 ` [PATCH v3 1/7] xfs: reorganize xfs_iomap_prealloc_size to remove indentation Brian Foster
2013-02-19 16:37 ` [PATCH v3 2/7] xfs: push rounddown_pow_of_two() to after prealloc throttle Brian Foster
2013-02-19 16:37 ` [PATCH v3 3/7] xfs: cap prealloc size to free space before shift Brian Foster
2013-02-19 21:48   ` Dave Chinner
2013-02-19 22:29     ` Brian Foster
2013-02-19 23:19       ` Dave Chinner
2013-02-20 13:17         ` Brian Foster
2013-02-19 16:37 ` [PATCH v3 4/7] xfs: pass xfs_dquot to xfs_qm_adjust_dqlimits() instead of xfs_disk_dquot_t Brian Foster
2013-02-19 16:37 ` [PATCH v3 5/7] xfs: xfs_dquot prealloc throttling watermarks and low free space Brian Foster
2013-02-19 23:08   ` Dave Chinner
2013-02-20 13:17     ` Brian Foster
2013-02-19 16:37 ` [PATCH v3 6/7] xfs: add quota-driven speculative preallocation throttling Brian Foster
2013-02-19 16:37 ` [PATCH v3 7/7] xfs: xfs_iomap_prealloc_size() tracepoint Brian Foster

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.