1/* 2 * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. 3 * Copyright (C) 2007 The Regents of the University of California. 4 * Copyright (c) 2015 by Chunwei Chen. All rights reserved. 5 * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). 6 * Written by Brian Behlendorf <behlendorf1@llnl.gov>. 7 * UCRL-CODE-235197 8 * 9 * This file is part of the SPL, Solaris Porting Layer. 10 * 11 * The SPL is free software; you can redistribute it and/or modify it 12 * under the terms of the GNU General Public License as published by the 13 * Free Software Foundation; either version 2 of the License, or (at your 14 * option) any later version. 15 * 16 * The SPL is distributed in the hope that it will be useful, but WITHOUT 17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 18 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 19 * for more details. 20 * 21 * You should have received a copy of the GNU General Public License along 22 * with the SPL. If not, see <http://www.gnu.org/licenses/>. 23 */ 24 25#ifndef _SPL_UIO_H 26#define _SPL_UIO_H 27 28#include <sys/debug.h> 29#include <linux/uio.h> 30#include <linux/blkdev.h> 31#include <linux/blkdev_compat.h> 32#include <linux/mm.h> 33#include <linux/bio.h> 34#include <asm/uaccess.h> 35#include <sys/types.h> 36 37#if defined(HAVE_VFS_IOV_ITER) && defined(HAVE_FAULT_IN_IOV_ITER_READABLE) 38#define iov_iter_fault_in_readable(a, b) fault_in_iov_iter_readable(a, b) 39#endif 40 41typedef struct iovec iovec_t; 42 43typedef enum zfs_uio_rw { 44 UIO_READ = 0, 45 UIO_WRITE = 1, 46} zfs_uio_rw_t; 47 48typedef enum zfs_uio_seg { 49 UIO_USERSPACE = 0, 50 UIO_SYSSPACE = 1, 51 UIO_BVEC = 2, 52#if defined(HAVE_VFS_IOV_ITER) 53 UIO_ITER = 3, 54#endif 55} zfs_uio_seg_t; 56 57typedef struct zfs_uio { 58 union { 59 const struct iovec *uio_iov; 60 const struct bio_vec *uio_bvec; 61#if defined(HAVE_VFS_IOV_ITER) 62 struct iov_iter *uio_iter; 63#endif 64 }; 65 int uio_iovcnt; 66 offset_t uio_loffset; 67 zfs_uio_seg_t uio_segflg; 68 boolean_t uio_fault_disable; 69 uint16_t uio_fmode; 70 uint16_t uio_extflg; 71 ssize_t uio_resid; 72 73 size_t uio_skip; 74 75 struct request *rq; 76} zfs_uio_t; 77 78 79#define zfs_uio_segflg(u) (u)->uio_segflg 80#define zfs_uio_offset(u) (u)->uio_loffset 81#define zfs_uio_resid(u) (u)->uio_resid 82#define zfs_uio_iovcnt(u) (u)->uio_iovcnt 83#define zfs_uio_iovlen(u, idx) (u)->uio_iov[(idx)].iov_len 84#define zfs_uio_iovbase(u, idx) (u)->uio_iov[(idx)].iov_base 85#define zfs_uio_fault_disable(u, set) (u)->uio_fault_disable = set 86#define zfs_uio_rlimit_fsize(z, u) (0) 87#define zfs_uio_fault_move(p, n, rw, u) zfs_uiomove((p), (n), (rw), (u)) 88 89extern int zfs_uio_prefaultpages(ssize_t, zfs_uio_t *); 90 91static inline void 92zfs_uio_setoffset(zfs_uio_t *uio, offset_t off) 93{ 94 uio->uio_loffset = off; 95} 96 97static inline void 98zfs_uio_advance(zfs_uio_t *uio, ssize_t size) 99{ 100 uio->uio_resid -= size; 101 uio->uio_loffset += size; 102} 103 104static inline void 105zfs_uio_iovec_init(zfs_uio_t *uio, const struct iovec *iov, 106 unsigned long nr_segs, offset_t offset, zfs_uio_seg_t seg, ssize_t resid, 107 size_t skip) 108{ 109 ASSERT(seg == UIO_USERSPACE || seg == UIO_SYSSPACE); 110 111 uio->uio_iov = iov; 112 uio->uio_iovcnt = nr_segs; 113 uio->uio_loffset = offset; 114 uio->uio_segflg = seg; 115 uio->uio_fault_disable = B_FALSE; 116 uio->uio_fmode = 0; 117 uio->uio_extflg = 0; 118 uio->uio_resid = resid; 119 uio->uio_skip = skip; 120} 121 122static inline void 123zfs_uio_bvec_init(zfs_uio_t *uio, struct bio *bio, struct request *rq) 124{ 125 /* Either bio or rq will be set, but not both */ 126 ASSERT3P(uio, !=, bio); 127 128 if (bio) { 129 uio->uio_iovcnt = bio->bi_vcnt - BIO_BI_IDX(bio); 130 uio->uio_bvec = &bio->bi_io_vec[BIO_BI_IDX(bio)]; 131 } else { 132 uio->uio_bvec = NULL; 133 uio->uio_iovcnt = 0; 134 } 135 136 uio->uio_loffset = io_offset(bio, rq); 137 uio->uio_segflg = UIO_BVEC; 138 uio->uio_fault_disable = B_FALSE; 139 uio->uio_fmode = 0; 140 uio->uio_extflg = 0; 141 uio->uio_resid = io_size(bio, rq); 142 if (bio) { 143 uio->uio_skip = BIO_BI_SKIP(bio); 144 } else { 145 uio->uio_skip = 0; 146 } 147 148 uio->rq = rq; 149} 150 151#if defined(HAVE_VFS_IOV_ITER) 152static inline void 153zfs_uio_iov_iter_init(zfs_uio_t *uio, struct iov_iter *iter, offset_t offset, 154 ssize_t resid, size_t skip) 155{ 156 uio->uio_iter = iter; 157 uio->uio_iovcnt = iter->nr_segs; 158 uio->uio_loffset = offset; 159 uio->uio_segflg = UIO_ITER; 160 uio->uio_fault_disable = B_FALSE; 161 uio->uio_fmode = 0; 162 uio->uio_extflg = 0; 163 uio->uio_resid = resid; 164 uio->uio_skip = skip; 165} 166#endif 167 168#if defined(HAVE_ITER_IOV) 169#define zfs_uio_iter_iov(iter) iter_iov((iter)) 170#else 171#define zfs_uio_iter_iov(iter) (iter)->iov 172#endif 173 174#if defined(HAVE_IOV_ITER_TYPE) 175#define zfs_uio_iov_iter_type(iter) iov_iter_type((iter)) 176#else 177#define zfs_uio_iov_iter_type(iter) (iter)->type 178#endif 179 180#endif /* SPL_UIO_H */ 181