diff options
Diffstat (limited to 'fs/ext3/inode.c')
-rw-r--r-- | fs/ext3/inode.c | 143 |
1 files changed, 76 insertions, 67 deletions
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 9b162cd6c16c..eb95670a27eb 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c | |||
@@ -439,16 +439,14 @@ static ext3_fsblk_t ext3_find_near(struct inode *inode, Indirect *ind) | |||
439 | * ext3_find_goal - find a prefered place for allocation. | 439 | * ext3_find_goal - find a prefered place for allocation. |
440 | * @inode: owner | 440 | * @inode: owner |
441 | * @block: block we want | 441 | * @block: block we want |
442 | * @chain: chain of indirect blocks | ||
443 | * @partial: pointer to the last triple within a chain | 442 | * @partial: pointer to the last triple within a chain |
444 | * @goal: place to store the result. | ||
445 | * | 443 | * |
446 | * Normally this function find the prefered place for block allocation, | 444 | * Normally this function find the prefered place for block allocation, |
447 | * stores it in *@goal and returns zero. | 445 | * returns it. |
448 | */ | 446 | */ |
449 | 447 | ||
450 | static ext3_fsblk_t ext3_find_goal(struct inode *inode, long block, | 448 | static ext3_fsblk_t ext3_find_goal(struct inode *inode, long block, |
451 | Indirect chain[4], Indirect *partial) | 449 | Indirect *partial) |
452 | { | 450 | { |
453 | struct ext3_block_alloc_info *block_i; | 451 | struct ext3_block_alloc_info *block_i; |
454 | 452 | ||
@@ -884,7 +882,7 @@ int ext3_get_blocks_handle(handle_t *handle, struct inode *inode, | |||
884 | if (S_ISREG(inode->i_mode) && (!ei->i_block_alloc_info)) | 882 | if (S_ISREG(inode->i_mode) && (!ei->i_block_alloc_info)) |
885 | ext3_init_block_alloc_info(inode); | 883 | ext3_init_block_alloc_info(inode); |
886 | 884 | ||
887 | goal = ext3_find_goal(inode, iblock, chain, partial); | 885 | goal = ext3_find_goal(inode, iblock, partial); |
888 | 886 | ||
889 | /* the number of blocks need to allocate for [d,t]indirect blocks */ | 887 | /* the number of blocks need to allocate for [d,t]indirect blocks */ |
890 | indirect_blks = (chain + depth) - partial - 1; | 888 | indirect_blks = (chain + depth) - partial - 1; |
@@ -941,55 +939,45 @@ out: | |||
941 | return err; | 939 | return err; |
942 | } | 940 | } |
943 | 941 | ||
944 | #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 | ||
945 | 952 | ||
946 | static int ext3_get_block(struct inode *inode, sector_t iblock, | 953 | static int ext3_get_block(struct inode *inode, sector_t iblock, |
947 | struct buffer_head *bh_result, int create) | 954 | struct buffer_head *bh_result, int create) |
948 | { | 955 | { |
949 | handle_t *handle = ext3_journal_current_handle(); | 956 | handle_t *handle = ext3_journal_current_handle(); |
950 | int ret = 0; | 957 | int ret = 0, started = 0; |
951 | unsigned max_blocks = bh_result->b_size >> inode->i_blkbits; | 958 | unsigned max_blocks = bh_result->b_size >> inode->i_blkbits; |
952 | 959 | ||
953 | if (!create) | 960 | if (create && !handle) { /* Direct IO write... */ |
954 | goto get_block; /* A read */ | 961 | if (max_blocks > DIO_MAX_BLOCKS) |
955 | 962 | max_blocks = DIO_MAX_BLOCKS; | |
956 | if (max_blocks == 1) | 963 | handle = ext3_journal_start(inode, DIO_CREDITS + |
957 | goto get_block; /* A single block get */ | 964 | 2 * EXT3_QUOTA_TRANS_BLOCKS(inode->i_sb)); |
958 | 965 | if (IS_ERR(handle)) { | |
959 | if (handle->h_transaction->t_state == T_LOCKED) { | ||
960 | /* | ||
961 | * Huge direct-io writes can hold off commits for long | ||
962 | * periods of time. Let this commit run. | ||
963 | */ | ||
964 | ext3_journal_stop(handle); | ||
965 | handle = ext3_journal_start(inode, DIO_CREDITS); | ||
966 | if (IS_ERR(handle)) | ||
967 | ret = PTR_ERR(handle); | 966 | ret = PTR_ERR(handle); |
968 | goto get_block; | 967 | goto out; |
969 | } | ||
970 | |||
971 | if (handle->h_buffer_credits <= EXT3_RESERVE_TRANS_BLOCKS) { | ||
972 | /* | ||
973 | * Getting low on buffer credits... | ||
974 | */ | ||
975 | ret = ext3_journal_extend(handle, DIO_CREDITS); | ||
976 | if (ret > 0) { | ||
977 | /* | ||
978 | * Couldn't extend the transaction. Start a new one. | ||
979 | */ | ||
980 | ret = ext3_journal_restart(handle, DIO_CREDITS); | ||
981 | } | 968 | } |
969 | started = 1; | ||
982 | } | 970 | } |
983 | 971 | ||
984 | get_block: | 972 | ret = ext3_get_blocks_handle(handle, inode, iblock, |
985 | if (ret == 0) { | ||
986 | ret = ext3_get_blocks_handle(handle, inode, iblock, | ||
987 | max_blocks, bh_result, create, 0); | 973 | max_blocks, bh_result, create, 0); |
988 | if (ret > 0) { | 974 | if (ret > 0) { |
989 | bh_result->b_size = (ret << inode->i_blkbits); | 975 | bh_result->b_size = (ret << inode->i_blkbits); |
990 | ret = 0; | 976 | ret = 0; |
991 | } | ||
992 | } | 977 | } |
978 | if (started) | ||
979 | ext3_journal_stop(handle); | ||
980 | out: | ||
993 | return ret; | 981 | return ret; |
994 | } | 982 | } |
995 | 983 | ||
@@ -1680,7 +1668,8 @@ static int ext3_releasepage(struct page *page, gfp_t wait) | |||
1680 | * if the machine crashes during the write. | 1668 | * if the machine crashes during the write. |
1681 | * | 1669 | * |
1682 | * 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 |
1683 | * 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. | ||
1684 | */ | 1673 | */ |
1685 | static ssize_t ext3_direct_IO(int rw, struct kiocb *iocb, | 1674 | static ssize_t ext3_direct_IO(int rw, struct kiocb *iocb, |
1686 | const struct iovec *iov, loff_t offset, | 1675 | const struct iovec *iov, loff_t offset, |
@@ -1689,7 +1678,7 @@ static ssize_t ext3_direct_IO(int rw, struct kiocb *iocb, | |||
1689 | struct file *file = iocb->ki_filp; | 1678 | struct file *file = iocb->ki_filp; |
1690 | struct inode *inode = file->f_mapping->host; | 1679 | struct inode *inode = file->f_mapping->host; |
1691 | struct ext3_inode_info *ei = EXT3_I(inode); | 1680 | struct ext3_inode_info *ei = EXT3_I(inode); |
1692 | handle_t *handle = NULL; | 1681 | handle_t *handle; |
1693 | ssize_t ret; | 1682 | ssize_t ret; |
1694 | int orphan = 0; | 1683 | int orphan = 0; |
1695 | size_t count = iov_length(iov, nr_segs); | 1684 | size_t count = iov_length(iov, nr_segs); |
@@ -1697,17 +1686,21 @@ static ssize_t ext3_direct_IO(int rw, struct kiocb *iocb, | |||
1697 | if (rw == WRITE) { | 1686 | if (rw == WRITE) { |
1698 | loff_t final_size = offset + count; | 1687 | loff_t final_size = offset + count; |
1699 | 1688 | ||
1700 | handle = ext3_journal_start(inode, DIO_CREDITS); | ||
1701 | if (IS_ERR(handle)) { | ||
1702 | ret = PTR_ERR(handle); | ||
1703 | goto out; | ||
1704 | } | ||
1705 | 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 | } | ||
1706 | ret = ext3_orphan_add(handle, inode); | 1696 | ret = ext3_orphan_add(handle, inode); |
1707 | if (ret) | 1697 | if (ret) { |
1708 | goto out_stop; | 1698 | ext3_journal_stop(handle); |
1699 | goto out; | ||
1700 | } | ||
1709 | orphan = 1; | 1701 | orphan = 1; |
1710 | ei->i_disksize = inode->i_size; | 1702 | ei->i_disksize = inode->i_size; |
1703 | ext3_journal_stop(handle); | ||
1711 | } | 1704 | } |
1712 | } | 1705 | } |
1713 | 1706 | ||
@@ -1715,18 +1708,21 @@ static ssize_t ext3_direct_IO(int rw, struct kiocb *iocb, | |||
1715 | offset, nr_segs, | 1708 | offset, nr_segs, |
1716 | ext3_get_block, NULL); | 1709 | ext3_get_block, NULL); |
1717 | 1710 | ||
1718 | /* | 1711 | if (orphan) { |
1719 | * Reacquire the handle: ext3_get_block() can restart the transaction | ||
1720 | */ | ||
1721 | handle = ext3_journal_current_handle(); | ||
1722 | |||
1723 | out_stop: | ||
1724 | if (handle) { | ||
1725 | int err; | 1712 | int err; |
1726 | 1713 | ||
1727 | 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) | ||
1728 | ext3_orphan_del(handle, inode); | 1724 | ext3_orphan_del(handle, inode); |
1729 | if (orphan && ret > 0) { | 1725 | if (ret > 0) { |
1730 | loff_t end = offset + ret; | 1726 | loff_t end = offset + ret; |
1731 | if (end > inode->i_size) { | 1727 | if (end > inode->i_size) { |
1732 | ei->i_disksize = end; | 1728 | ei->i_disksize = end; |
@@ -1845,7 +1841,7 @@ static int ext3_block_truncate_page(handle_t *handle, struct page *page, | |||
1845 | */ | 1841 | */ |
1846 | if (!page_has_buffers(page) && test_opt(inode->i_sb, NOBH) && | 1842 | if (!page_has_buffers(page) && test_opt(inode->i_sb, NOBH) && |
1847 | ext3_should_writeback_data(inode) && PageUptodate(page)) { | 1843 | ext3_should_writeback_data(inode) && PageUptodate(page)) { |
1848 | zero_user_page(page, offset, length, KM_USER0); | 1844 | zero_user(page, offset, length); |
1849 | set_page_dirty(page); | 1845 | set_page_dirty(page); |
1850 | goto unlock; | 1846 | goto unlock; |
1851 | } | 1847 | } |
@@ -1898,7 +1894,7 @@ static int ext3_block_truncate_page(handle_t *handle, struct page *page, | |||
1898 | goto unlock; | 1894 | goto unlock; |
1899 | } | 1895 | } |
1900 | 1896 | ||
1901 | zero_user_page(page, offset, length, KM_USER0); | 1897 | zero_user(page, offset, length); |
1902 | BUFFER_TRACE(bh, "zeroed end of block"); | 1898 | BUFFER_TRACE(bh, "zeroed end of block"); |
1903 | 1899 | ||
1904 | err = 0; | 1900 | err = 0; |
@@ -2658,21 +2654,31 @@ void ext3_get_inode_flags(struct ext3_inode_info *ei) | |||
2658 | ei->i_flags |= EXT3_DIRSYNC_FL; | 2654 | ei->i_flags |= EXT3_DIRSYNC_FL; |
2659 | } | 2655 | } |
2660 | 2656 | ||
2661 | void ext3_read_inode(struct inode * inode) | 2657 | struct inode *ext3_iget(struct super_block *sb, unsigned long ino) |
2662 | { | 2658 | { |
2663 | struct ext3_iloc iloc; | 2659 | struct ext3_iloc iloc; |
2664 | struct ext3_inode *raw_inode; | 2660 | struct ext3_inode *raw_inode; |
2665 | struct ext3_inode_info *ei = EXT3_I(inode); | 2661 | struct ext3_inode_info *ei; |
2666 | struct buffer_head *bh; | 2662 | struct buffer_head *bh; |
2663 | struct inode *inode; | ||
2664 | long ret; | ||
2667 | int block; | 2665 | int block; |
2668 | 2666 | ||
2667 | inode = iget_locked(sb, ino); | ||
2668 | if (!inode) | ||
2669 | return ERR_PTR(-ENOMEM); | ||
2670 | if (!(inode->i_state & I_NEW)) | ||
2671 | return inode; | ||
2672 | |||
2673 | ei = EXT3_I(inode); | ||
2669 | #ifdef CONFIG_EXT3_FS_POSIX_ACL | 2674 | #ifdef CONFIG_EXT3_FS_POSIX_ACL |
2670 | ei->i_acl = EXT3_ACL_NOT_CACHED; | 2675 | ei->i_acl = EXT3_ACL_NOT_CACHED; |
2671 | ei->i_default_acl = EXT3_ACL_NOT_CACHED; | 2676 | ei->i_default_acl = EXT3_ACL_NOT_CACHED; |
2672 | #endif | 2677 | #endif |
2673 | ei->i_block_alloc_info = NULL; | 2678 | ei->i_block_alloc_info = NULL; |
2674 | 2679 | ||
2675 | if (__ext3_get_inode_loc(inode, &iloc, 0)) | 2680 | ret = __ext3_get_inode_loc(inode, &iloc, 0); |
2681 | if (ret < 0) | ||
2676 | goto bad_inode; | 2682 | goto bad_inode; |
2677 | bh = iloc.bh; | 2683 | bh = iloc.bh; |
2678 | raw_inode = ext3_raw_inode(&iloc); | 2684 | raw_inode = ext3_raw_inode(&iloc); |
@@ -2703,6 +2709,7 @@ void ext3_read_inode(struct inode * inode) | |||
2703 | !(EXT3_SB(inode->i_sb)->s_mount_state & EXT3_ORPHAN_FS)) { | 2709 | !(EXT3_SB(inode->i_sb)->s_mount_state & EXT3_ORPHAN_FS)) { |
2704 | /* this inode is deleted */ | 2710 | /* this inode is deleted */ |
2705 | brelse (bh); | 2711 | brelse (bh); |
2712 | ret = -ESTALE; | ||
2706 | goto bad_inode; | 2713 | goto bad_inode; |
2707 | } | 2714 | } |
2708 | /* The only unlinked inodes we let through here have | 2715 | /* The only unlinked inodes we let through here have |
@@ -2746,6 +2753,7 @@ void ext3_read_inode(struct inode * inode) | |||
2746 | if (EXT3_GOOD_OLD_INODE_SIZE + ei->i_extra_isize > | 2753 | if (EXT3_GOOD_OLD_INODE_SIZE + ei->i_extra_isize > |
2747 | EXT3_INODE_SIZE(inode->i_sb)) { | 2754 | EXT3_INODE_SIZE(inode->i_sb)) { |
2748 | brelse (bh); | 2755 | brelse (bh); |
2756 | ret = -EIO; | ||
2749 | goto bad_inode; | 2757 | goto bad_inode; |
2750 | } | 2758 | } |
2751 | if (ei->i_extra_isize == 0) { | 2759 | if (ei->i_extra_isize == 0) { |
@@ -2787,11 +2795,12 @@ void ext3_read_inode(struct inode * inode) | |||
2787 | } | 2795 | } |
2788 | brelse (iloc.bh); | 2796 | brelse (iloc.bh); |
2789 | ext3_set_inode_flags(inode); | 2797 | ext3_set_inode_flags(inode); |
2790 | return; | 2798 | unlock_new_inode(inode); |
2799 | return inode; | ||
2791 | 2800 | ||
2792 | bad_inode: | 2801 | bad_inode: |
2793 | make_bad_inode(inode); | 2802 | iget_failed(inode); |
2794 | return; | 2803 | return ERR_PTR(ret); |
2795 | } | 2804 | } |
2796 | 2805 | ||
2797 | /* | 2806 | /* |