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