static int compat_cdrom_read_audio(struct block_device *bdev, fmode_t mode,
		unsigned int cmd, unsigned long arg)
{
	struct cdrom_read_audio __user *cdread_audio;
	struct compat_cdrom_read_audio __user *cdread_audio32;
	__u32 data;
	void __user *datap;

	cdread_audio = compat_alloc_user_space(sizeof(*cdread_audio));
	cdread_audio32 = compat_ptr(arg);

	if (copy_in_user(&cdread_audio->addr,
			 &cdread_audio32->addr,
			 (sizeof(*cdread_audio32) -
			  sizeof(compat_caddr_t))))
		return -EFAULT;

	if (get_user(data, &cdread_audio32->buf))
		return -EFAULT;
	datap = compat_ptr(data);
	if (put_user(datap, &cdread_audio->buf))
		return -EFAULT;

	return __blkdev_driver_ioctl(bdev, mode, cmd,
			(unsigned long)cdread_audio);
}
static int compat_cdrom_generic_command(struct block_device *bdev, fmode_t mode,
		unsigned int cmd, unsigned long arg)
{
	struct cdrom_generic_command __user *cgc;
	struct compat_cdrom_generic_command __user *cgc32;
	u32 data;
	unsigned char dir;
	int itmp;

	cgc = compat_alloc_user_space(sizeof(*cgc));
	cgc32 = compat_ptr(arg);

	if (copy_in_user(&cgc->cmd, &cgc32->cmd, sizeof(cgc->cmd)) ||
	    get_user(data, &cgc32->buffer) ||
	    put_user(compat_ptr(data), &cgc->buffer) ||
	    copy_in_user(&cgc->buflen, &cgc32->buflen,
			 (sizeof(unsigned int) + sizeof(int))) ||
	    get_user(data, &cgc32->sense) ||
	    put_user(compat_ptr(data), &cgc->sense) ||
	    get_user(dir, &cgc32->data_direction) ||
	    put_user(dir, &cgc->data_direction) ||
	    get_user(itmp, &cgc32->quiet) ||
	    put_user(itmp, &cgc->quiet) ||
	    get_user(itmp, &cgc32->timeout) ||
	    put_user(itmp, &cgc->timeout) ||
	    get_user(data, &cgc32->reserved[0]) ||
	    put_user(compat_ptr(data), &cgc->reserved[0]))
		return -EFAULT;

	return __blkdev_driver_ioctl(bdev, mode, cmd, (unsigned long)cgc);
}
示例#3
0
int vfs_fsync_range(struct file *file, loff_t start, loff_t end, int datasync)
{
	int err;
	struct super_block *sb = file->f_dentry->d_sb;
	struct block_device *bdev = sb->s_bdev;
	if (!file->f_op || !file->f_op->fsync)
		return -EINVAL;
	err = file->f_op->fsync(file, start, end, datasync);
	if(err)
		return err;
	/*
	 *2013.09.30: fix the bug that system cannot start up when storage
	 *device is emmc, ioctl chanel only for nand flash
	 */
	if (bdev != NULL && MAJOR(bdev->bd_dev) == NFTL_MAJOR)
		err = __blkdev_driver_ioctl(bdev, O_RDONLY, BLKFLSBUF, 0);
	return err;
}
static int compat_hdio_ioctl(struct block_device *bdev, fmode_t mode,
		unsigned int cmd, unsigned long arg)
{
	mm_segment_t old_fs = get_fs();
	unsigned long kval;
	unsigned int __user *uvp;
	int error;

	set_fs(KERNEL_DS);
	error = __blkdev_driver_ioctl(bdev, mode,
				cmd, (unsigned long)(&kval));
	set_fs(old_fs);

	if (error == 0) {
		uvp = compat_ptr(arg);
		if (put_user(kval, uvp))
			error = -EFAULT;
	}
	return error;
}
static int compat_fd_ioctl(struct block_device *bdev, fmode_t mode,
		unsigned int cmd, unsigned long arg)
{
	mm_segment_t old_fs = get_fs();
	void *karg = NULL;
	unsigned int kcmd = 0;
	int i, err;

	for (i = 0; i < NR_FD_IOCTL_TRANS; i++)
		if (cmd == fd_ioctl_trans_table[i].cmd32) {
			kcmd = fd_ioctl_trans_table[i].cmd;
			break;
		}
	if (!kcmd)
		return -EINVAL;

	switch (cmd) {
	case FDSETPRM32:
	case FDDEFPRM32:
	case FDGETPRM32:
	{
		compat_uptr_t name;
		struct compat_floppy_struct __user *uf;
		struct floppy_struct *f;

		uf = compat_ptr(arg);
		f = karg = kmalloc(sizeof(struct floppy_struct), GFP_KERNEL);
		if (!karg)
			return -ENOMEM;
		if (cmd == FDGETPRM32)
			break;
		err = __get_user(f->size, &uf->size);
		err |= __get_user(f->sect, &uf->sect);
		err |= __get_user(f->head, &uf->head);
		err |= __get_user(f->track, &uf->track);
		err |= __get_user(f->stretch, &uf->stretch);
		err |= __get_user(f->gap, &uf->gap);
		err |= __get_user(f->rate, &uf->rate);
		err |= __get_user(f->spec1, &uf->spec1);
		err |= __get_user(f->fmt_gap, &uf->fmt_gap);
		err |= __get_user(name, &uf->name);
		f->name = compat_ptr(name);
		if (err) {
			err = -EFAULT;
			goto out;
		}
		break;
	}
	case FDSETDRVPRM32:
	case FDGETDRVPRM32:
	{
		struct compat_floppy_drive_params __user *uf;
		struct floppy_drive_params *f;

		uf = compat_ptr(arg);
		f = karg = kmalloc(sizeof(struct floppy_drive_params), GFP_KERNEL);
		if (!karg)
			return -ENOMEM;
		if (cmd == FDGETDRVPRM32)
			break;
		err = __get_user(f->cmos, &uf->cmos);
		err |= __get_user(f->max_dtr, &uf->max_dtr);
		err |= __get_user(f->hlt, &uf->hlt);
		err |= __get_user(f->hut, &uf->hut);
		err |= __get_user(f->srt, &uf->srt);
		err |= __get_user(f->spinup, &uf->spinup);
		err |= __get_user(f->spindown, &uf->spindown);
		err |= __get_user(f->spindown_offset, &uf->spindown_offset);
		err |= __get_user(f->select_delay, &uf->select_delay);
		err |= __get_user(f->rps, &uf->rps);
		err |= __get_user(f->tracks, &uf->tracks);
		err |= __get_user(f->timeout, &uf->timeout);
		err |= __get_user(f->interleave_sect, &uf->interleave_sect);
		err |= __copy_from_user(&f->max_errors, &uf->max_errors, sizeof(f->max_errors));
		err |= __get_user(f->flags, &uf->flags);
		err |= __get_user(f->read_track, &uf->read_track);
		err |= __copy_from_user(f->autodetect, uf->autodetect, sizeof(f->autodetect));
		err |= __get_user(f->checkfreq, &uf->checkfreq);
		err |= __get_user(f->native_format, &uf->native_format);
		if (err) {
			err = -EFAULT;
			goto out;
		}
		break;
	}
	case FDGETDRVSTAT32:
	case FDPOLLDRVSTAT32:
		karg = kmalloc(sizeof(struct floppy_drive_struct), GFP_KERNEL);
		if (!karg)
			return -ENOMEM;
		break;
	case FDGETFDCSTAT32:
		karg = kmalloc(sizeof(struct floppy_fdc_state), GFP_KERNEL);
		if (!karg)
			return -ENOMEM;
		break;
	case FDWERRORGET32:
		karg = kmalloc(sizeof(struct floppy_write_errors), GFP_KERNEL);
		if (!karg)
			return -ENOMEM;
		break;
	default:
		return -EINVAL;
	}
	set_fs(KERNEL_DS);
	err = __blkdev_driver_ioctl(bdev, mode, kcmd, (unsigned long)karg);
	set_fs(old_fs);
	if (err)
		goto out;
	switch (cmd) {
	case FDGETPRM32:
	{
		struct floppy_struct *f = karg;
		struct compat_floppy_struct __user *uf = compat_ptr(arg);

		err = __put_user(f->size, &uf->size);
		err |= __put_user(f->sect, &uf->sect);
		err |= __put_user(f->head, &uf->head);
		err |= __put_user(f->track, &uf->track);
		err |= __put_user(f->stretch, &uf->stretch);
		err |= __put_user(f->gap, &uf->gap);
		err |= __put_user(f->rate, &uf->rate);
		err |= __put_user(f->spec1, &uf->spec1);
		err |= __put_user(f->fmt_gap, &uf->fmt_gap);
		err |= __put_user((u64)f->name, (compat_caddr_t __user *)&uf->name);
		break;
	}
	case FDGETDRVPRM32:
	{
		struct compat_floppy_drive_params __user *uf;
		struct floppy_drive_params *f = karg;

		uf = compat_ptr(arg);
		err = __put_user(f->cmos, &uf->cmos);
		err |= __put_user(f->max_dtr, &uf->max_dtr);
		err |= __put_user(f->hlt, &uf->hlt);
		err |= __put_user(f->hut, &uf->hut);
		err |= __put_user(f->srt, &uf->srt);
		err |= __put_user(f->spinup, &uf->spinup);
		err |= __put_user(f->spindown, &uf->spindown);
		err |= __put_user(f->spindown_offset, &uf->spindown_offset);
		err |= __put_user(f->select_delay, &uf->select_delay);
		err |= __put_user(f->rps, &uf->rps);
		err |= __put_user(f->tracks, &uf->tracks);
		err |= __put_user(f->timeout, &uf->timeout);
		err |= __put_user(f->interleave_sect, &uf->interleave_sect);
		err |= __copy_to_user(&uf->max_errors, &f->max_errors, sizeof(f->max_errors));
		err |= __put_user(f->flags, &uf->flags);
		err |= __put_user(f->read_track, &uf->read_track);
		err |= __copy_to_user(uf->autodetect, f->autodetect, sizeof(f->autodetect));
		err |= __put_user(f->checkfreq, &uf->checkfreq);
		err |= __put_user(f->native_format, &uf->native_format);
		break;
	}
	case FDGETDRVSTAT32:
	case FDPOLLDRVSTAT32:
	{
		struct compat_floppy_drive_struct __user *uf;
		struct floppy_drive_struct *f = karg;

		uf = compat_ptr(arg);
		err = __put_user(f->flags, &uf->flags);
		err |= __put_user(f->spinup_date, &uf->spinup_date);
		err |= __put_user(f->select_date, &uf->select_date);
		err |= __put_user(f->first_read_date, &uf->first_read_date);
		err |= __put_user(f->probed_format, &uf->probed_format);
		err |= __put_user(f->track, &uf->track);
		err |= __put_user(f->maxblock, &uf->maxblock);
		err |= __put_user(f->maxtrack, &uf->maxtrack);
		err |= __put_user(f->generation, &uf->generation);
		err |= __put_user(f->keep_data, &uf->keep_data);
		err |= __put_user(f->fd_ref, &uf->fd_ref);
		err |= __put_user(f->fd_device, &uf->fd_device);
		err |= __put_user(f->last_checked, &uf->last_checked);
		err |= __put_user((u64)f->dmabuf, &uf->dmabuf);
		err |= __put_user((u64)f->bufblocks, &uf->bufblocks);
		break;
	}
	case FDGETFDCSTAT32:
	{
		struct compat_floppy_fdc_state __user *uf;
		struct floppy_fdc_state *f = karg;

		uf = compat_ptr(arg);
		err = __put_user(f->spec1, &uf->spec1);
		err |= __put_user(f->spec2, &uf->spec2);
		err |= __put_user(f->dtr, &uf->dtr);
		err |= __put_user(f->version, &uf->version);
		err |= __put_user(f->dor, &uf->dor);
		err |= __put_user(f->address, &uf->address);
		err |= __copy_to_user((char __user *)&uf->address + sizeof(uf->address),
				   (char *)&f->address + sizeof(f->address), sizeof(int));
		err |= __put_user(f->driver_version, &uf->driver_version);
		err |= __copy_to_user(uf->track, f->track, sizeof(f->track));
		break;
	}
	case FDWERRORGET32:
	{
		struct compat_floppy_write_errors __user *uf;
		struct floppy_write_errors *f = karg;

		uf = compat_ptr(arg);
		err = __put_user(f->write_errors, &uf->write_errors);
		err |= __put_user(f->first_error_sector, &uf->first_error_sector);
		err |= __put_user(f->first_error_generation, &uf->first_error_generation);
		err |= __put_user(f->last_error_sector, &uf->last_error_sector);
		err |= __put_user(f->last_error_generation, &uf->last_error_generation);
		err |= __put_user(f->badness, &uf->badness);
		break;
	}
	default:
		break;
	}
	if (err)
		err = -EFAULT;

out:
	kfree(karg);
	return err;
}