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: Miklos Szeredi <mszeredi@redhat.com>
This commit is contained in:
Miklos Szeredi 2019-09-10 15:04:08 +02:00
Родитель 1f4e9d03d1
Коммит 40ac7ab2d0
4 изменённых файлов: 6 добавлений и 69 удалений

Просмотреть файл

@ -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,10 +289,7 @@ 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);
fuse_request_free(req);
}
}
EXPORT_SYMBOL_GPL(fuse_put_request);
@ -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;

Просмотреть файл

@ -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);

Просмотреть файл

@ -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

Просмотреть файл

@ -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);