aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse
diff options
context:
space:
mode:
authorMaxim Patlasov <mpatlasov@parallels.com>2012-12-14 10:20:51 -0500
committerMiklos Szeredi <mszeredi@suse.cz>2013-04-17 15:50:59 -0400
commit36cf66ed9f871fc0d0911921fba5873df3ddb2dc (patch)
tree8a449efaf4eeb9f0044258d926711d5ebb03416f /fs/fuse
parent01e9d11a3e79035ca5cd89b035435acd4ba61ee1 (diff)
fuse: make fuse_direct_io() aware about AIO
The patch implements passing "struct fuse_io_priv *io" down the stack up to fuse_send_read/write where it is used to submit request asynchronously. io->async==0 designates synchronous processing. Non-trivial part of the patch is changes in fuse_direct_io(): resources like fuse requests and user pages cannot be released immediately in async case. Signed-off-by: Maxim Patlasov <mpatlasov@parallels.com> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Diffstat (limited to 'fs/fuse')
-rw-r--r--fs/fuse/cuse.c6
-rw-r--r--fs/fuse/dev.c2
-rw-r--r--fs/fuse/file.c64
-rw-r--r--fs/fuse/fuse_i.h7
4 files changed, 58 insertions, 21 deletions
diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c
index c59c097eb2e9..b3aaf7b3578b 100644
--- a/fs/fuse/cuse.c
+++ b/fs/fuse/cuse.c
@@ -92,8 +92,9 @@ static ssize_t cuse_read(struct file *file, char __user *buf, size_t count,
92{ 92{
93 loff_t pos = 0; 93 loff_t pos = 0;
94 struct iovec iov = { .iov_base = buf, .iov_len = count }; 94 struct iovec iov = { .iov_base = buf, .iov_len = count };
95 struct fuse_io_priv io = { .async = 0, .file = file };
95 96
96 return fuse_direct_io(file, &iov, 1, count, &pos, 0); 97 return fuse_direct_io(&io, &iov, 1, count, &pos, 0);
97} 98}
98 99
99static ssize_t cuse_write(struct file *file, const char __user *buf, 100static ssize_t cuse_write(struct file *file, const char __user *buf,
@@ -101,12 +102,13 @@ static ssize_t cuse_write(struct file *file, const char __user *buf,
101{ 102{
102 loff_t pos = 0; 103 loff_t pos = 0;
103 struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = count }; 104 struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = count };
105 struct fuse_io_priv io = { .async = 0, .file = file };
104 106
105 /* 107 /*
106 * No locking or generic_write_checks(), the server is 108 * No locking or generic_write_checks(), the server is
107 * responsible for locking and sanity checks. 109 * responsible for locking and sanity checks.
108 */ 110 */
109 return fuse_direct_io(file, &iov, 1, count, &pos, 1); 111 return fuse_direct_io(&io, &iov, 1, count, &pos, 1);
110} 112}
111 113
112static int cuse_open(struct inode *inode, struct file *file) 114static int cuse_open(struct inode *inode, struct file *file)
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index be5c7e13320c..07bdb14ae7a3 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -111,7 +111,7 @@ static void restore_sigs(sigset_t *oldset)
111 sigprocmask(SIG_SETMASK, oldset, NULL); 111 sigprocmask(SIG_SETMASK, oldset, NULL);
112} 112}
113 113
114static void __fuse_get_request(struct fuse_req *req) 114void __fuse_get_request(struct fuse_req *req)
115{ 115{
116 atomic_inc(&req->count); 116 atomic_inc(&req->count);
117} 117}
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 4002889fbcc1..e207dcdf32c0 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -593,14 +593,16 @@ static size_t fuse_async_req_send(struct fuse_conn *fc, struct fuse_req *req,
593 req->io = io; 593 req->io = io;
594 req->end = fuse_aio_complete_req; 594 req->end = fuse_aio_complete_req;
595 595
596 __fuse_get_request(req);
596 fuse_request_send_background(fc, req); 597 fuse_request_send_background(fc, req);
597 598
598 return num_bytes; 599 return num_bytes;
599} 600}
600 601
601static size_t fuse_send_read(struct fuse_req *req, struct file *file, 602static size_t fuse_send_read(struct fuse_req *req, struct fuse_io_priv *io,
602 loff_t pos, size_t count, fl_owner_t owner) 603 loff_t pos, size_t count, fl_owner_t owner)
603{ 604{
605 struct file *file = io->file;
604 struct fuse_file *ff = file->private_data; 606 struct fuse_file *ff = file->private_data;
605 struct fuse_conn *fc = ff->fc; 607 struct fuse_conn *fc = ff->fc;
606 608
@@ -611,6 +613,10 @@ static size_t fuse_send_read(struct fuse_req *req, struct file *file,
611 inarg->read_flags |= FUSE_READ_LOCKOWNER; 613 inarg->read_flags |= FUSE_READ_LOCKOWNER;
612 inarg->lock_owner = fuse_lock_owner_id(fc, owner); 614 inarg->lock_owner = fuse_lock_owner_id(fc, owner);
613 } 615 }
616
617 if (io->async)
618 return fuse_async_req_send(fc, req, count, io);
619
614 fuse_request_send(fc, req); 620 fuse_request_send(fc, req);
615 return req->out.args[0].size; 621 return req->out.args[0].size;
616} 622}
@@ -631,6 +637,7 @@ static void fuse_read_update_size(struct inode *inode, loff_t size,
631 637
632static int fuse_readpage(struct file *file, struct page *page) 638static int fuse_readpage(struct file *file, struct page *page)
633{ 639{
640 struct fuse_io_priv io = { .async = 0, .file = file };
634 struct inode *inode = page->mapping->host; 641 struct inode *inode = page->mapping->host;
635 struct fuse_conn *fc = get_fuse_conn(inode); 642 struct fuse_conn *fc = get_fuse_conn(inode);
636 struct fuse_req *req; 643 struct fuse_req *req;
@@ -663,7 +670,7 @@ static int fuse_readpage(struct file *file, struct page *page)
663 req->num_pages = 1; 670 req->num_pages = 1;
664 req->pages[0] = page; 671 req->pages[0] = page;
665 req->page_descs[0].length = count; 672 req->page_descs[0].length = count;
666 num_read = fuse_send_read(req, file, pos, count, NULL); 673 num_read = fuse_send_read(req, &io, pos, count, NULL);
667 err = req->out.h.error; 674 err = req->out.h.error;
668 fuse_put_request(fc, req); 675 fuse_put_request(fc, req);
669 676
@@ -873,9 +880,10 @@ static void fuse_write_fill(struct fuse_req *req, struct fuse_file *ff,
873 req->out.args[0].value = outarg; 880 req->out.args[0].value = outarg;
874} 881}
875 882
876static size_t fuse_send_write(struct fuse_req *req, struct file *file, 883static size_t fuse_send_write(struct fuse_req *req, struct fuse_io_priv *io,
877 loff_t pos, size_t count, fl_owner_t owner) 884 loff_t pos, size_t count, fl_owner_t owner)
878{ 885{
886 struct file *file = io->file;
879 struct fuse_file *ff = file->private_data; 887 struct fuse_file *ff = file->private_data;
880 struct fuse_conn *fc = ff->fc; 888 struct fuse_conn *fc = ff->fc;
881 struct fuse_write_in *inarg = &req->misc.write.in; 889 struct fuse_write_in *inarg = &req->misc.write.in;
@@ -886,6 +894,10 @@ static size_t fuse_send_write(struct fuse_req *req, struct file *file,
886 inarg->write_flags |= FUSE_WRITE_LOCKOWNER; 894 inarg->write_flags |= FUSE_WRITE_LOCKOWNER;
887 inarg->lock_owner = fuse_lock_owner_id(fc, owner); 895 inarg->lock_owner = fuse_lock_owner_id(fc, owner);
888 } 896 }
897
898 if (io->async)
899 return fuse_async_req_send(fc, req, count, io);
900
889 fuse_request_send(fc, req); 901 fuse_request_send(fc, req);
890 return req->misc.write.out.size; 902 return req->misc.write.out.size;
891} 903}
@@ -909,11 +921,12 @@ static size_t fuse_send_write_pages(struct fuse_req *req, struct file *file,
909 size_t res; 921 size_t res;
910 unsigned offset; 922 unsigned offset;
911 unsigned i; 923 unsigned i;
924 struct fuse_io_priv io = { .async = 0, .file = file };
912 925
913 for (i = 0; i < req->num_pages; i++) 926 for (i = 0; i < req->num_pages; i++)
914 fuse_wait_on_page_writeback(inode, req->pages[i]->index); 927 fuse_wait_on_page_writeback(inode, req->pages[i]->index);
915 928
916 res = fuse_send_write(req, file, pos, count, NULL); 929 res = fuse_send_write(req, &io, pos, count, NULL);
917 930
918 offset = req->page_descs[0].offset; 931 offset = req->page_descs[0].offset;
919 count = res; 932 count = res;
@@ -1251,10 +1264,11 @@ static inline int fuse_iter_npages(const struct iov_iter *ii_p)
1251 return min(npages, FUSE_MAX_PAGES_PER_REQ); 1264 return min(npages, FUSE_MAX_PAGES_PER_REQ);
1252} 1265}
1253 1266
1254ssize_t fuse_direct_io(struct file *file, const struct iovec *iov, 1267ssize_t fuse_direct_io(struct fuse_io_priv *io, const struct iovec *iov,
1255 unsigned long nr_segs, size_t count, loff_t *ppos, 1268 unsigned long nr_segs, size_t count, loff_t *ppos,
1256 int write) 1269 int write)
1257{ 1270{
1271 struct file *file = io->file;
1258 struct fuse_file *ff = file->private_data; 1272 struct fuse_file *ff = file->private_data;
1259 struct fuse_conn *fc = ff->fc; 1273 struct fuse_conn *fc = ff->fc;
1260 size_t nmax = write ? fc->max_write : fc->max_read; 1274 size_t nmax = write ? fc->max_write : fc->max_read;
@@ -1280,11 +1294,12 @@ ssize_t fuse_direct_io(struct file *file, const struct iovec *iov,
1280 } 1294 }
1281 1295
1282 if (write) 1296 if (write)
1283 nres = fuse_send_write(req, file, pos, nbytes, owner); 1297 nres = fuse_send_write(req, io, pos, nbytes, owner);
1284 else 1298 else
1285 nres = fuse_send_read(req, file, pos, nbytes, owner); 1299 nres = fuse_send_read(req, io, pos, nbytes, owner);
1286 1300
1287 fuse_release_user_pages(req, !write); 1301 if (!io->async)
1302 fuse_release_user_pages(req, !write);
1288 if (req->out.h.error) { 1303 if (req->out.h.error) {
1289 if (!res) 1304 if (!res)
1290 res = req->out.h.error; 1305 res = req->out.h.error;
@@ -1314,16 +1329,18 @@ ssize_t fuse_direct_io(struct file *file, const struct iovec *iov,
1314} 1329}
1315EXPORT_SYMBOL_GPL(fuse_direct_io); 1330EXPORT_SYMBOL_GPL(fuse_direct_io);
1316 1331
1317static ssize_t __fuse_direct_read(struct file *file, const struct iovec *iov, 1332static ssize_t __fuse_direct_read(struct fuse_io_priv *io,
1333 const struct iovec *iov,
1318 unsigned long nr_segs, loff_t *ppos) 1334 unsigned long nr_segs, loff_t *ppos)
1319{ 1335{
1320 ssize_t res; 1336 ssize_t res;
1337 struct file *file = io->file;
1321 struct inode *inode = file_inode(file); 1338 struct inode *inode = file_inode(file);
1322 1339
1323 if (is_bad_inode(inode)) 1340 if (is_bad_inode(inode))
1324 return -EIO; 1341 return -EIO;
1325 1342
1326 res = fuse_direct_io(file, iov, nr_segs, iov_length(iov, nr_segs), 1343 res = fuse_direct_io(io, iov, nr_segs, iov_length(iov, nr_segs),
1327 ppos, 0); 1344 ppos, 0);
1328 1345
1329 fuse_invalidate_attr(inode); 1346 fuse_invalidate_attr(inode);
@@ -1334,21 +1351,24 @@ static ssize_t __fuse_direct_read(struct file *file, const struct iovec *iov,
1334static ssize_t fuse_direct_read(struct file *file, char __user *buf, 1351static ssize_t fuse_direct_read(struct file *file, char __user *buf,
1335 size_t count, loff_t *ppos) 1352 size_t count, loff_t *ppos)
1336{ 1353{
1354 struct fuse_io_priv io = { .async = 0, .file = file };
1337 struct iovec iov = { .iov_base = buf, .iov_len = count }; 1355 struct iovec iov = { .iov_base = buf, .iov_len = count };
1338 return __fuse_direct_read(file, &iov, 1, ppos); 1356 return __fuse_direct_read(&io, &iov, 1, ppos);
1339} 1357}
1340 1358
1341static ssize_t __fuse_direct_write(struct file *file, const struct iovec *iov, 1359static ssize_t __fuse_direct_write(struct fuse_io_priv *io,
1360 const struct iovec *iov,
1342 unsigned long nr_segs, loff_t *ppos) 1361 unsigned long nr_segs, loff_t *ppos)
1343{ 1362{
1363 struct file *file = io->file;
1344 struct inode *inode = file_inode(file); 1364 struct inode *inode = file_inode(file);
1345 size_t count = iov_length(iov, nr_segs); 1365 size_t count = iov_length(iov, nr_segs);
1346 ssize_t res; 1366 ssize_t res;
1347 1367
1348 res = generic_write_checks(file, ppos, &count, 0); 1368 res = generic_write_checks(file, ppos, &count, 0);
1349 if (!res) { 1369 if (!res) {
1350 res = fuse_direct_io(file, iov, nr_segs, count, ppos, 1); 1370 res = fuse_direct_io(io, iov, nr_segs, count, ppos, 1);
1351 if (res > 0) 1371 if (!io->async && res > 0)
1352 fuse_write_update_size(inode, *ppos); 1372 fuse_write_update_size(inode, *ppos);
1353 } 1373 }
1354 1374
@@ -1363,13 +1383,14 @@ static ssize_t fuse_direct_write(struct file *file, const char __user *buf,
1363 struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = count }; 1383 struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = count };
1364 struct inode *inode = file_inode(file); 1384 struct inode *inode = file_inode(file);
1365 ssize_t res; 1385 ssize_t res;
1386 struct fuse_io_priv io = { .async = 0, .file = file };
1366 1387
1367 if (is_bad_inode(inode)) 1388 if (is_bad_inode(inode))
1368 return -EIO; 1389 return -EIO;
1369 1390
1370 /* Don't allow parallel writes to the same file */ 1391 /* Don't allow parallel writes to the same file */
1371 mutex_lock(&inode->i_mutex); 1392 mutex_lock(&inode->i_mutex);
1372 res = __fuse_direct_write(file, &iov, 1, ppos); 1393 res = __fuse_direct_write(&io, &iov, 1, ppos);
1373 mutex_unlock(&inode->i_mutex); 1394 mutex_unlock(&inode->i_mutex);
1374 1395
1375 return res; 1396 return res;
@@ -2339,14 +2360,23 @@ fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
2339 ssize_t ret = 0; 2360 ssize_t ret = 0;
2340 struct file *file = NULL; 2361 struct file *file = NULL;
2341 loff_t pos = 0; 2362 loff_t pos = 0;
2363 struct fuse_io_priv *io;
2342 2364
2343 file = iocb->ki_filp; 2365 file = iocb->ki_filp;
2344 pos = offset; 2366 pos = offset;
2345 2367
2368 io = kzalloc(sizeof(struct fuse_io_priv), GFP_KERNEL);
2369 if (!io)
2370 return -ENOMEM;
2371
2372 io->file = file;
2373
2346 if (rw == WRITE) 2374 if (rw == WRITE)
2347 ret = __fuse_direct_write(file, iov, nr_segs, &pos); 2375 ret = __fuse_direct_write(io, iov, nr_segs, &pos);
2348 else 2376 else
2349 ret = __fuse_direct_read(file, iov, nr_segs, &pos); 2377 ret = __fuse_direct_read(io, iov, nr_segs, &pos);
2378
2379 kfree(io);
2350 2380
2351 return ret; 2381 return ret;
2352} 2382}
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index aea072413c47..337169a406c9 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -732,6 +732,11 @@ struct fuse_req *fuse_get_req(struct fuse_conn *fc, unsigned npages);
732struct fuse_req *fuse_get_req_for_background(struct fuse_conn *fc, 732struct fuse_req *fuse_get_req_for_background(struct fuse_conn *fc,
733 unsigned npages); 733 unsigned npages);
734 734
735/*
736 * Increment reference count on request
737 */
738void __fuse_get_request(struct fuse_req *req);
739
735/** 740/**
736 * Get a request, may fail with -ENOMEM, 741 * Get a request, may fail with -ENOMEM,
737 * useful for callers who doesn't use req->pages[] 742 * useful for callers who doesn't use req->pages[]
@@ -846,7 +851,7 @@ int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid,
846 851
847int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file, 852int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file,
848 bool isdir); 853 bool isdir);
849ssize_t fuse_direct_io(struct file *file, const struct iovec *iov, 854ssize_t fuse_direct_io(struct fuse_io_priv *io, const struct iovec *iov,
850 unsigned long nr_segs, size_t count, loff_t *ppos, 855 unsigned long nr_segs, size_t count, loff_t *ppos,
851 int write); 856 int write);
852long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, 857long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,