From: Nir Soffer <nirsof@gmail.com>
To: qemu-devel@nongnu.org
Cc: Kevin Wolf <kwolf@redhat.com>,
qemu-block@nongnu.org, Markus Armbruster <armbru@redhat.com>,
Max Reitz <mreitz@redhat.com>, Nir Soffer <nsoffer@redhat.com>
Subject: [PATCH 1/2] block: file-posix: Extract preallocate helpers
Date: Mon, 31 Aug 2020 17:01:26 +0300 [thread overview]
Message-ID: <20200831140127.657134-2-nsoffer@redhat.com> (raw)
In-Reply-To: <20200831140127.657134-1-nsoffer@redhat.com>
handle_aiocb_truncate() was too big and complex, implementing 3
different preallocation modes. In a future patch I want to introduce a
fallback from "falloc" to "full"; it will be too messy and error prone
with the current code.
Extract a helper for each of the preallocation modes (falloc, full, off)
and leave only the common preparation and cleanup code in
handle_aiocb_truncate().
Signed-off-by: Nir Soffer <nsoffer@redhat.com>
---
block/file-posix.c | 206 ++++++++++++++++++++++++++-------------------
1 file changed, 120 insertions(+), 86 deletions(-)
diff --git a/block/file-posix.c b/block/file-posix.c
index 9a00d4190a..341ffb1cb4 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -1832,12 +1832,128 @@ static int allocate_first_block(int fd, size_t max_size)
return ret;
}
+static int preallocate_falloc(int fd, int64_t current_length, int64_t offset,
+ Error **errp)
+{
+#ifdef CONFIG_POSIX_FALLOCATE
+ int result;
+
+ if (offset == current_length)
+ return 0;
+
+ /*
+ * Truncating before posix_fallocate() makes it about twice slower on
+ * file systems that do not support fallocate(), trying to check if a
+ * block is allocated before allocating it, so don't do that here.
+ */
+
+ result = -posix_fallocate(fd, current_length,
+ offset - current_length);
+ if (result != 0) {
+ /* posix_fallocate() doesn't set errno. */
+ error_setg_errno(errp, -result,
+ "Could not preallocate new data");
+ return result;
+ }
+
+ if (current_length == 0) {
+ /*
+ * posix_fallocate() uses fallocate() if the filesystem supports
+ * it, or fallback to manually writing zeroes. If fallocate()
+ * was used, unaligned reads from the fallocated area in
+ * raw_probe_alignment() will succeed, hence we need to allocate
+ * the first block.
+ *
+ * Optimize future alignment probing; ignore failures.
+ */
+ allocate_first_block(fd, offset);
+ }
+
+ return 0;
+#else
+ return -ENOTSUP;
+#endif
+}
+
+static int preallocate_full(int fd, int64_t current_length, int64_t offset,
+ Error **errp)
+{
+ int64_t num = 0, left = offset - current_length;
+ off_t seek_result;
+ int result;
+ char *buf = NULL;
+
+ /*
+ * Knowing the final size from the beginning could allow the file
+ * system driver to do less allocations and possibly avoid
+ * fragmentation of the file.
+ */
+ if (ftruncate(fd, offset) != 0) {
+ result = -errno;
+ error_setg_errno(errp, -result, "Could not resize file");
+ goto out;
+ }
+
+ buf = g_malloc0(65536);
+
+ seek_result = lseek(fd, current_length, SEEK_SET);
+ if (seek_result < 0) {
+ result = -errno;
+ error_setg_errno(errp, -result,
+ "Failed to seek to the old end of file");
+ goto out;
+ }
+
+ while (left > 0) {
+ num = MIN(left, 65536);
+ result = write(fd, buf, num);
+ if (result < 0) {
+ if (errno == EINTR) {
+ continue;
+ }
+ result = -errno;
+ error_setg_errno(errp, -result,
+ "Could not write zeros for preallocation");
+ goto out;
+ }
+ left -= result;
+ }
+
+ result = fsync(fd);
+ if (result < 0) {
+ result = -errno;
+ error_setg_errno(errp, -result, "Could not flush file to disk");
+ goto out;
+ }
+
+out:
+ g_free(buf);
+
+ return result;
+}
+
+static int preallocate_off(int fd, int64_t current_length, int64_t offset,
+ Error **errp)
+{
+ if (ftruncate(fd, offset) != 0) {
+ int result = -errno;
+ error_setg_errno(errp, -result, "Could not resize file");
+ return result;
+ }
+
+ if (current_length == 0 && offset > current_length) {
+ /* Optimize future alignment probing; ignore failures. */
+ allocate_first_block(fd, offset);
+ }
+
+ return 0;
+}
+
static int handle_aiocb_truncate(void *opaque)
{
RawPosixAIOData *aiocb = opaque;
int result = 0;
int64_t current_length = 0;
- char *buf = NULL;
struct stat st;
int fd = aiocb->aio_fildes;
int64_t offset = aiocb->aio_offset;
@@ -1859,95 +1975,14 @@ static int handle_aiocb_truncate(void *opaque)
switch (prealloc) {
#ifdef CONFIG_POSIX_FALLOCATE
case PREALLOC_MODE_FALLOC:
- /*
- * Truncating before posix_fallocate() makes it about twice slower on
- * file systems that do not support fallocate(), trying to check if a
- * block is allocated before allocating it, so don't do that here.
- */
- if (offset != current_length) {
- result = -posix_fallocate(fd, current_length,
- offset - current_length);
- if (result != 0) {
- /* posix_fallocate() doesn't set errno. */
- error_setg_errno(errp, -result,
- "Could not preallocate new data");
- } else if (current_length == 0) {
- /*
- * posix_fallocate() uses fallocate() if the filesystem
- * supports it, or fallback to manually writing zeroes. If
- * fallocate() was used, unaligned reads from the fallocated
- * area in raw_probe_alignment() will succeed, hence we need to
- * allocate the first block.
- *
- * Optimize future alignment probing; ignore failures.
- */
- allocate_first_block(fd, offset);
- }
- } else {
- result = 0;
- }
+ result = preallocate_falloc(fd, current_length, offset, errp);
goto out;
#endif
case PREALLOC_MODE_FULL:
- {
- int64_t num = 0, left = offset - current_length;
- off_t seek_result;
-
- /*
- * Knowing the final size from the beginning could allow the file
- * system driver to do less allocations and possibly avoid
- * fragmentation of the file.
- */
- if (ftruncate(fd, offset) != 0) {
- result = -errno;
- error_setg_errno(errp, -result, "Could not resize file");
- goto out;
- }
-
- buf = g_malloc0(65536);
-
- seek_result = lseek(fd, current_length, SEEK_SET);
- if (seek_result < 0) {
- result = -errno;
- error_setg_errno(errp, -result,
- "Failed to seek to the old end of file");
- goto out;
- }
-
- while (left > 0) {
- num = MIN(left, 65536);
- result = write(fd, buf, num);
- if (result < 0) {
- if (errno == EINTR) {
- continue;
- }
- result = -errno;
- error_setg_errno(errp, -result,
- "Could not write zeros for preallocation");
- goto out;
- }
- left -= result;
- }
- if (result >= 0) {
- result = fsync(fd);
- if (result < 0) {
- result = -errno;
- error_setg_errno(errp, -result,
- "Could not flush file to disk");
- goto out;
- }
- }
+ result = preallocate_full(fd, current_length, offset, errp);
goto out;
- }
case PREALLOC_MODE_OFF:
- if (ftruncate(fd, offset) != 0) {
- result = -errno;
- error_setg_errno(errp, -result, "Could not resize file");
- } else if (current_length == 0 && offset > current_length) {
- /* Optimize future alignment probing; ignore failures. */
- allocate_first_block(fd, offset);
- }
- return result;
+ return preallocate_off(fd, current_length, offset, errp);
default:
result = -ENOTSUP;
error_setg(errp, "Unsupported preallocation mode: %s",
@@ -1963,7 +1998,6 @@ out:
}
}
- g_free(buf);
return result;
}
--
2.26.2
next prev parent reply other threads:[~2020-08-31 14:02 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-08-31 14:01 [PATCH 0/2] Replace posix_fallocate() with falloate() Nir Soffer
2020-08-31 14:01 ` Nir Soffer [this message]
2020-09-01 10:24 ` [PATCH 1/2] block: file-posix: Extract preallocate helpers Alberto Garcia
2020-09-01 10:26 ` Alberto Garcia
2020-09-01 10:47 ` Nir Soffer
2020-08-31 14:01 ` [PATCH 2/2] block: file-posix: Replace posix_fallocate with fallocate Nir Soffer
2020-09-01 15:51 ` Alberto Garcia
2020-09-14 17:32 ` Daniel P. Berrangé
2020-09-15 8:55 ` Nir Soffer
2020-08-31 15:55 ` [PATCH 0/2] Replace posix_fallocate() with falloate() no-reply
2020-09-14 17:19 ` Nir Soffer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200831140127.657134-2-nsoffer@redhat.com \
--to=nirsof@gmail.com \
--cc=armbru@redhat.com \
--cc=kwolf@redhat.com \
--cc=mreitz@redhat.com \
--cc=nsoffer@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).