From patchwork Thu Dec 10 17:30:20 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikulas Patocka X-Patchwork-Id: 7820991 Return-Path: X-Original-To: patchwork-linux-block@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 40074BEEE1 for ; Thu, 10 Dec 2015 17:35:56 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 6EC3F20576 for ; Thu, 10 Dec 2015 17:35:55 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 80BED204D3 for ; Thu, 10 Dec 2015 17:35:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754354AbbLJRaY (ORCPT ); Thu, 10 Dec 2015 12:30:24 -0500 Received: from mx1.redhat.com ([209.132.183.28]:46865 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755000AbbLJRaV (ORCPT ); Thu, 10 Dec 2015 12:30:21 -0500 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by mx1.redhat.com (Postfix) with ESMTPS id E8BC933A898; Thu, 10 Dec 2015 17:30:20 +0000 (UTC) Received: from file01.intranet.prod.int.rdu2.redhat.com (file01.intranet.prod.int.rdu2.redhat.com [10.11.5.7]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id tBAHUKQ9008734 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 10 Dec 2015 12:30:20 -0500 Received: from file01.intranet.prod.int.rdu2.redhat.com (localhost [127.0.0.1]) by file01.intranet.prod.int.rdu2.redhat.com (8.14.4/8.14.4) with ESMTP id tBAHUKqD000651; Thu, 10 Dec 2015 12:30:20 -0500 Received: from localhost (mpatocka@localhost) by file01.intranet.prod.int.rdu2.redhat.com (8.14.4/8.14.4/Submit) with ESMTP id tBAHUKDl000647; Thu, 10 Dec 2015 12:30:20 -0500 X-Authentication-Warning: file01.intranet.prod.int.rdu2.redhat.com: mpatocka owned process doing -bs Date: Thu, 10 Dec 2015 12:30:20 -0500 (EST) From: Mikulas Patocka X-X-Sender: mpatocka@file01.intranet.prod.int.rdu2.redhat.com To: "James E.J. Bottomley" , "Martin K. Petersen" , Jens Axboe , Mike Snitzer , Jonathan Brassow cc: dm-devel@redhat.com, linux-scsi@vger.kernel.org, linux-kernel@vger.kernel.org, linux-block@vger.kernel.org Subject: [PATCH 4/15] block copy: use a timer to fix a theoretical deadlock In-Reply-To: Message-ID: References: User-Agent: Alpine 2.02 (LRH 1266 2009-07-14) MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The block layer creates two bios for each copy operation. The bios travel independently through the storage stack and they are paired at the block device. There is a theoretical problem with this - the block device stack only guarantees forward progress for a single bio. When two bios are sent, it is possible (though very unlikely) that the first bio exhausts some mempool and the second bio waits until there is free space in the mempool (and thus it waits until the first bio finishes). To avoid this deadlock, we introduce a timer. If the two bios are not paired at the physical block device within 10 seconds, the copy operation is aborted and the bio that waits to be paired is released with an error. Note that there is no guarantee that any XCOPY operation succeed, so aborting an operation with an error shouldn't cause any problems - the caller is supposed to perform the copy manually if XCOPY fails. Signed-off-by: Mikulas Patocka --- block/blk-lib.c | 31 +++++++++++++++++++++++++++++++ include/linux/blk_types.h | 2 ++ 2 files changed, 33 insertions(+) -- To unsubscribe from this list: send the line "unsubscribe linux-block" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Index: linux-4.3/block/blk-lib.c =================================================================== --- linux-4.3.orig/block/blk-lib.c 2015-11-02 18:43:06.000000000 +0100 +++ linux-4.3/block/blk-lib.c 2015-11-02 18:43:10.000000000 +0100 @@ -300,6 +300,34 @@ int blkdev_issue_zeroout(struct block_de } EXPORT_SYMBOL(blkdev_issue_zeroout); +#define BLK_COPY_TIMEOUT (10 * HZ) + +static void blk_copy_timeout(unsigned long bc_) +{ + struct bio_copy *bc = (struct bio_copy *)bc_; + struct bio *bio0 = NULL, *bio1 = NULL; + + WARN_ON(!irqs_disabled()); + + spin_lock(&bc->spinlock); /* the timer is IRQSAFE */ + if (bc->error == 1) { + bc->error = -ETIMEDOUT; + bio0 = bc->pair[0]; + bio1 = bc->pair[1]; + bc->pair[0] = bc->pair[1] = NULL; + } + spin_unlock(&bc->spinlock); + + if (bio0) { + bio0->bi_error = -ETIMEDOUT; + bio_endio(bio0); + } + if (bio1) { + bio1->bi_error = -ETIMEDOUT; + bio_endio(bio1); + } +} + static void bio_copy_end_io(struct bio *bio) { struct bio_copy *bc = bio->bi_copy; @@ -335,6 +363,7 @@ static void bio_copy_end_io(struct bio * } while (unlikely(atomic64_cmpxchg(bc->first_error, first_error, bc->offset) != first_error)); } + del_timer_sync(&bc->timer); kfree(bc); if (atomic_dec_and_test(&bb->done)) complete(bb->wait); @@ -425,6 +454,8 @@ int blkdev_issue_copy(struct block_devic bc->first_error = &first_error; bc->offset = offset; spin_lock_init(&bc->spinlock); + __setup_timer(&bc->timer, blk_copy_timeout, (unsigned long)bc, TIMER_IRQSAFE); + mod_timer(&bc->timer, jiffies + BLK_COPY_TIMEOUT); read_bio->bi_iter.bi_sector = src_sector; read_bio->bi_iter.bi_size = chunk << 9; Index: linux-4.3/include/linux/blk_types.h =================================================================== --- linux-4.3.orig/include/linux/blk_types.h 2015-11-02 18:43:06.000000000 +0100 +++ linux-4.3/include/linux/blk_types.h 2015-11-02 18:43:10.000000000 +0100 @@ -6,6 +6,7 @@ #define __LINUX_BLK_TYPES_H #include +#include struct bio_set; struct bio; @@ -52,6 +53,7 @@ struct bio_copy { atomic64_t *first_error; sector_t offset; spinlock_t spinlock; + struct timer_list timer; }; /*