From patchwork Sat Apr 9 11:29:24 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ilya Dryomov X-Patchwork-Id: 695851 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p39BTW8x020725 for ; Sat, 9 Apr 2011 11:29:32 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754582Ab1DIL3a (ORCPT ); Sat, 9 Apr 2011 07:29:30 -0400 Received: from mail-bw0-f46.google.com ([209.85.214.46]:34460 "EHLO mail-bw0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754388Ab1DIL33 (ORCPT ); Sat, 9 Apr 2011 07:29:29 -0400 Received: by bwz15 with SMTP id 15so3430089bwz.19 for ; Sat, 09 Apr 2011 04:29:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:date:from:to:cc:subject:message-id:mime-version :content-type:content-disposition:user-agent; bh=oXwc0RxPXA5uGWDyg881irosme1QdZaUAF5KHJXxR2U=; b=A9azAOnACBnkEZUuvH6cLz1PN9eVBfbMfviF7jHQdfthNXp6hb4DIOi513O8U1jFYR /6znTLuNU+m6ysX0w2VkH/VABGR2G3SGuwRYEH0eTRLAFH18K4DbmW6VYvyaDL8XJWHP oNqNgLEcB8UxvfOgwUmgATAasJoMnGFSwA4eg= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=date:from:to:cc:subject:message-id:mime-version:content-type :content-disposition:user-agent; b=nUG8Qj07G5Em6W49DPasyJJY9TF4Aj1/U9zRueKGH8zeAlZTSVEUH8h/gGB2sEFeDO GjTqtMQTXpJDZH6FKrjJOfPkeHOrM+ERyyR3bQb0zmsYrA5b2/Dqk3gwN1VlZ9vI4RH+ 55JRnb8P+HNw/EgqZvGyFwCLzGIKeHLd1/Vps= Received: by 10.204.141.14 with SMTP id k14mr2981242bku.37.1302348568372; Sat, 09 Apr 2011 04:29:28 -0700 (PDT) Received: from localhost ([46.35.244.78]) by mx.google.com with ESMTPS id q18sm2128206bka.3.2011.04.09.04.29.26 (version=TLSv1/SSLv3 cipher=OTHER); Sat, 09 Apr 2011 04:29:27 -0700 (PDT) Date: Sat, 9 Apr 2011 14:29:24 +0300 From: Ilya Dryomov To: linux-btrfs@vger.kernel.org Cc: Arne Jansen Subject: [PATCH] btrfs scrub - restore bios properly after media errors Message-ID: <20110409112924.GB29836@kwango.lan.net> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.18 (2008-05-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.6 (demeter1.kernel.org [140.211.167.41]); Sat, 09 Apr 2011 11:29:32 +0000 (UTC) The current code reallocates a bio after a media error. This is a temporary measure introduced in v3 after a serious problem related to bio reuse was found in v2 of scrub patchset. Basically we did not reset bv_offset and bv_len fields of the bio_vec structure. They are changed in case I/O error happens, for example, at offset 512 or 1024 into the page. Also bi_flags field wasn't properly setup before reusing the bio. Signed-off-by: Ilya Dryomov --- fs/btrfs/scrub.c | 48 +++++++++++++----------------------------------- 1 files changed, 13 insertions(+), 35 deletions(-) diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index e862167..1631327 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c @@ -418,45 +418,24 @@ static void scrub_checksum(scrub_work_t *work) int ret; if (sbio->err) { - struct bio *bio; - struct bio *old_bio; - - for (i = 0; i < sbio->count; ++i) { + for (i = 0; i < sbio->count; ++i) scrub_recheck_error(sbio, i); + + sbio->bio->bi_flags &= ~(BIO_POOL_MASK - 1); + sbio->bio->bi_flags |= 1 << BIO_UPTODATE; + sbio->bio->bi_phys_segments = 0; + sbio->bio->bi_idx = 0; + + for (i = 0; i < sbio->count; i++) { + struct bio_vec *bi; + bi = &sbio->bio->bi_io_vec[i]; + bi->bv_offset = 0; + bi->bv_len = PAGE_SIZE; } + spin_lock(&sdev->stat_lock); ++sdev->stat.read_errors; spin_unlock(&sdev->stat_lock); - - /* - * FIXME: allocate a new bio after a media error. I haven't - * figured out how to reuse this one - */ - old_bio = sbio->bio; - bio = bio_kmalloc(GFP_NOFS, SCRUB_PAGES_PER_BIO); - if (!bio) { - /* - * alloc failed. cancel the scrub and don't requeue - * this sbio - */ - printk(KERN_ERR "btrfs scrub: allocation failure, " - "cancelling scrub\n"); - atomic_inc(&sdev->dev->dev_root->fs_info-> - scrub_cancel_req); - goto out_no_enqueue; - } - sbio->bio = bio; - bio->bi_private = sbio; - bio->bi_end_io = scrub_bio_end_io; - bio->bi_sector = 0; - bio->bi_bdev = sbio->sdev->dev->bdev; - bio->bi_size = 0; - for (i = 0; i < SCRUB_PAGES_PER_BIO; ++i) { - struct page *page; - page = old_bio->bi_io_vec[i].bv_page; - bio_add_page(bio, page, PAGE_SIZE, 0); - } - bio_put(old_bio); goto out; } for (i = 0; i < sbio->count; ++i) { @@ -486,7 +465,6 @@ out: sbio->next_free = sdev->first_free; sdev->first_free = sbio->index; spin_unlock(&sdev->list_lock); -out_no_enqueue: atomic_dec(&sdev->in_flight); wake_up(&sdev->list_wait); }