]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
nfs: pass explicit offset/count to trace events
authorChristoph Hellwig <hch@lst.de>
Thu, 11 Jul 2024 07:17:02 +0000 (09:17 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 3 Aug 2024 07:00:05 +0000 (09:00 +0200)
[ Upstream commit fada32ed6dbc748f447c8d050a961b75d946055a ]

nfs_folio_length is unsafe to use without having the folio locked and a
check for a NULL ->f_mapping that protects against truncations and can
lead to kernel crashes.  E.g. when running xfstests generic/065 with
all nfs trace points enabled.

Follow the model of the XFS trace points and pass in an explŃ–cit offset
and length.  This has the additional benefit that these values can
be more accurate as some of the users touch partial folio ranges.

Fixes: eb5654b3b89d ("NFS: Enable tracing of nfs_invalidate_folio() and nfs_launder_folio()")
Reported-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/nfs/file.c
fs/nfs/nfstrace.h
fs/nfs/read.c
fs/nfs/write.c

index 6bd127e6683dcef2bef33ec721821e787c10098d..445db17f1b6c1426bd07c5f711f889b048678675 100644 (file)
@@ -434,7 +434,7 @@ static void nfs_invalidate_folio(struct folio *folio, size_t offset,
        /* Cancel any unstarted writes on this page */
        nfs_wb_folio_cancel(inode, folio);
        folio_wait_private_2(folio); /* [DEPRECATED] */
-       trace_nfs_invalidate_folio(inode, folio);
+       trace_nfs_invalidate_folio(inode, folio_pos(folio) + offset, length);
 }
 
 /*
@@ -502,7 +502,8 @@ static int nfs_launder_folio(struct folio *folio)
 
        folio_wait_private_2(folio); /* [DEPRECATED] */
        ret = nfs_wb_folio(inode, folio);
-       trace_nfs_launder_folio_done(inode, folio, ret);
+       trace_nfs_launder_folio_done(inode, folio_pos(folio),
+                       folio_size(folio), ret);
        return ret;
 }
 
index 1e710654af1173ae7e7f223cd20794725dde93a6..352fdaed4075418762ca5c176f0f2e4e15f3e523 100644 (file)
@@ -939,10 +939,11 @@ TRACE_EVENT(nfs_sillyrename_unlink,
 DECLARE_EVENT_CLASS(nfs_folio_event,
                TP_PROTO(
                        const struct inode *inode,
-                       struct folio *folio
+                       loff_t offset,
+                       size_t count
                ),
 
-               TP_ARGS(inode, folio),
+               TP_ARGS(inode, offset, count),
 
                TP_STRUCT__entry(
                        __field(dev_t, dev)
@@ -950,7 +951,7 @@ DECLARE_EVENT_CLASS(nfs_folio_event,
                        __field(u64, fileid)
                        __field(u64, version)
                        __field(loff_t, offset)
-                       __field(u32, count)
+                       __field(size_t, count)
                ),
 
                TP_fast_assign(
@@ -960,13 +961,13 @@ DECLARE_EVENT_CLASS(nfs_folio_event,
                        __entry->fileid = nfsi->fileid;
                        __entry->fhandle = nfs_fhandle_hash(&nfsi->fh);
                        __entry->version = inode_peek_iversion_raw(inode);
-                       __entry->offset = folio_file_pos(folio);
-                       __entry->count = nfs_folio_length(folio);
+                       __entry->offset = offset,
+                       __entry->count = count;
                ),
 
                TP_printk(
                        "fileid=%02x:%02x:%llu fhandle=0x%08x version=%llu "
-                       "offset=%lld count=%u",
+                       "offset=%lld count=%zu",
                        MAJOR(__entry->dev), MINOR(__entry->dev),
                        (unsigned long long)__entry->fileid,
                        __entry->fhandle, __entry->version,
@@ -978,18 +979,20 @@ DECLARE_EVENT_CLASS(nfs_folio_event,
        DEFINE_EVENT(nfs_folio_event, name, \
                        TP_PROTO( \
                                const struct inode *inode, \
-                               struct folio *folio \
+                               loff_t offset, \
+                               size_t count \
                        ), \
-                       TP_ARGS(inode, folio))
+                       TP_ARGS(inode, offset, count))
 
 DECLARE_EVENT_CLASS(nfs_folio_event_done,
                TP_PROTO(
                        const struct inode *inode,
-                       struct folio *folio,
+                       loff_t offset,
+                       size_t count,
                        int ret
                ),
 
-               TP_ARGS(inode, folio, ret),
+               TP_ARGS(inode, offset, count, ret),
 
                TP_STRUCT__entry(
                        __field(dev_t, dev)
@@ -998,7 +1001,7 @@ DECLARE_EVENT_CLASS(nfs_folio_event_done,
                        __field(u64, fileid)
                        __field(u64, version)
                        __field(loff_t, offset)
-                       __field(u32, count)
+                       __field(size_t, count)
                ),
 
                TP_fast_assign(
@@ -1008,14 +1011,14 @@ DECLARE_EVENT_CLASS(nfs_folio_event_done,
                        __entry->fileid = nfsi->fileid;
                        __entry->fhandle = nfs_fhandle_hash(&nfsi->fh);
                        __entry->version = inode_peek_iversion_raw(inode);
-                       __entry->offset = folio_file_pos(folio);
-                       __entry->count = nfs_folio_length(folio);
+                       __entry->offset = offset,
+                       __entry->count = count,
                        __entry->ret = ret;
                ),
 
                TP_printk(
                        "fileid=%02x:%02x:%llu fhandle=0x%08x version=%llu "
-                       "offset=%lld count=%u ret=%d",
+                       "offset=%lld count=%zu ret=%d",
                        MAJOR(__entry->dev), MINOR(__entry->dev),
                        (unsigned long long)__entry->fileid,
                        __entry->fhandle, __entry->version,
@@ -1027,10 +1030,11 @@ DECLARE_EVENT_CLASS(nfs_folio_event_done,
        DEFINE_EVENT(nfs_folio_event_done, name, \
                        TP_PROTO( \
                                const struct inode *inode, \
-                               struct folio *folio, \
+                               loff_t offset, \
+                               size_t count, \
                                int ret \
                        ), \
-                       TP_ARGS(inode, folio, ret))
+                       TP_ARGS(inode, offset, count, ret))
 
 DEFINE_NFS_FOLIO_EVENT(nfs_aop_readpage);
 DEFINE_NFS_FOLIO_EVENT_DONE(nfs_aop_readpage_done);
index a142287d86f68ed411dce6f9c410e41948c570b2..88e6a78d37fb3e790de1ede4d928c3abdb9fb9b5 100644 (file)
@@ -332,13 +332,15 @@ out:
 int nfs_read_folio(struct file *file, struct folio *folio)
 {
        struct inode *inode = file_inode(file);
+       loff_t pos = folio_pos(folio);
+       size_t len = folio_size(folio);
        struct nfs_pageio_descriptor pgio;
        struct nfs_open_context *ctx;
        int ret;
 
-       trace_nfs_aop_readpage(inode, folio);
+       trace_nfs_aop_readpage(inode, pos, len);
        nfs_inc_stats(inode, NFSIOS_VFSREADPAGE);
-       task_io_account_read(folio_size(folio));
+       task_io_account_read(len);
 
        /*
         * Try to flush any pending writes to the file..
@@ -381,7 +383,7 @@ int nfs_read_folio(struct file *file, struct folio *folio)
 out_put:
        put_nfs_open_context(ctx);
 out:
-       trace_nfs_aop_readpage_done(inode, folio, ret);
+       trace_nfs_aop_readpage_done(inode, pos, len, ret);
        return ret;
 out_unlock:
        folio_unlock(folio);
index 2329cbb0e446b97976de4ba587315957fb921a54..75c1b3c7faeadf93fc85fc9df2220124aa5b03b3 100644 (file)
@@ -2073,17 +2073,17 @@ int nfs_wb_folio_cancel(struct inode *inode, struct folio *folio)
  */
 int nfs_wb_folio(struct inode *inode, struct folio *folio)
 {
-       loff_t range_start = folio_file_pos(folio);
-       loff_t range_end = range_start + (loff_t)folio_size(folio) - 1;
+       loff_t range_start = folio_pos(folio);
+       size_t len = folio_size(folio);
        struct writeback_control wbc = {
                .sync_mode = WB_SYNC_ALL,
                .nr_to_write = 0,
                .range_start = range_start,
-               .range_end = range_end,
+               .range_end = range_start + len - 1,
        };
        int ret;
 
-       trace_nfs_writeback_folio(inode, folio);
+       trace_nfs_writeback_folio(inode, range_start, len);
 
        for (;;) {
                folio_wait_writeback(folio);
@@ -2101,7 +2101,7 @@ int nfs_wb_folio(struct inode *inode, struct folio *folio)
                        goto out_error;
        }
 out_error:
-       trace_nfs_writeback_folio_done(inode, folio, ret);
+       trace_nfs_writeback_folio_done(inode, range_start, len, ret);
        return ret;
 }