|
62 | 62 | #include <sys/ioctl.h>
|
63 | 63 | #include <sys/param.h>
|
64 | 64 | #include <sys/syscall.h>
|
| 65 | +#include <sys/vfs.h> |
65 | 66 | #include <linux/cdrom.h>
|
66 | 67 | #include <linux/fd.h>
|
67 | 68 | #include <linux/fs.h>
|
68 | 69 | #include <linux/hdreg.h>
|
| 70 | +#include <linux/magic.h> |
69 | 71 | #include <scsi/sg.h>
|
70 | 72 | #ifdef __s390__
|
71 | 73 | #include <asm/dasd.h>
|
@@ -300,6 +302,28 @@ static int probe_physical_blocksize(int fd, unsigned int *blk_size)
|
300 | 302 | #endif
|
301 | 303 | }
|
302 | 304 |
|
| 305 | +/* |
| 306 | + * Returns true if no alignment restrictions are necessary even for files |
| 307 | + * opened with O_DIRECT. |
| 308 | + * |
| 309 | + * raw_probe_alignment() probes the required alignment and assume that 1 means |
| 310 | + * the probing failed, so it falls back to a safe default of 4k. This can be |
| 311 | + * avoided if we know that byte alignment is okay for the file. |
| 312 | + */ |
| 313 | +static bool dio_byte_aligned(int fd) |
| 314 | +{ |
| 315 | +#ifdef __linux__ |
| 316 | + struct statfs buf; |
| 317 | + int ret; |
| 318 | + |
| 319 | + ret = fstatfs(fd, &buf); |
| 320 | + if (ret == 0 && buf.f_type == NFS_SUPER_MAGIC) { |
| 321 | + return true; |
| 322 | + } |
| 323 | +#endif |
| 324 | + return false; |
| 325 | +} |
| 326 | + |
303 | 327 | /* Check if read is allowed with given memory buffer and length.
|
304 | 328 | *
|
305 | 329 | * This function is used to check O_DIRECT memory buffer and request alignment.
|
@@ -401,6 +425,39 @@ static void raw_probe_alignment(BlockDriverState *bs, int fd, Error **errp)
|
401 | 425 | }
|
402 | 426 | }
|
403 | 427 |
|
| 428 | +static int check_hdev_writable(int fd) |
| 429 | +{ |
| 430 | +#if defined(BLKROGET) |
| 431 | + /* Linux block devices can be configured "read-only" using blockdev(8). |
| 432 | + * This is independent of device node permissions and therefore open(2) |
| 433 | + * with O_RDWR succeeds. Actual writes fail with EPERM. |
| 434 | + * |
| 435 | + * bdrv_open() is supposed to fail if the disk is read-only. Explicitly |
| 436 | + * check for read-only block devices so that Linux block devices behave |
| 437 | + * properly. |
| 438 | + */ |
| 439 | + struct stat st; |
| 440 | + int readonly = 0; |
| 441 | + |
| 442 | + if (fstat(fd, &st)) { |
| 443 | + return -errno; |
| 444 | + } |
| 445 | + |
| 446 | + if (!S_ISBLK(st.st_mode)) { |
| 447 | + return 0; |
| 448 | + } |
| 449 | + |
| 450 | + if (ioctl(fd, BLKROGET, &readonly) < 0) { |
| 451 | + return -errno; |
| 452 | + } |
| 453 | + |
| 454 | + if (readonly) { |
| 455 | + return -EACCES; |
| 456 | + } |
| 457 | +#endif /* defined(BLKROGET) */ |
| 458 | + return 0; |
| 459 | +} |
| 460 | + |
404 | 461 | static void raw_parse_flags(int bdrv_flags, int *open_flags, bool has_writers)
|
405 | 462 | {
|
406 | 463 | bool read_write = false;
|
@@ -585,6 +642,15 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
|
585 | 642 | }
|
586 | 643 | s->fd = fd;
|
587 | 644 |
|
| 645 | + /* Check s->open_flags rather than bdrv_flags due to auto-read-only */ |
| 646 | + if (s->open_flags & O_RDWR) { |
| 647 | + ret = check_hdev_writable(s->fd); |
| 648 | + if (ret < 0) { |
| 649 | + error_setg_errno(errp, -ret, "The device is not writable"); |
| 650 | + goto fail; |
| 651 | + } |
| 652 | + } |
| 653 | + |
588 | 654 | s->perm = 0;
|
589 | 655 | s->shared_perm = BLK_PERM_ALL;
|
590 | 656 |
|
@@ -629,7 +695,7 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
|
629 | 695 |
|
630 | 696 | s->has_discard = true;
|
631 | 697 | s->has_write_zeroes = true;
|
632 |
| - if ((bs->open_flags & BDRV_O_NOCACHE) != 0) { |
| 698 | + if ((bs->open_flags & BDRV_O_NOCACHE) != 0 && !dio_byte_aligned(s->fd)) { |
633 | 699 | s->needs_alignment = true;
|
634 | 700 | }
|
635 | 701 |
|
@@ -707,6 +773,9 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
|
707 | 773 | }
|
708 | 774 | ret = 0;
|
709 | 775 | fail:
|
| 776 | + if (ret < 0 && s->fd != -1) { |
| 777 | + qemu_close(s->fd); |
| 778 | + } |
710 | 779 | if (filename && (bdrv_flags & BDRV_O_TEMPORARY)) {
|
711 | 780 | unlink(filename);
|
712 | 781 | }
|
@@ -977,6 +1046,15 @@ static int raw_reconfigure_getfd(BlockDriverState *bs, int flags,
|
977 | 1046 | }
|
978 | 1047 | }
|
979 | 1048 |
|
| 1049 | + if (fd != -1 && (*open_flags & O_RDWR)) { |
| 1050 | + ret = check_hdev_writable(fd); |
| 1051 | + if (ret < 0) { |
| 1052 | + qemu_close(fd); |
| 1053 | + error_setg_errno(errp, -ret, "The device is not writable"); |
| 1054 | + return -1; |
| 1055 | + } |
| 1056 | + } |
| 1057 | + |
980 | 1058 | return fd;
|
981 | 1059 | }
|
982 | 1060 |
|
@@ -3299,39 +3377,6 @@ static int hdev_probe_device(const char *filename)
|
3299 | 3377 | return 0;
|
3300 | 3378 | }
|
3301 | 3379 |
|
3302 |
| -static int check_hdev_writable(BDRVRawState *s) |
3303 |
| -{ |
3304 |
| -#if defined(BLKROGET) |
3305 |
| - /* Linux block devices can be configured "read-only" using blockdev(8). |
3306 |
| - * This is independent of device node permissions and therefore open(2) |
3307 |
| - * with O_RDWR succeeds. Actual writes fail with EPERM. |
3308 |
| - * |
3309 |
| - * bdrv_open() is supposed to fail if the disk is read-only. Explicitly |
3310 |
| - * check for read-only block devices so that Linux block devices behave |
3311 |
| - * properly. |
3312 |
| - */ |
3313 |
| - struct stat st; |
3314 |
| - int readonly = 0; |
3315 |
| - |
3316 |
| - if (fstat(s->fd, &st)) { |
3317 |
| - return -errno; |
3318 |
| - } |
3319 |
| - |
3320 |
| - if (!S_ISBLK(st.st_mode)) { |
3321 |
| - return 0; |
3322 |
| - } |
3323 |
| - |
3324 |
| - if (ioctl(s->fd, BLKROGET, &readonly) < 0) { |
3325 |
| - return -errno; |
3326 |
| - } |
3327 |
| - |
3328 |
| - if (readonly) { |
3329 |
| - return -EACCES; |
3330 |
| - } |
3331 |
| -#endif /* defined(BLKROGET) */ |
3332 |
| - return 0; |
3333 |
| -} |
3334 |
| - |
3335 | 3380 | static void hdev_parse_filename(const char *filename, QDict *options,
|
3336 | 3381 | Error **errp)
|
3337 | 3382 | {
|
@@ -3454,15 +3499,6 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags,
|
3454 | 3499 | /* Since this does ioctl the device must be already opened */
|
3455 | 3500 | bs->sg = hdev_is_sg(bs);
|
3456 | 3501 |
|
3457 |
| - if (flags & BDRV_O_RDWR) { |
3458 |
| - ret = check_hdev_writable(s); |
3459 |
| - if (ret < 0) { |
3460 |
| - raw_close(bs); |
3461 |
| - error_setg_errno(errp, -ret, "The device is not writable"); |
3462 |
| - return ret; |
3463 |
| - } |
3464 |
| - } |
3465 |
| - |
3466 | 3502 | return ret;
|
3467 | 3503 | }
|
3468 | 3504 |
|
|
0 commit comments