< prev index next >

src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp

Print this page

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