Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'for-5.13' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup

Pull cgroup changes from Tejun Heo:
"The only notable change is Vipin's new misc cgroup controller.

This implements generic support for resources which can be controlled
by simply counting and limiting the number of resource instances - ie
there's X number of these on the system and this cgroup subtree can
have upto Y of those.

The first user is the address space IDs used for virtual machine
memory encryption and expected future usages are similar - niche
hardware features with concrete resource limits and simple usage
models"

* 'for-5.13' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup:
cgroup: use tsk->in_iowait instead of delayacct_is_task_waiting_on_io()
cgroup/cpuset: fix typos in comments
cgroup: misc: mark dummy misc_cg_res_total_usage() static inline
svm/sev: Register SEV and SEV-ES ASIDs to the misc controller
cgroup: Miscellaneous cgroup documentation.
cgroup: Add misc cgroup controller

+699 -16
+1
Documentation/admin-guide/cgroup-v1/index.rst
··· 17 17 hugetlb 18 18 memcg_test 19 19 memory 20 + misc 20 21 net_cls 21 22 net_prio 22 23 pids
+4
Documentation/admin-guide/cgroup-v1/misc.rst
··· 1 + =============== 2 + Misc controller 3 + =============== 4 + Please refer "Misc" documentation in Documentation/admin-guide/cgroup-v2.rst
+71 -2
Documentation/admin-guide/cgroup-v2.rst
··· 65 65 5-7-1. RDMA Interface Files 66 66 5-8. HugeTLB 67 67 5.8-1. HugeTLB Interface Files 68 - 5-8. Misc 69 - 5-8-1. perf_event 68 + 5-9. Misc 69 + 5.9-1 Miscellaneous cgroup Interface Files 70 + 5.9-2 Migration and Ownership 71 + 5-10. Others 72 + 5-10-1. perf_event 70 73 5-N. Non-normative information 71 74 5-N-1. CPU controller root cgroup process behaviour 72 75 5-N-2. IO controller root cgroup process behaviour ··· 2173 2170 2174 2171 Misc 2175 2172 ---- 2173 + 2174 + The Miscellaneous cgroup provides the resource limiting and tracking 2175 + mechanism for the scalar resources which cannot be abstracted like the other 2176 + cgroup resources. Controller is enabled by the CONFIG_CGROUP_MISC config 2177 + option. 2178 + 2179 + A resource can be added to the controller via enum misc_res_type{} in the 2180 + include/linux/misc_cgroup.h file and the corresponding name via misc_res_name[] 2181 + in the kernel/cgroup/misc.c file. Provider of the resource must set its 2182 + capacity prior to using the resource by calling misc_cg_set_capacity(). 2183 + 2184 + Once a capacity is set then the resource usage can be updated using charge and 2185 + uncharge APIs. All of the APIs to interact with misc controller are in 2186 + include/linux/misc_cgroup.h. 2187 + 2188 + Misc Interface Files 2189 + ~~~~~~~~~~~~~~~~~~~~ 2190 + 2191 + Miscellaneous controller provides 3 interface files. If two misc resources (res_a and res_b) are registered then: 2192 + 2193 + misc.capacity 2194 + A read-only flat-keyed file shown only in the root cgroup. It shows 2195 + miscellaneous scalar resources available on the platform along with 2196 + their quantities:: 2197 + 2198 + $ cat misc.capacity 2199 + res_a 50 2200 + res_b 10 2201 + 2202 + misc.current 2203 + A read-only flat-keyed file shown in the non-root cgroups. It shows 2204 + the current usage of the resources in the cgroup and its children.:: 2205 + 2206 + $ cat misc.current 2207 + res_a 3 2208 + res_b 0 2209 + 2210 + misc.max 2211 + A read-write flat-keyed file shown in the non root cgroups. Allowed 2212 + maximum usage of the resources in the cgroup and its children.:: 2213 + 2214 + $ cat misc.max 2215 + res_a max 2216 + res_b 4 2217 + 2218 + Limit can be set by:: 2219 + 2220 + # echo res_a 1 > misc.max 2221 + 2222 + Limit can be set to max by:: 2223 + 2224 + # echo res_a max > misc.max 2225 + 2226 + Limits can be set higher than the capacity value in the misc.capacity 2227 + file. 2228 + 2229 + Migration and Ownership 2230 + ~~~~~~~~~~~~~~~~~~~~~~~ 2231 + 2232 + A miscellaneous scalar resource is charged to the cgroup in which it is used 2233 + first, and stays charged to that cgroup until that resource is freed. Migrating 2234 + a process to a different cgroup does not move the charge to the destination 2235 + cgroup where the process has moved. 2236 + 2237 + Others 2238 + ------ 2176 2239 2177 2240 perf_event 2178 2241 ~~~~~~~~~~
+60 -10
arch/x86/kvm/svm/sev.c
··· 14 14 #include <linux/psp-sev.h> 15 15 #include <linux/pagemap.h> 16 16 #include <linux/swap.h> 17 + #include <linux/misc_cgroup.h> 17 18 #include <linux/processor.h> 18 19 #include <linux/trace_events.h> 19 20 #include <asm/fpu/internal.h> ··· 28 27 #include "trace.h" 29 28 30 29 #define __ex(x) __kvm_handle_fault_on_reboot(x) 30 + 31 + #ifndef CONFIG_KVM_AMD_SEV 32 + /* 33 + * When this config is not defined, SEV feature is not supported and APIs in 34 + * this file are not used but this file still gets compiled into the KVM AMD 35 + * module. 36 + * 37 + * We will not have MISC_CG_RES_SEV and MISC_CG_RES_SEV_ES entries in the enum 38 + * misc_res_type {} defined in linux/misc_cgroup.h. 39 + * 40 + * Below macros allow compilation to succeed. 41 + */ 42 + #define MISC_CG_RES_SEV MISC_CG_RES_TYPES 43 + #define MISC_CG_RES_SEV_ES MISC_CG_RES_TYPES 44 + #endif 31 45 32 46 static u8 sev_enc_bit; 33 47 static int sev_flush_asids(void); ··· 105 89 106 90 static int sev_asid_new(struct kvm_sev_info *sev) 107 91 { 108 - int pos, min_asid, max_asid; 92 + int pos, min_asid, max_asid, ret; 109 93 bool retry = true; 94 + enum misc_res_type type; 95 + 96 + type = sev->es_active ? MISC_CG_RES_SEV_ES : MISC_CG_RES_SEV; 97 + WARN_ON(sev->misc_cg); 98 + sev->misc_cg = get_current_misc_cg(); 99 + ret = misc_cg_try_charge(type, sev->misc_cg, 1); 100 + if (ret) { 101 + put_misc_cg(sev->misc_cg); 102 + sev->misc_cg = NULL; 103 + return ret; 104 + } 110 105 111 106 mutex_lock(&sev_bitmap_lock); 112 107 ··· 135 108 goto again; 136 109 } 137 110 mutex_unlock(&sev_bitmap_lock); 138 - return -EBUSY; 111 + ret = -EBUSY; 112 + goto e_uncharge; 139 113 } 140 114 141 115 __set_bit(pos, sev_asid_bitmap); ··· 144 116 mutex_unlock(&sev_bitmap_lock); 145 117 146 118 return pos + 1; 119 + e_uncharge: 120 + misc_cg_uncharge(type, sev->misc_cg, 1); 121 + put_misc_cg(sev->misc_cg); 122 + sev->misc_cg = NULL; 123 + return ret; 147 124 } 148 125 149 126 static int sev_get_asid(struct kvm *kvm) ··· 158 125 return sev->asid; 159 126 } 160 127 161 - static void sev_asid_free(int asid) 128 + static void sev_asid_free(struct kvm_sev_info *sev) 162 129 { 163 130 struct svm_cpu_data *sd; 164 131 int cpu, pos; 132 + enum misc_res_type type; 165 133 166 134 mutex_lock(&sev_bitmap_lock); 167 135 168 - pos = asid - 1; 136 + pos = sev->asid - 1; 169 137 __set_bit(pos, sev_reclaim_asid_bitmap); 170 138 171 139 for_each_possible_cpu(cpu) { ··· 175 141 } 176 142 177 143 mutex_unlock(&sev_bitmap_lock); 144 + 145 + type = sev->es_active ? MISC_CG_RES_SEV_ES : MISC_CG_RES_SEV; 146 + misc_cg_uncharge(type, sev->misc_cg, 1); 147 + put_misc_cg(sev->misc_cg); 148 + sev->misc_cg = NULL; 178 149 } 179 150 180 151 static void sev_unbind_asid(struct kvm *kvm, unsigned int handle) ··· 227 188 asid = sev_asid_new(sev); 228 189 if (asid < 0) 229 190 return ret; 191 + sev->asid = asid; 230 192 231 193 ret = sev_platform_init(&argp->error); 232 194 if (ret) 233 195 goto e_free; 234 196 235 197 sev->active = true; 236 - sev->asid = asid; 237 198 INIT_LIST_HEAD(&sev->regions_list); 238 199 239 200 return 0; 240 201 241 202 e_free: 242 - sev_asid_free(asid); 203 + sev_asid_free(sev); 204 + sev->asid = 0; 243 205 return ret; 244 206 } 245 207 ··· 1355 1315 mutex_unlock(&kvm->lock); 1356 1316 1357 1317 sev_unbind_asid(kvm, sev->handle); 1358 - sev_asid_free(sev->asid); 1318 + sev_asid_free(sev); 1359 1319 } 1360 1320 1361 1321 void __init sev_hardware_setup(void) 1362 1322 { 1363 - unsigned int eax, ebx, ecx, edx; 1323 + unsigned int eax, ebx, ecx, edx, sev_asid_count, sev_es_asid_count; 1364 1324 bool sev_es_supported = false; 1365 1325 bool sev_supported = false; 1366 1326 ··· 1392 1352 if (!sev_reclaim_asid_bitmap) 1393 1353 goto out; 1394 1354 1395 - pr_info("SEV supported: %u ASIDs\n", max_sev_asid - min_sev_asid + 1); 1355 + sev_asid_count = max_sev_asid - min_sev_asid + 1; 1356 + if (misc_cg_set_capacity(MISC_CG_RES_SEV, sev_asid_count)) 1357 + goto out; 1358 + 1359 + pr_info("SEV supported: %u ASIDs\n", sev_asid_count); 1396 1360 sev_supported = true; 1397 1361 1398 1362 /* SEV-ES support requested? */ ··· 1411 1367 if (min_sev_asid == 1) 1412 1368 goto out; 1413 1369 1414 - pr_info("SEV-ES supported: %u ASIDs\n", min_sev_asid - 1); 1370 + sev_es_asid_count = min_sev_asid - 1; 1371 + if (misc_cg_set_capacity(MISC_CG_RES_SEV_ES, sev_es_asid_count)) 1372 + goto out; 1373 + 1374 + pr_info("SEV-ES supported: %u ASIDs\n", sev_es_asid_count); 1415 1375 sev_es_supported = true; 1416 1376 1417 1377 out: ··· 1430 1382 1431 1383 bitmap_free(sev_asid_bitmap); 1432 1384 bitmap_free(sev_reclaim_asid_bitmap); 1385 + misc_cg_set_capacity(MISC_CG_RES_SEV, 0); 1386 + misc_cg_set_capacity(MISC_CG_RES_SEV_ES, 0); 1433 1387 1434 1388 sev_flush_asids(); 1435 1389 }
+1
arch/x86/kvm/svm/svm.h
··· 65 65 unsigned long pages_locked; /* Number of pages locked */ 66 66 struct list_head regions_list; /* List of registered regions */ 67 67 u64 ap_jump_table; /* SEV-ES AP Jump Table address */ 68 + struct misc_cg *misc_cg; /* For misc cgroup accounting */ 68 69 }; 69 70 70 71 struct kvm_svm {
+4
include/linux/cgroup_subsys.h
··· 61 61 SUBSYS(rdma) 62 62 #endif 63 63 64 + #if IS_ENABLED(CONFIG_CGROUP_MISC) 65 + SUBSYS(misc) 66 + #endif 67 + 64 68 /* 65 69 * The following subsystems are not supported on the default hierarchy. 66 70 */
+132
include/linux/misc_cgroup.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Miscellaneous cgroup controller. 4 + * 5 + * Copyright 2020 Google LLC 6 + * Author: Vipin Sharma <vipinsh@google.com> 7 + */ 8 + #ifndef _MISC_CGROUP_H_ 9 + #define _MISC_CGROUP_H_ 10 + 11 + /** 12 + * Types of misc cgroup entries supported by the host. 13 + */ 14 + enum misc_res_type { 15 + #ifdef CONFIG_KVM_AMD_SEV 16 + /* AMD SEV ASIDs resource */ 17 + MISC_CG_RES_SEV, 18 + /* AMD SEV-ES ASIDs resource */ 19 + MISC_CG_RES_SEV_ES, 20 + #endif 21 + MISC_CG_RES_TYPES 22 + }; 23 + 24 + struct misc_cg; 25 + 26 + #ifdef CONFIG_CGROUP_MISC 27 + 28 + #include <linux/cgroup.h> 29 + 30 + /** 31 + * struct misc_res: Per cgroup per misc type resource 32 + * @max: Maximum limit on the resource. 33 + * @usage: Current usage of the resource. 34 + * @failed: True if charged failed for the resource in a cgroup. 35 + */ 36 + struct misc_res { 37 + unsigned long max; 38 + atomic_long_t usage; 39 + bool failed; 40 + }; 41 + 42 + /** 43 + * struct misc_cg - Miscellaneous controller's cgroup structure. 44 + * @css: cgroup subsys state object. 45 + * @res: Array of misc resources usage in the cgroup. 46 + */ 47 + struct misc_cg { 48 + struct cgroup_subsys_state css; 49 + struct misc_res res[MISC_CG_RES_TYPES]; 50 + }; 51 + 52 + unsigned long misc_cg_res_total_usage(enum misc_res_type type); 53 + int misc_cg_set_capacity(enum misc_res_type type, unsigned long capacity); 54 + int misc_cg_try_charge(enum misc_res_type type, struct misc_cg *cg, 55 + unsigned long amount); 56 + void misc_cg_uncharge(enum misc_res_type type, struct misc_cg *cg, 57 + unsigned long amount); 58 + 59 + /** 60 + * css_misc() - Get misc cgroup from the css. 61 + * @css: cgroup subsys state object. 62 + * 63 + * Context: Any context. 64 + * Return: 65 + * * %NULL - If @css is null. 66 + * * struct misc_cg* - misc cgroup pointer of the passed css. 67 + */ 68 + static inline struct misc_cg *css_misc(struct cgroup_subsys_state *css) 69 + { 70 + return css ? container_of(css, struct misc_cg, css) : NULL; 71 + } 72 + 73 + /* 74 + * get_current_misc_cg() - Find and get the misc cgroup of the current task. 75 + * 76 + * Returned cgroup has its ref count increased by 1. Caller must call 77 + * put_misc_cg() to return the reference. 78 + * 79 + * Return: Misc cgroup to which the current task belongs to. 80 + */ 81 + static inline struct misc_cg *get_current_misc_cg(void) 82 + { 83 + return css_misc(task_get_css(current, misc_cgrp_id)); 84 + } 85 + 86 + /* 87 + * put_misc_cg() - Put the misc cgroup and reduce its ref count. 88 + * @cg - cgroup to put. 89 + */ 90 + static inline void put_misc_cg(struct misc_cg *cg) 91 + { 92 + if (cg) 93 + css_put(&cg->css); 94 + } 95 + 96 + #else /* !CONFIG_CGROUP_MISC */ 97 + 98 + static inline unsigned long misc_cg_res_total_usage(enum misc_res_type type) 99 + { 100 + return 0; 101 + } 102 + 103 + static inline int misc_cg_set_capacity(enum misc_res_type type, 104 + unsigned long capacity) 105 + { 106 + return 0; 107 + } 108 + 109 + static inline int misc_cg_try_charge(enum misc_res_type type, 110 + struct misc_cg *cg, 111 + unsigned long amount) 112 + { 113 + return 0; 114 + } 115 + 116 + static inline void misc_cg_uncharge(enum misc_res_type type, 117 + struct misc_cg *cg, 118 + unsigned long amount) 119 + { 120 + } 121 + 122 + static inline struct misc_cg *get_current_misc_cg(void) 123 + { 124 + return NULL; 125 + } 126 + 127 + static inline void put_misc_cg(struct misc_cg *cg) 128 + { 129 + } 130 + 131 + #endif /* CONFIG_CGROUP_MISC */ 132 + #endif /* _MISC_CGROUP_H_ */
+14
init/Kconfig
··· 1110 1110 BPF_CGROUP_INET_INGRESS will be executed on the ingress path of 1111 1111 inet sockets. 1112 1112 1113 + config CGROUP_MISC 1114 + bool "Misc resource controller" 1115 + default n 1116 + help 1117 + Provides a controller for miscellaneous resources on a host. 1118 + 1119 + Miscellaneous scalar resources are the resources on the host system 1120 + which cannot be abstracted like the other cgroups. This controller 1121 + tracks and limits the miscellaneous resources used by a process 1122 + attached to a cgroup hierarchy. 1123 + 1124 + For more information, please check misc cgroup section in 1125 + /Documentation/admin-guide/cgroup-v2.rst. 1126 + 1113 1127 config CGROUP_DEBUG 1114 1128 bool "Debug controller" 1115 1129 default n
+1
kernel/cgroup/Makefile
··· 5 5 obj-$(CONFIG_CGROUP_PIDS) += pids.o 6 6 obj-$(CONFIG_CGROUP_RDMA) += rdma.o 7 7 obj-$(CONFIG_CPUSETS) += cpuset.o 8 + obj-$(CONFIG_CGROUP_MISC) += misc.o 8 9 obj-$(CONFIG_CGROUP_DEBUG) += debug.o
+1 -1
kernel/cgroup/cgroup-v1.c
··· 727 727 stats->nr_stopped++; 728 728 break; 729 729 default: 730 - if (delayacct_is_task_waiting_on_io(tsk)) 730 + if (tsk->in_iowait) 731 731 stats->nr_io_wait++; 732 732 break; 733 733 }
+3 -3
kernel/cgroup/cpuset.c
··· 585 585 586 586 par = parent_cs(cur); 587 587 588 - /* On legacy hiearchy, we must be a subset of our parent cpuset. */ 588 + /* On legacy hierarchy, we must be a subset of our parent cpuset. */ 589 589 ret = -EACCES; 590 590 if (!is_in_v2_mode() && !is_cpuset_subset(trial, par)) 591 591 goto out; ··· 1726 1726 * When configured nodemask is changed, the effective nodemasks of this cpuset 1727 1727 * and all its descendants need to be updated. 1728 1728 * 1729 - * On legacy hiearchy, effective_mems will be the same with mems_allowed. 1729 + * On legacy hierarchy, effective_mems will be the same with mems_allowed. 1730 1730 * 1731 1731 * Called with cpuset_mutex held 1732 1732 */ ··· 2500 2500 BUG(); 2501 2501 } 2502 2502 2503 - /* Unrechable but makes gcc happy */ 2503 + /* Unreachable but makes gcc happy */ 2504 2504 return 0; 2505 2505 } 2506 2506
+407
kernel/cgroup/misc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Miscellaneous cgroup controller 4 + * 5 + * Copyright 2020 Google LLC 6 + * Author: Vipin Sharma <vipinsh@google.com> 7 + */ 8 + 9 + #include <linux/limits.h> 10 + #include <linux/cgroup.h> 11 + #include <linux/errno.h> 12 + #include <linux/atomic.h> 13 + #include <linux/slab.h> 14 + #include <linux/misc_cgroup.h> 15 + 16 + #define MAX_STR "max" 17 + #define MAX_NUM ULONG_MAX 18 + 19 + /* Miscellaneous res name, keep it in sync with enum misc_res_type */ 20 + static const char *const misc_res_name[] = { 21 + #ifdef CONFIG_KVM_AMD_SEV 22 + /* AMD SEV ASIDs resource */ 23 + "sev", 24 + /* AMD SEV-ES ASIDs resource */ 25 + "sev_es", 26 + #endif 27 + }; 28 + 29 + /* Root misc cgroup */ 30 + static struct misc_cg root_cg; 31 + 32 + /* 33 + * Miscellaneous resources capacity for the entire machine. 0 capacity means 34 + * resource is not initialized or not present in the host. 35 + * 36 + * root_cg.max and capacity are independent of each other. root_cg.max can be 37 + * more than the actual capacity. We are using Limits resource distribution 38 + * model of cgroup for miscellaneous controller. 39 + */ 40 + static unsigned long misc_res_capacity[MISC_CG_RES_TYPES]; 41 + 42 + /** 43 + * parent_misc() - Get the parent of the passed misc cgroup. 44 + * @cgroup: cgroup whose parent needs to be fetched. 45 + * 46 + * Context: Any context. 47 + * Return: 48 + * * struct misc_cg* - Parent of the @cgroup. 49 + * * %NULL - If @cgroup is null or the passed cgroup does not have a parent. 50 + */ 51 + static struct misc_cg *parent_misc(struct misc_cg *cgroup) 52 + { 53 + return cgroup ? css_misc(cgroup->css.parent) : NULL; 54 + } 55 + 56 + /** 57 + * valid_type() - Check if @type is valid or not. 58 + * @type: misc res type. 59 + * 60 + * Context: Any context. 61 + * Return: 62 + * * true - If valid type. 63 + * * false - If not valid type. 64 + */ 65 + static inline bool valid_type(enum misc_res_type type) 66 + { 67 + return type >= 0 && type < MISC_CG_RES_TYPES; 68 + } 69 + 70 + /** 71 + * misc_cg_res_total_usage() - Get the current total usage of the resource. 72 + * @type: misc res type. 73 + * 74 + * Context: Any context. 75 + * Return: Current total usage of the resource. 76 + */ 77 + unsigned long misc_cg_res_total_usage(enum misc_res_type type) 78 + { 79 + if (valid_type(type)) 80 + return atomic_long_read(&root_cg.res[type].usage); 81 + 82 + return 0; 83 + } 84 + EXPORT_SYMBOL_GPL(misc_cg_res_total_usage); 85 + 86 + /** 87 + * misc_cg_set_capacity() - Set the capacity of the misc cgroup res. 88 + * @type: Type of the misc res. 89 + * @capacity: Supported capacity of the misc res on the host. 90 + * 91 + * If capacity is 0 then the charging a misc cgroup fails for that type. 92 + * 93 + * Context: Any context. 94 + * Return: 95 + * * %0 - Successfully registered the capacity. 96 + * * %-EINVAL - If @type is invalid. 97 + */ 98 + int misc_cg_set_capacity(enum misc_res_type type, unsigned long capacity) 99 + { 100 + if (!valid_type(type)) 101 + return -EINVAL; 102 + 103 + WRITE_ONCE(misc_res_capacity[type], capacity); 104 + return 0; 105 + } 106 + EXPORT_SYMBOL_GPL(misc_cg_set_capacity); 107 + 108 + /** 109 + * misc_cg_cancel_charge() - Cancel the charge from the misc cgroup. 110 + * @type: Misc res type in misc cg to cancel the charge from. 111 + * @cg: Misc cgroup to cancel charge from. 112 + * @amount: Amount to cancel. 113 + * 114 + * Context: Any context. 115 + */ 116 + static void misc_cg_cancel_charge(enum misc_res_type type, struct misc_cg *cg, 117 + unsigned long amount) 118 + { 119 + WARN_ONCE(atomic_long_add_negative(-amount, &cg->res[type].usage), 120 + "misc cgroup resource %s became less than 0", 121 + misc_res_name[type]); 122 + } 123 + 124 + /** 125 + * misc_cg_try_charge() - Try charging the misc cgroup. 126 + * @type: Misc res type to charge. 127 + * @cg: Misc cgroup which will be charged. 128 + * @amount: Amount to charge. 129 + * 130 + * Charge @amount to the misc cgroup. Caller must use the same cgroup during 131 + * the uncharge call. 132 + * 133 + * Context: Any context. 134 + * Return: 135 + * * %0 - If successfully charged. 136 + * * -EINVAL - If @type is invalid or misc res has 0 capacity. 137 + * * -EBUSY - If max limit will be crossed or total usage will be more than the 138 + * capacity. 139 + */ 140 + int misc_cg_try_charge(enum misc_res_type type, struct misc_cg *cg, 141 + unsigned long amount) 142 + { 143 + struct misc_cg *i, *j; 144 + int ret; 145 + struct misc_res *res; 146 + int new_usage; 147 + 148 + if (!(valid_type(type) && cg && READ_ONCE(misc_res_capacity[type]))) 149 + return -EINVAL; 150 + 151 + if (!amount) 152 + return 0; 153 + 154 + for (i = cg; i; i = parent_misc(i)) { 155 + res = &i->res[type]; 156 + 157 + new_usage = atomic_long_add_return(amount, &res->usage); 158 + if (new_usage > READ_ONCE(res->max) || 159 + new_usage > READ_ONCE(misc_res_capacity[type])) { 160 + if (!res->failed) { 161 + pr_info("cgroup: charge rejected by the misc controller for %s resource in ", 162 + misc_res_name[type]); 163 + pr_cont_cgroup_path(i->css.cgroup); 164 + pr_cont("\n"); 165 + res->failed = true; 166 + } 167 + ret = -EBUSY; 168 + goto err_charge; 169 + } 170 + } 171 + return 0; 172 + 173 + err_charge: 174 + for (j = cg; j != i; j = parent_misc(j)) 175 + misc_cg_cancel_charge(type, j, amount); 176 + misc_cg_cancel_charge(type, i, amount); 177 + return ret; 178 + } 179 + EXPORT_SYMBOL_GPL(misc_cg_try_charge); 180 + 181 + /** 182 + * misc_cg_uncharge() - Uncharge the misc cgroup. 183 + * @type: Misc res type which was charged. 184 + * @cg: Misc cgroup which will be uncharged. 185 + * @amount: Charged amount. 186 + * 187 + * Context: Any context. 188 + */ 189 + void misc_cg_uncharge(enum misc_res_type type, struct misc_cg *cg, 190 + unsigned long amount) 191 + { 192 + struct misc_cg *i; 193 + 194 + if (!(amount && valid_type(type) && cg)) 195 + return; 196 + 197 + for (i = cg; i; i = parent_misc(i)) 198 + misc_cg_cancel_charge(type, i, amount); 199 + } 200 + EXPORT_SYMBOL_GPL(misc_cg_uncharge); 201 + 202 + /** 203 + * misc_cg_max_show() - Show the misc cgroup max limit. 204 + * @sf: Interface file 205 + * @v: Arguments passed 206 + * 207 + * Context: Any context. 208 + * Return: 0 to denote successful print. 209 + */ 210 + static int misc_cg_max_show(struct seq_file *sf, void *v) 211 + { 212 + int i; 213 + struct misc_cg *cg = css_misc(seq_css(sf)); 214 + unsigned long max; 215 + 216 + for (i = 0; i < MISC_CG_RES_TYPES; i++) { 217 + if (READ_ONCE(misc_res_capacity[i])) { 218 + max = READ_ONCE(cg->res[i].max); 219 + if (max == MAX_NUM) 220 + seq_printf(sf, "%s max\n", misc_res_name[i]); 221 + else 222 + seq_printf(sf, "%s %lu\n", misc_res_name[i], 223 + max); 224 + } 225 + } 226 + 227 + return 0; 228 + } 229 + 230 + /** 231 + * misc_cg_max_write() - Update the maximum limit of the cgroup. 232 + * @of: Handler for the file. 233 + * @buf: Data from the user. It should be either "max", 0, or a positive 234 + * integer. 235 + * @nbytes: Number of bytes of the data. 236 + * @off: Offset in the file. 237 + * 238 + * User can pass data like: 239 + * echo sev 23 > misc.max, OR 240 + * echo sev max > misc.max 241 + * 242 + * Context: Any context. 243 + * Return: 244 + * * >= 0 - Number of bytes processed in the input. 245 + * * -EINVAL - If buf is not valid. 246 + * * -ERANGE - If number is bigger than the unsigned long capacity. 247 + */ 248 + static ssize_t misc_cg_max_write(struct kernfs_open_file *of, char *buf, 249 + size_t nbytes, loff_t off) 250 + { 251 + struct misc_cg *cg; 252 + unsigned long max; 253 + int ret = 0, i; 254 + enum misc_res_type type = MISC_CG_RES_TYPES; 255 + char *token; 256 + 257 + buf = strstrip(buf); 258 + token = strsep(&buf, " "); 259 + 260 + if (!token || !buf) 261 + return -EINVAL; 262 + 263 + for (i = 0; i < MISC_CG_RES_TYPES; i++) { 264 + if (!strcmp(misc_res_name[i], token)) { 265 + type = i; 266 + break; 267 + } 268 + } 269 + 270 + if (type == MISC_CG_RES_TYPES) 271 + return -EINVAL; 272 + 273 + if (!strcmp(MAX_STR, buf)) { 274 + max = MAX_NUM; 275 + } else { 276 + ret = kstrtoul(buf, 0, &max); 277 + if (ret) 278 + return ret; 279 + } 280 + 281 + cg = css_misc(of_css(of)); 282 + 283 + if (READ_ONCE(misc_res_capacity[type])) 284 + WRITE_ONCE(cg->res[type].max, max); 285 + else 286 + ret = -EINVAL; 287 + 288 + return ret ? ret : nbytes; 289 + } 290 + 291 + /** 292 + * misc_cg_current_show() - Show the current usage of the misc cgroup. 293 + * @sf: Interface file 294 + * @v: Arguments passed 295 + * 296 + * Context: Any context. 297 + * Return: 0 to denote successful print. 298 + */ 299 + static int misc_cg_current_show(struct seq_file *sf, void *v) 300 + { 301 + int i; 302 + unsigned long usage; 303 + struct misc_cg *cg = css_misc(seq_css(sf)); 304 + 305 + for (i = 0; i < MISC_CG_RES_TYPES; i++) { 306 + usage = atomic_long_read(&cg->res[i].usage); 307 + if (READ_ONCE(misc_res_capacity[i]) || usage) 308 + seq_printf(sf, "%s %lu\n", misc_res_name[i], usage); 309 + } 310 + 311 + return 0; 312 + } 313 + 314 + /** 315 + * misc_cg_capacity_show() - Show the total capacity of misc res on the host. 316 + * @sf: Interface file 317 + * @v: Arguments passed 318 + * 319 + * Only present in the root cgroup directory. 320 + * 321 + * Context: Any context. 322 + * Return: 0 to denote successful print. 323 + */ 324 + static int misc_cg_capacity_show(struct seq_file *sf, void *v) 325 + { 326 + int i; 327 + unsigned long cap; 328 + 329 + for (i = 0; i < MISC_CG_RES_TYPES; i++) { 330 + cap = READ_ONCE(misc_res_capacity[i]); 331 + if (cap) 332 + seq_printf(sf, "%s %lu\n", misc_res_name[i], cap); 333 + } 334 + 335 + return 0; 336 + } 337 + 338 + /* Misc cgroup interface files */ 339 + static struct cftype misc_cg_files[] = { 340 + { 341 + .name = "max", 342 + .write = misc_cg_max_write, 343 + .seq_show = misc_cg_max_show, 344 + .flags = CFTYPE_NOT_ON_ROOT, 345 + }, 346 + { 347 + .name = "current", 348 + .seq_show = misc_cg_current_show, 349 + .flags = CFTYPE_NOT_ON_ROOT, 350 + }, 351 + { 352 + .name = "capacity", 353 + .seq_show = misc_cg_capacity_show, 354 + .flags = CFTYPE_ONLY_ON_ROOT, 355 + }, 356 + {} 357 + }; 358 + 359 + /** 360 + * misc_cg_alloc() - Allocate misc cgroup. 361 + * @parent_css: Parent cgroup. 362 + * 363 + * Context: Process context. 364 + * Return: 365 + * * struct cgroup_subsys_state* - css of the allocated cgroup. 366 + * * ERR_PTR(-ENOMEM) - No memory available to allocate. 367 + */ 368 + static struct cgroup_subsys_state * 369 + misc_cg_alloc(struct cgroup_subsys_state *parent_css) 370 + { 371 + enum misc_res_type i; 372 + struct misc_cg *cg; 373 + 374 + if (!parent_css) { 375 + cg = &root_cg; 376 + } else { 377 + cg = kzalloc(sizeof(*cg), GFP_KERNEL); 378 + if (!cg) 379 + return ERR_PTR(-ENOMEM); 380 + } 381 + 382 + for (i = 0; i < MISC_CG_RES_TYPES; i++) { 383 + WRITE_ONCE(cg->res[i].max, MAX_NUM); 384 + atomic_long_set(&cg->res[i].usage, 0); 385 + } 386 + 387 + return &cg->css; 388 + } 389 + 390 + /** 391 + * misc_cg_free() - Free the misc cgroup. 392 + * @css: cgroup subsys object. 393 + * 394 + * Context: Any context. 395 + */ 396 + static void misc_cg_free(struct cgroup_subsys_state *css) 397 + { 398 + kfree(css_misc(css)); 399 + } 400 + 401 + /* Cgroup controller callbacks */ 402 + struct cgroup_subsys misc_cgrp_subsys = { 403 + .css_alloc = misc_cg_alloc, 404 + .css_free = misc_cg_free, 405 + .legacy_cftypes = misc_cg_files, 406 + .dfl_cftypes = misc_cg_files, 407 + };