1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2014 Garrett D'Amore <garrett@damore.org>
  23  *
  24  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  25  * Use is subject to license terms.
  26  *
  27  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  28  * Copyright (c) 2015, Joyent, Inc.  All rights reserved.
  29  */
  30 
  31 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T     */
  32 /*        All Rights Reserved   */
  33 
  34 /*
  35  * University Copyright- Copyright (c) 1982, 1986, 1988
  36  * The Regents of the University of California
  37  * All Rights Reserved
  38  *
  39  * University Acknowledgment- Portions of this document are derived from
  40  * software developed by the University of California, Berkeley, and its
  41  * contributors.
  42  */
  43 
  44 #ifndef _SYS_UIO_H
  45 #define _SYS_UIO_H
  46 
  47 #include <sys/feature_tests.h>
  48 
  49 #ifdef  __cplusplus
  50 extern "C" {
  51 #endif
  52 
  53 #include <sys/types.h>
  54 
  55 /*
  56  * I/O parameter information.  A uio structure describes the I/O which
  57  * is to be performed by an operation.  Typically the data movement will
  58  * be performed by a routine such as uiomove(), which updates the uio
  59  * structure to reflect what was done.
  60  */
  61 
  62 #if     defined(_XPG4_2)
  63 typedef struct iovec {
  64         void    *iov_base;
  65         size_t  iov_len;
  66 } iovec_t;
  67 #else
  68 typedef struct iovec {
  69         caddr_t iov_base;
  70 #if defined(_LP64)
  71         size_t  iov_len;
  72 #else
  73         long    iov_len;
  74 #endif
  75 } iovec_t;
  76 #endif  /* defined(_XPG4_2) */
  77 
  78 #if defined(_SYSCALL32)
  79 
  80 /* Kernel's view of user ILP32 iovec struct */
  81 
  82 typedef struct iovec32 {
  83         caddr32_t       iov_base;
  84         int32_t         iov_len;
  85 } iovec32_t;
  86 
  87 #endif  /* _SYSCALL32 */
  88 
  89 #if     !defined(_XPG4_2) || defined(__EXTENSIONS__)
  90 /*
  91  * Segment flag values.
  92  */
  93 typedef enum uio_seg { UIO_USERSPACE, UIO_SYSSPACE, UIO_USERISPACE } uio_seg_t;
  94 
  95 typedef struct uio {
  96         iovec_t         *uio_iov;       /* pointer to array of iovecs */
  97         int             uio_iovcnt;     /* number of iovecs */
  98         lloff_t         _uio_offset;    /* file offset */
  99         uio_seg_t       uio_segflg;     /* address space (kernel or user) */
 100         uint16_t        uio_fmode;      /* file mode flags */
 101         uint16_t        uio_extflg;     /* extended flags */
 102         lloff_t         _uio_limit;     /* u-limit (maximum byte offset) */
 103         ssize_t         uio_resid;      /* residual count */
 104 } uio_t;
 105 
 106 /*
 107  * Extended uio_t uioa_t used for asynchronous uio.
 108  *
 109  * Note: UIOA_IOV_MAX is defined and used as it is in "fs/vncalls.c"
 110  *       as there isn't a formal definition of IOV_MAX for the kernel.
 111  */
 112 #define UIOA_IOV_MAX    16
 113 
 114 typedef struct uioa_page_s {            /* locked uio_iov state */
 115         int     uioa_pfncnt;            /* count of pfn_t(s) in *uioa_ppp */
 116         void    **uioa_ppp;             /* page_t or pfn_t arrary */
 117         caddr_t uioa_base;              /* address base */
 118         size_t  uioa_len;               /* span length */
 119 } uioa_page_t;
 120 
 121 typedef struct uioa_s {
 122         iovec_t         *uio_iov;       /* pointer to array of iovecs */
 123         int             uio_iovcnt;     /* number of iovecs */
 124         lloff_t         _uio_offset;    /* file offset */
 125         uio_seg_t       uio_segflg;     /* address space (kernel or user) */
 126         uint16_t        uio_fmode;      /* file mode flags */
 127         uint16_t        uio_extflg;     /* extended flags */
 128         lloff_t         _uio_limit;     /* u-limit (maximum byte offset) */
 129         ssize_t         uio_resid;      /* residual count */
 130         /*
 131          * uioa extended members.
 132          */
 133         uint32_t        uioa_state;     /* state of asynch i/o */
 134         ssize_t         uioa_mbytes;    /* bytes that have been uioamove()ed */
 135         uioa_page_t     *uioa_lcur;     /* pointer into uioa_locked[] */
 136         void            **uioa_lppp;    /* pointer into lcur->uioa_ppp[] */
 137         void            *uioa_hwst[4];  /* opaque hardware state */
 138         uioa_page_t     uioa_locked[UIOA_IOV_MAX]; /* Per iov locked pages */
 139 } uioa_t;
 140 
 141 /*
 142  * uio extensions
 143  *
 144  * PSARC 2009/478: Copy Reduction Interfaces
 145  */
 146 typedef enum xuio_type {
 147         UIOTYPE_ASYNCIO,
 148         UIOTYPE_ZEROCOPY,
 149         UIOTYPE_PEEKSIZE
 150 } xuio_type_t;
 151 
 152 typedef struct xuio {
 153         uio_t xu_uio;           /* Embedded UIO structure */
 154 
 155         /* Extended uio fields */
 156         enum xuio_type xu_type; /* What kind of uio structure? */
 157         union {
 158                 /* Async I/O Support, intend to replace uioa_t. */
 159                 struct {
 160                         uint32_t xu_a_state;    /* state of async i/o */
 161                         /* bytes that have been uioamove()ed */
 162                         ssize_t xu_a_mbytes;
 163                         uioa_page_t *xu_a_lcur; /* pointer into uioa_locked[] */
 164                         /* pointer into lcur->uioa_ppp[] */
 165                         void **xu_a_lppp;
 166                         void *xu_a_hwst[4];     /* opaque hardware state */
 167                         /* Per iov locked pages */
 168                         uioa_page_t xu_a_locked[UIOA_IOV_MAX];
 169                 } xu_aio;
 170 
 171                 /*
 172                  * Copy Reduction Support -- facilate loaning / returning of
 173                  * filesystem cache buffers.
 174                  */
 175                 struct {
 176                         int xu_zc_rw;   /* read or write buffer */
 177                         void *xu_zc_priv;       /* fs specific */
 178                 } xu_zc;
 179 
 180                 /*
 181                  * Peek Size Support -- facilitate peeking at the size of a
 182                  * waiting message on a socket.
 183                  */
 184                 struct {
 185                         ssize_t xu_ps_size;     /* size of waiting msg */
 186                         boolean_t xu_ps_set;    /* was size calculated? */
 187                 } xu_ps;
 188         } xu_ext;
 189 } xuio_t;
 190 
 191 #define XUIO_XUZC_PRIV(xuio)    xuio->xu_ext.xu_zc.xu_zc_priv
 192 #define XUIO_XUZC_RW(xuio)      xuio->xu_ext.xu_zc.xu_zc_rw
 193 
 194 #define UIOA_ALLOC      0x0001          /* allocated but not yet initialized */
 195 #define UIOA_INIT       0x0002          /* initialized but not yet enabled */
 196 #define UIOA_ENABLED    0x0004          /* enabled, asynch i/o active */
 197 #define UIOA_FINI       0x0008          /* finished waiting for uioafini() */
 198 
 199 #define UIOA_CLR        (~0x000F)       /* clear mutually exclusive bits */
 200 
 201 #define UIOA_POLL       0x0010          /* need dcopy_poll() */
 202 
 203 #define uio_loffset     _uio_offset._f
 204 #if !defined(_LP64)
 205 #define uio_offset      _uio_offset._p._l
 206 #else
 207 #define uio_offset      uio_loffset
 208 #endif
 209 
 210 #define uio_llimit      _uio_limit._f
 211 #if !defined(_LP64)
 212 #define uio_limit       _uio_limit._p._l
 213 #else
 214 #define uio_limit       uio_llimit
 215 #endif
 216 
 217 /*
 218  * I/O direction.
 219  */
 220 typedef enum uio_rw { UIO_READ, UIO_WRITE } uio_rw_t;
 221 
 222 /*
 223  * uio_extflg: extended flags
 224  *
 225  * NOTE: This flag will be used in uiomove to determine if non-temporal
 226  * access, ie, access bypassing caches, should be used.  Filesystems that
 227  * don't initialize this field could experience suboptimal performance due to
 228  * the random data the field contains.
 229  *
 230  * NOTE: This flag is also used by uioasync callers to pass an extended
 231  * uio_t (uioa_t), to uioasync enabled consumers. Unlike above all
 232  * consumers of a uioa_t require the uio_extflg to be initialized.
 233  */
 234 #define UIO_COPY_DEFAULT        0x0000  /* no special options to copy */
 235 #define UIO_COPY_CACHED         0x0001  /* copy should not bypass caches */
 236 
 237 #define UIO_ASYNC               0x0002  /* uio_t is really a uioa_t */
 238 #define UIO_XUIO                0x0004  /* Structure is xuio_t */
 239 
 240 /*
 241  * Global uioasync capability shadow state.
 242  */
 243 typedef struct uioasync_s {
 244         boolean_t       enabled;        /* Is uioasync enabled? */
 245         size_t          mincnt;         /* Minimum byte count for use of */
 246 } uioasync_t;
 247 
 248 #endif /* !defined(_XPG4_2) || defined(__EXTENSIONS__) */
 249 
 250 #if defined(_KERNEL) || defined(_FAKE_KERNEL)
 251 
 252 int     uiomove(void *, size_t, enum uio_rw, uio_t *);
 253 void    uio_prefaultpages(ssize_t, uio_t *);
 254 int     uiocopy(void *, size_t, enum uio_rw, uio_t *, size_t *);
 255 int     ureadc(int, uio_t *);   /* should be errno_t in future */
 256 int     uwritec(struct uio *);
 257 void    uioskip(uio_t *, size_t);
 258 int     uiodup(uio_t *, uio_t *, iovec_t *, int);
 259 
 260 int     uioamove(void *, size_t, enum uio_rw, uioa_t *);
 261 int     uioainit(uio_t *, uioa_t *);
 262 int     uioafini(uio_t *, uioa_t *);
 263 extern  uioasync_t uioasync;
 264 
 265 #else   /* defined(_KERNEL) */
 266 
 267 extern ssize_t readv(int, const struct iovec *, int);
 268 extern ssize_t writev(int, const struct iovec *, int);
 269 
 270 /*
 271  * When in the large file compilation environment,
 272  * map preadv/pwritev to their 64 bit offset versions
 273  */
 274 #if !defined(_LP64) && _FILE_OFFSET_BITS == 64
 275 #ifdef __PRAGMA_REDEFINE_EXTNAME
 276 #pragma redefine_extname        preadv  preadv64
 277 #pragma redefine_extname        pwritev pwritev64
 278 #else /* __PRAGMA_REDEFINE_EXTNAME */
 279 #define preadv  preadv64
 280 #define pwritev pwritev64
 281 #endif /* __PRAGMA_REDEFINE_EXTNAME */
 282 #endif /* !_LP64 && _FILE_OFFSET_BITS == 64 */
 283 
 284 /* In the LP64 compilation environment, the APIs are already large file */
 285 #if defined(_LP64) && defined(_LARGEFILE64_SOURCE)
 286 #ifdef  __PRAGMA_REDEFINE_EXTNAME
 287 #pragma redefine_extname        preadv64        preadv
 288 #pragma redefine_extname        pwritev64       pwritev
 289 #else   /* __PRAGMA_REDEFINE_EXTNAME */
 290 #define preadv64        preadv
 291 #define pwritev64       pwritev
 292 #endif  /* __PRAGMA_REDEFINE_EXTNAME */
 293 #endif  /* _LP64 && _LARGEFILE64_SOURCE */
 294 
 295 extern ssize_t preadv(int, const struct iovec *, int, off_t);
 296 extern ssize_t pwritev(int, const struct iovec *, int, off_t);
 297 
 298 /*
 299  * preadv64 and pwritev64 should be defined when:
 300  * - Using the transitional compilation environment, and not
 301  *     the large file compilation environment.
 302  */
 303 #if defined(_LARGEFILE64_SOURCE) && !((_FILE_OFFSET_BITS == 64) && \
 304         !defined(__PRAGMA_REDEFINE_EXTNAME))
 305 extern ssize_t preadv64(int, const struct iovec *, int, off64_t);
 306 extern ssize_t pwritev64(int, const struct iovec *, int, off64_t);
 307 #endif /* _LARGEFILE64_SOURCE */
 308 
 309 #endif  /* defined(_KERNEL) */
 310 
 311 #ifdef  __cplusplus
 312 }
 313 #endif
 314 
 315 #endif  /* _SYS_UIO_H */