From nobody Fri Nov 1 02:38:09 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 170.10.133.124 as permitted sender) client-ip=170.10.133.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=fail(p=none dis=none) header.from=suse.de Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by mx.zohomail.com with SMTPS id 1648314413106892.0431163887333; Sat, 26 Mar 2022 10:06:53 -0700 (PDT) Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-412-jtBZFfavON2FF7KkFmRrwQ-1; Sat, 26 Mar 2022 13:06:48 -0400 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.rdu2.redhat.com [10.11.54.7]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 0B9AE3C01BA1; Sat, 26 Mar 2022 17:06:46 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com [10.30.29.100]) by smtp.corp.redhat.com (Postfix) with ESMTP id 9BCA51402410; Sat, 26 Mar 2022 17:06:44 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (localhost [IPv6:::1]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id 3A16A19451F0; Sat, 26 Mar 2022 17:06:44 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx10.intmail.prod.int.rdu2.redhat.com [10.11.54.10]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id 3751C19451EF for ; Sat, 26 Mar 2022 17:06:43 +0000 (UTC) Received: by smtp.corp.redhat.com (Postfix) id 12729401E47; Sat, 26 Mar 2022 17:06:43 +0000 (UTC) Received: from mimecast-mx02.redhat.com (mimecast08.extmail.prod.ext.rdu2.redhat.com [10.11.55.24]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 0E87E401DBE for ; Sat, 26 Mar 2022 17:06:43 +0000 (UTC) Received: from us-smtp-1.mimecast.com (us-smtp-2.mimecast.com [207.211.31.81]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id E407D3803503 for ; Sat, 26 Mar 2022 17:06:42 +0000 (UTC) Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.220.29]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-193-epF4gM7LM9uG1cGu1ylaug-1; Sat, 26 Mar 2022 13:06:41 -0400 Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id 7271E1F745; Sat, 26 Mar 2022 17:06:39 +0000 (UTC) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id 3BCF613A83; Sat, 26 Mar 2022 17:06:39 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id xIDaDB9IP2KWJQAAMHmgww (envelope-from ); Sat, 26 Mar 2022 17:06:39 +0000 X-MC-Unique: jtBZFfavON2FF7KkFmRrwQ-1 X-Original-To: libvir-list@listman.corp.redhat.com X-MC-Unique: epF4gM7LM9uG1cGu1ylaug-1 From: Claudio Fontana To: =?UTF-8?q?Daniel=20P=20=2E=20Berrang=C3=A9?= Subject: [libvirt PATCH v2] iohelper: some refactoring Date: Sat, 26 Mar 2022 18:06:37 +0100 Message-Id: <20220326170637.12796-1-cfontana@suse.de> MIME-Version: 1.0 X-Mimecast-Impersonation-Protect: Policy=CLT - Impersonation Protection Definition; Similar Internal Domain=false; Similar Monitored External Domain=false; Custom External Domain=false; Mimecast External Domain=false; Newly Observed Domain=false; Internal User Name=false; Custom Display Name List=false; Reply-to Address Mismatch=false; Targeted Threat Dictionary=false; Mimecast Threat Dictionary=false; Custom Threat Dictionary=false X-Scanned-By: MIMEDefang 2.85 on 10.11.54.10 X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: libvir-list@redhat.com, Claudio Fontana Errors-To: libvir-list-bounces@redhat.com Sender: "libvir-list" X-Scanned-By: MIMEDefang 2.85 on 10.11.54.7 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=libvir-list-bounces@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-ZM-MESSAGEID: 1648314415345100001 Content-Type: text/plain; charset="utf-8"; x-default="true" while doing research with alternative implementations of runIO, it seemed necessary to do some refactoring, in order to separate parameter setting from the actual copy, so that alternative copy methods can be researched and hopefully eventually implemented. No functional changes are expected. Signed-off-by: Claudio Fontana --- src/util/iohelper.c | 197 +++++++++++++++++++++++++++----------------- 1 file changed, 122 insertions(+), 75 deletions(-) changes v1 -> v2: * fix missing write diff --git a/src/util/iohelper.c b/src/util/iohelper.c index 2c91bf4f93..ca569b5ae9 100644 --- a/src/util/iohelper.c +++ b/src/util/iohelper.c @@ -45,21 +45,38 @@ # define O_DIRECT 0 #endif =20 -static int -runIO(const char *path, int fd, int oflags) +struct runIOParams { + bool isBlockDev; + bool isDirect; + bool isWrite; + int fdin; + const char *fdinname; + int fdout; + const char *fdoutname; +}; + +/* runIOCopy: execute the IO copy based on the passed parameters */ +/** + * runIOCopy: + * @p: the IO parameters + * + * Execute the copy based on the passed parameters. + * + * Returns: size transfered, or < 0 on error. + * Errors: -1 =3D read/write error + * -2 =3D read error + * -3 =3D write error + * -4 =3D truncate error + */ + +static off_t +runIOCopy(const struct runIOParams p) { g_autofree void *base =3D NULL; /* Location to be freed */ char *buf =3D NULL; /* Aligned location within base */ size_t buflen =3D 1024*1024; intptr_t alignMask =3D 64*1024 - 1; - int ret =3D -1; - int fdin, fdout; - const char *fdinname, *fdoutname; - unsigned long long total =3D 0; - bool direct =3D O_DIRECT && ((oflags & O_DIRECT) !=3D 0); - off_t end =3D 0; - struct stat sb; - bool isBlockDev =3D false; + off_t total =3D 0; =20 #if WITH_POSIX_MEMALIGN if (posix_memalign(&base, alignMask + 1, buflen)) @@ -71,50 +88,6 @@ runIO(const char *path, int fd, int oflags) buf =3D (char *) (((intptr_t) base + alignMask) & ~alignMask); #endif =20 - if (fstat(fd, &sb) < 0) { - virReportSystemError(errno, - _("Unable to access file descriptor %d path %= s"), - fd, path); - goto cleanup; - } - isBlockDev =3D S_ISBLK(sb.st_mode); - - switch (oflags & O_ACCMODE) { - case O_RDONLY: - fdin =3D fd; - fdinname =3D path; - fdout =3D STDOUT_FILENO; - fdoutname =3D "stdout"; - /* To make the implementation simpler, we give up on any - * attempt to use O_DIRECT in a non-trivial manner. */ - if (!isBlockDev && direct && ((end =3D lseek(fd, 0, SEEK_CUR)) != =3D 0)) { - virReportSystemError(end < 0 ? errno : EINVAL, "%s", - _("O_DIRECT read needs entire seekable fi= le")); - goto cleanup; - } - break; - case O_WRONLY: - fdin =3D STDIN_FILENO; - fdinname =3D "stdin"; - fdout =3D fd; - fdoutname =3D path; - /* To make the implementation simpler, we give up on any - * attempt to use O_DIRECT in a non-trivial manner. */ - if (!isBlockDev && direct && (end =3D lseek(fd, 0, SEEK_END)) !=3D= 0) { - virReportSystemError(end < 0 ? errno : EINVAL, "%s", - _("O_DIRECT write needs empty seekable fi= le")); - goto cleanup; - } - break; - - case O_RDWR: - default: - virReportSystemError(EINVAL, - _("Unable to process file with flags %d"), - (oflags & O_ACCMODE)); - goto cleanup; - } - while (1) { ssize_t got; =20 @@ -124,53 +97,127 @@ runIO(const char *path, int fd, int oflags) * writes will be aligned. * In other cases using saferead reduces number of syscalls. */ - if (fdin =3D=3D fd && direct) { - if ((got =3D read(fdin, buf, buflen)) < 0 && + if (!p.isWrite && p.isDirect) { + if ((got =3D read(p.fdin, buf, buflen)) < 0 && errno =3D=3D EINTR) continue; } else { - got =3D saferead(fdin, buf, buflen); - } - - if (got < 0) { - virReportSystemError(errno, _("Unable to read %s"), fdinname); - goto cleanup; + got =3D saferead(p.fdin, buf, buflen); } + if (got < 0) + return -2; if (got =3D=3D 0) break; =20 total +=3D got; =20 /* handle last write size align in direct case */ - if (got < buflen && direct && fdout =3D=3D fd) { + if (got < buflen && p.isDirect && p.isWrite) { ssize_t aligned_got =3D (got + alignMask) & ~alignMask; =20 memset(buf + got, 0, aligned_got - got); =20 - if (safewrite(fdout, buf, aligned_got) < 0) { - virReportSystemError(errno, _("Unable to write %s"), fdout= name); - goto cleanup; + if (safewrite(p.fdout, buf, aligned_got) < 0) { + return -3; } - - if (!isBlockDev && ftruncate(fd, total) < 0) { - virReportSystemError(errno, _("Unable to truncate %s"), fd= outname); - goto cleanup; + if (!p.isBlockDev && ftruncate(p.fdout, total) < 0) { + return -4; } - break; } =20 - if (safewrite(fdout, buf, got) < 0) { - virReportSystemError(errno, _("Unable to write %s"), fdoutname= ); + if (safewrite(p.fdout, buf, got) < 0) { + return -3; + } + } + return total; +} + +static int +runIO(const char *path, int fd, int oflags) +{ + int ret =3D -1; + off_t total =3D 0; + struct stat sb; + struct runIOParams p; + + if (fstat(fd, &sb) < 0) { + virReportSystemError(errno, + _("Unable to access file descriptor %d path %= s"), + fd, path); + goto cleanup; + } + p.isBlockDev =3D S_ISBLK(sb.st_mode); + p.isDirect =3D O_DIRECT && (oflags & O_DIRECT); + + switch (oflags & O_ACCMODE) { + case O_RDONLY: + p.isWrite =3D false; + p.fdin =3D fd; + p.fdinname =3D path; + p.fdout =3D STDOUT_FILENO; + p.fdoutname =3D "stdout"; + break; + case O_WRONLY: + p.isWrite =3D true; + p.fdin =3D STDIN_FILENO; + p.fdinname =3D "stdin"; + p.fdout =3D fd; + p.fdoutname =3D path; + break; + case O_RDWR: + default: + virReportSystemError(EINVAL, + _("Unable to process file with flags %d"), + (oflags & O_ACCMODE)); + goto cleanup; + } + /* To make the implementation simpler, we give up on any + * attempt to use O_DIRECT in a non-trivial manner. */ + if (!p.isBlockDev && p.isDirect) { + off_t end; + if (p.isWrite) { + if ((end =3D lseek(fd, 0, SEEK_END)) !=3D 0) { + virReportSystemError(end < 0 ? errno : EINVAL, "%s", + _("O_DIRECT write needs empty seekabl= e file")); + goto cleanup; + } + } else if ((end =3D lseek(fd, 0, SEEK_CUR)) !=3D 0) { + virReportSystemError(end < 0 ? errno : EINVAL, "%s", + _("O_DIRECT read needs entire seekable fi= le")); goto cleanup; } } =20 + total =3D runIOCopy(p); + + if (total < 0) { + switch (total) { + case -1: + virReportSystemError(errno, _("Unable to move data from %s to = %s"), + p.fdinname, p.fdoutname); + break; + case -2: + virReportSystemError(errno, _("Unable to read %s"), p.fdinname= ); + break; + case -3: + virReportSystemError(errno, _("Unable to write %s"), p.fdoutna= me); + break; + case -4: + virReportSystemError(errno, _("Unable to truncate %s"), p.fdou= tname); + break; + default: + virReportError(VIR_ERR_INTERNAL_ERROR, _("Unknown runIOCopy er= ror %ld"), total); + break; + } + goto cleanup; + } + /* Ensure all data is written */ - if (virFileDataSync(fdout) < 0) { + if (virFileDataSync(p.fdout) < 0) { if (errno !=3D EINVAL && errno !=3D EROFS) { /* fdatasync() may fail on some special FDs, e.g. pipes */ - virReportSystemError(errno, _("unable to fsync %s"), fdoutname= ); + virReportSystemError(errno, _("unable to fsync %s"), p.fdoutna= me); goto cleanup; } } --=20 2.35.1