107 stringStream pp;
108 pp.print_raw(_mount_point);
109 pp.print_raw(suffix);
110 if (os::file_exists(pp.base())) {
111 ss.print_raw(suffix);
112 if (suffix != cgroup_path) {
113 log_trace(os, container)("set_subsystem_path: cgroup v1 path reduced to: %s.", suffix);
114 }
115 break;
116 }
117 log_trace(os, container)("set_subsystem_path: skipped non-existent directory: %s.", suffix);
118 suffix = strchr(suffix + 1, '/');
119 }
120 }
121 }
122 }
123 _path = os::strdup(ss.base());
124 }
125 }
126
127 /*
128 * The common case, containers, we have _root == _cgroup_path, and thus set the
129 * controller path to the _mount_point. This is where the limits are exposed in
130 * the cgroup pseudo filesystem (at the leaf) and adjustment of the path won't
131 * be needed for that reason.
132 */
133 bool CgroupV1Controller::needs_hierarchy_adjustment() {
134 assert(_cgroup_path != nullptr, "sanity");
135 return strcmp(_root, _cgroup_path) != 0;
136 }
137
138 static inline
139 void verbose_log(julong read_mem_limit, julong upper_mem_bound) {
140 if (log_is_enabled(Debug, os, container)) {
141 jlong mem_limit = (jlong)read_mem_limit; // account for negative values
142 if (mem_limit < 0 || read_mem_limit >= upper_mem_bound) {
143 const char *reason;
144 if (mem_limit == OSCONTAINER_ERROR) {
145 reason = "failed";
146 } else if (mem_limit == -1) {
147 reason = "unlimited";
148 } else {
149 assert(read_mem_limit >= upper_mem_bound, "Expected read value exceeding upper memory bound");
150 // Exceeding physical memory is treated as unlimited. This implementation
151 // caps it at host_mem since Cg v1 has no value to represent 'max'.
152 reason = "ignored";
153 }
154 log_debug(os, container)("container memory limit %s: " JLONG_FORMAT ", upper bound is " JLONG_FORMAT,
155 reason, mem_limit, upper_mem_bound);
156 }
157 }
158 }
159
160 jlong CgroupV1MemoryController::read_memory_limit_in_bytes(julong upper_bound) {
161 julong memlimit;
162 CONTAINER_READ_NUMBER_CHECKED(reader(), "/memory.limit_in_bytes", "Memory Limit", memlimit);
163 if (memlimit >= upper_bound) {
164 verbose_log(memlimit, upper_bound);
165 return (jlong)-1;
166 } else {
167 verbose_log(memlimit, upper_bound);
168 return (jlong)memlimit;
169 }
170 }
171
172 /* read_mem_swap
173 *
174 * Determine the memory and swap limit metric. Returns a positive limit value strictly
175 * lower than the physical memory and swap limit iff there is a limit. Otherwise a
176 * negative value is returned indicating the determined status.
177 *
178 * returns:
179 * * A number > 0 if the limit is available and lower than a physical upper bound.
180 * * OSCONTAINER_ERROR if the limit cannot be retrieved (i.e. not supported) or
181 * * -1 if there isn't any limit in place (note: includes values which exceed a physical
182 * upper bound)
183 */
184 jlong CgroupV1MemoryController::read_mem_swap(julong upper_memsw_bound) {
185 julong memswlimit;
186 CONTAINER_READ_NUMBER_CHECKED(reader(), "/memory.memsw.limit_in_bytes", "Memory and Swap Limit", memswlimit);
187 if (memswlimit >= upper_memsw_bound) {
188 log_trace(os, container)("Memory and Swap Limit is: Unlimited");
189 return (jlong)-1;
190 } else {
191 return (jlong)memswlimit;
192 }
193 }
194
195 jlong CgroupV1MemoryController::memory_and_swap_limit_in_bytes(julong upper_mem_bound, julong upper_swap_bound) {
196 jlong memory_swap = read_mem_swap(upper_mem_bound + upper_swap_bound);
197 if (memory_swap == -1) {
198 return memory_swap;
199 }
200 // If there is a swap limit, but swappiness == 0, reset the limit
201 // to the memory limit. Do the same for cases where swap isn't
202 // supported.
203 jlong swappiness = read_mem_swappiness();
204 if (swappiness == 0 || memory_swap == OSCONTAINER_ERROR) {
205 jlong memlimit = read_memory_limit_in_bytes(upper_mem_bound);
206 if (memory_swap == OSCONTAINER_ERROR) {
207 log_trace(os, container)("Memory and Swap Limit has been reset to " JLONG_FORMAT " because swap is not supported", memlimit);
208 } else {
209 log_trace(os, container)("Memory and Swap Limit has been reset to " JLONG_FORMAT " because swappiness is 0", memlimit);
210 }
211 return memlimit;
212 }
|
107 stringStream pp;
108 pp.print_raw(_mount_point);
109 pp.print_raw(suffix);
110 if (os::file_exists(pp.base())) {
111 ss.print_raw(suffix);
112 if (suffix != cgroup_path) {
113 log_trace(os, container)("set_subsystem_path: cgroup v1 path reduced to: %s.", suffix);
114 }
115 break;
116 }
117 log_trace(os, container)("set_subsystem_path: skipped non-existent directory: %s.", suffix);
118 suffix = strchr(suffix + 1, '/');
119 }
120 }
121 }
122 }
123 _path = os::strdup(ss.base());
124 }
125 }
126
127 jlong CgroupV1MemoryController::uses_mem_hierarchy() {
128 julong use_hierarchy;
129 CONTAINER_READ_NUMBER_CHECKED(reader(), "/memory.use_hierarchy", "Use Hierarchy", use_hierarchy);
130 return (jlong)use_hierarchy;
131 }
132
133 /*
134 * The common case, containers, we have _root == _cgroup_path, and thus set the
135 * controller path to the _mount_point. This is where the limits are exposed in
136 * the cgroup pseudo filesystem (at the leaf) and adjustment of the path won't
137 * be needed for that reason.
138 */
139 bool CgroupV1Controller::needs_hierarchy_adjustment() {
140 assert(_cgroup_path != nullptr, "sanity");
141 return strcmp(_root, _cgroup_path) != 0;
142 }
143
144 static inline
145 void verbose_log(julong read_mem_limit, julong upper_mem_bound) {
146 if (log_is_enabled(Debug, os, container)) {
147 jlong mem_limit = (jlong)read_mem_limit; // account for negative values
148 if (mem_limit < 0 || read_mem_limit >= upper_mem_bound) {
149 const char *reason;
150 if (mem_limit == OSCONTAINER_ERROR) {
151 reason = "failed";
152 } else if (mem_limit == -1) {
153 reason = "unlimited";
154 } else {
155 assert(read_mem_limit >= upper_mem_bound, "Expected read value exceeding upper memory bound");
156 // Exceeding physical memory is treated as unlimited. This implementation
157 // caps it at host_mem since Cg v1 has no value to represent 'max'.
158 reason = "ignored";
159 }
160 log_debug(os, container)("container memory limit %s: " JLONG_FORMAT ", upper bound is " JLONG_FORMAT,
161 reason, mem_limit, upper_mem_bound);
162 }
163 }
164 }
165
166 jlong CgroupV1MemoryController::read_memory_limit_in_bytes(julong upper_bound) {
167 julong memlimit;
168 CONTAINER_READ_NUMBER_CHECKED(reader(), "/memory.limit_in_bytes", "Memory Limit", memlimit);
169 if (memlimit >= upper_bound && uses_mem_hierarchy()) {
170 CONTAINER_READ_NUMERICAL_KEY_VALUE_CHECKED(reader(), "/memory.stat",
171 "hierarchical_memory_limit", "Hierarchical Memory Limit",
172 memlimit);
173 }
174 verbose_log(memlimit, upper_bound);
175 return (jlong)((memlimit < upper_bound) ? memlimit : -1);
176 }
177
178 /* read_mem_swap
179 *
180 * Determine the memory and swap limit metric. Returns a positive limit value strictly
181 * lower than the physical memory and swap limit iff there is a limit. Otherwise a
182 * negative value is returned indicating the determined status.
183 *
184 * returns:
185 * * A number > 0 if the limit is available and lower than a physical upper bound.
186 * * OSCONTAINER_ERROR if the limit cannot be retrieved (i.e. not supported) or
187 * * -1 if there isn't any limit in place (note: includes values which exceed a physical
188 * upper bound)
189 */
190 jlong CgroupV1MemoryController::read_mem_swap(julong upper_memsw_bound) {
191 julong memswlimit;
192 CONTAINER_READ_NUMBER_CHECKED(reader(), "/memory.memsw.limit_in_bytes", "Memory and Swap Limit", memswlimit);
193 if (memswlimit >= upper_memsw_bound && uses_mem_hierarchy()) {
194 CONTAINER_READ_NUMERICAL_KEY_VALUE_CHECKED(reader(), "/memory.stat",
195 "hierarchical_memsw_limit", "Hierarchical Memory and Swap Limit",
196 memswlimit);
197 }
198 verbose_log(memswlimit, upper_memsw_bound);
199 return (jlong)((memswlimit < upper_memsw_bound) ? memswlimit : -1);
200 }
201
202 jlong CgroupV1MemoryController::memory_and_swap_limit_in_bytes(julong upper_mem_bound, julong upper_swap_bound) {
203 jlong memory_swap = read_mem_swap(upper_mem_bound + upper_swap_bound);
204 if (memory_swap == -1) {
205 return memory_swap;
206 }
207 // If there is a swap limit, but swappiness == 0, reset the limit
208 // to the memory limit. Do the same for cases where swap isn't
209 // supported.
210 jlong swappiness = read_mem_swappiness();
211 if (swappiness == 0 || memory_swap == OSCONTAINER_ERROR) {
212 jlong memlimit = read_memory_limit_in_bytes(upper_mem_bound);
213 if (memory_swap == OSCONTAINER_ERROR) {
214 log_trace(os, container)("Memory and Swap Limit has been reset to " JLONG_FORMAT " because swap is not supported", memlimit);
215 } else {
216 log_trace(os, container)("Memory and Swap Limit has been reset to " JLONG_FORMAT " because swappiness is 0", memlimit);
217 }
218 return memlimit;
219 }
|