Author: hselasky
Date: Sat Nov 29 05:08:29 2014
New Revision: 275231
URL: https://svnweb.freebsd.org/changeset/base/275231

Log:
  MFC r274017, r274088 and r275205:
  
  Provide an on-stack temporary buffer for small IOCTL requests.
  Avoiding a memory allocation per IOCTL request can give a significant
  speedup for applications which heavily rely on IOCTLs.

Modified:
  stable/9/sys/kern/sys_generic.c
Directory Properties:
  stable/9/sys/   (props changed)

Modified: stable/9/sys/kern/sys_generic.c
==============================================================================
--- stable/9/sys/kern/sys_generic.c     Sat Nov 29 05:07:24 2014        
(r275230)
+++ stable/9/sys/kern/sys_generic.c     Sat Nov 29 05:08:29 2014        
(r275231)
@@ -74,6 +74,20 @@ __FBSDID("$FreeBSD$");
 
 #include <security/audit/audit.h>
 
+/*
+ * The following macro defines how many bytes will be allocated from
+ * the stack instead of memory allocated when passing the IOCTL data
+ * structures from userspace and to the kernel. Some IOCTLs having
+ * small data structures are used very frequently and this small
+ * buffer on the stack gives a significant speedup improvement for
+ * those requests. The value of this define should be greater or equal
+ * to 64 bytes and should also be power of two. The data structure is
+ * currently hard-aligned to a 8-byte boundary on the stack. This
+ * should currently be sufficient for all supported platforms.
+ */
+#define        SYS_IOCTL_SMALL_SIZE    128     /* bytes */
+#define        SYS_IOCTL_SMALL_ALIGN   8       /* bytes */
+
 int iosize_max_clamp = 1;
 SYSCTL_INT(_debug, OID_AUTO, iosize_max_clamp, CTLFLAG_RW,
     &iosize_max_clamp, 0, "Clamp max i/o size to INT_MAX");
@@ -640,6 +654,7 @@ struct ioctl_args {
 int
 sys_ioctl(struct thread *td, struct ioctl_args *uap)
 {
+       u_char smalldata[SYS_IOCTL_SMALL_SIZE] __aligned(SYS_IOCTL_SMALL_ALIGN);
        u_long com;
        int arg, error;
        u_int size;
@@ -674,17 +689,18 @@ sys_ioctl(struct thread *td, struct ioct
                        arg = (intptr_t)uap->data;
                        data = (void *)&arg;
                        size = 0;
-               } else
-                       data = malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
+               } else {
+                       if (size > SYS_IOCTL_SMALL_SIZE)
+                               data = malloc((u_long)size, M_IOCTLOPS, 
M_WAITOK);
+                       else
+                               data = smalldata;
+               }
        } else
                data = (void *)&uap->data;
        if (com & IOC_IN) {
                error = copyin(uap->data, data, (u_int)size);
-               if (error) {
-                       if (size > 0)
-                               free(data, M_IOCTLOPS);
-                       return (error);
-               }
+               if (error != 0)
+                       goto out;
        } else if (com & IOC_OUT) {
                /*
                 * Zero the buffer so the user always
@@ -698,7 +714,8 @@ sys_ioctl(struct thread *td, struct ioct
        if (error == 0 && (com & IOC_OUT))
                error = copyout(data, uap->data, (u_int)size);
 
-       if (size > 0)
+out:
+       if (size > SYS_IOCTL_SMALL_SIZE)
                free(data, M_IOCTLOPS);
        return (error);
 }
_______________________________________________
svn-src-stable-9@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-stable-9
To unsubscribe, send any mail to "svn-src-stable-9-unsubscr...@freebsd.org"

Reply via email to