2225 lines · 55.0 KB · C
RawDownload
/* *  linux/fs/block_dev.c * *  Copyright (C) 1991, 1992  Linus Torvalds *  Copyright (C) 2001  Andrea Arcangeli <andrea@suse.de> SuSE */ #include <linux/init.h>#include <linux/mm.h>#include <linux/fcntl.h>#include <linux/slab.h>#include <linux/kmod.h>#include <linux/major.h>#include <linux/device_cgroup.h>#include <linux/highmem.h>#include <linux/blkdev.h>#include <linux/backing-dev.h>#include <linux/module.h>#include <linux/blkpg.h>#include <linux/magic.h>#include <linux/dax.h>#include <linux/buffer_head.h>#include <linux/swap.h>#include <linux/pagevec.h>#include <linux/writeback.h>#include <linux/mpage.h>#include <linux/mount.h>#include <linux/uio.h>#include <linux/namei.h>#include <linux/log2.h>#include <linux/cleancache.h>#include <linux/dax.h>#include <linux/badblocks.h>#include <linux/task_io_accounting_ops.h>#include <linux/falloc.h>#include <linux/uaccess.h>#include "internal.h" struct bdev_inode {	struct block_device bdev;	struct inode vfs_inode;}; static const struct address_space_operations def_blk_aops; static inline struct bdev_inode *BDEV_I(struct inode *inode){	return container_of(inode, struct bdev_inode, vfs_inode);} struct block_device *I_BDEV(struct inode *inode){	return &BDEV_I(inode)->bdev;}EXPORT_SYMBOL(I_BDEV); static void bdev_write_inode(struct block_device *bdev){	struct inode *inode = bdev->bd_inode;	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) {			char name[BDEVNAME_SIZE];			pr_warn_ratelimited("VFS: Dirty inode writeback failed "					    "for block device %s (err=%d).\n",					    bdevname(bdev, name), ret);		}		spin_lock(&inode->i_lock);	}	spin_unlock(&inode->i_lock);} /* Kill _all_ buffers and pagecache , dirty or not.. */void kill_bdev(struct block_device *bdev){	struct address_space *mapping = bdev->bd_inode->i_mapping; 	if (mapping->nrpages == 0 && mapping->nrexceptional == 0)		return; 	invalidate_bh_lrus();	truncate_inode_pages(mapping, 0);}	EXPORT_SYMBOL(kill_bdev); /* Invalidate clean unused buffers and pagecache. */void invalidate_bdev(struct block_device *bdev){	struct address_space *mapping = bdev->bd_inode->i_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);	}	/* 99% of the time, we don't need to flush the cleancache on the bdev.	 * But, for the strange corners, lets be cautious	 */	cleancache_invalidate_inode(mapping);}EXPORT_SYMBOL(invalidate_bdev); static void set_init_blocksize(struct block_device *bdev){	unsigned bsize = bdev_logical_block_size(bdev);	loff_t size = i_size_read(bdev->bd_inode); 	while (bsize < PAGE_SIZE) {		if (size & bsize)			break;		bsize <<= 1;	}	bdev->bd_block_size = bsize;	bdev->bd_inode->i_blkbits = blksize_bits(bsize);} int set_blocksize(struct block_device *bdev, int size){	/* Size must be a power of two, and between 512 and PAGE_SIZE */	if (size > PAGE_SIZE || size < 512 || !is_power_of_2(size))		return -EINVAL; 	/* Size cannot be smaller than the size supported by the device */	if (size < bdev_logical_block_size(bdev))		return -EINVAL; 	/* Don't change the size if it is same as current */	if (bdev->bd_block_size != size) {		sync_blockdev(bdev);		bdev->bd_block_size = size;		bdev->bd_inode->i_blkbits = blksize_bits(size);		kill_bdev(bdev);	}	return 0;} EXPORT_SYMBOL(set_blocksize); int sb_set_blocksize(struct super_block *sb, int size){	if (set_blocksize(sb->s_bdev, size))		return 0;	/* If we get here, we know size is power of two	 * and it's value is between 512 and PAGE_SIZE */	sb->s_blocksize = size;	sb->s_blocksize_bits = blksize_bits(size);	return sb->s_blocksize;} EXPORT_SYMBOL(sb_set_blocksize); int 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); static intblkdev_get_block(struct inode *inode, sector_t iblock,		struct buffer_head *bh, int create){	bh->b_bdev = I_BDEV(inode);	bh->b_blocknr = iblock;	set_buffer_mapped(bh);	return 0;} static struct inode *bdev_file_inode(struct file *file){	return file->f_mapping->host;} static unsigned int dio_bio_write_op(struct kiocb *iocb){	unsigned int op = REQ_OP_WRITE | REQ_SYNC | REQ_IDLE; 	/* avoid the need for a I/O completion work item */	if (iocb->ki_flags & IOCB_DSYNC)		op |= REQ_FUA;	return op;} #define DIO_INLINE_BIO_VECS 4 static void blkdev_bio_end_io_simple(struct bio *bio){	struct task_struct *waiter = bio->bi_private; 	WRITE_ONCE(bio->bi_private, NULL);	blk_wake_io_task(waiter);} static ssize_t__blkdev_direct_IO_simple(struct kiocb *iocb, struct iov_iter *iter,		int nr_pages){	struct file *file = iocb->ki_filp;	struct block_device *bdev = I_BDEV(bdev_file_inode(file));	struct bio_vec inline_vecs[DIO_INLINE_BIO_VECS], *vecs, *bvec;	loff_t pos = iocb->ki_pos;	bool should_dirty = false;	struct bio bio;	ssize_t ret;	blk_qc_t qc;	int i;	struct bvec_iter_all iter_all; 	if ((pos | iov_iter_alignment(iter)) &	    (bdev_logical_block_size(bdev) - 1))		return -EINVAL; 	if (nr_pages <= DIO_INLINE_BIO_VECS)		vecs = inline_vecs;	else {		vecs = kmalloc_array(nr_pages, sizeof(struct bio_vec),				     GFP_KERNEL);		if (!vecs)			return -ENOMEM;	} 	bio_init(&bio, vecs, nr_pages);	bio_set_dev(&bio, bdev);	bio.bi_iter.bi_sector = pos >> 9;	bio.bi_write_hint = iocb->ki_hint;	bio.bi_private = current;	bio.bi_end_io = blkdev_bio_end_io_simple;	bio.bi_ioprio = iocb->ki_ioprio; 	ret = bio_iov_iter_get_pages(&bio, iter);	if (unlikely(ret))		goto out;	ret = bio.bi_iter.bi_size; 	if (iov_iter_rw(iter) == READ) {		bio.bi_opf = REQ_OP_READ;		if (iter_is_iovec(iter))			should_dirty = true;	} else {		bio.bi_opf = dio_bio_write_op(iocb);		task_io_account_write(ret);	}	if (iocb->ki_flags & IOCB_HIPRI)		bio_set_polled(&bio, iocb); 	qc = submit_bio(&bio);	for (;;) {		set_current_state(TASK_UNINTERRUPTIBLE);		if (!READ_ONCE(bio.bi_private))			break;		if (!(iocb->ki_flags & IOCB_HIPRI) ||		    !blk_poll(bdev_get_queue(bdev), qc, true))			io_schedule();	}	__set_current_state(TASK_RUNNING); 	bio_for_each_segment_all(bvec, &bio, i, iter_all) {		if (should_dirty && !PageCompound(bvec->bv_page))			set_page_dirty_lock(bvec->bv_page);		if (!bio_flagged(&bio, BIO_NO_PAGE_REF))			put_page(bvec->bv_page);	} 	if (unlikely(bio.bi_status))		ret = blk_status_to_errno(bio.bi_status); out:	if (vecs != inline_vecs)		kfree(vecs); 	bio_uninit(&bio); 	return ret;} struct blkdev_dio {	union {		struct kiocb		*iocb;		struct task_struct	*waiter;	};	size_t			size;	atomic_t		ref;	bool			multi_bio : 1;	bool			should_dirty : 1;	bool			is_sync : 1;	struct bio		bio;}; static struct bio_set blkdev_dio_pool; static int blkdev_iopoll(struct kiocb *kiocb, bool wait){	struct block_device *bdev = I_BDEV(kiocb->ki_filp->f_mapping->host);	struct request_queue *q = bdev_get_queue(bdev); 	return blk_poll(q, READ_ONCE(kiocb->ki_cookie), wait);} static void blkdev_bio_end_io(struct bio *bio){	struct blkdev_dio *dio = bio->bi_private;	bool should_dirty = dio->should_dirty; 	if (bio->bi_status && !dio->bio.bi_status)		dio->bio.bi_status = bio->bi_status; 	if (!dio->multi_bio || atomic_dec_and_test(&dio->ref)) {		if (!dio->is_sync) {			struct kiocb *iocb = dio->iocb;			ssize_t ret; 			if (likely(!dio->bio.bi_status)) {				ret = dio->size;				iocb->ki_pos += ret;			} else {				ret = blk_status_to_errno(dio->bio.bi_status);			} 			dio->iocb->ki_complete(iocb, ret, 0);			if (dio->multi_bio)				bio_put(&dio->bio);		} else {			struct task_struct *waiter = dio->waiter; 			WRITE_ONCE(dio->waiter, NULL);			blk_wake_io_task(waiter);		}	} 	if (should_dirty) {		bio_check_pages_dirty(bio);	} else {		if (!bio_flagged(bio, BIO_NO_PAGE_REF)) {			struct bvec_iter_all iter_all;			struct bio_vec *bvec;			int i; 			bio_for_each_segment_all(bvec, bio, i, iter_all)				put_page(bvec->bv_page);		}		bio_put(bio);	}} static ssize_t__blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, int nr_pages){	struct file *file = iocb->ki_filp;	struct inode *inode = bdev_file_inode(file);	struct block_device *bdev = I_BDEV(inode);	struct blk_plug plug;	struct blkdev_dio *dio;	struct bio *bio;	bool is_poll = (iocb->ki_flags & IOCB_HIPRI) != 0;	bool is_read = (iov_iter_rw(iter) == READ), is_sync;	loff_t pos = iocb->ki_pos;	blk_qc_t qc = BLK_QC_T_NONE;	int ret = 0; 	if ((pos | iov_iter_alignment(iter)) &	    (bdev_logical_block_size(bdev) - 1))		return -EINVAL; 	bio = bio_alloc_bioset(GFP_KERNEL, nr_pages, &blkdev_dio_pool); 	dio = container_of(bio, struct blkdev_dio, bio);	dio->is_sync = is_sync = is_sync_kiocb(iocb);	if (dio->is_sync) {		dio->waiter = current;		bio_get(bio);	} else {		dio->iocb = iocb;	} 	dio->size = 0;	dio->multi_bio = false;	dio->should_dirty = is_read && iter_is_iovec(iter); 	/*	 * Don't plug for HIPRI/polled IO, as those should go straight	 * to issue	 */	if (!is_poll)		blk_start_plug(&plug); 	for (;;) {		bio_set_dev(bio, bdev);		bio->bi_iter.bi_sector = pos >> 9;		bio->bi_write_hint = iocb->ki_hint;		bio->bi_private = dio;		bio->bi_end_io = blkdev_bio_end_io;		bio->bi_ioprio = iocb->ki_ioprio; 		ret = bio_iov_iter_get_pages(bio, iter);		if (unlikely(ret)) {			bio->bi_status = BLK_STS_IOERR;			bio_endio(bio);			break;		} 		if (is_read) {			bio->bi_opf = REQ_OP_READ;			if (dio->should_dirty)				bio_set_pages_dirty(bio);		} else {			bio->bi_opf = dio_bio_write_op(iocb);			task_io_account_write(bio->bi_iter.bi_size);		} 		dio->size += bio->bi_iter.bi_size;		pos += bio->bi_iter.bi_size; 		nr_pages = iov_iter_npages(iter, BIO_MAX_PAGES);		if (!nr_pages) {			bool polled = false; 			if (iocb->ki_flags & IOCB_HIPRI) {				bio_set_polled(bio, iocb);				polled = true;			} 			qc = submit_bio(bio); 			if (polled)				WRITE_ONCE(iocb->ki_cookie, qc);			break;		} 		if (!dio->multi_bio) {			/*			 * AIO needs an extra reference to ensure the dio			 * structure which is embedded into the first bio			 * stays around.			 */			if (!is_sync)				bio_get(bio);			dio->multi_bio = true;			atomic_set(&dio->ref, 2);		} else {			atomic_inc(&dio->ref);		} 		submit_bio(bio);		bio = bio_alloc(GFP_KERNEL, nr_pages);	} 	if (!is_poll)		blk_finish_plug(&plug); 	if (!is_sync)		return -EIOCBQUEUED; 	for (;;) {		set_current_state(TASK_UNINTERRUPTIBLE);		if (!READ_ONCE(dio->waiter))			break; 		if (!(iocb->ki_flags & IOCB_HIPRI) ||		    !blk_poll(bdev_get_queue(bdev), qc, true))			io_schedule();	}	__set_current_state(TASK_RUNNING); 	if (!ret)		ret = blk_status_to_errno(dio->bio.bi_status);	if (likely(!ret))		ret = dio->size; 	bio_put(&dio->bio);	return ret;} static ssize_tblkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter){	int nr_pages; 	nr_pages = iov_iter_npages(iter, BIO_MAX_PAGES + 1);	if (!nr_pages)		return 0;	if (is_sync_kiocb(iocb) && nr_pages <= BIO_MAX_PAGES)		return __blkdev_direct_IO_simple(iocb, iter, nr_pages); 	return __blkdev_direct_IO(iocb, iter, min(nr_pages, BIO_MAX_PAGES));} static __init int blkdev_init(void){	return bioset_init(&blkdev_dio_pool, 4, offsetof(struct blkdev_dio, bio), BIOSET_NEED_BVECS);}module_init(blkdev_init); int __sync_blockdev(struct block_device *bdev, int wait)

Lines 1–500 of 2225.