Christoph LameterRemove SLAB_CTOR_CONSTRUCTORa35afb819 years agoHistory
1483 lines · 35.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/smp_lock.h>#include <linux/highmem.h>#include <linux/blkdev.h>#include <linux/module.h>#include <linux/blkpg.h>#include <linux/buffer_head.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 <asm/uaccess.h>#include "internal.h" 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);} inline struct block_device *I_BDEV(struct inode *inode){	return &BDEV_I(inode)->bdev;} EXPORT_SYMBOL(I_BDEV); static sector_t max_block(struct block_device *bdev){	sector_t retval = ~((sector_t)0);	loff_t sz = i_size_read(bdev->bd_inode); 	if (sz) {		unsigned int size = block_size(bdev);		unsigned int sizebits = blksize_bits(size);		retval = (sz >> sizebits);	}	return retval;} /* Kill _all_ buffers and pagecache , dirty or not.. */static void kill_bdev(struct block_device *bdev){	if (bdev->bd_inode->i_mapping->nrpages == 0)		return;	invalidate_bh_lrus();	truncate_inode_pages(bdev->bd_inode->i_mapping, 0);}	 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_hardsect_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_hardsect_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){	if (iblock >= max_block(I_BDEV(inode))) {		if (create)			return -EIO; 		/*		 * for reads, we're just trying to fill a partial page.		 * return a hole, they will have to call get_block again		 * before they can fill it, and they will get -EIO at that		 * time		 */		return 0;	}	bh->b_bdev = I_BDEV(inode);	bh->b_blocknr = iblock;	set_buffer_mapped(bh);	return 0;} static intblkdev_get_blocks(struct inode *inode, sector_t iblock,		struct buffer_head *bh, int create){	sector_t end_block = max_block(I_BDEV(inode));	unsigned long max_blocks = bh->b_size >> inode->i_blkbits; 	if ((iblock + max_blocks) > end_block) {		max_blocks = end_block - iblock;		if ((long)max_blocks <= 0) {			if (create)				return -EIO;	/* write fully beyond EOF */			/*			 * It is a read which is fully beyond EOF.  We return			 * a !buffer_mapped buffer			 */			max_blocks = 0;		}	} 	bh->b_bdev = I_BDEV(inode);	bh->b_blocknr = iblock;	bh->b_size = max_blocks << inode->i_blkbits;	if (max_blocks)		set_buffer_mapped(bh);	return 0;} static ssize_tblkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,			loff_t offset, unsigned long nr_segs){	struct file *file = iocb->ki_filp;	struct inode *inode = file->f_mapping->host; 	return blockdev_direct_IO_no_locking(rw, iocb, inode, I_BDEV(inode),				iov, offset, nr_segs, blkdev_get_blocks, NULL);} #if 0static int blk_end_aio(struct bio *bio, unsigned int bytes_done, int error){	struct kiocb *iocb = bio->bi_private;	atomic_t *bio_count = &iocb->ki_bio_count; 	if (bio_data_dir(bio) == READ)		bio_check_pages_dirty(bio);	else {		bio_release_pages(bio);		bio_put(bio);	} 	/* iocb->ki_nbytes stores error code from LLDD */	if (error)		iocb->ki_nbytes = -EIO; 	if (atomic_dec_and_test(bio_count)) {		if ((long)iocb->ki_nbytes < 0)			aio_complete(iocb, iocb->ki_nbytes, 0);		else			aio_complete(iocb, iocb->ki_left, 0);	} 	return 0;} #define VEC_SIZE	16struct pvec {	unsigned short nr;	unsigned short idx;	struct page *page[VEC_SIZE];}; #define PAGES_SPANNED(addr, len)	\	(DIV_ROUND_UP((addr) + (len), PAGE_SIZE) - (addr) / PAGE_SIZE); /* * get page pointer for user addr, we internally cache struct page array for * (addr, count) range in pvec to avoid frequent call to get_user_pages.  If * internal page list is exhausted, a batch count of up to VEC_SIZE is used * to get next set of page struct. */static struct page *blk_get_page(unsigned long addr, size_t count, int rw,				 struct pvec *pvec){	int ret, nr_pages;	if (pvec->idx == pvec->nr) {		nr_pages = PAGES_SPANNED(addr, count);		nr_pages = min(nr_pages, VEC_SIZE);		down_read(&current->mm->mmap_sem);		ret = get_user_pages(current, current->mm, addr, nr_pages,				     rw == READ, 0, pvec->page, NULL);		up_read(&current->mm->mmap_sem);		if (ret < 0)			return ERR_PTR(ret);		pvec->nr = ret;		pvec->idx = 0;	}	return pvec->page[pvec->idx++];} /* return a page back to pvec array */static void blk_unget_page(struct page *page, struct pvec *pvec){	pvec->page[--pvec->idx] = page;} static ssize_tblkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,		 loff_t pos, unsigned long nr_segs){	struct inode *inode = iocb->ki_filp->f_mapping->host;	unsigned blkbits = blksize_bits(bdev_hardsect_size(I_BDEV(inode)));	unsigned blocksize_mask = (1 << blkbits) - 1;	unsigned long seg = 0;	/* iov segment iterator */	unsigned long nvec;	/* number of bio vec needed */	unsigned long cur_off;	/* offset into current page */	unsigned long cur_len;	/* I/O len of current page, up to PAGE_SIZE */ 	unsigned long addr;	/* user iovec address */	size_t count;		/* user iovec len */	size_t nbytes = iocb->ki_nbytes = iocb->ki_left; /* total xfer size */	loff_t size;		/* size of block device */	struct bio *bio;	atomic_t *bio_count = &iocb->ki_bio_count;	struct page *page;	struct pvec pvec; 	pvec.nr = 0;	pvec.idx = 0; 	if (pos & blocksize_mask)		return -EINVAL; 	size = i_size_read(inode);	if (pos + nbytes > size) {		nbytes = size - pos;		iocb->ki_left = nbytes;	} 	/*	 * check first non-zero iov alignment, the remaining	 * iov alignment is checked inside bio loop below.	 */	do {		addr = (unsigned long) iov[seg].iov_base;		count = min(iov[seg].iov_len, nbytes);		if (addr & blocksize_mask || count & blocksize_mask)			return -EINVAL;	} while (!count && ++seg < nr_segs);	atomic_set(bio_count, 1); 	while (nbytes) {		/* roughly estimate number of bio vec needed */		nvec = (nbytes + PAGE_SIZE - 1) / PAGE_SIZE;		nvec = max(nvec, nr_segs - seg);		nvec = min(nvec, (unsigned long) BIO_MAX_PAGES); 		/* bio_alloc should not fail with GFP_KERNEL flag */		bio = bio_alloc(GFP_KERNEL, nvec);		bio->bi_bdev = I_BDEV(inode);		bio->bi_end_io = blk_end_aio;		bio->bi_private = iocb;		bio->bi_sector = pos >> blkbits;same_bio:		cur_off = addr & ~PAGE_MASK;		cur_len = PAGE_SIZE - cur_off;		if (count < cur_len)			cur_len = count; 		page = blk_get_page(addr, count, rw, &pvec);		if (unlikely(IS_ERR(page)))			goto backout; 		if (bio_add_page(bio, page, cur_len, cur_off)) {			pos += cur_len;			addr += cur_len;			count -= cur_len;			nbytes -= cur_len; 			if (count)				goto same_bio;			while (++seg < nr_segs) {				addr = (unsigned long) iov[seg].iov_base;				count = iov[seg].iov_len;				if (!count)					continue;				if (unlikely(addr & blocksize_mask ||					     count & blocksize_mask)) {					page = ERR_PTR(-EINVAL);					goto backout;				}				count = min(count, nbytes);				goto same_bio;			}		} else {			blk_unget_page(page, &pvec);		} 		/* bio is ready, submit it */		if (rw == READ)			bio_set_pages_dirty(bio);		atomic_inc(bio_count);		submit_bio(rw, bio);	} completion:	iocb->ki_left -= nbytes;	nbytes = iocb->ki_left;	iocb->ki_pos += nbytes; 	blk_run_address_space(inode->i_mapping);	if (atomic_dec_and_test(bio_count))		aio_complete(iocb, nbytes, 0); 	return -EIOCBQUEUED; backout:	/*	 * back out nbytes count constructed so far for this bio,	 * we will throw away current bio.	 */	nbytes += bio->bi_size;	bio_release_pages(bio);	bio_put(bio); 	/*	 * if no bio was submmitted, return the error code.	 * otherwise, proceed with pending I/O completion.	 */	if (atomic_read(bio_count) == 1)		return PTR_ERR(page);	goto completion;}#endif static int blkdev_writepage(struct page *page, struct writeback_control *wbc){	return block_write_full_page(page, blkdev_get_block, wbc);} static int blkdev_readpage(struct file * file, struct page * page){	return block_read_full_page(page, blkdev_get_block);} static int blkdev_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to){	return block_prepare_write(page, from, to, blkdev_get_block);} static int blkdev_commit_write(struct file *file, struct page *page, unsigned from, unsigned to){	return block_commit_write(page, from, to);} /* * private llseek: * for a block special file file->f_path.dentry->d_inode->i_size is zero * so we compute the size by hand (just as in block_read/write above) */static loff_t block_llseek(struct file *file, loff_t offset, int origin){	struct inode *bd_inode = file->f_mapping->host;	loff_t size;	loff_t retval; 	mutex_lock(&bd_inode->i_mutex);	size = i_size_read(bd_inode); 	switch (origin) {		case 2:			offset += size;			break;		case 1:			offset += file->f_pos;	}	retval = -EINVAL;	if (offset >= 0 && offset <= size) {		if (offset != file->f_pos) {			file->f_pos = offset;		}		retval = offset;	}	mutex_unlock(&bd_inode->i_mutex);	return retval;}	/* *	Filp is never NULL; the only case when ->fsync() is called with *	NULL first argument is nfsd_sync_dir() and that's not a directory. */ static int block_fsync(struct file *filp, struct dentry *dentry, int datasync){	return sync_blockdev(I_BDEV(filp->f_mapping->host));} /* * pseudo-fs */ static  __cacheline_aligned_in_smp DEFINE_SPINLOCK(bdev_lock);static struct kmem_cache * bdev_cachep __read_mostly; static struct inode *bdev_alloc_inode(struct super_block *sb){	struct bdev_inode *ei = kmem_cache_alloc(bdev_cachep, GFP_KERNEL);	if (!ei)		return NULL;	return &ei->vfs_inode;} static void bdev_destroy_inode(struct inode *inode){	struct bdev_inode *bdi = BDEV_I(inode); 	bdi->bdev.bd_inode_backing_dev_info = NULL;	kmem_cache_free(bdev_cachep, bdi);} static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags){	struct bdev_inode *ei = (struct bdev_inode *) foo;	struct block_device *bdev = &ei->bdev; 	memset(bdev, 0, sizeof(*bdev));	mutex_init(&bdev->bd_mutex);	sema_init(&bdev->bd_mount_sem, 1);	INIT_LIST_HEAD(&bdev->bd_inodes);	INIT_LIST_HEAD(&bdev->bd_list);#ifdef CONFIG_SYSFS	INIT_LIST_HEAD(&bdev->bd_holder_list);#endif	inode_init_once(&ei->vfs_inode);} static inline void __bd_forget(struct inode *inode){	list_del_init(&inode->i_devices);	inode->i_bdev = NULL;	inode->i_mapping = &inode->i_data;} static void bdev_clear_inode(struct inode *inode){	struct block_device *bdev = &BDEV_I(inode)->bdev;	struct list_head *p;	spin_lock(&bdev_lock);	while ( (p = bdev->bd_inodes.next) != &bdev->bd_inodes ) {		__bd_forget(list_entry(p, struct inode, i_devices));	}	list_del_init(&bdev->bd_list);	spin_unlock(&bdev_lock);} static const struct super_operations bdev_sops = {	.statfs = simple_statfs,	.alloc_inode = bdev_alloc_inode,	.destroy_inode = bdev_destroy_inode,	.drop_inode = generic_delete_inode,	.clear_inode = bdev_clear_inode,}; static int bd_get_sb(struct file_system_type *fs_type,	int flags, const char *dev_name, void *data, struct vfsmount *mnt)

Lines 1–500 of 1483.