< prev index next >

src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp

Print this page

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   }
< prev index next >