TOMOYO: Use callback for updating entries.

Use common code for elements using "struct list_head" + "bool" structure.

Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: James Morris <jmorris@namei.org>
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c
index 09436d1..8015719 100644
--- a/security/tomoyo/file.c
+++ b/security/tomoyo/file.c
@@ -253,6 +253,15 @@
  */
 LIST_HEAD(tomoyo_globally_readable_list);
 
+static bool tomoyo_same_globally_readable(const struct tomoyo_acl_head *a,
+					  const struct tomoyo_acl_head *b)
+{
+	return container_of(a, struct tomoyo_globally_readable_file_entry,
+			    head)->filename ==
+		container_of(b, struct tomoyo_globally_readable_file_entry,
+			     head)->filename;
+}
+
 /**
  * tomoyo_update_globally_readable_entry - Update "struct tomoyo_globally_readable_file_entry" list.
  *
@@ -266,36 +275,17 @@
 static int tomoyo_update_globally_readable_entry(const char *filename,
 						 const bool is_delete)
 {
-	struct tomoyo_globally_readable_file_entry *ptr;
 	struct tomoyo_globally_readable_file_entry e = { };
-	int error = is_delete ? -ENOENT : -ENOMEM;
+	int error;
 
 	if (!tomoyo_is_correct_word(filename))
 		return -EINVAL;
 	e.filename = tomoyo_get_name(filename);
 	if (!e.filename)
 		return -ENOMEM;
-	if (mutex_lock_interruptible(&tomoyo_policy_lock))
-		goto out;
-	list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list,
-				head.list) {
-		if (ptr->filename != e.filename)
-			continue;
-		ptr->head.is_deleted = is_delete;
-		error = 0;
-		break;
-	}
-	if (!is_delete && error) {
-		struct tomoyo_globally_readable_file_entry *entry =
-			tomoyo_commit_ok(&e, sizeof(e));
-		if (entry) {
-			list_add_tail_rcu(&entry->head.list,
-					  &tomoyo_globally_readable_list);
-			error = 0;
-		}
-	}
-	mutex_unlock(&tomoyo_policy_lock);
- out:
+	error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
+				     &tomoyo_globally_readable_list,
+				     tomoyo_same_globally_readable);
 	tomoyo_put_name(e.filename);
 	return error;
 }
@@ -402,6 +392,13 @@
  */
 LIST_HEAD(tomoyo_pattern_list);
 
+static bool tomoyo_same_pattern(const struct tomoyo_acl_head *a,
+				const struct tomoyo_acl_head *b)
+{
+	return container_of(a, struct tomoyo_pattern_entry, head)->pattern ==
+		container_of(b, struct tomoyo_pattern_entry, head)->pattern;
+}
+
 /**
  * tomoyo_update_file_pattern_entry - Update "struct tomoyo_pattern_entry" list.
  *
@@ -415,35 +412,17 @@
 static int tomoyo_update_file_pattern_entry(const char *pattern,
 					    const bool is_delete)
 {
-	struct tomoyo_pattern_entry *ptr;
 	struct tomoyo_pattern_entry e = { };
-	int error = is_delete ? -ENOENT : -ENOMEM;
+	int error;
 
 	if (!tomoyo_is_correct_word(pattern))
 		return -EINVAL;
 	e.pattern = tomoyo_get_name(pattern);
 	if (!e.pattern)
-		return error;
-	if (mutex_lock_interruptible(&tomoyo_policy_lock))
-		goto out;
-	list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, head.list) {
-		if (e.pattern != ptr->pattern)
-			continue;
-		ptr->head.is_deleted = is_delete;
-		error = 0;
-		break;
-	}
-	if (!is_delete && error) {
-		struct tomoyo_pattern_entry *entry =
-			tomoyo_commit_ok(&e, sizeof(e));
-		if (entry) {
-			list_add_tail_rcu(&entry->head.list,
-					  &tomoyo_pattern_list);
-			error = 0;
-		}
-	}
-	mutex_unlock(&tomoyo_policy_lock);
- out:
+		return -ENOMEM;
+	error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
+				     &tomoyo_pattern_list,
+				     tomoyo_same_pattern);
 	tomoyo_put_name(e.pattern);
 	return error;
 }
@@ -553,6 +532,14 @@
  */
 LIST_HEAD(tomoyo_no_rewrite_list);
 
+static bool tomoyo_same_no_rewrite(const struct tomoyo_acl_head *a,
+				   const struct tomoyo_acl_head *b)
+{
+	return container_of(a, struct tomoyo_no_rewrite_entry, head)->pattern
+		== container_of(b, struct tomoyo_no_rewrite_entry, head)
+		->pattern;
+}
+
 /**
  * tomoyo_update_no_rewrite_entry - Update "struct tomoyo_no_rewrite_entry" list.
  *
@@ -566,35 +553,17 @@
 static int tomoyo_update_no_rewrite_entry(const char *pattern,
 					  const bool is_delete)
 {
-	struct tomoyo_no_rewrite_entry *ptr;
 	struct tomoyo_no_rewrite_entry e = { };
-	int error = is_delete ? -ENOENT : -ENOMEM;
+	int error;
 
 	if (!tomoyo_is_correct_word(pattern))
 		return -EINVAL;
 	e.pattern = tomoyo_get_name(pattern);
 	if (!e.pattern)
-		return error;
-	if (mutex_lock_interruptible(&tomoyo_policy_lock))
-		goto out;
-	list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, head.list) {
-		if (ptr->pattern != e.pattern)
-			continue;
-		ptr->head.is_deleted = is_delete;
-		error = 0;
-		break;
-	}
-	if (!is_delete && error) {
-		struct tomoyo_no_rewrite_entry *entry =
-			tomoyo_commit_ok(&e, sizeof(e));
-		if (entry) {
-			list_add_tail_rcu(&entry->head.list,
-					  &tomoyo_no_rewrite_list);
-			error = 0;
-		}
-	}
-	mutex_unlock(&tomoyo_policy_lock);
- out:
+		return -ENOMEM;
+	error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
+				     &tomoyo_no_rewrite_list,
+				     tomoyo_same_no_rewrite);
 	tomoyo_put_name(e.pattern);
 	return error;
 }