From nobody Mon May 13 20:57:02 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 164831088277999.58303013215959; Sat, 26 Mar 2022 09:08:02 -0700 (PDT) Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-590--EjH5J4lPFWxiwB79Fl_6g-1; Sat, 26 Mar 2022 12:07:32 -0400 Received: from smtp.corp.redhat.com (int-mx09.intmail.prod.int.rdu2.redhat.com [10.11.54.9]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id CCA558002BF; Sat, 26 Mar 2022 16:07:30 +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 4A5FF63BB4B; Sat, 26 Mar 2022 16:07:30 +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 78BBD19451F0; Sat, 26 Mar 2022 16:07:29 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id 3503319451EF for ; Sat, 26 Mar 2022 16:07:28 +0000 (UTC) Received: by smtp.corp.redhat.com (Postfix) id 239702166B2D; Sat, 26 Mar 2022 16:07:28 +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 1EFE32166B25 for ; Sat, 26 Mar 2022 16:07:24 +0000 (UTC) Received: from us-smtp-1.mimecast.com (us-smtp-delivery-1.mimecast.com [205.139.110.120]) (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 9036738041D8 for ; Sat, 26 Mar 2022 16:07:24 +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-572-L8wHNKBDN3mZUlZZHMxR1Q-1; Sat, 26 Mar 2022 12:07:22 -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 866471F745; Sat, 26 Mar 2022 16:07:20 +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 5730E139F9; Sat, 26 Mar 2022 16:07:20 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id RIJGEzg6P2IzGgAAMHmgww (envelope-from ); Sat, 26 Mar 2022 16:07:20 +0000 X-MC-Unique: -EjH5J4lPFWxiwB79Fl_6g-1 X-Original-To: libvir-list@listman.corp.redhat.com X-MC-Unique: L8wHNKBDN3mZUlZZHMxR1Q-1 From: Claudio Fontana To: =?UTF-8?q?Daniel=20P=20=2E=20Berrang=C3=A9?= Subject: [libvirt PATCH] iohelper: some refactoring Date: Sat, 26 Mar 2022 17:07:12 +0100 Message-Id: <20220326160712.11779-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.78 on 10.11.54.6 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.9 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: 1648310883773100001 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 | 193 +++++++++++++++++++++++++++----------------- 1 file changed, 118 insertions(+), 75 deletions(-) diff --git a/src/util/iohelper.c b/src/util/iohelper.c index 2c91bf4f93..c04c97af27 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 ssize_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; + ssize_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,123 @@ 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; } + } + return total; +} =20 - if (safewrite(fdout, buf, got) < 0) { - virReportSystemError(errno, _("Unable to write %s"), fdoutname= ); +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