From patchwork Mon Jun 7 21:07:10 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 104832 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o57L9ve5025961 for ; Mon, 7 Jun 2010 21:09:57 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753954Ab0FGVJm (ORCPT ); Mon, 7 Jun 2010 17:09:42 -0400 Received: from mx1.redhat.com ([209.132.183.28]:54900 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753883Ab0FGVJl (ORCPT ); Mon, 7 Jun 2010 17:09:41 -0400 Received: from int-mx04.intmail.prod.int.phx2.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.17]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o57L9eBO028552 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 7 Jun 2010 17:09:41 -0400 Received: from localhost.localdomain (test1244.test.redhat.com [10.10.10.244]) by int-mx04.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o57L9e9k015476 for ; Mon, 7 Jun 2010 17:09:40 -0400 From: Josef Bacik To: linux-btrfs@vger.kernel.org Subject: [PATCH] Btrfs: read from backup copy if csum fails with DIO Date: Mon, 7 Jun 2010 17:07:10 -0400 Message-Id: <1275944830-4698-1-git-send-email-josef@redhat.com> X-Scanned-By: MIMEDefang 2.67 on 10.5.11.17 Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Mon, 07 Jun 2010 21:09:57 +0000 (UTC) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index d999c53..78c0547 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -5494,6 +5494,7 @@ struct btrfs_dio_private { u64 bytes; u32 *csums; void *private; + int mirror; }; static void btrfs_endio_direct_read(struct bio *bio, int err) @@ -5503,8 +5504,11 @@ static void btrfs_endio_direct_read(struct bio *bio, int err) struct btrfs_dio_private *dip = bio->bi_private; struct inode *inode = dip->inode; struct btrfs_root *root = BTRFS_I(inode)->root; + struct bio *new_bio; u64 start; u32 *private = dip->csums; + int num_copies; + int ret; start = dip->logical_offset; do { @@ -5528,7 +5532,7 @@ static void btrfs_endio_direct_read(struct bio *bio, int err) " %llu csum %u private %u\n", inode->i_ino, (unsigned long long)start, csum, *private); - err = -EIO; + goto failed; } } @@ -5537,6 +5541,7 @@ static void btrfs_endio_direct_read(struct bio *bio, int err) bvec++; } while (bvec <= bvec_end); +out: unlock_extent(&BTRFS_I(inode)->io_tree, dip->logical_offset, dip->logical_offset + dip->bytes - 1, GFP_NOFS); bio->bi_private = dip->private; @@ -5544,6 +5549,40 @@ static void btrfs_endio_direct_read(struct bio *bio, int err) kfree(dip->csums); kfree(dip); dio_end_io(bio, err); + return; +failed: + num_copies = btrfs_num_copies(&root->fs_info->mapping_tree, + dip->logical_offset, dip->bytes); + dip->mirror++; + if (dip->mirror > num_copies) { + err = -EIO; + goto out; + } + + new_bio = bio_clone(bio, GFP_NOFS); + if (!new_bio) { + err = -EIO; + goto out; + } + + new_bio->bi_end_io = btrfs_endio_direct_read; + new_bio->bi_private = dip; + new_bio->bi_size = dip->bytes; + new_bio->bi_sector = dip->disk_bytenr >> 9; + + ret = btrfs_bio_wq_end_io(root->fs_info, new_bio, 0); + if (ret) { + bio_put(new_bio); + err = -EIO; + goto out; + } + + ret = btrfs_map_bio(root, READ, new_bio, dip->mirror, 1); + if (ret) { + bio_put(new_bio); + err = -EIO; + goto out; + } } static void btrfs_endio_direct_write(struct bio *bio, int err) @@ -5674,6 +5713,7 @@ static void btrfs_submit_direct(int rw, struct bio *bio, struct inode *inode, dip->private = bio->bi_private; dip->inode = inode; dip->logical_offset = file_offset; + dip->mirror = 0; start = dip->logical_offset; dip->bytes = 0;