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: Maxim Patlasov <mpatlasov@parallels.com> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
This commit is contained in:
		
					parent
					
						
							
								4c82456eeb
							
						
					
				
			
			
				commit
				
					
						8b41e6715e
					
				
			
		
					 5 changed files with 37 additions and 5 deletions
				
			
		| 
						 | 
					@ -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)
 | 
				
			||||||
	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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	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,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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);
 | 
				
			||||||
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)
 | 
				
			||||||
		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)
 | 
				
			||||||
	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)
 | 
				
			||||||
		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,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	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)
 | 
				
			||||||
	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);
 | 
				
			||||||
 * 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)
 | 
				
			||||||
		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)
 | 
				
			||||||
	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);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue