fuse: make request allocations for background processing explicit
authorMaxim Patlasov <mpatlasov@parallels.com>
Thu, 21 Mar 2013 14:02:04 +0000 (18:02 +0400)
committerMiklos Szeredi <mszeredi@suse.cz>
Wed, 17 Apr 2013 10:31:44 +0000 (12:31 +0200)
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>
fs/fuse/cuse.c
fs/fuse/dev.c
fs/fuse/file.c
fs/fuse/fuse_i.h
fs/fuse/inode.c

index 6f96a8d..b7c7f30 100644 (file)
@@ -422,7 +422,7 @@ static int cuse_send_init(struct cuse_conn *cc)
 
        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)) {
                rc = PTR_ERR(req);
                goto err;
index 11dfa0c..3b8301f 100644 (file)
@@ -130,7 +130,8 @@ static void fuse_req_init_context(struct fuse_req *req)
        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;
        sigset_t oldset;
@@ -156,14 +157,27 @@ struct fuse_req *fuse_get_req(struct fuse_conn *fc, unsigned npages)
 
        fuse_req_init_context(req);
        req->waiting = 1;
+       req->background = for_background;
        return req;
 
  out:
        atomic_dec(&fc->num_waiting);
        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);
 
+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
  * 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);
        req->waiting = 1;
+       req->background = 0;
        return req;
 }
 
@@ -442,6 +457,7 @@ __acquires(fc->lock)
 
 static void __fuse_request_send(struct fuse_conn *fc, struct fuse_req *req)
 {
+       BUG_ON(req->background);
        spin_lock(&fc->lock);
        if (!fc->connected)
                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,
                                            struct fuse_req *req)
 {
-       req->background = 1;
+       BUG_ON(!req->background);
        fc->num_background++;
        if (fc->num_background == fc->max_background)
                fc->blocked = 1;
index 34b80ba..4884790 100644 (file)
@@ -126,11 +126,13 @@ static void fuse_file_put(struct fuse_file *ff, bool sync)
                struct fuse_req *req = ff->reserved_req;
 
                if (sync) {
+                       req->background = 0;
                        fuse_request_send(ff->fc, req);
                        path_put(&req->misc.release.path);
                        fuse_put_request(ff->fc, req);
                } else {
                        req->end = fuse_release_end;
+                       req->background = 1;
                        fuse_request_send_background(ff->fc, req);
                }
                kfree(ff);
@@ -282,6 +284,7 @@ void fuse_sync_release(struct fuse_file *ff, int flags)
        WARN_ON(atomic_read(&ff->count) > 1);
        fuse_prepare_release(ff, flags, FUSE_RELEASE);
        ff->reserved_req->force = 1;
+       ff->reserved_req->background = 0;
        fuse_request_send(ff->fc, ff->reserved_req);
        fuse_put_request(ff->fc, ff->reserved_req);
        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,
                                     FUSE_MAX_PAGES_PER_REQ);
                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)) {
                        unlock_page(page);
                        return PTR_ERR(req);
@@ -696,7 +704,10 @@ static int fuse_readpages(struct file *file, struct address_space *mapping,
 
        data.file = file;
        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;
        err = PTR_ERR(data.req);
        if (IS_ERR(data.req))
@@ -1375,6 +1386,7 @@ static int fuse_writepage_locked(struct page *page)
        if (!req)
                goto err;
 
+       req->background = 1; /* writeback always goes to bg_queue */
        tmp_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM);
        if (!tmp_page)
                goto err_free;
index 6aeba86..47c94d2 100644 (file)
@@ -708,6 +708,8 @@ void fuse_request_free(struct fuse_req *req);
  * 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_for_background(struct fuse_conn *fc,
+                                            unsigned npages);
 
 /**
  * Get a request, may fail with -ENOMEM,
index 137185c..e26607d 100644 (file)
@@ -346,6 +346,7 @@ static void fuse_send_destroy(struct fuse_conn *fc)
                fc->destroy_req = NULL;
                req->in.h.opcode = FUSE_DESTROY;
                req->force = 1;
+               req->background = 0;
                fuse_request_send(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);
        if (!init_req)
                goto err_put_root;
+       init_req->background = 1;
 
        if (is_bdev) {
                fc->destroy_req = fuse_request_alloc(0);