aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorBrian Foster <bfoster@redhat.com>2013-03-18 10:51:47 -0400
committerBen Myers <bpm@sgi.com>2013-03-22 17:07:21 -0400
commit76a4202a388690e664668c4f668ee12d709100b3 (patch)
treec10ea589bed0223d520d3ff843dd65a7e72c5115 /fs/xfs
parentb136645116e5471cf0b037a1759dc83620236631 (diff)
xfs: add quota-driven speculative preallocation throttling
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> 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_iomap.c82
1 files changed, 82 insertions, 0 deletions
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 9072794e3a42..0a530853b53d 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -42,6 +42,8 @@
42#include "xfs_iomap.h" 42#include "xfs_iomap.h"
43#include "xfs_trace.h" 43#include "xfs_trace.h"
44#include "xfs_icache.h" 44#include "xfs_icache.h"
45#include "xfs_dquot_item.h"
46#include "xfs_dquot.h"
45 47
46 48
47#define XFS_WRITEIO_ALIGN(mp,off) (((off) >> mp->m_writeio_log) \ 49#define XFS_WRITEIO_ALIGN(mp,off) (((off) >> mp->m_writeio_log) \
@@ -366,6 +368,61 @@ xfs_iomap_eof_prealloc_initial_size(
366 return XFS_B_TO_FSB(mp, offset); 368 return XFS_B_TO_FSB(mp, offset);
367} 369}
368 370
371STATIC bool
372xfs_quota_need_throttle(
373 struct xfs_inode *ip,
374 int type,
375 xfs_fsblock_t alloc_blocks)
376{
377 struct xfs_dquot *dq = xfs_inode_dquot(ip, type);
378
379 if (!dq || !xfs_this_quota_on(ip->i_mount, type))
380 return false;
381
382 /* no hi watermark, no throttle */
383 if (!dq->q_prealloc_hi_wmark)
384 return false;
385
386 /* under the lo watermark, no throttle */
387 if (dq->q_res_bcount + alloc_blocks < dq->q_prealloc_lo_wmark)
388 return false;
389
390 return true;
391}
392
393STATIC void
394xfs_quota_calc_throttle(
395 struct xfs_inode *ip,
396 int type,
397 xfs_fsblock_t *qblocks,
398 int *qshift)
399{
400 int64_t freesp;
401 int shift = 0;
402 struct xfs_dquot *dq = xfs_inode_dquot(ip, type);
403
404 /* over hi wmark, squash the prealloc completely */
405 if (dq->q_res_bcount >= dq->q_prealloc_hi_wmark) {
406 *qblocks = 0;
407 return;
408 }
409
410 freesp = dq->q_prealloc_hi_wmark - dq->q_res_bcount;
411 if (freesp < dq->q_low_space[XFS_QLOWSP_5_PCNT]) {
412 shift = 2;
413 if (freesp < dq->q_low_space[XFS_QLOWSP_3_PCNT])
414 shift += 2;
415 if (freesp < dq->q_low_space[XFS_QLOWSP_1_PCNT])
416 shift += 2;
417 }
418
419 /* only overwrite the throttle values if we are more aggressive */
420 if ((freesp >> shift) < (*qblocks >> *qshift)) {
421 *qblocks = freesp;
422 *qshift = shift;
423 }
424}
425
369/* 426/*
370 * If we don't have a user specified preallocation size, dynamically increase 427 * If we don't have a user specified preallocation size, dynamically increase
371 * the preallocation size as the size of the file grows. Cap the maximum size 428 * the preallocation size as the size of the file grows. Cap the maximum size
@@ -383,11 +440,14 @@ xfs_iomap_prealloc_size(
383 xfs_fsblock_t alloc_blocks = 0; 440 xfs_fsblock_t alloc_blocks = 0;
384 int shift = 0; 441 int shift = 0;
385 int64_t freesp; 442 int64_t freesp;
443 xfs_fsblock_t qblocks;
444 int qshift = 0;
386 445
387 alloc_blocks = xfs_iomap_eof_prealloc_initial_size(mp, ip, offset, 446 alloc_blocks = xfs_iomap_eof_prealloc_initial_size(mp, ip, offset,
388 imap, nimaps); 447 imap, nimaps);
389 if (!alloc_blocks) 448 if (!alloc_blocks)
390 goto check_writeio; 449 goto check_writeio;
450 qblocks = alloc_blocks;
391 451
392 /* 452 /*
393 * MAXEXTLEN is not a power of two value but we round the prealloc down 453 * MAXEXTLEN is not a power of two value but we round the prealloc down
@@ -412,6 +472,28 @@ xfs_iomap_prealloc_size(
412 if (freesp < mp->m_low_space[XFS_LOWSP_1_PCNT]) 472 if (freesp < mp->m_low_space[XFS_LOWSP_1_PCNT])
413 shift++; 473 shift++;
414 } 474 }
475
476 /*
477 * Check each quota to cap the prealloc size and provide a shift
478 * value to throttle with.
479 */
480 if (xfs_quota_need_throttle(ip, XFS_DQ_USER, alloc_blocks))
481 xfs_quota_calc_throttle(ip, XFS_DQ_USER, &qblocks, &qshift);
482 if (xfs_quota_need_throttle(ip, XFS_DQ_GROUP, alloc_blocks))
483 xfs_quota_calc_throttle(ip, XFS_DQ_GROUP, &qblocks, &qshift);
484 if (xfs_quota_need_throttle(ip, XFS_DQ_PROJ, alloc_blocks))
485 xfs_quota_calc_throttle(ip, XFS_DQ_PROJ, &qblocks, &qshift);
486
487 /*
488 * The final prealloc size is set to the minimum of free space available
489 * in each of the quotas and the overall filesystem.
490 *
491 * The shift throttle value is set to the maximum value as determined by
492 * the global low free space values and per-quota low free space values.
493 */
494 alloc_blocks = MIN(alloc_blocks, qblocks);
495 shift = MAX(shift, qshift);
496
415 if (shift) 497 if (shift)
416 alloc_blocks >>= shift; 498 alloc_blocks >>= shift;
417 /* 499 /*