aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/fuse/dev.c19
-rw-r--r--fs/fuse/file.c132
-rw-r--r--fs/fuse/fuse_i.h20
-rw-r--r--fs/fuse/inode.c1
-rw-r--r--include/linux/fuse.h25
5 files changed, 197 insertions, 0 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index ffd670bb8c8c..6176e444c76e 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -816,10 +816,29 @@ static ssize_t fuse_dev_read(struct kiocb *iocb, const struct iovec *iov,
816 return err; 816 return err;
817} 817}
818 818
819static int fuse_notify_poll(struct fuse_conn *fc, unsigned int size,
820 struct fuse_copy_state *cs)
821{
822 struct fuse_notify_poll_wakeup_out outarg;
823 int err;
824
825 if (size != sizeof(outarg))
826 return -EINVAL;
827
828 err = fuse_copy_one(cs, &outarg, sizeof(outarg));
829 if (err)
830 return err;
831
832 return fuse_notify_poll_wakeup(fc, &outarg);
833}
834
819static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code, 835static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code,
820 unsigned int size, struct fuse_copy_state *cs) 836 unsigned int size, struct fuse_copy_state *cs)
821{ 837{
822 switch (code) { 838 switch (code) {
839 case FUSE_NOTIFY_POLL:
840 return fuse_notify_poll(fc, size, cs);
841
823 default: 842 default:
824 return -EINVAL; 843 return -EINVAL;
825 } 844 }
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index a28ced678d38..b3a944e4bb9c 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -62,6 +62,8 @@ struct fuse_file *fuse_file_alloc(struct fuse_conn *fc)
62 ff->kh = ++fc->khctr; 62 ff->kh = ++fc->khctr;
63 spin_unlock(&fc->lock); 63 spin_unlock(&fc->lock);
64 } 64 }
65 RB_CLEAR_NODE(&ff->polled_node);
66 init_waitqueue_head(&ff->poll_wait);
65 } 67 }
66 return ff; 68 return ff;
67} 69}
@@ -170,7 +172,11 @@ int fuse_release_common(struct inode *inode, struct file *file, int isdir)
170 172
171 spin_lock(&fc->lock); 173 spin_lock(&fc->lock);
172 list_del(&ff->write_entry); 174 list_del(&ff->write_entry);
175 if (!RB_EMPTY_NODE(&ff->polled_node))
176 rb_erase(&ff->polled_node, &fc->polled_files);
173 spin_unlock(&fc->lock); 177 spin_unlock(&fc->lock);
178
179 wake_up_interruptible_sync(&ff->poll_wait);
174 /* 180 /*
175 * Normally this will send the RELEASE request, 181 * Normally this will send the RELEASE request,
176 * however if some asynchronous READ or WRITE requests 182 * however if some asynchronous READ or WRITE requests
@@ -1749,6 +1755,130 @@ static long fuse_file_compat_ioctl(struct file *file, unsigned int cmd,
1749 return fuse_file_do_ioctl(file, cmd, arg, FUSE_IOCTL_COMPAT); 1755 return fuse_file_do_ioctl(file, cmd, arg, FUSE_IOCTL_COMPAT);
1750} 1756}
1751 1757
1758/*
1759 * All files which have been polled are linked to RB tree
1760 * fuse_conn->polled_files which is indexed by kh. Walk the tree and
1761 * find the matching one.
1762 */
1763static struct rb_node **fuse_find_polled_node(struct fuse_conn *fc, u64 kh,
1764 struct rb_node **parent_out)
1765{
1766 struct rb_node **link = &fc->polled_files.rb_node;
1767 struct rb_node *last = NULL;
1768
1769 while (*link) {
1770 struct fuse_file *ff;
1771
1772 last = *link;
1773 ff = rb_entry(last, struct fuse_file, polled_node);
1774
1775 if (kh < ff->kh)
1776 link = &last->rb_left;
1777 else if (kh > ff->kh)
1778 link = &last->rb_right;
1779 else
1780 return link;
1781 }
1782
1783 if (parent_out)
1784 *parent_out = last;
1785 return link;
1786}
1787
1788/*
1789 * The file is about to be polled. Make sure it's on the polled_files
1790 * RB tree. Note that files once added to the polled_files tree are
1791 * not removed before the file is released. This is because a file
1792 * polled once is likely to be polled again.
1793 */
1794static void fuse_register_polled_file(struct fuse_conn *fc,
1795 struct fuse_file *ff)
1796{
1797 spin_lock(&fc->lock);
1798 if (RB_EMPTY_NODE(&ff->polled_node)) {
1799 struct rb_node **link, *parent;
1800
1801 link = fuse_find_polled_node(fc, ff->kh, &parent);
1802 BUG_ON(*link);
1803 rb_link_node(&ff->polled_node, parent, link);
1804 rb_insert_color(&ff->polled_node, &fc->polled_files);
1805 }
1806 spin_unlock(&fc->lock);
1807}
1808
1809static unsigned fuse_file_poll(struct file *file, poll_table *wait)
1810{
1811 struct inode *inode = file->f_dentry->d_inode;
1812 struct fuse_file *ff = file->private_data;
1813 struct fuse_conn *fc = get_fuse_conn(inode);
1814 struct fuse_poll_in inarg = { .fh = ff->fh, .kh = ff->kh };
1815 struct fuse_poll_out outarg;
1816 struct fuse_req *req;
1817 int err;
1818
1819 if (fc->no_poll)
1820 return DEFAULT_POLLMASK;
1821
1822 poll_wait(file, &ff->poll_wait, wait);
1823
1824 /*
1825 * Ask for notification iff there's someone waiting for it.
1826 * The client may ignore the flag and always notify.
1827 */
1828 if (waitqueue_active(&ff->poll_wait)) {
1829 inarg.flags |= FUSE_POLL_SCHEDULE_NOTIFY;
1830 fuse_register_polled_file(fc, ff);
1831 }
1832
1833 req = fuse_get_req(fc);
1834 if (IS_ERR(req))
1835 return PTR_ERR(req);
1836
1837 req->in.h.opcode = FUSE_POLL;
1838 req->in.h.nodeid = get_node_id(inode);
1839 req->in.numargs = 1;
1840 req->in.args[0].size = sizeof(inarg);
1841 req->in.args[0].value = &inarg;
1842 req->out.numargs = 1;
1843 req->out.args[0].size = sizeof(outarg);
1844 req->out.args[0].value = &outarg;
1845 request_send(fc, req);
1846 err = req->out.h.error;
1847 fuse_put_request(fc, req);
1848
1849 if (!err)
1850 return outarg.revents;
1851 if (err == -ENOSYS) {
1852 fc->no_poll = 1;
1853 return DEFAULT_POLLMASK;
1854 }
1855 return POLLERR;
1856}
1857
1858/*
1859 * This is called from fuse_handle_notify() on FUSE_NOTIFY_POLL and
1860 * wakes up the poll waiters.
1861 */
1862int fuse_notify_poll_wakeup(struct fuse_conn *fc,
1863 struct fuse_notify_poll_wakeup_out *outarg)
1864{
1865 u64 kh = outarg->kh;
1866 struct rb_node **link;
1867
1868 spin_lock(&fc->lock);
1869
1870 link = fuse_find_polled_node(fc, kh, NULL);
1871 if (*link) {
1872 struct fuse_file *ff;
1873
1874 ff = rb_entry(*link, struct fuse_file, polled_node);
1875 wake_up_interruptible_sync(&ff->poll_wait);
1876 }
1877
1878 spin_unlock(&fc->lock);
1879 return 0;
1880}
1881
1752static const struct file_operations fuse_file_operations = { 1882static const struct file_operations fuse_file_operations = {
1753 .llseek = fuse_file_llseek, 1883 .llseek = fuse_file_llseek,
1754 .read = do_sync_read, 1884 .read = do_sync_read,
@@ -1765,6 +1895,7 @@ static const struct file_operations fuse_file_operations = {
1765 .splice_read = generic_file_splice_read, 1895 .splice_read = generic_file_splice_read,
1766 .unlocked_ioctl = fuse_file_ioctl, 1896 .unlocked_ioctl = fuse_file_ioctl,
1767 .compat_ioctl = fuse_file_compat_ioctl, 1897 .compat_ioctl = fuse_file_compat_ioctl,
1898 .poll = fuse_file_poll,
1768}; 1899};
1769 1900
1770static const struct file_operations fuse_direct_io_file_operations = { 1901static const struct file_operations fuse_direct_io_file_operations = {
@@ -1779,6 +1910,7 @@ static const struct file_operations fuse_direct_io_file_operations = {
1779 .flock = fuse_file_flock, 1910 .flock = fuse_file_flock,
1780 .unlocked_ioctl = fuse_file_ioctl, 1911 .unlocked_ioctl = fuse_file_ioctl,
1781 .compat_ioctl = fuse_file_compat_ioctl, 1912 .compat_ioctl = fuse_file_compat_ioctl,
1913 .poll = fuse_file_poll,
1782 /* no mmap and splice_read */ 1914 /* no mmap and splice_read */
1783}; 1915};
1784 1916
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 86f013303828..986fbd4c1ff5 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -19,6 +19,8 @@
19#include <linux/backing-dev.h> 19#include <linux/backing-dev.h>
20#include <linux/mutex.h> 20#include <linux/mutex.h>
21#include <linux/rwsem.h> 21#include <linux/rwsem.h>
22#include <linux/rbtree.h>
23#include <linux/poll.h>
22 24
23/** Max number of pages that can be used in a single read request */ 25/** Max number of pages that can be used in a single read request */
24#define FUSE_MAX_PAGES_PER_REQ 32 26#define FUSE_MAX_PAGES_PER_REQ 32
@@ -111,6 +113,12 @@ struct fuse_file {
111 113
112 /** Entry on inode's write_files list */ 114 /** Entry on inode's write_files list */
113 struct list_head write_entry; 115 struct list_head write_entry;
116
117 /** RB node to be linked on fuse_conn->polled_files */
118 struct rb_node polled_node;
119
120 /** Wait queue head for poll */
121 wait_queue_head_t poll_wait;
114}; 122};
115 123
116/** One input argument of a request */ 124/** One input argument of a request */
@@ -328,6 +336,9 @@ struct fuse_conn {
328 /** The next unique kernel file handle */ 336 /** The next unique kernel file handle */
329 u64 khctr; 337 u64 khctr;
330 338
339 /** rbtree of fuse_files waiting for poll events indexed by ph */
340 struct rb_root polled_files;
341
331 /** Number of requests currently in the background */ 342 /** Number of requests currently in the background */
332 unsigned num_background; 343 unsigned num_background;
333 344
@@ -416,6 +427,9 @@ struct fuse_conn {
416 /** Is bmap not implemented by fs? */ 427 /** Is bmap not implemented by fs? */
417 unsigned no_bmap:1; 428 unsigned no_bmap:1;
418 429
430 /** Is poll not implemented by fs? */
431 unsigned no_poll:1;
432
419 /** Do multi-page cached writes */ 433 /** Do multi-page cached writes */
420 unsigned big_writes:1; 434 unsigned big_writes:1;
421 435
@@ -525,6 +539,12 @@ int fuse_fsync_common(struct file *file, struct dentry *de, int datasync,
525 int isdir); 539 int isdir);
526 540
527/** 541/**
542 * Notify poll wakeup
543 */
544int fuse_notify_poll_wakeup(struct fuse_conn *fc,
545 struct fuse_notify_poll_wakeup_out *outarg);
546
547/**
528 * Initialize file operations on a regular file 548 * Initialize file operations on a regular file
529 */ 549 */
530void fuse_init_file_inode(struct inode *inode); 550void fuse_init_file_inode(struct inode *inode);
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 0e15bc221d23..ba7256128084 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -486,6 +486,7 @@ static struct fuse_conn *new_conn(struct super_block *sb)
486 /* fuse does it's own writeback accounting */ 486 /* fuse does it's own writeback accounting */
487 fc->bdi.capabilities = BDI_CAP_NO_ACCT_WB; 487 fc->bdi.capabilities = BDI_CAP_NO_ACCT_WB;
488 fc->khctr = 0; 488 fc->khctr = 0;
489 fc->polled_files = RB_ROOT;
489 fc->dev = sb->s_dev; 490 fc->dev = sb->s_dev;
490 err = bdi_init(&fc->bdi); 491 err = bdi_init(&fc->bdi);
491 if (err) 492 if (err)
diff --git a/include/linux/fuse.h b/include/linux/fuse.h
index abde9949e2c0..5650cf033e73 100644
--- a/include/linux/fuse.h
+++ b/include/linux/fuse.h
@@ -163,6 +163,13 @@ struct fuse_file_lock {
163 163
164#define FUSE_IOCTL_MAX_IOV 256 164#define FUSE_IOCTL_MAX_IOV 256
165 165
166/**
167 * Poll flags
168 *
169 * FUSE_POLL_SCHEDULE_NOTIFY: request poll notify
170 */
171#define FUSE_POLL_SCHEDULE_NOTIFY (1 << 0)
172
166enum fuse_opcode { 173enum fuse_opcode {
167 FUSE_LOOKUP = 1, 174 FUSE_LOOKUP = 1,
168 FUSE_FORGET = 2, /* no reply */ 175 FUSE_FORGET = 2, /* no reply */
@@ -201,9 +208,11 @@ enum fuse_opcode {
201 FUSE_BMAP = 37, 208 FUSE_BMAP = 37,
202 FUSE_DESTROY = 38, 209 FUSE_DESTROY = 38,
203 FUSE_IOCTL = 39, 210 FUSE_IOCTL = 39,
211 FUSE_POLL = 40,
204}; 212};
205 213
206enum fuse_notify_code { 214enum fuse_notify_code {
215 FUSE_NOTIFY_POLL = 1,
207 FUSE_NOTIFY_CODE_MAX, 216 FUSE_NOTIFY_CODE_MAX,
208}; 217};
209 218
@@ -421,6 +430,22 @@ struct fuse_ioctl_out {
421 __u32 out_iovs; 430 __u32 out_iovs;
422}; 431};
423 432
433struct fuse_poll_in {
434 __u64 fh;
435 __u64 kh;
436 __u32 flags;
437 __u32 padding;
438};
439
440struct fuse_poll_out {
441 __u32 revents;
442 __u32 padding;
443};
444
445struct fuse_notify_poll_wakeup_out {
446 __u64 kh;
447};
448
424struct fuse_in_header { 449struct fuse_in_header {
425 __u32 len; 450 __u32 len;
426 __u32 opcode; 451 __u32 opcode;