aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
Diffstat (limited to 'block')
-rw-r--r--block/ioctl.c26
1 files changed, 22 insertions, 4 deletions
diff --git a/block/ioctl.c b/block/ioctl.c
index ca939fc1030..d510c2a4eff 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -180,6 +180,26 @@ int __blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode,
180EXPORT_SYMBOL_GPL(__blkdev_driver_ioctl); 180EXPORT_SYMBOL_GPL(__blkdev_driver_ioctl);
181 181
182/* 182/*
183 * Is it an unrecognized ioctl? The correct returns are either
184 * ENOTTY (final) or ENOIOCTLCMD ("I don't know this one, try a
185 * fallback"). ENOIOCTLCMD gets turned into ENOTTY by the ioctl
186 * code before returning.
187 *
188 * Confused drivers sometimes return EINVAL, which is wrong. It
189 * means "I understood the ioctl command, but the parameters to
190 * it were wrong".
191 *
192 * We should aim to just fix the broken drivers, the EINVAL case
193 * should go away.
194 */
195static inline int is_unrecognized_ioctl(int ret)
196{
197 return ret == -EINVAL ||
198 ret == -ENOTTY ||
199 ret == -ENOIOCTLCMD;
200}
201
202/*
183 * always keep this in sync with compat_blkdev_ioctl() 203 * always keep this in sync with compat_blkdev_ioctl()
184 */ 204 */
185int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, 205int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
@@ -196,8 +216,7 @@ int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
196 return -EACCES; 216 return -EACCES;
197 217
198 ret = __blkdev_driver_ioctl(bdev, mode, cmd, arg); 218 ret = __blkdev_driver_ioctl(bdev, mode, cmd, arg);
199 /* -EINVAL to handle old uncorrected drivers */ 219 if (!is_unrecognized_ioctl(ret))
200 if (ret != -EINVAL && ret != -ENOTTY)
201 return ret; 220 return ret;
202 221
203 fsync_bdev(bdev); 222 fsync_bdev(bdev);
@@ -206,8 +225,7 @@ int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
206 225
207 case BLKROSET: 226 case BLKROSET:
208 ret = __blkdev_driver_ioctl(bdev, mode, cmd, arg); 227 ret = __blkdev_driver_ioctl(bdev, mode, cmd, arg);
209 /* -EINVAL to handle old uncorrected drivers */ 228 if (!is_unrecognized_ioctl(ret))
210 if (ret != -EINVAL && ret != -ENOTTY)
211 return ret; 229 return ret;
212 if (!capable(CAP_SYS_ADMIN)) 230 if (!capable(CAP_SYS_ADMIN))
213 return -EACCES; 231 return -EACCES;