Commit 40ac7ab2 authored by Miklos Szeredi's avatar Miklos Szeredi
Browse files

fuse: simplify 'nofail' request



Instead of complex games with a reserved request, just use __GFP_NOFAIL.

Both calers (flush, readdir) guarantee that connection was already
initialized, so no need to wait for fc->initialized.

Also remove unneeded clearing of FR_BACKGROUND flag.

Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
parent 1f4e9d03
Loading
Loading
Loading
Loading
+4 −60
Original line number Diff line number Diff line
@@ -242,52 +242,6 @@ struct fuse_req *fuse_get_req_for_background(struct fuse_conn *fc,
}
EXPORT_SYMBOL_GPL(fuse_get_req_for_background);

/*
 * Return request in fuse_file->reserved_req.  However that may
 * currently be in use.  If that is the case, wait for it to become
 * available.
 */
static struct fuse_req *get_reserved_req(struct fuse_conn *fc,
					 struct file *file)
{
	struct fuse_req *req = NULL;
	struct fuse_inode *fi = get_fuse_inode(file_inode(file));
	struct fuse_file *ff = file->private_data;

	do {
		wait_event(fc->reserved_req_waitq, ff->reserved_req);
		spin_lock(&fi->lock);
		if (ff->reserved_req) {
			req = ff->reserved_req;
			ff->reserved_req = NULL;
			req->stolen_file = get_file(file);
		}
		spin_unlock(&fi->lock);
	} while (!req);

	return req;
}

/*
 * Put stolen request back into fuse_file->reserved_req
 */
static void put_reserved_req(struct fuse_conn *fc, struct fuse_req *req)
{
	struct file *file = req->stolen_file;
	struct fuse_inode *fi = get_fuse_inode(file_inode(file));
	struct fuse_file *ff = file->private_data;

	WARN_ON(req->max_pages);
	spin_lock(&fi->lock);
	memset(req, 0, sizeof(*req));
	fuse_request_init(req, NULL, NULL, 0);
	BUG_ON(ff->reserved_req);
	ff->reserved_req = req;
	wake_up_all(&fc->reserved_req_waitq);
	spin_unlock(&fi->lock);
	fput(file);
}

/*
 * Gets a requests for a file operation, always succeeds
 *
@@ -301,25 +255,18 @@ static void put_reserved_req(struct fuse_conn *fc, struct fuse_req *req)
 * filesystem should not have it's own file open.  If deadlock is
 * intentional, it can still be broken by "aborting" the filesystem.
 */
struct fuse_req *fuse_get_req_nofail_nopages(struct fuse_conn *fc,
					     struct file *file)
struct fuse_req *fuse_get_req_nofail_nopages(struct fuse_conn *fc)
{
	struct fuse_req *req;

	atomic_inc(&fc->num_waiting);
	wait_event(fc->blocked_waitq, fc->initialized);
	/* Matches smp_wmb() in fuse_set_initialized() */
	smp_rmb();
	req = fuse_request_alloc(0);
	if (!req)
		req = get_reserved_req(fc, file);
	req = __fuse_request_alloc(0, GFP_KERNEL | __GFP_NOFAIL);

	req->in.h.uid = from_kuid_munged(fc->user_ns, current_fsuid());
	req->in.h.gid = from_kgid_munged(fc->user_ns, current_fsgid());
	req->in.h.pid = pid_nr_ns(task_pid(current), fc->pid_ns);

	__set_bit(FR_WAITING, &req->flags);
	__clear_bit(FR_BACKGROUND, &req->flags);
	return req;
}

@@ -342,9 +289,6 @@ void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req)
			fuse_drop_waiting(fc);
		}

		if (req->stolen_file)
			put_reserved_req(fc, req);
		else
		fuse_request_free(req);
	}
}
@@ -719,7 +663,7 @@ void fuse_force_forget(struct file *file, u64 nodeid)

	memset(&inarg, 0, sizeof(inarg));
	inarg.nlookup = 1;
	req = fuse_get_req_nofail_nopages(fc, file);
	req = fuse_get_req_nofail_nopages(fc);
	req->in.h.opcode = FUSE_FORGET;
	req->in.h.nodeid = nodeid;
	req->in.numargs = 1;
+1 −1
Original line number Diff line number Diff line
@@ -432,7 +432,7 @@ static int fuse_flush(struct file *file, fl_owner_t id)
	if (err)
		return err;

	req = fuse_get_req_nofail_nopages(fc, file);
	req = fuse_get_req_nofail_nopages(fc);
	memset(&inarg, 0, sizeof(inarg));
	inarg.fh = ff->fh;
	inarg.lock_owner = fuse_lock_owner_id(fc, id);
+1 −7
Original line number Diff line number Diff line
@@ -435,8 +435,6 @@ struct fuse_req {
	/** Request completion callback */
	void (*end)(struct fuse_conn *, struct fuse_req *);

	/** Request is stolen from fuse_file->reserved_req */
	struct file *stolen_file;
};

struct fuse_iqueue {
@@ -580,9 +578,6 @@ struct fuse_conn {
	/** waitq for blocked connection */
	wait_queue_head_t blocked_waitq;

	/** waitq for reserved requests */
	wait_queue_head_t reserved_req_waitq;

	/** Connection established, cleared on umount, connection
	    abort and device release */
	unsigned connected;
@@ -927,8 +922,7 @@ void __fuse_get_request(struct fuse_req *req);
/**
 * Gets a requests for a file operation, always succeeds
 */
struct fuse_req *fuse_get_req_nofail_nopages(struct fuse_conn *fc,
					     struct file *file);
struct fuse_req *fuse_get_req_nofail_nopages(struct fuse_conn *fc);

/**
 * Decrement reference count of a request.  If count goes to zero free
+0 −1
Original line number Diff line number Diff line
@@ -617,7 +617,6 @@ void fuse_conn_init(struct fuse_conn *fc, struct user_namespace *user_ns)
	refcount_set(&fc->count, 1);
	atomic_set(&fc->dev_count, 1);
	init_waitqueue_head(&fc->blocked_waitq);
	init_waitqueue_head(&fc->reserved_req_waitq);
	fuse_iqueue_init(&fc->iq);
	INIT_LIST_HEAD(&fc->bg_queue);
	INIT_LIST_HEAD(&fc->entry);