cache_poll() sleeps the poller on queue_wait, which went back to being a static queue so that a poll() on a procfs channel file can't be left on the queue of a cache_detail that its network namespace freed. procfs owns the queue poll() uses now and it outlives the file, so the procfs channel files leave the poll_wait() to procfs and an upcall wakes their pollers through proc_poll_notify(). The channel entry is remembered in the cache_detail for that and forgotten before the entries are removed. The rpc_pipefs files keep sleeping on queue_wait, procfs has nothing to do with them.
Signed-off-by: Christian Brauner (Amutable) <[email protected]> --- include/linux/sunrpc/cache.h | 2 ++ net/sunrpc/cache.c | 20 +++++++++++--------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h index bf4fc543e1e5..9d508205ebb2 100644 --- a/include/linux/sunrpc/cache.h +++ b/include/linux/sunrpc/cache.h @@ -129,6 +129,8 @@ struct cache_detail { struct proc_dir_entry *procfs; struct dentry *pipefs; }; + /* the channel file in @procfs, for proc_poll_notify() */ + struct proc_dir_entry *procfs_channel; struct net *net; }; diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index d242b6f33cbc..f220a3036b6e 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -970,20 +970,18 @@ out: } /* - * Not in struct cache_detail: poll and epoll waiters stay queued until - * their file is closed, but a channel file in procfs can stay open after - * the cache_detail of its dying network namespace has been freed. + * For the rpc_pipefs channel files. Not in struct cache_detail: poll and + * epoll waiters stay queued until their file is closed, which can be after + * the cache_detail is gone. The procfs channel files are polled on the wait + * queue procfs owns for them instead, see proc_poll_notify(). */ static DECLARE_WAIT_QUEUE_HEAD(queue_wait); -static __poll_t cache_poll(struct file *filp, poll_table *wait, - struct cache_detail *cd) +static __poll_t cache_poll(struct file *filp, struct cache_detail *cd) { __poll_t mask; struct cache_reader *rp = filp->private_data; - poll_wait(filp, &queue_wait, wait); - /* alway allow write */ mask = EPOLLOUT | EPOLLWRNORM; @@ -1248,6 +1246,7 @@ static int cache_do_upcall(struct cache_detail *detail, struct cache_head *h) if (ret != -EAGAIN && detail->cache_notify) detail->cache_notify(detail, h); wake_up(&queue_wait); + proc_poll_notify(detail->procfs_channel); if (ret == -EAGAIN) { kfree(buf); kfree(crq); @@ -1593,7 +1592,7 @@ static __poll_t cache_poll_procfs(struct file *filp, poll_table *wait) { struct cache_detail *cd = pde_data(file_inode(filp)); - return cache_poll(filp, wait, cd); + return cache_poll(filp, cd); } static int cache_open_procfs(struct inode *inode, struct file *filp) @@ -1690,6 +1689,7 @@ static const struct proc_ops cache_flush_proc_ops = { static void remove_cache_proc_entries(struct cache_detail *cd) { if (cd->procfs) { + cd->procfs_channel = NULL; proc_remove(cd->procfs); cd->procfs = NULL; } @@ -1718,6 +1718,7 @@ static int create_cache_proc_entries(struct cache_detail *cd, struct net *net) &cache_channel_proc_ops, cd); if (p == NULL) goto out_nomem; + cd->procfs_channel = p; } if (cd->cache_show) { p = proc_create_data("content", S_IFREG | 0400, cd->procfs, @@ -1806,7 +1807,8 @@ static __poll_t cache_poll_pipefs(struct file *filp, poll_table *wait) { struct cache_detail *cd = RPC_I(file_inode(filp))->private; - return cache_poll(filp, wait, cd); + poll_wait(filp, &queue_wait, wait); + return cache_poll(filp, cd); } static long cache_ioctl_pipefs(struct file *filp, -- 2.53.0
