Received: by 2002:a25:7ec1:0:0:0:0:0 with SMTP id z184csp3506316ybc; Thu, 21 Nov 2019 09:18:26 -0800 (PST) X-Google-Smtp-Source: APXvYqygc42FgLSPCjCk1EdBj3ZSFv7MhDFk25zWhpNUPiobLOuv9E7o1SjFwvrMMz2XZia6uDYB X-Received: by 2002:a5d:51c9:: with SMTP id n9mr12850034wrv.6.1574356706789; Thu, 21 Nov 2019 09:18:26 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1574356706; cv=none; d=google.com; s=arc-20160816; b=1HnoHK6sNEiRW+MtvbPhjfJ55lRQKDABW5m1BcCsqSuj8lh01g9n2GwuxtZDOG32KL yEY7uk7YMXtyjFgbS41JOzc1yc6KbGAirQ9BPcNzaiVjlMKLqcCkJDr6JSTKPPSxM04h eCzUHc3NzU/SJfhmZc9GHTPXIwiH3LvJb4WQHPuXa7j9CpWEf1K9+CaNl7bA0XdX41JR vqojnoNh7Dg8fNbKMgILtru4rAG7l2+/sm8o6/UGs9/1z+1awbc6E5ClS/txRG8qtNQl uk3wNcEWtr7ZEdQFrwP6nd+8pgEno8cgDc2t7ZgsnQ7XXkBmZo4ezCfbuNsi8EDiWDzn 7CuQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=aVFr1LNdneooTL7PAXANz2qMSKRv7xcL1i4cFtXH9vQ=; b=FZywK+CuF2h8VfPRliYIc5w726e/WdStUJnmNciRm6MTWHxuRbalY7ePrRv4hzJIaL M6U+3mP4GfPEAm/zBhX3f0xDSzBTBXtof97cSmXo7yHpr3qwooBA81swebr3uqBAWj1g u5k7n8Tz8KGh0D7cB5WBNE+AN7yv6SVByzmBXeGgB4eVenRrzSWFr3zQYoRzfj7+ixAy UePa9IMkInAeZ231dXwTurmAl0SioiBW5UFMLDr/gEhbPGX8jG8k/giQwnKTB6UH5Gdr kG4zrjMAUHyeIHTpr6wL51wThgKGhmkaVyTh+ipxKxjHujRt44KxhPf3THUpxt5/xUqn c6lA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id u93si3556741edc.184.2019.11.21.09.18.02; Thu, 21 Nov 2019 09:18:26 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727361AbfKURON (ORCPT + 99 others); Thu, 21 Nov 2019 12:14:13 -0500 Received: from mx2.suse.de ([195.135.220.15]:54188 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1727173AbfKURNo (ORCPT ); Thu, 21 Nov 2019 12:13:44 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 2315BB27E; Thu, 21 Nov 2019 17:13:42 +0000 (UTC) From: Michal Suchanek To: linux-scsi@vger.kernel.org, linux-block@vger.kernel.org Cc: Michal Suchanek , Jonathan Corbet , Jens Axboe , "James E.J. Bottomley" , "Martin K. Petersen" , Alexander Viro , Eric Biggers , "J. Bruce Fields" , Mauro Carvalho Chehab , Benjamin Coddington , Ming Lei , Chaitanya Kulkarni , Bart Van Assche , Damien Le Moal , Hou Tao , Pavel Begunkov , linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, Jan Kara , Hannes Reinecke , "Ewan D. Milne" , Christoph Hellwig , Matthew Wilcox Subject: [PATCH v4 08/10] bdev: add open_finish Date: Thu, 21 Nov 2019 18:13:15 +0100 Message-Id: X-Mailer: git-send-email 2.23.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Opening a block device may require a long operation such as waiting for the cdrom tray to close or disk to spin up. Performing this operation with locks held locks out other attempts to open the device from processes that donn't care about the medium state. To avoid this issue and still be able to perform time-consuming checks at open() the block device driver can provide open_finish(). If it does opening the device proceeds even when an error is returned from open(), bd_mutex is released and open_finish() is called. If open_finish() succeeds the device is now open, if it fails release() is called. When -ERESTARTSYS is returned from open() blkdev_get may loop without calling open_finish(). On -ERESTARTSYS open_finish() is not called. When -ENXIO is returned there is no device to retry opening so this error needs to be honored and open_finish() not called. Move a ret = 0 assignment up in the if/else branching to avoid returning -ENXIO. Previously the return value was ignored on the unhandled branch. Signed-off-by: Michal Suchanek --- v2: new patch v4: - fix crash on ENXIO - initialize capacity and partitions after open_finish --- Documentation/filesystems/locking.rst | 2 ++ fs/block_dev.c | 27 +++++++++++++++++++++++---- include/linux/blkdev.h | 1 + 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/Documentation/filesystems/locking.rst b/Documentation/filesystems/locking.rst index fc3a0704553c..2471ced5a8cf 100644 --- a/Documentation/filesystems/locking.rst +++ b/Documentation/filesystems/locking.rst @@ -456,6 +456,7 @@ block_device_operations prototypes:: int (*open) (struct block_device *, fmode_t); + int (*open_finish) (struct block_device *, fmode_t, int); int (*release) (struct gendisk *, fmode_t); int (*ioctl) (struct block_device *, fmode_t, unsigned, unsigned long); int (*compat_ioctl) (struct block_device *, fmode_t, unsigned, unsigned long); @@ -473,6 +474,7 @@ locking rules: ops bd_mutex ======================= =================== open: yes +open_finish: no release: yes ioctl: no compat_ioctl: no diff --git a/fs/block_dev.c b/fs/block_dev.c index 10c9e0ae2bdc..dc02af02d439 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1548,6 +1548,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) int partno; int perm = 0; bool first_open; + bool need_finish = false; if (mode & FMODE_READ) perm |= MAY_READ; @@ -1604,13 +1605,16 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) put_disk_and_module(disk); goto restart; } + if ((ret != -ENXIO) && + bdev->bd_disk->fops->open_finish) + need_finish = true; } if (!ret) blkdev_init_size(bdev, disk); blkdev_do_partitions(bdev, disk, ret); - if (ret) + if (ret && !need_finish) goto out_clear; } else { struct block_device *whole; @@ -1636,14 +1640,18 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) if (bdev->bd_bdi == &noop_backing_dev_info) bdev->bd_bdi = bdi_get(disk->queue->backing_dev_info); } else { + ret = 0; if (bdev->bd_contains == bdev) { - ret = 0; - if (bdev->bd_disk->fops->open) + if (bdev->bd_disk->fops->open) { ret = bdev->bd_disk->fops->open(bdev, mode); + if ((ret != -ERESTARTSYS) && (ret != -ENXIO) && + bdev->bd_disk->fops->open_finish) + need_finish = true; + } blkdev_do_partitions(bdev, disk, ret); - if (ret) + if (ret && !need_finish) goto out_unlock_bdev; } } @@ -1655,6 +1663,17 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) /* only one opener holds refs to the module and disk */ if (!first_open) put_disk_and_module(disk); + if (ret && need_finish) { + ret = bdev->bd_disk->fops->open_finish(bdev, mode, ret); + + if (!ret && first_open) + blkdev_init_size(bdev, disk); + blkdev_do_partitions(bdev, disk, ret); + } + if (ret) { + __blkdev_put(bdev, mode, for_part); + return ret; + } return 0; out_clear: diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index f3ea78b0c91c..b67e93c6afb7 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -1695,6 +1695,7 @@ static inline struct bio_vec *rq_integrity_vec(struct request *rq) struct block_device_operations { int (*open) (struct block_device *, fmode_t); + int (*open_finish)(struct block_device *bdev, fmode_t mode, int ret); void (*release) (struct gendisk *, fmode_t); int (*rw_page)(struct block_device *, sector_t, struct page *, unsigned int); int (*ioctl) (struct block_device *, fmode_t, unsigned, unsigned long); -- 2.23.0