Commit 3e5822e0 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'x86_cache_for_v6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 resource control updates from Borislav Petkov:

 - Implement a rename operation in resctrlfs to facilitate handling of
   application containers with dynamically changing task lists

 - When reading the tasks file, show the tasks' pid which are only in
   the current namespace as opposed to showing the pids from the init
   namespace too

 - Other fixes and improvements

* tag 'x86_cache_for_v6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  Documentation/x86: Documentation for MON group move feature
  x86/resctrl: Implement rename op for mon groups
  x86/resctrl: Factor rdtgroup lock for multi-file ops
  x86/resctrl: Only show tasks' pid in current pid namespace
parents 59035135 e0a6ede2
...@@ -287,6 +287,13 @@ Removing a directory will move all tasks and cpus owned by the group it ...@@ -287,6 +287,13 @@ Removing a directory will move all tasks and cpus owned by the group it
represents to the parent. Removing one of the created CTRL_MON groups represents to the parent. Removing one of the created CTRL_MON groups
will automatically remove all MON groups below it. will automatically remove all MON groups below it.
Moving MON group directories to a new parent CTRL_MON group is supported
for the purpose of changing the resource allocations of a MON group
without impacting its monitoring data or assigned tasks. This operation
is not allowed for MON groups which monitor CPUs. No other move
operation is currently allowed other than simply renaming a CTRL_MON or
MON group.
All groups contain the following files: All groups contain the following files:
"tasks": "tasks":
......
...@@ -726,11 +726,15 @@ static ssize_t rdtgroup_tasks_write(struct kernfs_open_file *of, ...@@ -726,11 +726,15 @@ static ssize_t rdtgroup_tasks_write(struct kernfs_open_file *of,
static void show_rdt_tasks(struct rdtgroup *r, struct seq_file *s) static void show_rdt_tasks(struct rdtgroup *r, struct seq_file *s)
{ {
struct task_struct *p, *t; struct task_struct *p, *t;
pid_t pid;
rcu_read_lock(); rcu_read_lock();
for_each_process_thread(p, t) { for_each_process_thread(p, t) {
if (is_closid_match(t, r) || is_rmid_match(t, r)) if (is_closid_match(t, r) || is_rmid_match(t, r)) {
seq_printf(s, "%d\n", t->pid); pid = task_pid_vnr(t);
if (pid)
seq_printf(s, "%d\n", pid);
}
} }
rcu_read_unlock(); rcu_read_unlock();
} }
...@@ -2301,6 +2305,26 @@ static struct rdtgroup *kernfs_to_rdtgroup(struct kernfs_node *kn) ...@@ -2301,6 +2305,26 @@ static struct rdtgroup *kernfs_to_rdtgroup(struct kernfs_node *kn)
} }
} }
static void rdtgroup_kn_get(struct rdtgroup *rdtgrp, struct kernfs_node *kn)
{
atomic_inc(&rdtgrp->waitcount);
kernfs_break_active_protection(kn);
}
static void rdtgroup_kn_put(struct rdtgroup *rdtgrp, struct kernfs_node *kn)
{
if (atomic_dec_and_test(&rdtgrp->waitcount) &&
(rdtgrp->flags & RDT_DELETED)) {
if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP ||
rdtgrp->mode == RDT_MODE_PSEUDO_LOCKED)
rdtgroup_pseudo_lock_remove(rdtgrp);
kernfs_unbreak_active_protection(kn);
rdtgroup_remove(rdtgrp);
} else {
kernfs_unbreak_active_protection(kn);
}
}
struct rdtgroup *rdtgroup_kn_lock_live(struct kernfs_node *kn) struct rdtgroup *rdtgroup_kn_lock_live(struct kernfs_node *kn)
{ {
struct rdtgroup *rdtgrp = kernfs_to_rdtgroup(kn); struct rdtgroup *rdtgrp = kernfs_to_rdtgroup(kn);
...@@ -2308,8 +2332,7 @@ struct rdtgroup *rdtgroup_kn_lock_live(struct kernfs_node *kn) ...@@ -2308,8 +2332,7 @@ struct rdtgroup *rdtgroup_kn_lock_live(struct kernfs_node *kn)
if (!rdtgrp) if (!rdtgrp)
return NULL; return NULL;
atomic_inc(&rdtgrp->waitcount); rdtgroup_kn_get(rdtgrp, kn);
kernfs_break_active_protection(kn);
mutex_lock(&rdtgroup_mutex); mutex_lock(&rdtgroup_mutex);
...@@ -2328,17 +2351,7 @@ void rdtgroup_kn_unlock(struct kernfs_node *kn) ...@@ -2328,17 +2351,7 @@ void rdtgroup_kn_unlock(struct kernfs_node *kn)
return; return;
mutex_unlock(&rdtgroup_mutex); mutex_unlock(&rdtgroup_mutex);
rdtgroup_kn_put(rdtgrp, kn);
if (atomic_dec_and_test(&rdtgrp->waitcount) &&
(rdtgrp->flags & RDT_DELETED)) {
if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP ||
rdtgrp->mode == RDT_MODE_PSEUDO_LOCKED)
rdtgroup_pseudo_lock_remove(rdtgrp);
kernfs_unbreak_active_protection(kn);
rdtgroup_remove(rdtgrp);
} else {
kernfs_unbreak_active_protection(kn);
}
} }
static int mkdir_mondata_all(struct kernfs_node *parent_kn, static int mkdir_mondata_all(struct kernfs_node *parent_kn,
...@@ -3505,6 +3518,133 @@ static int rdtgroup_rmdir(struct kernfs_node *kn) ...@@ -3505,6 +3518,133 @@ static int rdtgroup_rmdir(struct kernfs_node *kn)
return ret; return ret;
} }
/**
* mongrp_reparent() - replace parent CTRL_MON group of a MON group
* @rdtgrp: the MON group whose parent should be replaced
* @new_prdtgrp: replacement parent CTRL_MON group for @rdtgrp
* @cpus: cpumask provided by the caller for use during this call
*
* Replaces the parent CTRL_MON group for a MON group, resulting in all member
* tasks' CLOSID immediately changing to that of the new parent group.
* Monitoring data for the group is unaffected by this operation.
*/
static void mongrp_reparent(struct rdtgroup *rdtgrp,
struct rdtgroup *new_prdtgrp,
cpumask_var_t cpus)
{
struct rdtgroup *prdtgrp = rdtgrp->mon.parent;
WARN_ON(rdtgrp->type != RDTMON_GROUP);
WARN_ON(new_prdtgrp->type != RDTCTRL_GROUP);
/* Nothing to do when simply renaming a MON group. */
if (prdtgrp == new_prdtgrp)
return;
WARN_ON(list_empty(&prdtgrp->mon.crdtgrp_list));
list_move_tail(&rdtgrp->mon.crdtgrp_list,
&new_prdtgrp->mon.crdtgrp_list);
rdtgrp->mon.parent = new_prdtgrp;
rdtgrp->closid = new_prdtgrp->closid;
/* Propagate updated closid to all tasks in this group. */
rdt_move_group_tasks(rdtgrp, rdtgrp, cpus);
update_closid_rmid(cpus, NULL);
}
static int rdtgroup_rename(struct kernfs_node *kn,
struct kernfs_node *new_parent, const char *new_name)
{
struct rdtgroup *new_prdtgrp;
struct rdtgroup *rdtgrp;
cpumask_var_t tmpmask;
int ret;
rdtgrp = kernfs_to_rdtgroup(kn);
new_prdtgrp = kernfs_to_rdtgroup(new_parent);
if (!rdtgrp || !new_prdtgrp)
return -ENOENT;
/* Release both kernfs active_refs before obtaining rdtgroup mutex. */
rdtgroup_kn_get(rdtgrp, kn);
rdtgroup_kn_get(new_prdtgrp, new_parent);
mutex_lock(&rdtgroup_mutex);
rdt_last_cmd_clear();
/*
* Don't allow kernfs_to_rdtgroup() to return a parent rdtgroup if
* either kernfs_node is a file.
*/
if (kernfs_type(kn) != KERNFS_DIR ||
kernfs_type(new_parent) != KERNFS_DIR) {
rdt_last_cmd_puts("Source and destination must be directories");
ret = -EPERM;
goto out;
}
if ((rdtgrp->flags & RDT_DELETED) || (new_prdtgrp->flags & RDT_DELETED)) {
ret = -ENOENT;
goto out;
}
if (rdtgrp->type != RDTMON_GROUP || !kn->parent ||
!is_mon_groups(kn->parent, kn->name)) {
rdt_last_cmd_puts("Source must be a MON group\n");
ret = -EPERM;
goto out;
}
if (!is_mon_groups(new_parent, new_name)) {
rdt_last_cmd_puts("Destination must be a mon_groups subdirectory\n");
ret = -EPERM;
goto out;
}
/*
* If the MON group is monitoring CPUs, the CPUs must be assigned to the
* current parent CTRL_MON group and therefore cannot be assigned to
* the new parent, making the move illegal.
*/
if (!cpumask_empty(&rdtgrp->cpu_mask) &&
rdtgrp->mon.parent != new_prdtgrp) {
rdt_last_cmd_puts("Cannot move a MON group that monitors CPUs\n");
ret = -EPERM;
goto out;
}
/*
* Allocate the cpumask for use in mongrp_reparent() to avoid the
* possibility of failing to allocate it after kernfs_rename() has
* succeeded.
*/
if (!zalloc_cpumask_var(&tmpmask, GFP_KERNEL)) {
ret = -ENOMEM;
goto out;
}
/*
* Perform all input validation and allocations needed to ensure
* mongrp_reparent() will succeed before calling kernfs_rename(),
* otherwise it would be necessary to revert this call if
* mongrp_reparent() failed.
*/
ret = kernfs_rename(kn, new_parent, new_name);
if (!ret)
mongrp_reparent(rdtgrp, new_prdtgrp, tmpmask);
free_cpumask_var(tmpmask);
out:
mutex_unlock(&rdtgroup_mutex);
rdtgroup_kn_put(rdtgrp, kn);
rdtgroup_kn_put(new_prdtgrp, new_parent);
return ret;
}
static int rdtgroup_show_options(struct seq_file *seq, struct kernfs_root *kf) static int rdtgroup_show_options(struct seq_file *seq, struct kernfs_root *kf)
{ {
if (resctrl_arch_get_cdp_enabled(RDT_RESOURCE_L3)) if (resctrl_arch_get_cdp_enabled(RDT_RESOURCE_L3))
...@@ -3522,6 +3662,7 @@ static int rdtgroup_show_options(struct seq_file *seq, struct kernfs_root *kf) ...@@ -3522,6 +3662,7 @@ static int rdtgroup_show_options(struct seq_file *seq, struct kernfs_root *kf)
static struct kernfs_syscall_ops rdtgroup_kf_syscall_ops = { static struct kernfs_syscall_ops rdtgroup_kf_syscall_ops = {
.mkdir = rdtgroup_mkdir, .mkdir = rdtgroup_mkdir,
.rmdir = rdtgroup_rmdir, .rmdir = rdtgroup_rmdir,
.rename = rdtgroup_rename,
.show_options = rdtgroup_show_options, .show_options = rdtgroup_show_options,
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment