[PATCH] fs/proc: optimize exactly register one ctl_table

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

 



Currently, sysctl is being moved to its own file. But ctl_table
is quite large(64 bytes per entry) and every array is terminated
with an empty one. This leads to thar when register exactly one
ctl_table, we've gone from 64 bytes to 128 bytes.

So, it is obviously the right thing that we need to fix.

In order to avoid compatibility problems, and to be compatible
with array terminated with an empty one and register exactly one
ctl_table, add the register_one variable in the ctl_table
structure to fix it.

When we register exactly one table, we only need to add
"table->register = true" to avoid gone from 64 bytes to 128 bytes.

Signed-off-by: Meng Tang <tangmeng@xxxxxxxxxxxxx>
---
 fs/proc/proc_sysctl.c  | 58 +++++++++++++++++++++++++++++++++++++++---
 include/linux/sysctl.h |  1 +
 2 files changed, 56 insertions(+), 3 deletions(-)

diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index 7d9cfc730bd4..9ecd5c87e8dd 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -215,16 +215,24 @@ static void init_header(struct ctl_table_header *head,
 	INIT_HLIST_HEAD(&head->inodes);
 	if (node) {
 		struct ctl_table *entry;
-		for (entry = table; entry->procname; entry++, node++)
+		for (entry = table; entry->procname; entry++, node++) {
 			node->header = head;
+
+			if (entry->register_one)
+				break;
+		}
 	}
 }
 
 static void erase_header(struct ctl_table_header *head)
 {
 	struct ctl_table *entry;
-	for (entry = head->ctl_table; entry->procname; entry++)
+	for (entry = head->ctl_table; entry->procname; entry++) {
 		erase_entry(head, entry);
+
+		if (entry->register_one)
+			break;
+	}
 }
 
 static int insert_header(struct ctl_dir *dir, struct ctl_table_header *header)
@@ -252,6 +260,9 @@ static int insert_header(struct ctl_dir *dir, struct ctl_table_header *header)
 		err = insert_entry(header, entry);
 		if (err)
 			goto fail;
+
+		if (entry->register_one)
+			break;
 	}
 	return 0;
 fail:
@@ -1159,6 +1170,9 @@ static int sysctl_check_table(const char *path, struct ctl_table *table)
 		if ((table->mode & (S_IRUGO|S_IWUGO)) != table->mode)
 			err |= sysctl_err(path, table, "bogus .mode 0%o",
 				table->mode);
+
+		if (table->register_one)
+			break;
 	}
 	return err;
 }
@@ -1177,6 +1191,9 @@ static struct ctl_table_header *new_links(struct ctl_dir *dir, struct ctl_table
 	for (entry = table; entry->procname; entry++) {
 		nr_entries++;
 		name_bytes += strlen(entry->procname) + 1;
+
+		if (entry->register_one)
+			break;
 	}
 
 	links = kzalloc(sizeof(struct ctl_table_header) +
@@ -1199,6 +1216,9 @@ static struct ctl_table_header *new_links(struct ctl_dir *dir, struct ctl_table
 		link->mode = S_IFLNK|S_IRWXUGO;
 		link->data = link_root;
 		link_name += len;
+
+		if (entry->register_one)
+			break;
 	}
 	init_header(links, dir->header.root, dir->header.set, node, link_table);
 	links->nreg = nr_entries;
@@ -1218,6 +1238,15 @@ static bool get_links(struct ctl_dir *dir,
 		link = find_entry(&head, dir, procname, strlen(procname));
 		if (!link)
 			return false;
+
+		if (entry->register_one) {
+			if (S_ISDIR(link->mode) && S_ISDIR(entry->mode))
+				break;
+			if (S_ISLNK(link->mode) && (link->data == link_root))
+				break;
+			return false;
+		}
+
 		if (S_ISDIR(link->mode) && S_ISDIR(entry->mode))
 			continue;
 		if (S_ISLNK(link->mode) && (link->data == link_root))
@@ -1230,6 +1259,8 @@ static bool get_links(struct ctl_dir *dir,
 		const char *procname = entry->procname;
 		link = find_entry(&head, dir, procname, strlen(procname));
 		head->nreg++;
+		if (entry->register_one)
+			break;
 	}
 	return true;
 }
@@ -1295,6 +1326,8 @@ static int insert_links(struct ctl_table_header *head)
  *
  * mode - the file permissions for the /proc/sys file
  *
+ * register_one - set to true when exactly register one ctl_table
+ *
  * child - must be %NULL.
  *
  * proc_handler - the text handler routine (described below)
@@ -1329,9 +1362,13 @@ struct ctl_table_header *__register_sysctl_table(
 	struct ctl_node *node;
 	int nr_entries = 0;
 
-	for (entry = table; entry->procname; entry++)
+	for (entry = table; entry->procname; entry++) {
 		nr_entries++;
 
+		if (entry->register_one)
+			break;
+	}
+
 	header = kzalloc(sizeof(struct ctl_table_header) +
 			 sizeof(struct ctl_node)*nr_entries, GFP_KERNEL);
 	if (!header)
@@ -1461,6 +1498,9 @@ static int count_subheaders(struct ctl_table *table)
 			nr_subheaders += count_subheaders(entry->child);
 		else
 			has_files = 1;
+
+		if (entry->register_one)
+			break;
 	}
 	return nr_subheaders + has_files;
 }
@@ -1480,6 +1520,9 @@ static int register_leaf_sysctl_tables(const char *path, char *pos,
 			nr_dirs++;
 		else
 			nr_files++;
+
+		if (entry->register_one)
+			break;
 	}
 
 	files = table;
@@ -1497,6 +1540,9 @@ static int register_leaf_sysctl_tables(const char *path, char *pos,
 				continue;
 			*new = *entry;
 			new++;
+
+			if (entry->register_one)
+				break;
 		}
 	}
 
@@ -1532,6 +1578,9 @@ static int register_leaf_sysctl_tables(const char *path, char *pos,
 		pos[0] = '\0';
 		if (err)
 			goto out;
+
+		if (entry->register_one)
+			break;
 	}
 	err = 0;
 out:
@@ -1686,6 +1735,9 @@ static void put_links(struct ctl_table_header *header)
 			sysctl_print_dir(parent);
 			pr_cont("%s\n", name);
 		}
+
+		if (entry->register_one)
+			break;
 	}
 }
 
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 6353d6db69b2..889c995d8a08 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -134,6 +134,7 @@ struct ctl_table {
 	void *data;
 	int maxlen;
 	umode_t mode;
+	bool register_one;		/* Exactly register one ctl_table*/
 	struct ctl_table *child;	/* Deprecated */
 	proc_handler *proc_handler;	/* Callback for text formatting */
 	struct ctl_table_poll *poll;
-- 
2.20.1






[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [NTFS 3]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [NTFS 3]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux