aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse/file.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2008-11-26 06:03:55 -0500
committerMiklos Szeredi <miklos@szeredi.hu>2008-11-26 06:03:55 -0500
commit95668a69a4bb862063c4d28a746e55107dee7b98 (patch)
tree0679e0f43274648bad70e694a9efb8bcfed55adc /fs/fuse/file.c
parent8599396b5062bf6bd2a0b433503849e2322df1c2 (diff)
fuse: implement poll support
Implement poll support. Polled files are indexed using kh in a RB tree rooted at fuse_conn->polled_files. Client should send FUSE_NOTIFY_POLL notification once after processing FUSE_POLL which has FUSE_POLL_SCHEDULE_NOTIFY set. Sending notification unconditionally after the latest poll or everytime file content might have changed is inefficient but won't cause malfunction. fuse_file_poll() can sleep and requires patches from the following thread which allows f_op->poll() to sleep. http://thread.gmane.org/gmane.linux.kernel/726176 Signed-off-by: Tejun Heo <tj@kernel.org> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Diffstat (limited to 'fs/fuse/file.c')
-rw-r--r--fs/fuse/file.c132
1 files changed, 132 insertions, 0 deletions
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