cachefiles: pass a poll key when waking the daemon
Subsystems (3)
PATCH 1/1 cachefiles: pass a poll key when waking the daemon
Keyless wakeups bypass epoll's event-mask filtering. With only EPOLLOUT registered, any cachefiles_state_changed() call will wake up the epoll_wait() system call, but will not return any events, causing a busy loop.
Pass the relevant poll events with each wakeup so epoll can filter out unwanted notifications.
Fixes a5b3a80b899b ("CacheFiles: Provide read-and-reset release counters for cachefilesd")
Signed-off-by Max Kellermann <[email protected]>
---
Note: backports to older branches need to adjust ondemand.c as well like this:
- wake_up_all(&cache->daemon_pollwq);
+ cachefiles_wake_poll(cache, EPOLLIN);
--- fs/cachefiles/cache.c | 4 ++-- fs/cachefiles/internal.h | 15 +++++++++++++-- fs/cachefiles/namei.c | 2 +- 3 files changed, 16 insertions(+), 5 deletions(-)
fs/cachefiles/cache.c +2 -2
@@ -255,7 +255,7 @@ int cachefiles_has_space(struct cachefiles_cache *cache, test_and_clear_bit(CACHEFILES_CULLING, &cache->flags) ) {_debug ("cease culling" ); -cachefiles_state_changed (cache); +cachefiles_state_changed (cache,EPOLLIN ); }//_leave(" = 0");
@@ -275,7 +275,7 @@ int cachefiles_has_space(struct cachefiles_cache *cache, begin_cull:if (!test_and_set_bit (CACHEFILES_CULLING , &cache->flags)) {_debug ("### CULL CACHE ###" ); -cachefiles_state_changed (cache); +cachefiles_state_changed (cache,EPOLLIN |EPOLLOUT ); }_leave (" = %d" , ret);
fs/cachefiles/internal.h +13 -2
@@ -15,6 +15,7 @@#include <linux/fscache-cache.h> #include <linux/cred.h> #include <linux/security.h> +#include <linux/poll.h> #define CACHEFILES_DIO_BLOCK_SIZE 4096
@@ -117,13 +118,23 @@ struct cachefiles_object *cachefiles_cres_object(struct netfs_cache_resources *creturn fscache_cres_cookie (cres)->cache_priv; } +/* +* Wake up the daemon polling on /dev/cachefiles. +*/ +static inline void cachefiles_wake_poll (struct cachefiles_cache *cache, +__poll_t mask) +{ +__wake_up (&cache->daemon_pollwq,TASK_NORMAL ,0 ,poll_to_key (mask)); +} +/* * note change of state for daemon */ -static inline void cachefiles_state_changed (struct cachefiles_cache *cache) +static inline void cachefiles_state_changed (struct cachefiles_cache *cache, +__poll_t mask) {set_bit (CACHEFILES_STATE_CHANGED , &cache->flags); -wake_up_all (&cache->daemon_pollwq); +cachefiles_wake_poll (cache, mask); }/*
fs/cachefiles/namei.c +1 -1
@@ -74,7 +74,7 @@ void cachefiles_unmark_inode_in_use(struct cachefiles_object *object,if (!test_bit (CACHEFILES_OBJECT_USING_TMPFILE , &object->flags)) {atomic_long_add (inode->i_blocks, &cache->b_released);if (atomic_inc_return (&cache->f_released)) -cachefiles_state_changed (cache); +cachefiles_state_changed (cache,EPOLLIN ); } }
Signature · 1 line
2.47.3