diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-03-09 21:11:28 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-03-09 21:11:28 -0500 |
| commit | 9db61d6fd65f53eaee13fbb451fd761ce926dea9 (patch) | |
| tree | 253c4d2547e65cdf119b294ba4404696a596d1bf | |
| parent | 794fe7891d77fb9ee095313c60805a8ed609e2a7 (diff) | |
| parent | 2fcc319d2467a5f5b78f35f79fd6e22741a31b1e (diff) | |
Merge tag 'xfs-4.11-fixes-1' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
Pull xfs fixes from Darrick Wong:
"Here are some bug fixes for -rc2 to clean up the copy on write
handling and to remove a cause of hangs.
- Fix various iomap bugs
- Fix overly aggressive CoW preallocation garbage collection
- Fixes to CoW endio error handling
- Fix some incorrect geometry calculations
- Remove a potential system hang in bulkstat
- Try to allocate blocks more aggressively to reduce ENOSPC errors"
* tag 'xfs-4.11-fixes-1' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux:
xfs: try any AG when allocating the first btree block when reflinking
xfs: use iomap new flag for newly allocated delalloc blocks
xfs: remove kmem_zalloc_greedy
xfs: Use xfs_icluster_size_fsb() to calculate inode alignment mask
xfs: fix and streamline error handling in xfs_end_io
xfs: only reclaim unwritten COW extents periodically
iomap: invalidate page caches should be after iomap_dio_complete() in direct write
| -rw-r--r-- | fs/iomap.c | 17 | ||||
| -rw-r--r-- | fs/xfs/kmem.c | 18 | ||||
| -rw-r--r-- | fs/xfs/kmem.h | 2 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_bmap.c | 34 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_bmap_btree.c | 6 | ||||
| -rw-r--r-- | fs/xfs/xfs_aops.c | 59 | ||||
| -rw-r--r-- | fs/xfs/xfs_icache.c | 2 | ||||
| -rw-r--r-- | fs/xfs/xfs_inode.c | 2 | ||||
| -rw-r--r-- | fs/xfs/xfs_iomap.c | 25 | ||||
| -rw-r--r-- | fs/xfs/xfs_itable.c | 6 | ||||
| -rw-r--r-- | fs/xfs/xfs_mount.c | 3 | ||||
| -rw-r--r-- | fs/xfs/xfs_reflink.c | 23 | ||||
| -rw-r--r-- | fs/xfs/xfs_reflink.h | 4 | ||||
| -rw-r--r-- | fs/xfs/xfs_super.c | 2 |
14 files changed, 103 insertions, 100 deletions
diff --git a/fs/iomap.c b/fs/iomap.c index 3ca1a8e44135..141c3cd55a8b 100644 --- a/fs/iomap.c +++ b/fs/iomap.c | |||
| @@ -846,7 +846,8 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter, | |||
| 846 | struct address_space *mapping = iocb->ki_filp->f_mapping; | 846 | struct address_space *mapping = iocb->ki_filp->f_mapping; |
| 847 | struct inode *inode = file_inode(iocb->ki_filp); | 847 | struct inode *inode = file_inode(iocb->ki_filp); |
| 848 | size_t count = iov_iter_count(iter); | 848 | size_t count = iov_iter_count(iter); |
| 849 | loff_t pos = iocb->ki_pos, end = iocb->ki_pos + count - 1, ret = 0; | 849 | loff_t pos = iocb->ki_pos, start = pos; |
| 850 | loff_t end = iocb->ki_pos + count - 1, ret = 0; | ||
| 850 | unsigned int flags = IOMAP_DIRECT; | 851 | unsigned int flags = IOMAP_DIRECT; |
| 851 | struct blk_plug plug; | 852 | struct blk_plug plug; |
| 852 | struct iomap_dio *dio; | 853 | struct iomap_dio *dio; |
| @@ -887,12 +888,12 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter, | |||
| 887 | } | 888 | } |
| 888 | 889 | ||
| 889 | if (mapping->nrpages) { | 890 | if (mapping->nrpages) { |
| 890 | ret = filemap_write_and_wait_range(mapping, iocb->ki_pos, end); | 891 | ret = filemap_write_and_wait_range(mapping, start, end); |
| 891 | if (ret) | 892 | if (ret) |
| 892 | goto out_free_dio; | 893 | goto out_free_dio; |
| 893 | 894 | ||
| 894 | ret = invalidate_inode_pages2_range(mapping, | 895 | ret = invalidate_inode_pages2_range(mapping, |
| 895 | iocb->ki_pos >> PAGE_SHIFT, end >> PAGE_SHIFT); | 896 | start >> PAGE_SHIFT, end >> PAGE_SHIFT); |
| 896 | WARN_ON_ONCE(ret); | 897 | WARN_ON_ONCE(ret); |
| 897 | ret = 0; | 898 | ret = 0; |
| 898 | } | 899 | } |
| @@ -941,6 +942,8 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter, | |||
| 941 | __set_current_state(TASK_RUNNING); | 942 | __set_current_state(TASK_RUNNING); |
| 942 | } | 943 | } |
| 943 | 944 | ||
| 945 | ret = iomap_dio_complete(dio); | ||
| 946 | |||
| 944 | /* | 947 | /* |
| 945 | * Try again to invalidate clean pages which might have been cached by | 948 | * Try again to invalidate clean pages which might have been cached by |
| 946 | * non-direct readahead, or faulted in by get_user_pages() if the source | 949 | * non-direct readahead, or faulted in by get_user_pages() if the source |
| @@ -949,12 +952,12 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter, | |||
| 949 | * this invalidation fails, tough, the write still worked... | 952 | * this invalidation fails, tough, the write still worked... |
| 950 | */ | 953 | */ |
| 951 | if (iov_iter_rw(iter) == WRITE && mapping->nrpages) { | 954 | if (iov_iter_rw(iter) == WRITE && mapping->nrpages) { |
| 952 | ret = invalidate_inode_pages2_range(mapping, | 955 | int err = invalidate_inode_pages2_range(mapping, |
| 953 | iocb->ki_pos >> PAGE_SHIFT, end >> PAGE_SHIFT); | 956 | start >> PAGE_SHIFT, end >> PAGE_SHIFT); |
| 954 | WARN_ON_ONCE(ret); | 957 | WARN_ON_ONCE(err); |
| 955 | } | 958 | } |
| 956 | 959 | ||
| 957 | return iomap_dio_complete(dio); | 960 | return ret; |
| 958 | 961 | ||
| 959 | out_free_dio: | 962 | out_free_dio: |
| 960 | kfree(dio); | 963 | kfree(dio); |
diff --git a/fs/xfs/kmem.c b/fs/xfs/kmem.c index 2dfdc62f795e..70a5b55e0870 100644 --- a/fs/xfs/kmem.c +++ b/fs/xfs/kmem.c | |||
| @@ -25,24 +25,6 @@ | |||
| 25 | #include "kmem.h" | 25 | #include "kmem.h" |
| 26 | #include "xfs_message.h" | 26 | #include "xfs_message.h" |
| 27 | 27 | ||
| 28 | /* | ||
| 29 | * Greedy allocation. May fail and may return vmalloced memory. | ||
| 30 | */ | ||
| 31 | void * | ||
| 32 | kmem_zalloc_greedy(size_t *size, size_t minsize, size_t maxsize) | ||
| 33 | { | ||
| 34 | void *ptr; | ||
| 35 | size_t kmsize = maxsize; | ||
| 36 | |||
| 37 | while (!(ptr = vzalloc(kmsize))) { | ||
| 38 | if ((kmsize >>= 1) <= minsize) | ||
| 39 | kmsize = minsize; | ||
| 40 | } | ||
| 41 | if (ptr) | ||
| 42 | *size = kmsize; | ||
| 43 | return ptr; | ||
| 44 | } | ||
| 45 | |||
| 46 | void * | 28 | void * |
| 47 | kmem_alloc(size_t size, xfs_km_flags_t flags) | 29 | kmem_alloc(size_t size, xfs_km_flags_t flags) |
| 48 | { | 30 | { |
diff --git a/fs/xfs/kmem.h b/fs/xfs/kmem.h index 689f746224e7..f0fc84fcaac2 100644 --- a/fs/xfs/kmem.h +++ b/fs/xfs/kmem.h | |||
| @@ -69,8 +69,6 @@ static inline void kmem_free(const void *ptr) | |||
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | 71 | ||
| 72 | extern void *kmem_zalloc_greedy(size_t *, size_t, size_t); | ||
| 73 | |||
| 74 | static inline void * | 72 | static inline void * |
| 75 | kmem_zalloc(size_t size, xfs_km_flags_t flags) | 73 | kmem_zalloc(size_t size, xfs_km_flags_t flags) |
| 76 | { | 74 | { |
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index a9c66d47757a..9bd104f32908 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c | |||
| @@ -763,8 +763,8 @@ xfs_bmap_extents_to_btree( | |||
| 763 | args.type = XFS_ALLOCTYPE_START_BNO; | 763 | args.type = XFS_ALLOCTYPE_START_BNO; |
| 764 | args.fsbno = XFS_INO_TO_FSB(mp, ip->i_ino); | 764 | args.fsbno = XFS_INO_TO_FSB(mp, ip->i_ino); |
| 765 | } else if (dfops->dop_low) { | 765 | } else if (dfops->dop_low) { |
| 766 | try_another_ag: | ||
| 767 | args.type = XFS_ALLOCTYPE_START_BNO; | 766 | args.type = XFS_ALLOCTYPE_START_BNO; |
| 767 | try_another_ag: | ||
| 768 | args.fsbno = *firstblock; | 768 | args.fsbno = *firstblock; |
| 769 | } else { | 769 | } else { |
| 770 | args.type = XFS_ALLOCTYPE_NEAR_BNO; | 770 | args.type = XFS_ALLOCTYPE_NEAR_BNO; |
| @@ -790,13 +790,17 @@ try_another_ag: | |||
| 790 | if (xfs_sb_version_hasreflink(&cur->bc_mp->m_sb) && | 790 | if (xfs_sb_version_hasreflink(&cur->bc_mp->m_sb) && |
| 791 | args.fsbno == NULLFSBLOCK && | 791 | args.fsbno == NULLFSBLOCK && |
| 792 | args.type == XFS_ALLOCTYPE_NEAR_BNO) { | 792 | args.type == XFS_ALLOCTYPE_NEAR_BNO) { |
| 793 | dfops->dop_low = true; | 793 | args.type = XFS_ALLOCTYPE_FIRST_AG; |
| 794 | goto try_another_ag; | 794 | goto try_another_ag; |
| 795 | } | 795 | } |
| 796 | if (WARN_ON_ONCE(args.fsbno == NULLFSBLOCK)) { | ||
| 797 | xfs_iroot_realloc(ip, -1, whichfork); | ||
| 798 | xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); | ||
| 799 | return -ENOSPC; | ||
| 800 | } | ||
| 796 | /* | 801 | /* |
| 797 | * Allocation can't fail, the space was reserved. | 802 | * Allocation can't fail, the space was reserved. |
| 798 | */ | 803 | */ |
| 799 | ASSERT(args.fsbno != NULLFSBLOCK); | ||
| 800 | ASSERT(*firstblock == NULLFSBLOCK || | 804 | ASSERT(*firstblock == NULLFSBLOCK || |
| 801 | args.agno >= XFS_FSB_TO_AGNO(mp, *firstblock)); | 805 | args.agno >= XFS_FSB_TO_AGNO(mp, *firstblock)); |
| 802 | *firstblock = cur->bc_private.b.firstblock = args.fsbno; | 806 | *firstblock = cur->bc_private.b.firstblock = args.fsbno; |
| @@ -4150,6 +4154,19 @@ xfs_bmapi_read( | |||
| 4150 | return 0; | 4154 | return 0; |
| 4151 | } | 4155 | } |
| 4152 | 4156 | ||
| 4157 | /* | ||
| 4158 | * Add a delayed allocation extent to an inode. Blocks are reserved from the | ||
| 4159 | * global pool and the extent inserted into the inode in-core extent tree. | ||
| 4160 | * | ||
| 4161 | * On entry, got refers to the first extent beyond the offset of the extent to | ||
| 4162 | * allocate or eof is specified if no such extent exists. On return, got refers | ||
| 4163 | * to the extent record that was inserted to the inode fork. | ||
| 4164 | * | ||
| 4165 | * Note that the allocated extent may have been merged with contiguous extents | ||
| 4166 | * during insertion into the inode fork. Thus, got does not reflect the current | ||
| 4167 | * state of the inode fork on return. If necessary, the caller can use lastx to | ||
| 4168 | * look up the updated record in the inode fork. | ||
| 4169 | */ | ||
| 4153 | int | 4170 | int |
| 4154 | xfs_bmapi_reserve_delalloc( | 4171 | xfs_bmapi_reserve_delalloc( |
| 4155 | struct xfs_inode *ip, | 4172 | struct xfs_inode *ip, |
| @@ -4236,13 +4253,8 @@ xfs_bmapi_reserve_delalloc( | |||
| 4236 | got->br_startblock = nullstartblock(indlen); | 4253 | got->br_startblock = nullstartblock(indlen); |
| 4237 | got->br_blockcount = alen; | 4254 | got->br_blockcount = alen; |
| 4238 | got->br_state = XFS_EXT_NORM; | 4255 | got->br_state = XFS_EXT_NORM; |
| 4239 | xfs_bmap_add_extent_hole_delay(ip, whichfork, lastx, got); | ||
| 4240 | 4256 | ||
| 4241 | /* | 4257 | xfs_bmap_add_extent_hole_delay(ip, whichfork, lastx, got); |
| 4242 | * Update our extent pointer, given that xfs_bmap_add_extent_hole_delay | ||
| 4243 | * might have merged it into one of the neighbouring ones. | ||
| 4244 | */ | ||
| 4245 | xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *lastx), got); | ||
| 4246 | 4258 | ||
| 4247 | /* | 4259 | /* |
| 4248 | * Tag the inode if blocks were preallocated. Note that COW fork | 4260 | * Tag the inode if blocks were preallocated. Note that COW fork |
| @@ -4254,10 +4266,6 @@ xfs_bmapi_reserve_delalloc( | |||
| 4254 | if (whichfork == XFS_COW_FORK && (prealloc || aoff < off || alen > len)) | 4266 | if (whichfork == XFS_COW_FORK && (prealloc || aoff < off || alen > len)) |
