public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Matt Mackall <mpm@selenic.com>
To: Andi Kleen <andi@firstfloor.org>, Pavel Machek <pavel@suse.cz>,
	Ingo Molnar <mingo@elte.hu>
Cc: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
Subject: [RFC PATCH 2/2] Shrink compat_ioctl.c
Date: Mon, 29 Sep 2008 18:29:51 -0500	[thread overview]
Message-ID: <1222730991.23159.15.camel@calx> (raw)
In-Reply-To: <1222730830.23159.12.camel@calx>

compat-ioctl: further compactify table

Most entries use the basic compat handler, which means for most
entries it's redundant. Rather than store a handler for each entry, we
split the table so that there are two entry types, the 'basic stuff'
and the handler pointer.

At build time, the table is sorted so that each entry with a handler
pointer is two entries, handler pointer first. At init time we re-sort
the list so that all the handler pointers are at the end of the table
and each basic entry tracks the index that the corresponding handler
pointer is at.

This cuts the size of most entries in half, so the table goes from
~12k to ~7k.

diff -r b055e64aea17 -r 6841f3ce32be fs/compat_ioctl.c
--- a/fs/compat_ioctl.c	Mon Sep 29 17:28:41 2008 -0500
+++ b/fs/compat_ioctl.c	Mon Sep 29 17:28:44 2008 -0500
@@ -1825,21 +1825,26 @@
 					unsigned long, struct file *);
 
 struct ioctl_trans {
-	ioctl_trans_handler_t handler;
-	unsigned int cmd;
-	unsigned short next;
+	union {
+		struct {
+			unsigned int cmd;
+			short handle; /* index of entry containing fn ptr */
+			short next; /* index of next entry in hash chain */
+		} e;
+		ioctl_trans_handler_t handler;
+	} u;
 };
 
-#define HANDLE_IOCTL(cmd,handler) \
-	{ (ioctl_trans_handler_t)(handler), (cmd)},
+#define HANDLE_IOCTL(command, fn) \
+	{{ .handler = (ioctl_trans_handler_t)(fn) }},	\
+	{{ .e = { .cmd = (command), .handle = 1 }}},
+
+/* argument is an unsigned long integer, not a pointer */
+#define ULONG_IOCTL(cmd) HANDLE_IOCTL(cmd, sys_ioctl)
 
 /* pointer to compatible structure or no argument */
-#define COMPATIBLE_IOCTL(cmd) \
-	{ do_ioctl32_pointer, (cmd) },
-
-/* argument is an unsigned long integer, not a pointer */
-#define ULONG_IOCTL(cmd) \
-	{ (ioctl_trans_handler_t)sys_ioctl, (cmd) },
+#define COMPATIBLE_IOCTL(command) \
+	{{ .e = { .cmd = (command) }}},
 
 /* ioctl should not be warned about even if it's not implemented.
    Valid reasons to use this:
@@ -2814,8 +2819,8 @@
 		break;
 	}
 
-	for (t = ioctl32_hash(cmd); t >= 0; t = ioctl_table[t].next) {
-		if (ioctl_table[t].cmd == cmd)
+	for (t = ioctl32_hash(cmd); t >= 0; t = ioctl_table[t].u.e.next) {
+		if (ioctl_table[t].u.e.cmd == cmd)
 			goto found_handler;
 	}
 
@@ -2836,12 +2841,13 @@
 	goto out_fput;
 
  found_handler:
-	if (ioctl_table[t].handler) {
-		lock_kernel();
-		error = ioctl_table[t].handler(fd, cmd, arg, filp);
-		unlock_kernel();
-		goto out_fput;
-	}
+	lock_kernel();
+	if (ioctl_table[t].u.e.handle)
+		error = ioctl_table[ioctl_table[t].u.e.handle].u.handler(fd, cmd, arg, filp);
+	else
+		error = do_ioctl32_pointer(fd, cmd, arg, filp);
+	unlock_kernel();
+	goto out_fput;
 
  do_ioctl:
 	error = do_vfs_ioctl(filp, fd, cmd, arg);
@@ -2853,23 +2859,38 @@
 
 static int __init init_sys32_ioctl(void)
 {
-	int i;
+	int i, top;
 	unsigned long hash;
 	struct ioctl_trans t;
 
+	/* walk table backward moving handler entries to the end */
+	top = ARRAY_SIZE(ioctl_table) - 1;
+	for (i = top; i >= 0; i--)
+		if (ioctl_table[i].u.e.handle) {
+			/* next entry down is a handler pointer, swap to top */
+			t = ioctl_table[top];
+			ioctl_table[top] = ioctl_table[i - 1];
+			ioctl_table[i - 1] = t;
+			/* fix up handle index for current entry */
+			ioctl_table[i].u.e.handle = top;
+			/* update top and skip next entry */
+			top--;
+			i--;
+		}
+
 	/* hash-order table in-place */
-	for (i = 0; i < ARRAY_SIZE(ioctl_table); i++) {
-		hash = ioctl32_hash(ioctl_table[i].cmd);
+	for (i = 0; i <= top; i++) {
+		hash = ioctl32_hash(ioctl_table[i].u.e.cmd);
 		t = ioctl_table[hash];
 		ioctl_table[hash] = ioctl_table[i];
 		ioctl_table[i] = t;
 	}
 
 	/* link entries outside of hash area */
-	for (i = IOCTL_HASHSIZE; i < ARRAY_SIZE(ioctl_table); i++) {
-		hash = ioctl32_hash(ioctl_table[i].cmd);
-		ioctl_table[i].next = ioctl_table[hash].next;
-		ioctl_table[hash].next = i;
+	for (i = IOCTL_HASHSIZE; i <= top; i++) {
+		hash = ioctl32_hash(ioctl_table[i].u.e.cmd);
+		ioctl_table[i].u.e.next = ioctl_table[hash].u.e.next;
+		ioctl_table[hash].u.e.next = i;
 	}
 	return 0;
 }

-- 
Mathematics is the supreme nostalgia of our time.


  reply	other threads:[~2008-09-29 23:32 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-09-29 23:27 [RFC PATCH 1/2] Shrink compat_ioctl.c Matt Mackall
2008-09-29 23:29 ` Matt Mackall [this message]
2008-09-29 23:38 ` Andi Kleen
2008-09-29 23:38   ` Matt Mackall

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1222730991.23159.15.camel@calx \
    --to=mpm@selenic.com \
    --cc=andi@firstfloor.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@elte.hu \
    --cc=pavel@suse.cz \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox