diff options
Diffstat (limited to 'fs/xfs/xfs_file.c')
-rw-r--r-- | fs/xfs/xfs_file.c | 34 |
1 files changed, 20 insertions, 14 deletions
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index bbb9eb6811b2..086440e79b86 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c | |||
@@ -527,6 +527,15 @@ xfs_file_dio_aio_write( | |||
527 | if ((iocb->ki_pos & mp->m_blockmask) || | 527 | if ((iocb->ki_pos & mp->m_blockmask) || |
528 | ((iocb->ki_pos + count) & mp->m_blockmask)) { | 528 | ((iocb->ki_pos + count) & mp->m_blockmask)) { |
529 | unaligned_io = 1; | 529 | unaligned_io = 1; |
530 | |||
531 | /* | ||
532 | * We can't properly handle unaligned direct I/O to reflink | ||
533 | * files yet, as we can't unshare a partial block. | ||
534 | */ | ||
535 | if (xfs_is_reflink_inode(ip)) { | ||
536 | trace_xfs_reflink_bounce_dio_write(ip, iocb->ki_pos, count); | ||
537 | return -EREMCHG; | ||
538 | } | ||
530 | iolock = XFS_IOLOCK_EXCL; | 539 | iolock = XFS_IOLOCK_EXCL; |
531 | } else { | 540 | } else { |
532 | iolock = XFS_IOLOCK_SHARED; | 541 | iolock = XFS_IOLOCK_SHARED; |
@@ -552,14 +561,6 @@ xfs_file_dio_aio_write( | |||
552 | } | 561 | } |
553 | 562 | ||
554 | trace_xfs_file_direct_write(ip, count, iocb->ki_pos); | 563 | trace_xfs_file_direct_write(ip, count, iocb->ki_pos); |
555 | |||
556 | /* If this is a block-aligned directio CoW, remap immediately. */ | ||
557 | if (xfs_is_reflink_inode(ip) && !unaligned_io) { | ||
558 | ret = xfs_reflink_allocate_cow_range(ip, iocb->ki_pos, count); | ||
559 | if (ret) | ||
560 | goto out; | ||
561 | } | ||
562 | |||
563 | ret = iomap_dio_rw(iocb, from, &xfs_iomap_ops, xfs_dio_write_end_io); | 564 | ret = iomap_dio_rw(iocb, from, &xfs_iomap_ops, xfs_dio_write_end_io); |
564 | out: | 565 | out: |
565 | xfs_iunlock(ip, iolock); | 566 | xfs_iunlock(ip, iolock); |
@@ -614,8 +615,10 @@ xfs_file_buffered_aio_write( | |||
614 | struct xfs_inode *ip = XFS_I(inode); | 615 | struct xfs_inode *ip = XFS_I(inode); |
615 | ssize_t ret; | 616 | ssize_t ret; |
616 | int enospc = 0; | 617 | int enospc = 0; |
617 | int iolock = XFS_IOLOCK_EXCL; | 618 | int iolock; |
618 | 619 | ||
620 | write_retry: | ||
621 | iolock = XFS_IOLOCK_EXCL; | ||
619 | xfs_ilock(ip, iolock); | 622 | xfs_ilock(ip, iolock); |
620 | 623 | ||
621 | ret = xfs_file_aio_write_checks(iocb, from, &iolock); | 624 | ret = xfs_file_aio_write_checks(iocb, from, &iolock); |
@@ -625,7 +628,6 @@ xfs_file_buffered_aio_write( | |||
625 | /* We can write back this queue in page reclaim */ | 628 | /* We can write back this queue in page reclaim */ |
626 | current->backing_dev_info = inode_to_bdi(inode); | 629 | current->backing_dev_info = inode_to_bdi(inode); |
627 | 630 | ||
628 | write_retry: | ||
629 | trace_xfs_file_buffered_write(ip, iov_iter_count(from), iocb->ki_pos); | 631 | trace_xfs_file_buffered_write(ip, iov_iter_count(from), iocb->ki_pos); |
630 | ret = iomap_file_buffered_write(iocb, from, &xfs_iomap_ops); | 632 | ret = iomap_file_buffered_write(iocb, from, &xfs_iomap_ops); |
631 | if (likely(ret >= 0)) | 633 | if (likely(ret >= 0)) |
@@ -641,18 +643,21 @@ write_retry: | |||
641 | * running at the same time. | 643 | * running at the same time. |
642 | */ | 644 | */ |
643 | if (ret == -EDQUOT && !enospc) { | 645 | if (ret == -EDQUOT && !enospc) { |
646 | xfs_iunlock(ip, iolock); | ||
644 | enospc = xfs_inode_free_quota_eofblocks(ip); | 647 | enospc = xfs_inode_free_quota_eofblocks(ip); |
645 | if (enospc) | 648 | if (enospc) |
646 | goto write_retry; | 649 | goto write_retry; |
647 | enospc = xfs_inode_free_quota_cowblocks(ip); | 650 | enospc = xfs_inode_free_quota_cowblocks(ip); |
648 | if (enospc) | 651 | if (enospc) |
649 | goto write_retry; | 652 | goto write_retry; |
653 | iolock = 0; | ||
650 | } else if (ret == -ENOSPC && !enospc) { | 654 | } else if (ret == -ENOSPC && !enospc) { |
651 | struct xfs_eofblocks eofb = {0}; | 655 | struct xfs_eofblocks eofb = {0}; |
652 | 656 | ||
653 | enospc = 1; | 657 | enospc = 1; |
654 | xfs_flush_inodes(ip->i_mount); | 658 | xfs_flush_inodes(ip->i_mount); |
655 | eofb.eof_scan_owner = ip->i_ino; /* for locking */ | 659 | |
660 | xfs_iunlock(ip, iolock); | ||
656 | eofb.eof_flags = XFS_EOF_FLAGS_SYNC; | 661 | eofb.eof_flags = XFS_EOF_FLAGS_SYNC; |
657 | xfs_icache_free_eofblocks(ip->i_mount, &eofb); | 662 | xfs_icache_free_eofblocks(ip->i_mount, &eofb); |
658 | goto write_retry; | 663 | goto write_retry; |
@@ -660,7 +665,8 @@ write_retry: | |||
660 | 665 | ||
661 | current->backing_dev_info = NULL; | 666 | current->backing_dev_info = NULL; |
662 | out: | 667 | out: |
663 | xfs_iunlock(ip, iolock); | 668 | if (iolock) |
669 | xfs_iunlock(ip, iolock); | ||
664 | return ret; | 670 | return ret; |
665 | } | 671 | } |
666 | 672 | ||
@@ -908,9 +914,9 @@ xfs_dir_open( | |||
908 | */ | 914 | */ |
909 | mode = xfs_ilock_data_map_shared(ip); | 915 | mode = xfs_ilock_data_map_shared(ip); |
910 | if (ip->i_d.di_nextents > 0) | 916 | if (ip->i_d.di_nextents > 0) |
911 | xfs_dir3_data_readahead(ip, 0, -1); | 917 | error = xfs_dir3_data_readahead(ip, 0, -1); |
912 | xfs_iunlock(ip, mode); | 918 | xfs_iunlock(ip, mode); |
913 | return 0; | 919 | return error; |
914 | } | 920 | } |
915 | 921 | ||
916 | STATIC int | 922 | STATIC int |