From patchwork Wed Jul 27 15:08:27 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 9249975 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 88ACF60757 for ; Wed, 27 Jul 2016 15:11:22 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7977B269B2 for ; Wed, 27 Jul 2016 15:11:22 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6E36C26D17; Wed, 27 Jul 2016 15:11:22 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A405E269B2 for ; Wed, 27 Jul 2016 15:11:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932211AbcG0PLD (ORCPT ); Wed, 27 Jul 2016 11:11:03 -0400 Received: from mail-pf0-f195.google.com ([209.85.192.195]:36489 "EHLO mail-pf0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754206AbcG0PJ7 (ORCPT ); Wed, 27 Jul 2016 11:09:59 -0400 Received: by mail-pf0-f195.google.com with SMTP id y134so1998570pfg.3; Wed, 27 Jul 2016 08:09:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=iUd7R2UmUvC9E/WgeVwJ+3cXLzxYz13FZOjeUlNKc00=; b=ritJbsbJ9nxh7Frkkn8aTgyXkKsJzX8Z0CsOmZyw3GEIAZ5htnIiA/NrAlBezGp1V/ qeT9LCKqnJrUfNwlcveo3g1EfaSk8HKPfX1cXlnvsS//VrkwZ96o7ACRB/QKGNNP2k5v GV+qLnGdyvPII9nMl7Ir/SRd1mOsOT8nDhx0lnUQChAm4TvrbooonVdnVn6Z4cJRyGXc ZwBWgrD73giwVwoIWUi+i8++g4ouy00FwDPGXbD1Qa4JeFPlYn0MeoIY4tVeI8uqS67w uDDJtxaQDazjoYjUmgAZmbasO45PcXvWhSbPwsoJ+RBNgVTSWIPICO86ZkpCmMI76c16 W+1g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=iUd7R2UmUvC9E/WgeVwJ+3cXLzxYz13FZOjeUlNKc00=; b=F2Ep9S7iJfx+uL1DVgjftW0TF36NGytby+USzsvGTjSWgtU+77f7QkjKoQgJWeFbDy 5Yk6iMaYdA/QdYR0vN0ZvMpo9DMM+SXuXCId4gA6exTlUQqFrj/ikblDFRnUi1Bm6qMm 3WAteVYR9w0aSIzrZfXjWq2p+AG4t96r5U1u2D0PnlY1xm0LorT9BQVFbpZl5GtXa27X rsKFkHDUt6uH/59hIELbXTy2ojhSgFTICpAen/VdgNJr0CG+gNpLttuISfJh73hEpWM3 dfcrg5NCwRn0UfYRvlUTYlmEruvmNqB/TO35UA6uk0AeNpBBXgns70x5kbuMzZ+wU/IC MqyA== X-Gm-Message-State: AEkoouurlsdC5q+9G33z1MF3I15nK7DXr8IOL3VOD/gDFaDlqMy7Sfe3yVgRPKHzUkJwIw== X-Received: by 10.98.14.208 with SMTP id 77mr50226263pfo.23.1469632188845; Wed, 27 Jul 2016 08:09:48 -0700 (PDT) Received: from danjae.aot.lge.com ([210.100.147.61]) by smtp.gmail.com with ESMTPSA id 15sm10058488pfz.36.2016.07.27.08.09.45 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 27 Jul 2016 08:09:48 -0700 (PDT) From: Namhyung Kim To: kvm@vger.kernel.org, qemu-devel@nongnu.org, virtualization@lists.linux-foundation.org Cc: LKML , Anton Vorontsov , Colin Cross , Kees Cook , Tony Luck , Matt Fleming , linux-efi@vger.kernel.org Subject: [PATCH 3/7] pstore: Manage buffer position for async write Date: Thu, 28 Jul 2016 00:08:27 +0900 Message-Id: <1469632111-23260-4-git-send-email-namhyung@kernel.org> X-Mailer: git-send-email 2.8.0 In-Reply-To: <1469632111-23260-1-git-send-email-namhyung@kernel.org> References: <1469632111-23260-1-git-send-email-namhyung@kernel.org> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Some pstore backend only supports async mode, so it's possible to do some IO at the same time. In this case we need to manage the single psinfo->buf not to broken by concurrent IO. For example PSTORE_TYPE_CONSOLE IO is serialized by psinfo->buf_lock but later IO can be issued before finishing previous request. In this case it overwrites psinfo->buf so the previous result might be broken. This patch adds psinfo->bufpos field to keep track of current position in order to use psinfo->buf as a ring buffer. However it's just a simple, best-effort way of doing that, and provides no 100% guarantee. It's only effective for small concurrent IO like PSTORE_TYPE_CONSOLE IMHO. The new PSTORE_FLAGS_ASYNC flag enables management of buffer position. The pstore_prepare_buf() is called before accessing the psinfo->buf and the pstore_update_buf() is called after accessing the buf. The pstore_get_buf() is provided for psinfo->write callback to determine the current position of available buffer. Cc: Anton Vorontsov Cc: Colin Cross Cc: Kees Cook Cc: Tony Luck Cc: Matt Fleming Cc: linux-efi@vger.kernel.org Signed-off-by: Namhyung Kim --- drivers/firmware/efi/efi-pstore.c | 2 +- fs/pstore/platform.c | 48 +++++++++++++++++++++++++++++++-------- include/linux/pstore.h | 4 ++++ 3 files changed, 44 insertions(+), 10 deletions(-) diff --git a/drivers/firmware/efi/efi-pstore.c b/drivers/firmware/efi/efi-pstore.c index 4daa5acd9117..ae0ffe259e07 100644 --- a/drivers/firmware/efi/efi-pstore.c +++ b/drivers/firmware/efi/efi-pstore.c @@ -259,7 +259,7 @@ static int efi_pstore_write(enum pstore_type_id type, efivar_entry_set_safe(efi_name, vendor, PSTORE_EFI_ATTRIBUTES, !pstore_cannot_block_path(reason), - size, psi->buf); + size, pstore_get_buf(psi)); if (reason == KMSG_DUMP_OOPS) efivar_run_worker(); diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index 76dd604a0f2c..26e2808cf554 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -150,6 +150,27 @@ bool pstore_cannot_block_path(enum kmsg_dump_reason reason) } EXPORT_SYMBOL_GPL(pstore_cannot_block_path); +static void *pstore_prepare_buf(struct pstore_info *psi, size_t len) +{ + if (psi->bufpos + len > psi->bufsize || + (psi->flags & PSTORE_FLAGS_ASYNC) == 0) + psi->bufpos = 0; + + return psi->buf + psi->bufpos; +} + +static void pstore_update_buf(struct pstore_info *psi, size_t len) +{ + if (psi->flags & PSTORE_FLAGS_ASYNC) + psi->bufpos += len; +} + +void *pstore_get_buf(struct pstore_info *psi) +{ + return psi->buf + psi->bufpos; +} +EXPORT_SYMBOL_GPL(pstore_get_buf); + #ifdef CONFIG_PSTORE_ZLIB_COMPRESS /* Derived from logfs_compress() */ static int compress_zlib(const void *in, void *out, size_t inlen, size_t outlen) @@ -455,18 +476,21 @@ static size_t copy_kmsg_to_buffer(int hsize, size_t len) { size_t total_len; size_t diff; + void *dst; total_len = hsize + len; + dst = pstore_prepare_buf(psinfo, total_len); if (total_len > psinfo->bufsize) { diff = total_len - psinfo->bufsize + hsize; - memcpy(psinfo->buf, big_oops_buf, hsize); - memcpy(psinfo->buf + hsize, big_oops_buf + diff, + memcpy(dst, big_oops_buf, hsize); + memcpy(dst + hsize, big_oops_buf + diff, psinfo->bufsize - hsize); total_len = psinfo->bufsize; } else - memcpy(psinfo->buf, big_oops_buf, total_len); + memcpy(dst, big_oops_buf, total_len); + pstore_update_buf(psinfo, total_len); return total_len; } @@ -500,7 +524,7 @@ static void pstore_dump(struct kmsg_dumper *dumper, } oopscount++; while (total < kmsg_bytes) { - char *dst; + char *dst, *buf; unsigned long size; int hsize; int zipped_len = -1; @@ -514,6 +538,7 @@ static void pstore_dump(struct kmsg_dumper *dumper, } else { dst = psinfo->buf; size = psinfo->bufsize; + psinfo->bufpos = 0; } hsize = sprintf(dst, "%s#%d Part%u\n", why, oopscount, part); @@ -524,8 +549,9 @@ static void pstore_dump(struct kmsg_dumper *dumper, break; if (big_oops_buf && is_locked) { - zipped_len = pstore_compress(dst, psinfo->buf, - hsize + len, psinfo->bufsize); + buf = pstore_prepare_buf(psinfo, hsize + len); + zipped_len = pstore_compress(dst, buf, hsize + len, + psinfo->bufsize - psinfo->bufpos); if (zipped_len > 0) { compressed = true; @@ -543,6 +569,7 @@ static void pstore_dump(struct kmsg_dumper *dumper, pstore_new_entry = 1; total += total_len; + pstore_update_buf(psinfo, total_len); part++; } if (is_locked) @@ -573,6 +600,7 @@ static void pstore_console_write(struct console *con, const char *s, unsigned c) while (s < e) { unsigned long flags; + void *dst; u64 id; if (c > psinfo->bufsize) @@ -584,8 +612,10 @@ static void pstore_console_write(struct console *con, const char *s, unsigned c) } else { spin_lock_irqsave(&psinfo->buf_lock, flags); } - memcpy(psinfo->buf, s, c); + dst = pstore_prepare_buf(psinfo, c); + memcpy(dst, s, c); psinfo->write(PSTORE_TYPE_CONSOLE, 0, &id, 0, 0, 0, c, psinfo); + pstore_update_buf(psinfo, c); spin_unlock_irqrestore(&psinfo->buf_lock, flags); s += c; c = e - s; @@ -619,8 +649,8 @@ static int pstore_write_compat(enum pstore_type_id type, bool compressed, size_t size, struct pstore_info *psi) { - return psi->write_buf(type, reason, id, part, psinfo->buf, compressed, - size, psi); + return psi->write_buf(type, reason, id, part, pstore_get_buf(psinfo), + compressed, size, psi); } /* diff --git a/include/linux/pstore.h b/include/linux/pstore.h index 9790904de6d2..14f524177b1f 100644 --- a/include/linux/pstore.h +++ b/include/linux/pstore.h @@ -52,6 +52,7 @@ struct pstore_info { spinlock_t buf_lock; /* serialize access to 'buf' */ char *buf; size_t bufsize; + size_t bufpos; struct mutex read_mutex; /* serialize open/read/close */ int flags; int (*open)(struct pstore_info *psi); @@ -79,8 +80,11 @@ struct pstore_info { #define PSTORE_FLAGS_FTRACE (1 << 2) #define PSTORE_FLAGS_PMSG (1 << 3) +#define PSTORE_FLAGS_ASYNC (1 << 30) + extern int pstore_register(struct pstore_info *); extern void pstore_unregister(struct pstore_info *); extern bool pstore_cannot_block_path(enum kmsg_dump_reason reason); +extern void *pstore_get_buf(struct pstore_info *); #endif /*_LINUX_PSTORE_H*/