lkml.org 
[lkml]   [2023]   [Oct]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[RFC PATCH 01/53] netfs: Add a procfile to list in-progress requests
    Date
    Add a procfile, /proc/fs/netfs/requests, to list in-progress netfslib I/O
    requests.

    Signed-off-by: David Howells <dhowells@redhat.com>
    cc: Jeff Layton <jlayton@kernel.org>
    cc: linux-cachefs@redhat.com
    cc: linux-fsdevel@vger.kernel.org
    cc: linux-mm@kvack.org
    ---
    fs/netfs/internal.h | 22 +++++++++++
    fs/netfs/main.c | 91 +++++++++++++++++++++++++++++++++++++++++++
    fs/netfs/objects.c | 4 +-
    include/linux/netfs.h | 6 ++-
    4 files changed, 121 insertions(+), 2 deletions(-)

    diff --git a/fs/netfs/internal.h b/fs/netfs/internal.h
    index 43fac1b14e40..1f067aa96c50 100644
    --- a/fs/netfs/internal.h
    +++ b/fs/netfs/internal.h
    @@ -29,6 +29,28 @@ int netfs_begin_read(struct netfs_io_request *rreq, bool sync);
    * main.c
    */
    extern unsigned int netfs_debug;
    +extern struct list_head netfs_io_requests;
    +extern spinlock_t netfs_proc_lock;
    +
    +#ifdef CONFIG_PROC_FS
    +static inline void netfs_proc_add_rreq(struct netfs_io_request *rreq)
    +{
    + spin_lock(&netfs_proc_lock);
    + list_add_tail_rcu(&rreq->proc_link, &netfs_io_requests);
    + spin_unlock(&netfs_proc_lock);
    +}
    +static inline void netfs_proc_del_rreq(struct netfs_io_request *rreq)
    +{
    + if (!list_empty(&rreq->proc_link)) {
    + spin_lock(&netfs_proc_lock);
    + list_del_rcu(&rreq->proc_link);
    + spin_unlock(&netfs_proc_lock);
    + }
    +}
    +#else
    +static inline void netfs_proc_add_rreq(struct netfs_io_request *rreq) {}
    +static inline void netfs_proc_del_rreq(struct netfs_io_request *rreq) {}
    +#endif

    /*
    * objects.c
    diff --git a/fs/netfs/main.c b/fs/netfs/main.c
    index 068568702957..21f814eee6af 100644
    --- a/fs/netfs/main.c
    +++ b/fs/netfs/main.c
    @@ -7,6 +7,8 @@

    #include <linux/module.h>
    #include <linux/export.h>
    +#include <linux/proc_fs.h>
    +#include <linux/seq_file.h>
    #include "internal.h"
    #define CREATE_TRACE_POINTS
    #include <trace/events/netfs.h>
    @@ -18,3 +20,92 @@ MODULE_LICENSE("GPL");
    unsigned netfs_debug;
    module_param_named(debug, netfs_debug, uint, S_IWUSR | S_IRUGO);
    MODULE_PARM_DESC(netfs_debug, "Netfs support debugging mask");
    +
    +#ifdef CONFIG_PROC_FS
    +LIST_HEAD(netfs_io_requests);
    +DEFINE_SPINLOCK(netfs_proc_lock);
    +
    +static const char *netfs_origins[] = {
    + [NETFS_READAHEAD] = "RA",
    + [NETFS_READPAGE] = "RP",
    + [NETFS_READ_FOR_WRITE] = "RW",
    +};
    +
    +/*
    + * Generate a list of I/O requests in /proc/fs/netfs/requests
    + */
    +static int netfs_requests_seq_show(struct seq_file *m, void *v)
    +{
    + struct netfs_io_request *rreq;
    +
    + if (v == &netfs_io_requests) {
    + seq_puts(m,
    + "REQUEST OR REF FL ERR OPS COVERAGE\n"
    + "======== == === == ==== === =========\n"
    + );
    + return 0;
    + }
    +
    + rreq = list_entry(v, struct netfs_io_request, proc_link);
    + seq_printf(m,
    + "%08x %s %3d %2lx %4d %3d @%04llx %zx/%zx",
    + rreq->debug_id,
    + netfs_origins[rreq->origin],
    + refcount_read(&rreq->ref),
    + rreq->flags,
    + rreq->error,
    + atomic_read(&rreq->nr_outstanding),
    + rreq->start, rreq->submitted, rreq->len);
    + seq_putc(m, '\n');
    + return 0;
    +}
    +
    +static void *netfs_requests_seq_start(struct seq_file *m, loff_t *_pos)
    + __acquires(rcu)
    +{
    + rcu_read_lock();
    + return seq_list_start_head(&netfs_io_requests, *_pos);
    +}
    +
    +static void *netfs_requests_seq_next(struct seq_file *m, void *v, loff_t *_pos)
    +{
    + return seq_list_next(v, &netfs_io_requests, _pos);
    +}
    +
    +static void netfs_requests_seq_stop(struct seq_file *m, void *v)
    + __releases(rcu)
    +{
    + rcu_read_unlock();
    +}
    +
    +static const struct seq_operations netfs_requests_seq_ops = {
    + .start = netfs_requests_seq_start,
    + .next = netfs_requests_seq_next,
    + .stop = netfs_requests_seq_stop,
    + .show = netfs_requests_seq_show,
    +};
    +#endif /* CONFIG_PROC_FS */
    +
    +static int __init netfs_init(void)
    +{
    + if (!proc_mkdir("fs/netfs", NULL))
    + goto error;
    +
    + if (!proc_create_seq("fs/netfs/requests", S_IFREG | 0444, NULL,
    + &netfs_requests_seq_ops))
    + goto error_proc;
    +
    + return 0;
    +
    +error_proc:
    + remove_proc_entry("fs/netfs", NULL);
    +error:
    + return -ENOMEM;
    +}
    +fs_initcall(netfs_init);
    +
    +static void __exit netfs_exit(void)
    +{
    + remove_proc_entry("fs/netfs", NULL);
    +}
    +module_exit(netfs_exit);
    diff --git a/fs/netfs/objects.c b/fs/netfs/objects.c
    index e17cdf53f6a7..85f428fc52e6 100644
    --- a/fs/netfs/objects.c
    +++ b/fs/netfs/objects.c
    @@ -45,6 +45,7 @@ struct netfs_io_request *netfs_alloc_request(struct address_space *mapping,
    }
    }

    + netfs_proc_add_rreq(rreq);
    netfs_stat(&netfs_n_rh_rreq);
    return rreq;
    }
    @@ -76,12 +77,13 @@ static void netfs_free_request(struct work_struct *work)
    container_of(work, struct netfs_io_request, work);

    trace_netfs_rreq(rreq, netfs_rreq_trace_free);
    + netfs_proc_del_rreq(rreq);
    netfs_clear_subrequests(rreq, false);
    if (rreq->netfs_ops->free_request)
    rreq->netfs_ops->free_request(rreq);
    if (rreq->cache_resources.ops)
    rreq->cache_resources.ops->end_operation(&rreq->cache_resources);
    - kfree(rreq);
    + kfree_rcu(rreq, rcu);
    netfs_stat_d(&netfs_n_rh_rreq);
    }

    diff --git a/include/linux/netfs.h b/include/linux/netfs.h
    index b11a84f6c32b..b447cb67f599 100644
    --- a/include/linux/netfs.h
    +++ b/include/linux/netfs.h
    @@ -175,10 +175,14 @@ enum netfs_io_origin {
    * operations to a variety of data stores and then stitch the result together.
    */
    struct netfs_io_request {
    - struct work_struct work;
    + union {
    + struct work_struct work;
    + struct rcu_head rcu;
    + };
    struct inode *inode; /* The file being accessed */
    struct address_space *mapping; /* The mapping being accessed */
    struct netfs_cache_resources cache_resources;
    + struct list_head proc_link; /* Link in netfs_iorequests */
    struct list_head subrequests; /* Contributory I/O operations */
    void *netfs_priv; /* Private data for the netfs */
    unsigned int debug_id;
    \
     
     \ /
      Last update: 2023-10-13 18:00    [W:7.683 / U:0.024 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site