lkml.org 
[lkml]   [2021]   [Oct]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Subject[PATCH v2 34/53] cachefiles: Provide a function to check how much space there is
    From
    Date
    Provide a function to check how much space there is.  This also flips the
    state on the cache and will signal the daemon to inform it of the change
    and to ask it to do some culling if necessary.

    Signed-off-by: David Howells <dhowells@redhat.com>
    cc: linux-cachefs@redhat.com
    ---

    fs/cachefiles/Makefile | 1
    fs/cachefiles/daemon.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++
    fs/cachefiles/internal.h | 15 ++++++
    3 files changed, 124 insertions(+)
    create mode 100644 fs/cachefiles/daemon.c

    diff --git a/fs/cachefiles/Makefile b/fs/cachefiles/Makefile
    index 183fb5f3b8b1..4c80d9af151f 100644
    --- a/fs/cachefiles/Makefile
    +++ b/fs/cachefiles/Makefile
    @@ -4,6 +4,7 @@
    #

    cachefiles-y := \
    + daemon.o \
    main.o

    cachefiles-$(CONFIG_CACHEFILES_ERROR_INJECTION) += error_inject.o
    diff --git a/fs/cachefiles/daemon.c b/fs/cachefiles/daemon.c
    new file mode 100644
    index 000000000000..dca2520a14ee
    --- /dev/null
    +++ b/fs/cachefiles/daemon.c
    @@ -0,0 +1,108 @@
    +// SPDX-License-Identifier: GPL-2.0-or-later
    +/* Daemon interface
    + *
    + * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved.
    + * Written by David Howells (dhowells@redhat.com)
    + */
    +
    +#include <linux/module.h>
    +#include <linux/init.h>
    +#include <linux/sched.h>
    +#include <linux/completion.h>
    +#include <linux/slab.h>
    +#include <linux/fs.h>
    +#include <linux/file.h>
    +#include <linux/namei.h>
    +#include <linux/poll.h>
    +#include <linux/mount.h>
    +#include <linux/statfs.h>
    +#include <linux/ctype.h>
    +#include <linux/string.h>
    +#include <linux/fs_struct.h>
    +#include "internal.h"
    +
    +/*
    + * see if we have space for a number of pages and/or a number of files in the
    + * cache
    + */
    +int cachefiles_has_space(struct cachefiles_cache *cache,
    + unsigned fnr, unsigned bnr)
    +{
    + struct kstatfs stats;
    + int ret;
    +
    + struct path path = {
    + .mnt = cache->mnt,
    + .dentry = cache->store,
    + };
    +
    + //_enter("{%llu,%llu,%llu,%llu,%llu,%llu},%u,%u",
    + // (unsigned long long) cache->frun,
    + // (unsigned long long) cache->fcull,
    + // (unsigned long long) cache->fstop,
    + // (unsigned long long) cache->brun,
    + // (unsigned long long) cache->bcull,
    + // (unsigned long long) cache->bstop,
    + // fnr, bnr);
    +
    + /* find out how many pages of blockdev are available */
    + memset(&stats, 0, sizeof(stats));
    +
    + ret = vfs_statfs(&path, &stats);
    + if (ret < 0) {
    + trace_cachefiles_vfs_error(NULL, d_inode(cache->store), ret,
    + cachefiles_trace_statfs_error);
    + if (ret == -EIO)
    + cachefiles_io_error(cache, "statfs failed");
    + _leave(" = %d", ret);
    + return ret;
    + }
    +
    + stats.f_bavail >>= cache->bshift;
    +
    + //_debug("avail %llu,%llu",
    + // (unsigned long long) stats.f_ffree,
    + // (unsigned long long) stats.f_bavail);
    +
    + /* see if there is sufficient space */
    + if (stats.f_ffree > fnr)
    + stats.f_ffree -= fnr;
    + else
    + stats.f_ffree = 0;
    +
    + if (stats.f_bavail > bnr)
    + stats.f_bavail -= bnr;
    + else
    + stats.f_bavail = 0;
    +
    + ret = -ENOBUFS;
    + if (stats.f_ffree < cache->fstop ||
    + stats.f_bavail < cache->bstop)
    + goto begin_cull;
    +
    + ret = 0;
    + if (stats.f_ffree < cache->fcull ||
    + stats.f_bavail < cache->bcull)
    + goto begin_cull;
    +
    + if (test_bit(CACHEFILES_CULLING, &cache->flags) &&
    + stats.f_ffree >= cache->frun &&
    + stats.f_bavail >= cache->brun &&
    + test_and_clear_bit(CACHEFILES_CULLING, &cache->flags)
    + ) {
    + _debug("cease culling");
    + cachefiles_state_changed(cache);
    + }
    +
    + //_leave(" = 0");
    + return 0;
    +
    +begin_cull:
    + if (!test_and_set_bit(CACHEFILES_CULLING, &cache->flags)) {
    + _debug("### CULL CACHE ###");
    + cachefiles_state_changed(cache);
    + }
    +
    + _leave(" = %d", ret);
    + return ret;
    +}
    diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h
    index 230a1a2bf01d..3ccc8411c502 100644
    --- a/fs/cachefiles/internal.h
    +++ b/fs/cachefiles/internal.h
    @@ -114,6 +114,21 @@ struct cachefiles_cache {

    #include <trace/events/cachefiles.h>

    +/*
    + * note change of state for daemon
    + */
    +static inline void cachefiles_state_changed(struct cachefiles_cache *cache)
    +{
    + set_bit(CACHEFILES_STATE_CHANGED, &cache->flags);
    + wake_up_all(&cache->daemon_pollwq);
    +}
    +
    +/*
    + * daemon.c
    + */
    +extern int cachefiles_has_space(struct cachefiles_cache *cache,
    + unsigned fnr, unsigned bnr);
    +
    /*
    * error_inject.c
    */

    \
     
     \ /
      Last update: 2021-10-22 21:09    [W:2.056 / U:0.040 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site