Skip to content

Commit a5b3a80

Browse files
dhowellsAl Viro
authored andcommitted
CacheFiles: Provide read-and-reset release counters for cachefilesd
Provide read-and-reset objects- and blocks-released counters for cachefilesd to use to work out whether there's anything new that can be culled. One of the problems cachefilesd has is that if all the objects in the cache are pinned by inodes lying dormant in the kernel inode cache, there isn't anything for it to cull. In such a case, it just spins around walking the filesystem tree and scanning for something to cull. This eats up a lot of CPU time. By telling cachefilesd if there have been any releases, the daemon can sleep until there is the possibility of something to do. cachefilesd finds this information by the following means: (1) When the control fd is read, the kernel presents a list of values of interest. "freleased=N" and "breleased=N" are added to this list to indicate the number of files released and number of blocks released since the last read call. At this point the counters are reset. (2) POLLIN is signalled if the number of files released becomes greater than 0. Note that by 'released' it just means that the kernel has released its interest in those files for the moment, not necessarily that the files should be deleted from the cache. Signed-off-by: David Howells <[email protected]> Reviewed-by: Steve Dickson <[email protected]> Signed-off-by: Al Viro <[email protected]>
1 parent 92e963f commit a5b3a80

File tree

4 files changed

+39
-17
lines changed

4 files changed

+39
-17
lines changed

fs/cachefiles/daemon.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,8 @@ static ssize_t cachefiles_daemon_read(struct file *file, char __user *_buffer,
162162
size_t buflen, loff_t *pos)
163163
{
164164
struct cachefiles_cache *cache = file->private_data;
165+
unsigned long long b_released;
166+
unsigned f_released;
165167
char buffer[256];
166168
int n;
167169

@@ -174,6 +176,8 @@ static ssize_t cachefiles_daemon_read(struct file *file, char __user *_buffer,
174176
cachefiles_has_space(cache, 0, 0);
175177

176178
/* summarise */
179+
f_released = atomic_xchg(&cache->f_released, 0);
180+
b_released = atomic_long_xchg(&cache->b_released, 0);
177181
clear_bit(CACHEFILES_STATE_CHANGED, &cache->flags);
178182

179183
n = snprintf(buffer, sizeof(buffer),
@@ -183,15 +187,18 @@ static ssize_t cachefiles_daemon_read(struct file *file, char __user *_buffer,
183187
" fstop=%llx"
184188
" brun=%llx"
185189
" bcull=%llx"
186-
" bstop=%llx",
190+
" bstop=%llx"
191+
" freleased=%x"
192+
" breleased=%llx",
187193
test_bit(CACHEFILES_CULLING, &cache->flags) ? '1' : '0',
188194
(unsigned long long) cache->frun,
189195
(unsigned long long) cache->fcull,
190196
(unsigned long long) cache->fstop,
191197
(unsigned long long) cache->brun,
192198
(unsigned long long) cache->bcull,
193-
(unsigned long long) cache->bstop
194-
);
199+
(unsigned long long) cache->bstop,
200+
f_released,
201+
b_released);
195202

196203
if (n > buflen)
197204
return -EMSGSIZE;

fs/cachefiles/interface.c

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -291,15 +291,8 @@ static void cachefiles_drop_object(struct fscache_object *_object)
291291
}
292292

293293
/* note that the object is now inactive */
294-
if (test_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags)) {
295-
write_lock(&cache->active_lock);
296-
if (!test_and_clear_bit(CACHEFILES_OBJECT_ACTIVE,
297-
&object->flags))
298-
BUG();
299-
rb_erase(&object->active_node, &cache->active_nodes);
300-
wake_up_bit(&object->flags, CACHEFILES_OBJECT_ACTIVE);
301-
write_unlock(&cache->active_lock);
302-
}
294+
if (test_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags))
295+
cachefiles_mark_object_inactive(cache, object);
303296

304297
dput(object->dentry);
305298
object->dentry = NULL;

fs/cachefiles/internal.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ struct cachefiles_cache {
6666
struct rb_root active_nodes; /* active nodes (can't be culled) */
6767
rwlock_t active_lock; /* lock for active_nodes */
6868
atomic_t gravecounter; /* graveyard uniquifier */
69+
atomic_t f_released; /* number of objects released lately */
70+
atomic_long_t b_released; /* number of blocks released lately */
6971
unsigned frun_percent; /* when to stop culling (% files) */
7072
unsigned fcull_percent; /* when to start culling (% files) */
7173
unsigned fstop_percent; /* when to stop allocating (% files) */
@@ -157,6 +159,8 @@ extern char *cachefiles_cook_key(const u8 *raw, int keylen, uint8_t type);
157159
/*
158160
* namei.c
159161
*/
162+
extern void cachefiles_mark_object_inactive(struct cachefiles_cache *cache,
163+
struct cachefiles_object *object);
160164
extern int cachefiles_delete_object(struct cachefiles_cache *cache,
161165
struct cachefiles_object *object);
162166
extern int cachefiles_walk_to_object(struct cachefiles_object *parent,

fs/cachefiles/namei.c

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,28 @@ static int cachefiles_mark_object_active(struct cachefiles_cache *cache,
257257
return -ETIMEDOUT;
258258
}
259259

260+
/*
261+
* Mark an object as being inactive.
262+
*/
263+
void cachefiles_mark_object_inactive(struct cachefiles_cache *cache,
264+
struct cachefiles_object *object)
265+
{
266+
write_lock(&cache->active_lock);
267+
rb_erase(&object->active_node, &cache->active_nodes);
268+
clear_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags);
269+
write_unlock(&cache->active_lock);
270+
271+
wake_up_bit(&object->flags, CACHEFILES_OBJECT_ACTIVE);
272+
273+
/* This object can now be culled, so we need to let the daemon know
274+
* that there is something it can remove if it needs to.
275+
*/
276+
atomic_long_add(d_backing_inode(object->dentry)->i_blocks,
277+
&cache->b_released);
278+
if (atomic_inc_return(&cache->f_released))
279+
cachefiles_state_changed(cache);
280+
}
281+
260282
/*
261283
* delete an object representation from the cache
262284
* - file backed objects are unlinked
@@ -684,11 +706,7 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent,
684706

685707
check_error:
686708
_debug("check error %d", ret);
687-
write_lock(&cache->active_lock);
688-
rb_erase(&object->active_node, &cache->active_nodes);
689-
clear_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags);
690-
wake_up_bit(&object->flags, CACHEFILES_OBJECT_ACTIVE);
691-
write_unlock(&cache->active_lock);
709+
cachefiles_mark_object_inactive(cache, object);
692710
release_dentry:
693711
dput(object->dentry);
694712
object->dentry = NULL;

0 commit comments

Comments
 (0)