From patchwork Fri Jun 16 19:34:17 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Layton X-Patchwork-Id: 9793641 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 73D6B6038F for ; Fri, 16 Jun 2017 19:38:24 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6419B2865D for ; Fri, 16 Jun 2017 19:38:24 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5700728652; Fri, 16 Jun 2017 19:38:24 +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.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI 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 CD6DE285D1 for ; Fri, 16 Jun 2017 19:38:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752528AbdFPTfv (ORCPT ); Fri, 16 Jun 2017 15:35:51 -0400 Received: from mx1.redhat.com ([209.132.183.28]:25320 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752479AbdFPTfs (ORCPT ); Fri, 16 Jun 2017 15:35:48 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id BDAD161E48; Fri, 16 Jun 2017 19:35:42 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com BDAD161E48 Authentication-Results: ext-mx10.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx10.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=jlayton@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com BDAD161E48 Received: from tleilax.poochiereds.net (ovpn-120-225.rdu2.redhat.com [10.10.120.225]) by smtp.corp.redhat.com (Postfix) with ESMTP id C917F8D57D; Fri, 16 Jun 2017 19:35:40 +0000 (UTC) From: Jeff Layton To: Andrew Morton , Al Viro , Jan Kara , tytso@mit.edu, axboe@kernel.dk, mawilcox@microsoft.com, ross.zwisler@linux.intel.com, corbet@lwn.net, Chris Mason , Josef Bacik , David Sterba , "Darrick J . Wong" Cc: Carlos Maiolino , Eryu Guan , David Howells , Christoph Hellwig , linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, linux-ext4@vger.kernel.org, linux-xfs@vger.kernel.org, linux-btrfs@vger.kernel.org, linux-block@vger.kernel.org Subject: [PATCH v7 12/22] mm: tracepoints for writeback error events Date: Fri, 16 Jun 2017 15:34:17 -0400 Message-Id: <20170616193427.13955-13-jlayton@redhat.com> In-Reply-To: <20170616193427.13955-1-jlayton@redhat.com> References: <20170616193427.13955-1-jlayton@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Fri, 16 Jun 2017 19:35:43 +0000 (UTC) Sender: linux-xfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP To enable that, make __errseq_set return the value that it was set to when we exit the loop. Take heed that that value is not suitable as a later "since" value, as it will not have been marked seen. Signed-off-by: Jeff Layton --- include/linux/errseq.h | 2 +- include/linux/fs.h | 5 +++- include/trace/events/filemap.h | 55 ++++++++++++++++++++++++++++++++++++++++++ lib/errseq.c | 20 ++++++++++----- mm/filemap.c | 13 +++++++++- 5 files changed, 86 insertions(+), 9 deletions(-) diff --git a/include/linux/errseq.h b/include/linux/errseq.h index 0d2555f310cd..9e0d444ac88d 100644 --- a/include/linux/errseq.h +++ b/include/linux/errseq.h @@ -5,7 +5,7 @@ typedef u32 errseq_t; -void __errseq_set(errseq_t *eseq, int err); +errseq_t __errseq_set(errseq_t *eseq, int err); static inline void errseq_set(errseq_t *eseq, int err) { /* Optimize for the common case of no error */ diff --git a/include/linux/fs.h b/include/linux/fs.h index 09d511771b25..8980e5ce2063 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2525,6 +2525,7 @@ extern int filemap_fdatawrite_range(struct address_space *mapping, extern int filemap_check_errors(struct address_space *mapping); extern int __must_check filemap_report_wb_err(struct file *file); +extern void __filemap_set_wb_err(struct address_space *mapping, int err); /** * filemap_set_wb_err - set a writeback error on an address_space @@ -2544,7 +2545,9 @@ extern int __must_check filemap_report_wb_err(struct file *file); */ static inline void filemap_set_wb_err(struct address_space *mapping, int err) { - errseq_set(&mapping->wb_err, err); + /* Fastpath for common case of no error */ + if (unlikely(err)) + __filemap_set_wb_err(mapping, err); } /** diff --git a/include/trace/events/filemap.h b/include/trace/events/filemap.h index 42febb6bc1d5..2af66920f267 100644 --- a/include/trace/events/filemap.h +++ b/include/trace/events/filemap.h @@ -10,6 +10,7 @@ #include #include #include +#include DECLARE_EVENT_CLASS(mm_filemap_op_page_cache, @@ -52,6 +53,60 @@ DEFINE_EVENT(mm_filemap_op_page_cache, mm_filemap_add_to_page_cache, TP_ARGS(page) ); +TRACE_EVENT(filemap_set_wb_err, + TP_PROTO(struct address_space *mapping, errseq_t eseq), + + TP_ARGS(mapping, eseq), + + TP_STRUCT__entry( + __field(unsigned long, i_ino) + __field(dev_t, s_dev) + __field(errseq_t, errseq) + ), + + TP_fast_assign( + __entry->i_ino = mapping->host->i_ino; + __entry->errseq = eseq; + if (mapping->host->i_sb) + __entry->s_dev = mapping->host->i_sb->s_dev; + else + __entry->s_dev = mapping->host->i_rdev; + ), + + TP_printk("dev=%d:%d ino=0x%lx errseq=0x%x", + MAJOR(__entry->s_dev), MINOR(__entry->s_dev), + __entry->i_ino, __entry->errseq) +); + +TRACE_EVENT(filemap_report_wb_err, + TP_PROTO(struct file *file, errseq_t old), + + TP_ARGS(file, old), + + TP_STRUCT__entry( + __field(struct file *, file); + __field(unsigned long, i_ino) + __field(dev_t, s_dev) + __field(errseq_t, old) + __field(errseq_t, new) + ), + + TP_fast_assign( + __entry->file = file; + __entry->i_ino = file->f_mapping->host->i_ino; + if (file->f_mapping->host->i_sb) + __entry->s_dev = file->f_mapping->host->i_sb->s_dev; + else + __entry->s_dev = file->f_mapping->host->i_rdev; + __entry->old = old; + __entry->new = file->f_wb_err; + ), + + TP_printk("file=%p dev=%d:%d ino=0x%lx old=0x%x new=0x%x", + __entry->file, MAJOR(__entry->s_dev), + MINOR(__entry->s_dev), __entry->i_ino, __entry->old, + __entry->new) +); #endif /* _TRACE_FILEMAP_H */ /* This part must be outside protection */ diff --git a/lib/errseq.c b/lib/errseq.c index d129c0611c1f..009972d3000c 100644 --- a/lib/errseq.c +++ b/lib/errseq.c @@ -52,10 +52,14 @@ * * Most callers will want to use the errseq_set inline wrapper to efficiently * handle the common case where err is 0. + * + * We do return an errseq_t here, primarily for debugging purposes. The return + * value should not be used as a previously sampled value in later calls as it + * will not have the SEEN flag set. */ -void __errseq_set(errseq_t *eseq, int err) +errseq_t __errseq_set(errseq_t *eseq, int err) { - errseq_t old; + errseq_t cur, old; /* MAX_ERRNO must be able to serve as a mask */ BUILD_BUG_ON_NOT_POWER_OF_2(MAX_ERRNO + 1); @@ -66,13 +70,14 @@ void __errseq_set(errseq_t *eseq, int err) * also don't accept zero here as that would effectively clear a * previous error. */ + old = READ_ONCE(*eseq); + if (WARN(unlikely(err == 0 || (unsigned int)-err > MAX_ERRNO), "err = %d\n", err)) - return; + return old; - old = READ_ONCE(*eseq); for (;;) { - errseq_t new, cur; + errseq_t new; /* Clear out error bits and set new error */ new = (old & ~(MAX_ERRNO|ERRSEQ_SEEN)) | -err; @@ -82,8 +87,10 @@ void __errseq_set(errseq_t *eseq, int err) new += ERRSEQ_CTR_INC; /* If there would be no change, then call it done */ - if (new == old) + if (new == old) { + cur = new; break; + } /* Try to swap the new value into place */ cur = cmpxchg(eseq, old, new); @@ -98,6 +105,7 @@ void __errseq_set(errseq_t *eseq, int err) /* Raced with an update, try again */ old = cur; } + return cur; } EXPORT_SYMBOL(__errseq_set); diff --git a/mm/filemap.c b/mm/filemap.c index 2803b30cbb5d..879623032016 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -555,6 +555,14 @@ int filemap_write_and_wait_range(struct address_space *mapping, } EXPORT_SYMBOL(filemap_write_and_wait_range); +void __filemap_set_wb_err(struct address_space *mapping, int err) +{ + errseq_t eseq = __errseq_set(&mapping->wb_err, err); + trace_filemap_set_wb_err(mapping, eseq); + +} +EXPORT_SYMBOL(__filemap_set_wb_err); + /** * filemap_report_wb_err - report wb error (if any) that was previously set * @file: struct file on which the error is being reported @@ -579,14 +587,17 @@ EXPORT_SYMBOL(filemap_write_and_wait_range); int filemap_report_wb_err(struct file *file) { int err = 0; + errseq_t old = READ_ONCE(file->f_wb_err); struct address_space *mapping = file->f_mapping; /* Locklessly handle the common case where nothing has changed */ - if (errseq_check(&mapping->wb_err, READ_ONCE(file->f_wb_err))) { + if (errseq_check(&mapping->wb_err, old)) { /* Something changed, must use slow path */ spin_lock(&file->f_lock); + old = file->f_wb_err; err = errseq_check_and_advance(&mapping->wb_err, &file->f_wb_err); + trace_filemap_report_wb_err(file, old); spin_unlock(&file->f_lock); } return err;