[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Perfromance issues



Hello,

Attached is a patch against .88 kernel that should help performance. It 
removes unconditional loads and changes a couple switch/case constructs to a 
lookup & assignment.

There are other performance issues that need checking.  In calls that hook the 
file system, it is probably better to check that audit is enabled at the 
point of the hook rather than in the function:

+++ linux-2.6.9~pre75/fs/attr.c
@@ -68,6 +69,8 @@
        unsigned int ia_valid = attr->ia_valid;
        int error = 0;

+       audit_notify_watch(inode, MAY_WRITE);
+
        if (ia_valid & ATTR_SIZE) {
                if (attr->ia_size != i_size_read(inode)) {
                        error = vmtruncate(inode, attr->ia_size);

+void audit_notify_watch(struct inode *inode, int mask)
+{
+       struct audit_inode_data *data;
+
+       if (likely(!audit_enabled))
+               return;

This means that the variables have to be pushed onto the stack, a call 
performed, the enabled test, do a return instruction, and then pop the stack. 
Its probably faster to do:

+       if (unlikely(audit_enabled))
+              audit_notify_watch(inode, MAY_WRITE);
+

Same thing with audit_syscall_entry & audit_syscall_exit.

NOTE: I am in no way advocating rolling a .89 release just for this.

-Steve
diff -urp linux-2.6.9.orig/kernel/auditsc.c linux-2.6.9/kernel/auditsc.c
--- linux-2.6.9.orig/kernel/auditsc.c	2005-08-04 12:31:38.000000000 -0400
+++ linux-2.6.9/kernel/auditsc.c	2005-08-04 12:28:44.000000000 -0400
@@ -84,6 +84,11 @@ enum audit_state {
 				 * record at syscall exit time.  */
 };
 
+/* This table is used to lookup state in filters */
+#define STATE_LOOKUP_MASK	3
+static const int state_lookup[STATE_LOOKUP_MASK] = 
+	{ AUDIT_DISABLED, AUDIT_BUILD_CONTEXT, AUDIT_RECORD_CONTEXT };
+
 /* When fs/namei.c:getname() is called, we store the pointer in name and
  * we don't let putname() free it (instead we free all of the saved
  * pointers at syscall exit time).
@@ -502,11 +519,7 @@ static int audit_filter_rules(struct tas
 		if (!result)
 			return 0;
 	}
-	switch (rule->action) {
-	case AUDIT_NEVER:    *state = AUDIT_DISABLED;	    break;
-	case AUDIT_POSSIBLE: *state = AUDIT_BUILD_CONTEXT;  break;
-	case AUDIT_ALWAYS:   *state = AUDIT_RECORD_CONTEXT; break;
-	}
+	*state = state_lookup[rule->action & STATE_LOOKUP_MASK];
 	return 1;
 }
 
@@ -571,7 +584,7 @@ static int audit_filter_user_rules(struc
 	for (i = 0; i < rule->field_count; i++) {
 		u32 field  = rule->fields[i] & ~AUDIT_NEGATE;
 		u32 value  = rule->values[i];
-		int result = 0;
+		int result;
 
 		switch (field) {
 		case AUDIT_PID:
@@ -586,6 +599,8 @@ static int audit_filter_user_rules(struc
 		case AUDIT_LOGINUID:
 			result = (cb->loginuid == value);
 			break;
+		default:
+			return 0;
 		}
 
 		if (rule->fields[i] & AUDIT_NEGATE)
@@ -593,11 +608,7 @@ static int audit_filter_user_rules(struc
 		if (!result)
 			return 0;
 	}
-	switch (rule->action) {
-	case AUDIT_NEVER:    *state = AUDIT_DISABLED;	    break;
-	case AUDIT_POSSIBLE: *state = AUDIT_BUILD_CONTEXT;  break;
-	case AUDIT_ALWAYS:   *state = AUDIT_RECORD_CONTEXT; break;
-	}
+	*state = state_lookup[rule->action & STATE_LOOKUP_MASK];
 	return 1;
 }
 
@@ -762,9 +773,10 @@ int audit_alloc(struct task_struct *tsk)
 	}
 
 				/* Preserve login uid */
-	context->loginuid = -1;
 	if (current->audit_context)
 		context->loginuid = current->audit_context->loginuid;
+	else
+		context->loginuid = -1;
 
 	tsk->audit_context  = context;
 	set_tsk_thread_flag(tsk, TIF_SYSCALL_AUDIT);
@@ -1054,7 +1066,7 @@ void audit_syscall_entry(struct task_str
 	context->serial     = 0;
 	context->ctime      = CURRENT_TIME;
 	context->in_syscall = 1;
-	context->auditable  = !!(state == AUDIT_RECORD_CONTEXT);
+	context->auditable  = (state == AUDIT_RECORD_CONTEXT);
 }
 
 /* Tear down after system call.  If the audit context has been marked as
@@ -1079,15 +1091,14 @@ void audit_syscall_exit(struct task_stru
 	if (context->in_syscall && context->auditable)
 		audit_log_exit(context, GFP_KERNEL);
 
-	context->in_syscall = 0;
-	context->auditable  = 0;
-
-	if (context->previous) {
+	if (unlikely(context->previous)) {
 		struct audit_context *new_context = context->previous;
 		context->previous  = NULL;
 		audit_free_context(context);
 		tsk->audit_context = new_context;
 	} else {
+		context->in_syscall = 0;
+		context->auditable  = 0;
 		audit_free_names(context);
 		audit_free_aux(context);
 		tsk->audit_context = context;

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]