1366 lines · 34.7 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-only/* *  Copyright (C) 1991, 1992  Linus Torvalds *  Copyright (C) 2001  Andrea Arcangeli <andrea@suse.de> SuSE *  Copyright (C) 2016 - 2020 Christoph Hellwig */ #include <linux/init.h>#include <linux/mm.h>#include <linux/slab.h>#include <linux/kmod.h>#include <linux/major.h>#include <linux/device_cgroup.h>#include <linux/blkdev.h>#include <linux/blk-integrity.h>#include <linux/backing-dev.h>#include <linux/module.h>#include <linux/blkpg.h>#include <linux/magic.h>#include <linux/buffer_head.h>#include <linux/swap.h>#include <linux/writeback.h>#include <linux/mount.h>#include <linux/pseudo_fs.h>#include <linux/uio.h>#include <linux/namei.h>#include <linux/security.h>#include <linux/part_stat.h>#include <linux/uaccess.h>#include <linux/stat.h>#include "../fs/internal.h"#include "blk.h" /* Should we allow writing to mounted block devices? */static bool bdev_allow_write_mounted = IS_ENABLED(CONFIG_BLK_DEV_WRITE_MOUNTED); struct bdev_inode {	struct block_device bdev;	struct inode vfs_inode;}; static inline struct bdev_inode *BDEV_I(struct inode *inode){	return container_of(inode, struct bdev_inode, vfs_inode);} static inline struct inode *BD_INODE(struct block_device *bdev){	return &container_of(bdev, struct bdev_inode, bdev)->vfs_inode;} struct block_device *I_BDEV(struct inode *inode){	return &BDEV_I(inode)->bdev;}EXPORT_SYMBOL(I_BDEV); struct block_device *file_bdev(struct file *bdev_file){	return I_BDEV(bdev_file->f_mapping->host);}EXPORT_SYMBOL(file_bdev); static void bdev_write_inode(struct block_device *bdev){	struct inode *inode = BD_INODE(bdev);	int ret; 	spin_lock(&inode->i_lock);	while (inode->i_state & I_DIRTY) {		spin_unlock(&inode->i_lock);		ret = write_inode_now(inode, true);		if (ret)			pr_warn_ratelimited(	"VFS: Dirty inode writeback failed for block device %pg (err=%d).\n",				bdev, ret);		spin_lock(&inode->i_lock);	}	spin_unlock(&inode->i_lock);} /* Kill _all_ buffers and pagecache , dirty or not.. */static void kill_bdev(struct block_device *bdev){	struct address_space *mapping = bdev->bd_mapping; 	if (mapping_empty(mapping))		return; 	invalidate_bh_lrus();	truncate_inode_pages(mapping, 0);} /* Invalidate clean unused buffers and pagecache. */void invalidate_bdev(struct block_device *bdev){	struct address_space *mapping = bdev->bd_mapping; 	if (mapping->nrpages) {		invalidate_bh_lrus();		lru_add_drain_all();	/* make sure all lru add caches are flushed */		invalidate_mapping_pages(mapping, 0, -1);	}}EXPORT_SYMBOL(invalidate_bdev); /* * Drop all buffers & page cache for given bdev range. This function bails * with error if bdev has other exclusive owner (such as filesystem). */int truncate_bdev_range(struct block_device *bdev, blk_mode_t mode,			loff_t lstart, loff_t lend){	/*	 * If we don't hold exclusive handle for the device, upgrade to it	 * while we discard the buffer cache to avoid discarding buffers	 * under live filesystem.	 */	if (!(mode & BLK_OPEN_EXCL)) {		int err = bd_prepare_to_claim(bdev, truncate_bdev_range, NULL);		if (err)			goto invalidate;	} 	truncate_inode_pages_range(bdev->bd_mapping, lstart, lend);	if (!(mode & BLK_OPEN_EXCL))		bd_abort_claiming(bdev, truncate_bdev_range);	return 0; invalidate:	/*	 * Someone else has handle exclusively open. Try invalidating instead.	 * The 'end' argument is inclusive so the rounding is safe.	 */	return invalidate_inode_pages2_range(bdev->bd_mapping,					     lstart >> PAGE_SHIFT,					     lend >> PAGE_SHIFT);} static void set_init_blocksize(struct block_device *bdev){	unsigned int bsize = bdev_logical_block_size(bdev);	loff_t size = i_size_read(BD_INODE(bdev)); 	while (bsize < PAGE_SIZE) {		if (size & bsize)			break;		bsize <<= 1;	}	BD_INODE(bdev)->i_blkbits = blksize_bits(bsize);	mapping_set_folio_min_order(BD_INODE(bdev)->i_mapping,				    get_order(bsize));} /** * bdev_validate_blocksize - check that this block size is acceptable * @bdev:	blockdevice to check * @block_size:	block size to check * * For block device users that do not use buffer heads or the block device * page cache, make sure that this block size can be used with the device. * * Return: On success zero is returned, negative error code on failure. */int bdev_validate_blocksize(struct block_device *bdev, int block_size){	if (blk_validate_block_size(block_size))		return -EINVAL; 	/* Size cannot be smaller than the size supported by the device */	if (block_size < bdev_logical_block_size(bdev))		return -EINVAL; 	return 0;}EXPORT_SYMBOL_GPL(bdev_validate_blocksize); int set_blocksize(struct file *file, int size){	struct inode *inode = file->f_mapping->host;	struct block_device *bdev = I_BDEV(inode);	int ret; 	ret = bdev_validate_blocksize(bdev, size);	if (ret)		return ret; 	if (!file->private_data)		return -EINVAL; 	/* Don't change the size if it is same as current */	if (inode->i_blkbits != blksize_bits(size)) {		/*		 * Flush and truncate the pagecache before we reconfigure the		 * mapping geometry because folio sizes are variable now.  If a		 * reader has already allocated a folio whose size is smaller		 * than the new min_order but invokes readahead after the new		 * min_order becomes visible, readahead will think there are		 * "zero" blocks per folio and crash.  Take the inode and		 * invalidation locks to avoid racing with		 * read/write/fallocate.		 */		inode_lock(inode);		filemap_invalidate_lock(inode->i_mapping); 		sync_blockdev(bdev);		kill_bdev(bdev); 		inode->i_blkbits = blksize_bits(size);		mapping_set_folio_min_order(inode->i_mapping, get_order(size));		kill_bdev(bdev);		filemap_invalidate_unlock(inode->i_mapping);		inode_unlock(inode);	}	return 0;} EXPORT_SYMBOL(set_blocksize); int sb_set_blocksize(struct super_block *sb, int size){	if (!(sb->s_type->fs_flags & FS_LBS) && size > PAGE_SIZE)		return 0;	if (set_blocksize(sb->s_bdev_file, size))		return 0;	/* If we get here, we know size is validated */	sb->s_blocksize = size;	sb->s_blocksize_bits = blksize_bits(size);	return sb->s_blocksize;} EXPORT_SYMBOL(sb_set_blocksize); int __must_check sb_min_blocksize(struct super_block *sb, int size){	int minsize = bdev_logical_block_size(sb->s_bdev);	if (size < minsize)		size = minsize;	return sb_set_blocksize(sb, size);} EXPORT_SYMBOL(sb_min_blocksize); int sync_blockdev_nowait(struct block_device *bdev){	if (!bdev)		return 0;	return filemap_flush(bdev->bd_mapping);}EXPORT_SYMBOL_GPL(sync_blockdev_nowait); /* * Write out and wait upon all the dirty data associated with a block * device via its mapping.  Does not take the superblock lock. */int sync_blockdev(struct block_device *bdev){	if (!bdev)		return 0;	return filemap_write_and_wait(bdev->bd_mapping);}EXPORT_SYMBOL(sync_blockdev); int sync_blockdev_range(struct block_device *bdev, loff_t lstart, loff_t lend){	return filemap_write_and_wait_range(bdev->bd_mapping,			lstart, lend);}EXPORT_SYMBOL(sync_blockdev_range); /** * bdev_freeze - lock a filesystem and force it into a consistent state * @bdev:	blockdevice to lock * * If a superblock is found on this device, we take the s_umount semaphore * on it to make sure nobody unmounts until the snapshot creation is done. * The reference counter (bd_fsfreeze_count) guarantees that only the last * unfreeze process can unfreeze the frozen filesystem actually when multiple * freeze requests arrive simultaneously. It counts up in bdev_freeze() and * count down in bdev_thaw(). When it becomes 0, thaw_bdev() will unfreeze * actually. * * Return: On success zero is returned, negative error code on failure. */int bdev_freeze(struct block_device *bdev){	int error = 0; 	mutex_lock(&bdev->bd_fsfreeze_mutex); 	if (atomic_inc_return(&bdev->bd_fsfreeze_count) > 1) {		mutex_unlock(&bdev->bd_fsfreeze_mutex);		return 0;	} 	mutex_lock(&bdev->bd_holder_lock);	if (bdev->bd_holder_ops && bdev->bd_holder_ops->freeze) {		error = bdev->bd_holder_ops->freeze(bdev);		lockdep_assert_not_held(&bdev->bd_holder_lock);	} else {		mutex_unlock(&bdev->bd_holder_lock);		error = sync_blockdev(bdev);	} 	if (error)		atomic_dec(&bdev->bd_fsfreeze_count); 	mutex_unlock(&bdev->bd_fsfreeze_mutex);	return error;}EXPORT_SYMBOL(bdev_freeze); /** * bdev_thaw - unlock filesystem * @bdev:	blockdevice to unlock * * Unlocks the filesystem and marks it writeable again after bdev_freeze(). * * Return: On success zero is returned, negative error code on failure. */int bdev_thaw(struct block_device *bdev){	int error = -EINVAL, nr_freeze; 	mutex_lock(&bdev->bd_fsfreeze_mutex); 	/*	 * If this returns < 0 it means that @bd_fsfreeze_count was	 * already 0 and no decrement was performed.	 */	nr_freeze = atomic_dec_if_positive(&bdev->bd_fsfreeze_count);	if (nr_freeze < 0)		goto out; 	error = 0;	if (nr_freeze > 0)		goto out; 	mutex_lock(&bdev->bd_holder_lock);	if (bdev->bd_holder_ops && bdev->bd_holder_ops->thaw) {		error = bdev->bd_holder_ops->thaw(bdev);		lockdep_assert_not_held(&bdev->bd_holder_lock);	} else {		mutex_unlock(&bdev->bd_holder_lock);	} 	if (error)		atomic_inc(&bdev->bd_fsfreeze_count);out:	mutex_unlock(&bdev->bd_fsfreeze_mutex);	return error;}EXPORT_SYMBOL(bdev_thaw); /* * pseudo-fs */ static  __cacheline_aligned_in_smp DEFINE_MUTEX(bdev_lock);static struct kmem_cache *bdev_cachep __ro_after_init; static struct inode *bdev_alloc_inode(struct super_block *sb){	struct bdev_inode *ei = alloc_inode_sb(sb, bdev_cachep, GFP_KERNEL); 	if (!ei)		return NULL;	memset(&ei->bdev, 0, sizeof(ei->bdev)); 	if (security_bdev_alloc(&ei->bdev)) {		kmem_cache_free(bdev_cachep, ei);		return NULL;	}	return &ei->vfs_inode;} static void bdev_free_inode(struct inode *inode){	struct block_device *bdev = I_BDEV(inode); 	free_percpu(bdev->bd_stats);	kfree(bdev->bd_meta_info);	security_bdev_free(bdev); 	if (!bdev_is_partition(bdev)) {		if (bdev->bd_disk && bdev->bd_disk->bdi)			bdi_put(bdev->bd_disk->bdi);		kfree(bdev->bd_disk);	} 	if (MAJOR(bdev->bd_dev) == BLOCK_EXT_MAJOR)		blk_free_ext_minor(MINOR(bdev->bd_dev)); 	kmem_cache_free(bdev_cachep, BDEV_I(inode));} static void init_once(void *data){	struct bdev_inode *ei = data; 	inode_init_once(&ei->vfs_inode);} static void bdev_evict_inode(struct inode *inode){	truncate_inode_pages_final(&inode->i_data);	invalidate_inode_buffers(inode); /* is it needed here? */	clear_inode(inode);} static const struct super_operations bdev_sops = {	.statfs = simple_statfs,	.alloc_inode = bdev_alloc_inode,	.free_inode = bdev_free_inode,	.drop_inode = inode_just_drop,	.evict_inode = bdev_evict_inode,}; static int bd_init_fs_context(struct fs_context *fc){	struct pseudo_fs_context *ctx = init_pseudo(fc, BDEVFS_MAGIC);	if (!ctx)		return -ENOMEM;	fc->s_iflags |= SB_I_CGROUPWB;	ctx->ops = &bdev_sops;	return 0;} static struct file_system_type bd_type = {	.name		= "bdev",	.init_fs_context = bd_init_fs_context,	.kill_sb	= kill_anon_super,}; struct super_block *blockdev_superblock __ro_after_init;static struct vfsmount *blockdev_mnt __ro_after_init;EXPORT_SYMBOL_GPL(blockdev_superblock); void __init bdev_cache_init(void){	int err; 	bdev_cachep = kmem_cache_create("bdev_cache", sizeof(struct bdev_inode),			0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|				SLAB_ACCOUNT|SLAB_PANIC),			init_once);	err = register_filesystem(&bd_type);	if (err)		panic("Cannot register bdev pseudo-fs");	blockdev_mnt = kern_mount(&bd_type);	if (IS_ERR(blockdev_mnt))		panic("Cannot create bdev pseudo-fs");	blockdev_superblock = blockdev_mnt->mnt_sb;   /* For writeback */} struct block_device *bdev_alloc(struct gendisk *disk, u8 partno){	struct block_device *bdev;	struct inode *inode; 	inode = new_inode(blockdev_superblock);	if (!inode)		return NULL;	inode->i_mode = S_IFBLK;	inode->i_rdev = 0;	inode->i_data.a_ops = &def_blk_aops;	mapping_set_gfp_mask(&inode->i_data, GFP_USER); 	bdev = I_BDEV(inode);	mutex_init(&bdev->bd_fsfreeze_mutex);	spin_lock_init(&bdev->bd_size_lock);	mutex_init(&bdev->bd_holder_lock);	atomic_set(&bdev->__bd_flags, partno);	bdev->bd_mapping = &inode->i_data;	bdev->bd_queue = disk->queue;	if (partno && bdev_test_flag(disk->part0, BD_HAS_SUBMIT_BIO))		bdev_set_flag(bdev, BD_HAS_SUBMIT_BIO);	bdev->bd_stats = alloc_percpu(struct disk_stats);	if (!bdev->bd_stats) {		iput(inode);		return NULL;	}	bdev->bd_disk = disk;	return bdev;} void bdev_set_nr_sectors(struct block_device *bdev, sector_t sectors){	spin_lock(&bdev->bd_size_lock);	i_size_write(BD_INODE(bdev), (loff_t)sectors << SECTOR_SHIFT);	bdev->bd_nr_sectors = sectors;	spin_unlock(&bdev->bd_size_lock);} void bdev_add(struct block_device *bdev, dev_t dev){	struct inode *inode = BD_INODE(bdev);	if (bdev_stable_writes(bdev))		mapping_set_stable_writes(bdev->bd_mapping);	bdev->bd_dev = dev;

Lines 1–500 of 1366.