Commit a9cb55a3 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-request' into staging



Block pull request

 * Support -drive cache.direct=off live migration for POSIX files

# gpg: Signature made Sat 12 May 2018 10:27:51 BST
# gpg:                using RSA key 9CA4ABB381AB73C8
# gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>"
# gpg:                 aka "Stefan Hajnoczi <stefanha@gmail.com>"
# Primary key fingerprint: 8695 A8BF D3F9 7CDA AC35  775A 9CA4 ABB3 81AB 73C8

* remotes/stefanha/tags/block-pull-request:
  block/file-posix: add x-check-page-cache=on|off option
  block/file-posix: implement bdrv_co_invalidate_cache() on Linux
  checkpatch: reduce MAINTAINERS update message frequency
  checkpatch: emit a warning on file add/move/delete
  checkpatch: ignore email headers better
  checkpatch: check utf-8 content from a commit log when it's missing from charset
  checkpatch: add a --strict check for utf-8 in commit logs
  blockjob: drop block_job_pause/resume_all()

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 7a9180b7 31be8a2a
Loading
Loading
Loading
Loading
+144 −2
Original line number Diff line number Diff line
@@ -161,6 +161,7 @@ typedef struct BDRVRawState {
    bool page_cache_inconsistent:1;
    bool has_fallocate;
    bool needs_alignment;
    bool check_cache_dropped;

    PRManager *pr_mgr;
} BDRVRawState;
@@ -168,6 +169,7 @@ typedef struct BDRVRawState {
typedef struct BDRVRawReopenState {
    int fd;
    int open_flags;
    bool check_cache_dropped;
} BDRVRawReopenState;

static int fd_open(BlockDriverState *bs);
@@ -415,6 +417,11 @@ static QemuOptsList raw_runtime_opts = {
            .type = QEMU_OPT_STRING,
            .help = "id of persistent reservation manager object (default: none)",
        },
        {
            .name = "x-check-cache-dropped",
            .type = QEMU_OPT_BOOL,
            .help = "check that page cache was dropped on live migration (default: off)"
        },
        { /* end of list */ }
    },
};
@@ -500,6 +507,9 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
        }
    }

    s->check_cache_dropped = qemu_opt_get_bool(opts, "x-check-cache-dropped",
                                               false);

    s->open_flags = open_flags;
    raw_parse_flags(bdrv_flags, &s->open_flags);

@@ -777,6 +787,7 @@ static int raw_reopen_prepare(BDRVReopenState *state,
{
    BDRVRawState *s;
    BDRVRawReopenState *rs;
    QemuOpts *opts;
    int ret = 0;
    Error *local_err = NULL;

@@ -787,6 +798,19 @@ static int raw_reopen_prepare(BDRVReopenState *state,

    state->opaque = g_new0(BDRVRawReopenState, 1);
    rs = state->opaque;
    rs->fd = -1;

    /* Handle options changes */
    opts = qemu_opts_create(&raw_runtime_opts, NULL, 0, &error_abort);
    qemu_opts_absorb_qdict(opts, state->options, &local_err);
    if (local_err) {
        error_propagate(errp, local_err);
        ret = -EINVAL;
        goto out;
    }

    rs->check_cache_dropped = qemu_opt_get_bool(opts, "x-check-cache-dropped",
                                                s->check_cache_dropped);

    if (s->type == FTYPE_CD) {
        rs->open_flags |= O_NONBLOCK;
@@ -794,8 +818,6 @@ static int raw_reopen_prepare(BDRVReopenState *state,

    raw_parse_flags(state->flags, &rs->open_flags);

    rs->fd = -1;

    int fcntl_flags = O_APPEND | O_NONBLOCK;
#ifdef O_NOATIME
    fcntl_flags |= O_NOATIME;
@@ -850,6 +872,8 @@ static int raw_reopen_prepare(BDRVReopenState *state,
        }
    }

out:
    qemu_opts_del(opts);
    return ret;
}

@@ -858,6 +882,7 @@ static void raw_reopen_commit(BDRVReopenState *state)
    BDRVRawReopenState *rs = state->opaque;
    BDRVRawState *s = state->bs->opaque;

    s->check_cache_dropped = rs->check_cache_dropped;
    s->open_flags = rs->open_flags;

    qemu_close(s->fd);
@@ -2236,6 +2261,120 @@ static int coroutine_fn raw_co_block_status(BlockDriverState *bs,
    return ret | BDRV_BLOCK_OFFSET_VALID;
}

#if defined(__linux__)
/* Verify that the file is not in the page cache */
static void check_cache_dropped(BlockDriverState *bs, Error **errp)
{
    const size_t window_size = 128 * 1024 * 1024;
    BDRVRawState *s = bs->opaque;
    void *window = NULL;
    size_t length = 0;
    unsigned char *vec;
    size_t page_size;
    off_t offset;
    off_t end;

    /* mincore(2) page status information requires 1 byte per page */
    page_size = sysconf(_SC_PAGESIZE);
    vec = g_malloc(DIV_ROUND_UP(window_size, page_size));

    end = raw_getlength(bs);

    for (offset = 0; offset < end; offset += window_size) {
        void *new_window;
        size_t new_length;
        size_t vec_end;
        size_t i;
        int ret;

        /* Unmap previous window if size has changed */
        new_length = MIN(end - offset, window_size);
        if (new_length != length) {
            munmap(window, length);
            window = NULL;
            length = 0;
        }

        new_window = mmap(window, new_length, PROT_NONE, MAP_PRIVATE,
                          s->fd, offset);
        if (new_window == MAP_FAILED) {
            error_setg_errno(errp, errno, "mmap failed");
            break;
        }

        window = new_window;
        length = new_length;

        ret = mincore(window, length, vec);
        if (ret < 0) {
            error_setg_errno(errp, errno, "mincore failed");
            break;
        }

        vec_end = DIV_ROUND_UP(length, page_size);
        for (i = 0; i < vec_end; i++) {
            if (vec[i] & 0x1) {
                error_setg(errp, "page cache still in use!");
                break;
            }
        }
    }

    if (window) {
        munmap(window, length);
    }

    g_free(vec);
}
#endif /* __linux__ */

static void coroutine_fn raw_co_invalidate_cache(BlockDriverState *bs,
                                                 Error **errp)
{
    BDRVRawState *s = bs->opaque;
    int ret;

    ret = fd_open(bs);
    if (ret < 0) {
        error_setg_errno(errp, -ret, "The file descriptor is not open");
        return;
    }

    if (s->open_flags & O_DIRECT) {
        return; /* No host kernel page cache */
    }

#if defined(__linux__)
    /* This sets the scene for the next syscall... */
    ret = bdrv_co_flush(bs);
    if (ret < 0) {
        error_setg_errno(errp, -ret, "flush failed");
        return;
    }

    /* Linux does not invalidate pages that are dirty, locked, or mmapped by a
     * process.  These limitations are okay because we just fsynced the file,
     * we don't use mmap, and the file should not be in use by other processes.
     */
    ret = posix_fadvise(s->fd, 0, 0, POSIX_FADV_DONTNEED);
    if (ret != 0) { /* the return value is a positive errno */
        error_setg_errno(errp, ret, "fadvise failed");
        return;
    }

    if (s->check_cache_dropped) {
        check_cache_dropped(bs, errp);
    }
#else /* __linux__ */
    /* Do nothing.  Live migration to a remote host with cache.direct=off is
     * unsupported on other host operating systems.  Cache consistency issues
     * may occur but no error is reported here, partly because that's the
     * historical behavior and partly because it's hard to differentiate valid
     * configurations that should not cause errors.
     */
#endif /* !__linux__ */
}

static coroutine_fn BlockAIOCB *raw_aio_pdiscard(BlockDriverState *bs,
    int64_t offset, int bytes,
    BlockCompletionFunc *cb, void *opaque)
@@ -2328,6 +2467,7 @@ BlockDriver bdrv_file = {
    .bdrv_co_create_opts = raw_co_create_opts,
    .bdrv_has_zero_init = bdrv_has_zero_init_1,
    .bdrv_co_block_status = raw_co_block_status,
    .bdrv_co_invalidate_cache = raw_co_invalidate_cache,
    .bdrv_co_pwrite_zeroes = raw_co_pwrite_zeroes,

    .bdrv_co_preadv         = raw_co_preadv,
@@ -2805,6 +2945,7 @@ static BlockDriver bdrv_host_device = {
    .bdrv_reopen_abort   = raw_reopen_abort,
    .bdrv_co_create_opts = hdev_co_create_opts,
    .create_opts         = &raw_create_opts,
    .bdrv_co_invalidate_cache = raw_co_invalidate_cache,
    .bdrv_co_pwrite_zeroes = hdev_co_pwrite_zeroes,

    .bdrv_co_preadv         = raw_co_preadv,
@@ -2927,6 +3068,7 @@ static BlockDriver bdrv_host_cdrom = {
    .bdrv_reopen_abort   = raw_reopen_abort,
    .bdrv_co_create_opts = hdev_co_create_opts,
    .create_opts         = &raw_create_opts,
    .bdrv_co_invalidate_cache = raw_co_invalidate_cache,


    .bdrv_co_preadv         = raw_co_preadv,
+0 −27
Original line number Diff line number Diff line
@@ -988,19 +988,6 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
    return job;
}

void block_job_pause_all(void)
{
    BlockJob *job = NULL;
    while ((job = block_job_next(job))) {
        AioContext *aio_context = blk_get_aio_context(job->blk);

        aio_context_acquire(aio_context);
        block_job_ref(job);
        block_job_pause(job);
        aio_context_release(aio_context);
    }
}

void block_job_early_fail(BlockJob *job)
{
    assert(job->status == BLOCK_JOB_STATUS_CREATED);
@@ -1078,20 +1065,6 @@ void coroutine_fn block_job_pause_point(BlockJob *job)
    }
}

void block_job_resume_all(void)
{
    BlockJob *job, *next;

    QLIST_FOREACH_SAFE(job, &block_jobs, job_list, next) {
        AioContext *aio_context = blk_get_aio_context(job->blk);

        aio_context_acquire(aio_context);
        block_job_resume(job);
        block_job_unref(job);
        aio_context_release(aio_context);
    }
}

/*
 * Conditionally enter a block_job pending a call to fn() while
 * under the block_job_lock critical section.
+0 −14
Original line number Diff line number Diff line
@@ -168,20 +168,6 @@ void block_job_sleep_ns(BlockJob *job, int64_t ns);
 */
void block_job_yield(BlockJob *job);

/**
 * block_job_pause_all:
 *
 * Asynchronously pause all jobs.
 */
void block_job_pause_all(void);

/**
 * block_job_resume_all:
 *
 * Resume all block jobs.  Must be paired with a preceding block_job_pause_all.
 */
void block_job_resume_all(void);

/**
 * block_job_early_fail:
 * @bs: The block device.
+6 −1
Original line number Diff line number Diff line
@@ -2530,6 +2530,10 @@
# @locking:     whether to enable file locking. If set to 'auto', only enable
#               when Open File Descriptor (OFD) locking API is available
#               (default: auto, since 2.10)
# @x-check-cache-dropped: whether to check that page cache was dropped on live
#                         migration.  May cause noticeable delays if the image
#                         file is large, do not use in production.
#                         (default: off) (since: 2.13)
#
# Since: 2.9
##
@@ -2537,7 +2541,8 @@
  'data': { 'filename': 'str',
            '*pr-manager': 'str',
            '*locking': 'OnOffAuto',
            '*aio': 'BlockdevAioOptions' } }
            '*aio': 'BlockdevAioOptions',
            '*x-check-cache-dropped': 'bool' } }

##
# @BlockdevOptionsNull:
+52 −4
Original line number Diff line number Diff line
@@ -224,9 +224,8 @@ our $NonptrType;
our $Type;
our $Declare;

our $UTF8	= qr {
	[\x09\x0A\x0D\x20-\x7E]              # ASCII
	| [\xC2-\xDF][\x80-\xBF]             # non-overlong 2-byte
our $NON_ASCII_UTF8	= qr{
	[\xC2-\xDF][\x80-\xBF]               # non-overlong 2-byte
	|  \xE0[\xA0-\xBF][\x80-\xBF]        # excluding overlongs
	| [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}  # straight 3-byte
	|  \xED[\x80-\x9F][\x80-\xBF]        # excluding surrogates
@@ -235,6 +234,11 @@ our $UTF8 = qr {
	|  \xF4[\x80-\x8F][\x80-\xBF]{2}     # plane 16
}x;

our $UTF8	= qr{
	[\x09\x0A\x0D\x20-\x7E]              # ASCII
	| $NON_ASCII_UTF8
}x;

# There are still some false positives, but this catches most
# common cases.
our $typeTypedefs = qr{(?x:
@@ -1207,6 +1211,11 @@ sub process {
	my $signoff = 0;
	my $is_patch = 0;

	my $in_header_lines = $file ? 0 : 1;
	my $in_commit_log = 0;		#Scanning lines before patch
	my $reported_maintainer_file = 0;
	my $non_utf8_charset = 0;

	our @report = ();
	our $cnt_lines = 0;
	our $cnt_error = 0;
@@ -1359,7 +1368,6 @@ sub process {
		if ($line =~ /^diff --git.*?(\S+)$/) {
			$realfile = $1;
			$realfile =~ s@^([^/]*)/@@;

		} elsif ($line =~ /^\+\+\+\s+(\S+)/) {
			$realfile = $1;
			$realfile =~ s@^([^/]*)/@@;
@@ -1398,6 +1406,8 @@ sub process {
		if ($line =~ /^\s*signed-off-by:/i) {
			# This is a signoff, if ugly, so do not double report.
			$signoff++;
			$in_commit_log = 0;

			if (!($line =~ /^\s*Signed-off-by:/)) {
				ERROR("The correct form is \"Signed-off-by\"\n" .
					$herecurr);
@@ -1408,6 +1418,22 @@ sub process {
			}
		}

# Check if MAINTAINERS is being updated.  If so, there's probably no need to
# emit the "does MAINTAINERS need updating?" message on file add/move/delete
		if ($line =~ /^\s*MAINTAINERS\s*\|/) {
			$reported_maintainer_file = 1;
		}

# Check for added, moved or deleted files
		if (!$reported_maintainer_file && !$in_commit_log &&
		    ($line =~ /^(?:new|deleted) file mode\s*\d+\s*$/ ||
		     $line =~ /^rename (?:from|to) [\w\/\.\-]+\s*$/ ||
		     ($line =~ /\{\s*([\w\/\.\-]*)\s*\=\>\s*([\w\/\.\-]*)\s*\}/ &&
		      (defined($1) || defined($2))))) {
			$reported_maintainer_file = 1;
			WARN("added, moved or deleted file(s), does MAINTAINERS need updating?\n" . $herecurr);
		}

# Check for wrappage within a valid hunk of the file
		if ($realcnt != 0 && $line !~ m{^(?:\+|-| |\\ No newline|$)}) {
			ERROR("patch seems to be corrupt (line wrapped?)\n" .
@@ -1426,6 +1452,28 @@ sub process {
			ERROR("Invalid UTF-8, patch and commit message should be encoded in UTF-8\n" . $hereptr);
		}

# Check if it's the start of a commit log
# (not a header line and we haven't seen the patch filename)
		if ($in_header_lines && $realfile =~ /^$/ &&
		    !($rawline =~ /^\s+\S/ ||
		      $rawline =~ /^(commit\b|from\b|[\w-]+:).*$/i)) {
			$in_header_lines = 0;
			$in_commit_log = 1;
		}

# Check if there is UTF-8 in a commit log when a mail header has explicitly
# declined it, i.e defined some charset where it is missing.
		if ($in_header_lines &&
		    $rawline =~ /^Content-Type:.+charset="(.+)".*$/ &&
		    $1 !~ /utf-8/i) {
			$non_utf8_charset = 1;
		}

		if ($in_commit_log && $non_utf8_charset && $realfile =~ /^$/ &&
		    $rawline =~ /$NON_ASCII_UTF8/) {
			WARN("8-bit UTF-8 used in possible commit log\n" . $herecurr);
		}

# ignore non-hunk lines and lines being removed
		next if (!$hunk_line || $line =~ /^-/);