mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 04:18:39 +08:00
nfs: pass explicit offset/count to trace events
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: eb5654b3b8
("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>
This commit is contained in:
parent
39c910a430
commit
fada32ed6d
@ -436,7 +436,7 @@ static void nfs_invalidate_folio(struct folio *folio, size_t offset,
|
|||||||
/* Cancel any unstarted writes on this page */
|
/* Cancel any unstarted writes on this page */
|
||||||
nfs_wb_folio_cancel(inode, folio);
|
nfs_wb_folio_cancel(inode, folio);
|
||||||
folio_wait_private_2(folio); /* [DEPRECATED] */
|
folio_wait_private_2(folio); /* [DEPRECATED] */
|
||||||
trace_nfs_invalidate_folio(inode, folio);
|
trace_nfs_invalidate_folio(inode, folio_pos(folio) + offset, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -504,7 +504,8 @@ static int nfs_launder_folio(struct folio *folio)
|
|||||||
|
|
||||||
folio_wait_private_2(folio); /* [DEPRECATED] */
|
folio_wait_private_2(folio); /* [DEPRECATED] */
|
||||||
ret = nfs_wb_folio(inode, folio);
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -939,10 +939,11 @@ TRACE_EVENT(nfs_sillyrename_unlink,
|
|||||||
DECLARE_EVENT_CLASS(nfs_folio_event,
|
DECLARE_EVENT_CLASS(nfs_folio_event,
|
||||||
TP_PROTO(
|
TP_PROTO(
|
||||||
const struct inode *inode,
|
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(
|
TP_STRUCT__entry(
|
||||||
__field(dev_t, dev)
|
__field(dev_t, dev)
|
||||||
@ -950,7 +951,7 @@ DECLARE_EVENT_CLASS(nfs_folio_event,
|
|||||||
__field(u64, fileid)
|
__field(u64, fileid)
|
||||||
__field(u64, version)
|
__field(u64, version)
|
||||||
__field(loff_t, offset)
|
__field(loff_t, offset)
|
||||||
__field(u32, count)
|
__field(size_t, count)
|
||||||
),
|
),
|
||||||
|
|
||||||
TP_fast_assign(
|
TP_fast_assign(
|
||||||
@ -960,13 +961,13 @@ DECLARE_EVENT_CLASS(nfs_folio_event,
|
|||||||
__entry->fileid = nfsi->fileid;
|
__entry->fileid = nfsi->fileid;
|
||||||
__entry->fhandle = nfs_fhandle_hash(&nfsi->fh);
|
__entry->fhandle = nfs_fhandle_hash(&nfsi->fh);
|
||||||
__entry->version = inode_peek_iversion_raw(inode);
|
__entry->version = inode_peek_iversion_raw(inode);
|
||||||
__entry->offset = folio_file_pos(folio);
|
__entry->offset = offset,
|
||||||
__entry->count = nfs_folio_length(folio);
|
__entry->count = count;
|
||||||
),
|
),
|
||||||
|
|
||||||
TP_printk(
|
TP_printk(
|
||||||
"fileid=%02x:%02x:%llu fhandle=0x%08x version=%llu "
|
"fileid=%02x:%02x:%llu fhandle=0x%08x version=%llu "
|
||||||
"offset=%lld count=%u",
|
"offset=%lld count=%zu",
|
||||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||||
(unsigned long long)__entry->fileid,
|
(unsigned long long)__entry->fileid,
|
||||||
__entry->fhandle, __entry->version,
|
__entry->fhandle, __entry->version,
|
||||||
@ -978,18 +979,20 @@ DECLARE_EVENT_CLASS(nfs_folio_event,
|
|||||||
DEFINE_EVENT(nfs_folio_event, name, \
|
DEFINE_EVENT(nfs_folio_event, name, \
|
||||||
TP_PROTO( \
|
TP_PROTO( \
|
||||||
const struct inode *inode, \
|
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,
|
DECLARE_EVENT_CLASS(nfs_folio_event_done,
|
||||||
TP_PROTO(
|
TP_PROTO(
|
||||||
const struct inode *inode,
|
const struct inode *inode,
|
||||||
struct folio *folio,
|
loff_t offset,
|
||||||
|
size_t count,
|
||||||
int ret
|
int ret
|
||||||
),
|
),
|
||||||
|
|
||||||
TP_ARGS(inode, folio, ret),
|
TP_ARGS(inode, offset, count, ret),
|
||||||
|
|
||||||
TP_STRUCT__entry(
|
TP_STRUCT__entry(
|
||||||
__field(dev_t, dev)
|
__field(dev_t, dev)
|
||||||
@ -998,7 +1001,7 @@ DECLARE_EVENT_CLASS(nfs_folio_event_done,
|
|||||||
__field(u64, fileid)
|
__field(u64, fileid)
|
||||||
__field(u64, version)
|
__field(u64, version)
|
||||||
__field(loff_t, offset)
|
__field(loff_t, offset)
|
||||||
__field(u32, count)
|
__field(size_t, count)
|
||||||
),
|
),
|
||||||
|
|
||||||
TP_fast_assign(
|
TP_fast_assign(
|
||||||
@ -1008,14 +1011,14 @@ DECLARE_EVENT_CLASS(nfs_folio_event_done,
|
|||||||
__entry->fileid = nfsi->fileid;
|
__entry->fileid = nfsi->fileid;
|
||||||
__entry->fhandle = nfs_fhandle_hash(&nfsi->fh);
|
__entry->fhandle = nfs_fhandle_hash(&nfsi->fh);
|
||||||
__entry->version = inode_peek_iversion_raw(inode);
|
__entry->version = inode_peek_iversion_raw(inode);
|
||||||
__entry->offset = folio_file_pos(folio);
|
__entry->offset = offset,
|
||||||
__entry->count = nfs_folio_length(folio);
|
__entry->count = count,
|
||||||
__entry->ret = ret;
|
__entry->ret = ret;
|
||||||
),
|
),
|
||||||
|
|
||||||
TP_printk(
|
TP_printk(
|
||||||
"fileid=%02x:%02x:%llu fhandle=0x%08x version=%llu "
|
"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),
|
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||||
(unsigned long long)__entry->fileid,
|
(unsigned long long)__entry->fileid,
|
||||||
__entry->fhandle, __entry->version,
|
__entry->fhandle, __entry->version,
|
||||||
@ -1027,10 +1030,11 @@ DECLARE_EVENT_CLASS(nfs_folio_event_done,
|
|||||||
DEFINE_EVENT(nfs_folio_event_done, name, \
|
DEFINE_EVENT(nfs_folio_event_done, name, \
|
||||||
TP_PROTO( \
|
TP_PROTO( \
|
||||||
const struct inode *inode, \
|
const struct inode *inode, \
|
||||||
struct folio *folio, \
|
loff_t offset, \
|
||||||
|
size_t count, \
|
||||||
int ret \
|
int ret \
|
||||||
), \
|
), \
|
||||||
TP_ARGS(inode, folio, ret))
|
TP_ARGS(inode, offset, count, ret))
|
||||||
|
|
||||||
DEFINE_NFS_FOLIO_EVENT(nfs_aop_readpage);
|
DEFINE_NFS_FOLIO_EVENT(nfs_aop_readpage);
|
||||||
DEFINE_NFS_FOLIO_EVENT_DONE(nfs_aop_readpage_done);
|
DEFINE_NFS_FOLIO_EVENT_DONE(nfs_aop_readpage_done);
|
||||||
|
@ -333,13 +333,15 @@ out:
|
|||||||
int nfs_read_folio(struct file *file, struct folio *folio)
|
int nfs_read_folio(struct file *file, struct folio *folio)
|
||||||
{
|
{
|
||||||
struct inode *inode = file_inode(file);
|
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_pageio_descriptor pgio;
|
||||||
struct nfs_open_context *ctx;
|
struct nfs_open_context *ctx;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
trace_nfs_aop_readpage(inode, folio);
|
trace_nfs_aop_readpage(inode, pos, len);
|
||||||
nfs_inc_stats(inode, NFSIOS_VFSREADPAGE);
|
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..
|
* Try to flush any pending writes to the file..
|
||||||
@ -383,7 +385,7 @@ int nfs_read_folio(struct file *file, struct folio *folio)
|
|||||||
out_put:
|
out_put:
|
||||||
put_nfs_open_context(ctx);
|
put_nfs_open_context(ctx);
|
||||||
out:
|
out:
|
||||||
trace_nfs_aop_readpage_done(inode, folio, ret);
|
trace_nfs_aop_readpage_done(inode, pos, len, ret);
|
||||||
return ret;
|
return ret;
|
||||||
out_unlock:
|
out_unlock:
|
||||||
folio_unlock(folio);
|
folio_unlock(folio);
|
||||||
|
@ -2063,17 +2063,17 @@ int nfs_wb_folio_cancel(struct inode *inode, struct folio *folio)
|
|||||||
*/
|
*/
|
||||||
int nfs_wb_folio(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_start = folio_pos(folio);
|
||||||
loff_t range_end = range_start + (loff_t)folio_size(folio) - 1;
|
size_t len = folio_size(folio);
|
||||||
struct writeback_control wbc = {
|
struct writeback_control wbc = {
|
||||||
.sync_mode = WB_SYNC_ALL,
|
.sync_mode = WB_SYNC_ALL,
|
||||||
.nr_to_write = 0,
|
.nr_to_write = 0,
|
||||||
.range_start = range_start,
|
.range_start = range_start,
|
||||||
.range_end = range_end,
|
.range_end = range_start + len - 1,
|
||||||
};
|
};
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
trace_nfs_writeback_folio(inode, folio);
|
trace_nfs_writeback_folio(inode, range_start, len);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
folio_wait_writeback(folio);
|
folio_wait_writeback(folio);
|
||||||
@ -2091,7 +2091,7 @@ int nfs_wb_folio(struct inode *inode, struct folio *folio)
|
|||||||
goto out_error;
|
goto out_error;
|
||||||
}
|
}
|
||||||
out_error:
|
out_error:
|
||||||
trace_nfs_writeback_folio_done(inode, folio, ret);
|
trace_nfs_writeback_folio_done(inode, range_start, len, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user