xdr_proc_t really is different on linux26_i386
authorSimon Wilkinson <sxw@your-file-system.com>
Tue, 2 Feb 2010 13:14:28 +0000 (13:14 +0000)
committerDerrick Brashear <shadow|account-1000005@unknown>
Tue, 2 Feb 2010 14:02:36 +0000 (06:02 -0800)
i386 Linux uses a register based calling convention within the
kernel, but uses the stack for va_args based functions. This means
that the hack of prototyping xdrproc_t as a va_args function doesn't
work, as you end up with arguments being in the wrong place.

Restore the Linux only xdrproc_t prototype that
167e1aa21f5bbea1272b239dc6518a7bdbfc3ee6 removed, add a warning to
explain why its there, and modify xdr_free() so that it works
without error.

Change-Id: I789d387b01fcb892b187fe05f961f01c2c1f55e4
Reviewed-on: http://gerrit.openafs.org/1202
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Tested-by: Derrick Brashear <shadow@dementia.org>

src/rx/xdr.c
src/rx/xdr.h

index 4481c39..e05293e 100644 (file)
@@ -594,6 +594,12 @@ xdr_free(xdrproc_t proc, void *obj)
     XDR x;
 
     x.x_op = XDR_FREE;
+
+    /* See note in xdr.h for the method behind this madness */
+#if defined(AFS_I386_LINUX26_ENV) && defined(KERNEL) && !defined(UKERNEL)
+    (*proc)(&x, obj, 0);
+#else
     (*proc)(&x, obj);
+#endif
 }
 #endif /* NeXT */
index c91d17a..2936e29 100644 (file)
@@ -174,8 +174,17 @@ enum xdr_op {
  * allocate dynamic storage of the appropriate size and return it.
  * bool_t      (*xdrproc_t)(XDR *, caddr_t *);
  */
-typedef bool_t(*xdrproc_t) (void *, ...);
 
+/* We need a different prototype for i386 Linux kernel code, because it 
+ * uses a register (rather than stack) based calling convention. The
+ * normal va_args prototype results in the arguments being placed on the
+ * stack, where they aren't accessible to the 'real' function.
+ */
+#if defined(AFS_I386_LINUX26_ENV) && defined(KERNEL) && !defined(UKERNEL)
+typedef bool_t(*xdrproc_t) (void *, caddr_t, u_int);
+#else
+typedef bool_t(*xdrproc_t) (void *, ...);
+#endif
 
 /*
  * The XDR handle.