Skip to content

Test pull request #1198

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
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
37 changes: 11 additions & 26 deletions fs/fuse/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -299,24 +299,6 @@ unsigned int fuse_len_args(unsigned int numargs, struct fuse_arg *args)
}
EXPORT_SYMBOL_GPL(fuse_len_args);

static u64 fuse_get_unique_locked(struct fuse_iqueue *fiq)
{
fiq->reqctr += FUSE_REQ_ID_STEP;
return fiq->reqctr;
}

u64 fuse_get_unique(struct fuse_iqueue *fiq)
{
u64 ret;

spin_lock(&fiq->lock);
ret = fuse_get_unique_locked(fiq);
spin_unlock(&fiq->lock);

return ret;
}
EXPORT_SYMBOL_GPL(fuse_get_unique);

unsigned int fuse_req_hash(u64 unique)
{
return hash_long(unique & ~FUSE_INT_REQ_BIT, FUSE_PQ_HASH_BITS);
Expand Down Expand Up @@ -372,8 +354,6 @@ static void fuse_dev_queue_req(struct fuse_iqueue *fiq, struct fuse_req *req)
{
spin_lock(&fiq->lock);
if (fiq->connected) {
if (req->in.h.opcode != FUSE_NOTIFY_REPLY)
req->in.h.unique = fuse_get_unique_locked(fiq);
list_add_tail(&req->list, &fiq->pending);
fuse_dev_wake_and_unlock(fiq);
} else {
Expand All @@ -396,7 +376,9 @@ static void fuse_send_one(struct fuse_iqueue *fiq, struct fuse_req *req)
req->in.h.len = sizeof(struct fuse_in_header) +
fuse_len_args(req->args->in_numargs,
(struct fuse_arg *) req->args->in_args);
trace_fuse_request_send(req);

/* enqueue, as it is send to "fiq->ops queue" */
trace_fuse_request_enqueue(req);
fiq->ops->send_req(fiq, req);
}

Expand Down Expand Up @@ -637,6 +619,9 @@ static void fuse_args_to_req(struct fuse_req *req, struct fuse_args *args)
req->in.h.total_extlen = args->in_args[args->ext_idx].size / 8;
if (args->end)
__set_bit(FR_ASYNC, &req->flags);

if (req->in.h.opcode != FUSE_NOTIFY_REPLY)
req->in.h.unique = fuse_get_unique(&req->fm->fc->iq);
}

ssize_t __fuse_simple_request(struct mnt_idmap *idmap,
Expand Down Expand Up @@ -684,9 +669,6 @@ ssize_t __fuse_simple_request(struct mnt_idmap *idmap,
static bool fuse_request_queue_background_uring(struct fuse_conn *fc,
struct fuse_req *req)
{
struct fuse_iqueue *fiq = &fc->iq;

req->in.h.unique = fuse_get_unique(fiq);
req->in.h.len = sizeof(struct fuse_in_header) +
fuse_len_args(req->args->in_numargs,
(struct fuse_arg *) req->args->in_args);
Expand All @@ -711,6 +693,8 @@ static int fuse_request_queue_background(struct fuse_req *req)
}
__set_bit(FR_ISREPLY, &req->flags);

trace_fuse_request_bg_enqueue(req);

#ifdef CONFIG_FUSE_IO_URING
if (fuse_uring_ready(fc))
return fuse_request_queue_background_uring(fc, req);
Expand Down Expand Up @@ -1288,7 +1272,7 @@ __releases(fiq->lock)
struct fuse_in_header ih = {
.opcode = FUSE_FORGET,
.nodeid = forget->forget_one.nodeid,
.unique = fuse_get_unique_locked(fiq),
.unique = fuse_get_unique(fiq),
.len = sizeof(ih) + sizeof(arg),
};

Expand Down Expand Up @@ -1319,7 +1303,7 @@ __releases(fiq->lock)
struct fuse_batch_forget_in arg = { .count = 0 };
struct fuse_in_header ih = {
.opcode = FUSE_BATCH_FORGET,
.unique = fuse_get_unique_locked(fiq),
.unique = fuse_get_unique(fiq),
.len = sizeof(ih) + sizeof(arg),
};

Expand Down Expand Up @@ -1445,6 +1429,7 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file,
clear_bit(FR_PENDING, &req->flags);
list_del_init(&req->list);
spin_unlock(&fiq->lock);
trace_fuse_request_send(req);

args = req->args;
reqsize = req->in.h.len;
Expand Down
44 changes: 17 additions & 27 deletions fs/fuse/dev_uring.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "fuse_i.h"
#include "dev_uring_i.h"
#include "fuse_dev_i.h"
#include "fuse_trace.h"

#include <linux/fs.h>
#include <linux/io_uring/cmd.h>
Expand Down Expand Up @@ -693,6 +694,21 @@ static int fuse_uring_prepare_send(struct fuse_ring_ent *ent,
return err;
}

static void fuse_uring_send(struct fuse_ring_ent *ent, struct io_uring_cmd *cmd,
ssize_t ret, unsigned int issue_flags)
{
struct fuse_ring_queue *queue = ent->queue;

spin_lock(&queue->lock);
ent->state = FRRS_USERSPACE;
list_move(&ent->list, &queue->ent_in_userspace);
ent->cmd = NULL;
spin_unlock(&queue->lock);

trace_fuse_request_send(ent->fuse_req);
io_uring_cmd_done(cmd, ret, 0, issue_flags);
}

/*
* Write data to the ring buffer and send the request to userspace,
* userspace will read it
Expand All @@ -702,22 +718,13 @@ static int fuse_uring_send_next_to_ring(struct fuse_ring_ent *ent,
struct fuse_req *req,
unsigned int issue_flags)
{
struct fuse_ring_queue *queue = ent->queue;
int err;
struct io_uring_cmd *cmd;

err = fuse_uring_prepare_send(ent, req);
if (err)
return err;

spin_lock(&queue->lock);
cmd = ent->cmd;
ent->cmd = NULL;
ent->state = FRRS_USERSPACE;
list_move(&ent->list, &queue->ent_in_userspace);
spin_unlock(&queue->lock);

io_uring_cmd_done(cmd, 0, 0, issue_flags);
fuse_uring_send(ent, ent->cmd, 0, issue_flags);
return 0;
}

Expand Down Expand Up @@ -1173,20 +1180,6 @@ int fuse_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags)
return -EIOCBQUEUED;
}

static void fuse_uring_send(struct fuse_ring_ent *ent, struct io_uring_cmd *cmd,
ssize_t ret, unsigned int issue_flags)
{
struct fuse_ring_queue *queue = ent->queue;

spin_lock(&queue->lock);
ent->state = FRRS_USERSPACE;
list_move(&ent->list, &queue->ent_in_userspace);
ent->cmd = NULL;
spin_unlock(&queue->lock);

io_uring_cmd_done(cmd, ret, 0, issue_flags);
}

/*
* This prepares and sends the ring request in fuse-uring task context.
* User buffers are not mapped yet - the application does not have permission
Expand Down Expand Up @@ -1252,9 +1245,6 @@ void fuse_uring_queue_fuse_req(struct fuse_iqueue *fiq, struct fuse_req *req)
if (!queue)
goto err;

if (req->in.h.opcode != FUSE_NOTIFY_REPLY)
req->in.h.unique = fuse_get_unique(fiq);

spin_lock(&queue->lock);
err = -ENOTCONN;
if (unlikely(queue->stopped))
Expand Down
4 changes: 0 additions & 4 deletions fs/fuse/fuse_dev_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,6 @@

#include <linux/types.h>

/* Ordinary requests have even IDs, while interrupts IDs are odd */
#define FUSE_INT_REQ_BIT (1ULL << 0)
#define FUSE_REQ_ID_STEP (1ULL << 1)

struct fuse_arg;
struct fuse_args;
struct fuse_pqueue;
Expand Down
21 changes: 16 additions & 5 deletions fs/fuse/fuse_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@
/** Frequency (in jiffies) of request timeout checks, if opted into */
extern const unsigned long fuse_timeout_timer_freq;

/* Ordinary requests have even IDs, while interrupts IDs are odd */
#define FUSE_INT_REQ_BIT (1ULL << 0)
#define FUSE_REQ_ID_STEP (1ULL << 1)

/** Maximum of max_pages received in init_out */
extern unsigned int fuse_max_pages_limit;
/*
Expand Down Expand Up @@ -515,7 +519,7 @@ struct fuse_iqueue {
wait_queue_head_t waitq;

/** The next unique request id */
u64 reqctr;
u64 __percpu *reqctr;

/** The list of pending requests */
struct list_head pending;
Expand Down Expand Up @@ -1105,6 +1109,17 @@ static inline void fuse_sync_bucket_dec(struct fuse_sync_bucket *bucket)
rcu_read_unlock();
}

/**
* Get the next unique ID for a request
*/
static inline u64 fuse_get_unique(struct fuse_iqueue *fiq)
{
int step = FUSE_REQ_ID_STEP * (task_cpu(current));
u64 cntr = this_cpu_inc_return(*fiq->reqctr);

return cntr * FUSE_REQ_ID_STEP * NR_CPUS + step;
}

/** Device operations */
extern const struct file_operations fuse_dev_operations;

Expand Down Expand Up @@ -1458,10 +1473,6 @@ int fuse_readdir(struct file *file, struct dir_context *ctx);
*/
unsigned int fuse_len_args(unsigned int numargs, struct fuse_arg *args);

/**
* Get the next unique ID for a request
*/
u64 fuse_get_unique(struct fuse_iqueue *fiq);
void fuse_free_conn(struct fuse_conn *fc);

/* dax.c */
Expand Down
51 changes: 38 additions & 13 deletions fs/fuse/fuse_trace.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,30 +77,55 @@ OPCODES
#define EM(a, b) {a, b},
#define EMe(a, b) {a, b}

TRACE_EVENT(fuse_request_send,
#define FUSE_REQ_TRACE_FIELDS \
__field(dev_t, connection) \
__field(uint64_t, unique) \
__field(enum fuse_opcode, opcode) \
__field(uint32_t, len) \

#define FUSE_REQ_TRACE_ASSIGN(req) \
do { \
__entry->connection = req->fm->fc->dev; \
__entry->unique = req->in.h.unique; \
__entry->opcode = req->in.h.opcode; \
__entry->len = req->in.h.len; \
} while (0)


TRACE_EVENT(fuse_request_enqueue,
TP_PROTO(const struct fuse_req *req),
TP_ARGS(req),
TP_STRUCT__entry(FUSE_REQ_TRACE_FIELDS),
TP_fast_assign(FUSE_REQ_TRACE_ASSIGN(req)),

TP_printk("connection %u req %llu opcode %u (%s) len %u ",
__entry->connection, __entry->unique, __entry->opcode,
__print_symbolic(__entry->opcode, OPCODES), __entry->len)
);

TRACE_EVENT(fuse_request_bg_enqueue,
TP_PROTO(const struct fuse_req *req),
TP_ARGS(req),
TP_STRUCT__entry(FUSE_REQ_TRACE_FIELDS),
TP_fast_assign(FUSE_REQ_TRACE_ASSIGN(req)),

TP_STRUCT__entry(
__field(dev_t, connection)
__field(uint64_t, unique)
__field(enum fuse_opcode, opcode)
__field(uint32_t, len)
),
TP_printk("connection %u req %llu opcode %u (%s) len %u ",
__entry->connection, __entry->unique, __entry->opcode,
__print_symbolic(__entry->opcode, OPCODES), __entry->len)
);

TP_fast_assign(
__entry->connection = req->fm->fc->dev;
__entry->unique = req->in.h.unique;
__entry->opcode = req->in.h.opcode;
__entry->len = req->in.h.len;
),
TRACE_EVENT(fuse_request_send,
TP_PROTO(const struct fuse_req *req),
TP_ARGS(req),
TP_STRUCT__entry(FUSE_REQ_TRACE_FIELDS),
TP_fast_assign(FUSE_REQ_TRACE_ASSIGN(req)),

TP_printk("connection %u req %llu opcode %u (%s) len %u ",
__entry->connection, __entry->unique, __entry->opcode,
__print_symbolic(__entry->opcode, OPCODES), __entry->len)
);


TRACE_EVENT(fuse_request_end,
TP_PROTO(const struct fuse_req *req),

Expand Down
7 changes: 7 additions & 0 deletions fs/fuse/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -933,6 +933,7 @@ static void fuse_iqueue_init(struct fuse_iqueue *fiq,
memset(fiq, 0, sizeof(struct fuse_iqueue));
spin_lock_init(&fiq->lock);
init_waitqueue_head(&fiq->waitq);
fiq->reqctr = alloc_percpu(u64);
INIT_LIST_HEAD(&fiq->pending);
INIT_LIST_HEAD(&fiq->interrupts);
fiq->forget_list_tail = &fiq->forget_list_head;
Expand All @@ -941,6 +942,11 @@ static void fuse_iqueue_init(struct fuse_iqueue *fiq,
fiq->priv = priv;
}

static void fuse_iqueue_destroy(struct fuse_iqueue *fiq)
{
free_percpu(fiq->reqctr);
}

void fuse_pqueue_init(struct fuse_pqueue *fpq)
{
unsigned int i;
Expand Down Expand Up @@ -999,6 +1005,7 @@ static void delayed_release(struct rcu_head *p)
struct fuse_conn *fc = container_of(p, struct fuse_conn, rcu);

fuse_uring_destruct(fc);
fuse_iqueue_destroy(&fc->iq);

put_user_ns(fc->user_ns);
fc->release(fc);
Expand Down
3 changes: 0 additions & 3 deletions fs/fuse/virtio_fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1481,9 +1481,6 @@ static void virtio_fs_send_req(struct fuse_iqueue *fiq, struct fuse_req *req)
struct virtio_fs_vq *fsvq;
int ret;

if (req->in.h.opcode != FUSE_NOTIFY_REPLY)
req->in.h.unique = fuse_get_unique(fiq);

clear_bit(FR_PENDING, &req->flags);

fs = fiq->priv;
Expand Down