From: Al Viro <viro@zeniv.linux.org.uk>
To: Jason Yan <yanaijie@huawei.com>
Cc: Kanchan Joshi <joshi.k@samsung.com>,
David Howells <dhowells@redhat.com>,
hch@lst.de, linux-block@vger.kernel.org
Subject: Re: How best to get the size of a blockdev from a file?
Date: Thu, 20 Apr 2023 20:04:11 +0100 [thread overview]
Message-ID: <20230420190411.GM3390869@ZenIV> (raw)
In-Reply-To: <e4f7df06-ccba-700b-5a69-ea44bd54e672@huawei.com>
On Tue, Apr 18, 2023 at 10:05:12PM +0800, Jason Yan wrote:
> On 2023/4/18 20:28, Kanchan Joshi wrote:
> > On Tue, Apr 18, 2023 at 11:00:12AM +0100, David Howells wrote:
> > > Hi Christoph,
> > >
> > > It seems that my use of i_size_read(file_inode(in)) in
> > > filemap_splice_read()
> > > to get the size of the file to be spliced from doesn't work in the
> > > case of
> > > blockdevs and it always returns 0.
> > >
> > > What would be the best way to get the blockdev size? Look at
> > > file->f_mapping->i_size maybe?
> >
> > bdev_nr_bytes(I_BDEV(file->f_mapping->host))
> > should work I suppose.
> >
>
> This needs the caller to check if the file is a blockdev. Can we fill the
> upper inode size which belongs to devtmpfs so that the generic code do not
> need to aware the low level inode type?
We do:
static inline loff_t bdev_nr_bytes(struct block_device *bdev)
{
return (loff_t)bdev_nr_sectors(bdev) << SECTOR_SHIFT;
}
static inline sector_t bdev_nr_sectors(struct block_device *bdev)
{
return bdev->bd_nr_sectors;
}
$ git grep -n -w bd_nr_sectors
block/genhd.c:64: bdev->bd_nr_sectors = sectors;
block/partitions/core.c:92: bdev->bd_nr_sectors = sectors;
include/linux/blk_types.h:42: sector_t bd_nr_sectors;
include/linux/blkdev.h:785: return bdev->bd_nr_sectors;
and if you look into the functions with those assignments you'll see
void set_capacity(struct gendisk *disk, sector_t sectors)
{
struct block_device *bdev = disk->part0;
spin_lock(&bdev->bd_size_lock);
i_size_write(bdev->bd_inode, (loff_t)sectors << SECTOR_SHIFT);
bdev->bd_nr_sectors = sectors;
spin_unlock(&bdev->bd_size_lock);
}
and
static void bdev_set_nr_sectors(struct block_device *bdev, sector_t sectors)
{
spin_lock(&bdev->bd_size_lock);
i_size_write(bdev->bd_inode, (loff_t)sectors << SECTOR_SHIFT);
bdev->bd_nr_sectors = sectors;
spin_unlock(&bdev->bd_size_lock);
}
As you can see, both do i_size_write() on bdev->bd_inode with the value
equal to what bdev_nr_bytes() will return after the store to ->bd_nr_sectors.
Now, bdev->bd_inode always points to inode coallocated with bdev
(see bdev_alloc() for details) and that's what we have
->f_mapping->host pointing to for opened file after
blkdev_open() - see
filp->f_mapping = bdev->bd_inode->i_mapping;
in there combined with inode->i_mapping.host set to inode by
inode_init_always()<-alloc_inode()<-new_inode_pseudo()<-new_inode()<-bdev_alloc().
IOW, i_size_read(file->f_mapping->host) is correct answer for any kind of file.
next prev parent reply other threads:[~2023-04-20 19:04 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <CGME20230418100108epcas5p2d0f2a7a274e78731373986b3d4fced9b@epcas5p2.samsung.com>
2023-04-18 10:00 ` How best to get the size of a blockdev from a file? David Howells
2023-04-18 12:28 ` Kanchan Joshi
2023-04-18 14:05 ` Jason Yan
2023-04-20 19:04 ` Al Viro [this message]
2023-04-21 1:38 ` Jason Yan
2023-04-18 15:34 ` Christoph Hellwig
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230420190411.GM3390869@ZenIV \
--to=viro@zeniv.linux.org.uk \
--cc=dhowells@redhat.com \
--cc=hch@lst.de \
--cc=joshi.k@samsung.com \
--cc=linux-block@vger.kernel.org \
--cc=yanaijie@huawei.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox