diff options
| -rw-r--r-- | fs/ext3/fsync.c | 36 | ||||
| -rw-r--r-- | fs/ext3/inode.c | 36 | ||||
| -rw-r--r-- | fs/ext3/super.c | 2 | ||||
| -rw-r--r-- | fs/jbd/journal.c | 2 | ||||
| -rw-r--r-- | fs/jbd2/journal.c | 2 | ||||
| -rw-r--r-- | include/linux/ext3_fs_i.h | 8 |
6 files changed, 65 insertions, 21 deletions
diff --git a/fs/ext3/fsync.c b/fs/ext3/fsync.c index 451d166bbe93..8209f266e9ad 100644 --- a/fs/ext3/fsync.c +++ b/fs/ext3/fsync.c | |||
| @@ -46,19 +46,21 @@ | |||
| 46 | int ext3_sync_file(struct file * file, struct dentry *dentry, int datasync) | 46 | int ext3_sync_file(struct file * file, struct dentry *dentry, int datasync) |
| 47 | { | 47 | { |
| 48 | struct inode *inode = dentry->d_inode; | 48 | struct inode *inode = dentry->d_inode; |
| 49 | struct ext3_inode_info *ei = EXT3_I(inode); | ||
| 50 | journal_t *journal = EXT3_SB(inode->i_sb)->s_journal; | ||
| 49 | int ret = 0; | 51 | int ret = 0; |
| 52 | tid_t commit_tid; | ||
| 53 | |||
| 54 | if (inode->i_sb->s_flags & MS_RDONLY) | ||
| 55 | return 0; | ||
| 50 | 56 | ||
| 51 | J_ASSERT(ext3_journal_current_handle() == NULL); | 57 | J_ASSERT(ext3_journal_current_handle() == NULL); |
| 52 | 58 | ||
| 53 | /* | 59 | /* |
| 54 | * data=writeback: | 60 | * data=writeback,ordered: |
| 55 | * The caller's filemap_fdatawrite()/wait will sync the data. | 61 | * The caller's filemap_fdatawrite()/wait will sync the data. |
| 56 | * sync_inode() will sync the metadata | 62 | * Metadata is in the journal, we wait for a proper transaction |
| 57 | * | 63 | * to commit here. |
| 58 | * data=ordered: | ||
| 59 | * The caller's filemap_fdatawrite() will write the data and | ||
| 60 | * sync_inode() will write the inode if it is dirty. Then the caller's | ||
| 61 | * filemap_fdatawait() will wait on the pages. | ||
| 62 | * | 64 | * |
| 63 | * data=journal: | 65 | * data=journal: |
| 64 | * filemap_fdatawrite won't do anything (the buffers are clean). | 66 | * filemap_fdatawrite won't do anything (the buffers are clean). |
| @@ -73,22 +75,16 @@ int ext3_sync_file(struct file * file, struct dentry *dentry, int datasync) | |||
| 73 | goto out; | 75 | goto out; |
| 74 | } | 76 | } |
| 75 | 77 | ||
| 76 | if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) | 78 | if (datasync) |
| 77 | goto flush; | 79 | commit_tid = atomic_read(&ei->i_datasync_tid); |
| 80 | else | ||
| 81 | commit_tid = atomic_read(&ei->i_sync_tid); | ||
| 78 | 82 | ||
| 79 | /* | 83 | if (log_start_commit(journal, commit_tid)) { |
| 80 | * The VFS has written the file data. If the inode is unaltered | 84 | log_wait_commit(journal, commit_tid); |
| 81 | * then we need not start a commit. | ||
| 82 | */ | ||
| 83 | if (inode->i_state & (I_DIRTY_SYNC|I_DIRTY_DATASYNC)) { | ||
| 84 | struct writeback_control wbc = { | ||
| 85 | .sync_mode = WB_SYNC_ALL, | ||
| 86 | .nr_to_write = 0, /* sys_fsync did this */ | ||
| 87 | }; | ||
| 88 | ret = sync_inode(inode, &wbc); | ||
| 89 | goto out; | 85 | goto out; |
| 90 | } | 86 | } |
| 91 | flush: | 87 | |
| 92 | /* | 88 | /* |
| 93 | * In case we didn't commit a transaction, we have to flush | 89 | * In case we didn't commit a transaction, we have to flush |
| 94 | * disk caches manually so that data really is on persistent | 90 | * disk caches manually so that data really is on persistent |
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index acf1b1423327..354ed3b47b30 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c | |||
| @@ -699,8 +699,9 @@ static int ext3_splice_branch(handle_t *handle, struct inode *inode, | |||
| 699 | int err = 0; | 699 | int err = 0; |
| 700 | struct ext3_block_alloc_info *block_i; | 700 | struct ext3_block_alloc_info *block_i; |
| 701 | ext3_fsblk_t current_block; | 701 | ext3_fsblk_t current_block; |
| 702 | struct ext3_inode_info *ei = EXT3_I(inode); | ||
| 702 | 703 | ||
| 703 | block_i = EXT3_I(inode)->i_block_alloc_info; | 704 | block_i = ei->i_block_alloc_info; |
| 704 | /* | 705 | /* |
| 705 | * If we're splicing into a [td]indirect block (as opposed to the | 706 | * If we're splicing into a [td]indirect block (as opposed to the |
| 706 | * inode) then we need to get write access to the [td]indirect block | 707 | * inode) then we need to get write access to the [td]indirect block |
| @@ -741,6 +742,8 @@ static int ext3_splice_branch(handle_t *handle, struct inode *inode, | |||
| 741 | 742 | ||
| 742 | inode->i_ctime = CURRENT_TIME_SEC; | 743 | inode->i_ctime = CURRENT_TIME_SEC; |
| 743 | ext3_mark_inode_dirty(handle, inode); | 744 | ext3_mark_inode_dirty(handle, inode); |
| 745 | /* ext3_mark_inode_dirty already updated i_sync_tid */ | ||
| 746 | atomic_set(&ei->i_datasync_tid, handle->h_transaction->t_tid); | ||
| 744 | 747 | ||
| 745 | /* had we spliced it onto indirect block? */ | 748 | /* had we spliced it onto indirect block? */ |
| 746 | if (where->bh) { | 749 | if (where->bh) { |
| @@ -1735,6 +1738,7 @@ static ssize_t ext3_direct_IO(int rw, struct kiocb *iocb, | |||
| 1735 | ssize_t ret; | 1738 | ssize_t ret; |
| 1736 | int orphan = 0; | 1739 | int orphan = 0; |
| 1737 | size_t count = iov_length(iov, nr_segs); | 1740 | size_t count = iov_length(iov, nr_segs); |
| 1741 | int retries = 0; | ||
| 1738 | 1742 | ||
| 1739 | if (rw == WRITE) { | 1743 | if (rw == WRITE) { |
| 1740 | loff_t final_size = offset + count; | 1744 | loff_t final_size = offset + count; |
| @@ -1757,9 +1761,12 @@ static ssize_t ext3_direct_IO(int rw, struct kiocb *iocb, | |||
| 1757 | } | 1761 | } |
| 1758 | } | 1762 | } |
| 1759 | 1763 | ||
| 1764 | retry: | ||
| 1760 | ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, | 1765 | ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, |
| 1761 | offset, nr_segs, | 1766 | offset, nr_segs, |
| 1762 | ext3_get_block, NULL); | 1767 | ext3_get_block, NULL); |
| 1768 | if (ret == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries)) | ||
| 1769 | goto retry; | ||
| 1763 | 1770 | ||
| 1764 | if (orphan) { | 1771 | if (orphan) { |
| 1765 | int err; | 1772 | int err; |
| @@ -2750,6 +2757,8 @@ struct inode *ext3_iget(struct super_block *sb, unsigned long ino) | |||
| 2750 | struct ext3_inode_info *ei; | 2757 | struct ext3_inode_info *ei; |
| 2751 | struct buffer_head *bh; | 2758 | struct buffer_head *bh; |
| 2752 | struct inode *inode; | 2759 | struct inode *inode; |
| 2760 | journal_t *journal = EXT3_SB(sb)->s_journal; | ||
| 2761 | transaction_t *transaction; | ||
| 2753 | long ret; | 2762 | long ret; |
| 2754 | int block; | 2763 | int block; |
| 2755 | 2764 | ||
| @@ -2827,6 +2836,30 @@ struct inode *ext3_iget(struct super_block *sb, unsigned long ino) | |||
| 2827 | ei->i_data[block] = raw_inode->i_block[block]; | 2836 | ei->i_data[block] = raw_inode->i_block[block]; |
| 2828 | INIT_LIST_HEAD(&ei->i_orphan); | 2837 | INIT_LIST_HEAD(&ei->i_orphan); |
| 2829 | 2838 | ||
| 2839 | /* | ||
| 2840 | * Set transaction id's of transactions that have to be committed | ||
| 2841 | * to finish f[data]sync. We set them to currently running transaction | ||
| 2842 | * as we cannot be sure that the inode or some of its metadata isn't | ||
| 2843 | * part of the transaction - the inode could have been reclaimed and | ||
| 2844 | * now it is reread from disk. | ||
| 2845 | */ | ||
| 2846 | if (journal) { | ||
| 2847 | tid_t tid; | ||
| 2848 | |||
| 2849 | spin_lock(&journal->j_state_lock); | ||
| 2850 | if (journal->j_running_transaction) | ||
| 2851 | transaction = journal->j_running_transaction; | ||
| 2852 | else | ||
| 2853 | transaction = journal->j_committing_transaction; | ||
| 2854 | if (transaction) | ||
| 2855 | tid = transaction->t_tid; | ||
| 2856 | else | ||
| 2857 | tid = journal->j_commit_sequence; | ||
| 2858 | spin_unlock(&journal->j_state_lock); | ||
| 2859 | atomic_set(&ei->i_sync_tid, tid); | ||
| 2860 | atomic_set(&ei->i_datasync_tid, tid); | ||
| 2861 | } | ||
| 2862 | |||
| 2830 | if (inode->i_ino >= EXT3_FIRST_INO(inode->i_sb) + 1 && | 2863 | if (inode->i_ino >= EXT3_FIRST_INO(inode->i_sb) + 1 && |
| 2831 | EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) { | 2864 | EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) { |
| 2832 | /* | 2865 | /* |
| @@ -3011,6 +3044,7 @@ again: | |||
| 3011 | err = rc; | 3044 | err = rc; |
| 3012 | ei->i_state &= ~EXT3_STATE_NEW; | 3045 | ei->i_state &= ~EXT3_STATE_NEW; |
| 3013 | 3046 | ||
| 3047 | atomic_set(&ei->i_sync_tid, handle->h_transaction->t_tid); | ||
| 3014 | out_brelse: | 3048 | out_brelse: |
| 3015 | brelse (bh); | 3049 | brelse (bh); |
| 3016 | ext3_std_error(inode->i_sb, err); | 3050 | ext3_std_error(inode->i_sb, err); |
diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 7a520a862f49..427496c4767c 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c | |||
| @@ -466,6 +466,8 @@ static struct inode *ext3_alloc_inode(struct super_block *sb) | |||
| 466 | return NULL; | 466 | return NULL; |
| 467 | ei->i_block_alloc_info = NULL; | 467 | ei->i_block_alloc_info = NULL; |
| 468 | ei->vfs_inode.i_version = 1; | 468 | ei->vfs_inode.i_version = 1; |
| 469 | atomic_set(&ei->i_datasync_tid, 0); | ||
| 470 | atomic_set(&ei->i_sync_tid, 0); | ||
| 469 | return &ei->vfs_inode; | 471 | return &ei->vfs_inode; |
| 470 | } | 472 | } |
| 471 | 473 | ||
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c index bd3c073b485d..49d5cd6053c8 100644 --- a/fs/jbd/journal.c +++ b/fs/jbd/journal.c | |||
| @@ -756,6 +756,7 @@ journal_t * journal_init_dev(struct block_device *bdev, | |||
| 756 | 756 | ||
| 757 | return journal; | 757 | return journal; |
| 758 | out_err: | 758 | out_err: |
| 759 | kfree(journal->j_wbuf); | ||
| 759 | kfree(journal); | 760 | kfree(journal); |
| 760 | return NULL; | 761 | return NULL; |
| 761 | } | 762 | } |
| @@ -820,6 +821,7 @@ journal_t * journal_init_inode (struct inode *inode) | |||
| 820 | 821 | ||
| 821 | return journal; | 822 | return journal; |
| 822 | out_err: | 823 | out_err: |
| 824 | kfree(journal->j_wbuf); | ||
| 823 | kfree(journal); | 825 | kfree(journal); |
| 824 | return NULL; | 826 | return NULL; |
| 825 | } | 827 | } |
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index b0ab5219becb..fed85388ee86 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c | |||
| @@ -913,6 +913,7 @@ journal_t * jbd2_journal_init_dev(struct block_device *bdev, | |||
| 913 | 913 | ||
| 914 | return journal; | 914 | return journal; |
| 915 | out_err: | 915 | out_err: |
| 916 | kfree(journal->j_wbuf); | ||
| 916 | jbd2_stats_proc_exit(journal); | 917 | jbd2_stats_proc_exit(journal); |
| 917 | kfree(journal); | 918 | kfree(journal); |
| 918 | return NULL; | 919 | return NULL; |
| @@ -986,6 +987,7 @@ journal_t * jbd2_journal_init_inode (struct inode *inode) | |||
| 986 | 987 | ||
| 987 | return journal; | 988 | return journal; |
| 988 | out_err: | 989 | out_err: |
| 990 | kfree(journal->j_wbuf); | ||
| 989 | jbd2_stats_proc_exit(journal); | 991 | jbd2_stats_proc_exit(journal); |
| 990 | kfree(journal); | 992 | kfree(journal); |
| 991 | return NULL; | 993 | return NULL; |
diff --git a/include/linux/ext3_fs_i.h b/include/linux/ext3_fs_i.h index ca1bfe90004f..93e7428156ba 100644 --- a/include/linux/ext3_fs_i.h +++ b/include/linux/ext3_fs_i.h | |||
| @@ -137,6 +137,14 @@ struct ext3_inode_info { | |||
| 137 | * by other means, so we have truncate_mutex. | 137 | * by other means, so we have truncate_mutex. |
| 138 | */ | 138 | */ |
| 139 | struct mutex truncate_mutex; | 139 | struct mutex truncate_mutex; |
| 140 | |||
| 141 | /* | ||
| 142 | * Transactions that contain inode's metadata needed to complete | ||
| 143 | * fsync and fdatasync, respectively. | ||
| 144 | */ | ||
| 145 | atomic_t i_sync_tid; | ||
| 146 | atomic_t i_datasync_tid; | ||
| 147 | |||
| 140 | struct inode vfs_inode; | 148 | struct inode vfs_inode; |
| 141 | }; | 149 | }; |
| 142 | 150 | ||
