lkml.org 
[lkml]   [2021]   [Dec]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Subject[PATCH v4 15/68] fscache: Provide and use cache methods to lookup/create/free a volume
    From
    Date
    Add cache methods to lookup, create and remove a volume.

    Looking up or creating the volume requires the cache pinning for access;
    freeing the volume requires the volume pinning for access. The
    ->acquire_volume() method is used to ask the cache backend to lookup and,
    if necessary, create a volume; the ->free_volume() method is used to free
    the resources for a volume.

    Signed-off-by: David Howells <dhowells@redhat.com>
    Reviewed-by: Jeff Layton <jlayton@kernel.org>
    cc: linux-cachefs@redhat.com
    Link: https://lore.kernel.org/r/163819597821.215744.5225318658134989949.stgit@warthog.procyon.org.uk/ # v1
    Link: https://lore.kernel.org/r/163906898645.143852.8537799955945956818.stgit@warthog.procyon.org.uk/ # v2
    Link: https://lore.kernel.org/r/163967099771.1823006.1455197910571061835.stgit@warthog.procyon.org.uk/ # v3
    ---

    fs/fscache/volume.c | 89 +++++++++++++++++++++++++++++++++++++++-
    include/linux/fscache-cache.h | 7 +++
    include/trace/events/fscache.h | 11 ++++-
    3 files changed, 103 insertions(+), 4 deletions(-)

    diff --git a/fs/fscache/volume.c b/fs/fscache/volume.c
    index 20497f0f10bb..e1a8e92a6adb 100644
    --- a/fs/fscache/volume.c
    +++ b/fs/fscache/volume.c
    @@ -15,6 +15,8 @@ static struct hlist_bl_head fscache_volume_hash[1 << fscache_volume_hash_shift];
    static atomic_t fscache_volume_debug_id;
    static LIST_HEAD(fscache_volumes);

    +static void fscache_create_volume_work(struct work_struct *work);
    +
    struct fscache_volume *fscache_get_volume(struct fscache_volume *volume,
    enum fscache_volume_trace where)
    {
    @@ -213,7 +215,7 @@ static struct fscache_volume *fscache_alloc_volume(const char *volume_key,

    volume->cache = cache;
    INIT_LIST_HEAD(&volume->proc_link);
    - INIT_WORK(&volume->work, NULL /* PLACEHOLDER */);
    + INIT_WORK(&volume->work, fscache_create_volume_work);
    refcount_set(&volume->ref, 1);
    spin_lock_init(&volume->lock);

    @@ -249,6 +251,58 @@ static struct fscache_volume *fscache_alloc_volume(const char *volume_key,
    return NULL;
    }

    +/*
    + * Create a volume's representation on disk. Have a volume ref and a cache
    + * access we have to release.
    + */
    +static void fscache_create_volume_work(struct work_struct *work)
    +{
    + const struct fscache_cache_ops *ops;
    + struct fscache_volume *volume =
    + container_of(work, struct fscache_volume, work);
    +
    + fscache_see_volume(volume, fscache_volume_see_create_work);
    +
    + ops = volume->cache->ops;
    + if (ops->acquire_volume)
    + ops->acquire_volume(volume);
    + fscache_end_cache_access(volume->cache,
    + fscache_access_acquire_volume_end);
    +
    + clear_bit_unlock(FSCACHE_VOLUME_CREATING, &volume->flags);
    + wake_up_bit(&volume->flags, FSCACHE_VOLUME_CREATING);
    + fscache_put_volume(volume, fscache_volume_put_create_work);
    +}
    +
    +/*
    + * Dispatch a worker thread to create a volume's representation on disk.
    + */
    +void fscache_create_volume(struct fscache_volume *volume, bool wait)
    +{
    + if (test_and_set_bit(FSCACHE_VOLUME_CREATING, &volume->flags))
    + goto maybe_wait;
    + if (volume->cache_priv)
    + goto no_wait; /* We raced */
    + if (!fscache_begin_cache_access(volume->cache,
    + fscache_access_acquire_volume))
    + goto no_wait;
    +
    + fscache_get_volume(volume, fscache_volume_get_create_work);
    + if (!schedule_work(&volume->work))
    + fscache_put_volume(volume, fscache_volume_put_create_work);
    +
    +maybe_wait:
    + if (wait) {
    + fscache_see_volume(volume, fscache_volume_wait_create_work);
    + wait_on_bit(&volume->flags, FSCACHE_VOLUME_CREATING,
    + TASK_UNINTERRUPTIBLE);
    + }
    + return;
    +no_wait:
    + clear_bit_unlock(FSCACHE_VOLUME_CREATING, &volume->flags);
    + wake_up_bit(&volume->flags, FSCACHE_VOLUME_CREATING);
    +}
    +
    /*
    * Acquire a volume representation cookie and link it to a (proposed) cache.
    */
    @@ -269,7 +323,7 @@ struct fscache_volume *__fscache_acquire_volume(const char *volume_key,
    return ERR_PTR(-EBUSY);
    }

    - // PLACEHOLDER: Create the volume if we have a cache available
    + fscache_create_volume(volume, false);
    return volume;
    }
    EXPORT_SYMBOL(__fscache_acquire_volume);
    @@ -316,7 +370,12 @@ static void fscache_free_volume(struct fscache_volume *volume)
    struct fscache_cache *cache = volume->cache;

    if (volume->cache_priv) {
    - // PLACEHOLDER: Detach any attached cache
    + __fscache_begin_volume_access(volume, NULL,
    + fscache_access_relinquish_volume);
    + if (volume->cache_priv)
    + cache->ops->free_volume(volume);
    + fscache_end_volume_access(volume, NULL,
    + fscache_access_relinquish_volume_end);
    }

    down_write(&fscache_addremove_sem);
    @@ -369,6 +428,30 @@ void __fscache_relinquish_volume(struct fscache_volume *volume,
    }
    EXPORT_SYMBOL(__fscache_relinquish_volume);

    +/**
    + * fscache_withdraw_volume - Withdraw a volume from being cached
    + * @volume: Volume cookie
    + *
    + * Withdraw a cache volume from service, waiting for all accesses to complete
    + * before returning.
    + */
    +void fscache_withdraw_volume(struct fscache_volume *volume)
    +{
    + int n_accesses;
    +
    + _debug("withdraw V=%x", volume->debug_id);
    +
    + /* Allow wakeups on dec-to-0 */
    + n_accesses = atomic_dec_return(&volume->n_accesses);
    + trace_fscache_access_volume(volume->debug_id, 0,
    + refcount_read(&volume->ref),
    + n_accesses, fscache_access_cache_unpin);
    +
    + wait_var_event(&volume->n_accesses,
    + atomic_read(&volume->n_accesses) == 0);
    +}
    +EXPORT_SYMBOL(fscache_withdraw_volume);
    +
    #ifdef CONFIG_PROC_FS
    /*
    * Generate a list of volumes in /proc/fs/fscache/volumes
    diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h
    index f78add6e7823..a10b66ca3544 100644
    --- a/include/linux/fscache-cache.h
    +++ b/include/linux/fscache-cache.h
    @@ -51,6 +51,12 @@ struct fscache_cache {
    struct fscache_cache_ops {
    /* name of cache provider */
    const char *name;
    +
    + /* Acquire a volume */
    + void (*acquire_volume)(struct fscache_volume *volume);
    +
    + /* Free the cache's data attached to a volume */
    + void (*free_volume)(struct fscache_volume *volume);
    };

    extern struct workqueue_struct *fscache_wq;
    @@ -65,6 +71,7 @@ extern int fscache_add_cache(struct fscache_cache *cache,
    const struct fscache_cache_ops *ops,
    void *cache_priv);
    extern void fscache_withdraw_cache(struct fscache_cache *cache);
    +extern void fscache_withdraw_volume(struct fscache_volume *volume);

    extern void fscache_end_volume_access(struct fscache_volume *volume,
    struct fscache_cookie *cookie,
    diff --git a/include/trace/events/fscache.h b/include/trace/events/fscache.h
    index b1a962adfd16..1d576bd8112e 100644
    --- a/include/trace/events/fscache.h
    +++ b/include/trace/events/fscache.h
    @@ -64,8 +64,12 @@ enum fscache_cookie_trace {
    };

    enum fscache_access_trace {
    + fscache_access_acquire_volume,
    + fscache_access_acquire_volume_end,
    fscache_access_cache_pin,
    fscache_access_cache_unpin,
    + fscache_access_relinquish_volume,
    + fscache_access_relinquish_volume_end,
    fscache_access_unlive,
    };

    @@ -96,7 +100,8 @@ enum fscache_access_trace {
    EM(fscache_volume_put_hash_collision, "PUT hcoll") \
    EM(fscache_volume_put_relinquish, "PUT relnq") \
    EM(fscache_volume_see_create_work, "SEE creat") \
    - E_(fscache_volume_see_hash_wake, "SEE hwake")
    + EM(fscache_volume_see_hash_wake, "SEE hwake") \
    + E_(fscache_volume_wait_create_work, "WAIT crea")

    #define fscache_cookie_traces \
    EM(fscache_cookie_collision, "*COLLIDE*") \
    @@ -115,8 +120,12 @@ enum fscache_access_trace {
    E_(fscache_cookie_see_work, "- work ")

    #define fscache_access_traces \
    + EM(fscache_access_acquire_volume, "BEGIN acq_vol") \
    + EM(fscache_access_acquire_volume_end, "END acq_vol") \
    EM(fscache_access_cache_pin, "PIN cache ") \
    EM(fscache_access_cache_unpin, "UNPIN cache ") \
    + EM(fscache_access_relinquish_volume, "BEGIN rlq_vol") \
    + EM(fscache_access_relinquish_volume_end,"END rlq_vol") \
    E_(fscache_access_unlive, "END unlive ")

    /*

    \
     
     \ /
      Last update: 2021-12-23 00:18    [W:6.661 / U:0.112 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site