Blame view

block/bsg.c 6.12 KB
8c16567d8   Christoph Hellwig   block: switch all...
1
  // SPDX-License-Identifier: GPL-2.0
3d6392cfb   Jens Axboe   bsg: support for ...
2
  /*
0c6a89ba6   FUJITA Tomonori   [SCSI] bsg: updat...
3
   * bsg.c - block layer implementation of the sg v4 interface
3d6392cfb   Jens Axboe   bsg: support for ...
4
   */
3d6392cfb   Jens Axboe   bsg: support for ...
5
6
7
8
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/file.h>
  #include <linux/blkdev.h>
3d6392cfb   Jens Axboe   bsg: support for ...
9
  #include <linux/cdev.h>
ad5ebd2fa   Randy Dunlap   block: jiffies fixes
10
  #include <linux/jiffies.h>
3d6392cfb   Jens Axboe   bsg: support for ...
11
  #include <linux/percpu.h>
598443a21   FUJITA Tomonori   [SCSI] bsg: use l...
12
  #include <linux/idr.h>
3d6392cfb   Jens Axboe   bsg: support for ...
13
  #include <linux/bsg.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
14
  #include <linux/slab.h>
3d6392cfb   Jens Axboe   bsg: support for ...
15
16
17
  
  #include <scsi/scsi.h>
  #include <scsi/scsi_ioctl.h>
3d6392cfb   Jens Axboe   bsg: support for ...
18
  #include <scsi/sg.h>
0ed081ce2   FUJITA Tomonori   bsg: minor cleanup
19
20
  #define BSG_DESCRIPTION	"Block layer SCSI generic (bsg) driver"
  #define BSG_VERSION	"0.4"
3d6392cfb   Jens Axboe   bsg: support for ...
21

3d6392cfb   Jens Axboe   bsg: support for ...
22
  struct bsg_device {
165125e1e   Jens Axboe   [BLOCK] Get rid o...
23
  	struct request_queue *queue;
ead09dd3a   Christoph Hellwig   scsi: bsg: Simpli...
24
25
  	struct device device;
  	struct cdev cdev;
3d6392cfb   Jens Axboe   bsg: support for ...
26
  	int max_queue;
1e61c1a80   Christoph Hellwig   scsi: block: Remo...
27
28
  	unsigned int timeout;
  	unsigned int reserved_size;
75ca56409   Christoph Hellwig   scsi: bsg: Move t...
29
  	bsg_sg_io_fn *sg_io_fn;
3d6392cfb   Jens Axboe   bsg: support for ...
30
  };
ead09dd3a   Christoph Hellwig   scsi: bsg: Simpli...
31
32
33
34
  static inline struct bsg_device *to_bsg_device(struct inode *inode)
  {
  	return container_of(inode->i_cdev, struct bsg_device, cdev);
  }
5309cb38d   Jens Axboe   Add queue resizin...
35
  #define BSG_DEFAULT_CMDS	64
292b7f271   FUJITA Tomonori   improve bsg devic...
36
  #define BSG_MAX_DEVS		32768
3d6392cfb   Jens Axboe   bsg: support for ...
37

ead09dd3a   Christoph Hellwig   scsi: bsg: Simpli...
38
  static DEFINE_IDA(bsg_minor_ida);
3d6392cfb   Jens Axboe   bsg: support for ...
39
  static struct class *bsg_class;
46f6ef4af   Jens Axboe   bsg: convert to d...
40
  static int bsg_major;
3d6392cfb   Jens Axboe   bsg: support for ...
41

75ca56409   Christoph Hellwig   scsi: bsg: Move t...
42
43
44
45
46
47
48
49
50
51
52
  static unsigned int bsg_timeout(struct bsg_device *bd, struct sg_io_v4 *hdr)
  {
  	unsigned int timeout = BLK_DEFAULT_SG_TIMEOUT;
  
  	if (hdr->timeout)
  		timeout = msecs_to_jiffies(hdr->timeout);
  	else if (bd->timeout)
  		timeout = bd->timeout;
  
  	return max_t(unsigned int, timeout, BLK_MIN_SG_TIMEOUT);
  }
17cb960f2   Christoph Hellwig   bsg: split handli...
53

ead09dd3a   Christoph Hellwig   scsi: bsg: Simpli...
54
  static int bsg_sg_io(struct bsg_device *bd, fmode_t mode, void __user *uarg)
3d6392cfb   Jens Axboe   bsg: support for ...
55
  {
ccf3209f0   Christoph Hellwig   scsi: bsg: refact...
56
  	struct sg_io_v4 hdr;
aebf526b5   Christoph Hellwig   block: fold cmd_t...
57
  	int ret;
c7a841f3a   James Smart   [SCSI] bsg: corre...
58

ccf3209f0   Christoph Hellwig   scsi: bsg: refact...
59
60
  	if (copy_from_user(&hdr, uarg, sizeof(hdr)))
  		return -EFAULT;
ccf3209f0   Christoph Hellwig   scsi: bsg: refact...
61
62
  	if (hdr.guard != 'Q')
  		return -EINVAL;
75ca56409   Christoph Hellwig   scsi: bsg: Move t...
63
  	ret = bd->sg_io_fn(bd->queue, &hdr, mode, bsg_timeout(bd, &hdr));
972248e91   Christoph Hellwig   scsi: bsg-lib: ha...
64
  	if (!ret && copy_to_user(uarg, &hdr, sizeof(hdr)))
ccf3209f0   Christoph Hellwig   scsi: bsg: refact...
65
66
  		return -EFAULT;
  	return ret;
70e36ecea   FUJITA Tomonori   bsg: replace SG v...
67
  }
3d6392cfb   Jens Axboe   bsg: support for ...
68
69
  static int bsg_open(struct inode *inode, struct file *file)
  {
ead09dd3a   Christoph Hellwig   scsi: bsg: Simpli...
70
71
  	if (!blk_get_queue(to_bsg_device(inode)->queue))
  		return -ENXIO;
3d6392cfb   Jens Axboe   bsg: support for ...
72
73
74
75
76
  	return 0;
  }
  
  static int bsg_release(struct inode *inode, struct file *file)
  {
ead09dd3a   Christoph Hellwig   scsi: bsg: Simpli...
77
78
  	blk_put_queue(to_bsg_device(inode)->queue);
  	return 0;
3d6392cfb   Jens Axboe   bsg: support for ...
79
  }
ccf3209f0   Christoph Hellwig   scsi: bsg: refact...
80
81
  static int bsg_get_command_q(struct bsg_device *bd, int __user *uarg)
  {
ead09dd3a   Christoph Hellwig   scsi: bsg: Simpli...
82
  	return put_user(READ_ONCE(bd->max_queue), uarg);
ccf3209f0   Christoph Hellwig   scsi: bsg: refact...
83
84
85
86
  }
  
  static int bsg_set_command_q(struct bsg_device *bd, int __user *uarg)
  {
ead09dd3a   Christoph Hellwig   scsi: bsg: Simpli...
87
  	int max_queue;
ccf3209f0   Christoph Hellwig   scsi: bsg: refact...
88

ead09dd3a   Christoph Hellwig   scsi: bsg: Simpli...
89
  	if (get_user(max_queue, uarg))
ccf3209f0   Christoph Hellwig   scsi: bsg: refact...
90
  		return -EFAULT;
ead09dd3a   Christoph Hellwig   scsi: bsg: Simpli...
91
  	if (max_queue < 1)
ccf3209f0   Christoph Hellwig   scsi: bsg: refact...
92
  		return -EINVAL;
ead09dd3a   Christoph Hellwig   scsi: bsg: Simpli...
93
  	WRITE_ONCE(bd->max_queue, max_queue);
ccf3209f0   Christoph Hellwig   scsi: bsg: refact...
94
95
  	return 0;
  }
25fd16430   Jens Axboe   bsg: address vari...
96
  static long bsg_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
3d6392cfb   Jens Axboe   bsg: support for ...
97
  {
ead09dd3a   Christoph Hellwig   scsi: bsg: Simpli...
98
  	struct bsg_device *bd = to_bsg_device(file_inode(file));
d52fe8f43   Christoph Hellwig   scsi: bsg: Decoup...
99
  	struct request_queue *q = bd->queue;
ccf3209f0   Christoph Hellwig   scsi: bsg: refact...
100
  	void __user *uarg = (void __user *) arg;
d52fe8f43   Christoph Hellwig   scsi: bsg: Decoup...
101
102
  	int __user *intp = uarg;
  	int val;
3d6392cfb   Jens Axboe   bsg: support for ...
103

3d6392cfb   Jens Axboe   bsg: support for ...
104
  	switch (cmd) {
ccf3209f0   Christoph Hellwig   scsi: bsg: refact...
105
106
107
  	/*
  	 * Our own ioctls
  	 */
3d6392cfb   Jens Axboe   bsg: support for ...
108
  	case SG_GET_COMMAND_Q:
ccf3209f0   Christoph Hellwig   scsi: bsg: refact...
109
110
111
  		return bsg_get_command_q(bd, uarg);
  	case SG_SET_COMMAND_Q:
  		return bsg_set_command_q(bd, uarg);
3d6392cfb   Jens Axboe   bsg: support for ...
112
113
114
115
116
  
  	/*
  	 * SCSI/sg ioctls
  	 */
  	case SG_GET_VERSION_NUM:
d52fe8f43   Christoph Hellwig   scsi: bsg: Decoup...
117
  		return put_user(30527, intp);
3d6392cfb   Jens Axboe   bsg: support for ...
118
  	case SCSI_IOCTL_GET_IDLUN:
d52fe8f43   Christoph Hellwig   scsi: bsg: Decoup...
119
  		return put_user(0, intp);
3d6392cfb   Jens Axboe   bsg: support for ...
120
  	case SCSI_IOCTL_GET_BUS_NUMBER:
d52fe8f43   Christoph Hellwig   scsi: bsg: Decoup...
121
  		return put_user(0, intp);
3d6392cfb   Jens Axboe   bsg: support for ...
122
  	case SG_SET_TIMEOUT:
d52fe8f43   Christoph Hellwig   scsi: bsg: Decoup...
123
124
  		if (get_user(val, intp))
  			return -EFAULT;
1e61c1a80   Christoph Hellwig   scsi: block: Remo...
125
  		bd->timeout = clock_t_to_jiffies(val);
d52fe8f43   Christoph Hellwig   scsi: bsg: Decoup...
126
  		return 0;
3d6392cfb   Jens Axboe   bsg: support for ...
127
  	case SG_GET_TIMEOUT:
1e61c1a80   Christoph Hellwig   scsi: block: Remo...
128
  		return jiffies_to_clock_t(bd->timeout);
3d6392cfb   Jens Axboe   bsg: support for ...
129
  	case SG_GET_RESERVED_SIZE:
1e61c1a80   Christoph Hellwig   scsi: block: Remo...
130
  		return put_user(min(bd->reserved_size, queue_max_bytes(q)),
d52fe8f43   Christoph Hellwig   scsi: bsg: Decoup...
131
  				intp);
3d6392cfb   Jens Axboe   bsg: support for ...
132
  	case SG_SET_RESERVED_SIZE:
d52fe8f43   Christoph Hellwig   scsi: bsg: Decoup...
133
134
135
136
  		if (get_user(val, intp))
  			return -EFAULT;
  		if (val < 0)
  			return -EINVAL;
1e61c1a80   Christoph Hellwig   scsi: block: Remo...
137
  		bd->reserved_size =
d52fe8f43   Christoph Hellwig   scsi: bsg: Decoup...
138
139
  			min_t(unsigned int, val, queue_max_bytes(q));
  		return 0;
3d6392cfb   Jens Axboe   bsg: support for ...
140
  	case SG_EMULATED_HOST:
d52fe8f43   Christoph Hellwig   scsi: bsg: Decoup...
141
  		return put_user(1, intp);
ccf3209f0   Christoph Hellwig   scsi: bsg: refact...
142
  	case SG_IO:
ead09dd3a   Christoph Hellwig   scsi: bsg: Simpli...
143
  		return bsg_sg_io(bd, file->f_mode, uarg);
beec64d0c   Christoph Hellwig   scsi: bsg: Remove...
144
145
146
147
148
  	case SCSI_IOCTL_SEND_COMMAND:
  		pr_warn_ratelimited("%s: calling unsupported SCSI_IOCTL_SEND_COMMAND
  ",
  				current->comm);
  		return -EINVAL;
3d6392cfb   Jens Axboe   bsg: support for ...
149
  	default:
3d6392cfb   Jens Axboe   bsg: support for ...
150
  		return -ENOTTY;
3d6392cfb   Jens Axboe   bsg: support for ...
151
152
  	}
  }
7344be053   Arjan van de Ven   bsg: mark struct ...
153
  static const struct file_operations bsg_fops = {
3d6392cfb   Jens Axboe   bsg: support for ...
154
155
  	.open		=	bsg_open,
  	.release	=	bsg_release,
25fd16430   Jens Axboe   bsg: address vari...
156
  	.unlocked_ioctl	=	bsg_ioctl,
fe0da4e5e   Arnd Bergmann   compat_ioctl: bsg...
157
  	.compat_ioctl	=	compat_ptr_ioctl,
3d6392cfb   Jens Axboe   bsg: support for ...
158
  	.owner		=	THIS_MODULE,
6038f373a   Arnd Bergmann   llseek: automatic...
159
  	.llseek		=	default_llseek,
3d6392cfb   Jens Axboe   bsg: support for ...
160
  };
1a0db7744   Zenghui Yu   scsi: bsg: Fix de...
161
162
163
164
165
166
167
  static void bsg_device_release(struct device *dev)
  {
  	struct bsg_device *bd = container_of(dev, struct bsg_device, device);
  
  	ida_simple_remove(&bsg_minor_ida, MINOR(bd->device.devt));
  	kfree(bd);
  }
ead09dd3a   Christoph Hellwig   scsi: bsg: Simpli...
168
  void bsg_unregister_queue(struct bsg_device *bd)
3d6392cfb   Jens Axboe   bsg: support for ...
169
  {
ead09dd3a   Christoph Hellwig   scsi: bsg: Simpli...
170
171
172
  	if (bd->queue->kobj.sd)
  		sysfs_remove_link(&bd->queue->kobj, "bsg");
  	cdev_device_del(&bd->cdev, &bd->device);
1a0db7744   Zenghui Yu   scsi: bsg: Fix de...
173
  	put_device(&bd->device);
3d6392cfb   Jens Axboe   bsg: support for ...
174
  }
4cf0723ac   FUJITA Tomonori   bsg: minor bug fixes
175
  EXPORT_SYMBOL_GPL(bsg_unregister_queue);
3d6392cfb   Jens Axboe   bsg: support for ...
176

ead09dd3a   Christoph Hellwig   scsi: bsg: Simpli...
177
  struct bsg_device *bsg_register_queue(struct request_queue *q,
75ca56409   Christoph Hellwig   scsi: bsg: Move t...
178
  		struct device *parent, const char *name, bsg_sg_io_fn *sg_io_fn)
3d6392cfb   Jens Axboe   bsg: support for ...
179
  {
ead09dd3a   Christoph Hellwig   scsi: bsg: Simpli...
180
  	struct bsg_device *bd;
bab998d62   Tejun Heo   block: convert to...
181
  	int ret;
3d6392cfb   Jens Axboe   bsg: support for ...
182

ead09dd3a   Christoph Hellwig   scsi: bsg: Simpli...
183
184
185
186
  	bd = kzalloc(sizeof(*bd), GFP_KERNEL);
  	if (!bd)
  		return ERR_PTR(-ENOMEM);
  	bd->max_queue = BSG_DEFAULT_CMDS;
1e61c1a80   Christoph Hellwig   scsi: block: Remo...
187
  	bd->reserved_size = INT_MAX;
ead09dd3a   Christoph Hellwig   scsi: bsg: Simpli...
188
  	bd->queue = q;
75ca56409   Christoph Hellwig   scsi: bsg: Move t...
189
  	bd->sg_io_fn = sg_io_fn;
292b7f271   FUJITA Tomonori   improve bsg devic...
190

ead09dd3a   Christoph Hellwig   scsi: bsg: Simpli...
191
  	ret = ida_simple_get(&bsg_minor_ida, 0, BSG_MAX_DEVS, GFP_KERNEL);
bab998d62   Tejun Heo   block: convert to...
192
  	if (ret < 0) {
ead09dd3a   Christoph Hellwig   scsi: bsg: Simpli...
193
194
195
  		if (ret == -ENOSPC)
  			dev_err(parent, "bsg: too many bsg devices
  ");
1a0db7744   Zenghui Yu   scsi: bsg: Fix de...
196
197
  		kfree(bd);
  		return ERR_PTR(ret);
4e2872d6b   FUJITA Tomonori   bind bsg to all S...
198
  	}
ead09dd3a   Christoph Hellwig   scsi: bsg: Simpli...
199
200
201
  	bd->device.devt = MKDEV(bsg_major, ret);
  	bd->device.class = bsg_class;
  	bd->device.parent = parent;
1a0db7744   Zenghui Yu   scsi: bsg: Fix de...
202
  	bd->device.release = bsg_device_release;
ead09dd3a   Christoph Hellwig   scsi: bsg: Simpli...
203
204
205
206
207
208
209
  	dev_set_name(&bd->device, "%s", name);
  	device_initialize(&bd->device);
  
  	cdev_init(&bd->cdev, &bsg_fops);
  	bd->cdev.owner = THIS_MODULE;
  	ret = cdev_device_add(&bd->cdev, &bd->device);
  	if (ret)
1a0db7744   Zenghui Yu   scsi: bsg: Fix de...
210
  		goto out_put_device;
4e2872d6b   FUJITA Tomonori   bind bsg to all S...
211

abce891a1   Linus Torvalds   Fix new generic b...
212
  	if (q->kobj.sd) {
ead09dd3a   Christoph Hellwig   scsi: bsg: Simpli...
213
  		ret = sysfs_create_link(&q->kobj, &bd->device.kobj, "bsg");
4e2872d6b   FUJITA Tomonori   bind bsg to all S...
214
  		if (ret)
ead09dd3a   Christoph Hellwig   scsi: bsg: Simpli...
215
  			goto out_device_del;
4e2872d6b   FUJITA Tomonori   bind bsg to all S...
216
  	}
ead09dd3a   Christoph Hellwig   scsi: bsg: Simpli...
217
  	return bd;
6826ee4fd   James Bottomley   [SCSI] bsg: fix b...
218

ead09dd3a   Christoph Hellwig   scsi: bsg: Simpli...
219
220
  out_device_del:
  	cdev_device_del(&bd->cdev, &bd->device);
1a0db7744   Zenghui Yu   scsi: bsg: Fix de...
221
222
  out_put_device:
  	put_device(&bd->device);
ead09dd3a   Christoph Hellwig   scsi: bsg: Simpli...
223
  	return ERR_PTR(ret);
4e2872d6b   FUJITA Tomonori   bind bsg to all S...
224
  }
780110426   Christoph Hellwig   scsi: bsg: Move b...
225
  EXPORT_SYMBOL_GPL(bsg_register_queue);
4e2872d6b   FUJITA Tomonori   bind bsg to all S...
226

2c9ede55e   Al Viro   switch device_get...
227
  static char *bsg_devnode(struct device *dev, umode_t *mode)
2bdf91491   Kay Sievers   Driver Core: bsg:...
228
229
230
  {
  	return kasprintf(GFP_KERNEL, "bsg/%s", dev_name(dev));
  }
3d6392cfb   Jens Axboe   bsg: support for ...
231
232
  static int __init bsg_init(void)
  {
46f6ef4af   Jens Axboe   bsg: convert to d...
233
  	dev_t devid;
ead09dd3a   Christoph Hellwig   scsi: bsg: Simpli...
234
  	int ret;
3d6392cfb   Jens Axboe   bsg: support for ...
235
236
  
  	bsg_class = class_create(THIS_MODULE, "bsg");
28519c891   Christoph Hellwig   bsg: remove read/...
237
238
  	if (IS_ERR(bsg_class))
  		return PTR_ERR(bsg_class);
e454cea20   Kay Sievers   Driver-Core: exte...
239
  	bsg_class->devnode = bsg_devnode;
3d6392cfb   Jens Axboe   bsg: support for ...
240

46f6ef4af   Jens Axboe   bsg: convert to d...
241
  	ret = alloc_chrdev_region(&devid, 0, BSG_MAX_DEVS, "bsg");
9b9f770ce   FUJITA Tomonori   bsg: fix initiali...
242
243
  	if (ret)
  		goto destroy_bsg_class;
46f6ef4af   Jens Axboe   bsg: convert to d...
244
  	bsg_major = MAJOR(devid);
5d3a8cd34   Jens Axboe   bsg: fix missing ...
245
  	printk(KERN_INFO BSG_DESCRIPTION " version " BSG_VERSION
0ed081ce2   FUJITA Tomonori   bsg: minor cleanup
246
247
  	       " loaded (major %d)
  ", bsg_major);
3d6392cfb   Jens Axboe   bsg: support for ...
248
  	return 0;
ead09dd3a   Christoph Hellwig   scsi: bsg: Simpli...
249

9b9f770ce   FUJITA Tomonori   bsg: fix initiali...
250
251
  destroy_bsg_class:
  	class_destroy(bsg_class);
9b9f770ce   FUJITA Tomonori   bsg: fix initiali...
252
  	return ret;
3d6392cfb   Jens Axboe   bsg: support for ...
253
254
255
  }
  
  MODULE_AUTHOR("Jens Axboe");
0ed081ce2   FUJITA Tomonori   bsg: minor cleanup
256
  MODULE_DESCRIPTION(BSG_DESCRIPTION);
3d6392cfb   Jens Axboe   bsg: support for ...
257
  MODULE_LICENSE("GPL");
4e2872d6b   FUJITA Tomonori   bind bsg to all S...
258
  device_initcall(bsg_init);