Add a tracepoint to log internal failures (such as cache errors) that we
don't otherwise want to pass back to the netfs.

Signed-off-by: David Howells <dhowe...@redhat.com>
---

 fs/netfs/read_helper.c       |   14 +++++++++-
 include/trace/events/netfs.h |   58 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 70 insertions(+), 2 deletions(-)

diff --git a/fs/netfs/read_helper.c b/fs/netfs/read_helper.c
index ce2f31d20250..762a15350242 100644
--- a/fs/netfs/read_helper.c
+++ b/fs/netfs/read_helper.c
@@ -271,6 +271,8 @@ static void netfs_rreq_copy_terminated(void *priv, ssize_t 
transferred_or_error,
 
        if (IS_ERR_VALUE(transferred_or_error)) {
                netfs_stat(&netfs_n_rh_write_failed);
+               trace_netfs_failure(rreq, subreq, transferred_or_error,
+                                   netfs_fail_copy_to_cache);
        } else {
                netfs_stat(&netfs_n_rh_write_done);
        }
@@ -323,6 +325,7 @@ static void netfs_rreq_do_write_to_cache(struct 
netfs_read_request *rreq)
                ret = cres->ops->prepare_write(cres, &subreq->start, 
&subreq->len,
                                               rreq->i_size);
                if (ret < 0) {
+                       trace_netfs_failure(rreq, subreq, ret, 
netfs_fail_prepare_write);
                        trace_netfs_sreq(subreq, netfs_sreq_trace_write_skip);
                        continue;
                }
@@ -627,6 +630,8 @@ void netfs_subreq_terminated(struct netfs_read_subrequest 
*subreq,
 
        if (IS_ERR_VALUE(transferred_or_error)) {
                subreq->error = transferred_or_error;
+               trace_netfs_failure(rreq, subreq, transferred_or_error,
+                                   netfs_fail_read);
                goto failed;
        }
 
@@ -996,8 +1001,10 @@ int netfs_readpage(struct file *file,
        } while (test_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags));
 
        ret = rreq->error;
-       if (ret == 0 && rreq->submitted < rreq->len)
+       if (ret == 0 && rreq->submitted < rreq->len) {
+               trace_netfs_failure(rreq, NULL, ret, netfs_fail_short_readpage);
                ret = -EIO;
+       }
 out:
        netfs_put_read_request(rreq, false);
        return ret;
@@ -1074,6 +1081,7 @@ int netfs_write_begin(struct file *file, struct 
address_space *mapping,
                /* Allow the netfs (eg. ceph) to flush conflicts. */
                ret = ops->check_write_begin(file, pos, len, page, _fsdata);
                if (ret < 0) {
+                       trace_netfs_failure(NULL, NULL, ret, 
netfs_fail_check_write_begin);
                        if (ret == -EAGAIN)
                                goto retry;
                        goto error;
@@ -1150,8 +1158,10 @@ int netfs_write_begin(struct file *file, struct 
address_space *mapping,
        }
 
        ret = rreq->error;
-       if (ret == 0 && rreq->submitted < rreq->len)
+       if (ret == 0 && rreq->submitted < rreq->len) {
+               trace_netfs_failure(rreq, NULL, ret, 
netfs_fail_short_write_begin);
                ret = -EIO;
+       }
        netfs_put_read_request(rreq, false);
        if (ret < 0)
                goto error;
diff --git a/include/trace/events/netfs.h b/include/trace/events/netfs.h
index e3ebeabd3852..de1c64635e42 100644
--- a/include/trace/events/netfs.h
+++ b/include/trace/events/netfs.h
@@ -47,6 +47,15 @@ enum netfs_sreq_trace {
        netfs_sreq_trace_write_term,
 };
 
+enum netfs_failure {
+       netfs_fail_check_write_begin,
+       netfs_fail_copy_to_cache,
+       netfs_fail_read,
+       netfs_fail_short_readpage,
+       netfs_fail_short_write_begin,
+       netfs_fail_prepare_write,
+};
+
 #endif
 
 #define netfs_read_traces                                      \
@@ -81,6 +90,14 @@ enum netfs_sreq_trace {
        EM(netfs_sreq_trace_write_skip,         "SKIP ")        \
        E_(netfs_sreq_trace_write_term,         "WTERM")
 
+#define netfs_failures                                                 \
+       EM(netfs_fail_check_write_begin,        "check-write-begin")    \
+       EM(netfs_fail_copy_to_cache,            "copy-to-cache")        \
+       EM(netfs_fail_read,                     "read")                 \
+       EM(netfs_fail_short_readpage,           "short-readpage")       \
+       EM(netfs_fail_short_write_begin,        "short-write-begin")    \
+       E_(netfs_fail_prepare_write,            "prep-write")
+
 
 /*
  * Export enum symbols via userspace.
@@ -94,6 +111,7 @@ netfs_read_traces;
 netfs_rreq_traces;
 netfs_sreq_sources;
 netfs_sreq_traces;
+netfs_failures;
 
 /*
  * Now redefine the EM() and E_() macros to map the enums to the strings that
@@ -197,6 +215,46 @@ TRACE_EVENT(netfs_sreq,
                      __entry->error)
            );
 
+TRACE_EVENT(netfs_failure,
+           TP_PROTO(struct netfs_read_request *rreq,
+                    struct netfs_read_subrequest *sreq,
+                    int error, enum netfs_failure what),
+
+           TP_ARGS(rreq, sreq, error, what),
+
+           TP_STRUCT__entry(
+                   __field(unsigned int,               rreq            )
+                   __field(unsigned short,             index           )
+                   __field(short,                      error           )
+                   __field(unsigned short,             flags           )
+                   __field(enum netfs_read_source,     source          )
+                   __field(enum netfs_failure,         what            )
+                   __field(size_t,                     len             )
+                   __field(size_t,                     transferred     )
+                   __field(loff_t,                     start           )
+                            ),
+
+           TP_fast_assign(
+                   __entry->rreq       = rreq->debug_id;
+                   __entry->index      = sreq ? sreq->debug_index : 0;
+                   __entry->error      = error;
+                   __entry->flags      = sreq ? sreq->flags : 0;
+                   __entry->source     = sreq ? sreq->source : 
NETFS_INVALID_READ;
+                   __entry->what       = what;
+                   __entry->len        = sreq ? sreq->len : 0;
+                   __entry->transferred = sreq ? sreq->transferred : 0;
+                   __entry->start      = sreq ? sreq->start : 0;
+                          ),
+
+           TP_printk("R=%08x[%u] %s f=%02x s=%llx %zx/%zx %s e=%d",
+                     __entry->rreq, __entry->index,
+                     __print_symbolic(__entry->source, netfs_sreq_sources),
+                     __entry->flags,
+                     __entry->start, __entry->transferred, __entry->len,
+                     __print_symbolic(__entry->what, netfs_failures),
+                     __entry->error)
+           );
+
 #endif /* _TRACE_NETFS_H */
 
 /* This part must be outside protection */


Reply via email to