[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <1222730830.23159.12.camel@calx>
Date: Mon, 29 Sep 2008 18:27:10 -0500
From: Matt Mackall <mpm@...enic.com>
To: Andi Kleen <andi@...stfloor.org>, Pavel Machek <pavel@...e.cz>,
Ingo Molnar <mingo@...e.hu>
Cc: Linux Kernel Mailing List <linux-kernel@...r.kernel.org>
Subject: [RFC PATCH 1/2] Shrink compat_ioctl.c
I'm throwing this out untested as I don't have a mixed 64/32 system
handy at the moment.
compat_ioctl: shrink structures
Initially, compat_ioctl.c has a ~18k table of translated ioctls.
Each table entry is 24 bytes but we can shrink this to 16:
- use short table indexes rather than a pointer for .next values
- use unsigned ints for cmd numbers (they're 32-bit ioctls, after all)
In addition, there's a 2k hash table that we can do away with simply
by hashifying the main table in place at init time.
This saves about 6k data and 2k BSS.
diff -r f6d1daaf90b2 -r b055e64aea17 fs/compat_ioctl.c
--- a/fs/compat_ioctl.c Mon Sep 29 17:28:28 2008 -0500
+++ b/fs/compat_ioctl.c Mon Sep 29 17:28:41 2008 -0500
@@ -1825,21 +1825,21 @@
unsigned long, struct file *);
struct ioctl_trans {
- unsigned long cmd;
ioctl_trans_handler_t handler;
- struct ioctl_trans *next;
+ unsigned int cmd;
+ unsigned short next;
};
#define HANDLE_IOCTL(cmd,handler) \
- { (cmd), (ioctl_trans_handler_t)(handler) },
+ { (ioctl_trans_handler_t)(handler), (cmd)},
/* pointer to compatible structure or no argument */
#define COMPATIBLE_IOCTL(cmd) \
- { (cmd), do_ioctl32_pointer },
+ { do_ioctl32_pointer, (cmd) },
/* argument is an unsigned long integer, not a pointer */
#define ULONG_IOCTL(cmd) \
- { (cmd), (ioctl_trans_handler_t)sys_ioctl },
+ { (ioctl_trans_handler_t)sys_ioctl, (cmd) },
/* ioctl should not be warned about even if it's not implemented.
Valid reasons to use this:
@@ -1850,7 +1850,7 @@
Most other reasons are not valid. */
#define IGNORE_IOCTL(cmd) COMPATIBLE_IOCTL(cmd)
-static struct ioctl_trans ioctl_start[] = {
+static struct ioctl_trans ioctl_table[] = {
/* compatible ioctls first */
COMPATIBLE_IOCTL(0x4B50) /* KDGHWCLK - not in the kernel, but don't complain */
COMPATIBLE_IOCTL(0x4B51) /* KDSHWCLK - not in the kernel, but don't complain */
@@ -2728,10 +2728,9 @@
#endif
};
-#define IOCTL_HASHSIZE 256
-static struct ioctl_trans *ioctl32_hash_table[IOCTL_HASHSIZE];
+#define IOCTL_HASHSIZE 256 /* must be less than table size */
-static inline unsigned long ioctl32_hash(unsigned long cmd)
+static inline unsigned int ioctl32_hash(unsigned int cmd)
{
return (((cmd >> 6) ^ (cmd >> 4) ^ cmd)) % IOCTL_HASHSIZE;
}
@@ -2770,7 +2769,7 @@
{
struct file *filp;
int error = -EBADF;
- struct ioctl_trans *t;
+ int t;
int fput_needed;
filp = fget_light(fd, &fput_needed);
@@ -2815,8 +2814,8 @@
break;
}
- for (t = ioctl32_hash_table[ioctl32_hash(cmd)]; t; t = t->next) {
- if (t->cmd == cmd)
+ for (t = ioctl32_hash(cmd); t >= 0; t = ioctl_table[t].next) {
+ if (ioctl_table[t].cmd == cmd)
goto found_handler;
}
@@ -2837,9 +2836,9 @@
goto out_fput;
found_handler:
- if (t->handler) {
+ if (ioctl_table[t].handler) {
lock_kernel();
- error = t->handler(fd, cmd, arg, filp);
+ error = ioctl_table[t].handler(fd, cmd, arg, filp);
unlock_kernel();
goto out_fput;
}
@@ -2852,34 +2851,25 @@
return error;
}
-static void ioctl32_insert_translation(struct ioctl_trans *trans)
-{
- unsigned long hash;
- struct ioctl_trans *t;
-
- hash = ioctl32_hash (trans->cmd);
- if (!ioctl32_hash_table[hash])
- ioctl32_hash_table[hash] = trans;
- else {
- t = ioctl32_hash_table[hash];
- while (t->next)
- t = t->next;
- trans->next = NULL;
- t->next = trans;
- }
-}
-
static int __init init_sys32_ioctl(void)
{
int i;
+ unsigned long hash;
+ struct ioctl_trans t;
- for (i = 0; i < ARRAY_SIZE(ioctl_start); i++) {
- if (ioctl_start[i].next) {
- printk("ioctl translation %d bad\n",i);
- return -1;
- }
+ /* hash-order table in-place */
+ for (i = 0; i < ARRAY_SIZE(ioctl_table); i++) {
+ hash = ioctl32_hash(ioctl_table[i].cmd);
+ t = ioctl_table[hash];
+ ioctl_table[hash] = ioctl_table[i];
+ ioctl_table[i] = t;
+ }
- ioctl32_insert_translation(&ioctl_start[i]);
+ /* 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;
}
return 0;
}
--
Mathematics is the supreme nostalgia of our time.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists