23
23
#include <linux/fs.h>
24
24
#include <linux/sysfs.h>
25
25
#include <linux/kernfs.h>
26
+ #include <linux/seq_file.h>
27
+ #include <linux/sched.h>
26
28
#include <linux/slab.h>
27
29
28
30
#include <uapi/linux/magic.h>
@@ -34,6 +36,176 @@ struct kernfs_root *rdt_root;
34
36
struct rdtgroup rdtgroup_default ;
35
37
LIST_HEAD (rdt_all_groups );
36
38
39
+ /* Kernel fs node for "info" directory under root */
40
+ static struct kernfs_node * kn_info ;
41
+
42
+ /* set uid and gid of rdtgroup dirs and files to that of the creator */
43
+ static int rdtgroup_kn_set_ugid (struct kernfs_node * kn )
44
+ {
45
+ struct iattr iattr = { .ia_valid = ATTR_UID | ATTR_GID ,
46
+ .ia_uid = current_fsuid (),
47
+ .ia_gid = current_fsgid (), };
48
+
49
+ if (uid_eq (iattr .ia_uid , GLOBAL_ROOT_UID ) &&
50
+ gid_eq (iattr .ia_gid , GLOBAL_ROOT_GID ))
51
+ return 0 ;
52
+
53
+ return kernfs_setattr (kn , & iattr );
54
+ }
55
+
56
+ static int rdtgroup_add_file (struct kernfs_node * parent_kn , struct rftype * rft )
57
+ {
58
+ struct kernfs_node * kn ;
59
+ int ret ;
60
+
61
+ kn = __kernfs_create_file (parent_kn , rft -> name , rft -> mode ,
62
+ 0 , rft -> kf_ops , rft , NULL , NULL );
63
+ if (IS_ERR (kn ))
64
+ return PTR_ERR (kn );
65
+
66
+ ret = rdtgroup_kn_set_ugid (kn );
67
+ if (ret ) {
68
+ kernfs_remove (kn );
69
+ return ret ;
70
+ }
71
+
72
+ return 0 ;
73
+ }
74
+
75
+ static int rdtgroup_add_files (struct kernfs_node * kn , struct rftype * rfts ,
76
+ int len )
77
+ {
78
+ struct rftype * rft ;
79
+ int ret ;
80
+
81
+ lockdep_assert_held (& rdtgroup_mutex );
82
+
83
+ for (rft = rfts ; rft < rfts + len ; rft ++ ) {
84
+ ret = rdtgroup_add_file (kn , rft );
85
+ if (ret )
86
+ goto error ;
87
+ }
88
+
89
+ return 0 ;
90
+ error :
91
+ pr_warn ("Failed to add %s, err=%d\n" , rft -> name , ret );
92
+ while (-- rft >= rfts )
93
+ kernfs_remove_by_name (kn , rft -> name );
94
+ return ret ;
95
+ }
96
+
97
+ static int rdtgroup_seqfile_show (struct seq_file * m , void * arg )
98
+ {
99
+ struct kernfs_open_file * of = m -> private ;
100
+ struct rftype * rft = of -> kn -> priv ;
101
+
102
+ if (rft -> seq_show )
103
+ return rft -> seq_show (of , m , arg );
104
+ return 0 ;
105
+ }
106
+
107
+ static ssize_t rdtgroup_file_write (struct kernfs_open_file * of , char * buf ,
108
+ size_t nbytes , loff_t off )
109
+ {
110
+ struct rftype * rft = of -> kn -> priv ;
111
+
112
+ if (rft -> write )
113
+ return rft -> write (of , buf , nbytes , off );
114
+
115
+ return - EINVAL ;
116
+ }
117
+
118
+ static struct kernfs_ops rdtgroup_kf_single_ops = {
119
+ .atomic_write_len = PAGE_SIZE ,
120
+ .write = rdtgroup_file_write ,
121
+ .seq_show = rdtgroup_seqfile_show ,
122
+ };
123
+
124
+ static int rdt_num_closids_show (struct kernfs_open_file * of ,
125
+ struct seq_file * seq , void * v )
126
+ {
127
+ struct rdt_resource * r = of -> kn -> parent -> priv ;
128
+
129
+ seq_printf (seq , "%d\n" , r -> num_closid );
130
+
131
+ return 0 ;
132
+ }
133
+
134
+ static int rdt_cbm_mask_show (struct kernfs_open_file * of ,
135
+ struct seq_file * seq , void * v )
136
+ {
137
+ struct rdt_resource * r = of -> kn -> parent -> priv ;
138
+
139
+ seq_printf (seq , "%x\n" , r -> max_cbm );
140
+
141
+ return 0 ;
142
+ }
143
+
144
+ /* rdtgroup information files for one cache resource. */
145
+ static struct rftype res_info_files [] = {
146
+ {
147
+ .name = "num_closids" ,
148
+ .mode = 0444 ,
149
+ .kf_ops = & rdtgroup_kf_single_ops ,
150
+ .seq_show = rdt_num_closids_show ,
151
+ },
152
+ {
153
+ .name = "cbm_mask" ,
154
+ .mode = 0444 ,
155
+ .kf_ops = & rdtgroup_kf_single_ops ,
156
+ .seq_show = rdt_cbm_mask_show ,
157
+ },
158
+ };
159
+
160
+ static int rdtgroup_create_info_dir (struct kernfs_node * parent_kn )
161
+ {
162
+ struct kernfs_node * kn_subdir ;
163
+ struct rdt_resource * r ;
164
+ int ret ;
165
+
166
+ /* create the directory */
167
+ kn_info = kernfs_create_dir (parent_kn , "info" , parent_kn -> mode , NULL );
168
+ if (IS_ERR (kn_info ))
169
+ return PTR_ERR (kn_info );
170
+ kernfs_get (kn_info );
171
+
172
+ for_each_enabled_rdt_resource (r ) {
173
+ kn_subdir = kernfs_create_dir (kn_info , r -> name ,
174
+ kn_info -> mode , r );
175
+ if (IS_ERR (kn_subdir )) {
176
+ ret = PTR_ERR (kn_subdir );
177
+ goto out_destroy ;
178
+ }
179
+ kernfs_get (kn_subdir );
180
+ ret = rdtgroup_kn_set_ugid (kn_subdir );
181
+ if (ret )
182
+ goto out_destroy ;
183
+ ret = rdtgroup_add_files (kn_subdir , res_info_files ,
184
+ ARRAY_SIZE (res_info_files ));
185
+ if (ret )
186
+ goto out_destroy ;
187
+ kernfs_activate (kn_subdir );
188
+ }
189
+
190
+ /*
191
+ * This extra ref will be put in kernfs_remove() and guarantees
192
+ * that @rdtgrp->kn is always accessible.
193
+ */
194
+ kernfs_get (kn_info );
195
+
196
+ ret = rdtgroup_kn_set_ugid (kn_info );
197
+ if (ret )
198
+ goto out_destroy ;
199
+
200
+ kernfs_activate (kn_info );
201
+
202
+ return 0 ;
203
+
204
+ out_destroy :
205
+ kernfs_remove (kn_info );
206
+ return ret ;
207
+ }
208
+
37
209
static void l3_qos_cfg_update (void * arg )
38
210
{
39
211
bool * enable = arg ;
@@ -137,6 +309,10 @@ static struct dentry *rdt_mount(struct file_system_type *fs_type,
137
309
goto out_cdp ;
138
310
}
139
311
312
+ ret = rdtgroup_create_info_dir (rdtgroup_default .kn );
313
+ if (ret )
314
+ goto out_cdp ;
315
+
140
316
dentry = kernfs_mount (fs_type , flags , rdt_root ,
141
317
RDTGROUP_SUPER_MAGIC , NULL );
142
318
if (IS_ERR (dentry ))
@@ -191,6 +367,14 @@ static int reset_all_cbms(struct rdt_resource *r)
191
367
return 0 ;
192
368
}
193
369
370
+ /*
371
+ * Forcibly remove all of subdirectories under root.
372
+ */
373
+ static void rmdir_all_sub (void )
374
+ {
375
+ kernfs_remove (kn_info );
376
+ }
377
+
194
378
static void rdt_kill_sb (struct super_block * sb )
195
379
{
196
380
struct rdt_resource * r ;
@@ -201,6 +385,7 @@ static void rdt_kill_sb(struct super_block *sb)
201
385
for_each_enabled_rdt_resource (r )
202
386
reset_all_cbms (r );
203
387
cdp_disable ();
388
+ rmdir_all_sub ();
204
389
static_branch_disable (& rdt_enable_key );
205
390
kernfs_kill_sb (sb );
206
391
mutex_unlock (& rdtgroup_mutex );
0 commit comments