aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSeth Forshee <seth.forshee@canonical.com>2016-03-11 11:35:34 -0500
committerMiklos Szeredi <miklos@szeredi.hu>2016-03-14 10:02:51 -0400
commit744742d692e37ad5c20630e57d526c8f2e2fe3c9 (patch)
treeef5965099fadc7d4c199a104e4715256afc53e9f
parent7cabc61e01a0a8b663bd2b4c982aa53048218734 (diff)
fuse: Add reference counting for fuse_io_priv
The 'reqs' member of fuse_io_priv serves two purposes. First is to track the number of oustanding async requests to the server and to signal that the io request is completed. The second is to be a reference count on the structure to know when it can be freed. For sync io requests these purposes can be at odds. fuse_direct_IO() wants to block until the request is done, and since the signal is sent when 'reqs' reaches 0 it cannot keep a reference to the object. Yet it needs to use the object after the userspace server has completed processing requests. This leads to some handshaking and special casing that it needlessly complicated and responsible for at least one race condition. It's much cleaner and safer to maintain a separate reference count for the object lifecycle and to let 'reqs' just be a count of outstanding requests to the userspace server. Then we can know for sure when it is safe to free the object without any handshaking or special cases. The catch here is that most of the time these objects are stack allocated and should not be freed. Initializing these objects with a single reference that is never released prevents accidental attempts to free the objects. Fixes: 9d5722b7777e ("fuse: handle synchronous iocbs internally") Cc: stable@vger.kernel.org # v4.1+ Signed-off-by: Seth Forshee <seth.forshee@canonical.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
-rw-r--r--fs/fuse/cuse.c4
-rw-r--r--fs/fuse/file.c28
-rw-r--r--fs/fuse/fuse_i.h9
3 files changed, 32 insertions, 9 deletions
diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c
index 8e3ee1936c7e..c5b6b7165489 100644
--- a/fs/fuse/cuse.c
+++ b/fs/fuse/cuse.c
@@ -90,7 +90,7 @@ static struct list_head *cuse_conntbl_head(dev_t devt)
90 90
91static ssize_t cuse_read_iter(struct kiocb *kiocb, struct iov_iter *to) 91static ssize_t cuse_read_iter(struct kiocb *kiocb, struct iov_iter *to)
92{ 92{
93 struct fuse_io_priv io = { .async = 0, .file = kiocb->ki_filp }; 93 struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(kiocb->ki_filp);
94 loff_t pos = 0; 94 loff_t pos = 0;
95 95
96 return fuse_direct_io(&io, to, &pos, FUSE_DIO_CUSE); 96 return fuse_direct_io(&io, to, &pos, FUSE_DIO_CUSE);
@@ -98,7 +98,7 @@ static ssize_t cuse_read_iter(struct kiocb *kiocb, struct iov_iter *to)
98 98
99static ssize_t cuse_write_iter(struct kiocb *kiocb, struct iov_iter *from) 99static ssize_t cuse_write_iter(struct kiocb *kiocb, struct iov_iter *from)
100{ 100{
101 struct fuse_io_priv io = { .async = 0, .file = kiocb->ki_filp }; 101 struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(kiocb->ki_filp);
102 loff_t pos = 0; 102 loff_t pos = 0;
103 /* 103 /*
104 * No locking or generic_write_checks(), the server is 104 * No locking or generic_write_checks(), the server is
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 34a23df361ca..416108b42412 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -528,6 +528,11 @@ static void fuse_release_user_pages(struct fuse_req *req, int write)
528 } 528 }
529} 529}
530 530
531static void fuse_io_release(struct kref *kref)
532{
533 kfree(container_of(kref, struct fuse_io_priv, refcnt));
534}
535
531static ssize_t fuse_get_res_by_io(struct fuse_io_priv *io) 536static ssize_t fuse_get_res_by_io(struct fuse_io_priv *io)
532{ 537{
533 if (io->err) 538 if (io->err)
@@ -585,8 +590,9 @@ static void fuse_aio_complete(struct fuse_io_priv *io, int err, ssize_t pos)
585 } 590 }
586 591
587 io->iocb->ki_complete(io->iocb, res, 0); 592 io->iocb->ki_complete(io->iocb, res, 0);
588 kfree(io);
589 } 593 }
594
595 kref_put(&io->refcnt, fuse_io_release);
590} 596}
591 597
592static void fuse_aio_complete_req(struct fuse_conn *fc, struct fuse_req *req) 598static void fuse_aio_complete_req(struct fuse_conn *fc, struct fuse_req *req)
@@ -613,6 +619,7 @@ static size_t fuse_async_req_send(struct fuse_conn *fc, struct fuse_req *req,
613 size_t num_bytes, struct fuse_io_priv *io) 619 size_t num_bytes, struct fuse_io_priv *io)
614{ 620{
615 spin_lock(&io->lock); 621 spin_lock(&io->lock);
622 kref_get(&io->refcnt);
616 io->size += num_bytes; 623 io->size += num_bytes;
617 io->reqs++; 624 io->reqs++;
618 spin_unlock(&io->lock); 625 spin_unlock(&io->lock);
@@ -691,7 +698,7 @@ static void fuse_short_read(struct fuse_req *req, struct inode *inode,
691 698
692static int fuse_do_readpage(struct file *file, struct page *page) 699static int fuse_do_readpage(struct file *file, struct page *page)
693{ 700{
694 struct fuse_io_priv io = { .async = 0, .file = file }; 701 struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(file);
695 struct inode *inode = page->mapping->host; 702 struct inode *inode = page->mapping->host;
696 struct fuse_conn *fc = get_fuse_conn(inode); 703 struct fuse_conn *fc = get_fuse_conn(inode);
697 struct fuse_req *req; 704 struct fuse_req *req;
@@ -984,7 +991,7 @@ static size_t fuse_send_write_pages(struct fuse_req *req, struct file *file,
984 size_t res; 991 size_t res;
985 unsigned offset; 992 unsigned offset;
986 unsigned i; 993 unsigned i;
987 struct fuse_io_priv io = { .async = 0, .file = file }; 994 struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(file);
988 995
989 for (i = 0; i < req->num_pages; i++) 996 for (i = 0; i < req->num_pages; i++)
990 fuse_wait_on_page_writeback(inode, req->pages[i]->index); 997 fuse_wait_on_page_writeback(inode, req->pages[i]->index);
@@ -1398,7 +1405,7 @@ static ssize_t __fuse_direct_read(struct fuse_io_priv *io,
1398 1405
1399static ssize_t fuse_direct_read_iter(struct kiocb *iocb, struct iov_iter *to) 1406static ssize_t fuse_direct_read_iter(struct kiocb *iocb, struct iov_iter *to)
1400{ 1407{
1401 struct fuse_io_priv io = { .async = 0, .file = iocb->ki_filp }; 1408 struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(iocb->ki_filp);
1402 return __fuse_direct_read(&io, to, &iocb->ki_pos); 1409 return __fuse_direct_read(&io, to, &iocb->ki_pos);
1403} 1410}
1404 1411
@@ -1406,7 +1413,7 @@ static ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from)
1406{ 1413{
1407 struct file *file = iocb->ki_filp; 1414 struct file *file = iocb->ki_filp;
1408 struct inode *inode = file_inode(file); 1415 struct inode *inode = file_inode(file);
1409 struct fuse_io_priv io = { .async = 0, .file = file }; 1416 struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(file);
1410 ssize_t res; 1417 ssize_t res;
1411 1418
1412 if (is_bad_inode(inode)) 1419 if (is_bad_inode(inode))
@@ -2864,6 +2871,7 @@ fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter, loff_t offset)
2864 if (!io) 2871 if (!io)
2865 return -ENOMEM; 2872 return -ENOMEM;
2866 spin_lock_init(&io->lock); 2873 spin_lock_init(&io->lock);
2874 kref_init(&io->refcnt);
2867 io->reqs = 1; 2875 io->reqs = 1;
2868 io->bytes = -1; 2876 io->bytes = -1;
2869 io->size = 0; 2877 io->size = 0;
@@ -2887,8 +2895,14 @@ fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter, loff_t offset)
2887 iov_iter_rw(iter) == WRITE) 2895 iov_iter_rw(iter) == WRITE)
2888 io->async = false; 2896 io->async = false;
2889 2897
2890 if (io->async && is_sync) 2898 if (io->async && is_sync) {
2899 /*
2900 * Additional reference to keep io around after
2901 * calling fuse_aio_complete()
2902 */
2903 kref_get(&io->refcnt);
2891 io->done = &wait; 2904 io->done = &wait;
2905 }
2892 2906
2893 if (iov_iter_rw(iter) == WRITE) { 2907 if (iov_iter_rw(iter) == WRITE) {
2894 ret = fuse_direct_io(io, iter, &pos, FUSE_DIO_WRITE); 2908 ret = fuse_direct_io(io, iter, &pos, FUSE_DIO_WRITE);
@@ -2908,7 +2922,7 @@ fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter, loff_t offset)
2908 ret = fuse_get_res_by_io(io); 2922 ret = fuse_get_res_by_io(io);
2909 } 2923 }
2910 2924
2911 kfree(io); 2925 kref_put(&io->refcnt, fuse_io_release);
2912 2926
2913 if (iov_iter_rw(iter) == WRITE) { 2927 if (iov_iter_rw(iter) == WRITE) {
2914 if (ret > 0) 2928 if (ret > 0)
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index ce394b5fe6b4..eddbe02c4028 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -22,6 +22,7 @@
22#include <linux/rbtree.h> 22#include <linux/rbtree.h>
23#include <linux/poll.h> 23#include <linux/poll.h>
24#include <linux/workqueue.h> 24#include <linux/workqueue.h>
25#include <linux/kref.h>
25 26
26/** Max number of pages that can be used in a single read request */ 27/** Max number of pages that can be used in a single read request */
27#define FUSE_MAX_PAGES_PER_REQ 32 28#define FUSE_MAX_PAGES_PER_REQ 32
@@ -243,6 +244,7 @@ struct fuse_args {
243 244
244/** The request IO state (for asynchronous processing) */ 245/** The request IO state (for asynchronous processing) */
245struct fuse_io_priv { 246struct fuse_io_priv {
247 struct kref refcnt;
246 int async; 248 int async;
247 spinlock_t lock; 249 spinlock_t lock;
248 unsigned reqs; 250 unsigned reqs;
@@ -256,6 +258,13 @@ struct fuse_io_priv {
256 struct completion *done; 258 struct completion *done;
257}; 259};
258 260
261#define FUSE_IO_PRIV_SYNC(f) \
262{ \
263 .refcnt = { ATOMIC_INIT(1) }, \
264 .async = 0, \
265 .file = f, \
266}
267
259/** 268/**
260 * Request flags 269 * Request flags
261 * 270 *