From patchwork Sat Apr 16 15:05:55 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sasha Levin X-Patchwork-Id: 712561 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p3GF6JbV029459 for ; Sat, 16 Apr 2011 15:06:19 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755861Ab1DPPGO (ORCPT ); Sat, 16 Apr 2011 11:06:14 -0400 Received: from mail-wy0-f174.google.com ([74.125.82.174]:49526 "EHLO mail-wy0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754581Ab1DPPGO (ORCPT ); Sat, 16 Apr 2011 11:06:14 -0400 Received: by wya21 with SMTP id 21so2916440wya.19 for ; Sat, 16 Apr 2011 08:06:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:from:to:cc:subject:date:message-id:x-mailer; bh=PkrDIo7g3pQ+g+wT703pr1DiPRFylmYXawvxUfSJxQc=; b=H5AkPWjDS58iFTR7YUZdiDiOkrCfOvE05U8glWKAZuwyDCkv/iPxvspbe8q9dfsEHc +fXocnrWmLmgvOmyB6fIAZ6x9HyG6kcppQrdVsbSrlGEXO8sw2IAmC5JPy1pFAPMNC5y PkWNZLGfyOO9Rlgr0HojqjP1bizMCRub3aQHA= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer; b=frLeoWdgnCmxQNVx/G5/S61q5aZkBjcpll9yS9v6Zozzp6h16ND1CKwdtnvw8qSl2c 0UpEs+BtZLMcyGDLQgLTt4ucbmyzREBqhLtFfFg+Hl3aHrSaAl2TVQ7Dr4mzksIRWxmH zReaaQXO0rhwbi79XiNLIxrDIb2tnQcKNG8Ko= Received: by 10.216.152.193 with SMTP id d43mr107425wek.53.1302966372966; Sat, 16 Apr 2011 08:06:12 -0700 (PDT) Received: from localhost.localdomain (46-117-236-160.bb.netvision.net.il [46.117.236.160]) by mx.google.com with ESMTPS id r80sm1770866wei.39.2011.04.16.08.06.11 (version=TLSv1/SSLv3 cipher=OTHER); Sat, 16 Apr 2011 08:06:12 -0700 (PDT) From: Sasha Levin To: penberg@kernel.org Cc: mingo@elte.hu, asias.hejun@gmail.com, gorcunov@gmail.com, kvm@vger.kernel.org, Sasha Levin Subject: [PATCH 1/2 V2] kvm tools: Add scatter-gather variants of IO functions Date: Sat, 16 Apr 2011 18:05:55 +0300 Message-Id: <1302966356-13145-1-git-send-email-levinsasha928@gmail.com> X-Mailer: git-send-email 1.7.5.rc1 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Sat, 16 Apr 2011 15:06:20 +0000 (UTC) Added scatter-gather variants of [x,xp][read,write]() and [p]read_in_full(). Signed-off-by: Sasha Levin --- tools/kvm/include/kvm/read-write.h | 13 +++ tools/kvm/read-write.c | 172 ++++++++++++++++++++++++++++++++++++ 2 files changed, 185 insertions(+), 0 deletions(-) diff --git a/tools/kvm/include/kvm/read-write.h b/tools/kvm/include/kvm/read-write.h index 069326b..3351103 100644 --- a/tools/kvm/include/kvm/read-write.h +++ b/tools/kvm/include/kvm/read-write.h @@ -2,6 +2,7 @@ #define KVM_READ_WRITE_H #include +#include #include ssize_t xread(int fd, void *buf, size_t count); @@ -16,4 +17,16 @@ ssize_t xpwrite(int fd, const void *buf, size_t count, off_t offset); ssize_t pread_in_full(int fd, void *buf, size_t count, off_t offset); ssize_t pwrite_in_full(int fd, const void *buf, size_t count, off_t offset); +ssize_t xreadv(int fd, const struct iovec *iov, int iovcnt); +ssize_t xwritev(int fd, const struct iovec *iov, int iovcnt); + +ssize_t readv_in_full(int fd, const struct iovec *iov, int iovcnt); +ssize_t writev_in_full(int fd, const struct iovec *iov, int iovcnt); + +ssize_t xpreadv(int fd, const struct iovec *iov, int iovcnt, off_t offset); +ssize_t xpwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset); + +ssize_t preadv_in_full(int fd, const struct iovec *iov, int iovcnt, off_t offset); +ssize_t pwritev_in_full(int fd, const struct iovec *iov, int iovcnt, off_t offset); + #endif /* KVM_READ_WRITE_H */ diff --git a/tools/kvm/read-write.c b/tools/kvm/read-write.c index 398918b..449e8a2 100644 --- a/tools/kvm/read-write.c +++ b/tools/kvm/read-write.c @@ -152,3 +152,175 @@ ssize_t pwrite_in_full(int fd, const void *buf, size_t count, off_t offset) return total; } + +/* Same as readv(2) except that this function never returns EAGAIN or EINTR. */ +ssize_t xreadv(int fd, const struct iovec *iov, int iovcnt) +{ + ssize_t nr; + +restart: + nr = readv(fd, iov, iovcnt); + if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR))) + goto restart; + + return nr; +} + +/* Same as writev(2) except that this function never returns EAGAIN or EINTR. */ +ssize_t xwritev(int fd, const struct iovec *iov, int iovcnt) +{ + ssize_t nr; + +restart: + nr = write(fd, iov, iovcnt); + if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR))) + goto restart; + + return nr; +} + +static inline ssize_t get_iov_size(const struct iovec *iov, int iovcnt) +{ + size_t size = 0; + while (iovcnt--) + size += (iov++)->iov_len; + + return size; +} + +ssize_t readv_in_full(int fd, const struct iovec *iov, int iovcnt) +{ + ssize_t total = 0; + ssize_t count = get_iov_size(iov, iovcnt); + + while (count > 0) { + ssize_t nr; + + nr = xreadv(fd, iov, iovcnt); + if (nr <= 0) { + if (total > 0) + return total; + + return -1; + } + + while ((size_t)nr >= iov->iov_len) { + nr -= iov->iov_len; + total += iov->iov_len; + count -= iov->iov_len; + iovcnt--; + iov++; + } + } + + return total; +} + +ssize_t writev_in_full(int fd, const struct iovec *iov, int iovcnt) +{ + ssize_t total = 0; + size_t count = get_iov_size(iov, iovcnt); + + while (count > 0) { + ssize_t nr; + + nr = xwritev(fd, iov, iovcnt); + if (nr < 0) + return -1; + if (nr == 0) { + errno = ENOSPC; + return -1; + } + + while ((size_t)nr >= iov->iov_len) { + nr -= iov->iov_len; + total += iov->iov_len; + count -= iov->iov_len; + iovcnt--; + iov++; + } + } + + return total; +} + +/* Same as preadv(2) except that this function never returns EAGAIN or EINTR. */ +ssize_t xpreadv(int fd, const struct iovec *iov, int iovcnt, off_t offset) +{ + ssize_t nr; + +restart: + nr = preadv(fd, iov, iovcnt, offset); + if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR))) + goto restart; + + return nr; +} + +/* Same as pwritev(2) except that this function never returns EAGAIN or EINTR. */ +ssize_t xpwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset) +{ + ssize_t nr; + +restart: + nr = pwritev(fd, iov, iovcnt, offset); + if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR))) + goto restart; + + return nr; +} + +ssize_t preadv_in_full(int fd, const struct iovec *iov, int iovcnt, off_t offset) +{ + ssize_t total = 0; + size_t count = get_iov_size(iov, iovcnt); + + while (count > 0) { + ssize_t nr; + + nr = xpreadv(fd, iov, iovcnt, offset); + if (nr <= 0) { + if (total > 0) + return total; + + return -1; + } + + while ((size_t)nr >= iov->iov_len) { + nr -= iov->iov_len; + total += iov->iov_len; + count -= iov->iov_len; + iovcnt--; + iov++; + } + } + + return total; +} + +ssize_t pwritev_in_full(int fd, const struct iovec *iov, int iovcnt, off_t offset) +{ + ssize_t total = 0; + size_t count = get_iov_size(iov, iovcnt); + + while (count > 0) { + ssize_t nr; + + nr = xpwritev(fd, iov, iovcnt, offset); + if (nr < 0) + return -1; + if (nr == 0) { + errno = ENOSPC; + return -1; + } + while ((size_t)nr >= iov->iov_len) { + nr -= iov->iov_len; + total += iov->iov_len; + count -= iov->iov_len; + iovcnt--; + iov++; + } + } + + return total; +}