⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 block_dev.c

📁 ARM 嵌入式 系统 设计与实例开发 实验教材 二源码
💻 C
📖 第 1 页 / 共 2 页
字号:
				return new_bdev;			}			spin_unlock(&bdev_lock);			iput(new_bdev->bd_inode);		}		destroy_bdev(new_bdev);	}	return bdev;}static inline void __bd_forget(struct inode *inode){	list_del_init(&inode->i_devices);	inode->i_bdev = NULL;	inode->i_mapping = &inode->i_data;}void bdput(struct block_device *bdev){	if (atomic_dec_and_lock(&bdev->bd_count, &bdev_lock)) {		struct list_head *p;		if (bdev->bd_openers)			BUG();		list_del(&bdev->bd_hash);		while ( (p = bdev->bd_inodes.next) != &bdev->bd_inodes ) {			__bd_forget(list_entry(p, struct inode, i_devices));		}		spin_unlock(&bdev_lock);		iput(bdev->bd_inode);		destroy_bdev(bdev);	}} int bd_acquire(struct inode *inode){	struct block_device *bdev;	spin_lock(&bdev_lock);	if (inode->i_bdev) {		atomic_inc(&inode->i_bdev->bd_count);		spin_unlock(&bdev_lock);		return 0;	}	spin_unlock(&bdev_lock);	bdev = bdget(kdev_t_to_nr(inode->i_rdev));	if (!bdev)		return -ENOMEM;	spin_lock(&bdev_lock);	if (!inode->i_bdev) {		inode->i_bdev = bdev;		inode->i_mapping = bdev->bd_inode->i_mapping;		list_add(&inode->i_devices, &bdev->bd_inodes);	} else if (inode->i_bdev != bdev)		BUG();	spin_unlock(&bdev_lock);	return 0;}/* Call when you free inode */void bd_forget(struct inode *inode){	spin_lock(&bdev_lock);	if (inode->i_bdev)		__bd_forget(inode);	spin_unlock(&bdev_lock);}static struct {	const char *name;	struct block_device_operations *bdops;} blkdevs[MAX_BLKDEV];int get_blkdev_list(char * p){	int i;	int len;	len = sprintf(p, "\nBlock devices:\n");	for (i = 0; i < MAX_BLKDEV ; i++) {		if (blkdevs[i].bdops) {			len += sprintf(p+len, "%3d %s\n", i, blkdevs[i].name);		}	}	return len;}/*	Return the function table of a device.	Load the driver if needed.*/const struct block_device_operations * get_blkfops(unsigned int major){	const struct block_device_operations *ret = NULL;	/* major 0 is used for non-device mounts */	if (major && major < MAX_BLKDEV) {#ifdef CONFIG_KMOD		if (!blkdevs[major].bdops) {			char name[20];			sprintf(name, "block-major-%d", major);			request_module(name);		}#endif		ret = blkdevs[major].bdops;	}	return ret;}int register_blkdev(unsigned int major, const char * name, struct block_device_operations *bdops){	if (major == 0) {		for (major = MAX_BLKDEV-1; major > 0; major--) {			if (blkdevs[major].bdops == NULL) {				blkdevs[major].name = name;				blkdevs[major].bdops = bdops;				return major;			}		}		return -EBUSY;	}	if (major >= MAX_BLKDEV)		return -EINVAL;	if (blkdevs[major].bdops && blkdevs[major].bdops != bdops)		return -EBUSY;	blkdevs[major].name = name;	blkdevs[major].bdops = bdops;	return 0;}int unregister_blkdev(unsigned int major, const char * name){	if (major >= MAX_BLKDEV)		return -EINVAL;	if (!blkdevs[major].bdops)		return -EINVAL;	if (strcmp(blkdevs[major].name, name))		return -EINVAL;	blkdevs[major].name = NULL;	blkdevs[major].bdops = NULL;	return 0;}/* * This routine checks whether a removable media has been changed, * and invalidates all buffer-cache-entries in that case. This * is a relatively slow routine, so we have to try to minimize using * it. Thus it is called only upon a 'mount' or 'open'. This * is the best way of combining speed and utility, I think. * People changing diskettes in the middle of an operation deserve * to lose :-) */int check_disk_change(kdev_t dev){	int i;	const struct block_device_operations * bdops = NULL;	i = MAJOR(dev);	if (i < MAX_BLKDEV)		bdops = blkdevs[i].bdops;	if (bdops == NULL) {		devfs_handle_t de;		de = devfs_find_handle (NULL, NULL, i, MINOR (dev),					DEVFS_SPECIAL_BLK, 0);		if (de) {			bdops = devfs_get_ops (de);			devfs_put_ops (de); /* We're running in owner module */		}	}	if (bdops == NULL)		return 0;	if (bdops->check_media_change == NULL)		return 0;	if (!bdops->check_media_change(dev))		return 0;	printk(KERN_DEBUG "VFS: Disk change detected on device %s\n",		bdevname(dev));	if (invalidate_device(dev, 0))		printk("VFS: busy inodes on changed media.\n");	if (bdops->revalidate)		bdops->revalidate(dev);	return 1;}int ioctl_by_bdev(struct block_device *bdev, unsigned cmd, unsigned long arg){	int res;	mm_segment_t old_fs = get_fs();	if (!bdev->bd_op->ioctl)		return -EINVAL;	set_fs(KERNEL_DS);	res = bdev->bd_op->ioctl(bdev->bd_inode, NULL, cmd, arg);	set_fs(old_fs);	return res;}static int do_open(struct block_device *bdev, struct inode *inode, struct file *file){	int ret = -ENXIO;	kdev_t dev = to_kdev_t(bdev->bd_dev);	down(&bdev->bd_sem);	lock_kernel();	if (!bdev->bd_op)		bdev->bd_op = get_blkfops(MAJOR(dev));	if (bdev->bd_op) {		ret = 0;		if (bdev->bd_op->owner)			__MOD_INC_USE_COUNT(bdev->bd_op->owner);		if (bdev->bd_op->open)			ret = bdev->bd_op->open(inode, file);		if (!ret) {			bdev->bd_openers++;			bdev->bd_inode->i_size = blkdev_size(dev);			bdev->bd_inode->i_blkbits = blksize_bits(block_size(dev));		} else {			if (bdev->bd_op->owner)				__MOD_DEC_USE_COUNT(bdev->bd_op->owner);			if (!bdev->bd_openers)				bdev->bd_op = NULL;		}	}	unlock_kernel();	up(&bdev->bd_sem);	if (ret)		bdput(bdev);	return ret;}int blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags, int kind){	/*	 * This crockload is due to bad choice of ->open() type.	 * It will go away.	 * For now, block device ->open() routine must _not_	 * examine anything in 'inode' argument except ->i_rdev.	 */	struct file fake_file = {};	struct dentry fake_dentry = {};	fake_file.f_mode = mode;	fake_file.f_flags = flags;	fake_file.f_dentry = &fake_dentry;	fake_dentry.d_inode = bdev->bd_inode;	return do_open(bdev, bdev->bd_inode, &fake_file);}int blkdev_open(struct inode * inode, struct file * filp){	struct block_device *bdev;	/*	 * Preserve backwards compatibility and allow large file access	 * even if userspace doesn't ask for it explicitly. Some mkfs	 * binary needs it. We might want to drop this workaround	 * during an unstable branch.	 */	filp->f_flags |= O_LARGEFILE;	bd_acquire(inode);	bdev = inode->i_bdev;	return do_open(bdev, inode, filp);}	int blkdev_put(struct block_device *bdev, int kind){	int ret = 0;	kdev_t rdev = to_kdev_t(bdev->bd_dev); /* this should become bdev */	struct inode *bd_inode = bdev->bd_inode;	down(&bdev->bd_sem);	lock_kernel();	if (kind == BDEV_FILE)		__block_fsync(bd_inode);	else if (kind == BDEV_FS)		fsync_no_super(rdev);	if (!--bdev->bd_openers)		kill_bdev(bdev);	if (bdev->bd_op->release)		ret = bdev->bd_op->release(bd_inode, NULL);	if (bdev->bd_op->owner)		__MOD_DEC_USE_COUNT(bdev->bd_op->owner);	if (!bdev->bd_openers)		bdev->bd_op = NULL;	unlock_kernel();	up(&bdev->bd_sem);	bdput(bdev);	return ret;}int blkdev_close(struct inode * inode, struct file * filp){	return blkdev_put(inode->i_bdev, BDEV_FILE);}static int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,			unsigned long arg){	if (inode->i_bdev->bd_op->ioctl)		return inode->i_bdev->bd_op->ioctl(inode, file, cmd, arg);	return -EINVAL;}struct address_space_operations def_blk_aops = {	readpage: blkdev_readpage,	writepage: blkdev_writepage,	sync_page: block_sync_page,	prepare_write: blkdev_prepare_write,	commit_write: blkdev_commit_write,	direct_IO: blkdev_direct_IO,};struct file_operations def_blk_fops = {	open:		blkdev_open,	release:	blkdev_close,	llseek:		block_llseek,	read:		generic_file_read,	write:		generic_file_write,	mmap:		generic_file_mmap,	fsync:		block_fsync,	ioctl:		blkdev_ioctl,};const char * bdevname(kdev_t dev){	static char buffer[32];	const char * name = blkdevs[MAJOR(dev)].name;	if (!name)		name = "unknown-block";	sprintf(buffer, "%s(%d,%d)", name, MAJOR(dev), MINOR(dev));	return buffer;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -