diff options
| author | Thomas Gleixner <tglx@linutronix.de> | 2016-09-26 15:47:03 -0400 |
|---|---|---|
| committer | Thomas Gleixner <tglx@linutronix.de> | 2016-09-26 15:47:03 -0400 |
| commit | 1e1b37273cf719545da50b76f214f983a710aaf4 (patch) | |
| tree | 033f6062325ef7aaeefe8559bb409ab7d2be3c76 /fs/xfs | |
| parent | c183a603e8d8a5a189729b77d0c623a3d5950e5f (diff) | |
| parent | c291b015158577be533dd5a959dfc09bab119eed (diff) | |
Merge branch 'x86/urgent' into x86/apic
Bring in the upstream modifications so we can fixup the silent merge
conflict which is introduced by this merge.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'fs/xfs')
| -rw-r--r-- | fs/xfs/libxfs/xfs_alloc.c | 16 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_btree.c | 14 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_defer.c | 17 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_defer.h | 2 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_format.h | 13 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_rmap_btree.c | 6 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_sb.c | 3 | ||||
| -rw-r--r-- | fs/xfs/xfs_buf.c | 3 | ||||
| -rw-r--r-- | fs/xfs/xfs_file.c | 13 | ||||
| -rw-r--r-- | fs/xfs/xfs_fsops.c | 1 | ||||
| -rw-r--r-- | fs/xfs/xfs_iomap.c | 69 | ||||
| -rw-r--r-- | fs/xfs/xfs_iomap.h | 1 | ||||
| -rw-r--r-- | fs/xfs/xfs_iops.c | 9 | ||||
| -rw-r--r-- | fs/xfs/xfs_super.c | 9 | ||||
| -rw-r--r-- | fs/xfs/xfs_trace.h | 3 |
15 files changed, 140 insertions, 39 deletions
diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 776ae2f325d1..05b5243d89f6 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c | |||
| @@ -1582,6 +1582,7 @@ xfs_alloc_ag_vextent_small( | |||
| 1582 | xfs_extlen_t *flenp, /* result length */ | 1582 | xfs_extlen_t *flenp, /* result length */ |
| 1583 | int *stat) /* status: 0-freelist, 1-normal/none */ | 1583 | int *stat) /* status: 0-freelist, 1-normal/none */ |
| 1584 | { | 1584 | { |
| 1585 | struct xfs_owner_info oinfo; | ||
| 1585 | int error; | 1586 | int error; |
| 1586 | xfs_agblock_t fbno; | 1587 | xfs_agblock_t fbno; |
| 1587 | xfs_extlen_t flen; | 1588 | xfs_extlen_t flen; |
| @@ -1624,6 +1625,18 @@ xfs_alloc_ag_vextent_small( | |||
| 1624 | error0); | 1625 | error0); |
| 1625 | args->wasfromfl = 1; | 1626 | args->wasfromfl = 1; |
| 1626 | trace_xfs_alloc_small_freelist(args); | 1627 | trace_xfs_alloc_small_freelist(args); |
| 1628 | |||
| 1629 | /* | ||
| 1630 | * If we're feeding an AGFL block to something that | ||
| 1631 | * doesn't live in the free space, we need to clear | ||
| 1632 | * out the OWN_AG rmap. | ||
| 1633 | */ | ||
| 1634 | xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_AG); | ||
| 1635 | error = xfs_rmap_free(args->tp, args->agbp, args->agno, | ||
| 1636 | fbno, 1, &oinfo); | ||
| 1637 | if (error) | ||
| 1638 | goto error0; | ||
| 1639 | |||
| 1627 | *stat = 0; | 1640 | *stat = 0; |
| 1628 | return 0; | 1641 | return 0; |
| 1629 | } | 1642 | } |
| @@ -2264,6 +2277,9 @@ xfs_alloc_log_agf( | |||
| 2264 | offsetof(xfs_agf_t, agf_longest), | 2277 | offsetof(xfs_agf_t, agf_longest), |
| 2265 | offsetof(xfs_agf_t, agf_btreeblks), | 2278 | offsetof(xfs_agf_t, agf_btreeblks), |
| 2266 | offsetof(xfs_agf_t, agf_uuid), | 2279 | offsetof(xfs_agf_t, agf_uuid), |
| 2280 | offsetof(xfs_agf_t, agf_rmap_blocks), | ||
| 2281 | /* needed so that we don't log the whole rest of the structure: */ | ||
| 2282 | offsetof(xfs_agf_t, agf_spare64), | ||
| 2267 | sizeof(xfs_agf_t) | 2283 | sizeof(xfs_agf_t) |
| 2268 | }; | 2284 | }; |
| 2269 | 2285 | ||
diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c index b5c213a051cd..08569792fe20 100644 --- a/fs/xfs/libxfs/xfs_btree.c +++ b/fs/xfs/libxfs/xfs_btree.c | |||
| @@ -1814,6 +1814,10 @@ xfs_btree_lookup( | |||
| 1814 | 1814 | ||
| 1815 | XFS_BTREE_STATS_INC(cur, lookup); | 1815 | XFS_BTREE_STATS_INC(cur, lookup); |
| 1816 | 1816 | ||
| 1817 | /* No such thing as a zero-level tree. */ | ||
| 1818 | if (cur->bc_nlevels == 0) | ||
| 1819 | return -EFSCORRUPTED; | ||
| 1820 | |||
| 1817 | block = NULL; | 1821 | block = NULL; |
| 1818 | keyno = 0; | 1822 | keyno = 0; |
| 1819 | 1823 | ||
| @@ -4554,15 +4558,22 @@ xfs_btree_simple_query_range( | |||
| 4554 | if (error) | 4558 | if (error) |
| 4555 | goto out; | 4559 | goto out; |
| 4556 | 4560 | ||
| 4561 | /* Nothing? See if there's anything to the right. */ | ||
| 4562 | if (!stat) { | ||
| 4563 | error = xfs_btree_increment(cur, 0, &stat); | ||
| 4564 | if (error) | ||
| 4565 | goto out; | ||
| 4566 | } | ||
| 4567 | |||
| 4557 | while (stat) { | 4568 | while (stat) { |
| 4558 | /* Find the record. */ | 4569 | /* Find the record. */ |
| 4559 | error = xfs_btree_get_rec(cur, &recp, &stat); | 4570 | error = xfs_btree_get_rec(cur, &recp, &stat); |
| 4560 | if (error || !stat) | 4571 | if (error || !stat) |
| 4561 | break; | 4572 | break; |
| 4562 | cur->bc_ops->init_high_key_from_rec(&rec_key, recp); | ||
| 4563 | 4573 | ||
| 4564 | /* Skip if high_key(rec) < low_key. */ | 4574 | /* Skip if high_key(rec) < low_key. */ |
| 4565 | if (firstrec) { | 4575 | if (firstrec) { |
| 4576 | cur->bc_ops->init_high_key_from_rec(&rec_key, recp); | ||
| 4566 | firstrec = false; | 4577 | firstrec = false; |
| 4567 | diff = cur->bc_ops->diff_two_keys(cur, low_key, | 4578 | diff = cur->bc_ops->diff_two_keys(cur, low_key, |
| 4568 | &rec_key); | 4579 | &rec_key); |
| @@ -4571,6 +4582,7 @@ xfs_btree_simple_query_range( | |||
| 4571 | } | 4582 | } |
| 4572 | 4583 | ||
| 4573 | /* Stop if high_key < low_key(rec). */ | 4584 | /* Stop if high_key < low_key(rec). */ |
| 4585 | cur->bc_ops->init_key_from_rec(&rec_key, recp); | ||
| 4574 | diff = cur->bc_ops->diff_two_keys(cur, &rec_key, high_key); | 4586 | diff = cur->bc_ops->diff_two_keys(cur, &rec_key, high_key); |
| 4575 | if (diff > 0) | 4587 | if (diff > 0) |
| 4576 | break; | 4588 | break; |
diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c index 054a2032fdb3..c221d0ecd52e 100644 --- a/fs/xfs/libxfs/xfs_defer.c +++ b/fs/xfs/libxfs/xfs_defer.c | |||
| @@ -194,7 +194,7 @@ xfs_defer_trans_abort( | |||
| 194 | /* Abort intent items. */ | 194 | /* Abort intent items. */ |
| 195 | list_for_each_entry(dfp, &dop->dop_pending, dfp_list) { | 195 | list_for_each_entry(dfp, &dop->dop_pending, dfp_list) { |
| 196 | trace_xfs_defer_pending_abort(tp->t_mountp, dfp); | 196 | trace_xfs_defer_pending_abort(tp->t_mountp, dfp); |
| 197 | if (dfp->dfp_committed) | 197 | if (!dfp->dfp_done) |
| 198 | dfp->dfp_type->abort_intent(dfp->dfp_intent); | 198 | dfp->dfp_type->abort_intent(dfp->dfp_intent); |
| 199 | } | 199 | } |
| 200 | 200 | ||
| @@ -290,7 +290,6 @@ xfs_defer_finish( | |||
| 290 | struct xfs_defer_pending *dfp; | 290 | struct xfs_defer_pending *dfp; |
| 291 | struct list_head *li; | 291 | struct list_head *li; |
| 292 | struct list_head *n; | 292 | struct list_head *n; |
| 293 | void *done_item = NULL; | ||
| 294 | void *state; | 293 | void *state; |
| 295 | int error = 0; | 294 | int error = 0; |
| 296 | void (*cleanup_fn)(struct xfs_trans *, void *, int); | 295 | void (*cleanup_fn)(struct xfs_trans *, void *, int); |
| @@ -309,19 +308,11 @@ xfs_defer_finish( | |||
| 309 | if (error) | 308 | if (error) |
| 310 | goto out; | 309 | goto out; |
| 311 | 310 | ||
| 312 | /* Mark all pending intents as committed. */ | ||
| 313 | list_for_each_entry_reverse(dfp, &dop->dop_pending, dfp_list) { | ||
| 314 | if (dfp->dfp_committed) | ||
| 315 | break; | ||
| 316 | trace_xfs_defer_pending_commit((*tp)->t_mountp, dfp); | ||
| 317 | dfp->dfp_committed = true; | ||
| 318 | } | ||
| 319 | |||
| 320 | /* Log an intent-done item for the first pending item. */ | 311 | /* Log an intent-done item for the first pending item. */ |
| 321 | dfp = list_first_entry(&dop->dop_pending, | 312 | dfp = list_first_entry(&dop->dop_pending, |
| 322 | struct xfs_defer_pending, dfp_list); | 313 | struct xfs_defer_pending, dfp_list); |
| 323 | trace_xfs_defer_pending_finish((*tp)->t_mountp, dfp); | 314 | trace_xfs_defer_pending_finish((*tp)->t_mountp, dfp); |
| 324 | done_item = dfp->dfp_type->create_done(*tp, dfp->dfp_intent, | 315 | dfp->dfp_done = dfp->dfp_type->create_done(*tp, dfp->dfp_intent, |
| 325 | dfp->dfp_count); | 316 | dfp->dfp_count); |
| 326 | cleanup_fn = dfp->dfp_type->finish_cleanup; | 317 | cleanup_fn = dfp->dfp_type->finish_cleanup; |
| 327 | 318 | ||
| @@ -331,7 +322,7 @@ xfs_defer_finish( | |||
| 331 | list_del(li); | 322 | list_del(li); |
| 332 | dfp->dfp_count--; | 323 | dfp->dfp_count--; |
| 333 | error = dfp->dfp_type->finish_item(*tp, dop, li, | 324 | error = dfp->dfp_type->finish_item(*tp, dop, li, |
| 334 | done_item, &state); | 325 | dfp->dfp_done, &state); |
| 335 | if (error) { | 326 | if (error) { |
| 336 | /* | 327 | /* |
| 337 | * Clean up after ourselves and jump out. | 328 | * Clean up after ourselves and jump out. |
| @@ -428,8 +419,8 @@ xfs_defer_add( | |||
| 428 | dfp = kmem_alloc(sizeof(struct xfs_defer_pending), | 419 | dfp = kmem_alloc(sizeof(struct xfs_defer_pending), |
| 429 | KM_SLEEP | KM_NOFS); | 420 | KM_SLEEP | KM_NOFS); |
| 430 | dfp->dfp_type = defer_op_types[type]; | 421 | dfp->dfp_type = defer_op_types[type]; |
| 431 | dfp->dfp_committed = false; | ||
| 432 | dfp->dfp_intent = NULL; | 422 | dfp->dfp_intent = NULL; |
| 423 | dfp->dfp_done = NULL; | ||
| 433 | dfp->dfp_count = 0; | 424 | dfp->dfp_count = 0; |
| 434 | INIT_LIST_HEAD(&dfp->dfp_work); | 425 | INIT_LIST_HEAD(&dfp->dfp_work); |
| 435 | list_add_tail(&dfp->dfp_list, &dop->dop_intake); | 426 | list_add_tail(&dfp->dfp_list, &dop->dop_intake); |
diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h index cc3981c48296..e96533d178cf 100644 --- a/fs/xfs/libxfs/xfs_defer.h +++ b/fs/xfs/libxfs/xfs_defer.h | |||
| @@ -30,8 +30,8 @@ struct xfs_defer_op_type; | |||
| 30 | struct xfs_defer_pending { | 30 | struct xfs_defer_pending { |
| 31 | const struct xfs_defer_op_type *dfp_type; /* function pointers */ | 31 | const struct xfs_defer_op_type *dfp_type; /* function pointers */ |
| 32 | struct list_head dfp_list; /* pending items */ | 32 | struct list_head dfp_list; /* pending items */ |
| 33 | bool dfp_committed; /* committed trans? */ | ||
| 34 | void *dfp_intent; /* log intent item */ | 33 | void *dfp_intent; /* log intent item */ |
| 34 | void *dfp_done; /* log done item */ | ||
| 35 | struct list_head dfp_work; /* work items */ | 35 | struct list_head dfp_work; /* work items */ |
| 36 | unsigned int dfp_count; /* # extent items */ | 36 | unsigned int dfp_count; /* # extent items */ |
| 37 | }; | 37 | }; |
diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index f814d42c73b2..270fb5cf4fa1 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h | |||
| @@ -640,12 +640,15 @@ typedef struct xfs_agf { | |||
| 640 | __be32 agf_btreeblks; /* # of blocks held in AGF btrees */ | 640 | __be32 agf_btreeblks; /* # of blocks held in AGF btrees */ |
| 641 | uuid_t agf_uuid; /* uuid of filesystem */ | 641 | uuid_t agf_uuid; /* uuid of filesystem */ |
| 642 | 642 | ||
| 643 | __be32 agf_rmap_blocks; /* rmapbt blocks used */ | ||
| 644 | __be32 agf_padding; /* padding */ | ||
| 645 | |||
| 643 | /* | 646 | /* |
| 644 | * reserve some contiguous space for future logged fields before we add | 647 | * reserve some contiguous space for future logged fields before we add |
| 645 | * the unlogged fields. This makes the range logging via flags and | 648 | * the unlogged fields. This makes the range logging via flags and |
| 646 | * structure offsets much simpler. | 649 | * structure offsets much simpler. |
| 647 | */ | 650 | */ |
| 648 | __be64 agf_spare64[16]; | 651 | __be64 agf_spare64[15]; |
| 649 | 652 | ||
| 650 | /* unlogged fields, written during buffer writeback. */ | 653 | /* unlogged fields, written during buffer writeback. */ |
| 651 | __be64 agf_lsn; /* last write sequence */ | 654 | __be64 agf_lsn; /* last write sequence */ |
| @@ -670,7 +673,9 @@ typedef struct xfs_agf { | |||
| 670 | #define XFS_AGF_LONGEST 0x00000400 | 673 | #define XFS_AGF_LONGEST 0x00000400 |
| 671 | #define XFS_AGF_BTREEBLKS 0x00000800 | 674 | #define XFS_AGF_BTREEBLKS 0x00000800 |
| 672 | #define XFS_AGF_UUID 0x00001000 | 675 | #define XFS_AGF_UUID 0x00001000 |
| 673 | #define XFS_AGF_NUM_BITS 13 | 676 | #define XFS_AGF_RMAP_BLOCKS 0x00002000 |
| 677 | #define XFS_AGF_SPARE64 0x00004000 | ||
| 678 | #define XFS_AGF_NUM_BITS 15 | ||
| 674 | #define XFS_AGF_ALL_BITS ((1 << XFS_AGF_NUM_BITS) - 1) | 679 | #define XFS_AGF_ALL_BITS ((1 << XFS_AGF_NUM_BITS) - 1) |
| 675 | 680 | ||
| 676 | #define XFS_AGF_FLAGS \ | 681 | #define XFS_AGF_FLAGS \ |
| @@ -686,7 +691,9 @@ typedef struct xfs_agf { | |||
| 686 | { XFS_AGF_FREEBLKS, "FREEBLKS" }, \ | 691 | { XFS_AGF_FREEBLKS, "FREEBLKS" }, \ |
| 687 | { XFS_AGF_LONGEST, "LONGEST" }, \ | 692 | { XFS_AGF_LONGEST, "LONGEST" }, \ |
| 688 | { XFS_AGF_BTREEBLKS, "BTREEBLKS" }, \ | 693 | { XFS_AGF_BTREEBLKS, "BTREEBLKS" }, \ |
| 689 | { XFS_AGF_UUID, "UUID" } | 694 | { XFS_AGF_UUID, "UUID" }, \ |
| 695 | { XFS_AGF_RMAP_BLOCKS, "RMAP_BLOCKS" }, \ | ||
| 696 | { XFS_AGF_SPARE64, "SPARE64" } | ||
| 690 | 697 | ||
| 691 | /* disk block (xfs_daddr_t) in the AG */ | 698 | /* disk block (xfs_daddr_t) in the AG */ |
| 692 | #define XFS_AGF_DADDR(mp) ((xfs_daddr_t)(1 << (mp)->m_sectbb_log)) | 699 | #define XFS_AGF_DADDR(mp) ((xfs_daddr_t)(1 << (mp)->m_sectbb_log)) |
diff --git a/fs/xfs/libxfs/xfs_rmap_btree.c b/fs/xfs/libxfs/xfs_rmap_btree.c index bc1faebc84ec..17b8eeb34ac8 100644 --- a/fs/xfs/libxfs/xfs_rmap_btree.c +++ b/fs/xfs/libxfs/xfs_rmap_btree.c | |||
| @@ -98,6 +98,8 @@ xfs_rmapbt_alloc_block( | |||
| 98 | union xfs_btree_ptr *new, | 98 | union xfs_btree_ptr *new, |
| 99 | int *stat) | 99 | int *stat) |
| 100 | { | 100 | { |
| 101 | struct xfs_buf *agbp = cur->bc_private.a.agbp; | ||
| 102 | struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); | ||
| 101 | int error; | 103 | int error; |
| 102 | xfs_agblock_t bno; | 104 | xfs_agblock_t bno; |
| 103 | 105 | ||
| @@ -124,6 +126,8 @@ xfs_rmapbt_alloc_block( | |||
| 124 | 126 | ||
| 125 | xfs_trans_agbtree_delta(cur->bc_tp, 1); | 127 | xfs_trans_agbtree_delta(cur->bc_tp, 1); |
| 126 | new->s = cpu_to_be32(bno); | 128 | new->s = cpu_to_be32(bno); |
| 129 | be32_add_cpu(&agf->agf_rmap_blocks, 1); | ||
| 130 | xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_RMAP_BLOCKS); | ||
| 127 | 131 | ||
| 128 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); | 132 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); |
| 129 | *stat = 1; | 133 | *stat = 1; |
| @@ -143,6 +147,8 @@ xfs_rmapbt_free_block( | |||
| 143 | bno = xfs_daddr_to_agbno(cur->bc_mp, XFS_BUF_ADDR(bp)); | 147 | bno = xfs_daddr_to_agbno(cur->bc_mp, XFS_BUF_ADDR(bp)); |
| 144 | trace_xfs_rmapbt_free_block(cur->bc_mp, cur->bc_private.a.agno, | 148 | trace_xfs_rmapbt_free_block(cur->bc_mp, cur->bc_private.a.agno, |
| 145 | bno, 1); | 149 | bno, 1); |
| 150 | be32_add_cpu(&agf->agf_rmap_blocks, -1); | ||
| 151 | xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_RMAP_BLOCKS); | ||
| 146 | error = xfs_alloc_put_freelist(cur->bc_tp, agbp, NULL, bno, 1); | 152 | error = xfs_alloc_put_freelist(cur->bc_tp, agbp, NULL, bno, 1); |
| 147 | if (error) | 153 | if (error) |
| 148 | return error; | 154 | return error; |
diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c index 0e3d4f5ec33c..4aecc5fefe96 100644 --- a/fs/xfs/libxfs/xfs_sb.c +++ b/fs/xfs/libxfs/xfs_sb.c | |||
| @@ -583,7 +583,8 @@ xfs_sb_verify( | |||
| 583 | * Only check the in progress field for the primary superblock as | 583 | * Only check the in progress field for the primary superblock as |
| 584 | * mkfs.xfs doesn't clear it from secondary superblocks. | 584 | * mkfs.xfs doesn't clear it from secondary superblocks. |
| 585 | */ | 585 | */ |
| 586 | return xfs_mount_validate_sb(mp, &sb, bp->b_bn == XFS_SB_DADDR, | 586 | return xfs_mount_validate_sb(mp, &sb, |
| 587 | bp->b_maps[0].bm_bn == XFS_SB_DADDR, | ||
| 587 | check_version); | 588 | check_version); |
| 588 | } | 589 | } |
| 589 | 590 | ||
diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index 47a318ce82e0..b5b9bffe3520 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c | |||
| @@ -115,7 +115,6 @@ xfs_buf_ioacct_dec( | |||
| 115 | if (!(bp->b_flags & _XBF_IN_FLIGHT)) | 115 | if (!(bp->b_flags & _XBF_IN_FLIGHT)) |
| 116 | return; | 116 | return; |
| 117 | 117 | ||
| 118 | ASSERT(bp->b_flags & XBF_ASYNC); | ||
| 119 | bp->b_flags &= ~_XBF_IN_FLIGHT; | 118 | bp->b_flags &= ~_XBF_IN_FLIGHT; |
| 120 | percpu_counter_dec(&bp->b_target->bt_io_count); | 119 | percpu_counter_dec(&bp->b_target->bt_io_count); |
| 121 | } | 120 | } |
| @@ -1612,7 +1611,7 @@ xfs_wait_buftarg( | |||
| 1612 | */ | 1611 | */ |
| 1613 | while (percpu_counter_sum(&btp->bt_io_count)) | 1612 | while (percpu_counter_sum(&btp->bt_io_count)) |
| 1614 | delay(100); | 1613 | delay(100); |
| 1615 | drain_workqueue(btp->bt_mount->m_buf_workqueue); | 1614 | flush_workqueue(btp->bt_mount->m_buf_workqueue); |
| 1616 | 1615 | ||
| 1617 | /* loop until there is nothing left on the lru list. */ | 1616 | /* loop until there is nothing left on the lru list. */ |
| 1618 | while (list_lru_count(&btp->bt_lru)) { | 1617 | while (list_lru_count(&btp->bt_lru)) { |
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index ed95e5bb04e6..e612a0233710 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c | |||
| @@ -741,9 +741,20 @@ xfs_file_dax_write( | |||
| 741 | * page is inserted into the pagecache when we have to serve a write | 741 | * page is inserted into the pagecache when we have to serve a write |
| 742 | * fault on a hole. It should never be dirtied and can simply be | 742 | * fault on a hole. It should never be dirtied and can simply be |
| 743 | * dropped from the pagecache once we get real data for the page. | 743 | * dropped from the pagecache once we get real data for the page. |
| 744 | * | ||
| 745 | * XXX: This is racy against mmap, and there's nothing we can do about | ||
| 746 | * it. dax_do_io() should really do this invalidation internally as | ||
| 747 | * it will know if we've allocated over a holei for this specific IO and | ||
| 748 | * if so it needs to update the mapping tree and invalidate existing | ||
| 749 | * PTEs over the newly allocated range. Remove this invalidation when | ||
| 750 | * dax_do_io() is fixed up. | ||
| 744 | */ | 751 | */ |
| 745 | if (mapping->nrpages) { | 752 | if (mapping->nrpages) { |
| 746 | ret = invalidate_inode_pages2(mapping); | 753 | loff_t end = iocb->ki_pos + iov_iter_count(from) - 1; |
| 754 | |||
| 755 | ret = invalidate_inode_pages2_range(mapping, | ||
| 756 | iocb->ki_pos >> PAGE_SHIFT, | ||
| 757 | end >> PAGE_SHIFT); | ||
| 747 | WARN_ON_ONCE(ret); | 758 | WARN_ON_ONCE(ret); |
| 748 | } | 759 | } |
| 749 | 760 | ||
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index 0f96847b90e1..0b7f986745c1 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c | |||
| @@ -248,6 +248,7 @@ xfs_growfs_data_private( | |||
| 248 | agf->agf_roots[XFS_BTNUM_RMAPi] = | 248 | agf->agf_roots[XFS_BTNUM_RMAPi] = |
| 249 | cpu_to_be32(XFS_RMAP_BLOCK(mp)); | 249 | cpu_to_be32(XFS_RMAP_BLOCK(mp)); |
| 250 | agf->agf_levels[XFS_BTNUM_RMAPi] = cpu_to_be32(1); | 250 | agf->agf_levels[XFS_BTNUM_RMAPi] = cpu_to_be32(1); |
| 251 | agf->agf_rmap_blocks = cpu_to_be32(1); | ||
| 251 | } | 252 | } |
| 252 | 253 | ||
| 253 | agf->agf_flfirst = cpu_to_be32(1); | 254 | agf->agf_flfirst = cpu_to_be32(1); |
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 2114d53df433..2af0dda1c978 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c | |||
| @@ -715,12 +715,16 @@ xfs_iomap_write_allocate( | |||
| 715 | * is in the delayed allocation extent on which we sit | 715 | * is in the delayed allocation extent on which we sit |
| 716 | * but before our buffer starts. | 716 | * but before our buffer starts. |
| 717 | */ | 717 | */ |
| 718 | |||
| 719 | nimaps = 0; | 718 | nimaps = 0; |
| 720 | while (nimaps == 0) { | 719 | while (nimaps == 0) { |
| 721 | nres = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK); | 720 | nres = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK); |
| 722 | 721 | /* | |
| 723 | error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, nres, | 722 | * We have already reserved space for the extent and any |
| 723 | * indirect blocks when creating the delalloc extent, | ||
| 724 | * there is no need to reserve space in this transaction | ||
| 725 | * again. | ||
| 726 | */ | ||
| 727 | error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, 0, | ||
| 724 | 0, XFS_TRANS_RESERVE, &tp); | 728 | 0, XFS_TRANS_RESERVE, &tp); |
| 725 | if (error) | 729 | if (error) |
| 726 | return error; | 730 | return error; |
| @@ -1037,20 +1041,14 @@ xfs_file_iomap_begin( | |||
| 1037 | return error; | 1041 | return error; |
| 1038 | 1042 | ||
| 1039 | trace_xfs_iomap_alloc(ip, offset, length, 0, &imap); | 1043 | trace_xfs_iomap_alloc(ip, offset, length, 0, &imap); |
| 1040 | xfs_bmbt_to_iomap(ip, iomap, &imap); | ||
| 1041 | } else if (nimaps) { | ||
| 1042 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
| 1043 | trace_xfs_iomap_found(ip, offset, length, 0, &imap); | ||
| 1044 | xfs_bmbt_to_iomap(ip, iomap, &imap); | ||
| 1045 | } else { | 1044 | } else { |
| 1045 | ASSERT(nimaps); | ||
| 1046 | |||
| 1046 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | 1047 | xfs_iunlock(ip, XFS_ILOCK_EXCL); |
| 1047 | trace_xfs_iomap_not_found(ip, offset, length, 0, &imap); | 1048 | trace_xfs_iomap_found(ip, offset, length, 0, &imap); |
| 1048 | iomap->blkno = IOMAP_NULL_BLOCK; | ||
| 1049 | iomap->type = IOMAP_HOLE; | ||
| 1050 | iomap->offset = offset; | ||
| 1051 | iomap->length = length; | ||
| 1052 | } | 1049 | } |
| 1053 | 1050 | ||
| 1051 | xfs_bmbt_to_iomap(ip, iomap, &imap); | ||
| 1054 | return 0; | 1052 | return 0; |
| 1055 | } | 1053 | } |
| 1056 | 1054 | ||
| @@ -1112,3 +1110,48 @@ struct iomap_ops xfs_iomap_ops = { | |||
| 1112 | .iomap_begin = xfs_file_iomap_begin, | 1110 | .iomap_begin = xfs_file_iomap_begin, |
| 1113 | .iomap_end = xfs_file_iomap_end, | 1111 | .iomap_end = xfs_file_iomap_end, |
| 1114 | }; | 1112 | }; |
| 1113 | |||
| 1114 | static int | ||
| 1115 | xfs_xattr_iomap_begin( | ||
| 1116 | struct inode *inode, | ||
| 1117 | loff_t offset, | ||
| 1118 | loff_t length, | ||
| 1119 | unsigned flags, | ||
| 1120 | struct iomap *iomap) | ||
| 1121 | { | ||
| 1122 | struct xfs_inode *ip = XFS_I(inode); | ||
| 1123 | struct xfs_mount *mp = ip->i_mount; | ||
| 1124 | xfs_fileoff_t offset_fsb = XFS_B_TO_FSBT(mp, offset); | ||
| 1125 | xfs_fileoff_t end_fsb = XFS_B_TO_FSB(mp, offset + length); | ||
| 1126 | struct xfs_bmbt_irec imap; | ||
| 1127 | int nimaps = 1, error = 0; | ||
| 1128 | unsigned lockmode; | ||
| 1129 | |||
| 1130 | if (XFS_FORCED_SHUTDOWN(mp)) | ||
| 1131 | return -EIO; | ||
| 1132 | |||
| 1133 | lockmode = xfs_ilock_data_map_shared(ip); | ||
| 1134 | |||
| 1135 | /* if there are no attribute fork or extents, return ENOENT */ | ||
| 1136 | if (XFS_IFORK_Q(ip) || !ip->i_d.di_anextents) { | ||
| 1137 | error = -ENOENT; | ||
| 1138 | goto out_unlock; | ||
| 1139 | } | ||
| 1140 | |||
| 1141 | ASSERT(ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL); | ||
| 1142 | error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb, &imap, | ||
| 1143 | &nimaps, XFS_BMAPI_ENTIRE | XFS_BMAPI_ATTRFORK); | ||
| 1144 | out_unlock: | ||
| 1145 | xfs_iunlock(ip, lockmode); | ||
| 1146 | |||
| 1147 | if (!error) { | ||
| 1148 | ASSERT(nimaps); | ||
| 1149 | xfs_bmbt_to_iomap(ip, iomap, &imap); | ||
| 1150 | } | ||
| 1151 | |||
| 1152 | return error; | ||
| 1153 | } | ||
| 1154 | |||
| 1155 | struct iomap_ops xfs_xattr_iomap_ops = { | ||
| 1156 | .iomap_begin = xfs_xattr_iomap_begin, | ||
| 1157 | }; | ||
diff --git a/fs/xfs/xfs_iomap.h b/fs/xfs/xfs_iomap.h index e066d045e2ff..fb8aca3d69ab 100644 --- a/fs/xfs/xfs_iomap.h +++ b/fs/xfs/xfs_iomap.h | |||
| @@ -35,5 +35,6 @@ void xfs_bmbt_to_iomap(struct xfs_inode *, struct iomap *, | |||
| 35 | struct xfs_bmbt_irec *); | 35 | struct xfs_bmbt_irec *); |
| 36 | 36 | ||
| 37 | extern struct iomap_ops xfs_iomap_ops; | 37 | extern struct iomap_ops xfs_iomap_ops; |
| 38 | extern struct iomap_ops xfs_xattr_iomap_ops; | ||
| 38 | 39 | ||
| 39 | #endif /* __XFS_IOMAP_H__*/ | 40 | #endif /* __XFS_IOMAP_H__*/ |
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index ab820f84ed50..b24c3102fa93 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c | |||
| @@ -1009,7 +1009,14 @@ xfs_vn_fiemap( | |||
| 1009 | int error; | 1009 | int error; |
| 1010 | 1010 | ||
| 1011 | xfs_ilock(XFS_I(inode), XFS_IOLOCK_SHARED); | 1011 | xfs_ilock(XFS_I(inode), XFS_IOLOCK_SHARED); |
| 1012 | error = iomap_fiemap(inode, fieinfo, start, length, &xfs_iomap_ops); | 1012 | if (fieinfo->fi_flags & FIEMAP_FLAG_XATTR) { |
| 1013 | fieinfo->fi_flags &= ~FIEMAP_FLAG_XATTR; | ||
| 1014 | error = iomap_fiemap(inode, fieinfo, start, length, | ||
| 1015 | &xfs_xattr_iomap_ops); | ||
| 1016 | } else { | ||
| 1017 | error = iomap_fiemap(inode, fieinfo, start, length, | ||
| 1018 | &xfs_iomap_ops); | ||
| 1019 | } | ||
| 1013 | xfs_iunlock(XFS_I(inode), XFS_IOLOCK_SHARED); | 1020 | xfs_iunlock(XFS_I(inode), XFS_IOLOCK_SHARED); |
| 1014 | 1021 | ||
| 1015 | return error; | 1022 | return error; |
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index 24ef83ef04de..fd6be45b3a1e 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c | |||
| @@ -1574,9 +1574,16 @@ xfs_fs_fill_super( | |||
| 1574 | } | 1574 | } |
| 1575 | } | 1575 | } |
| 1576 | 1576 | ||
| 1577 | if (xfs_sb_version_hasrmapbt(&mp->m_sb)) | 1577 | if (xfs_sb_version_hasrmapbt(&mp->m_sb)) { |
| 1578 | if (mp->m_sb.sb_rblocks) { | ||
| 1579 | xfs_alert(mp, | ||
| 1580 | "EXPERIMENTAL reverse mapping btree not compatible with realtime device!"); | ||
| 1581 | error = -EINVAL; | ||
| 1582 | goto out_filestream_unmount; | ||
| 1583 | } | ||
| 1578 | xfs_alert(mp, | 1584 | xfs_alert(mp, |
| 1579 | "EXPERIMENTAL reverse mapping btree feature enabled. Use at your own risk!"); | 1585 | "EXPERIMENTAL reverse mapping btree feature enabled. Use at your own risk!"); |
| 1586 | } | ||
| 1580 | 1587 | ||
| 1581 | error = xfs_mountfs(mp); | 1588 | error = xfs_mountfs(mp); |
| 1582 | if (error) | 1589 | if (error) |
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 551b7e26980c..d303a665dba9 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h | |||
| @@ -1298,7 +1298,6 @@ DEFINE_IOMAP_EVENT(xfs_get_blocks_alloc); | |||
| 1298 | DEFINE_IOMAP_EVENT(xfs_get_blocks_map_direct); | 1298 | DEFINE_IOMAP_EVENT(xfs_get_blocks_map_direct); |
| 1299 | DEFINE_IOMAP_EVENT(xfs_iomap_alloc); | 1299 | DEFINE_IOMAP_EVENT(xfs_iomap_alloc); |
| 1300 | DEFINE_IOMAP_EVENT(xfs_iomap_found); | 1300 | DEFINE_IOMAP_EVENT(xfs_iomap_found); |
| 1301 | DEFINE_IOMAP_EVENT(xfs_iomap_not_found); | ||
| 1302 | 1301 | ||
| 1303 | DECLARE_EVENT_CLASS(xfs_simple_io_class, | 1302 | DECLARE_EVENT_CLASS(xfs_simple_io_class, |
| 1304 | TP_PROTO(struct xfs_inode *ip, xfs_off_t offset, ssize_t count), | 1303 | TP_PROTO(struct xfs_inode *ip, xfs_off_t offset, ssize_t count), |
| @@ -2296,7 +2295,7 @@ DECLARE_EVENT_CLASS(xfs_defer_pending_class, | |||
| 2296 | __entry->dev = mp ? mp->m_super->s_dev : 0; | 2295 | __entry->dev = mp ? mp->m_super->s_dev : 0; |
| 2297 | __entry->type = dfp->dfp_type->type; | 2296 | __entry->type = dfp->dfp_type->type; |
| 2298 | __entry->intent = dfp->dfp_intent; | 2297 | __entry->intent = dfp->dfp_intent; |
| 2299 | __entry->committed = dfp->dfp_committed; | 2298 | __entry->committed = dfp->dfp_done != NULL; |
| 2300 | __entry->nr = dfp->dfp_count; | 2299 | __entry->nr = dfp->dfp_count; |
| 2301 | ), | 2300 | ), |
| 2302 | TP_printk("dev %d:%d optype %d intent %p committed %d nr %d\n", | 2301 | TP_printk("dev %d:%d optype %d intent %p committed %d nr %d\n", |
