1 /*
2  * Partition table and disk geometry handling
3  *
4  * This obsoletes the partition-handling code in genhd.c:
5  * Userspace can look at a disk in arbitrary format and tell
6  * the kernel what partitions there are on the disk, and how
7  * these should be numbered.
8  * It also allows one to repartition a disk that is being used.
9  *
10  * A single ioctl with lots of subfunctions:
11  *
12  * Device number stuff:
13  *    get_whole_disk()          (given the device number of a partition, find
14  *                               the device number of the encompassing disk)
15  *    get_all_partitions()      (given the device number of a disk, return the
16  *                               device numbers of all its known partitions)
17  *
18  * Partition stuff:
19  *    add_partition()
20  *    delete_partition()
21  *    test_partition_in_use()   (also for test_disk_in_use)
22  *
23  * Geometry stuff:
24  *    get_geometry()
25  *    set_geometry()
26  *    get_bios_drivedata()
27  *
28  * For today, only the partition stuff - aeb, 990515
29  */
30 
31 #include <linux/errno.h>
32 #include <linux/fs.h>			/* for BLKRASET, ... */
33 #include <linux/sched.h>		/* for capable() */
34 #include <linux/blk.h>			/* for set_device_ro() */
35 #include <linux/blkpg.h>
36 #include <linux/genhd.h>
37 #include <linux/swap.h>			/* for is_swap_partition() */
38 #include <linux/module.h>               /* for EXPORT_SYMBOL */
39 
40 #include <asm/uaccess.h>
41 
42 /*
43  * What is the data describing a partition?
44  *
45  * 1. a device number (kdev_t)
46  * 2. a starting sector and number of sectors (hd_struct)
47  *    given in the part[] array of the gendisk structure for the drive.
48  *
49  * The number of sectors is replicated in the sizes[] array of
50  * the gendisk structure for the major, which again is copied to
51  * the blk_size[][] array.
52  * (However, hd_struct has the number of 512-byte sectors,
53  *  g->sizes[] and blk_size[][] have the number of 1024-byte blocks.)
54  * Note that several drives may have the same major.
55  */
56 
57 /*
58  * Add a partition.
59  *
60  * returns: EINVAL: bad parameters
61  *          ENXIO: cannot find drive
62  *          EBUSY: proposed partition overlaps an existing one
63  *                 or has the same number as an existing one
64  *          0: all OK.
65  */
add_partition(kdev_t dev,struct blkpg_partition * p)66 int add_partition(kdev_t dev, struct blkpg_partition *p) {
67 	struct gendisk *g;
68 	long long ppstart, pplength;
69 	long pstart, plength;
70 	int i, drive, first_minor, end_minor, minor;
71 
72 	/* convert bytes to sectors, check for fit in a hd_struct */
73 	ppstart = (p->start >> 9);
74 	pplength = (p->length >> 9);
75 	pstart = ppstart;
76 	plength = pplength;
77 	if (pstart != ppstart || plength != pplength
78 	    || pstart < 0 || plength < 0)
79 		return -EINVAL;
80 
81 	/* find the drive major */
82 	g = get_gendisk(dev);
83 	if (!g)
84 		return -ENXIO;
85 
86 	/* existing drive? */
87 	drive = (MINOR(dev) >> g->minor_shift);
88 	first_minor = (drive << g->minor_shift);
89 	end_minor   = first_minor + g->max_p;
90 	if (drive >= g->nr_real)
91 		return -ENXIO;
92 
93 	/* drive and partition number OK? */
94 	if (first_minor != MINOR(dev) || p->pno <= 0 || p->pno >= g->max_p)
95 		return -EINVAL;
96 
97 	/* partition number in use? */
98 	minor = first_minor + p->pno;
99 	if (g->part[minor].nr_sects != 0)
100 		return -EBUSY;
101 
102 	/* overlap? */
103 	for (i=first_minor+1; i<end_minor; i++)
104 		if (!(pstart+plength <= g->part[i].start_sect ||
105 		      pstart >= g->part[i].start_sect + g->part[i].nr_sects))
106 			return -EBUSY;
107 
108 	/* all seems OK */
109 	g->part[minor].start_sect = pstart;
110 	g->part[minor].nr_sects = plength;
111 	if (g->sizes)
112 		g->sizes[minor] = (plength >> (BLOCK_SIZE_BITS - 9));
113 	devfs_register_partitions (g, first_minor, 0);
114 	return 0;
115 }
116 
117 /*
118  * Delete a partition given by partition number
119  *
120  * returns: EINVAL: bad parameters
121  *          ENXIO: cannot find partition
122  *          EBUSY: partition is busy
123  *          0: all OK.
124  *
125  * Note that the dev argument refers to the entire disk, not the partition.
126  */
del_partition(kdev_t dev,struct blkpg_partition * p)127 int del_partition(kdev_t dev, struct blkpg_partition *p) {
128 	struct gendisk *g;
129 	kdev_t devp;
130 	int drive, first_minor, minor;
131 
132 	/* find the drive major */
133 	g = get_gendisk(dev);
134 	if (!g)
135 		return -ENXIO;
136 
137 	/* drive and partition number OK? */
138 	drive = (MINOR(dev) >> g->minor_shift);
139 	first_minor = (drive << g->minor_shift);
140 	if (first_minor != MINOR(dev) || p->pno <= 0 || p->pno >= g->max_p)
141 		return -EINVAL;
142 
143 	/* existing drive and partition? */
144 	minor = first_minor + p->pno;
145 	if (drive >= g->nr_real || g->part[minor].nr_sects == 0)
146 		return -ENXIO;
147 
148 	/* partition in use? Incomplete check for now. */
149 	devp = MKDEV(MAJOR(dev), minor);
150 	if (is_mounted(devp) || is_swap_partition(devp))
151 		return -EBUSY;
152 
153 	/* all seems OK */
154 	fsync_dev(devp);
155 	invalidate_buffers(devp);
156 
157 	g->part[minor].start_sect = 0;
158 	g->part[minor].nr_sects = 0;
159 	if (g->sizes)
160 		g->sizes[minor] = 0;
161 	devfs_register_partitions (g, first_minor, 0);
162 
163 	return 0;
164 }
165 
blkpg_ioctl(kdev_t dev,struct blkpg_ioctl_arg * arg)166 int blkpg_ioctl(kdev_t dev, struct blkpg_ioctl_arg *arg)
167 {
168 	struct blkpg_ioctl_arg a;
169 	struct blkpg_partition p;
170 	int len;
171 
172 	if (copy_from_user(&a, arg, sizeof(struct blkpg_ioctl_arg)))
173 		return -EFAULT;
174 
175 	switch (a.op) {
176 		case BLKPG_ADD_PARTITION:
177 		case BLKPG_DEL_PARTITION:
178 			len = a.datalen;
179 			if (len < sizeof(struct blkpg_partition))
180 				return -EINVAL;
181 			if (copy_from_user(&p, a.data, sizeof(struct blkpg_partition)))
182 				return -EFAULT;
183 			if (!capable(CAP_SYS_ADMIN))
184 				return -EACCES;
185 			if (a.op == BLKPG_ADD_PARTITION)
186 				return add_partition(dev, &p);
187 			else
188 				return del_partition(dev, &p);
189 		default:
190 			return -EINVAL;
191 	}
192 }
193 
194 /*
195  * Common ioctl's for block devices
196  */
197 
blk_ioctl(kdev_t dev,unsigned int cmd,unsigned long arg)198 int blk_ioctl(kdev_t dev, unsigned int cmd, unsigned long arg)
199 {
200 	struct gendisk *g;
201 	u64 ullval = 0;
202 	int intval;
203 
204 	if (!dev)
205 		return -EINVAL;
206 
207 	switch (cmd) {
208 		case BLKROSET:
209 			if (!capable(CAP_SYS_ADMIN))
210 				return -EACCES;
211 			if (get_user(intval, (int *)(arg)))
212 				return -EFAULT;
213 			set_device_ro(dev, intval);
214 			return 0;
215 		case BLKROGET:
216 			intval = (is_read_only(dev) != 0);
217 			return put_user(intval, (int *)(arg));
218 
219 		case BLKRASET:
220 			if(!capable(CAP_SYS_ADMIN))
221 				return -EACCES;
222 			if(arg > 0xff)
223 				return -EINVAL;
224 			read_ahead[MAJOR(dev)] = arg;
225 			return 0;
226 		case BLKRAGET:
227 			if (!arg)
228 				return -EINVAL;
229 			return put_user(read_ahead[MAJOR(dev)], (long *) arg);
230 
231 		case BLKFLSBUF:
232 			if(!capable(CAP_SYS_ADMIN))
233 				return -EACCES;
234 			fsync_dev(dev);
235 			invalidate_buffers(dev);
236 			return 0;
237 
238 		case BLKSSZGET:
239 			/* get block device sector size as needed e.g. by fdisk */
240 			intval = get_hardsect_size(dev);
241 			return put_user(intval, (int *) arg);
242 
243 		case BLKGETSIZE:
244 		case BLKGETSIZE64:
245 			g = get_gendisk(dev);
246 			if (g)
247 				ullval = g->part[MINOR(dev)].nr_sects;
248 
249 			if (cmd == BLKGETSIZE)
250 				return put_user((unsigned long)ullval, (unsigned long *)arg);
251 			else
252 				return put_user(ullval << 9, (u64 *)arg);
253 #if 0
254 		case BLKRRPART: /* Re-read partition tables */
255 			if (!capable(CAP_SYS_ADMIN))
256 				return -EACCES;
257 			return reread_partitions(dev, 1);
258 #endif
259 
260 		case BLKPG:
261 			return blkpg_ioctl(dev, (struct blkpg_ioctl_arg *) arg);
262 
263 		case BLKELVGET:
264 			return blkelvget_ioctl(&blk_get_queue(dev)->elevator,
265 					       (blkelv_ioctl_arg_t *) arg);
266 		case BLKELVSET:
267 			return blkelvset_ioctl(&blk_get_queue(dev)->elevator,
268 					       (blkelv_ioctl_arg_t *) arg);
269 
270 		case BLKBSZGET:
271 			/* get the logical block size (cf. BLKSSZGET) */
272 			intval = BLOCK_SIZE;
273 			if (blksize_size[MAJOR(dev)])
274 				intval = blksize_size[MAJOR(dev)][MINOR(dev)];
275 			return put_user (intval, (int *) arg);
276 
277 		case BLKBSZSET:
278 			/* set the logical block size */
279 			if (!capable (CAP_SYS_ADMIN))
280 				return -EACCES;
281 			if (!dev || !arg)
282 				return -EINVAL;
283 			if (get_user (intval, (int *) arg))
284 				return -EFAULT;
285 			if (intval > PAGE_SIZE || intval < 512 ||
286 			    (intval & (intval - 1)))
287 				return -EINVAL;
288 			if (is_mounted (dev) || is_swap_partition (dev))
289 				return -EBUSY;
290 			set_blocksize (dev, intval);
291 			return 0;
292 
293 		default:
294 			return -EINVAL;
295 	}
296 }
297 
298 EXPORT_SYMBOL(blk_ioctl);
299