diff options
author | mjg <mjg@FreeBSD.org> | 2014-02-20 21:52:39 +0000 |
---|---|---|
committer | mjg <mjg@FreeBSD.org> | 2014-02-20 21:52:39 +0000 |
commit | 7a394d25ecae035c6def6d233684e3410edf8ca7 (patch) | |
tree | d41891791fd81acffb6d7be836c590f2d928d37f | |
parent | c581d5764a887d5655bd1705cfd23b1e1400b826 (diff) | |
download | FreeBSD-src-7a394d25ecae035c6def6d233684e3410edf8ca7.zip FreeBSD-src-7a394d25ecae035c6def6d233684e3410edf8ca7.tar.gz |
MFC r259330,r259331:
rlimit: add and utilize lim_shared
rlimit: avoid unnecessary copying of rlimits
If refcount is 1 just modify rlimits in place.
-rw-r--r-- | sys/kern/kern_resource.c | 34 |
1 files changed, 27 insertions, 7 deletions
diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c index 57ee671..51b66f4 100644 --- a/sys/kern/kern_resource.c +++ b/sys/kern/kern_resource.c @@ -80,6 +80,8 @@ static int donice(struct thread *td, struct proc *chgp, int n); static struct uidinfo *uilookup(uid_t uid); static void ruxagg_locked(struct rusage_ext *rux, struct thread *td); +static __inline int lim_shared(struct plimit *limp); + /* * Resource controls and accounting. */ @@ -677,21 +679,29 @@ kern_proc_setrlimit(struct thread *td, struct proc *p, u_int which, limp->rlim_max = RLIM_INFINITY; oldssiz.rlim_cur = 0; - newlim = lim_alloc(); + newlim = NULL; PROC_LOCK(p); + if (lim_shared(p->p_limit)) { + PROC_UNLOCK(p); + newlim = lim_alloc(); + PROC_LOCK(p); + } oldlim = p->p_limit; alimp = &oldlim->pl_rlimit[which]; if (limp->rlim_cur > alimp->rlim_max || limp->rlim_max > alimp->rlim_max) if ((error = priv_check(td, PRIV_PROC_SETRLIMIT))) { PROC_UNLOCK(p); - lim_free(newlim); + if (newlim != NULL) + lim_free(newlim); return (error); } if (limp->rlim_cur > limp->rlim_max) limp->rlim_cur = limp->rlim_max; - lim_copy(newlim, oldlim); - alimp = &newlim->pl_rlimit[which]; + if (newlim != NULL) { + lim_copy(newlim, oldlim); + alimp = &newlim->pl_rlimit[which]; + } switch (which) { @@ -741,9 +751,11 @@ kern_proc_setrlimit(struct thread *td, struct proc *p, u_int which, if (p->p_sysent->sv_fixlimit != NULL) p->p_sysent->sv_fixlimit(limp, which); *alimp = *limp; - p->p_limit = newlim; + if (newlim != NULL) + p->p_limit = newlim; PROC_UNLOCK(p); - lim_free(oldlim); + if (newlim != NULL) + lim_free(oldlim); if (which == RLIMIT_STACK) { /* @@ -1129,6 +1141,14 @@ lim_hold(limp) return (limp); } +static __inline int +lim_shared(limp) + struct plimit *limp; +{ + + return (limp->pl_refcnt > 1); +} + void lim_fork(struct proc *p1, struct proc *p2) { @@ -1162,7 +1182,7 @@ lim_copy(dst, src) struct plimit *dst, *src; { - KASSERT(dst->pl_refcnt == 1, ("lim_copy to shared limit")); + KASSERT(!lim_shared(dst), ("lim_copy to shared limit")); bcopy(src->pl_rlimit, dst->pl_rlimit, sizeof(src->pl_rlimit)); } |