diff options
| -rw-r--r-- | fs/ext4/inode.c | 115 | ||||
| -rw-r--r-- | fs/ext4/mballoc.c | 164 | ||||
| -rw-r--r-- | fs/ext4/migrate.c | 123 | ||||
| -rw-r--r-- | fs/ext4/namei.c | 1 | ||||
| -rw-r--r-- | fs/ext4/super.c | 11 | ||||
| -rw-r--r-- | fs/jbd/commit.c | 14 | ||||
| -rw-r--r-- | fs/jbd2/commit.c | 10 | ||||
| -rw-r--r-- | fs/jbd2/recovery.c | 2 | ||||
| -rw-r--r-- | include/linux/ext4_fs.h | 7 |
9 files changed, 270 insertions, 177 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index f4e387452246..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; |
| @@ -2758,13 +2757,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) | |||
| 2758 | ei->i_data[block] = raw_inode->i_block[block]; | 2757 | ei->i_data[block] = raw_inode->i_block[block]; |
| 2759 | INIT_LIST_HEAD(&ei->i_orphan); | 2758 | INIT_LIST_HEAD(&ei->i_orphan); |
| 2760 | 2759 | ||
| 2761 | if (inode->i_ino >= EXT4_FIRST_INO(inode->i_sb) + 1 && | 2760 | if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE) { |
| 2762 | EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE) { | ||
| 2763 | /* | ||
| 2764 | * When mke2fs creates big inodes it does not zero out | ||
| 2765 | * the unused bytes above EXT4_GOOD_OLD_INODE_SIZE, | ||
