* Handle four cases for updating an entire process. * * 1) Set is non-null and the process is not rebasing onto a new root. This * reparents all anonymous sets to the provided set and replaces all * non-anonymous td_cpusets with the provided set. * 2) Set is non-null and the process is rebasing onto a new root. This * creates a new base set if the process previously had its own ba
| 1202 | * state. |
| 1203 | */ |
| 1204 | static int |
| 1205 | cpuset_setproc(pid_t pid, struct cpuset *set, cpuset_t *mask, |
| 1206 | struct domainset *domain, bool rebase) |
| 1207 | { |
| 1208 | struct setlist freelist; |
| 1209 | struct setlist droplist; |
| 1210 | struct domainlist domainlist; |
| 1211 | struct cpuset *base, *nset, *nroot, *tdroot; |
| 1212 | struct thread *td; |
| 1213 | struct proc *p; |
| 1214 | int needed; |
| 1215 | int nfree; |
| 1216 | int error; |
| 1217 | |
| 1218 | /* |
| 1219 | * The algorithm requires two passes due to locking considerations. |
| 1220 | * |
| 1221 | * 1) Lookup the process and acquire the locks in the required order. |
| 1222 | * 2) If enough cpusets have not been allocated release the locks and |
| 1223 | * allocate them. Loop. |
| 1224 | */ |
| 1225 | cpuset_freelist_init(&freelist, 1); |
| 1226 | domainset_freelist_init(&domainlist, 1); |
| 1227 | nfree = 1; |
| 1228 | LIST_INIT(&droplist); |
| 1229 | nfree = 0; |
| 1230 | base = set; |
| 1231 | nroot = NULL; |
| 1232 | if (set != NULL) |
| 1233 | nroot = cpuset_getroot(set); |
| 1234 | for (;;) { |
| 1235 | error = cpuset_which(CPU_WHICH_PID, pid, &p, &td, &nset); |
| 1236 | if (error) |
| 1237 | goto out; |
| 1238 | tdroot = cpuset_getroot(td->td_cpuset); |
| 1239 | needed = p->p_numthreads; |
| 1240 | if (set != NULL && rebase && tdroot != nroot) |
| 1241 | needed++; |
| 1242 | if (nfree >= needed) |
| 1243 | break; |
| 1244 | PROC_UNLOCK(p); |
| 1245 | if (nfree < needed) { |
| 1246 | cpuset_freelist_add(&freelist, needed - nfree); |
| 1247 | domainset_freelist_add(&domainlist, needed - nfree); |
| 1248 | nfree = needed; |
| 1249 | } |
| 1250 | } |
| 1251 | PROC_LOCK_ASSERT(p, MA_OWNED); |
| 1252 | |
| 1253 | /* |
| 1254 | * If we're changing roots and the root set is what has been specified |
| 1255 | * as the parent, then we'll check if the process was previously using |
| 1256 | * the root set and, if it wasn't, create a new base with the process's |
| 1257 | * mask applied to it. |
| 1258 | * |
| 1259 | * If the new root is incompatible with the existing mask, then we allow |
| 1260 | * the process to take on the new root if and only if they have |
| 1261 | * privilege to widen their mask anyways. Unprivileged processes get |
no test coverage detected