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 <linux/compat_ioctl.h>
@@ -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 <linux/compat_ioctl.h>
@@ -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 <linux/compat_ioctl.h>
 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 <linux/compat_ioctl.h>
@@ -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 <linux/compat_ioctl.h>
@@ -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 <linux/compat_ioctl.h>
@@ -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 <linux/compat_ioctl.h>
@@ -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: 

_