From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.5 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id F33EFC64E75 for ; Thu, 26 Nov 2020 13:32:28 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 3A97D21D40 for ; Thu, 26 Nov 2020 13:32:28 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b="JIuiR46Q" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 3A97D21D40 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=lst.de Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id 97B0D6B0092; Thu, 26 Nov 2020 08:32:27 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 92CAA6B0093; Thu, 26 Nov 2020 08:32:27 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 7A8AE6B0095; Thu, 26 Nov 2020 08:32:27 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0002.hostedemail.com [216.40.44.2]) by kanga.kvack.org (Postfix) with ESMTP id 575206B0092 for ; Thu, 26 Nov 2020 08:32:27 -0500 (EST) Received: from smtpin29.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay03.hostedemail.com (Postfix) with ESMTP id 19BA582499A8 for ; Thu, 26 Nov 2020 13:32:27 +0000 (UTC) X-FDA: 77526658734.29.apple33_24178532737f Received: from filter.hostedemail.com (10.5.16.251.rfc1918.com [10.5.16.251]) by smtpin29.hostedemail.com (Postfix) with ESMTP id E468818086CC2 for ; Thu, 26 Nov 2020 13:32:26 +0000 (UTC) X-HE-Tag: apple33_24178532737f X-Filterd-Recvd-Size: 30395 Received: from casper.infradead.org (casper.infradead.org [90.155.50.34]) by imf15.hostedemail.com (Postfix) with ESMTP for ; Thu, 26 Nov 2020 13:32:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To: Content-Type:Content-ID:Content-Description; bh=Fdk2SbxFJnUzF1xr66AiIRjJsPPsVh7OjkOGZYMxKrY=; b=JIuiR46QhAlyfGkO2XlYufT60H PxwxDjkvrIvrMNrlXVt+onF/DqqPNRBwXUJxu3Crt+BF85Sv/nSLmbjCQLVTsAeJNe4h4ak71SIDx K+a368pcVPgVAGGqoTWHJ/9bBe5mBH2XwlfwXxR0Hp2TkFxDqft4si0AbBz4/ptGB8VxJQh+EBCPn iPS1yfkh1cNujH1GGmzyljRIMMbqUSwyEBkPUFKcp4/cq8LIfxnijPVGZ4k2foJWSRm09su8EwQED QykV+C5W0jeeUug2OFGMl/s3x/aywh3+RqFovBH81BrM6+V4KVTRBN1fnHxBJ7ldjxAa6WoFoFffw mPHh4c6g==; Received: from [2001:4bb8:18c:1dd6:27b8:b8a1:c13e:ceb1] (helo=localhost) by casper.infradead.org with esmtpsa (Exim 4.92.3 #3 (Red Hat Linux)) id 1kiGzJ-00042b-99; Thu, 26 Nov 2020 13:07:05 +0000 From: Christoph Hellwig To: Jens Axboe Cc: Tejun Heo , Josef Bacik , Coly Li , Mike Snitzer , Greg Kroah-Hartman , Jan Kara , Johannes Thumshirn , dm-devel@redhat.com, Jan Kara , linux-block@vger.kernel.org, linux-bcache@vger.kernel.org, linux-mtd@lists.infradead.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org Subject: [PATCH 23/44] block: remove i_bdev Date: Thu, 26 Nov 2020 14:04:01 +0100 Message-Id: <20201126130422.92945-24-hch@lst.de> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20201126130422.92945-1-hch@lst.de> References: <20201126130422.92945-1-hch@lst.de> MIME-Version: 1.0 X-SRS-Rewrite: SMTP reverse-path rewritten from by casper.infradead.org. See http://www.infradead.org/rpr.html Content-Transfer-Encoding: quoted-printable X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: Switch the block device lookup interfaces to directly work with a dev_t so that struct block_device references are only acquired by the blkdev_get variants (and the blk-cgroup special case). This means that we now don't need an extra reference in the inode and can generally simplify handling of struct block_device to keep the lookups contained in the core block layer code. Signed-off-by: Christoph Hellwig Acked-by: Tejun Heo Acked-by: Coly Li [bcache] --- block/ioctl.c | 3 +- drivers/block/loop.c | 8 +- drivers/md/bcache/super.c | 20 +- drivers/md/dm-table.c | 9 +- drivers/mtd/mtdsuper.c | 17 +- drivers/target/target_core_file.c | 6 +- drivers/usb/gadget/function/storage_common.c | 8 +- fs/block_dev.c | 195 +++++-------------- fs/btrfs/volumes.c | 13 +- fs/inode.c | 3 - fs/internal.h | 7 +- fs/io_uring.c | 10 +- fs/pipe.c | 5 +- fs/quota/quota.c | 19 +- fs/statfs.c | 2 +- fs/super.c | 37 ++-- include/linux/blkdev.h | 2 +- include/linux/fs.h | 1 - 18 files changed, 114 insertions(+), 251 deletions(-) diff --git a/block/ioctl.c b/block/ioctl.c index 0c09bb7a6ff35f..a6d8171221c7dc 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -590,8 +590,7 @@ long compat_blkdev_ioctl(struct file *file, unsigned = cmd, unsigned long arg) { int ret; void __user *argp =3D compat_ptr(arg); - struct inode *inode =3D file->f_mapping->host; - struct block_device *bdev =3D inode->i_bdev; + struct block_device *bdev =3D I_BDEV(file->f_mapping->host); struct gendisk *disk =3D bdev->bd_disk; fmode_t mode =3D file->f_mode; loff_t size; diff --git a/drivers/block/loop.c b/drivers/block/loop.c index b42c728620c9e4..26c7aafba7c5f8 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -675,10 +675,10 @@ static int loop_validate_file(struct file *file, st= ruct block_device *bdev) while (is_loop_device(f)) { struct loop_device *l; =20 - if (f->f_mapping->host->i_bdev =3D=3D bdev) + if (f->f_mapping->host->i_rdev =3D=3D bdev->bd_dev) return -EBADF; =20 - l =3D f->f_mapping->host->i_bdev->bd_disk->private_data; + l =3D I_BDEV(f->f_mapping->host)->bd_disk->private_data; if (l->lo_state !=3D Lo_bound) { return -EINVAL; } @@ -885,9 +885,7 @@ static void loop_config_discard(struct loop_device *l= o) * file-backed loop devices: discarded regions read back as zero. */ if (S_ISBLK(inode->i_mode) && !lo->lo_encrypt_key_size) { - struct request_queue *backingq; - - backingq =3D bdev_get_queue(inode->i_bdev); + struct request_queue *backingq =3D bdev_get_queue(I_BDEV(inode)); =20 max_discard_sectors =3D backingq->limits.max_write_zeroes_sectors; granularity =3D backingq->limits.discard_granularity ?: diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c index a6a5e21e4fd136..c55d3c58a7ef55 100644 --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c @@ -2380,38 +2380,38 @@ kobj_attribute_write(register, register_bcache); kobj_attribute_write(register_quiet, register_bcache); kobj_attribute_write(pendings_cleanup, bch_pending_bdevs_cleanup); =20 -static bool bch_is_open_backing(struct block_device *bdev) +static bool bch_is_open_backing(dev_t dev) { struct cache_set *c, *tc; struct cached_dev *dc, *t; =20 list_for_each_entry_safe(c, tc, &bch_cache_sets, list) list_for_each_entry_safe(dc, t, &c->cached_devs, list) - if (dc->bdev =3D=3D bdev) + if (dc->bdev->bd_dev =3D=3D dev) return true; list_for_each_entry_safe(dc, t, &uncached_devices, list) - if (dc->bdev =3D=3D bdev) + if (dc->bdev->bd_dev =3D=3D dev) return true; return false; } =20 -static bool bch_is_open_cache(struct block_device *bdev) +static bool bch_is_open_cache(dev_t dev) { struct cache_set *c, *tc; =20 list_for_each_entry_safe(c, tc, &bch_cache_sets, list) { struct cache *ca =3D c->cache; =20 - if (ca->bdev =3D=3D bdev) + if (ca->bdev->bd_dev =3D=3D dev) return true; } =20 return false; } =20 -static bool bch_is_open(struct block_device *bdev) +static bool bch_is_open(dev_t dev) { - return bch_is_open_cache(bdev) || bch_is_open_backing(bdev); + return bch_is_open_cache(dev) || bch_is_open_backing(dev); } =20 struct async_reg_args { @@ -2535,9 +2535,11 @@ static ssize_t register_bcache(struct kobject *k, = struct kobj_attribute *attr, sb); if (IS_ERR(bdev)) { if (bdev =3D=3D ERR_PTR(-EBUSY)) { - bdev =3D lookup_bdev(strim(path)); + dev_t dev; + mutex_lock(&bch_register_lock); - if (!IS_ERR(bdev) && bch_is_open(bdev)) + if (lookup_bdev(strim(path), &dev) =3D=3D 0 && + bch_is_open(dev)) err =3D "device already registered"; else err =3D "device busy"; diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index ce543b761be7b2..dea67772171053 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -348,16 +348,9 @@ static int upgrade_mode(struct dm_dev_internal *dd, = fmode_t new_mode, dev_t dm_get_dev_t(const char *path) { dev_t dev; - struct block_device *bdev; =20 - bdev =3D lookup_bdev(path); - if (IS_ERR(bdev)) + if (lookup_bdev(path, &dev)) dev =3D name_to_dev_t(path); - else { - dev =3D bdev->bd_dev; - bdput(bdev); - } - return dev; } EXPORT_SYMBOL_GPL(dm_get_dev_t); diff --git a/drivers/mtd/mtdsuper.c b/drivers/mtd/mtdsuper.c index c3e2098372f2e5..38b6aa849c6383 100644 --- a/drivers/mtd/mtdsuper.c +++ b/drivers/mtd/mtdsuper.c @@ -120,8 +120,8 @@ int get_tree_mtd(struct fs_context *fc, struct fs_context *fc)) { #ifdef CONFIG_BLOCK - struct block_device *bdev; - int ret, major; + dev_t dev; + int ret; #endif int mtdnr; =20 @@ -169,20 +169,15 @@ int get_tree_mtd(struct fs_context *fc, /* try the old way - the hack where we allowed users to mount * /dev/mtdblock$(n) but didn't actually _use_ the blockdev */ - bdev =3D lookup_bdev(fc->source); - if (IS_ERR(bdev)) { - ret =3D PTR_ERR(bdev); + ret =3D lookup_bdev(fc->source, &dev); + if (ret) { errorf(fc, "MTD: Couldn't look up '%s': %d", fc->source, ret); return ret; } pr_debug("MTDSB: lookup_bdev() returned 0\n"); =20 - major =3D MAJOR(bdev->bd_dev); - mtdnr =3D MINOR(bdev->bd_dev); - bdput(bdev); - - if (major =3D=3D MTD_BLOCK_MAJOR) - return mtd_get_sb_by_nr(fc, mtdnr, fill_super); + if (MAJOR(dev) =3D=3D MTD_BLOCK_MAJOR) + return mtd_get_sb_by_nr(fc, MINOR(dev), fill_super); =20 #endif /* CONFIG_BLOCK */ =20 diff --git a/drivers/target/target_core_file.c b/drivers/target/target_co= re_file.c index 7143d03f0e027e..b0cb5b95e892d3 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c @@ -133,10 +133,10 @@ static int fd_configure_device(struct se_device *de= v) */ inode =3D file->f_mapping->host; if (S_ISBLK(inode->i_mode)) { - struct request_queue *q =3D bdev_get_queue(inode->i_bdev); + struct request_queue *q =3D bdev_get_queue(I_BDEV(inode)); unsigned long long dev_size; =20 - fd_dev->fd_block_size =3D bdev_logical_block_size(inode->i_bdev); + fd_dev->fd_block_size =3D bdev_logical_block_size(I_BDEV(inode)); /* * Determine the number of bytes from i_size_read() minus * one (1) logical sector from underlying struct block_device @@ -559,7 +559,7 @@ fd_execute_unmap(struct se_cmd *cmd, sector_t lba, se= ctor_t nolb) =20 if (S_ISBLK(inode->i_mode)) { /* The backend is block device, use discard */ - struct block_device *bdev =3D inode->i_bdev; + struct block_device *bdev =3D I_BDEV(inode); struct se_device *dev =3D cmd->se_dev; =20 ret =3D blkdev_issue_discard(bdev, diff --git a/drivers/usb/gadget/function/storage_common.c b/drivers/usb/g= adget/function/storage_common.c index f7e6c42558eb76..b859a158a4140e 100644 --- a/drivers/usb/gadget/function/storage_common.c +++ b/drivers/usb/gadget/function/storage_common.c @@ -204,7 +204,7 @@ int fsg_lun_open(struct fsg_lun *curlun, const char *= filename) if (!(filp->f_mode & FMODE_WRITE)) ro =3D 1; =20 - inode =3D file_inode(filp); + inode =3D filp->f_mapping->host; if ((!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode))) { LINFO(curlun, "invalid file type: %s\n", filename); goto out; @@ -221,7 +221,7 @@ int fsg_lun_open(struct fsg_lun *curlun, const char *= filename) if (!(filp->f_mode & FMODE_CAN_WRITE)) ro =3D 1; =20 - size =3D i_size_read(inode->i_mapping->host); + size =3D i_size_read(inode); if (size < 0) { LINFO(curlun, "unable to find file size: %s\n", filename); rc =3D (int) size; @@ -231,8 +231,8 @@ int fsg_lun_open(struct fsg_lun *curlun, const char *= filename) if (curlun->cdrom) { blksize =3D 2048; blkbits =3D 11; - } else if (inode->i_bdev) { - blksize =3D bdev_logical_block_size(inode->i_bdev); + } else if (S_ISBLK(inode->i_mode)) { + blksize =3D bdev_logical_block_size(I_BDEV(inode)); blkbits =3D blksize_bits(blksize); } else { blksize =3D 512; diff --git a/fs/block_dev.c b/fs/block_dev.c index b12ab68297baf3..03f06c1614152b 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -883,7 +883,6 @@ static struct block_device *bdget(dev_t dev) bdev->bd_dev =3D dev; inode->i_mode =3D S_IFBLK; inode->i_rdev =3D dev; - inode->i_bdev =3D bdev; inode->i_data.a_ops =3D &def_blk_aops; mapping_set_gfp_mask(&inode->i_data, GFP_USER); unlock_new_inode(inode); @@ -924,67 +923,8 @@ void bdput(struct block_device *bdev) { iput(bdev->bd_inode); } - EXPORT_SYMBOL(bdput); =20 -static struct block_device *bd_acquire(struct inode *inode) -{ - struct block_device *bdev; - - spin_lock(&bdev_lock); - bdev =3D inode->i_bdev; - if (bdev && !inode_unhashed(bdev->bd_inode)) { - bdgrab(bdev); - spin_unlock(&bdev_lock); - return bdev; - } - spin_unlock(&bdev_lock); - - /* - * i_bdev references block device inode that was already shut down - * (corresponding device got removed). Remove the reference and look - * up block device inode again just in case new device got - * reestablished under the same device number. - */ - if (bdev) - bd_forget(inode); - - bdev =3D bdget(inode->i_rdev); - if (bdev) { - spin_lock(&bdev_lock); - if (!inode->i_bdev) { - /* - * We take an additional reference to bd_inode, - * and it's released in clear_inode() of inode. - * So, we can access it via ->i_mapping always - * without igrab(). - */ - bdgrab(bdev); - inode->i_bdev =3D bdev; - inode->i_mapping =3D bdev->bd_inode->i_mapping; - } - spin_unlock(&bdev_lock); - } - return bdev; -} - -/* Call when you free inode */ - -void bd_forget(struct inode *inode) -{ - struct block_device *bdev =3D NULL; - - spin_lock(&bdev_lock); - if (!sb_is_blkdev_sb(inode->i_sb)) - bdev =3D inode->i_bdev; - inode->i_bdev =3D NULL; - inode->i_mapping =3D &inode->i_data; - spin_unlock(&bdev_lock); - - if (bdev) - bdput(bdev); -} - /** * bd_may_claim - test whether a block device can be claimed * @bdev: block device of interest @@ -1493,38 +1433,45 @@ static int __blkdev_get(struct block_device *bdev= , struct gendisk *disk, } =20 /** - * blkdev_get - open a block device - * @bdev: block_device to open + * blkdev_get_by_dev - open a block device by device number + * @dev: device number of block device to open * @mode: FMODE_* mask * @holder: exclusive holder identifier * - * Open @bdev with @mode. If @mode includes %FMODE_EXCL, @bdev is - * open with exclusive access. Specifying %FMODE_EXCL with %NULL - * @holder is invalid. Exclusive opens may nest for the same @holder. + * Open the block device described by device number @dev. If @mode incl= udes + * If @mode includes %FMODE_EXCL, the block device is opened with exclus= ive + * access. Specifying %FMODE_EXCL with a %NULL @holder is invalid. Exc= lusive + * opens may nest for the same @holder. * - * On success, the reference count of @bdev is unchanged. On failure, - * @bdev is put. + * Use this interface ONLY if you really do not have anything better - i= .e. when + * you are behind a truly sucky interface and all you are given is a dev= ice + * number. Everything else should use blkdev_get_by_path(). * * CONTEXT: * Might sleep. * * RETURNS: - * 0 on success, -errno on failure. + * Reference to the block_device on success, ERR_PTR(-errno) on failure. */ -static int blkdev_get(struct block_device *bdev, fmode_t mode, void *hol= der) +struct block_device *blkdev_get_by_dev(dev_t dev, fmode_t mode, void *ho= lder) { struct block_device *claiming; bool unblock_events =3D true; + struct block_device *bdev; struct gendisk *disk; int partno; int ret; =20 ret =3D devcgroup_check_permission(DEVCG_DEV_BLOCK, - imajor(bdev->bd_inode), iminor(bdev->bd_inode), + MAJOR(dev), MINOR(dev), ((mode & FMODE_READ) ? DEVCG_ACC_READ : 0) | ((mode & FMODE_WRITE) ? DEVCG_ACC_WRITE : 0)); if (ret) - goto bdput; + return ERR_PTR(ret); + + bdev =3D bdget(dev); + if (!bdev) + return ERR_PTR(-ENOMEM); =20 /* * If we lost a race with 'disk' being deleted, try again. See md.c. @@ -1585,10 +1532,13 @@ static int blkdev_get(struct block_device *bdev, = fmode_t mode, void *holder) if (ret =3D=3D -ERESTARTSYS) goto retry; bdput: - if (ret) + if (ret) { bdput(bdev); - return ret; + return ERR_PTR(ret); + } + return bdev; } +EXPORT_SYMBOL(blkdev_get_by_dev); =20 /** * blkdev_get_by_path - open a block device by name @@ -1596,32 +1546,31 @@ static int blkdev_get(struct block_device *bdev, = fmode_t mode, void *holder) * @mode: FMODE_* mask * @holder: exclusive holder identifier * - * Open the blockdevice described by the device file at @path. @mode - * and @holder are identical to blkdev_get(). + * Open the block device described by the device file at &path. * - * On success, the returned block_device has reference count of one. + * If @mode includes %FMODE_EXCL, the block device is opened with exclus= ive + * access. Specifying %FMODE_EXCL with a %NULL @holder is invalid. Exc= lusive + * opens may nest for the same @holder. * * CONTEXT: * Might sleep. * * RETURNS: - * Pointer to block_device on success, ERR_PTR(-errno) on failure. + * Reference to the block_device on success, ERR_PTR(-errno) on failure. */ struct block_device *blkdev_get_by_path(const char *path, fmode_t mode, void *holder) { struct block_device *bdev; - int err; - - bdev =3D lookup_bdev(path); - if (IS_ERR(bdev)) - return bdev; + dev_t dev; + int error; =20 - err =3D blkdev_get(bdev, mode, holder); - if (err) - return ERR_PTR(err); + error =3D lookup_bdev(path, &dev); + if (error) + return ERR_PTR(error); =20 - if ((mode & FMODE_WRITE) && bdev_read_only(bdev)) { + bdev =3D blkdev_get_by_dev(dev, mode, holder); + if (!IS_ERR(bdev) && (mode & FMODE_WRITE) && bdev_read_only(bdev)) { blkdev_put(bdev, mode); return ERR_PTR(-EACCES); } @@ -1630,45 +1579,6 @@ struct block_device *blkdev_get_by_path(const char= *path, fmode_t mode, } EXPORT_SYMBOL(blkdev_get_by_path); =20 -/** - * blkdev_get_by_dev - open a block device by device number - * @dev: device number of block device to open - * @mode: FMODE_* mask - * @holder: exclusive holder identifier - * - * Open the blockdevice described by device number @dev. @mode and - * @holder are identical to blkdev_get(). - * - * Use it ONLY if you really do not have anything better - i.e. when - * you are behind a truly sucky interface and all you are given is a - * device number. _Never_ to be used for internal purposes. If you - * ever need it - reconsider your API. - * - * On success, the returned block_device has reference count of one. - * - * CONTEXT: - * Might sleep. - * - * RETURNS: - * Pointer to block_device on success, ERR_PTR(-errno) on failure. - */ -struct block_device *blkdev_get_by_dev(dev_t dev, fmode_t mode, void *ho= lder) -{ - struct block_device *bdev; - int err; - - bdev =3D bdget(dev); - if (!bdev) - return ERR_PTR(-ENOMEM); - - err =3D blkdev_get(bdev, mode, holder); - if (err) - return ERR_PTR(err); - - return bdev; -} -EXPORT_SYMBOL(blkdev_get_by_dev); - static int blkdev_open(struct inode * inode, struct file * filp) { struct block_device *bdev; @@ -1690,14 +1600,12 @@ static int blkdev_open(struct inode * inode, stru= ct file * filp) if ((filp->f_flags & O_ACCMODE) =3D=3D 3) filp->f_mode |=3D FMODE_WRITE_IOCTL; =20 - bdev =3D bd_acquire(inode); - if (bdev =3D=3D NULL) - return -ENOMEM; - + bdev =3D blkdev_get_by_dev(inode->i_rdev, filp->f_mode, filp); + if (IS_ERR(bdev)) + return PTR_ERR(bdev); filp->f_mapping =3D bdev->bd_inode->i_mapping; filp->f_wb_err =3D filemap_sample_wb_err(filp->f_mapping); - - return blkdev_get(bdev, filp->f_mode, filp); + return 0; } =20 static void __blkdev_put(struct block_device *bdev, fmode_t mode, int fo= r_part) @@ -2006,37 +1914,32 @@ const struct file_operations def_blk_fops =3D { * namespace if possible and return it. Return ERR_PTR(error) * otherwise. */ -struct block_device *lookup_bdev(const char *pathname) +int lookup_bdev(const char *pathname, dev_t *dev) { - struct block_device *bdev; struct inode *inode; struct path path; int error; =20 if (!pathname || !*pathname) - return ERR_PTR(-EINVAL); + return -EINVAL; =20 error =3D kern_path(pathname, LOOKUP_FOLLOW, &path); if (error) - return ERR_PTR(error); + return error; =20 inode =3D d_backing_inode(path.dentry); error =3D -ENOTBLK; if (!S_ISBLK(inode->i_mode)) - goto fail; + goto out_path_put; error =3D -EACCES; if (!may_open_dev(&path)) - goto fail; - error =3D -ENOMEM; - bdev =3D bd_acquire(inode); - if (!bdev) - goto fail; -out: + goto out_path_put; + + *dev =3D inode->i_rdev; + error =3D 0; +out_path_put: path_put(&path); - return bdev; -fail: - bdev =3D ERR_PTR(error); - goto out; + return error; } EXPORT_SYMBOL(lookup_bdev); =20 diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index a6406b3b8c2b4f..fbc4b58228f784 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -929,16 +929,16 @@ static noinline struct btrfs_device *device_list_ad= d(const char *path, * make sure it's the same device if the device is mounted */ if (device->bdev) { - struct block_device *path_bdev; + int error; + dev_t path_dev; =20 - path_bdev =3D lookup_bdev(path); - if (IS_ERR(path_bdev)) { + error =3D lookup_bdev(path, &path_dev); + if (error) { mutex_unlock(&fs_devices->device_list_mutex); - return ERR_CAST(path_bdev); + return ERR_PTR(error); } =20 - if (device->bdev !=3D path_bdev) { - bdput(path_bdev); + if (device->bdev->bd_dev !=3D path_dev) { mutex_unlock(&fs_devices->device_list_mutex); btrfs_warn_in_rcu(device->fs_info, "duplicate device %s devid %llu generation %llu scanned by %s (%d)", @@ -947,7 +947,6 @@ static noinline struct btrfs_device *device_list_add(= const char *path, task_pid_nr(current)); return ERR_PTR(-EEXIST); } - bdput(path_bdev); btrfs_info_in_rcu(device->fs_info, "devid %llu device path %s changed to %s scanned by %s (%d)", devid, rcu_str_deref(device->name), diff --git a/fs/inode.c b/fs/inode.c index 9d78c37b00b817..cb008acf0efdb8 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -155,7 +155,6 @@ int inode_init_always(struct super_block *sb, struct = inode *inode) inode->i_bytes =3D 0; inode->i_generation =3D 0; inode->i_pipe =3D NULL; - inode->i_bdev =3D NULL; inode->i_cdev =3D NULL; inode->i_link =3D NULL; inode->i_dir_seq =3D 0; @@ -580,8 +579,6 @@ static void evict(struct inode *inode) truncate_inode_pages_final(&inode->i_data); clear_inode(inode); } - if (S_ISBLK(inode->i_mode) && inode->i_bdev) - bd_forget(inode); if (S_ISCHR(inode->i_mode) && inode->i_cdev) cd_forget(inode); =20 diff --git a/fs/internal.h b/fs/internal.h index 47be21dfeebef5..53f890446e7508 100644 --- a/fs/internal.h +++ b/fs/internal.h @@ -25,7 +25,6 @@ extern void __init bdev_cache_init(void); extern int __sync_blockdev(struct block_device *bdev, int wait); void iterate_bdevs(void (*)(struct block_device *, void *), void *); void emergency_thaw_bdev(struct super_block *sb); -void bd_forget(struct inode *inode); #else static inline void bdev_cache_init(void) { @@ -43,9 +42,6 @@ static inline int emergency_thaw_bdev(struct super_bloc= k *sb) { return 0; } -static inline void bd_forget(struct inode *inode) -{ -} #endif /* CONFIG_BLOCK */ =20 /* @@ -114,8 +110,7 @@ extern struct file *alloc_empty_file_noaccount(int, c= onst struct cred *); */ extern int reconfigure_super(struct fs_context *); extern bool trylock_super(struct super_block *sb); -struct super_block *__get_super(struct block_device *bdev, bool excl); -extern struct super_block *user_get_super(dev_t); +struct super_block *user_get_super(dev_t, bool excl); void put_super(struct super_block *sb); extern bool mount_capable(struct fs_context *); =20 diff --git a/fs/io_uring.c b/fs/io_uring.c index 4ead291b2976f3..8f13c0417f940c 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -2716,11 +2716,7 @@ static struct file *__io_file_get(struct io_submit= _state *state, int fd) =20 static bool io_bdev_nowait(struct block_device *bdev) { -#ifdef CONFIG_BLOCK return !bdev || blk_queue_nowait(bdev_get_queue(bdev)); -#else - return true; -#endif } =20 /* @@ -2733,14 +2729,16 @@ static bool io_file_supports_async(struct file *f= ile, int rw) umode_t mode =3D file_inode(file)->i_mode; =20 if (S_ISBLK(mode)) { - if (io_bdev_nowait(file->f_inode->i_bdev)) + if (IS_ENABLED(CONFIG_BLOCK) && + io_bdev_nowait(I_BDEV(file->f_mapping->host))) return true; return false; } if (S_ISCHR(mode) || S_ISSOCK(mode)) return true; if (S_ISREG(mode)) { - if (io_bdev_nowait(file->f_inode->i_sb->s_bdev) && + if (IS_ENABLED(CONFIG_BLOCK) && + io_bdev_nowait(file->f_inode->i_sb->s_bdev) && file->f_op !=3D &io_uring_fops) return true; return false; diff --git a/fs/pipe.c b/fs/pipe.c index 0ac197658a2d6e..c5989cfd564d45 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -1342,9 +1342,8 @@ static long pipe_set_size(struct pipe_inode_info *p= ipe, unsigned long arg) } =20 /* - * After the inode slimming patch, i_pipe/i_bdev/i_cdev share the same - * location, so checking ->i_pipe is not enough to verify that this is a - * pipe. + * Note that i_pipe and i_cdev share the same location, so checking ->i_= pipe is + * not enough to verify that this is a pipe. */ struct pipe_inode_info *get_pipe_info(struct file *file, bool for_splice= ) { diff --git a/fs/quota/quota.c b/fs/quota/quota.c index f3d32b0d9008f2..6d16b2be5ac4a3 100644 --- a/fs/quota/quota.c +++ b/fs/quota/quota.c @@ -866,17 +866,18 @@ static bool quotactl_cmd_onoff(int cmd) static struct super_block *quotactl_block(const char __user *special, in= t cmd) { #ifdef CONFIG_BLOCK - struct block_device *bdev; struct super_block *sb; struct filename *tmp =3D getname(special); bool excl =3D false, thawed =3D false; + int error; + dev_t dev; =20 if (IS_ERR(tmp)) return ERR_CAST(tmp); - bdev =3D lookup_bdev(tmp->name); + error =3D lookup_bdev(tmp->name, &dev); putname(tmp); - if (IS_ERR(bdev)) - return ERR_CAST(bdev); + if (error) + return ERR_PTR(error); =20 if (quotactl_cmd_onoff(cmd)) { excl =3D true; @@ -886,8 +887,10 @@ static struct super_block *quotactl_block(const char= __user *special, int cmd) } =20 retry: - sb =3D __get_super(bdev, excl); - if (thawed && sb && sb->s_writers.frozen !=3D SB_UNFROZEN) { + sb =3D user_get_super(dev, excl); + if (!sb) + return ERR_PTR(-ENODEV); + if (thawed && sb->s_writers.frozen !=3D SB_UNFROZEN) { if (excl) up_write(&sb->s_umount); else @@ -897,10 +900,6 @@ static struct super_block *quotactl_block(const char= __user *special, int cmd) put_super(sb); goto retry; } - - bdput(bdev); - if (!sb) - return ERR_PTR(-ENODEV); return sb; =20 #else diff --git a/fs/statfs.c b/fs/statfs.c index 59f33752c1311f..68cb077887504f 100644 --- a/fs/statfs.c +++ b/fs/statfs.c @@ -235,7 +235,7 @@ SYSCALL_DEFINE3(fstatfs64, unsigned int, fd, size_t, = sz, struct statfs64 __user =20 static int vfs_ustat(dev_t dev, struct kstatfs *sbuf) { - struct super_block *s =3D user_get_super(dev); + struct super_block *s =3D user_get_super(dev, false); int err; if (!s) return -EINVAL; diff --git a/fs/super.c b/fs/super.c index 343e5c1e538d2a..7a1611e5d0f45d 100644 --- a/fs/super.c +++ b/fs/super.c @@ -740,7 +740,7 @@ void iterate_supers_type(struct file_system_type *typ= e, =20 EXPORT_SYMBOL(iterate_supers_type); =20 -struct super_block *__get_super(struct block_device *bdev, bool excl) +struct super_block *get_super(struct block_device *bdev) { struct super_block *sb; =20 @@ -755,17 +755,11 @@ struct super_block *__get_super(struct block_device= *bdev, bool excl) if (sb->s_bdev =3D=3D bdev) { sb->s_count++; spin_unlock(&sb_lock); - if (!excl) - down_read(&sb->s_umount); - else - down_write(&sb->s_umount); + down_read(&sb->s_umount); /* still alive? */ if (sb->s_root && (sb->s_flags & SB_BORN)) return sb; - if (!excl) - up_read(&sb->s_umount); - else - up_write(&sb->s_umount); + up_read(&sb->s_umount); /* nope, got unmounted */ spin_lock(&sb_lock); __put_super(sb); @@ -776,19 +770,6 @@ struct super_block *__get_super(struct block_device = *bdev, bool excl) return NULL; } =20 -/** - * get_super - get the superblock of a device - * @bdev: device to get the superblock for - * - * Scans the superblock list and finds the superblock of the file system - * mounted on the device given. %NULL is returned if no match is found. - */ -struct super_block *get_super(struct block_device *bdev) -{ - return __get_super(bdev, false); -} -EXPORT_SYMBOL(get_super); - /** * get_active_super - get an active reference to the superblock of a dev= ice * @bdev: device to get the superblock for @@ -820,7 +801,7 @@ struct super_block *get_active_super(struct block_dev= ice *bdev) return NULL; } =20 -struct super_block *user_get_super(dev_t dev) +struct super_block *user_get_super(dev_t dev, bool excl) { struct super_block *sb; =20 @@ -832,11 +813,17 @@ struct super_block *user_get_super(dev_t dev) if (sb->s_dev =3D=3D dev) { sb->s_count++; spin_unlock(&sb_lock); - down_read(&sb->s_umount); + if (excl) + down_write(&sb->s_umount); + else + down_read(&sb->s_umount); /* still alive? */ if (sb->s_root && (sb->s_flags & SB_BORN)) return sb; - up_read(&sb->s_umount); + if (excl) + up_write(&sb->s_umount); + else + up_read(&sb->s_umount); /* nope, got unmounted */ spin_lock(&sb_lock); __put_super(sb); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 12810a19edebc4..bdd7339bcda462 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -1973,7 +1973,7 @@ int bdev_read_only(struct block_device *bdev); int set_blocksize(struct block_device *bdev, int size); =20 const char *bdevname(struct block_device *bdev, char *buffer); -struct block_device *lookup_bdev(const char *); +int lookup_bdev(const char *pathname, dev_t *dev); =20 void blkdev_show(struct seq_file *seqf, off_t offset); =20 diff --git a/include/linux/fs.h b/include/linux/fs.h index a61df0dd4f1989..b0b358309657ba 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -696,7 +696,6 @@ struct inode { struct list_head i_devices; union { struct pipe_inode_info *i_pipe; - struct block_device *i_bdev; struct cdev *i_cdev; char *i_link; unsigned i_dir_seq; --=20 2.29.2