Message ID | 20231205123728.1866699-2-yukuai1@huaweicloud.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | block: don't access bd_inode directly from other modules | expand |
On 12/5/23 04:37, Yu Kuai wrote: > +static inline u8 block_bits(struct block_device *bdev) > +{ > + return bdev->bd_inode->i_blkbits; > +} This function needs a name that's more descriptive. Thanks, Bart.
> +void invalidate_bdev_range(struct block_device *bdev, pgoff_t start, > + pgoff_t end) > +{ > + invalidate_mapping_pages(bdev->bd_inode->i_mapping, start, end); > +} > +EXPORT_SYMBOL_GPL(invalidate_bdev_range); All these could probably use kerneldoc comments. For this one I really don't like it existing at all, but we'll have to discuss that in the btrfs patch. > +loff_t bdev_size(struct block_device *bdev) > +{ > + loff_t size; > + > + spin_lock(&bdev->bd_size_lock); > + size = i_size_read(bdev->bd_inode); > + spin_unlock(&bdev->bd_size_lock); > + > + return size; > +} > +EXPORT_SYMBOL_GPL(bdev_size); No need for this one. The callers can simply use bdev_nr_bytes. > +struct folio *bdev_read_folio(struct block_device *bdev, pgoff_t index) > +{ > + return read_mapping_folio(bdev->bd_inode->i_mapping, index, NULL); > +} > +EXPORT_SYMBOL_GPL(bdev_read_folio); > + > +struct folio *bdev_read_folio_gfp(struct block_device *bdev, pgoff_t index, > + gfp_t gfp) > +{ > + return mapping_read_folio_gfp(bdev->bd_inode->i_mapping, index, gfp); > +} > +EXPORT_SYMBOL_GPL(bdev_read_folio_gfp); I think we can just drop bdev_read_folio_gfp. Half of the callers simply pass GPK_KERNEL, and the other half passes GFP_NOFS and could just use memalloc_nofs_save(). > +void bdev_balance_dirty_pages_ratelimited(struct block_device *bdev) > +{ > + return balance_dirty_pages_ratelimited(bdev->bd_inode->i_mapping); > +} > +EXPORT_SYMBOL_GPL(bdev_balance_dirty_pages_ratelimited); Hmm, this is just used for block2mtd, and feels a little too low-level to me, as block2mtd really should be using the normal fileread/write APIs. I guess we'll have to live with it for now if we want to expedite killing off bd_inode. > +void bdev_correlate_mapping(struct block_device *bdev, > + struct address_space *mapping) > +{ > + mapping->host = bdev->bd_inode; > +} > +EXPORT_SYMBOL_GPL(bdev_correlate_mapping); Maybe associated insted of correlate? Either way this basically fully exposes the bdev inode again :( > +gfp_t bdev_gfp_constraint(struct block_device *bdev, gfp_t gfp) > +{ > + return mapping_gfp_constraint(bdev->bd_inode->i_mapping, gfp); > +} > +EXPORT_SYMBOL_GPL(bdev_gfp_constraint); The right fix here is to: - use memalloc_nofs_save in extet instead of using mapping_gfp_constraint to clear it from the mapping flags - remove __ext4_sb_bread_gfp and just have buffer.c helper that does the right thing (either by changing the calling conventions of an existing one, or adding a new one). > +/* > + * The del_gendisk() function uninitializes the disk-specific data > + * structures, including the bdi structure, without telling anyone > + * else. Once this happens, any attempt to call mark_buffer_dirty() > + * (for example, by ext4_commit_super), will cause a kernel OOPS. > + * This is a kludge to prevent these oops until we can put in a proper > + * hook in del_gendisk() to inform the VFS and file system layers. > + */ > +int bdev_ejected(struct block_device *bdev) > +{ > + struct backing_dev_info *bdi = inode_to_bdi(bdev->bd_inode); > + > + return bdi->dev == NULL; > +} > +EXPORT_SYMBOL_GPL(bdev_ejected); And this code in ext4 should just go away entirely. The bdi should always be valid for a live bdev for years. > --- a/block/bio.c > +++ b/block/bio.c > @@ -1119,6 +1119,7 @@ void bio_add_folio_nofail(struct bio *bio, struct folio *folio, size_t len, > WARN_ON_ONCE(off > UINT_MAX); > __bio_add_page(bio, &folio->page, len, off); > } > +EXPORT_SYMBOL_GPL(bio_add_folio_nofail); How is this realted? The export is fine, but really should be a separate, well-documented commit. > > +static inline u8 block_bits(struct block_device *bdev) > +{ > + return bdev->bd_inode->i_blkbits; > +} Not sure we should need this. i_blkbits comes from the blocksize the fs set, so it should have other ways to get at it.
Hi, 在 2023/12/06 14:14, Christoph Hellwig 写道: >> +void invalidate_bdev_range(struct block_device *bdev, pgoff_t start, >> + pgoff_t end) >> +{ >> + invalidate_mapping_pages(bdev->bd_inode->i_mapping, start, end); >> +} >> +EXPORT_SYMBOL_GPL(invalidate_bdev_range); > > All these could probably use kerneldoc comments. Ok, and thanks for reviewing the patchset! > > For this one I really don't like it existing at all, but we'll have to > discuss that in the btrfs patch. > >> +loff_t bdev_size(struct block_device *bdev) >> +{ >> + loff_t size; >> + >> + spin_lock(&bdev->bd_size_lock); >> + size = i_size_read(bdev->bd_inode); >> + spin_unlock(&bdev->bd_size_lock); >> + >> + return size; >> +} >> +EXPORT_SYMBOL_GPL(bdev_size); > > No need for this one. The callers can simply use bdev_nr_bytes. Ok, I'll replace it with bdev_nr_bytes. > >> +struct folio *bdev_read_folio(struct block_device *bdev, pgoff_t index) >> +{ >> + return read_mapping_folio(bdev->bd_inode->i_mapping, index, NULL); >> +} >> +EXPORT_SYMBOL_GPL(bdev_read_folio); >> + >> +struct folio *bdev_read_folio_gfp(struct block_device *bdev, pgoff_t index, >> + gfp_t gfp) >> +{ >> + return mapping_read_folio_gfp(bdev->bd_inode->i_mapping, index, gfp); >> +} >> +EXPORT_SYMBOL_GPL(bdev_read_folio_gfp); > > I think we can just drop bdev_read_folio_gfp. Half of the callers simply > pass GPK_KERNEL, and the other half passes GFP_NOFS and could just use > memalloc_nofs_save(). I'm a litter confused, so there are 3 use cases: 1) use GFP_USER, default gfp from bdev_alloc. 2) use GFP_KERNEL 3) use GFP_NOFS I understand that you're suggesting memalloc_nofs_save() to distinguish 2 and 3, but how can I distinguish 1? > >> +void bdev_balance_dirty_pages_ratelimited(struct block_device *bdev) >> +{ >> + return balance_dirty_pages_ratelimited(bdev->bd_inode->i_mapping); >> +} >> +EXPORT_SYMBOL_GPL(bdev_balance_dirty_pages_ratelimited); > > Hmm, this is just used for block2mtd, and feels a little too low-level > to me, as block2mtd really should be using the normal fileread/write > APIs. I guess we'll have to live with it for now if we want to expedite > killing off bd_inode. > >> +void bdev_correlate_mapping(struct block_device *bdev, >> + struct address_space *mapping) >> +{ >> + mapping->host = bdev->bd_inode; >> +} >> +EXPORT_SYMBOL_GPL(bdev_correlate_mapping); > > Maybe associated insted of correlate? Either way this basically > fully exposes the bdev inode again :( > >> +gfp_t bdev_gfp_constraint(struct block_device *bdev, gfp_t gfp) >> +{ >> + return mapping_gfp_constraint(bdev->bd_inode->i_mapping, gfp); >> +} >> +EXPORT_SYMBOL_GPL(bdev_gfp_constraint); > > The right fix here is to: > > - use memalloc_nofs_save in extet instead of using > mapping_gfp_constraint to clear it from the mapping flags > - remove __ext4_sb_bread_gfp and just have buffer.c helper that does > the right thing (either by changing the calling conventions of an > existing one, or adding a new one). Thanks for the suggestions, but I'm not sure how to do this yet, I must read more ext4 code. > >> +/* >> + * The del_gendisk() function uninitializes the disk-specific data >> + * structures, including the bdi structure, without telling anyone >> + * else. Once this happens, any attempt to call mark_buffer_dirty() >> + * (for example, by ext4_commit_super), will cause a kernel OOPS. >> + * This is a kludge to prevent these oops until we can put in a proper >> + * hook in del_gendisk() to inform the VFS and file system layers. >> + */ >> +int bdev_ejected(struct block_device *bdev) >> +{ >> + struct backing_dev_info *bdi = inode_to_bdi(bdev->bd_inode); >> + >> + return bdi->dev == NULL; >> +} >> +EXPORT_SYMBOL_GPL(bdev_ejected); > > And this code in ext4 should just go away entirely. The bdi should > always be valid for a live bdev for years. Sounds good, I was confused about this code as well. > >> --- a/block/bio.c >> +++ b/block/bio.c >> @@ -1119,6 +1119,7 @@ void bio_add_folio_nofail(struct bio *bio, struct folio *folio, size_t len, >> WARN_ON_ONCE(off > UINT_MAX); >> __bio_add_page(bio, &folio->page, len, off); >> } >> +EXPORT_SYMBOL_GPL(bio_add_folio_nofail); > > How is this realted? The export is fine, but really should be a > separate, well-documented commit. This is used to replace __bio_add_page() in btrfs while converting page to folio, please let me know if I should keep this, if so, I'll split this into a new commit. > >> >> +static inline u8 block_bits(struct block_device *bdev) >> +{ >> + return bdev->bd_inode->i_blkbits; >> +} > > Not sure we should need this. i_blkbits comes from the blocksize > the fs set, so it should have other ways to get at it. Yes, this is now only used for erofs, and erofs do call sb_set_blocksize() while initializing, hence it's right there is other way to get blkbits and this helper is not needed. Thanks, Kuai > . >
On Wed, Dec 06, 2023 at 02:50:56PM +0800, Yu Kuai wrote: > I'm a litter confused, so there are 3 use cases: > 1) use GFP_USER, default gfp from bdev_alloc. > 2) use GFP_KERNEL > 3) use GFP_NOFS > > I understand that you're suggesting memalloc_nofs_save() to distinguish > 2 and 3, but how can I distinguish 1? You shouldn't. Diverging from the default flags except for clearing the FS or IO flags is simply a bug. Note that things like block2mtd should probably also ensure a noio allocation if they aren't doing that yet. > > - use memalloc_nofs_save in extet instead of using > > mapping_gfp_constraint to clear it from the mapping flags > > - remove __ext4_sb_bread_gfp and just have buffer.c helper that does > > the right thing (either by changing the calling conventions of an > > existing one, or adding a new one). > > Thanks for the suggestions, but I'm not sure how to do this yet, I must > read more ext4 code. the nofs save part should be trivial. You can just skip the rest for now as it's not needed for this patch series.
On Tue, Dec 05, 2023 at 08:37:15PM +0800, Yu Kuai wrote: > +struct folio *bdev_read_folio(struct block_device *bdev, pgoff_t index) > +{ > + return read_mapping_folio(bdev->bd_inode->i_mapping, index, NULL); > +} > +EXPORT_SYMBOL_GPL(bdev_read_folio); I'm coming to the opinion that 'index' is the wrong parameter here. Looking through all the callers of bdev_read_folio() in this patchset, they all have a position in bytes, and they all convert it to index for this call. The API should probably be: struct folio *bdev_read_folio(struct block_device *bdev, loff_t pos) { return read_mapping_folio(bdev->bd_inode->i_mapping, pos / PAGE_SIZE, NULL); } ... and at some point, we'll get round to converting read_mapping_folio() to take its argument in loff_t. Similiarly for these two APIs: > +struct folio *bdev_read_folio_gfp(struct block_device *bdev, pgoff_t index, > + gfp_t gfp) > +struct folio *bdev_get_folio(struct block_device *bdev, pgoff_t index) > +struct folio *bdev_find_or_create_folio(struct block_device *bdev, > + pgoff_t index, gfp_t gfp) > +{ > + return __filemap_get_folio(bdev->bd_inode->i_mapping, index, > + FGP_LOCK | FGP_ACCESSED | FGP_CREAT, gfp); > +} > +EXPORT_SYMBOL_GPL(bdev_find_or_create_folio); This one probably shouldn't exist. I've been converting callers of find_or_create_page() to call __filemap_get_folio; I suspect we should expose a __bdev_get_folio and have the callers use the FGP arguments directly, but I'm open to other opinions here. > +void bdev_sync_readahead(struct block_device *bdev, struct file_ra_state *ra, > + struct file *file, pgoff_t index, > + unsigned long req_count) > +{ > + struct file_ra_state tmp_ra = {}; > + > + if (!ra) { > + ra = &tmp_ra; > + file_ra_state_init(ra, bdev->bd_inode->i_mapping); > + } > + page_cache_sync_readahead(bdev->bd_inode->i_mapping, ra, file, index, > + req_count); > +} I think the caller should always be passing in a valid file_ra_state. It's only cramfs that doesn't have one, and it really should! Not entirely sure about the arguments here; part of me says "bytes", but this is weird enough to maybe take arguments in pages.
On Tue, Dec 05, 2023 at 10:14:00PM -0800, Christoph Hellwig wrote: > > +/* > > + * The del_gendisk() function uninitializes the disk-specific data > > + * structures, including the bdi structure, without telling anyone > > + * else. Once this happens, any attempt to call mark_buffer_dirty() > > + * (for example, by ext4_commit_super), will cause a kernel OOPS. > > + * This is a kludge to prevent these oops until we can put in a proper > > + * hook in del_gendisk() to inform the VFS and file system layers. > > + */ > > +int bdev_ejected(struct block_device *bdev) > > +{ > > + struct backing_dev_info *bdi = inode_to_bdi(bdev->bd_inode); > > + > > + return bdi->dev == NULL; > > +} > > +EXPORT_SYMBOL_GPL(bdev_ejected); > > And this code in ext4 should just go away entirely. The bdi should > always be valid for a live bdev for years. This was added because pulling a mounted a USB thumb drive (or a HDD drops off the SATA bus) while the file system is mounted and actively in use, would result in a kernel OOPS. If that's no longer true, that's great, but it would be good to test to make sure this is the case.... If we really want to remove it, I'd suggest doing this as a separate commit, so that after we see syzbot reports, or users complaining about kernel crashes, we can revert the removal if necessary. Cheers, - Ted
On Wed, Dec 06, 2023 at 12:50:38PM -0500, Theodore Ts'o wrote: > This was added because pulling a mounted a USB thumb drive (or a HDD > drops off the SATA bus) while the file system is mounted and actively > in use, would result in a kernel OOPS. If that's no longer true, > that's great, but it would be good to test to make sure this is the > case.... And, surprise, surprise - that didn't just affect ext4. So I ended up fixing this properly in the block layer. > If we really want to remove it, I'd suggest doing this as a separate > commit, so that after we see syzbot reports, or users complaining > about kernel crashes, we can revert the removal if necessary. Yes, this should of course be separate, well documented commit.
Hi, 在 2023/12/06 22:58, Matthew Wilcox 写道: > On Tue, Dec 05, 2023 at 08:37:15PM +0800, Yu Kuai wrote: >> +struct folio *bdev_read_folio(struct block_device *bdev, pgoff_t index) >> +{ >> + return read_mapping_folio(bdev->bd_inode->i_mapping, index, NULL); >> +} >> +EXPORT_SYMBOL_GPL(bdev_read_folio); > > I'm coming to the opinion that 'index' is the wrong parameter here. > Looking through all the callers of bdev_read_folio() in this patchset, > they all have a position in bytes, and they all convert it to > index for this call. The API should probably be: > > struct folio *bdev_read_folio(struct block_device *bdev, loff_t pos) > { > return read_mapping_folio(bdev->bd_inode->i_mapping, > pos / PAGE_SIZE, NULL); > } Thanks for reviewing this patchset! Okay, I'll convert to pass in "pos" in v2. > > ... and at some point, we'll get round to converting read_mapping_folio() > to take its argument in loff_t. > > Similiarly for these two APIs: > >> +struct folio *bdev_read_folio_gfp(struct block_device *bdev, pgoff_t index, >> + gfp_t gfp) >> +struct folio *bdev_get_folio(struct block_device *bdev, pgoff_t index) > >> +struct folio *bdev_find_or_create_folio(struct block_device *bdev, >> + pgoff_t index, gfp_t gfp) >> +{ >> + return __filemap_get_folio(bdev->bd_inode->i_mapping, index, >> + FGP_LOCK | FGP_ACCESSED | FGP_CREAT, gfp); >> +} >> +EXPORT_SYMBOL_GPL(bdev_find_or_create_folio); > > This one probably shouldn't exist. I've been converting callers of > find_or_create_page() to call __filemap_get_folio; I suspect we > should expose a __bdev_get_folio and have the callers use the FGP > arguments directly, but I'm open to other opinions here. If nobody against this, I will expose single __bdev_get_folio() to use in v2. > >> +void bdev_sync_readahead(struct block_device *bdev, struct file_ra_state *ra, >> + struct file *file, pgoff_t index, >> + unsigned long req_count) >> +{ >> + struct file_ra_state tmp_ra = {}; >> + >> + if (!ra) { >> + ra = &tmp_ra; >> + file_ra_state_init(ra, bdev->bd_inode->i_mapping); >> + } >> + page_cache_sync_readahead(bdev->bd_inode->i_mapping, ra, file, index, >> + req_count); >> +} > > I think the caller should always be passing in a valid file_ra_state. > It's only cramfs that doesn't have one, and it really should! > Not entirely sure about the arguments here; part of me says "bytes", > but this is weird enough to maybe take arguments in pages. In fact, bdev_sync_readahead() is only called for cramfs and ext4. For ext4 it's used in ext4_readdir() so there is valid file_ra_state. Hoever, for cramfs it's used in cramfs_read(), and cramfs_read() is used for: 1) cramfs_read_folio 2) cramfs_readdir 3) cramfs_lookup 4) cramfs_read_super Looks like it's easy to pass in valid file_ra_state() for 1) and 2), however, I don't see an easy way to do this for 3) and 4). Thanks, Kuai > > . >
diff --git a/block/bdev.c b/block/bdev.c index 6f73b02d549c..fcba5c1bd113 100644 --- a/block/bdev.c +++ b/block/bdev.c @@ -92,6 +92,13 @@ void invalidate_bdev(struct block_device *bdev) } EXPORT_SYMBOL(invalidate_bdev); +void invalidate_bdev_range(struct block_device *bdev, pgoff_t start, + pgoff_t end) +{ + invalidate_mapping_pages(bdev->bd_inode->i_mapping, start, end); +} +EXPORT_SYMBOL_GPL(invalidate_bdev_range); + /* * Drop all buffers & page cache for given bdev range. This function bails * with error if bdev has other exclusive owner (such as filesystem). @@ -124,6 +131,7 @@ int truncate_bdev_range(struct block_device *bdev, blk_mode_t mode, lstart >> PAGE_SHIFT, lend >> PAGE_SHIFT); } +EXPORT_SYMBOL_GPL(truncate_bdev_range); static void set_init_blocksize(struct block_device *bdev) { @@ -138,6 +146,18 @@ static void set_init_blocksize(struct block_device *bdev) bdev->bd_inode->i_blkbits = blksize_bits(bsize); } +loff_t bdev_size(struct block_device *bdev) +{ + loff_t size; + + spin_lock(&bdev->bd_size_lock); + size = i_size_read(bdev->bd_inode); + spin_unlock(&bdev->bd_size_lock); + + return size; +} +EXPORT_SYMBOL_GPL(bdev_size); + int set_blocksize(struct block_device *bdev, int size) { /* Size must be a power of two, and between 512 and PAGE_SIZE */ @@ -1144,3 +1164,99 @@ static int __init setup_bdev_allow_write_mounted(char *str) return 1; } __setup("bdev_allow_write_mounted=", setup_bdev_allow_write_mounted); + +struct folio *bdev_read_folio(struct block_device *bdev, pgoff_t index) +{ + return read_mapping_folio(bdev->bd_inode->i_mapping, index, NULL); +} +EXPORT_SYMBOL_GPL(bdev_read_folio); + +struct folio *bdev_read_folio_gfp(struct block_device *bdev, pgoff_t index, + gfp_t gfp) +{ + return mapping_read_folio_gfp(bdev->bd_inode->i_mapping, index, gfp); +} +EXPORT_SYMBOL_GPL(bdev_read_folio_gfp); + +struct folio *bdev_get_folio(struct block_device *bdev, pgoff_t index) +{ + return filemap_get_folio(bdev->bd_inode->i_mapping, index); +} +EXPORT_SYMBOL_GPL(bdev_get_folio); + +struct folio *bdev_find_or_create_folio(struct block_device *bdev, + pgoff_t index, gfp_t gfp) +{ + return __filemap_get_folio(bdev->bd_inode->i_mapping, index, + FGP_LOCK | FGP_ACCESSED | FGP_CREAT, gfp); +} +EXPORT_SYMBOL_GPL(bdev_find_or_create_folio); + +int bdev_wb_err_check(struct block_device *bdev, errseq_t since) +{ + return errseq_check(&bdev->bd_inode->i_mapping->wb_err, since); +} +EXPORT_SYMBOL_GPL(bdev_wb_err_check); + +int bdev_wb_err_check_and_advance(struct block_device *bdev, errseq_t *since) +{ + return errseq_check_and_advance(&bdev->bd_inode->i_mapping->wb_err, + since); +} +EXPORT_SYMBOL_GPL(bdev_wb_err_check_and_advance); + +void bdev_balance_dirty_pages_ratelimited(struct block_device *bdev) +{ + return balance_dirty_pages_ratelimited(bdev->bd_inode->i_mapping); +} +EXPORT_SYMBOL_GPL(bdev_balance_dirty_pages_ratelimited); + +void bdev_sync_readahead(struct block_device *bdev, struct file_ra_state *ra, + struct file *file, pgoff_t index, + unsigned long req_count) +{ + struct file_ra_state tmp_ra = {}; + + if (!ra) { + ra = &tmp_ra; + file_ra_state_init(ra, bdev->bd_inode->i_mapping); + } + page_cache_sync_readahead(bdev->bd_inode->i_mapping, ra, file, index, + req_count); +} +EXPORT_SYMBOL_GPL(bdev_sync_readahead); + +void bdev_attach_wb(struct block_device *bdev) +{ + inode_attach_wb(bdev->bd_inode, NULL); +} +EXPORT_SYMBOL_GPL(bdev_attach_wb); + +void bdev_correlate_mapping(struct block_device *bdev, + struct address_space *mapping) +{ + mapping->host = bdev->bd_inode; +} +EXPORT_SYMBOL_GPL(bdev_correlate_mapping); + +gfp_t bdev_gfp_constraint(struct block_device *bdev, gfp_t gfp) +{ + return mapping_gfp_constraint(bdev->bd_inode->i_mapping, gfp); +} +EXPORT_SYMBOL_GPL(bdev_gfp_constraint); + +/* + * The del_gendisk() function uninitializes the disk-specific data + * structures, including the bdi structure, without telling anyone + * else. Once this happens, any attempt to call mark_buffer_dirty() + * (for example, by ext4_commit_super), will cause a kernel OOPS. + * This is a kludge to prevent these oops until we can put in a proper + * hook in del_gendisk() to inform the VFS and file system layers. + */ +int bdev_ejected(struct block_device *bdev) +{ + struct backing_dev_info *bdi = inode_to_bdi(bdev->bd_inode); + + return bdi->dev == NULL; +} +EXPORT_SYMBOL_GPL(bdev_ejected); diff --git a/block/bio.c b/block/bio.c index 816d412c06e9..f7123ad9b4ee 100644 --- a/block/bio.c +++ b/block/bio.c @@ -1119,6 +1119,7 @@ void bio_add_folio_nofail(struct bio *bio, struct folio *folio, size_t len, WARN_ON_ONCE(off > UINT_MAX); __bio_add_page(bio, &folio->page, len, off); } +EXPORT_SYMBOL_GPL(bio_add_folio_nofail); /** * bio_add_folio - Attempt to add part of a folio to a bio. diff --git a/block/blk.h b/block/blk.h index 08a358bc0919..da4becd4f7e9 100644 --- a/block/blk.h +++ b/block/blk.h @@ -467,8 +467,6 @@ extern struct device_attribute dev_attr_events_poll_msecs; extern struct attribute_group blk_trace_attr_group; blk_mode_t file_to_blk_mode(struct file *file); -int truncate_bdev_range(struct block_device *bdev, blk_mode_t mode, - loff_t lstart, loff_t lend); long blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg); long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 3f8a21cd9233..a55db77274a4 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -1342,6 +1342,11 @@ static inline unsigned int block_size(struct block_device *bdev) return 1 << bdev->bd_inode->i_blkbits; } +static inline u8 block_bits(struct block_device *bdev) +{ + return bdev->bd_inode->i_blkbits; +} + int kblockd_schedule_work(struct work_struct *work); int kblockd_mod_delayed_work_on(int cpu, struct delayed_work *dwork, unsigned long delay); @@ -1515,6 +1520,28 @@ struct block_device *blkdev_get_no_open(dev_t dev); void blkdev_put_no_open(struct block_device *bdev); struct block_device *I_BDEV(struct inode *inode); +loff_t bdev_size(struct block_device *bdev); +void invalidate_bdev_range(struct block_device *bdev, pgoff_t start, + pgoff_t end); +int truncate_bdev_range(struct block_device *bdev, blk_mode_t mode, + loff_t lstart, loff_t lend); +struct folio *bdev_get_folio(struct block_device *bdev, pgoff_t index); +struct folio *bdev_find_or_create_folio(struct block_device *bdev, + pgoff_t index, gfp_t gfp); +struct folio *bdev_read_folio(struct block_device *bdev, pgoff_t index); +struct folio *bdev_read_folio_gfp(struct block_device *bdev, pgoff_t index, + gfp_t gfp); +int bdev_wb_err_check(struct block_device *bdev, errseq_t since); +int bdev_wb_err_check_and_advance(struct block_device *bdev, errseq_t *since); +void bdev_balance_dirty_pages_ratelimited(struct block_device *bdev); +void bdev_sync_readahead(struct block_device *bdev, struct file_ra_state *ra, + struct file *file, pgoff_t index, + unsigned long req_count); +void bdev_attach_wb(struct block_device *bdev); +void bdev_correlate_mapping(struct block_device *bdev, + struct address_space *mapping); +gfp_t bdev_gfp_constraint(struct block_device *bdev, gfp_t gfp); +int bdev_ejected(struct block_device *bdev); #ifdef CONFIG_BLOCK void invalidate_bdev(struct block_device *bdev);