diff options
Diffstat (limited to 'fs/ext4/inode.c')
-rw-r--r-- | fs/ext4/inode.c | 107 |
1 files changed, 53 insertions, 54 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index bbfabf876e78..7dd9b50d5ebc 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -892,7 +892,16 @@ out: | |||
892 | return err; | 892 | return err; |
893 | } | 893 | } |
894 | 894 | ||
895 | #define DIO_CREDITS (EXT4_RESERVE_TRANS_BLOCKS + 32) | 895 | /* Maximum number of blocks we map for direct IO at once. */ |
896 | #define DIO_MAX_BLOCKS 4096 | ||
897 | /* | ||
898 | * Number of credits we need for writing DIO_MAX_BLOCKS: | ||
899 | * We need sb + group descriptor + bitmap + inode -> 4 | ||
900 | * For B blocks with A block pointers per block we need: | ||
901 | * 1 (triple ind.) + (B/A/A + 2) (doubly ind.) + (B/A + 2) (indirect). | ||
902 | * If we plug in 4096 for B and 256 for A (for 1KB block size), we get 25. | ||
903 | */ | ||
904 | #define DIO_CREDITS 25 | ||
896 | 905 | ||
897 | int ext4_get_blocks_wrap(handle_t *handle, struct inode *inode, sector_t block, | 906 | int ext4_get_blocks_wrap(handle_t *handle, struct inode *inode, sector_t block, |
898 | unsigned long max_blocks, struct buffer_head *bh, | 907 | unsigned long max_blocks, struct buffer_head *bh, |
@@ -939,49 +948,31 @@ static int ext4_get_block(struct inode *inode, sector_t iblock, | |||
939 | struct buffer_head *bh_result, int create) | 948 | struct buffer_head *bh_result, int create) |
940 | { | 949 | { |
941 | handle_t *handle = ext4_journal_current_handle(); | 950 | handle_t *handle = ext4_journal_current_handle(); |
942 | int ret = 0; | 951 | int ret = 0, started = 0; |
943 | unsigned max_blocks = bh_result->b_size >> inode->i_blkbits; | 952 | unsigned max_blocks = bh_result->b_size >> inode->i_blkbits; |
944 | 953 | ||
945 | if (!create) | 954 | if (create && !handle) { |
946 | goto get_block; /* A read */ | 955 | /* Direct IO write... */ |
947 | 956 | if (max_blocks > DIO_MAX_BLOCKS) | |
948 | if (max_blocks == 1) | 957 | max_blocks = DIO_MAX_BLOCKS; |
949 | goto get_block; /* A single block get */ | 958 | handle = ext4_journal_start(inode, DIO_CREDITS + |
950 | 959 | 2 * EXT4_QUOTA_TRANS_BLOCKS(inode->i_sb)); | |
951 | if (handle->h_transaction->t_state == T_LOCKED) { | 960 | if (IS_ERR(handle)) { |
952 | /* | ||
953 | * Huge direct-io writes can hold off commits for long | ||
954 | * periods of time. Let this commit run. | ||
955 | */ | ||
956 | ext4_journal_stop(handle); | ||
957 | handle = ext4_journal_start(inode, DIO_CREDITS); | ||
958 | if (IS_ERR(handle)) | ||
959 | ret = PTR_ERR(handle); | 961 | ret = PTR_ERR(handle); |
960 | goto get_block; | 962 | goto out; |
961 | } | ||
962 | |||
963 | if (handle->h_buffer_credits <= EXT4_RESERVE_TRANS_BLOCKS) { | ||
964 | /* | ||
965 | * Getting low on buffer credits... | ||
966 | */ | ||
967 | ret = ext4_journal_extend(handle, DIO_CREDITS); | ||
968 | if (ret > 0) { | ||
969 | /* | ||
970 | * Couldn't extend the transaction. Start a new one. | ||
971 | */ | ||
972 | ret = ext4_journal_restart(handle, DIO_CREDITS); | ||
973 | } | 963 | } |
964 | started = 1; | ||
974 | } | 965 | } |
975 | 966 | ||
976 | get_block: | 967 | ret = ext4_get_blocks_wrap(handle, inode, iblock, |
977 | if (ret == 0) { | ||
978 | ret = ext4_get_blocks_wrap(handle, inode, iblock, | ||
979 | max_blocks, bh_result, create, 0); | 968 | max_blocks, bh_result, create, 0); |
980 | if (ret > 0) { | 969 | if (ret > 0) { |
981 | bh_result->b_size = (ret << inode->i_blkbits); | 970 | bh_result->b_size = (ret << inode->i_blkbits); |
982 | ret = 0; | 971 | ret = 0; |
983 | } | ||
984 | } | 972 | } |
973 | if (started) | ||
974 | ext4_journal_stop(handle); | ||
975 | out: | ||
985 | return ret; | 976 | return ret; |
986 | } | 977 | } |
987 | 978 | ||
@@ -1671,7 +1662,8 @@ static int ext4_releasepage(struct page *page, gfp_t wait) | |||
1671 | * if the machine crashes during the write. | 1662 | * if the machine crashes during the write. |
1672 | * | 1663 | * |
1673 | * If the O_DIRECT write is intantiating holes inside i_size and the machine | 1664 | * If the O_DIRECT write is intantiating holes inside i_size and the machine |
1674 | * crashes then stale disk data _may_ be exposed inside the file. | 1665 | * crashes then stale disk data _may_ be exposed inside the file. But current |
1666 | * VFS code falls back into buffered path in that case so we are safe. | ||
1675 | */ | 1667 | */ |
1676 | static ssize_t ext4_direct_IO(int rw, struct kiocb *iocb, | 1668 | static ssize_t ext4_direct_IO(int rw, struct kiocb *iocb, |
1677 | const struct iovec *iov, loff_t offset, | 1669 | const struct iovec *iov, loff_t offset, |
@@ -1680,7 +1672,7 @@ static ssize_t ext4_direct_IO(int rw, struct kiocb *iocb, | |||
1680 | struct file *file = iocb->ki_filp; | 1672 | struct file *file = iocb->ki_filp; |
1681 | struct inode *inode = file->f_mapping->host; | 1673 | struct inode *inode = file->f_mapping->host; |
1682 | struct ext4_inode_info *ei = EXT4_I(inode); | 1674 | struct ext4_inode_info *ei = EXT4_I(inode); |
1683 | handle_t *handle = NULL; | 1675 | handle_t *handle; |
1684 | ssize_t ret; | 1676 | ssize_t ret; |
1685 | int orphan = 0; | 1677 | int orphan = 0; |
1686 | size_t count = iov_length(iov, nr_segs); | 1678 | size_t count = iov_length(iov, nr_segs); |
@@ -1688,17 +1680,21 @@ static ssize_t ext4_direct_IO(int rw, struct kiocb *iocb, | |||
1688 | if (rw == WRITE) { | 1680 | if (rw == WRITE) { |
1689 | loff_t final_size = offset + count; | 1681 | loff_t final_size = offset + count; |
1690 | 1682 | ||
1691 | handle = ext4_journal_start(inode, DIO_CREDITS); | ||
1692 | if (IS_ERR(handle)) { | ||
1693 | ret = PTR_ERR(handle); | ||
1694 | goto out; | ||
1695 | } | ||
1696 | if (final_size > inode->i_size) { | 1683 | if (final_size > inode->i_size) { |
1684 | /* Credits for sb + inode write */ | ||
1685 | handle = ext4_journal_start(inode, 2); | ||
1686 | if (IS_ERR(handle)) { | ||
1687 | ret = PTR_ERR(handle); | ||
1688 | goto out; | ||
1689 | } | ||
1697 | ret = ext4_orphan_add(handle, inode); | 1690 | ret = ext4_orphan_add(handle, inode); |
1698 | if (ret) | 1691 | if (ret) { |
1699 | goto out_stop; | 1692 | ext4_journal_stop(handle); |
1693 | goto out; | ||
1694 | } | ||
1700 | orphan = 1; | 1695 | orphan = 1; |
1701 | ei->i_disksize = inode->i_size; | 1696 | ei->i_disksize = inode->i_size; |
1697 | ext4_journal_stop(handle); | ||
1702 | } | 1698 | } |
1703 | } | 1699 | } |
1704 | 1700 | ||
@@ -1706,18 +1702,21 @@ static ssize_t ext4_direct_IO(int rw, struct kiocb *iocb, | |||
1706 | offset, nr_segs, | 1702 | offset, nr_segs, |
1707 | ext4_get_block, NULL); | 1703 | ext4_get_block, NULL); |
1708 | 1704 | ||
1709 | /* | 1705 | if (orphan) { |
1710 | * Reacquire the handle: ext4_get_block() can restart the transaction | ||
1711 | */ | ||
1712 | handle = ext4_journal_current_handle(); | ||
1713 | |||
1714 | out_stop: | ||
1715 | if (handle) { | ||
1716 | int err; | 1706 | int err; |
1717 | 1707 | ||
1718 | if (orphan && inode->i_nlink) | 1708 | /* Credits for sb + inode write */ |
1709 | handle = ext4_journal_start(inode, 2); | ||
1710 | if (IS_ERR(handle)) { | ||
1711 | /* This is really bad luck. We've written the data | ||
1712 | * but cannot extend i_size. Bail out and pretend | ||
1713 | * the write failed... */ | ||
1714 | ret = PTR_ERR(handle); | ||
1715 | goto out; | ||
1716 | } | ||
1717 | if (inode->i_nlink) | ||
1719 | ext4_orphan_del(handle, inode); | 1718 | ext4_orphan_del(handle, inode); |
1720 | if (orphan && ret > 0) { | 1719 | if (ret > 0) { |
1721 | loff_t end = offset + ret; | 1720 | loff_t end = offset + ret; |
1722 | if (end > inode->i_size) { | 1721 | if (end > inode->i_size) { |
1723 | ei->i_disksize = end; | 1722 | ei->i_disksize = end; |