Commit 12597287 authored by Miklos Szeredi's avatar Miklos Szeredi
Browse files

fuse: add simple background helper



Create a helper named fuse_simple_background() that is similar to
fuse_simple_request().  Unlike the latter, it returns immediately and calls
the supplied 'end' callback when the reply is received.

The supplied 'args' pointer is stored in 'fuse_req' which allows the
callback to interpret the output arguments decoded from the reply.

Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
parent 338f2e3f
Loading
Loading
Loading
Loading
+45 −0
Original line number Diff line number Diff line
@@ -626,6 +626,51 @@ bool fuse_request_queue_background(struct fuse_conn *fc, struct fuse_req *req)
	return queued;
}

static void fuse_simple_end(struct fuse_conn *fc, struct fuse_req *req)
{
	struct fuse_args *args = req->args;
	int err = req->out.h.error;

	if (!err && args->out_argvar) {
		BUG_ON(args->out_numargs == 0);
		args->out_args[args->out_numargs - 1].size =
			req->out.args[args->out_numargs - 1].size;
	}
	req->args->end(fc, req->args, req->out.h.error);
}

int fuse_simple_background(struct fuse_conn *fc, struct fuse_args *args,
			    gfp_t gfp_flags)
{
	struct fuse_req *req;

	if (args->force) {
		WARN_ON(!args->nocreds);
		req = __fuse_request_alloc(0, gfp_flags);
		if (!req)
			return -ENOMEM;
		__set_bit(FR_BACKGROUND, &req->flags);
	} else {
		WARN_ON(args->nocreds);
		req = __fuse_get_req(fc, 0, true);
		if (IS_ERR(req))
			return PTR_ERR(req);
	}

	fuse_args_to_req(req, args);

	req->args = args;
	req->end = fuse_simple_end;

	if (!fuse_request_queue_background(fc, req)) {
		fuse_put_request(fc, req);
		return -ENOTCONN;
	}

	return 0;
}
EXPORT_SYMBOL_GPL(fuse_simple_background);

void fuse_request_send_background(struct fuse_conn *fc, struct fuse_req *req)
{
	WARN_ON(!req->end);
+6 −0
Original line number Diff line number Diff line
@@ -301,6 +301,7 @@ struct fuse_args {
	bool page_replace:1;
	struct fuse_in_arg in_args[3];
	struct fuse_arg out_args[2];
	void (*end)(struct fuse_conn *fc, struct fuse_args *args, int error);
};

struct fuse_args_pages {
@@ -381,6 +382,9 @@ struct fuse_req {
	/** Entry on the interrupts list  */
	struct list_head intr_entry;

	/* Input/output arguments */
	struct fuse_args *args;

	/** refcount */
	refcount_t count;

@@ -948,6 +952,8 @@ void fuse_request_send(struct fuse_conn *fc, struct fuse_req *req);
 * Simple request sending that does request allocation and freeing
 */
ssize_t fuse_simple_request(struct fuse_conn *fc, struct fuse_args *args);
int fuse_simple_background(struct fuse_conn *fc, struct fuse_args *args,
			   gfp_t gfp_flags);

/**
 * Send a request in the background