@@ -113,12 +113,220 @@ static struct kobj_type damon_sysfs_ul_range_ktype = {
113
113
.default_groups = damon_sysfs_ul_range_groups ,
114
114
};
115
115
116
+ /*
117
+ * init region directory
118
+ */
119
+
120
+ struct damon_sysfs_region {
121
+ struct kobject kobj ;
122
+ unsigned long start ;
123
+ unsigned long end ;
124
+ };
125
+
126
+ static struct damon_sysfs_region * damon_sysfs_region_alloc (
127
+ unsigned long start ,
128
+ unsigned long end )
129
+ {
130
+ struct damon_sysfs_region * region = kmalloc (sizeof (* region ),
131
+ GFP_KERNEL );
132
+
133
+ if (!region )
134
+ return NULL ;
135
+ region -> kobj = (struct kobject ){};
136
+ region -> start = start ;
137
+ region -> end = end ;
138
+ return region ;
139
+ }
140
+
141
+ static ssize_t start_show (struct kobject * kobj , struct kobj_attribute * attr ,
142
+ char * buf )
143
+ {
144
+ struct damon_sysfs_region * region = container_of (kobj ,
145
+ struct damon_sysfs_region , kobj );
146
+
147
+ return sysfs_emit (buf , "%lu\n" , region -> start );
148
+ }
149
+
150
+ static ssize_t start_store (struct kobject * kobj , struct kobj_attribute * attr ,
151
+ const char * buf , size_t count )
152
+ {
153
+ struct damon_sysfs_region * region = container_of (kobj ,
154
+ struct damon_sysfs_region , kobj );
155
+ int err = kstrtoul (buf , 0 , & region -> start );
156
+
157
+ if (err )
158
+ return - EINVAL ;
159
+ return count ;
160
+ }
161
+
162
+ static ssize_t end_show (struct kobject * kobj , struct kobj_attribute * attr ,
163
+ char * buf )
164
+ {
165
+ struct damon_sysfs_region * region = container_of (kobj ,
166
+ struct damon_sysfs_region , kobj );
167
+
168
+ return sysfs_emit (buf , "%lu\n" , region -> end );
169
+ }
170
+
171
+ static ssize_t end_store (struct kobject * kobj , struct kobj_attribute * attr ,
172
+ const char * buf , size_t count )
173
+ {
174
+ struct damon_sysfs_region * region = container_of (kobj ,
175
+ struct damon_sysfs_region , kobj );
176
+ int err = kstrtoul (buf , 0 , & region -> end );
177
+
178
+ if (err )
179
+ return - EINVAL ;
180
+ return count ;
181
+ }
182
+
183
+ static void damon_sysfs_region_release (struct kobject * kobj )
184
+ {
185
+ kfree (container_of (kobj , struct damon_sysfs_region , kobj ));
186
+ }
187
+
188
+ static struct kobj_attribute damon_sysfs_region_start_attr =
189
+ __ATTR_RW_MODE (start , 0600 );
190
+
191
+ static struct kobj_attribute damon_sysfs_region_end_attr =
192
+ __ATTR_RW_MODE (end , 0600 );
193
+
194
+ static struct attribute * damon_sysfs_region_attrs [] = {
195
+ & damon_sysfs_region_start_attr .attr ,
196
+ & damon_sysfs_region_end_attr .attr ,
197
+ NULL ,
198
+ };
199
+ ATTRIBUTE_GROUPS (damon_sysfs_region );
200
+
201
+ static struct kobj_type damon_sysfs_region_ktype = {
202
+ .release = damon_sysfs_region_release ,
203
+ .sysfs_ops = & kobj_sysfs_ops ,
204
+ .default_groups = damon_sysfs_region_groups ,
205
+ };
206
+
207
+ /*
208
+ * init_regions directory
209
+ */
210
+
211
+ struct damon_sysfs_regions {
212
+ struct kobject kobj ;
213
+ struct damon_sysfs_region * * regions_arr ;
214
+ int nr ;
215
+ };
216
+
217
+ static struct damon_sysfs_regions * damon_sysfs_regions_alloc (void )
218
+ {
219
+ return kzalloc (sizeof (struct damon_sysfs_regions ), GFP_KERNEL );
220
+ }
221
+
222
+ static void damon_sysfs_regions_rm_dirs (struct damon_sysfs_regions * regions )
223
+ {
224
+ struct damon_sysfs_region * * regions_arr = regions -> regions_arr ;
225
+ int i ;
226
+
227
+ for (i = 0 ; i < regions -> nr ; i ++ )
228
+ kobject_put (& regions_arr [i ]-> kobj );
229
+ regions -> nr = 0 ;
230
+ kfree (regions_arr );
231
+ regions -> regions_arr = NULL ;
232
+ }
233
+
234
+ static int damon_sysfs_regions_add_dirs (struct damon_sysfs_regions * regions ,
235
+ int nr_regions )
236
+ {
237
+ struct damon_sysfs_region * * regions_arr , * region ;
238
+ int err , i ;
239
+
240
+ damon_sysfs_regions_rm_dirs (regions );
241
+ if (!nr_regions )
242
+ return 0 ;
243
+
244
+ regions_arr = kmalloc_array (nr_regions , sizeof (* regions_arr ),
245
+ GFP_KERNEL | __GFP_NOWARN );
246
+ if (!regions_arr )
247
+ return - ENOMEM ;
248
+ regions -> regions_arr = regions_arr ;
249
+
250
+ for (i = 0 ; i < nr_regions ; i ++ ) {
251
+ region = damon_sysfs_region_alloc (0 , 0 );
252
+ if (!region ) {
253
+ damon_sysfs_regions_rm_dirs (regions );
254
+ return - ENOMEM ;
255
+ }
256
+
257
+ err = kobject_init_and_add (& region -> kobj ,
258
+ & damon_sysfs_region_ktype , & regions -> kobj ,
259
+ "%d" , i );
260
+ if (err ) {
261
+ kobject_put (& region -> kobj );
262
+ damon_sysfs_regions_rm_dirs (regions );
263
+ return err ;
264
+ }
265
+
266
+ regions_arr [i ] = region ;
267
+ regions -> nr ++ ;
268
+ }
269
+ return 0 ;
270
+ }
271
+
272
+ static ssize_t nr_regions_show (struct kobject * kobj ,
273
+ struct kobj_attribute * attr , char * buf )
274
+ {
275
+ struct damon_sysfs_regions * regions = container_of (kobj ,
276
+ struct damon_sysfs_regions , kobj );
277
+
278
+ return sysfs_emit (buf , "%d\n" , regions -> nr );
279
+ }
280
+
281
+ static ssize_t nr_regions_store (struct kobject * kobj ,
282
+ struct kobj_attribute * attr , const char * buf , size_t count )
283
+ {
284
+ struct damon_sysfs_regions * regions = container_of (kobj ,
285
+ struct damon_sysfs_regions , kobj );
286
+ int nr , err = kstrtoint (buf , 0 , & nr );
287
+
288
+ if (err )
289
+ return err ;
290
+ if (nr < 0 )
291
+ return - EINVAL ;
292
+
293
+ if (!mutex_trylock (& damon_sysfs_lock ))
294
+ return - EBUSY ;
295
+ err = damon_sysfs_regions_add_dirs (regions , nr );
296
+ mutex_unlock (& damon_sysfs_lock );
297
+ if (err )
298
+ return err ;
299
+
300
+ return count ;
301
+ }
302
+
303
+ static void damon_sysfs_regions_release (struct kobject * kobj )
304
+ {
305
+ kfree (container_of (kobj , struct damon_sysfs_regions , kobj ));
306
+ }
307
+
308
+ static struct kobj_attribute damon_sysfs_regions_nr_attr =
309
+ __ATTR_RW_MODE (nr_regions , 0600 );
310
+
311
+ static struct attribute * damon_sysfs_regions_attrs [] = {
312
+ & damon_sysfs_regions_nr_attr .attr ,
313
+ NULL ,
314
+ };
315
+ ATTRIBUTE_GROUPS (damon_sysfs_regions );
316
+
317
+ static struct kobj_type damon_sysfs_regions_ktype = {
318
+ .release = damon_sysfs_regions_release ,
319
+ .sysfs_ops = & kobj_sysfs_ops ,
320
+ .default_groups = damon_sysfs_regions_groups ,
321
+ };
322
+
116
323
/*
117
324
* target directory
118
325
*/
119
326
120
327
struct damon_sysfs_target {
121
328
struct kobject kobj ;
329
+ struct damon_sysfs_regions * regions ;
122
330
int pid ;
123
331
};
124
332
@@ -127,6 +335,29 @@ static struct damon_sysfs_target *damon_sysfs_target_alloc(void)
127
335
return kzalloc (sizeof (struct damon_sysfs_target ), GFP_KERNEL );
128
336
}
129
337
338
+ static int damon_sysfs_target_add_dirs (struct damon_sysfs_target * target )
339
+ {
340
+ struct damon_sysfs_regions * regions = damon_sysfs_regions_alloc ();
341
+ int err ;
342
+
343
+ if (!regions )
344
+ return - ENOMEM ;
345
+
346
+ err = kobject_init_and_add (& regions -> kobj , & damon_sysfs_regions_ktype ,
347
+ & target -> kobj , "regions" );
348
+ if (err )
349
+ kobject_put (& regions -> kobj );
350
+ else
351
+ target -> regions = regions ;
352
+ return err ;
353
+ }
354
+
355
+ static void damon_sysfs_target_rm_dirs (struct damon_sysfs_target * target )
356
+ {
357
+ damon_sysfs_regions_rm_dirs (target -> regions );
358
+ kobject_put (& target -> regions -> kobj );
359
+ }
360
+
130
361
static ssize_t pid_target_show (struct kobject * kobj ,
131
362
struct kobj_attribute * attr , char * buf )
132
363
{
@@ -188,8 +419,10 @@ static void damon_sysfs_targets_rm_dirs(struct damon_sysfs_targets *targets)
188
419
struct damon_sysfs_target * * targets_arr = targets -> targets_arr ;
189
420
int i ;
190
421
191
- for (i = 0 ; i < targets -> nr ; i ++ )
422
+ for (i = 0 ; i < targets -> nr ; i ++ ) {
423
+ damon_sysfs_target_rm_dirs (targets_arr [i ]);
192
424
kobject_put (& targets_arr [i ]-> kobj );
425
+ }
193
426
targets -> nr = 0 ;
194
427
kfree (targets_arr );
195
428
targets -> targets_arr = NULL ;
@@ -224,6 +457,10 @@ static int damon_sysfs_targets_add_dirs(struct damon_sysfs_targets *targets,
224
457
if (err )
225
458
goto out ;
226
459
460
+ err = damon_sysfs_target_add_dirs (target );
461
+ if (err )
462
+ goto out ;
463
+
227
464
targets_arr [i ] = target ;
228
465
targets -> nr ++ ;
229
466
}
@@ -610,9 +847,6 @@ static ssize_t operations_store(struct kobject *kobj,
610
847
611
848
for (id = 0 ; id < NR_DAMON_OPS ; id ++ ) {
612
849
if (sysfs_streq (buf , damon_sysfs_ops_strs [id ])) {
613
- /* Support only vaddr */
614
- if (id != DAMON_OPS_VADDR )
615
- return - EINVAL ;
616
850
context -> ops_id = id ;
617
851
return count ;
618
852
}
@@ -857,10 +1091,37 @@ static void damon_sysfs_destroy_targets(struct damon_ctx *ctx)
857
1091
}
858
1092
}
859
1093
1094
+ static int damon_sysfs_set_regions (struct damon_target * t ,
1095
+ struct damon_sysfs_regions * sysfs_regions )
1096
+ {
1097
+ int i ;
1098
+
1099
+ for (i = 0 ; i < sysfs_regions -> nr ; i ++ ) {
1100
+ struct damon_sysfs_region * sys_region =
1101
+ sysfs_regions -> regions_arr [i ];
1102
+ struct damon_region * prev , * r ;
1103
+
1104
+ if (sys_region -> start > sys_region -> end )
1105
+ return - EINVAL ;
1106
+ r = damon_new_region (sys_region -> start , sys_region -> end );
1107
+ if (!r )
1108
+ return - ENOMEM ;
1109
+ damon_add_region (r , t );
1110
+ if (damon_nr_regions (t ) > 1 ) {
1111
+ prev = damon_prev_region (r );
1112
+ if (prev -> ar .end > r -> ar .start ) {
1113
+ damon_destroy_region (r , t );
1114
+ return - EINVAL ;
1115
+ }
1116
+ }
1117
+ }
1118
+ return 0 ;
1119
+ }
1120
+
860
1121
static int damon_sysfs_set_targets (struct damon_ctx * ctx ,
861
1122
struct damon_sysfs_targets * sysfs_targets )
862
1123
{
863
- int i ;
1124
+ int i , err ;
864
1125
865
1126
for (i = 0 ; i < sysfs_targets -> nr ; i ++ ) {
866
1127
struct damon_sysfs_target * sys_target =
@@ -879,6 +1140,11 @@ static int damon_sysfs_set_targets(struct damon_ctx *ctx,
879
1140
}
880
1141
}
881
1142
damon_add_target (ctx , t );
1143
+ err = damon_sysfs_set_regions (t , sys_target -> regions );
1144
+ if (err ) {
1145
+ damon_sysfs_destroy_targets (ctx );
1146
+ return err ;
1147
+ }
882
1148
}
883
1149
return 0 ;
884
1150
}
0 commit comments