Blame view
block/ioctl.c
8.65 KB
c59ede7b7 [PATCH] move capa... |
1 |
#include <linux/capability.h> |
1da177e4c Linux-2.6.12-rc2 |
2 |
#include <linux/blkdev.h> |
d5decd3b9 block: add export... |
3 |
#include <linux/export.h> |
5a0e3ad6a include cleanup: ... |
4 |
#include <linux/gfp.h> |
1da177e4c Linux-2.6.12-rc2 |
5 |
#include <linux/blkpg.h> |
a885c8c43 [PATCH] Add block... |
6 |
#include <linux/hdreg.h> |
1da177e4c Linux-2.6.12-rc2 |
7 |
#include <linux/backing-dev.h> |
ff01bb483 fs: move code out... |
8 |
#include <linux/fs.h> |
2056a782f [PATCH] Block que... |
9 |
#include <linux/blktrace_api.h> |
1da177e4c Linux-2.6.12-rc2 |
10 11 12 13 14 15 |
#include <asm/uaccess.h> static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user *arg) { struct block_device *bdevp; struct gendisk *disk; |
e71bf0d0e block: fix disk->... |
16 |
struct hd_struct *part; |
1da177e4c Linux-2.6.12-rc2 |
17 18 |
struct blkpg_ioctl_arg a; struct blkpg_partition p; |
e71bf0d0e block: fix disk->... |
19 |
struct disk_part_iter piter; |
1da177e4c Linux-2.6.12-rc2 |
20 |
long long start, length; |
cf771cb5a block: make varia... |
21 |
int partno; |
1da177e4c Linux-2.6.12-rc2 |
22 23 24 25 26 27 28 29 30 31 |
if (!capable(CAP_SYS_ADMIN)) return -EACCES; if (copy_from_user(&a, arg, sizeof(struct blkpg_ioctl_arg))) return -EFAULT; if (copy_from_user(&p, a.data, sizeof(struct blkpg_partition))) return -EFAULT; disk = bdev->bd_disk; if (bdev != bdev->bd_contains) return -EINVAL; |
cf771cb5a block: make varia... |
32 |
partno = p.pno; |
540eed563 block: make parti... |
33 |
if (partno <= 0) |
1da177e4c Linux-2.6.12-rc2 |
34 35 36 37 38 39 40 41 42 43 44 45 46 |
return -EINVAL; switch (a.op) { case BLKPG_ADD_PARTITION: start = p.start >> 9; length = p.length >> 9; /* check for fit in a hd_struct */ if (sizeof(sector_t) == sizeof(long) && sizeof(long long) > sizeof(long)) { long pstart = start, plength = length; if (pstart != start || plength != length || pstart < 0 || plength < 0) return -EINVAL; } |
88e341261 block: update add... |
47 |
|
c039e3134 [PATCH] sem2mutex... |
48 |
mutex_lock(&bdev->bd_mutex); |
88e341261 block: update add... |
49 |
|
1da177e4c Linux-2.6.12-rc2 |
50 |
/* overlap? */ |
e71bf0d0e block: fix disk->... |
51 52 53 54 55 56 |
disk_part_iter_init(&piter, disk, DISK_PITER_INCL_EMPTY); while ((part = disk_part_iter_next(&piter))) { if (!(start + length <= part->start_sect || start >= part->start_sect + part->nr_sects)) { disk_part_iter_exit(&piter); |
c039e3134 [PATCH] sem2mutex... |
57 |
mutex_unlock(&bdev->bd_mutex); |
1da177e4c Linux-2.6.12-rc2 |
58 59 60 |
return -EBUSY; } } |
e71bf0d0e block: fix disk->... |
61 |
disk_part_iter_exit(&piter); |
1da177e4c Linux-2.6.12-rc2 |
62 |
/* all seems OK */ |
ba32929a9 block: make add_p... |
63 |
part = add_partition(disk, partno, start, length, |
6d1d8050b block, partition:... |
64 |
ADDPART_FLAG_NONE, NULL); |
c039e3134 [PATCH] sem2mutex... |
65 |
mutex_unlock(&bdev->bd_mutex); |
ba32929a9 block: make add_p... |
66 |
return IS_ERR(part) ? PTR_ERR(part) : 0; |
1da177e4c Linux-2.6.12-rc2 |
67 |
case BLKPG_DEL_PARTITION: |
e71bf0d0e block: fix disk->... |
68 69 |
part = disk_get_part(disk, partno); if (!part) |
1da177e4c Linux-2.6.12-rc2 |
70 |
return -ENXIO; |
e71bf0d0e block: fix disk->... |
71 72 73 |
bdevp = bdget(part_devt(part)); disk_put_part(part); |
1da177e4c Linux-2.6.12-rc2 |
74 75 |
if (!bdevp) return -ENOMEM; |
e71bf0d0e block: fix disk->... |
76 |
|
2e7b651df [PATCH] remove th... |
77 |
mutex_lock(&bdevp->bd_mutex); |
1da177e4c Linux-2.6.12-rc2 |
78 |
if (bdevp->bd_openers) { |
c039e3134 [PATCH] sem2mutex... |
79 |
mutex_unlock(&bdevp->bd_mutex); |
1da177e4c Linux-2.6.12-rc2 |
80 81 82 83 84 |
bdput(bdevp); return -EBUSY; } /* all seems OK */ fsync_bdev(bdevp); |
f98393a64 mm: remove destro... |
85 |
invalidate_bdev(bdevp); |
1da177e4c Linux-2.6.12-rc2 |
86 |
|
6d740cd5b [PATCH] lockdep: ... |
87 |
mutex_lock_nested(&bdev->bd_mutex, 1); |
cf771cb5a block: make varia... |
88 |
delete_partition(disk, partno); |
c039e3134 [PATCH] sem2mutex... |
89 90 |
mutex_unlock(&bdev->bd_mutex); mutex_unlock(&bdevp->bd_mutex); |
1da177e4c Linux-2.6.12-rc2 |
91 92 93 94 95 96 97 98 99 100 101 102 |
bdput(bdevp); return 0; default: return -EINVAL; } } static int blkdev_reread_part(struct block_device *bdev) { struct gendisk *disk = bdev->bd_disk; int res; |
d27769ec3 block: add GENHD_... |
103 |
if (!disk_part_scan_enabled(disk) || bdev != bdev->bd_contains) |
1da177e4c Linux-2.6.12-rc2 |
104 105 106 |
return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EACCES; |
c039e3134 [PATCH] sem2mutex... |
107 |
if (!mutex_trylock(&bdev->bd_mutex)) |
1da177e4c Linux-2.6.12-rc2 |
108 109 |
return -EBUSY; res = rescan_partitions(disk, bdev); |
c039e3134 [PATCH] sem2mutex... |
110 |
mutex_unlock(&bdev->bd_mutex); |
1da177e4c Linux-2.6.12-rc2 |
111 112 |
return res; } |
d30a2605b Add BLKDISCARD io... |
113 |
static int blk_ioctl_discard(struct block_device *bdev, uint64_t start, |
8d57a98cc block: add secure... |
114 |
uint64_t len, int secure) |
d30a2605b Add BLKDISCARD io... |
115 |
{ |
dd3932edd block: remove BLK... |
116 |
unsigned long flags = 0; |
8d57a98cc block: add secure... |
117 |
|
d30a2605b Add BLKDISCARD io... |
118 119 120 121 122 123 |
if (start & 511) return -EINVAL; if (len & 511) return -EINVAL; start >>= 9; len >>= 9; |
77304d2ab block: read i_siz... |
124 |
if (start + len > (i_size_read(bdev->bd_inode) >> 9)) |
d30a2605b Add BLKDISCARD io... |
125 |
return -EINVAL; |
8d57a98cc block: add secure... |
126 |
if (secure) |
dd3932edd block: remove BLK... |
127 |
flags |= BLKDEV_DISCARD_SECURE; |
8d57a98cc block: add secure... |
128 |
return blkdev_issue_discard(bdev, start, len, GFP_KERNEL, flags); |
d30a2605b Add BLKDISCARD io... |
129 |
} |
1da177e4c Linux-2.6.12-rc2 |
130 131 132 133 134 135 136 137 138 |
static int put_ushort(unsigned long arg, unsigned short val) { return put_user(val, (unsigned short __user *)arg); } static int put_int(unsigned long arg, int val) { return put_user(val, (int __user *)arg); } |
ac481c20e block: Topology i... |
139 140 141 142 |
static int put_uint(unsigned long arg, unsigned int val) { return put_user(val, (unsigned int __user *)arg); } |
1da177e4c Linux-2.6.12-rc2 |
143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
static int put_long(unsigned long arg, long val) { return put_user(val, (long __user *)arg); } static int put_ulong(unsigned long arg, unsigned long val) { return put_user(val, (unsigned long __user *)arg); } static int put_u64(unsigned long arg, u64 val) { return put_user(val, (u64 __user *)arg); } |
633a08b81 [PATCH] introduce... |
157 158 159 160 |
int __blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, unsigned long arg) { struct gendisk *disk = bdev->bd_disk; |
d4430d62f [PATCH] beginning... |
161 162 163 |
if (disk->fops->ioctl) return disk->fops->ioctl(bdev, mode, cmd, arg); |
633a08b81 [PATCH] introduce... |
164 |
|
633a08b81 [PATCH] introduce... |
165 166 167 168 169 170 171 172 |
return -ENOTTY; } /* * For the record: _GPL here is only because somebody decided to slap it * on the previous export. Sheer idiocy, since it wasn't copyrightable * at all and could be open-coded without any exports by anybody who cares. */ EXPORT_SYMBOL_GPL(__blkdev_driver_ioctl); |
f58c4c0a1 compat_ioctl: mov... |
173 |
/* |
07d106d0a vfs: fix up ENOIO... |
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
* Is it an unrecognized ioctl? The correct returns are either * ENOTTY (final) or ENOIOCTLCMD ("I don't know this one, try a * fallback"). ENOIOCTLCMD gets turned into ENOTTY by the ioctl * code before returning. * * Confused drivers sometimes return EINVAL, which is wrong. It * means "I understood the ioctl command, but the parameters to * it were wrong". * * We should aim to just fix the broken drivers, the EINVAL case * should go away. */ static inline int is_unrecognized_ioctl(int ret) { return ret == -EINVAL || ret == -ENOTTY || ret == -ENOIOCTLCMD; } /* |
8a6cfeb6d block: push down ... |
194 |
* always keep this in sync with compat_blkdev_ioctl() |
f58c4c0a1 compat_ioctl: mov... |
195 |
*/ |
56b26add0 [PATCH] kill the ... |
196 |
int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, |
bb93e3a52 [PATCH] block: ad... |
197 198 |
unsigned long arg) { |
bb93e3a52 [PATCH] block: ad... |
199 |
struct gendisk *disk = bdev->bd_disk; |
45048d096 [PATCH] get rid o... |
200 201 |
struct backing_dev_info *bdi; loff_t size; |
bb93e3a52 [PATCH] block: ad... |
202 203 204 |
int ret, n; switch(cmd) { |
1da177e4c Linux-2.6.12-rc2 |
205 206 207 |
case BLKFLSBUF: if (!capable(CAP_SYS_ADMIN)) return -EACCES; |
bb93e3a52 [PATCH] block: ad... |
208 |
|
e436fdae7 [PATCH] get rid o... |
209 |
ret = __blkdev_driver_ioctl(bdev, mode, cmd, arg); |
07d106d0a vfs: fix up ENOIO... |
210 |
if (!is_unrecognized_ioctl(ret)) |
bb93e3a52 [PATCH] block: ad... |
211 |
return ret; |
1da177e4c Linux-2.6.12-rc2 |
212 |
fsync_bdev(bdev); |
f98393a64 mm: remove destro... |
213 |
invalidate_bdev(bdev); |
1da177e4c Linux-2.6.12-rc2 |
214 |
return 0; |
bb93e3a52 [PATCH] block: ad... |
215 |
|
1da177e4c Linux-2.6.12-rc2 |
216 |
case BLKROSET: |
e436fdae7 [PATCH] get rid o... |
217 |
ret = __blkdev_driver_ioctl(bdev, mode, cmd, arg); |
07d106d0a vfs: fix up ENOIO... |
218 |
if (!is_unrecognized_ioctl(ret)) |
bb93e3a52 [PATCH] block: ad... |
219 |
return ret; |
1da177e4c Linux-2.6.12-rc2 |
220 221 222 223 224 225 |
if (!capable(CAP_SYS_ADMIN)) return -EACCES; if (get_user(n, (int __user *)(arg))) return -EFAULT; set_device_ro(bdev, n); return 0; |
d30a2605b Add BLKDISCARD io... |
226 |
|
8d57a98cc block: add secure... |
227 228 |
case BLKDISCARD: case BLKSECDISCARD: { |
d30a2605b Add BLKDISCARD io... |
229 |
uint64_t range[2]; |
e436fdae7 [PATCH] get rid o... |
230 |
if (!(mode & FMODE_WRITE)) |
d30a2605b Add BLKDISCARD io... |
231 232 233 234 |
return -EBADF; if (copy_from_user(range, (void __user *)arg, sizeof(range))) return -EFAULT; |
8d57a98cc block: add secure... |
235 236 |
return blk_ioctl_discard(bdev, range[0], range[1], cmd == BLKSECDISCARD); |
d30a2605b Add BLKDISCARD io... |
237 |
} |
a885c8c43 [PATCH] Add block... |
238 239 240 241 242 243 244 245 246 247 248 249 |
case HDIO_GETGEO: { struct hd_geometry geo; if (!arg) return -EINVAL; if (!disk->fops->getgeo) return -ENOTTY; /* * We need to set the startsect first, the driver may * want to override it. */ |
a014741c0 block: ioctl: fix... |
250 |
memset(&geo, 0, sizeof(geo)); |
a885c8c43 [PATCH] Add block... |
251 252 253 254 255 256 257 258 259 |
geo.start = get_start_sect(bdev); ret = disk->fops->getgeo(bdev, &geo); if (ret) return ret; if (copy_to_user((struct hd_geometry __user *)arg, &geo, sizeof(geo))) return -EFAULT; return 0; } |
45048d096 [PATCH] get rid o... |
260 261 262 263 264 265 266 267 268 269 |
case BLKRAGET: case BLKFRAGET: if (!arg) return -EINVAL; bdi = blk_get_backing_dev_info(bdev); if (bdi == NULL) return -ENOTTY; return put_long(arg, (bdi->ra_pages * PAGE_CACHE_SIZE) / 512); case BLKROGET: return put_int(arg, bdev_read_only(bdev) != 0); |
ac481c20e block: Topology i... |
270 |
case BLKBSZGET: /* get block device soft block size (cf. BLKSSZGET) */ |
45048d096 [PATCH] get rid o... |
271 |
return put_int(arg, block_size(bdev)); |
ac481c20e block: Topology i... |
272 |
case BLKSSZGET: /* get block device logical block size */ |
e1defc4ff block: Do away wi... |
273 |
return put_int(arg, bdev_logical_block_size(bdev)); |
ac481c20e block: Topology i... |
274 275 276 277 278 279 280 281 |
case BLKPBSZGET: /* get block device physical block size */ return put_uint(arg, bdev_physical_block_size(bdev)); case BLKIOMIN: return put_uint(arg, bdev_io_min(bdev)); case BLKIOOPT: return put_uint(arg, bdev_io_opt(bdev)); case BLKALIGNOFF: return put_int(arg, bdev_alignment_offset(bdev)); |
98262f276 block: Allow devi... |
282 283 |
case BLKDISCARDZEROES: return put_uint(arg, bdev_discard_zeroes_data(bdev)); |
45048d096 [PATCH] get rid o... |
284 |
case BLKSECTGET: |
ae03bf639 block: Use access... |
285 |
return put_ushort(arg, queue_max_sectors(bdev_get_queue(bdev))); |
ef00f59c9 block: Add BLKROT... |
286 287 |
case BLKROTATIONAL: return put_ushort(arg, !blk_queue_nonrot(bdev_get_queue(bdev))); |
45048d096 [PATCH] get rid o... |
288 289 290 291 292 293 294 |
case BLKRASET: case BLKFRASET: if(!capable(CAP_SYS_ADMIN)) return -EACCES; bdi = blk_get_backing_dev_info(bdev); if (bdi == NULL) return -ENOTTY; |
45048d096 [PATCH] get rid o... |
295 |
bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE; |
45048d096 [PATCH] get rid o... |
296 297 298 299 300 301 302 303 304 |
return 0; case BLKBSZSET: /* set the logical block size */ if (!capable(CAP_SYS_ADMIN)) return -EACCES; if (!arg) return -EINVAL; if (get_user(n, (int __user *) arg)) return -EFAULT; |
3c522cedb block: fix refcou... |
305 306 307 308 309 |
if (!(mode & FMODE_EXCL)) { bdgrab(bdev); if (blkdev_get(bdev, mode | FMODE_EXCL, &bdev) < 0) return -EBUSY; } |
45048d096 [PATCH] get rid o... |
310 |
ret = set_blocksize(bdev, n); |
6af3a56e1 [PATCH] get rid o... |
311 |
if (!(mode & FMODE_EXCL)) |
e525fd89d block: make blkde... |
312 |
blkdev_put(bdev, mode | FMODE_EXCL); |
bb93e3a52 [PATCH] block: ad... |
313 |
return ret; |
45048d096 [PATCH] get rid o... |
314 |
case BLKPG: |
45048d096 [PATCH] get rid o... |
315 |
ret = blkpg_ioctl(bdev, (struct blkpg_ioctl_arg __user *) arg); |
45048d096 [PATCH] get rid o... |
316 317 |
break; case BLKRRPART: |
45048d096 [PATCH] get rid o... |
318 |
ret = blkdev_reread_part(bdev); |
45048d096 [PATCH] get rid o... |
319 320 |
break; case BLKGETSIZE: |
77304d2ab block: read i_siz... |
321 |
size = i_size_read(bdev->bd_inode); |
45048d096 [PATCH] get rid o... |
322 323 324 325 |
if ((size >> 9) > ~0UL) return -EFBIG; return put_ulong(arg, size >> 9); case BLKGETSIZE64: |
77304d2ab block: read i_siz... |
326 |
return put_u64(arg, i_size_read(bdev->bd_inode)); |
45048d096 [PATCH] get rid o... |
327 328 329 330 |
case BLKTRACESTART: case BLKTRACESTOP: case BLKTRACESETUP: case BLKTRACETEARDOWN: |
45048d096 [PATCH] get rid o... |
331 |
ret = blk_trace_ioctl(bdev, cmd, (char __user *) arg); |
45048d096 [PATCH] get rid o... |
332 333 334 335 336 |
break; default: ret = __blkdev_driver_ioctl(bdev, mode, cmd, arg); } return ret; |
1da177e4c Linux-2.6.12-rc2 |
337 |
} |
68f66feb3 [PATCH] Fix root ... |
338 |
EXPORT_SYMBOL_GPL(blkdev_ioctl); |