Skip to content

Commit c7d9aac

Browse files
Vikas ShivappaKAGA-KOKO
authored andcommitted
x86/intel_rdt/cqm: Add mkdir support for RDT monitoring
Resource control groups can be created using mkdir in resctrl fs(rdtgroup). In order to extend the resctrl interface to support monitoring the control groups, extend the current mkdir to support resource monitoring also. This allows the rdtgroup created under the root directory to be able to both control and monitor resources (ctrl_mon group). The ctrl_mon groups are associated with one CLOSID like the legacy rdtgroups and one RMID(Resource monitoring ID) as well. Hardware uses RMID to track the resource usage. Once either of the CLOSID or RMID are exhausted, the mkdir fails with -ENOSPC. If there are RMIDs in limbo list but not free an -EBUSY is returned. User can also monitor a subset of the ctrl_mon rdtgroup's tasks/cpus using the monitor groups. The monitor groups are created using mkdir under the "mon_groups" directory in every ctrl_mon group. [Merged Tony's code: Removed a lot of common mkdir code, a fix to handling of the list of the child rdtgroups and some cleanups in list traversal. Also the changes to have similar alloc and free for CLOS/RMID and return -EBUSY when RMIDs are in limbo and not free] Signed-off-by: Tony Luck <[email protected]> Signed-off-by: Vikas Shivappa <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Link: http://lkml.kernel.org/r/1501017287-28083-14-git-send-email-vikas.shivappa@linux.intel.com
1 parent 65b4f40 commit c7d9aac

File tree

2 files changed

+151
-8
lines changed

2 files changed

+151
-8
lines changed

arch/x86/kernel/cpu/intel_rdt.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,25 @@ extern unsigned int intel_cqm_threshold;
3737
extern bool rdt_alloc_capable;
3838
extern bool rdt_mon_capable;
3939
extern unsigned int rdt_mon_features;
40+
41+
enum rdt_group_type {
42+
RDTCTRL_GROUP = 0,
43+
RDTMON_GROUP,
44+
RDT_NUM_GROUP,
45+
};
46+
47+
/**
48+
* struct mongroup - store mon group's data in resctrl fs.
49+
* @parent: parent rdtgrp
50+
* @crdtgrp_list: child rdtgroup node list
51+
* @rmid: rmid for this rdtgroup
52+
*/
53+
struct mongroup {
54+
struct rdtgroup *parent;
55+
struct list_head crdtgrp_list;
56+
u32 rmid;
57+
};
58+
4059
/**
4160
* struct rdtgroup - store rdtgroup's data in resctrl file system.
4261
* @kn: kernfs node
@@ -46,6 +65,9 @@ extern unsigned int rdt_mon_features;
4665
* @flags: status bits
4766
* @waitcount: how many cpus expect to find this
4867
* group when they acquire rdtgroup_mutex
68+
* @type: indicates type of this rdtgroup - either
69+
* monitor only or ctrl_mon group
70+
* @mon: mongroup related data
4971
*/
5072
struct rdtgroup {
5173
struct kernfs_node *kn;
@@ -54,6 +76,8 @@ struct rdtgroup {
5476
struct cpumask cpu_mask;
5577
int flags;
5678
atomic_t waitcount;
79+
enum rdt_group_type type;
80+
struct mongroup mon;
5781
};
5882

5983
/* rdtgroup.flags */
@@ -306,6 +330,8 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of,
306330
int rdtgroup_schemata_show(struct kernfs_open_file *of,
307331
struct seq_file *s, void *v);
308332
struct rdt_domain *get_domain_from_cpu(int cpu, struct rdt_resource *r);
333+
int alloc_rmid(void);
334+
void free_rmid(u32 rmid);
309335
int rdt_get_mon_l3_config(struct rdt_resource *r);
310336

311337
#endif /* _ASM_X86_INTEL_RDT_H */

arch/x86/kernel/cpu/intel_rdt_rdtgroup.c

Lines changed: 125 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -758,6 +758,39 @@ static int rdtgroup_create_info_dir(struct kernfs_node *parent_kn)
758758
return ret;
759759
}
760760

761+
static int
762+
mongroup_create_dir(struct kernfs_node *parent_kn, struct rdtgroup *prgrp,
763+
char *name, struct kernfs_node **dest_kn)
764+
{
765+
struct kernfs_node *kn;
766+
int ret;
767+
768+
/* create the directory */
769+
kn = kernfs_create_dir(parent_kn, name, parent_kn->mode, prgrp);
770+
if (IS_ERR(kn))
771+
return PTR_ERR(kn);
772+
773+
if (dest_kn)
774+
*dest_kn = kn;
775+
776+
/*
777+
* This extra ref will be put in kernfs_remove() and guarantees
778+
* that @rdtgrp->kn is always accessible.
779+
*/
780+
kernfs_get(kn);
781+
782+
ret = rdtgroup_kn_set_ugid(kn);
783+
if (ret)
784+
goto out_destroy;
785+
786+
kernfs_activate(kn);
787+
788+
return 0;
789+
790+
out_destroy:
791+
kernfs_remove(kn);
792+
return ret;
793+
}
761794
static void l3_qos_cfg_update(void *arg)
762795
{
763796
bool *enable = arg;
@@ -1085,7 +1118,7 @@ static struct file_system_type rdt_fs_type = {
10851118
static int mkdir_rdt_prepare(struct kernfs_node *parent_kn,
10861119
struct kernfs_node *prgrp_kn,
10871120
const char *name, umode_t mode,
1088-
struct rdtgroup **r)
1121+
enum rdt_group_type rtype, struct rdtgroup **r)
10891122
{
10901123
struct rdtgroup *prdtgrp, *rdtgrp;
10911124
struct kernfs_node *kn;
@@ -1105,6 +1138,9 @@ static int mkdir_rdt_prepare(struct kernfs_node *parent_kn,
11051138
goto out_unlock;
11061139
}
11071140
*r = rdtgrp;
1141+
rdtgrp->mon.parent = prdtgrp;
1142+
rdtgrp->type = rtype;
1143+
INIT_LIST_HEAD(&rdtgrp->mon.crdtgrp_list);
11081144

11091145
/* kernfs creates the directory for rdtgrp */
11101146
kn = kernfs_create_dir(parent_kn, name, mode, rdtgrp);
@@ -1127,10 +1163,17 @@ static int mkdir_rdt_prepare(struct kernfs_node *parent_kn,
11271163
goto out_destroy;
11281164

11291165
files = RFTYPE_BASE | RFTYPE_CTRL;
1166+
files = RFTYPE_BASE | BIT(RF_CTRLSHIFT + rtype);
11301167
ret = rdtgroup_add_files(kn, files);
11311168
if (ret)
11321169
goto out_destroy;
11331170

1171+
if (rdt_mon_capable) {
1172+
ret = alloc_rmid();
1173+
if (ret < 0)
1174+
goto out_destroy;
1175+
rdtgrp->mon.rmid = ret;
1176+
}
11341177
kernfs_activate(kn);
11351178

11361179
/*
@@ -1150,23 +1193,56 @@ static int mkdir_rdt_prepare(struct kernfs_node *parent_kn,
11501193
static void mkdir_rdt_prepare_clean(struct rdtgroup *rgrp)
11511194
{
11521195
kernfs_remove(rgrp->kn);
1196+
free_rmid(rgrp->mon.rmid);
11531197
kfree(rgrp);
11541198
}
11551199

1200+
/*
1201+
* Create a monitor group under "mon_groups" directory of a control
1202+
* and monitor group(ctrl_mon). This is a resource group
1203+
* to monitor a subset of tasks and cpus in its parent ctrl_mon group.
1204+
*/
1205+
static int rdtgroup_mkdir_mon(struct kernfs_node *parent_kn,
1206+
struct kernfs_node *prgrp_kn,
1207+
const char *name,
1208+
umode_t mode)
1209+
{
1210+
struct rdtgroup *rdtgrp, *prgrp;
1211+
int ret;
1212+
1213+
ret = mkdir_rdt_prepare(parent_kn, prgrp_kn, name, mode, RDTMON_GROUP,
1214+
&rdtgrp);
1215+
if (ret)
1216+
return ret;
1217+
1218+
prgrp = rdtgrp->mon.parent;
1219+
rdtgrp->closid = prgrp->closid;
1220+
1221+
/*
1222+
* Add the rdtgrp to the list of rdtgrps the parent
1223+
* ctrl_mon group has to track.
1224+
*/
1225+
list_add_tail(&rdtgrp->mon.crdtgrp_list, &prgrp->mon.crdtgrp_list);
1226+
1227+
rdtgroup_kn_unlock(prgrp_kn);
1228+
return ret;
1229+
}
1230+
11561231
/*
11571232
* These are rdtgroups created under the root directory. Can be used
1158-
* to allocate resources.
1233+
* to allocate and monitor resources.
11591234
*/
1160-
static int rdtgroup_mkdir_ctrl(struct kernfs_node *parent_kn,
1161-
struct kernfs_node *prgrp_kn,
1162-
const char *name, umode_t mode)
1235+
static int rdtgroup_mkdir_ctrl_mon(struct kernfs_node *parent_kn,
1236+
struct kernfs_node *prgrp_kn,
1237+
const char *name, umode_t mode)
11631238
{
11641239
struct rdtgroup *rdtgrp;
11651240
struct kernfs_node *kn;
11661241
u32 closid;
11671242
int ret;
11681243

1169-
ret = mkdir_rdt_prepare(parent_kn, prgrp_kn, name, mode, &rdtgrp);
1244+
ret = mkdir_rdt_prepare(parent_kn, prgrp_kn, name, mode, RDTCTRL_GROUP,
1245+
&rdtgrp);
11701246
if (ret)
11711247
return ret;
11721248

@@ -1179,15 +1255,44 @@ static int rdtgroup_mkdir_ctrl(struct kernfs_node *parent_kn,
11791255
rdtgrp->closid = closid;
11801256
list_add(&rdtgrp->rdtgroup_list, &rdt_all_groups);
11811257

1258+
if (rdt_mon_capable) {
1259+
/*
1260+
* Create an empty mon_groups directory to hold the subset
1261+
* of tasks and cpus to monitor.
1262+
*/
1263+
ret = mongroup_create_dir(kn, NULL, "mon_groups", NULL);
1264+
if (ret)
1265+
goto out_id_free;
1266+
}
1267+
11821268
goto out_unlock;
11831269

1270+
out_id_free:
1271+
closid_free(closid);
1272+
list_del(&rdtgrp->rdtgroup_list);
11841273
out_common_fail:
11851274
mkdir_rdt_prepare_clean(rdtgrp);
11861275
out_unlock:
11871276
rdtgroup_kn_unlock(prgrp_kn);
11881277
return ret;
11891278
}
11901279

1280+
/*
1281+
* We allow creating mon groups only with in a directory called "mon_groups"
1282+
* which is present in every ctrl_mon group. Check if this is a valid
1283+
* "mon_groups" directory.
1284+
*
1285+
* 1. The directory should be named "mon_groups".
1286+
* 2. The mon group itself should "not" be named "mon_groups".
1287+
* This makes sure "mon_groups" directory always has a ctrl_mon group
1288+
* as parent.
1289+
*/
1290+
static bool is_mon_groups(struct kernfs_node *kn, const char *name)
1291+
{
1292+
return (!strcmp(kn->name, "mon_groups") &&
1293+
strcmp(name, "mon_groups"));
1294+
}
1295+
11911296
static int rdtgroup_mkdir(struct kernfs_node *parent_kn, const char *name,
11921297
umode_t mode)
11931298
{
@@ -1197,10 +1302,18 @@ static int rdtgroup_mkdir(struct kernfs_node *parent_kn, const char *name,
11971302

11981303
/*
11991304
* If the parent directory is the root directory and RDT
1200-
* allocation is supported, add a control rdtgroup.
1305+
* allocation is supported, add a control and monitoring
1306+
* subdirectory
12011307
*/
12021308
if (rdt_alloc_capable && parent_kn == rdtgroup_default.kn)
1203-
return rdtgroup_mkdir_ctrl(parent_kn, parent_kn, name, mode);
1309+
return rdtgroup_mkdir_ctrl_mon(parent_kn, parent_kn, name, mode);
1310+
1311+
/*
1312+
* If RDT monitoring is supported and the parent directory is a valid
1313+
* "mon_groups" directory, add a monitoring subdirectory.
1314+
*/
1315+
if (rdt_mon_capable && is_mon_groups(parent_kn, name))
1316+
return rdtgroup_mkdir_mon(parent_kn, parent_kn->parent, name, mode);
12041317

12051318
return -EPERM;
12061319
}
@@ -1280,6 +1393,10 @@ static int __init rdtgroup_setup_root(void)
12801393
mutex_lock(&rdtgroup_mutex);
12811394

12821395
rdtgroup_default.closid = 0;
1396+
rdtgroup_default.mon.rmid = 0;
1397+
rdtgroup_default.type = RDTCTRL_GROUP;
1398+
INIT_LIST_HEAD(&rdtgroup_default.mon.crdtgrp_list);
1399+
12831400
list_add(&rdtgroup_default.rdtgroup_list, &rdt_all_groups);
12841401

12851402
ret = rdtgroup_add_files(rdt_root->kn, RF_CTRL_BASE);

0 commit comments

Comments
 (0)