Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion fs/fuse/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "fuse_i.h"
#include "fuse_dlm_cache.h"
#include "fuse_trace.h"

#include <linux/pagemap.h>
#include <linux/slab.h>
Expand Down Expand Up @@ -1069,6 +1070,7 @@ static int fuse_do_readfolio(struct file *file, struct folio *folio,

fuse_read_args_fill(&ia, file, pos, desc.length, FUSE_READ);
res = fuse_simple_request(fm, &ia.ap.args);
trace_fuse_readfolio_reply(inode, pos, desc.length, res);
if (res < 0) {
/*
* Please refer to Documentation/filesystems/fuse/fuse-AOP_TRUNCATED_PAGE-reason.txt
Expand Down Expand Up @@ -2529,6 +2531,8 @@ static ssize_t fuse_cache_write_iter(struct kiocb *iocb, struct iov_iter *from)
orig_size = i_size_read(inode);
if (end > orig_size) {
i_size_write(inode, end);
trace_fuse_isize_change(inode, orig_size, end,
FUSE_ISIZE_WRITE_CLAIM);
extended = true;
}
spin_unlock(&fi->lock);
Expand All @@ -2553,8 +2557,11 @@ static ssize_t fuse_cache_write_iter(struct kiocb *iocb, struct iov_iter *from)

if (reached < end) {
spin_lock(&fi->lock);
if (i_size_read(inode) == end)
if (i_size_read(inode) == end) {
i_size_write(inode, reached);
trace_fuse_isize_change(inode, end, reached,
FUSE_ISIZE_WRITE_RETRACT);
}
spin_unlock(&fi->lock);
}
}
Expand Down Expand Up @@ -3320,6 +3327,8 @@ static ssize_t fuse_iomap_writeback_range(struct iomap_writepage_ctx *wpc,
if (pos + len > end_pos)
send_len = end_pos - pos;

trace_fuse_writeback_range(inode, pos, len, end_pos, send_len);

if (!data->ff) {
data->ff = fuse_write_file_get(fi);
if (!data->ff)
Expand Down
6 changes: 6 additions & 0 deletions fs/fuse/fuse_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -1230,6 +1230,12 @@ static inline struct fuse_mount *get_fuse_mount(struct inode *inode)
return get_fuse_mount_super(inode->i_sb);
}

enum fuse_isize_reason {
FUSE_ISIZE_WRITE_CLAIM,
FUSE_ISIZE_WRITE_RETRACT,
FUSE_ISIZE_ATTR,
};

static inline struct fuse_conn *get_fuse_conn(struct inode *inode)
{
return get_fuse_mount_super(inode->i_sb)->fc;
Expand Down
108 changes: 108 additions & 0 deletions fs/fuse/fuse_trace.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,114 @@ TRACE_EVENT(fuse_request_end,
__entry->unique, __entry->len, __entry->error)
);

#define FUSE_ISIZE_REASONS \
EM( FUSE_ISIZE_WRITE_CLAIM, "write_claim") \
EM( FUSE_ISIZE_WRITE_RETRACT, "write_retract")\
EMe(FUSE_ISIZE_ATTR, "attr")

#undef EM
#undef EMe
#define EM(a, b) TRACE_DEFINE_ENUM(a);
#define EMe(a, b) TRACE_DEFINE_ENUM(a);
FUSE_ISIZE_REASONS
#undef EM
#undef EMe
#define EM(a, b) { a, b },
#define EMe(a, b) { a, b }

/*
* Under DLM i_size is this node's view only; recording every change with its
* reason is what lets a lost update be tied to the local EOF at writeback.
*/
TRACE_EVENT(fuse_isize_change,
TP_PROTO(struct inode *inode, loff_t old_size, loff_t new_size,
int reason),

TP_ARGS(inode, old_size, new_size, reason),

TP_STRUCT__entry(
__field(dev_t, connection)
__field(uint64_t, nodeid)
__field(loff_t, old_size)
__field(loff_t, new_size)
__field(int, reason)
),

TP_fast_assign(
__entry->connection = get_fuse_conn(inode)->dev;
__entry->nodeid = get_fuse_inode(inode)->nodeid;
__entry->old_size = old_size;
__entry->new_size = new_size;
__entry->reason = reason;
),

TP_printk("connection %u nodeid %llu i_size %lld -> %lld (%s)",
__entry->connection, __entry->nodeid, __entry->old_size,
__entry->new_size,
__print_symbolic(__entry->reason, FUSE_ISIZE_REASONS))
);

TRACE_EVENT(fuse_writeback_range,
TP_PROTO(struct inode *inode, u64 pos, unsigned int len,
u64 end_pos, unsigned int send_len),

TP_ARGS(inode, pos, len, end_pos, send_len),

TP_STRUCT__entry(
__field(dev_t, connection)
__field(uint64_t, nodeid)
__field(uint64_t, pos)
__field(uint32_t, len)
__field(uint32_t, send_len)
__field(uint64_t, end_pos)
__field(loff_t, i_size)
),

TP_fast_assign(
__entry->connection = get_fuse_conn(inode)->dev;
__entry->nodeid = get_fuse_inode(inode)->nodeid;
__entry->pos = pos;
__entry->len = len;
__entry->send_len = send_len;
__entry->end_pos = end_pos;
__entry->i_size = i_size_read(inode);
),

TP_printk("connection %u nodeid %llu pos %llu len %u send %u end_pos %llu i_size %lld",
__entry->connection, __entry->nodeid, __entry->pos,
__entry->len, __entry->send_len, __entry->end_pos,
__entry->i_size)
);

TRACE_EVENT(fuse_readfolio_reply,
TP_PROTO(struct inode *inode, loff_t pos, size_t len,
ssize_t res),

TP_ARGS(inode, pos, len, res),

TP_STRUCT__entry(
__field(dev_t, connection)
__field(uint64_t, nodeid)
__field(loff_t, pos)
__field(size_t, len)
__field(ssize_t, res)
__field(loff_t, i_size)
),

TP_fast_assign(
__entry->connection = get_fuse_conn(inode)->dev;
__entry->nodeid = get_fuse_inode(inode)->nodeid;
__entry->pos = pos;
__entry->len = len;
__entry->res = res;
__entry->i_size = i_size_read(inode);
),

TP_printk("connection %u nodeid %llu pos %lld len %zu res %zd i_size %lld",
__entry->connection, __entry->nodeid, __entry->pos,
__entry->len, __entry->res, __entry->i_size)
);

#endif /* _TRACE_FUSE_H */

#undef TRACE_INCLUDE_PATH
Expand Down
7 changes: 6 additions & 1 deletion fs/fuse/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "fuse_dlm_cache.h"
#include "fuse_dev_i.h"
#include "dev_uring_i.h"
#include "fuse_trace.h"

#include <linux/dax.h>
#include <linux/pagemap.h>
Expand Down Expand Up @@ -660,8 +661,12 @@ static void fuse_change_attributes_i(struct inode *inode, struct fuse_attr *attr
* attr->size coming from server can be stale. We cannot trust it.
* Only update i_size if SIZE was actually returned by the server.
*/
if (have_size && !(cache_mask & STATX_SIZE))
if (have_size && !(cache_mask & STATX_SIZE)) {
i_size_write(inode, attr->size);
if (oldsize != attr->size)
trace_fuse_isize_change(inode, oldsize, attr->size,
FUSE_ISIZE_ATTR);
}
spin_unlock(&fi->lock);

/*
Expand Down
Loading