Merge branch 'tracing-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[firefly-linux-kernel-4.4.55.git] / fs / ext3 / inode.c
index acf1b14233275e891fd5e1d55560fed331add18c..354ed3b47b301dc34fb13c0ace2e5123311a9e89 100644 (file)
@@ -699,8 +699,9 @@ static int ext3_splice_branch(handle_t *handle, struct inode *inode,
        int err = 0;
        struct ext3_block_alloc_info *block_i;
        ext3_fsblk_t current_block;
+       struct ext3_inode_info *ei = EXT3_I(inode);
 
-       block_i = EXT3_I(inode)->i_block_alloc_info;
+       block_i = ei->i_block_alloc_info;
        /*
         * If we're splicing into a [td]indirect block (as opposed to the
         * 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,
 
        inode->i_ctime = CURRENT_TIME_SEC;
        ext3_mark_inode_dirty(handle, inode);
+       /* ext3_mark_inode_dirty already updated i_sync_tid */
+       atomic_set(&ei->i_datasync_tid, handle->h_transaction->t_tid);
 
        /* had we spliced it onto indirect block? */
        if (where->bh) {
@@ -1735,6 +1738,7 @@ static ssize_t ext3_direct_IO(int rw, struct kiocb *iocb,
        ssize_t ret;
        int orphan = 0;
        size_t count = iov_length(iov, nr_segs);
+       int retries = 0;
 
        if (rw == WRITE) {
                loff_t final_size = offset + count;
@@ -1757,9 +1761,12 @@ static ssize_t ext3_direct_IO(int rw, struct kiocb *iocb,
                }
        }
 
+retry:
        ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
                                 offset, nr_segs,
                                 ext3_get_block, NULL);
+       if (ret == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries))
+               goto retry;
 
        if (orphan) {
                int err;
@@ -2750,6 +2757,8 @@ struct inode *ext3_iget(struct super_block *sb, unsigned long ino)
        struct ext3_inode_info *ei;
        struct buffer_head *bh;
        struct inode *inode;
+       journal_t *journal = EXT3_SB(sb)->s_journal;
+       transaction_t *transaction;
        long ret;
        int block;
 
@@ -2827,6 +2836,30 @@ struct inode *ext3_iget(struct super_block *sb, unsigned long ino)
                ei->i_data[block] = raw_inode->i_block[block];
        INIT_LIST_HEAD(&ei->i_orphan);
 
+       /*
+        * Set transaction id's of transactions that have to be committed
+        * to finish f[data]sync. We set them to currently running transaction
+        * as we cannot be sure that the inode or some of its metadata isn't
+        * part of the transaction - the inode could have been reclaimed and
+        * now it is reread from disk.
+        */
+       if (journal) {
+               tid_t tid;
+
+               spin_lock(&journal->j_state_lock);
+               if (journal->j_running_transaction)
+                       transaction = journal->j_running_transaction;
+               else
+                       transaction = journal->j_committing_transaction;
+               if (transaction)
+                       tid = transaction->t_tid;
+               else
+                       tid = journal->j_commit_sequence;
+               spin_unlock(&journal->j_state_lock);
+               atomic_set(&ei->i_sync_tid, tid);
+               atomic_set(&ei->i_datasync_tid, tid);
+       }
+
        if (inode->i_ino >= EXT3_FIRST_INO(inode->i_sb) + 1 &&
            EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) {
                /*
@@ -3011,6 +3044,7 @@ again:
                err = rc;
        ei->i_state &= ~EXT3_STATE_NEW;
 
+       atomic_set(&ei->i_sync_tid, handle->h_transaction->t_tid);
 out_brelse:
        brelse (bh);
        ext3_std_error(inode->i_sb, err);