Merge branch 'for-linus-4.3' of git://git.kernel.org/pub/scm/linux/kernel/git/mason...
[linux-2.6-microblaze.git] / fs / btrfs / inode.c
index e33dff3..237da01 100644 (file)
@@ -1845,8 +1845,10 @@ static int __btrfs_submit_bio_done(struct inode *inode, int rw, struct bio *bio,
        int ret;
 
        ret = btrfs_map_bio(root, rw, bio, mirror_num, 1);
-       if (ret)
-               bio_endio(bio, ret);
+       if (ret) {
+               bio->bi_error = ret;
+               bio_endio(bio);
+       }
        return ret;
 }
 
@@ -1906,8 +1908,10 @@ mapit:
        ret = btrfs_map_bio(root, rw, bio, mirror_num, 0);
 
 out:
-       if (ret < 0)
-               bio_endio(bio, ret);
+       if (ret < 0) {
+               bio->bi_error = ret;
+               bio_endio(bio);
+       }
        return ret;
 }
 
@@ -3654,6 +3658,35 @@ cache_index:
                set_bit(BTRFS_INODE_NEEDS_FULL_SYNC,
                        &BTRFS_I(inode)->runtime_flags);
 
+       /*
+        * We don't persist the id of the transaction where an unlink operation
+        * against the inode was last made. So here we assume the inode might
+        * have been evicted, and therefore the exact value of last_unlink_trans
+        * lost, and set it to last_trans to avoid metadata inconsistencies
+        * between the inode and its parent if the inode is fsync'ed and the log
+        * replayed. For example, in the scenario:
+        *
+        * touch mydir/foo
+        * ln mydir/foo mydir/bar
+        * sync
+        * unlink mydir/bar
+        * echo 2 > /proc/sys/vm/drop_caches   # evicts inode
+        * xfs_io -c fsync mydir/foo
+        * <power failure>
+        * mount fs, triggers fsync log replay
+        *
+        * We must make sure that when we fsync our inode foo we also log its
+        * parent inode, otherwise after log replay the parent still has the
+        * dentry with the "bar" name but our inode foo has a link count of 1
+        * and doesn't have an inode ref with the name "bar" anymore.
+        *
+        * Setting last_unlink_trans to last_trans is a pessimistic approach,
+        * but it guarantees correctness at the expense of ocassional full
+        * transaction commits on fsync if our inode is a directory, or if our
+        * inode is not a directory, logging its parent unnecessarily.
+        */
+       BTRFS_I(inode)->last_unlink_trans = BTRFS_I(inode)->last_trans;
+
        path->slots[0]++;
        if (inode->i_nlink != 1 ||
            path->slots[0] >= btrfs_header_nritems(leaf))
@@ -7688,13 +7721,13 @@ struct btrfs_retry_complete {
        int uptodate;
 };
 
-static void btrfs_retry_endio_nocsum(struct bio *bio, int err)
+static void btrfs_retry_endio_nocsum(struct bio *bio)
 {
        struct btrfs_retry_complete *done = bio->bi_private;
        struct bio_vec *bvec;
        int i;
 
-       if (err)
+       if (bio->bi_error)
                goto end;
 
        done->uptodate = 1;
@@ -7743,7 +7776,7 @@ try_again:
        return 0;
 }
 
-static void btrfs_retry_endio(struct bio *bio, int err)
+static void btrfs_retry_endio(struct bio *bio)
 {
        struct btrfs_retry_complete *done = bio->bi_private;
        struct btrfs_io_bio *io_bio = btrfs_io_bio(bio);
@@ -7752,7 +7785,7 @@ static void btrfs_retry_endio(struct bio *bio, int err)
        int ret;
        int i;
 
-       if (err)
+       if (bio->bi_error)
                goto end;
 
        uptodate = 1;
@@ -7835,12 +7868,13 @@ static int btrfs_subio_endio_read(struct inode *inode,
        }
 }
 
-static void btrfs_endio_direct_read(struct bio *bio, int err)
+static void btrfs_endio_direct_read(struct bio *bio)
 {
        struct btrfs_dio_private *dip = bio->bi_private;
        struct inode *inode = dip->inode;
        struct bio *dio_bio;
        struct btrfs_io_bio *io_bio = btrfs_io_bio(bio);
+       int err = bio->bi_error;
 
        if (dip->flags & BTRFS_DIO_ORIG_BIO_SUBMITTED)
                err = btrfs_subio_endio_read(inode, io_bio, err);
@@ -7851,17 +7885,14 @@ static void btrfs_endio_direct_read(struct bio *bio, int err)
 
        kfree(dip);
 
-       /* If we had a csum failure make sure to clear the uptodate flag */
-       if (err)
-               clear_bit(BIO_UPTODATE, &dio_bio->bi_flags);
-       dio_end_io(dio_bio, err);
+       dio_end_io(dio_bio, bio->bi_error);
 
        if (io_bio->end_io)
                io_bio->end_io(io_bio, err);
        bio_put(bio);
 }
 
-static void btrfs_endio_direct_write(struct bio *bio, int err)
+static void btrfs_endio_direct_write(struct bio *bio)
 {
        struct btrfs_dio_private *dip = bio->bi_private;
        struct inode *inode = dip->inode;
@@ -7875,7 +7906,8 @@ static void btrfs_endio_direct_write(struct bio *bio, int err)
 again:
        ret = btrfs_dec_test_first_ordered_pending(inode, &ordered,
                                                   &ordered_offset,
-                                                  ordered_bytes, !err);
+                                                  ordered_bytes,
+                                                  !bio->bi_error);
        if (!ret)
                goto out_test;
 
@@ -7898,10 +7930,7 @@ out_test:
 
        kfree(dip);
 
-       /* If we had an error make sure to clear the uptodate flag */
-       if (err)
-               clear_bit(BIO_UPTODATE, &dio_bio->bi_flags);
-       dio_end_io(dio_bio, err);
+       dio_end_io(dio_bio, bio->bi_error);
        bio_put(bio);
 }
 
@@ -7916,9 +7945,10 @@ static int __btrfs_submit_bio_start_direct_io(struct inode *inode, int rw,
        return 0;
 }
 
-static void btrfs_end_dio_bio(struct bio *bio, int err)
+static void btrfs_end_dio_bio(struct bio *bio)
 {
        struct btrfs_dio_private *dip = bio->bi_private;
+       int err = bio->bi_error;
 
        if (err)
                btrfs_warn(BTRFS_I(dip->inode)->root->fs_info,
@@ -7947,8 +7977,8 @@ static void btrfs_end_dio_bio(struct bio *bio, int err)
        if (dip->errors) {
                bio_io_error(dip->orig_bio);
        } else {
-               set_bit(BIO_UPTODATE, &dip->dio_bio->bi_flags);
-               bio_endio(dip->orig_bio, 0);
+               dip->dio_bio->bi_error = 0;
+               bio_endio(dip->orig_bio);
        }
 out:
        bio_put(bio);
@@ -7957,8 +7987,11 @@ out:
 static struct bio *btrfs_dio_bio_alloc(struct block_device *bdev,
                                       u64 first_sector, gfp_t gfp_flags)
 {
-       int nr_vecs = bio_get_nr_vecs(bdev);
-       return btrfs_bio_alloc(bdev, first_sector, nr_vecs, gfp_flags);
+       struct bio *bio;
+       bio = btrfs_bio_alloc(bdev, first_sector, BIO_MAX_PAGES, gfp_flags);
+       if (bio)
+               bio_associate_current(bio);
+       return bio;
 }
 
 static inline int btrfs_lookup_and_bind_dio_csum(struct btrfs_root *root,
@@ -8219,7 +8252,8 @@ free_ordered:
         * callbacks - they require an allocated dip and a clone of dio_bio.
         */
        if (io_bio && dip) {
-               bio_endio(io_bio, ret);
+               io_bio->bi_error = -EIO;
+               bio_endio(io_bio);
                /*
                 * The end io callbacks free our dip, do the final put on io_bio
                 * and all the cleanup and final put for dio_bio (through
@@ -8246,7 +8280,7 @@ free_ordered:
                        unlock_extent(&BTRFS_I(inode)->io_tree, file_offset,
                              file_offset + dio_bio->bi_iter.bi_size - 1);
                }
-               clear_bit(BIO_UPTODATE, &dio_bio->bi_flags);
+               dio_bio->bi_error = -EIO;
                /*
                 * Releases and cleans up our dio_bio, no need to bio_put()
                 * nor bio_endio()/bio_io_error() against dio_bio.