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:
Родитель
1f4e9d03d1
Коммит
40ac7ab2d0
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче