The arch ioctl tables are doing this: struct foo ioctl_start[] = { ... }; struct foo ioctl_end[0]; and fs/compat.c expects that the table lies between &ioctl_end and &ioctl_start. Problem is, gcc-3.3 puts ioctl_end into bss, even if it is initialised. It doesn't work. So we do away with the ioctl_end thing and add int ioctl_table_length = ARRAY_SIZE(ioctl_start); to each architecture. 25-akpm/arch/ia64/ia32/ia32_ioctl.c | 4 +++- 25-akpm/arch/mips/kernel/ioctl32.c | 5 +++-- 25-akpm/arch/parisc/kernel/ioctl32.c | 3 ++- 25-akpm/arch/ppc64/kernel/ioctl32.c | 4 +++- 25-akpm/arch/s390/kernel/compat_ioctl.c | 4 +++- 25-akpm/arch/sparc64/kernel/ioctl32.c | 4 +++- 25-akpm/arch/x86_64/ia32/ia32_ioctl.c | 9 ++++----- 25-akpm/fs/compat.c | 8 ++++---- 8 files changed, 25 insertions(+), 16 deletions(-) diff -puN arch/sparc64/kernel/ioctl32.c~ioctl_end-fix arch/sparc64/kernel/ioctl32.c --- 25/arch/sparc64/kernel/ioctl32.c~ioctl_end-fix Thu Aug 28 15:04:05 2003 +++ 25-akpm/arch/sparc64/kernel/ioctl32.c Thu Aug 28 15:04:05 2003 @@ -1388,7 +1388,7 @@ typedef int (* ioctl32_handler_t)(unsign #define IOCTL_TABLE_START \ struct ioctl_trans ioctl_start[] = { #define IOCTL_TABLE_END \ - }; struct ioctl_trans ioctl_end[0]; + }; IOCTL_TABLE_START #include @@ -1583,3 +1583,5 @@ HANDLE_IOCTL(USBDEVFS_REAPURBNDELAY32, d HANDLE_IOCTL(USBDEVFS_DISCSIGNAL32, do_usbdevfs_discsignal) /* take care of sizeof(sizeof()) breakage */ IOCTL_TABLE_END + +int ioctl_table_size = ARRAY_SIZE(ioctl_start); diff -puN arch/mips/kernel/ioctl32.c~ioctl_end-fix arch/mips/kernel/ioctl32.c --- 25/arch/mips/kernel/ioctl32.c~ioctl_end-fix Thu Aug 28 15:04:05 2003 +++ 25-akpm/arch/mips/kernel/ioctl32.c Thu Aug 28 15:04:05 2003 @@ -810,8 +810,7 @@ typedef int (* ioctl32_handler_t)(unsign #define IOCTL_TABLE_START \ struct ioctl_trans ioctl_start[] = { #define IOCTL_TABLE_END \ - }; struct ioctl_trans ioctl_end[0]; - + }; IOCTL_TABLE_START #include @@ -1206,5 +1205,7 @@ COMPATIBLE_IOCTL(RTC_WKALM_SET) COMPATIBLE_IOCTL(RTC_WKALM_RD) IOCTL_TABLE_END +int ioctl_table_size = ARRAY_SIZE(ioctl_start); + #define NR_IOCTL_TRANS (sizeof(ioctl_translations) / \ sizeof(ioctl_translations[0])) diff -puN arch/ia64/ia32/ia32_ioctl.c~ioctl_end-fix arch/ia64/ia32/ia32_ioctl.c --- 25/arch/ia64/ia32/ia32_ioctl.c~ioctl_end-fix Thu Aug 28 15:04:05 2003 +++ 25-akpm/arch/ia64/ia32/ia32_ioctl.c Thu Aug 28 15:04:05 2003 @@ -70,7 +70,7 @@ typedef int (* ioctl32_handler_t)(unsign #define IOCTL_TABLE_START \ struct ioctl_trans ioctl_start[] = { #define IOCTL_TABLE_END \ - }; struct ioctl_trans ioctl_end[0]; + }; IOCTL_TABLE_START HANDLE_IOCTL(VFAT_IOCTL_READDIR_BOTH32, vfat_ioctl32) @@ -79,3 +79,5 @@ HANDLE_IOCTL(VFAT_IOCTL_READDIR_SHORT32, #include "compat_ioctl.c" #include IOCTL_TABLE_END + +int ioctl_table_size = ARRAY_SIZE(ioctl_start); diff -puN arch/ppc64/kernel/ioctl32.c~ioctl_end-fix arch/ppc64/kernel/ioctl32.c --- 25/arch/ppc64/kernel/ioctl32.c~ioctl_end-fix Thu Aug 28 15:04:05 2003 +++ 25-akpm/arch/ppc64/kernel/ioctl32.c Thu Aug 28 15:04:05 2003 @@ -725,7 +725,7 @@ static int do_usbdevfs_discsignal(unsign #define IOCTL_TABLE_START \ struct ioctl_trans ioctl_start[] = { #define IOCTL_TABLE_END \ - }; struct ioctl_trans ioctl_end[0]; + }; IOCTL_TABLE_START #include @@ -763,3 +763,5 @@ HANDLE_IOCTL(USBDEVFS_REAPURB32, do_usbd HANDLE_IOCTL(USBDEVFS_REAPURBNDELAY32, do_usbdevfs_reapurb) HANDLE_IOCTL(USBDEVFS_DISCSIGNAL32, do_usbdevfs_discsignal) IOCTL_TABLE_END + +int ioctl_table_size = ARRAY_SIZE(ioctl_start); diff -puN arch/parisc/kernel/ioctl32.c~ioctl_end-fix arch/parisc/kernel/ioctl32.c --- 25/arch/parisc/kernel/ioctl32.c~ioctl_end-fix Thu Aug 28 15:04:05 2003 +++ 25-akpm/arch/parisc/kernel/ioctl32.c Thu Aug 28 15:04:05 2003 @@ -2458,7 +2458,7 @@ int siocdevprivate_ioctl(unsigned int fd #define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL(cmd, sys_ioctl) #define IOCTL_TABLE_START struct ioctl_trans ioctl_start[] = { -#define IOCTL_TABLE_END }; struct ioctl_trans ioctl_end[0]; +#define IOCTL_TABLE_END }; IOCTL_TABLE_START #include @@ -2631,3 +2631,4 @@ HANDLE_IOCTL(DRM32_IOCTL_RES_CTX, drm32_ #endif /* DRM */ IOCTL_TABLE_END +int ioctl_table_size = ARRAY_SIZE(ioctl_start); diff -puN arch/x86_64/ia32/ia32_ioctl.c~ioctl_end-fix arch/x86_64/ia32/ia32_ioctl.c --- 25/arch/x86_64/ia32/ia32_ioctl.c~ioctl_end-fix Thu Aug 28 15:04:05 2003 +++ 25-akpm/arch/x86_64/ia32/ia32_ioctl.c Thu Aug 28 15:04:18 2003 @@ -673,12 +673,10 @@ static int mtrr_ioctl32(unsigned int fd, return err; } -#define REF_SYMBOL(handler) if (0) (void)handler; -#define HANDLE_IOCTL2(cmd,handler) REF_SYMBOL(handler); asm volatile(".quad %P0, " #handler ",0"::"i" (cmd)); -#define HANDLE_IOCTL(cmd,handler) HANDLE_IOCTL2(cmd,handler) +#define HANDLE_IOCTL(cmd,handler) { (cmd), (ioctl_trans_handler_t)(handler), NULL }, #define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL(cmd,sys_ioctl) -#define IOCTL_TABLE_START void ioctl_dummy(void) { asm volatile("\n.global ioctl_start\nioctl_start:\n\t" ); -#define IOCTL_TABLE_END asm volatile("\n.global ioctl_end;\nioctl_end:\n"); } +#define IOCTL_TABLE_START struct ioctl_trans ioctl_start[] = { +#define IOCTL_TABLE_END }; IOCTL_TABLE_START #include @@ -765,3 +763,4 @@ HANDLE_IOCTL(MTRRIOC32_GET_PAGE_ENTRY, m HANDLE_IOCTL(MTRRIOC32_KILL_PAGE_ENTRY, mtrr_ioctl32) IOCTL_TABLE_END +int ioctl_table_size = ARRAY_SIZE(ioctl_start); diff -puN arch/s390/kernel/compat_ioctl.c~ioctl_end-fix arch/s390/kernel/compat_ioctl.c --- 25/arch/s390/kernel/compat_ioctl.c~ioctl_end-fix Thu Aug 28 15:04:05 2003 +++ 25-akpm/arch/s390/kernel/compat_ioctl.c Thu Aug 28 15:04:05 2003 @@ -808,7 +808,7 @@ int siocdevprivate_ioctl(unsigned int fd #define IOCTL_TABLE_START \ struct ioctl_trans ioctl_start[] = { #define IOCTL_TABLE_END \ - }; struct ioctl_trans ioctl_end[0]; + }; IOCTL_TABLE_START #include @@ -899,3 +899,5 @@ HANDLE_IOCTL(BLKSECTGET, w_long) HANDLE_IOCTL(BLKPG, blkpg_ioctl_trans) IOCTL_TABLE_END + +int ioctl_table_size = ARRAY_SIZE(ioctl_start); diff -puN fs/compat.c~ioctl_end-fix fs/compat.c --- 25/fs/compat.c~ioctl_end-fix Thu Aug 28 15:04:05 2003 +++ 25-akpm/fs/compat.c Thu Aug 28 15:04:05 2003 @@ -227,7 +227,8 @@ out: #define IOCTL_HASHSIZE 256 struct ioctl_trans *ioctl32_hash_table[IOCTL_HASHSIZE]; -extern struct ioctl_trans ioctl_start[], ioctl_end[]; +extern struct ioctl_trans ioctl_start[]; +extern int ioctl_table_size; static inline unsigned long ioctl32_hash(unsigned long cmd) { @@ -255,7 +256,7 @@ static int __init init_sys32_ioctl(void) { int i; - for (i = 0; &ioctl_start[i] < &ioctl_end[0]; i++) { + for (i = 0; i < ioctl_table_size; i++) { if (ioctl_start[i].next != 0) { printk("ioctl translation %d bad\n",i); return -1; @@ -318,8 +319,7 @@ int register_ioctl32_conversion(unsigned static inline int builtin_ioctl(struct ioctl_trans *t) { - return t >= (struct ioctl_trans *)ioctl_start && - t < (struct ioctl_trans *)ioctl_end; + return t >= ioctl_start && t < (ioctl_start + ioctl_table_size); } /* Problem: _