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 #include <sys/string.h> 37 38 /* 39 * uio_extflg: extended flags 40 */ 41 #define UIO_DIRECT 0x0001 /* Direct I/O request */ 42 43 #if defined(HAVE_FAULT_IN_IOV_ITER_READABLE) 44 #define iov_iter_fault_in_readable(a, b) fault_in_iov_iter_readable(a, b) 45 #endif 46 47 typedef struct iovec iovec_t; 48 49 typedef enum zfs_uio_rw { 50 UIO_READ = 0, 51 UIO_WRITE = 1, 52 } zfs_uio_rw_t; 53 54 typedef enum zfs_uio_seg { 55 UIO_SYSSPACE = 0, 56 UIO_BVEC = 1, 57 UIO_ITER = 2, 58 } zfs_uio_seg_t; 59 60 /* 61 * This structures is used when doing Direct I/O. 62 */ 63 typedef struct { 64 struct page **pages; /* Mapped pages */ 65 long npages; /* Number of mapped pages */ 66 } zfs_uio_dio_t; 67 68 typedef struct zfs_uio { 69 union { 70 const struct iovec *uio_iov; 71 const struct bio_vec *uio_bvec; 72 struct iov_iter *uio_iter; 73 }; 74 int uio_iovcnt; /* Number of iovecs */ 75 offset_t uio_soffset; /* Starting logical offset */ 76 offset_t uio_loffset; /* Current logical offset */ 77 zfs_uio_seg_t uio_segflg; /* Segment type */ 78 boolean_t uio_fault_disable; 79 uint16_t uio_fmode; /* Access mode (unused) */ 80 uint16_t uio_extflg; /* Extra flags (UIO_DIRECT) */ 81 ssize_t uio_resid; /* Residual unprocessed bytes */ 82 size_t uio_skip; /* Skipped bytes in current iovec */ 83 zfs_uio_dio_t uio_dio; /* Direct I/O user pages */ 84 85 struct request *rq; 86 } zfs_uio_t; 87 88 89 #define zfs_uio_segflg(u) (u)->uio_segflg 90 #define zfs_uio_offset(u) (u)->uio_loffset 91 #define zfs_uio_resid(u) (u)->uio_resid 92 #define zfs_uio_iovcnt(u) (u)->uio_iovcnt 93 #define zfs_uio_iovlen(u, idx) (u)->uio_iov[(idx)].iov_len 94 #define zfs_uio_iovbase(u, idx) (u)->uio_iov[(idx)].iov_base 95 #define zfs_uio_fault_disable(u, set) (u)->uio_fault_disable = set 96 #define zfs_uio_soffset(u) (u)->uio_soffset 97 #define zfs_uio_rlimit_fsize(z, u) (0) 98 #define zfs_uio_fault_move(p, n, rw, u) zfs_uiomove((p), (n), (rw), (u)) 99 100 extern int zfs_uio_prefaultpages(ssize_t, zfs_uio_t *); 101 102 static inline void 103 zfs_uio_setoffset(zfs_uio_t *uio, offset_t off) 104 { 105 uio->uio_loffset = off; 106 } 107 108 static inline void 109 zfs_uio_setsoffset(zfs_uio_t *uio, offset_t off) 110 { 111 ASSERT3U(zfs_uio_offset(uio), ==, off); 112 zfs_uio_soffset(uio) = off; 113 } 114 115 static inline void 116 zfs_uio_advance(zfs_uio_t *uio, ssize_t size) 117 { 118 uio->uio_resid -= size; 119 uio->uio_loffset += size; 120 } 121 122 static inline void 123 zfs_uio_iovec_init(zfs_uio_t *uio, const struct iovec *iov, 124 unsigned long nr_segs, offset_t offset, zfs_uio_seg_t seg, ssize_t resid, 125 size_t skip) 126 { 127 ASSERT(seg == UIO_SYSSPACE); 128 129 uio->uio_iov = iov; 130 uio->uio_iovcnt = nr_segs; 131 uio->uio_loffset = offset; 132 uio->uio_segflg = seg; 133 uio->uio_fault_disable = B_FALSE; 134 uio->uio_fmode = 0; 135 uio->uio_extflg = 0; 136 uio->uio_resid = resid; 137 uio->uio_skip = skip; 138 uio->uio_soffset = uio->uio_loffset; 139 memset(&uio->uio_dio, 0, sizeof (zfs_uio_dio_t)); 140 } 141 142 static inline void 143 zfs_uio_bvec_init(zfs_uio_t *uio, struct bio *bio, struct request *rq) 144 { 145 /* Either bio or rq will be set, but not both */ 146 ASSERT3P(uio, !=, bio); 147 148 if (bio) { 149 uio->uio_iovcnt = bio->bi_vcnt - BIO_BI_IDX(bio); 150 uio->uio_bvec = &bio->bi_io_vec[BIO_BI_IDX(bio)]; 151 } else { 152 uio->uio_bvec = NULL; 153 uio->uio_iovcnt = 0; 154 } 155 156 uio->uio_loffset = io_offset(bio, rq); 157 uio->uio_segflg = UIO_BVEC; 158 uio->uio_fault_disable = B_FALSE; 159 uio->uio_fmode = 0; 160 uio->uio_extflg = 0; 161 uio->uio_resid = io_size(bio, rq); 162 if (bio) { 163 uio->uio_skip = BIO_BI_SKIP(bio); 164 } else { 165 uio->uio_skip = 0; 166 } 167 168 uio->rq = rq; 169 uio->uio_soffset = uio->uio_loffset; 170 memset(&uio->uio_dio, 0, sizeof (zfs_uio_dio_t)); 171 } 172 173 static inline void 174 zfs_uio_iov_iter_init(zfs_uio_t *uio, struct iov_iter *iter, offset_t offset, 175 ssize_t resid, size_t skip) 176 { 177 uio->uio_iter = iter; 178 uio->uio_iovcnt = iter->nr_segs; 179 uio->uio_loffset = offset; 180 uio->uio_segflg = UIO_ITER; 181 uio->uio_fault_disable = B_FALSE; 182 uio->uio_fmode = 0; 183 uio->uio_extflg = 0; 184 uio->uio_resid = resid; 185 uio->uio_skip = skip; 186 uio->uio_soffset = uio->uio_loffset; 187 memset(&uio->uio_dio, 0, sizeof (zfs_uio_dio_t)); 188 } 189 190 #if defined(HAVE_ITER_IOV) 191 #define zfs_uio_iter_iov(iter) iter_iov((iter)) 192 #else 193 #define zfs_uio_iter_iov(iter) (iter)->iov 194 #endif 195 196 #if defined(HAVE_IOV_ITER_TYPE) 197 #define zfs_uio_iov_iter_type(iter) iov_iter_type((iter)) 198 #else 199 #define zfs_uio_iov_iter_type(iter) (iter)->type 200 #endif 201 202 #endif /* SPL_UIO_H */ 203