Commit 8b41e671 authored by Maxim Patlasov's avatar Maxim Patlasov Committed by Miklos Szeredi

fuse: make request allocations for background processing explicit

There are two types of processing requests in FUSE: synchronous (via
fuse_request_send()) and asynchronous (via adding to fc->bg_queue).

Fortunately, the type of processing is always known in advance, at the time
of request allocation. This preparatory patch utilizes this fact making
fuse_get_req() aware about the type. Next patches will use it.
Signed-off-by: default avatarMaxim Patlasov <mpatlasov@parallels.com>
Signed-off-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
parent 4c82456e
...@@ -422,7 +422,7 @@ static int cuse_send_init(struct cuse_conn *cc) ...@@ -422,7 +422,7 @@ static int cuse_send_init(struct cuse_conn *cc)
BUILD_BUG_ON(CUSE_INIT_INFO_MAX > PAGE_SIZE); BUILD_BUG_ON(CUSE_INIT_INFO_MAX > PAGE_SIZE);
req = fuse_get_req(fc, 1); req = fuse_get_req_for_background(fc, 1);
if (IS_ERR(req)) { if (IS_ERR(req)) {
rc = PTR_ERR(req); rc = PTR_ERR(req);
goto err; goto err;
......
...@@ -130,7 +130,8 @@ static void fuse_req_init_context(struct fuse_req *req) ...@@ -130,7 +130,8 @@ static void fuse_req_init_context(struct fuse_req *req)
req->in.h.pid = current->pid; req->in.h.pid = current->pid;
} }
struct fuse_req *fuse_get_req(struct fuse_conn *fc, unsigned npages) static struct fuse_req *__fuse_get_req(struct fuse_conn *fc, unsigned npages,
bool for_background)
{ {
struct fuse_req *req; struct fuse_req *req;
sigset_t oldset; sigset_t oldset;
...@@ -156,14 +157,27 @@ struct fuse_req *fuse_get_req(struct fuse_conn *fc, unsigned npages) ...@@ -156,14 +157,27 @@ struct fuse_req *fuse_get_req(struct fuse_conn *fc, unsigned npages)
fuse_req_init_context(req); fuse_req_init_context(req);
req->waiting = 1; req->waiting = 1;
req->background = for_background;
return req; return req;
out: out:
atomic_dec(&fc->num_waiting); atomic_dec(&fc->num_waiting);
return ERR_PTR(err); return ERR_PTR(err);
} }
struct fuse_req *fuse_get_req(struct fuse_conn *fc, unsigned npages)
{
return __fuse_get_req(fc, npages, false);
}
EXPORT_SYMBOL_GPL(fuse_get_req); EXPORT_SYMBOL_GPL(fuse_get_req);
struct fuse_req *fuse_get_req_for_background(struct fuse_conn *fc,
unsigned npages)
{
return __fuse_get_req(fc, npages, true);
}
EXPORT_SYMBOL_GPL(fuse_get_req_for_background);
/* /*
* Return request in fuse_file->reserved_req. However that may * Return request in fuse_file->reserved_req. However that may
* currently be in use. If that is the case, wait for it to become * currently be in use. If that is the case, wait for it to become
...@@ -232,6 +246,7 @@ struct fuse_req *fuse_get_req_nofail_nopages(struct fuse_conn *fc, ...@@ -232,6 +246,7 @@ struct fuse_req *fuse_get_req_nofail_nopages(struct fuse_conn *fc,
fuse_req_init_context(req); fuse_req_init_context(req);
req->waiting = 1; req->waiting = 1;
req->background = 0;
return req; return req;
} }
...@@ -442,6 +457,7 @@ __acquires(fc->lock) ...@@ -442,6 +457,7 @@ __acquires(fc->lock)
static void __fuse_request_send(struct fuse_conn *fc, struct fuse_req *req) static void __fuse_request_send(struct fuse_conn *fc, struct fuse_req *req)
{ {
BUG_ON(req->background);
spin_lock(&fc->lock); spin_lock(&fc->lock);
if (!fc->connected) if (!fc->connected)
req->out.h.error = -ENOTCONN; req->out.h.error = -ENOTCONN;
...@@ -469,7 +485,7 @@ EXPORT_SYMBOL_GPL(fuse_request_send); ...@@ -469,7 +485,7 @@ EXPORT_SYMBOL_GPL(fuse_request_send);
static void fuse_request_send_nowait_locked(struct fuse_conn *fc, static void fuse_request_send_nowait_locked(struct fuse_conn *fc,
struct fuse_req *req) struct fuse_req *req)
{ {
req->background = 1; BUG_ON(!req->background);
fc->num_background++; fc->num_background++;
if (fc->num_background == fc->max_background) if (fc->num_background == fc->max_background)
fc->blocked = 1; fc->blocked = 1;
......
...@@ -126,11 +126,13 @@ static void fuse_file_put(struct fuse_file *ff, bool sync) ...@@ -126,11 +126,13 @@ static void fuse_file_put(struct fuse_file *ff, bool sync)
struct fuse_req *req = ff->reserved_req; struct fuse_req *req = ff->reserved_req;
if (sync) { if (sync) {
req->background = 0;
fuse_request_send(ff->fc, req); fuse_request_send(ff->fc, req);
path_put(&req->misc.release.path); path_put(&req->misc.release.path);
fuse_put_request(ff->fc, req); fuse_put_request(ff->fc, req);
} else { } else {
req->end = fuse_release_end; req->end = fuse_release_end;
req->background = 1;
fuse_request_send_background(ff->fc, req); fuse_request_send_background(ff->fc, req);
} }
kfree(ff); kfree(ff);
...@@ -282,6 +284,7 @@ void fuse_sync_release(struct fuse_file *ff, int flags) ...@@ -282,6 +284,7 @@ void fuse_sync_release(struct fuse_file *ff, int flags)
WARN_ON(atomic_read(&ff->count) > 1); WARN_ON(atomic_read(&ff->count) > 1);
fuse_prepare_release(ff, flags, FUSE_RELEASE); fuse_prepare_release(ff, flags, FUSE_RELEASE);
ff->reserved_req->force = 1; ff->reserved_req->force = 1;
ff->reserved_req->background = 0;
fuse_request_send(ff->fc, ff->reserved_req); fuse_request_send(ff->fc, ff->reserved_req);
fuse_put_request(ff->fc, ff->reserved_req); fuse_put_request(ff->fc, ff->reserved_req);
kfree(ff); kfree(ff);
...@@ -661,7 +664,12 @@ static int fuse_readpages_fill(void *_data, struct page *page) ...@@ -661,7 +664,12 @@ static int fuse_readpages_fill(void *_data, struct page *page)
int nr_alloc = min_t(unsigned, data->nr_pages, int nr_alloc = min_t(unsigned, data->nr_pages,
FUSE_MAX_PAGES_PER_REQ); FUSE_MAX_PAGES_PER_REQ);
fuse_send_readpages(req, data->file); fuse_send_readpages(req, data->file);
data->req = req = fuse_get_req(fc, nr_alloc); if (fc->async_read)
req = fuse_get_req_for_background(fc, nr_alloc);
else
req = fuse_get_req(fc, nr_alloc);
data->req = req;
if (IS_ERR(req)) { if (IS_ERR(req)) {
unlock_page(page); unlock_page(page);
return PTR_ERR(req); return PTR_ERR(req);
...@@ -696,7 +704,10 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, ...@@ -696,7 +704,10 @@ static int fuse_readpages(struct file *file, struct address_space *mapping,
data.file = file; data.file = file;
data.inode = inode; data.inode = inode;
data.req = fuse_get_req(fc, nr_alloc); if (fc->async_read)
data.req = fuse_get_req_for_background(fc, nr_alloc);
else
data.req = fuse_get_req(fc, nr_alloc);
data.nr_pages = nr_pages; data.nr_pages = nr_pages;
err = PTR_ERR(data.req); err = PTR_ERR(data.req);
if (IS_ERR(data.req)) if (IS_ERR(data.req))
...@@ -1375,6 +1386,7 @@ static int fuse_writepage_locked(struct page *page) ...@@ -1375,6 +1386,7 @@ static int fuse_writepage_locked(struct page *page)
if (!req) if (!req)
goto err; goto err;
req->background = 1; /* writeback always goes to bg_queue */
tmp_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM); tmp_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM);
if (!tmp_page) if (!tmp_page)
goto err_free; goto err_free;
......
...@@ -708,6 +708,8 @@ void fuse_request_free(struct fuse_req *req); ...@@ -708,6 +708,8 @@ void fuse_request_free(struct fuse_req *req);
* caller should specify # elements in req->pages[] explicitly * caller should specify # elements in req->pages[] explicitly
*/ */
struct fuse_req *fuse_get_req(struct fuse_conn *fc, unsigned npages); struct fuse_req *fuse_get_req(struct fuse_conn *fc, unsigned npages);
struct fuse_req *fuse_get_req_for_background(struct fuse_conn *fc,
unsigned npages);
/** /**
* Get a request, may fail with -ENOMEM, * Get a request, may fail with -ENOMEM,
......
...@@ -346,6 +346,7 @@ static void fuse_send_destroy(struct fuse_conn *fc) ...@@ -346,6 +346,7 @@ static void fuse_send_destroy(struct fuse_conn *fc)
fc->destroy_req = NULL; fc->destroy_req = NULL;
req->in.h.opcode = FUSE_DESTROY; req->in.h.opcode = FUSE_DESTROY;
req->force = 1; req->force = 1;
req->background = 0;
fuse_request_send(fc, req); fuse_request_send(fc, req);
fuse_put_request(fc, req); fuse_put_request(fc, req);
} }
...@@ -1043,6 +1044,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) ...@@ -1043,6 +1044,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
init_req = fuse_request_alloc(0); init_req = fuse_request_alloc(0);
if (!init_req) if (!init_req)
goto err_put_root; goto err_put_root;
init_req->background = 1;
if (is_bdev) { if (is_bdev) {
fc->destroy_req = fuse_request_alloc(0); fc->destroy_req = fuse_request_alloc(0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment