diff options
author | Brian Foster <bfoster@redhat.com> | 2018-08-01 10:20:31 -0400 |
---|---|---|
committer | Darrick J. Wong <darrick.wong@oracle.com> | 2018-08-03 02:05:13 -0400 |
commit | 1214f1cf663b0939fbb8f1bccdc74c1d1e452d53 (patch) | |
tree | 24a8b208cbfff610e5099eab6cdae0f474aad9df | |
parent | ce356d64772f920f26cd6c1b02878a737a275638 (diff) |
xfs: replace dop_low with transaction flag
The dop_low field enables the low free space allocation mode when a
previous allocation has detected difficulty allocating blocks. It
has historically been part of the xfs_defer_ops structure, which
means if enabled, it remains enabled across a set of transactions
until the deferred operations have completed and the dfops is reset.
Now that the dfops is embedded in the transaction, we can save a bit
more space by using a transaction flag rather than a standalone
boolean. Drop the ->dop_low field and replace it with a transaction
flag that is set at the same points, carried across rolling
transactions and cleared on completion of deferred operations. This
essentially emulates the behavior of ->dop_low and so should not
change behavior.
Signed-off-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
-rw-r--r-- | fs/xfs/libxfs/xfs_bmap.c | 8 | ||||
-rw-r--r-- | fs/xfs/libxfs/xfs_bmap_btree.c | 4 | ||||
-rw-r--r-- | fs/xfs/libxfs/xfs_defer.c | 16 | ||||
-rw-r--r-- | fs/xfs/libxfs/xfs_defer.h | 11 | ||||
-rw-r--r-- | fs/xfs/libxfs/xfs_shared.h | 12 | ||||
-rw-r--r-- | fs/xfs/xfs_filestream.c | 3 | ||||
-rw-r--r-- | fs/xfs/xfs_trace.h | 10 | ||||
-rw-r--r-- | fs/xfs/xfs_trans.h | 2 |
8 files changed, 36 insertions, 30 deletions
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index a85c0445b38f..8edf7522aaff 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c | |||
@@ -700,7 +700,7 @@ xfs_bmap_extents_to_btree( | |||
700 | if (tp->t_firstblock == NULLFSBLOCK) { | 700 | if (tp->t_firstblock == NULLFSBLOCK) { |
701 | args.type = XFS_ALLOCTYPE_START_BNO; | 701 | args.type = XFS_ALLOCTYPE_START_BNO; |
702 | args.fsbno = XFS_INO_TO_FSB(mp, ip->i_ino); | 702 | args.fsbno = XFS_INO_TO_FSB(mp, ip->i_ino); |
703 | } else if (tp->t_dfops->dop_low) { | 703 | } else if (tp->t_flags & XFS_TRANS_LOWMODE) { |
704 | args.type = XFS_ALLOCTYPE_START_BNO; | 704 | args.type = XFS_ALLOCTYPE_START_BNO; |
705 | args.fsbno = tp->t_firstblock; | 705 | args.fsbno = tp->t_firstblock; |
706 | } else { | 706 | } else { |
@@ -3449,7 +3449,7 @@ xfs_bmap_btalloc( | |||
3449 | error = xfs_bmap_btalloc_nullfb(ap, &args, &blen); | 3449 | error = xfs_bmap_btalloc_nullfb(ap, &args, &blen); |
3450 | if (error) | 3450 | if (error) |
3451 | return error; | 3451 | return error; |
3452 | } else if (ap->tp->t_dfops->dop_low) { | 3452 | } else if (ap->tp->t_flags & XFS_TRANS_LOWMODE) { |
3453 | if (xfs_inode_is_filestream(ap->ip)) | 3453 | if (xfs_inode_is_filestream(ap->ip)) |
3454 | args.type = XFS_ALLOCTYPE_FIRST_AG; | 3454 | args.type = XFS_ALLOCTYPE_FIRST_AG; |
3455 | else | 3455 | else |
@@ -3484,7 +3484,7 @@ xfs_bmap_btalloc( | |||
3484 | * is >= the stripe unit and the allocation offset is | 3484 | * is >= the stripe unit and the allocation offset is |
3485 | * at the end of file. | 3485 | * at the end of file. |
3486 | */ | 3486 | */ |
3487 | if (!ap->tp->t_dfops->dop_low && ap->aeof) { | 3487 | if (!(ap->tp->t_flags & XFS_TRANS_LOWMODE) && ap->aeof) { |
3488 | if (!ap->offset) { | 3488 | if (!ap->offset) { |
3489 | args.alignment = stripe_align; | 3489 | args.alignment = stripe_align; |
3490 | atype = args.type; | 3490 | atype = args.type; |
@@ -3576,7 +3576,7 @@ xfs_bmap_btalloc( | |||
3576 | args.total = ap->minlen; | 3576 | args.total = ap->minlen; |
3577 | if ((error = xfs_alloc_vextent(&args))) | 3577 | if ((error = xfs_alloc_vextent(&args))) |
3578 | return error; | 3578 | return error; |
3579 | ap->tp->t_dfops->dop_low = true; | 3579 | ap->tp->t_flags |= XFS_TRANS_LOWMODE; |
3580 | } | 3580 | } |
3581 | if (args.fsbno != NULLFSBLOCK) { | 3581 | if (args.fsbno != NULLFSBLOCK) { |
3582 | /* | 3582 | /* |
diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c index 01489714a253..955e29de8cae 100644 --- a/fs/xfs/libxfs/xfs_bmap_btree.c +++ b/fs/xfs/libxfs/xfs_bmap_btree.c | |||
@@ -226,7 +226,7 @@ xfs_bmbt_alloc_block( | |||
226 | * block allocation here and corrupt the filesystem. | 226 | * block allocation here and corrupt the filesystem. |
227 | */ | 227 | */ |
228 | args.minleft = args.tp->t_blk_res; | 228 | args.minleft = args.tp->t_blk_res; |
229 | } else if (cur->bc_tp->t_dfops->dop_low) { | 229 | } else if (cur->bc_tp->t_flags & XFS_TRANS_LOWMODE) { |
230 | args.type = XFS_ALLOCTYPE_START_BNO; | 230 | args.type = XFS_ALLOCTYPE_START_BNO; |
231 | } else { | 231 | } else { |
232 | args.type = XFS_ALLOCTYPE_NEAR_BNO; | 232 | args.type = XFS_ALLOCTYPE_NEAR_BNO; |
@@ -253,7 +253,7 @@ xfs_bmbt_alloc_block( | |||
253 | error = xfs_alloc_vextent(&args); | 253 | error = xfs_alloc_vextent(&args); |
254 | if (error) | 254 | if (error) |
255 | goto error0; | 255 | goto error0; |
256 | cur->bc_tp->t_dfops->dop_low = true; | 256 | cur->bc_tp->t_flags |= XFS_TRANS_LOWMODE; |
257 | } | 257 | } |
258 | if (WARN_ON_ONCE(args.fsbno == NULLFSBLOCK)) { | 258 | if (WARN_ON_ONCE(args.fsbno == NULLFSBLOCK)) { |
259 | *stat = 0; | 259 | *stat = 0; |
diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c index e3517a53c525..64e1abc60edc 100644 --- a/fs/xfs/libxfs/xfs_defer.c +++ b/fs/xfs/libxfs/xfs_defer.c | |||
@@ -330,9 +330,14 @@ xfs_defer_reset( | |||
330 | 330 | ||
331 | ASSERT(!xfs_defer_has_unfinished_work(dop)); | 331 | ASSERT(!xfs_defer_has_unfinished_work(dop)); |
332 | 332 | ||
333 | dop->dop_low = false; | ||
334 | memset(dop->dop_inodes, 0, sizeof(dop->dop_inodes)); | 333 | memset(dop->dop_inodes, 0, sizeof(dop->dop_inodes)); |
335 | memset(dop->dop_bufs, 0, sizeof(dop->dop_bufs)); | 334 | memset(dop->dop_bufs, 0, sizeof(dop->dop_bufs)); |
335 | |||
336 | /* | ||
337 | * Low mode state transfers across transaction rolls to mirror dfops | ||
338 | * lifetime. Clear it now that dfops is reset. | ||
339 | */ | ||
340 | tp->t_flags &= ~XFS_TRANS_LOWMODE; | ||
336 | } | 341 | } |
337 | 342 | ||
338 | /* | 343 | /* |
@@ -590,7 +595,14 @@ xfs_defer_move( | |||
590 | 595 | ||
591 | memcpy(dst->dop_inodes, src->dop_inodes, sizeof(dst->dop_inodes)); | 596 | memcpy(dst->dop_inodes, src->dop_inodes, sizeof(dst->dop_inodes)); |
592 | memcpy(dst->dop_bufs, src->dop_bufs, sizeof(dst->dop_bufs)); | 597 | memcpy(dst->dop_bufs, src->dop_bufs, sizeof(dst->dop_bufs)); |
593 | dst->dop_low = src->dop_low; | 598 | |
599 | /* | ||
600 | * Low free space mode was historically controlled by a dfops field. | ||
601 | * This meant that low mode state potentially carried across multiple | ||
602 | * transaction rolls. Transfer low mode on a dfops move to preserve | ||
603 | * that behavior. | ||
604 | */ | ||
605 | dtp->t_flags |= (stp->t_flags & XFS_TRANS_LOWMODE); | ||
594 | 606 | ||
595 | xfs_defer_reset(stp); | 607 | xfs_defer_reset(stp); |
596 | } | 608 | } |
diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h index d60c50498fdf..8908a2716774 100644 --- a/fs/xfs/libxfs/xfs_defer.h +++ b/fs/xfs/libxfs/xfs_defer.h | |||
@@ -25,17 +25,6 @@ struct xfs_defer_pending { | |||
25 | 25 | ||
26 | /* | 26 | /* |
27 | * Header for deferred operation list. | 27 | * Header for deferred operation list. |
28 | * | ||
29 | * dop_low is used by the allocator to activate the lowspace algorithm - | ||
30 | * when free space is running low the extent allocator may choose to | ||
31 | * allocate an extent from an AG without leaving sufficient space for | ||
32 | * a btree split when inserting the new extent. In this case the allocator | ||
33 | * will enable the lowspace algorithm which is supposed to allow further | ||
34 | * allocations (such as btree splits and newroots) to allocate from | ||
35 | * sequential AGs. In order to avoid locking AGs out of order the lowspace | ||
36 | * algorithm will start searching for free space from AG 0. If the correct | ||
37 | * transaction reservations have been made then this algorithm will eventually | ||
38 | * find all the space it needs. | ||
39 | */ | 28 | */ |
40 | enum xfs_defer_ops_type { | 29 | enum xfs_defer_ops_type { |
41 | XFS_DEFER_OPS_TYPE_BMAP, | 30 | XFS_DEFER_OPS_TYPE_BMAP, |
diff --git a/fs/xfs/libxfs/xfs_shared.h b/fs/xfs/libxfs/xfs_shared.h index 22089f1c880a..1c5debe748f0 100644 --- a/fs/xfs/libxfs/xfs_shared.h +++ b/fs/xfs/libxfs/xfs_shared.h | |||
@@ -64,6 +64,18 @@ void xfs_log_get_max_trans_res(struct xfs_mount *mp, | |||
64 | #define XFS_TRANS_RESERVE 0x20 /* OK to use reserved data blocks */ | 64 | #define XFS_TRANS_RESERVE 0x20 /* OK to use reserved data blocks */ |
65 | #define XFS_TRANS_NO_WRITECOUNT 0x40 /* do not elevate SB writecount */ | 65 | #define XFS_TRANS_NO_WRITECOUNT 0x40 /* do not elevate SB writecount */ |
66 | #define XFS_TRANS_NOFS 0x80 /* pass KM_NOFS to kmem_alloc */ | 66 | #define XFS_TRANS_NOFS 0x80 /* pass KM_NOFS to kmem_alloc */ |
67 | /* | ||
68 | * LOWMODE is used by the allocator to activate the lowspace algorithm - when | ||
69 | * free space is running low the extent allocator may choose to allocate an | ||
70 | * extent from an AG without leaving sufficient space for a btree split when | ||
71 | * inserting the new extent. In this case the allocator will enable the | ||
72 | * lowspace algorithm which is supposed to allow further allocations (such as | ||
73 | * btree splits and newroots) to allocate from sequential AGs. In order to | ||
74 | * avoid locking AGs out of order the lowspace algorithm will start searching | ||
75 | * for free space from AG 0. If the correct transaction reservations have been | ||
76 | * made then this algorithm will eventually find all the space it needs. | ||
77 | */ | ||
78 | #define XFS_TRANS_LOWMODE 0x100 /* allocate in low space mode */ | ||
67 | 79 | ||
68 | /* | 80 | /* |
69 | * Field values for xfs_trans_mod_sb. | 81 | * Field values for xfs_trans_mod_sb. |
diff --git a/fs/xfs/xfs_filestream.c b/fs/xfs/xfs_filestream.c index 212173c62588..182501373af2 100644 --- a/fs/xfs/xfs_filestream.c +++ b/fs/xfs/xfs_filestream.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include "xfs_trace.h" | 20 | #include "xfs_trace.h" |
21 | #include "xfs_ag_resv.h" | 21 | #include "xfs_ag_resv.h" |
22 | #include "xfs_trans.h" | 22 | #include "xfs_trans.h" |
23 | #include "xfs_shared.h" | ||
23 | 24 | ||
24 | struct xfs_fstrm_item { | 25 | struct xfs_fstrm_item { |
25 | struct xfs_mru_cache_elem mru; | 26 | struct xfs_mru_cache_elem mru; |
@@ -378,7 +379,7 @@ xfs_filestream_new_ag( | |||
378 | 379 | ||
379 | if (xfs_alloc_is_userdata(ap->datatype)) | 380 | if (xfs_alloc_is_userdata(ap->datatype)) |
380 | flags |= XFS_PICK_USERDATA; | 381 | flags |= XFS_PICK_USERDATA; |
381 | if (ap->tp->t_dfops->dop_low) | 382 | if (ap->tp->t_flags & XFS_TRANS_LOWMODE) |
382 | flags |= XFS_PICK_LOWSPACE; | 383 | flags |= XFS_PICK_LOWSPACE; |
383 | 384 | ||
384 | err = xfs_filestream_pick_ag(pip, startag, agp, flags, minlen); | 385 | err = xfs_filestream_pick_ag(pip, startag, agp, flags, minlen); |
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index cc6995cfce66..8807f1bb814a 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h | |||
@@ -2223,19 +2223,16 @@ DECLARE_EVENT_CLASS(xfs_defer_class, | |||
2223 | __field(dev_t, dev) | 2223 | __field(dev_t, dev) |
2224 | __field(void *, dop) | 2224 | __field(void *, dop) |
2225 | __field(char, committed) | 2225 | __field(char, committed) |
2226 | __field(char, low) | ||
2227 | __field(unsigned long, caller_ip) | 2226 | __field(unsigned long, caller_ip) |
2228 | ), | 2227 | ), |
2229 | TP_fast_assign( | 2228 | TP_fast_assign( |
2230 | __entry->dev = mp ? mp->m_super->s_dev : 0; | 2229 | __entry->dev = mp ? mp->m_super->s_dev : 0; |
2231 | __entry->dop = dop; | 2230 | __entry->dop = dop; |
2232 | __entry->low = dop->dop_low; | ||
2233 | __entry->caller_ip = caller_ip; | 2231 | __entry->caller_ip = caller_ip; |
2234 | ), | 2232 | ), |
2235 | TP_printk("dev %d:%d ops %p low %d, caller %pS", | 2233 | TP_printk("dev %d:%d ops %p caller %pS", |
2236 | MAJOR(__entry->dev), MINOR(__entry->dev), | 2234 | MAJOR(__entry->dev), MINOR(__entry->dev), |
2237 | __entry->dop, | 2235 | __entry->dop, |
2238 | __entry->low, | ||
2239 | (char *)__entry->caller_ip) | 2236 | (char *)__entry->caller_ip) |
2240 | ) | 2237 | ) |
2241 | #define DEFINE_DEFER_EVENT(name) \ | 2238 | #define DEFINE_DEFER_EVENT(name) \ |
@@ -2251,19 +2248,16 @@ DECLARE_EVENT_CLASS(xfs_defer_error_class, | |||
2251 | __field(dev_t, dev) | 2248 | __field(dev_t, dev) |
2252 | __field(void *, dop) | 2249 | __field(void *, dop) |
2253 | __field(char, committed) | 2250 | __field(char, committed) |
2254 | __field(char, low) | ||
2255 | __field(int, error) | 2251 | __field(int, error) |
2256 | ), | 2252 | ), |
2257 | TP_fast_assign( | 2253 | TP_fast_assign( |
2258 | __entry->dev = mp ? mp->m_super->s_dev : 0; | 2254 | __entry->dev = mp ? mp->m_super->s_dev : 0; |
2259 | __entry->dop = dop; | 2255 | __entry->dop = dop; |
2260 | __entry->low = dop->dop_low; | ||
2261 | __entry->error = error; | 2256 | __entry->error = error; |
2262 | ), | 2257 | ), |
2263 | TP_printk("dev %d:%d ops %p low %d err %d", | 2258 | TP_printk("dev %d:%d ops %p err %d", |
2264 | MAJOR(__entry->dev), MINOR(__entry->dev), | 2259 | MAJOR(__entry->dev), MINOR(__entry->dev), |
2265 | __entry->dop, | 2260 | __entry->dop, |
2266 | __entry->low, | ||
2267 | __entry->error) | 2261 | __entry->error) |
2268 | ) | 2262 | ) |
2269 | #define DEFINE_DEFER_ERROR_EVENT(name) \ | 2263 | #define DEFINE_DEFER_ERROR_EVENT(name) \ |
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index dc79e3c1d3e8..7e493221160e 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h | |||
@@ -101,8 +101,6 @@ struct xfs_defer_ops { | |||
101 | /* relog these with each roll */ | 101 | /* relog these with each roll */ |
102 | struct xfs_inode *dop_inodes[XFS_DEFER_OPS_NR_INODES]; | 102 | struct xfs_inode *dop_inodes[XFS_DEFER_OPS_NR_INODES]; |
103 | struct xfs_buf *dop_bufs[XFS_DEFER_OPS_NR_BUFS]; | 103 | struct xfs_buf *dop_bufs[XFS_DEFER_OPS_NR_BUFS]; |
104 | |||
105 | bool dop_low; /* alloc in low mode */ | ||
106 | }; | 104 | }; |
107 | 105 | ||
108 | /* | 106 | /* |