aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext3
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext3')
-rw-r--r--fs/ext3/inode.c106
1 files changed, 52 insertions, 54 deletions
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index a4f2d673d382..8a9ce2d09bde 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -939,55 +939,45 @@ out:
939 return err; 939 return err;
940} 940}
941 941
942#define DIO_CREDITS (EXT3_RESERVE_TRANS_BLOCKS + 32) 942/* Maximum number of blocks we map for direct IO at once. */
943#define DIO_MAX_BLOCKS 4096
944/*
945 * Number of credits we need for writing DIO_MAX_BLOCKS:
946 * We need sb + group descriptor + bitmap + inode -> 4
947 * For B blocks with A block pointers per block we need:
948 * 1 (triple ind.) + (B/A/A + 2) (doubly ind.) + (B/A + 2) (indirect).
949 * If we plug in 4096 for B and 256 for A (for 1KB block size), we get 25.
950 */
951#define DIO_CREDITS 25
943 952
944static int ext3_get_block(struct inode *inode, sector_t iblock, 953static int ext3_get_block(struct inode *inode, sector_t iblock,
945 struct buffer_head *bh_result, int create) 954 struct buffer_head *bh_result, int create)
946{ 955{
947 handle_t *handle = ext3_journal_current_handle(); 956 handle_t *handle = ext3_journal_current_handle();
948 int ret = 0; 957 int ret = 0, started = 0;
949 unsigned max_blocks = bh_result->b_size >> inode->i_blkbits; 958 unsigned max_blocks = bh_result->b_size >> inode->i_blkbits;
950 959
951 if (!create) 960 if (create && !handle) { /* Direct IO write... */
952 goto get_block; /* A read */ 961 if (max_blocks > DIO_MAX_BLOCKS)
953 962 max_blocks = DIO_MAX_BLOCKS;
954 if (max_blocks == 1) 963 handle = ext3_journal_start(inode, DIO_CREDITS +
955 goto get_block; /* A single block get */ 964 2 * EXT3_QUOTA_TRANS_BLOCKS(inode->i_sb));
956 965 if (IS_ERR(handle)) {
957 if (handle->h_transaction->t_state == T_LOCKED) {
958 /*
959 * Huge direct-io writes can hold off commits for long
960 * periods of time. Let this commit run.
961 */
962 ext3_journal_stop(handle);
963 handle = ext3_journal_start(inode, DIO_CREDITS);
964 if (IS_ERR(handle))
965 ret = PTR_ERR(handle); 966 ret = PTR_ERR(handle);
966 goto get_block; 967 goto out;
967 }
968
969 if (handle->h_buffer_credits <= EXT3_RESERVE_TRANS_BLOCKS) {
970 /*
971 * Getting low on buffer credits...
972 */
973 ret = ext3_journal_extend(handle, DIO_CREDITS);
974 if (ret > 0) {
975 /*
976 * Couldn't extend the transaction. Start a new one.
977 */
978 ret = ext3_journal_restart(handle, DIO_CREDITS);
979 } 968 }
969 started = 1;
980 } 970 }
981 971
982get_block: 972 ret = ext3_get_blocks_handle(handle, inode, iblock,
983 if (ret == 0) {
984 ret = ext3_get_blocks_handle(handle, inode, iblock,
985 max_blocks, bh_result, create, 0); 973 max_blocks, bh_result, create, 0);
986 if (ret > 0) { 974 if (ret > 0) {
987 bh_result->b_size = (ret << inode->i_blkbits); 975 bh_result->b_size = (ret << inode->i_blkbits);
988 ret = 0; 976 ret = 0;
989 }
990 } 977 }
978 if (started)
979 ext3_journal_stop(handle);
980out:
991 return ret; 981 return ret;
992} 982}
993 983
@@ -1678,7 +1668,8 @@ static int ext3_releasepage(struct page *page, gfp_t wait)
1678 * if the machine crashes during the write. 1668 * if the machine crashes during the write.
1679 * 1669 *
1680 * If the O_DIRECT write is intantiating holes inside i_size and the machine 1670 * If the O_DIRECT write is intantiating holes inside i_size and the machine
1681 * crashes then stale disk data _may_ be exposed inside the file. 1671 * crashes then stale disk data _may_ be exposed inside the file. But current
1672 * VFS code falls back into buffered path in that case so we are safe.
1682 */ 1673 */
1683static ssize_t ext3_direct_IO(int rw, struct kiocb *iocb, 1674static ssize_t ext3_direct_IO(int rw, struct kiocb *iocb,
1684 const struct iovec *iov, loff_t offset, 1675 const struct iovec *iov, loff_t offset,
@@ -1687,7 +1678,7 @@ static ssize_t ext3_direct_IO(int rw, struct kiocb *iocb,
1687 struct file *file = iocb->ki_filp; 1678 struct file *file = iocb->ki_filp;
1688 struct inode *inode = file->f_mapping->host; 1679 struct inode *inode = file->f_mapping->host;
1689 struct ext3_inode_info *ei = EXT3_I(inode); 1680 struct ext3_inode_info *ei = EXT3_I(inode);
1690 handle_t *handle = NULL; 1681 handle_t *handle;
1691 ssize_t ret; 1682 ssize_t ret;
1692 int orphan = 0; 1683 int orphan = 0;
1693 size_t count = iov_length(iov, nr_segs); 1684 size_t count = iov_length(iov, nr_segs);
@@ -1695,17 +1686,21 @@ static ssize_t ext3_direct_IO(int rw, struct kiocb *iocb,
1695 if (rw == WRITE) { 1686 if (rw == WRITE) {
1696 loff_t final_size = offset + count; 1687 loff_t final_size = offset + count;
1697 1688
1698 handle = ext3_journal_start(inode, DIO_CREDITS);
1699 if (IS_ERR(handle)) {
1700 ret = PTR_ERR(handle);
1701 goto out;
1702 }
1703 if (final_size > inode->i_size) { 1689 if (final_size > inode->i_size) {
1690 /* Credits for sb + inode write */
1691 handle = ext3_journal_start(inode, 2);
1692 if (IS_ERR(handle)) {
1693 ret = PTR_ERR(handle);
1694 goto out;
1695 }
1704 ret = ext3_orphan_add(handle, inode); 1696 ret = ext3_orphan_add(handle, inode);
1705 if (ret) 1697 if (ret) {
1706 goto out_stop; 1698 ext3_journal_stop(handle);
1699 goto out;
1700 }
1707 orphan = 1; 1701 orphan = 1;
1708 ei->i_disksize = inode->i_size; 1702 ei->i_disksize = inode->i_size;
1703 ext3_journal_stop(handle);
1709 } 1704 }
1710 } 1705 }
1711 1706
@@ -1713,18 +1708,21 @@ static ssize_t ext3_direct_IO(int rw, struct kiocb *iocb,
1713 offset, nr_segs, 1708 offset, nr_segs,
1714 ext3_get_block, NULL); 1709 ext3_get_block, NULL);
1715 1710
1716 /* 1711 if (orphan) {
1717 * Reacquire the handle: ext3_get_block() can restart the transaction
1718 */
1719 handle = ext3_journal_current_handle();
1720
1721out_stop:
1722 if (handle) {
1723 int err; 1712 int err;
1724 1713
1725 if (orphan && inode->i_nlink) 1714 /* Credits for sb + inode write */
1715 handle = ext3_journal_start(inode, 2);
1716 if (IS_ERR(handle)) {
1717 /* This is really bad luck. We've written the data
1718 * but cannot extend i_size. Bail out and pretend
1719 * the write failed... */
1720 ret = PTR_ERR(handle);
1721 goto out;
1722 }
1723 if (inode->i_nlink)
1726 ext3_orphan_del(handle, inode); 1724 ext3_orphan_del(handle, inode);
1727 if (orphan && ret > 0) { 1725 if (ret > 0) {
1728 loff_t end = offset + ret; 1726 loff_t end = offset + ret;
1729 if (end > inode->i_size) { 1727 if (end > inode->i_size) {
1730 ei->i_disksize = end; 1728 ei->i_disksize = end;