aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2007-06-04 17:41:22 -0400
committerJames Morris <jmorris@namei.org>2007-07-11 22:52:23 -0400
commit9dc9978084ea2a96b9f42752753d9e38a9f9d7b2 (patch)
tree24aac2351df72f9f12fa9143a7746a2e83d24899
parente47c8fc582a2c9f3cba059e543c4a056cd6bf8c4 (diff)
selinux: introduce schedule points in policydb_destroy()
During the LSPP testing we found that it was possible for policydb_destroy() to take 10+ seconds of kernel time to complete. Basically all policydb_destroy() does is walk some (possibly long) lists and free the memory it finds. Turning off slab debugging config options made the problem go away since the actual functions which took most of the time were (as seen by oprofile) > 121202 23.9879 .check_poison_obj > 78247 15.4864 .check_slabp were caused by that. So I decided to also add some voluntary schedule points in that code so config voluntary preempt would be enough to solve the problem. Something similar was done in places like shmem_free_pages() when we have to walk a list of memory and free it. This was tested by the LSPP group on the hardware which could reproduce the problem just loading a new policy and was found to not trigger the softlock detector. It takes just as much processing time, but the kernel doesn't spend all that time stuck doing one thing and never scheduling. Someday a better way to handle memory might make the time needed in this function a lot less, but this fixes the current issue as it stands today. Signed-off-by: Eric Paris <eparis@redhat.com> Signed-off-by: James Morris <jmorris@namei.org>
-rw-r--r--security/selinux/ss/policydb.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 0ac1021734c0..f05f97a2bc3a 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -21,6 +21,7 @@
21 */ 21 */
22 22
23#include <linux/kernel.h> 23#include <linux/kernel.h>
24#include <linux/sched.h>
24#include <linux/slab.h> 25#include <linux/slab.h>
25#include <linux/string.h> 26#include <linux/string.h>
26#include <linux/errno.h> 27#include <linux/errno.h>
@@ -598,6 +599,7 @@ void policydb_destroy(struct policydb *p)
598 struct range_trans *rt, *lrt = NULL; 599 struct range_trans *rt, *lrt = NULL;
599 600
600 for (i = 0; i < SYM_NUM; i++) { 601 for (i = 0; i < SYM_NUM; i++) {
602 cond_resched();
601 hashtab_map(p->symtab[i].table, destroy_f[i], NULL); 603 hashtab_map(p->symtab[i].table, destroy_f[i], NULL);
602 hashtab_destroy(p->symtab[i].table); 604 hashtab_destroy(p->symtab[i].table);
603 } 605 }
@@ -612,6 +614,7 @@ void policydb_destroy(struct policydb *p)
612 avtab_destroy(&p->te_avtab); 614 avtab_destroy(&p->te_avtab);
613 615
614 for (i = 0; i < OCON_NUM; i++) { 616 for (i = 0; i < OCON_NUM; i++) {
617 cond_resched();
615 c = p->ocontexts[i]; 618 c = p->ocontexts[i];
616 while (c) { 619 while (c) {
617 ctmp = c; 620 ctmp = c;
@@ -623,6 +626,7 @@ void policydb_destroy(struct policydb *p)
623 626
624 g = p->genfs; 627 g = p->genfs;
625 while (g) { 628 while (g) {
629 cond_resched();
626 kfree(g->fstype); 630 kfree(g->fstype);
627 c = g->head; 631 c = g->head;
628 while (c) { 632 while (c) {
@@ -639,18 +643,21 @@ void policydb_destroy(struct policydb *p)
639 cond_policydb_destroy(p); 643 cond_policydb_destroy(p);
640 644
641 for (tr = p->role_tr; tr; tr = tr->next) { 645 for (tr = p->role_tr; tr; tr = tr->next) {
646 cond_resched();
642 kfree(ltr); 647 kfree(ltr);
643 ltr = tr; 648 ltr = tr;
644 } 649 }
645 kfree(ltr); 650 kfree(ltr);
646 651
647 for (ra = p->role_allow; ra; ra = ra -> next) { 652 for (ra = p->role_allow; ra; ra = ra -> next) {
653 cond_resched();
648 kfree(lra); 654 kfree(lra);
649 lra = ra; 655 lra = ra;
650 } 656 }
651 kfree(lra); 657 kfree(lra);
652 658
653 for (rt = p->range_tr; rt; rt = rt -> next) { 659 for (rt = p->range_tr; rt; rt = rt -> next) {
660 cond_resched();
654 if (lrt) { 661 if (lrt) {
655 ebitmap_destroy(&lrt->target_range.level[0].cat); 662 ebitmap_destroy(&lrt->target_range.level[0].cat);
656 ebitmap_destroy(&lrt->target_range.level[1].cat); 663 ebitmap_destroy(&lrt->target_range.level[1].cat);