*/
#include "qemu/osdep.h"
-#include "qemu-common.h"
#include "qapi/error.h"
#include "qemu/cutils.h"
#include "qemu/error-report.h"
#include "qemu/module.h"
#include "qemu/option.h"
#include "qemu/units.h"
+#include "qemu/memalign.h"
#include "trace.h"
#include "block/thread-pool.h"
#include "qemu/iov.h"
#include <sys/diskslice.h>
#endif
-#ifdef CONFIG_XFS
-#include <xfs/xfs.h>
-#endif
-
/* OS X does not have O_DSYNC */
#ifndef O_DSYNC
#ifdef O_SYNC
int perm_change_flags;
BDRVReopenState *reopen_state;
-#ifdef CONFIG_XFS
- bool is_xfs:1;
-#endif
bool has_discard:1;
bool has_write_zeroes:1;
- bool discard_zeroes:1;
bool use_linux_aio:1;
bool use_linux_io_uring:1;
int page_cache_inconsistent; /* errno from fdatasync failure */
bool has_fallocate;
bool needs_alignment;
+ bool force_alignment;
bool drop_cache;
bool check_cache_dropped;
struct {
return false;
}
+static bool raw_needs_alignment(BlockDriverState *bs)
+{
+ BDRVRawState *s = bs->opaque;
+
+ if ((bs->open_flags & BDRV_O_NOCACHE) != 0 && !dio_byte_aligned(s->fd)) {
+ return true;
+ }
+
+ return s->force_alignment;
+}
+
/* Check if read is allowed with given memory buffer and length.
*
* This function is used to check O_DIRECT memory buffer and request alignment.
{
BDRVRawState *s = bs->opaque;
char *buf;
- size_t max_align = MAX(MAX_BLOCKSIZE, qemu_real_host_page_size);
+ size_t max_align = MAX(MAX_BLOCKSIZE, qemu_real_host_page_size());
size_t alignments[] = {1, 512, 1024, 2048, 4096};
/* For SCSI generic devices the alignment is not really used.
if (probe_logical_blocksize(fd, &bs->bl.request_alignment) < 0) {
bs->bl.request_alignment = 0;
}
-#ifdef CONFIG_XFS
- if (s->is_xfs) {
- struct dioattr da;
- if (xfsctl(NULL, fd, XFS_IOC_DIOINFO, &da) >= 0) {
- bs->bl.request_alignment = da.d_miniosz;
- /* The kernel returns wrong information for d_mem */
- /* s->buf_align = da.d_mem; */
- }
+
+#ifdef __linux__
+ /*
+ * The XFS ioctl definitions are shipped in extra packages that might
+ * not always be available. Since we just need the XFS_IOC_DIOINFO ioctl
+ * here, we simply use our own definition instead:
+ */
+ struct xfs_dioattr {
+ uint32_t d_mem;
+ uint32_t d_miniosz;
+ uint32_t d_maxiosz;
+ } da;
+ if (ioctl(fd, _IOR('X', 30, struct xfs_dioattr), &da) >= 0) {
+ bs->bl.request_alignment = da.d_miniosz;
+ /* The kernel returns wrong information for d_mem */
+ /* s->buf_align = da.d_mem; */
}
#endif
s->has_discard = true;
s->has_write_zeroes = true;
- if ((bs->open_flags & BDRV_O_NOCACHE) != 0 && !dio_byte_aligned(s->fd)) {
- s->needs_alignment = true;
- }
if (fstat(s->fd, &st) < 0) {
ret = -errno;
ret = -EINVAL;
goto fail;
} else {
- s->discard_zeroes = true;
s->has_fallocate = true;
}
} else {
}
if (S_ISBLK(st.st_mode)) {
-#ifdef BLKDISCARDZEROES
- unsigned int arg;
- if (ioctl(s->fd, BLKDISCARDZEROES, &arg) == 0 && arg) {
- s->discard_zeroes = true;
- }
-#endif
#ifdef __linux__
/* On Linux 3.10, BLKDISCARD leaves stale data in the page cache. Do
* not rely on the contents of discarded blocks unless using O_DIRECT.
* Same for BLKZEROOUT.
*/
if (!(bs->open_flags & BDRV_O_NOCACHE)) {
- s->discard_zeroes = false;
s->has_write_zeroes = false;
}
#endif
* so QEMU makes sure all IO operations on the device are aligned
* to sector size, or else FreeBSD will reject them with EINVAL.
*/
- s->needs_alignment = true;
- }
-#endif
-
-#ifdef CONFIG_XFS
- if (platform_test_xfs_fd(s->fd)) {
- s->is_xfs = true;
+ s->force_alignment = true;
}
#endif
+ s->needs_alignment = raw_needs_alignment(bs);
bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK;
if (S_ISREG(st.st_mode)) {
return ret;
}
+/* Sets a specific flag */
+static int fcntl_setfl(int fd, int flag)
+{
+ int flags;
+
+ flags = fcntl(fd, F_GETFL);
+ if (flags == -1) {
+ return -errno;
+ }
+ if (fcntl(fd, F_SETFL, flags | flag) == -1) {
+ return -errno;
+ }
+ return 0;
+}
+
static int raw_reconfigure_getfd(BlockDriverState *bs, int flags,
int *open_flags, uint64_t perm, bool force_dup,
Error **errp)
BDRVRawState *s = bs->opaque;
struct stat st;
+ s->needs_alignment = raw_needs_alignment(bs);
raw_probe_alignment(bs, s->fd, errp);
+
bs->bl.min_mem_alignment = s->buf_align;
- bs->bl.opt_mem_alignment = MAX(s->buf_align, qemu_real_host_page_size);
+ bs->bl.opt_mem_alignment = MAX(s->buf_align, qemu_real_host_page_size());
/*
* Maximum transfers are best effort, so it is okay to ignore any
}
#endif
- if (bs->sg || S_ISBLK(st.st_mode)) {
+ if (bdrv_is_sg(bs) || S_ISBLK(st.st_mode)) {
int ret = hdev_get_max_hw_transfer(s->fd, &st);
if (ret > 0 && ret <= BDRV_REQUEST_MAX_BYTES) {
size_t write_size = (max_size < MAX_BLOCKSIZE)
? BDRV_SECTOR_SIZE
: MAX_BLOCKSIZE;
- size_t max_align = MAX(MAX_BLOCKSIZE, qemu_real_host_page_size);
+ size_t max_align = MAX(MAX_BLOCKSIZE, qemu_real_host_page_size());
void *buf;
ssize_t n;
int ret;
return thread_pool_submit_co(pool, func, arg);
}
+/*
+ * Check if all memory in this vector is sector aligned.
+ */
+static bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov)
+{
+ int i;
+ size_t alignment = bdrv_min_mem_align(bs);
+ size_t len = bs->bl.request_alignment;
+ IO_CODE();
+
+ for (i = 0; i < qiov->niov; i++) {
+ if ((uintptr_t) qiov->iov[i].iov_base % alignment) {
+ return false;
+ }
+ if (qiov->iov[i].iov_len % len) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
static int coroutine_fn raw_co_prw(BlockDriverState *bs, uint64_t offset,
uint64_t bytes, QEMUIOVector *qiov, int type)
{
#endif
}
-static int raw_co_flush_to_disk(BlockDriverState *bs)
+static int coroutine_fn raw_co_flush_to_disk(BlockDriverState *bs)
{
BDRVRawState *s = bs->opaque;
RawPosixAIOData acb;
#if defined(__APPLE__) && defined(__MACH__)
static kern_return_t GetBSDPath(io_iterator_t mediaIterator, char *bsdPath,
CFIndex maxPathSize, int flags);
+
+#if !defined(MAC_OS_VERSION_12_0) \
+ || (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_VERSION_12_0)
+#define IOMainPort IOMasterPort
+#endif
+
static char *FindEjectableOpticalMedia(io_iterator_t *mediaIterator)
{
kern_return_t kernResult = KERN_FAILURE;
- mach_port_t masterPort;
+ mach_port_t mainPort;
CFMutableDictionaryRef classesToMatch;
const char *matching_array[] = {kIODVDMediaClass, kIOCDMediaClass};
char *mediaType = NULL;
- kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort );
+ kernResult = IOMainPort(MACH_PORT_NULL, &mainPort);
if ( KERN_SUCCESS != kernResult ) {
- printf( "IOMasterPort returned %d\n", kernResult );
+ printf("IOMainPort returned %d\n", kernResult);
}
int index;
}
CFDictionarySetValue(classesToMatch, CFSTR(kIOMediaEjectableKey),
kCFBooleanTrue);
- kernResult = IOServiceGetMatchingServices(masterPort, classesToMatch,
+ kernResult = IOServiceGetMatchingServices(mainPort, classesToMatch,
mediaIterator);
if (kernResult != KERN_SUCCESS) {
error_report("Note: IOServiceGetMatchingServices returned %d",