xref: /linux/fs/netfs/main.c (revision 13b6931c44969ff057ad2a3aa1c20a1b28b79b6f)
1  // SPDX-License-Identifier: GPL-2.0-or-later
2  /* Miscellaneous bits for the netfs support library.
3   *
4   * Copyright (C) 2022 Red Hat, Inc. All Rights Reserved.
5   * Written by David Howells (dhowells@redhat.com)
6   */
7  
8  #include <linux/module.h>
9  #include <linux/export.h>
10  #include <linux/mempool.h>
11  #include <linux/proc_fs.h>
12  #include <linux/seq_file.h>
13  #include "internal.h"
14  #define CREATE_TRACE_POINTS
15  #include <trace/events/netfs.h>
16  
17  MODULE_DESCRIPTION("Network fs support");
18  MODULE_AUTHOR("Red Hat, Inc.");
19  MODULE_LICENSE("GPL");
20  
21  EXPORT_TRACEPOINT_SYMBOL(netfs_sreq);
22  
23  unsigned netfs_debug;
24  module_param_named(debug, netfs_debug, uint, S_IWUSR | S_IRUGO);
25  MODULE_PARM_DESC(netfs_debug, "Netfs support debugging mask");
26  
27  static struct kmem_cache *netfs_request_slab;
28  static struct kmem_cache *netfs_subrequest_slab;
29  mempool_t netfs_request_pool;
30  mempool_t netfs_subrequest_pool;
31  
32  #ifdef CONFIG_PROC_FS
33  LIST_HEAD(netfs_io_requests);
34  DEFINE_SPINLOCK(netfs_proc_lock);
35  
36  static const char *netfs_origins[nr__netfs_io_origin] = {
37  	[NETFS_READAHEAD]		= "RA",
38  	[NETFS_READPAGE]		= "RP",
39  	[NETFS_READ_GAPS]		= "RG",
40  	[NETFS_READ_SINGLE]		= "R1",
41  	[NETFS_READ_FOR_WRITE]		= "RW",
42  	[NETFS_DIO_READ]		= "DR",
43  	[NETFS_WRITEBACK]		= "WB",
44  	[NETFS_WRITEBACK_SINGLE]	= "W1",
45  	[NETFS_WRITETHROUGH]		= "WT",
46  	[NETFS_UNBUFFERED_WRITE]	= "UW",
47  	[NETFS_DIO_WRITE]		= "DW",
48  	[NETFS_PGPRIV2_COPY_TO_CACHE]	= "2C",
49  };
50  
51  /*
52   * Generate a list of I/O requests in /proc/fs/netfs/requests
53   */
54  static int netfs_requests_seq_show(struct seq_file *m, void *v)
55  {
56  	struct netfs_io_request *rreq;
57  
58  	if (v == &netfs_io_requests) {
59  		seq_puts(m,
60  			 "REQUEST  OR REF FL ERR  OPS COVERAGE\n"
61  			 "======== == === == ==== === =========\n"
62  			 );
63  		return 0;
64  	}
65  
66  	rreq = list_entry(v, struct netfs_io_request, proc_link);
67  	seq_printf(m,
68  		   "%08x %s %3d %2lx %4ld %3d @%04llx %llx/%llx",
69  		   rreq->debug_id,
70  		   netfs_origins[rreq->origin],
71  		   refcount_read(&rreq->ref),
72  		   rreq->flags,
73  		   rreq->error,
74  		   0,
75  		   rreq->start, rreq->submitted, rreq->len);
76  	seq_putc(m, '\n');
77  	return 0;
78  }
79  
80  static void *netfs_requests_seq_start(struct seq_file *m, loff_t *_pos)
81  	__acquires(rcu)
82  {
83  	rcu_read_lock();
84  	return seq_list_start_head(&netfs_io_requests, *_pos);
85  }
86  
87  static void *netfs_requests_seq_next(struct seq_file *m, void *v, loff_t *_pos)
88  {
89  	return seq_list_next(v, &netfs_io_requests, _pos);
90  }
91  
92  static void netfs_requests_seq_stop(struct seq_file *m, void *v)
93  	__releases(rcu)
94  {
95  	rcu_read_unlock();
96  }
97  
98  static const struct seq_operations netfs_requests_seq_ops = {
99  	.start  = netfs_requests_seq_start,
100  	.next   = netfs_requests_seq_next,
101  	.stop   = netfs_requests_seq_stop,
102  	.show   = netfs_requests_seq_show,
103  };
104  #endif /* CONFIG_PROC_FS */
105  
106  static int __init netfs_init(void)
107  {
108  	int ret = -ENOMEM;
109  
110  	netfs_request_slab = kmem_cache_create("netfs_request",
111  					       sizeof(struct netfs_io_request), 0,
112  					       SLAB_HWCACHE_ALIGN | SLAB_ACCOUNT,
113  					       NULL);
114  	if (!netfs_request_slab)
115  		goto error_req;
116  
117  	if (mempool_init_slab_pool(&netfs_request_pool, 100, netfs_request_slab) < 0)
118  		goto error_reqpool;
119  
120  	netfs_subrequest_slab = kmem_cache_create("netfs_subrequest",
121  						  sizeof(struct netfs_io_subrequest) + 16, 0,
122  						  SLAB_HWCACHE_ALIGN | SLAB_ACCOUNT,
123  						  NULL);
124  	if (!netfs_subrequest_slab)
125  		goto error_subreq;
126  
127  	if (mempool_init_slab_pool(&netfs_subrequest_pool, 100, netfs_subrequest_slab) < 0)
128  		goto error_subreqpool;
129  
130  	if (!proc_mkdir("fs/netfs", NULL))
131  		goto error_proc;
132  	if (!proc_create_seq("fs/netfs/requests", S_IFREG | 0444, NULL,
133  			     &netfs_requests_seq_ops))
134  		goto error_procfile;
135  #ifdef CONFIG_FSCACHE_STATS
136  	if (!proc_create_single("fs/netfs/stats", S_IFREG | 0444, NULL,
137  				netfs_stats_show))
138  		goto error_procfile;
139  #endif
140  
141  	ret = fscache_init();
142  	if (ret < 0)
143  		goto error_fscache;
144  	return 0;
145  
146  error_fscache:
147  error_procfile:
148  	remove_proc_subtree("fs/netfs", NULL);
149  error_proc:
150  	mempool_exit(&netfs_subrequest_pool);
151  error_subreqpool:
152  	kmem_cache_destroy(netfs_subrequest_slab);
153  error_subreq:
154  	mempool_exit(&netfs_request_pool);
155  error_reqpool:
156  	kmem_cache_destroy(netfs_request_slab);
157  error_req:
158  	return ret;
159  }
160  fs_initcall(netfs_init);
161  
162  static void __exit netfs_exit(void)
163  {
164  	fscache_exit();
165  	remove_proc_subtree("fs/netfs", NULL);
166  	mempool_exit(&netfs_subrequest_pool);
167  	kmem_cache_destroy(netfs_subrequest_slab);
168  	mempool_exit(&netfs_request_pool);
169  	kmem_cache_destroy(netfs_request_slab);
170  }
171  module_exit(netfs_exit);
172