Date: Mon, 25 Apr 2016 04:24:00 +0000 (UTC) From: Jamie Gritton <jamie@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r298565 - in head/sys: kern sys Message-ID: <201604250424.u3P4O0rY093716@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: jamie Date: Mon Apr 25 04:24:00 2016 New Revision: 298565 URL: https://svnweb.freebsd.org/changeset/base/298565 Log: Add a new jail OSD method, PR_METHOD_REMOVE. It's called when a jail is removed from the user perspective, i.e. when the last pr_uref goes away, even though the jail mail still exist in the dying state. It will also be called if either PR_METHOD_CREATE or PR_METHOD_SET fail. PR: 48471 MFC after: 5 days Modified: head/sys/kern/kern_jail.c head/sys/sys/jail.h Modified: head/sys/kern/kern_jail.c ============================================================================== --- head/sys/kern/kern_jail.c Mon Apr 25 03:58:08 2016 (r298564) +++ head/sys/kern/kern_jail.c Mon Apr 25 04:24:00 2016 (r298565) @@ -556,7 +556,8 @@ kern_jail_set(struct thread *td, struct #endif unsigned long hid; size_t namelen, onamelen; - int created, cuflags, descend, enforce, error, errmsg_len, errmsg_pos; + int born, created, cuflags, descend, enforce; + int error, errmsg_len, errmsg_pos; int gotchildmax, gotenforce, gothid, gotrsnum, gotslevel; int fi, jid, jsys, len, level; int childmax, osreldt, rsnum, slevel; @@ -1767,6 +1768,7 @@ kern_jail_set(struct thread *td, struct * for now, so new ones will remain unseen until after the module * handlers have completed. */ + born = pr->pr_uref == 0; if (!created && (ch_flags & PR_PERSIST & (pr_flags ^ pr->pr_flags))) { if (pr_flags & PR_PERSIST) { pr->pr_ref++; @@ -1836,15 +1838,20 @@ kern_jail_set(struct thread *td, struct /* Let the modules do their work. */ sx_downgrade(&allprison_lock); - if (created) { + if (born) { error = osd_jail_call(pr, PR_METHOD_CREATE, opts); if (error) { - prison_deref(pr, PD_LIST_SLOCKED); + (void)osd_jail_call(pr, PR_METHOD_REMOVE, NULL); + prison_deref(pr, created + ? PD_LIST_SLOCKED + : PD_DEREF | PD_LIST_SLOCKED); goto done_errmsg; } } error = osd_jail_call(pr, PR_METHOD_SET, opts); if (error) { + if (born) + (void)osd_jail_call(pr, PR_METHOD_REMOVE, NULL); prison_deref(pr, created ? PD_LIST_SLOCKED : PD_DEREF | PD_LIST_SLOCKED); @@ -1896,7 +1903,7 @@ kern_jail_set(struct thread *td, struct sx_sunlock(&allprison_lock); } - goto done_errmsg; + goto done_free; done_deref_locked: prison_deref(pr, created @@ -2596,19 +2603,46 @@ static void prison_deref(struct prison *pr, int flags) { struct prison *ppr, *tpr; + int ref, lasturef; if (!(flags & PD_LOCKED)) mtx_lock(&pr->pr_mtx); for (;;) { if (flags & PD_DEUREF) { pr->pr_uref--; + lasturef = pr->pr_uref == 0; + if (lasturef) + pr->pr_ref++; KASSERT(prison0.pr_uref != 0, ("prison0 pr_uref=0")); - } + } else + lasturef = 0; if (flags & PD_DEREF) pr->pr_ref--; - /* If the prison still has references, nothing else to do. */ - if (pr->pr_ref > 0) { + ref = pr->pr_ref; + mtx_unlock(&pr->pr_mtx); + + /* + * Tell the modules if the last user reference was removed + * (even it sticks around in dying state). + */ + if (lasturef) { + if (!(flags & (PD_LIST_SLOCKED | PD_LIST_XLOCKED))) { + if (ref > 1) { + sx_slock(&allprison_lock); + flags |= PD_LIST_SLOCKED; + } else { + sx_xlock(&allprison_lock); + flags |= PD_LIST_XLOCKED; + } + } + (void)osd_jail_call(pr, PR_METHOD_REMOVE, NULL); + mtx_lock(&pr->pr_mtx); + ref = --pr->pr_ref; mtx_unlock(&pr->pr_mtx); + } + + /* If the prison still has references, nothing else to do. */ + if (ref > 0) { if (flags & PD_LIST_SLOCKED) sx_sunlock(&allprison_lock); else if (flags & PD_LIST_XLOCKED) @@ -2616,7 +2650,6 @@ prison_deref(struct prison *pr, int flag return; } - mtx_unlock(&pr->pr_mtx); if (flags & PD_LIST_SLOCKED) { if (!sx_try_upgrade(&allprison_lock)) { sx_sunlock(&allprison_lock); Modified: head/sys/sys/jail.h ============================================================================== --- head/sys/sys/jail.h Mon Apr 25 03:58:08 2016 (r298564) +++ head/sys/sys/jail.h Mon Apr 25 04:24:00 2016 (r298565) @@ -241,7 +241,8 @@ struct prison_racct { #define PR_METHOD_SET 2 #define PR_METHOD_CHECK 3 #define PR_METHOD_ATTACH 4 -#define PR_MAXMETHOD 5 +#define PR_METHOD_REMOVE 5 +#define PR_MAXMETHOD 6 /* * Lock/unlock a prison.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201604250424.u3P4O0rY093716>