diff options
author | Christoph Hellwig <hch@lst.de> | 2019-06-28 22:31:38 -0400 |
---|---|---|
committer | Darrick J. Wong <darrick.wong@oracle.com> | 2019-06-30 12:05:17 -0400 |
commit | 73d30d48749f883fbaaf68ef5d774e99ffafda5d (patch) | |
tree | bb1fc3ef60bb74dac86f8db0c3e3a80d95d56e65 | |
parent | fe64e0d26b1c8096073661851edc99d6370f5e96 (diff) |
xfs: remove XFS_TRANS_NOFS
Instead of a magic flag for xfs_trans_alloc, just ensure all callers
that can't relclaim through the file system use memalloc_nofs_save to
set the per-task nofs flag.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
-rw-r--r-- | fs/xfs/libxfs/xfs_shared.h | 1 | ||||
-rw-r--r-- | fs/xfs/xfs_aops.c | 35 | ||||
-rw-r--r-- | fs/xfs/xfs_file.c | 18 | ||||
-rw-r--r-- | fs/xfs/xfs_iomap.c | 2 | ||||
-rw-r--r-- | fs/xfs/xfs_reflink.c | 4 | ||||
-rw-r--r-- | fs/xfs/xfs_trans.c | 4 |
6 files changed, 41 insertions, 23 deletions
diff --git a/fs/xfs/libxfs/xfs_shared.h b/fs/xfs/libxfs/xfs_shared.h index b9094709bc79..c45acbd3add9 100644 --- a/fs/xfs/libxfs/xfs_shared.h +++ b/fs/xfs/libxfs/xfs_shared.h | |||
@@ -65,7 +65,6 @@ void xfs_log_get_max_trans_res(struct xfs_mount *mp, | |||
65 | #define XFS_TRANS_DQ_DIRTY 0x10 /* at least one dquot in trx dirty */ | 65 | #define XFS_TRANS_DQ_DIRTY 0x10 /* at least one dquot in trx dirty */ |
66 | #define XFS_TRANS_RESERVE 0x20 /* OK to use reserved data blocks */ | 66 | #define XFS_TRANS_RESERVE 0x20 /* OK to use reserved data blocks */ |
67 | #define XFS_TRANS_NO_WRITECOUNT 0x40 /* do not elevate SB writecount */ | 67 | #define XFS_TRANS_NO_WRITECOUNT 0x40 /* do not elevate SB writecount */ |
68 | #define XFS_TRANS_NOFS 0x80 /* pass KM_NOFS to kmem_alloc */ | ||
69 | /* | 68 | /* |
70 | * LOWMODE is used by the allocator to activate the lowspace algorithm - when | 69 | * LOWMODE is used by the allocator to activate the lowspace algorithm - when |
71 | * free space is running low the extent allocator may choose to allocate an | 70 | * free space is running low the extent allocator may choose to allocate an |
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 326294a4918f..137b3a273f3d 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c | |||
@@ -133,8 +133,7 @@ xfs_setfilesize_trans_alloc( | |||
133 | struct xfs_trans *tp; | 133 | struct xfs_trans *tp; |
134 | int error; | 134 | int error; |
135 | 135 | ||
136 | error = xfs_trans_alloc(mp, &M_RES(mp)->tr_fsyncts, 0, 0, | 136 | error = xfs_trans_alloc(mp, &M_RES(mp)->tr_fsyncts, 0, 0, 0, &tp); |
137 | XFS_TRANS_NOFS, &tp); | ||
138 | if (error) | 137 | if (error) |
139 | return error; | 138 | return error; |
140 | 139 | ||
@@ -235,9 +234,17 @@ xfs_end_ioend( | |||
235 | struct xfs_inode *ip = XFS_I(ioend->io_inode); | 234 | struct xfs_inode *ip = XFS_I(ioend->io_inode); |
236 | xfs_off_t offset = ioend->io_offset; | 235 | xfs_off_t offset = ioend->io_offset; |
237 | size_t size = ioend->io_size; | 236 | size_t size = ioend->io_size; |
237 | unsigned int nofs_flag; | ||
238 | int error; | 238 | int error; |
239 | 239 | ||
240 | /* | 240 | /* |
241 | * We can allocate memory here while doing writeback on behalf of | ||
242 | * memory reclaim. To avoid memory allocation deadlocks set the | ||
243 | * task-wide nofs context for the following operations. | ||
244 | */ | ||
245 | nofs_flag = memalloc_nofs_save(); | ||
246 | |||
247 | /* | ||
241 | * Just clean up the in-memory strutures if the fs has been shut down. | 248 | * Just clean up the in-memory strutures if the fs has been shut down. |
242 | */ | 249 | */ |
243 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) { | 250 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) { |
@@ -277,6 +284,8 @@ done: | |||
277 | list_del_init(&ioend->io_list); | 284 | list_del_init(&ioend->io_list); |
278 | xfs_destroy_ioend(ioend, error); | 285 | xfs_destroy_ioend(ioend, error); |
279 | } | 286 | } |
287 | |||
288 | memalloc_nofs_restore(nofs_flag); | ||
280 | } | 289 | } |
281 | 290 | ||
282 | /* | 291 | /* |
@@ -637,21 +646,19 @@ xfs_submit_ioend( | |||
637 | struct xfs_ioend *ioend, | 646 | struct xfs_ioend *ioend, |
638 | int status) | 647 | int status) |
639 | { | 648 | { |
649 | unsigned int nofs_flag; | ||
650 | |||
651 | /* | ||
652 | * We can allocate memory here while doing writeback on behalf of | ||
653 | * memory reclaim. To avoid memory allocation deadlocks set the | ||
654 | * task-wide nofs context for the following operations. | ||
655 | */ | ||
656 | nofs_flag = memalloc_nofs_save(); | ||
657 | |||
640 | /* Convert CoW extents to regular */ | 658 | /* Convert CoW extents to regular */ |
641 | if (!status && ioend->io_fork == XFS_COW_FORK) { | 659 | if (!status && ioend->io_fork == XFS_COW_FORK) { |
642 | /* | ||
643 | * Yuk. This can do memory allocation, but is not a | ||
644 | * transactional operation so everything is done in GFP_KERNEL | ||
645 | * context. That can deadlock, because we hold pages in | ||
646 | * writeback state and GFP_KERNEL allocations can block on them. | ||
647 | * Hence we must operate in nofs conditions here. | ||
648 | */ | ||
649 | unsigned nofs_flag; | ||
650 | |||
651 | nofs_flag = memalloc_nofs_save(); | ||
652 | status = xfs_reflink_convert_cow(XFS_I(ioend->io_inode), | 660 | status = xfs_reflink_convert_cow(XFS_I(ioend->io_inode), |
653 | ioend->io_offset, ioend->io_size); | 661 | ioend->io_offset, ioend->io_size); |
654 | memalloc_nofs_restore(nofs_flag); | ||
655 | } | 662 | } |
656 | 663 | ||
657 | /* Reserve log space if we might write beyond the on-disk inode size. */ | 664 | /* Reserve log space if we might write beyond the on-disk inode size. */ |
@@ -662,6 +669,8 @@ xfs_submit_ioend( | |||
662 | !ioend->io_append_trans) | 669 | !ioend->io_append_trans) |
663 | status = xfs_setfilesize_trans_alloc(ioend); | 670 | status = xfs_setfilesize_trans_alloc(ioend); |
664 | 671 | ||
672 | memalloc_nofs_restore(nofs_flag); | ||
673 | |||
665 | ioend->io_bio->bi_private = ioend; | 674 | ioend->io_bio->bi_private = ioend; |
666 | ioend->io_bio->bi_end_io = xfs_end_bio; | 675 | ioend->io_bio->bi_end_io = xfs_end_bio; |
667 | 676 | ||
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 3041b44e38c6..e93bacbd49ae 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c | |||
@@ -374,6 +374,7 @@ xfs_dio_write_end_io( | |||
374 | struct inode *inode = file_inode(iocb->ki_filp); | 374 | struct inode *inode = file_inode(iocb->ki_filp); |
375 | struct xfs_inode *ip = XFS_I(inode); | 375 | struct xfs_inode *ip = XFS_I(inode); |
376 | loff_t offset = iocb->ki_pos; | 376 | loff_t offset = iocb->ki_pos; |
377 | unsigned int nofs_flag; | ||
377 | int error = 0; | 378 | int error = 0; |
378 | 379 | ||
379 | trace_xfs_end_io_direct_write(ip, offset, size); | 380 | trace_xfs_end_io_direct_write(ip, offset, size); |
@@ -390,10 +391,17 @@ xfs_dio_write_end_io( | |||
390 | */ | 391 | */ |
391 | XFS_STATS_ADD(ip->i_mount, xs_write_bytes, size); | 392 | XFS_STATS_ADD(ip->i_mount, xs_write_bytes, size); |
392 | 393 | ||
394 | /* | ||
395 | * We can allocate memory here while doing writeback on behalf of | ||
396 | * memory reclaim. To avoid memory allocation deadlocks set the | ||
397 | * task-wide nofs context for the following operations. | ||
398 | */ | ||
399 | nofs_flag = memalloc_nofs_save(); | ||
400 | |||
393 | if (flags & IOMAP_DIO_COW) { | 401 | if (flags & IOMAP_DIO_COW) { |
394 | error = xfs_reflink_end_cow(ip, offset, size); | 402 | error = xfs_reflink_end_cow(ip, offset, size); |
395 | if (error) | 403 | if (error) |
396 | return error; | 404 | goto out; |
397 | } | 405 | } |
398 | 406 | ||
399 | /* | 407 | /* |
@@ -402,8 +410,10 @@ xfs_dio_write_end_io( | |||
402 | * earlier allows a racing dio read to find unwritten extents before | 410 | * earlier allows a racing dio read to find unwritten extents before |
403 | * they are converted. | 411 | * they are converted. |
404 | */ | 412 | */ |
405 | if (flags & IOMAP_DIO_UNWRITTEN) | 413 | if (flags & IOMAP_DIO_UNWRITTEN) { |
406 | return xfs_iomap_write_unwritten(ip, offset, size, true); | 414 | error = xfs_iomap_write_unwritten(ip, offset, size, true); |
415 | goto out; | ||
416 | } | ||
407 | 417 | ||
408 | /* | 418 | /* |
409 | * We need to update the in-core inode size here so that we don't end up | 419 | * We need to update the in-core inode size here so that we don't end up |
@@ -425,6 +435,8 @@ xfs_dio_write_end_io( | |||
425 | spin_unlock(&ip->i_flags_lock); | 435 | spin_unlock(&ip->i_flags_lock); |
426 | } | 436 | } |
427 | 437 | ||
438 | out: | ||
439 | memalloc_nofs_restore(nofs_flag); | ||
428 | return error; | 440 | return error; |
429 | } | 441 | } |
430 | 442 | ||
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index b1ef32822bb9..3a4310d7cb59 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c | |||
@@ -776,7 +776,7 @@ xfs_iomap_write_unwritten( | |||
776 | * complete here and might deadlock on the iolock. | 776 | * complete here and might deadlock on the iolock. |
777 | */ | 777 | */ |
778 | error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, | 778 | error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, |
779 | XFS_TRANS_RESERVE | XFS_TRANS_NOFS, &tp); | 779 | XFS_TRANS_RESERVE, &tp); |
780 | if (error) | 780 | if (error) |
781 | return error; | 781 | return error; |
782 | 782 | ||
diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index da0ef8483c13..c4ec7afd1170 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c | |||
@@ -561,7 +561,7 @@ xfs_reflink_cancel_cow_range( | |||
561 | 561 | ||
562 | /* Start a rolling transaction to remove the mappings */ | 562 | /* Start a rolling transaction to remove the mappings */ |
563 | error = xfs_trans_alloc(ip->i_mount, &M_RES(ip->i_mount)->tr_write, | 563 | error = xfs_trans_alloc(ip->i_mount, &M_RES(ip->i_mount)->tr_write, |
564 | 0, 0, XFS_TRANS_NOFS, &tp); | 564 | 0, 0, 0, &tp); |
565 | if (error) | 565 | if (error) |
566 | goto out; | 566 | goto out; |
567 | 567 | ||
@@ -620,7 +620,7 @@ xfs_reflink_end_cow_extent( | |||
620 | 620 | ||
621 | resblks = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK); | 621 | resblks = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK); |
622 | error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, | 622 | error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, |
623 | XFS_TRANS_RESERVE | XFS_TRANS_NOFS, &tp); | 623 | XFS_TRANS_RESERVE, &tp); |
624 | if (error) | 624 | if (error) |
625 | return error; | 625 | return error; |
626 | 626 | ||
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index 5b31e0b400f4..d42a68d8313b 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c | |||
@@ -263,9 +263,7 @@ xfs_trans_alloc( | |||
263 | * GFP_NOFS allocation context so that we avoid lockdep false positives | 263 | * GFP_NOFS allocation context so that we avoid lockdep false positives |
264 | * by doing GFP_KERNEL allocations inside sb_start_intwrite(). | 264 | * by doing GFP_KERNEL allocations inside sb_start_intwrite(). |
265 | */ | 265 | */ |
266 | tp = kmem_zone_zalloc(xfs_trans_zone, | 266 | tp = kmem_zone_zalloc(xfs_trans_zone, KM_SLEEP); |
267 | (flags & XFS_TRANS_NOFS) ? KM_NOFS : KM_SLEEP); | ||
268 | |||
269 | if (!(flags & XFS_TRANS_NO_WRITECOUNT)) | 267 | if (!(flags & XFS_TRANS_NO_WRITECOUNT)) |
270 | sb_start_intwrite(mp->m_super); | 268 | sb_start_intwrite(mp->m_super); |
271 | 269 | ||