aboutsummaryrefslogtreecommitdiffstats
path: root/include/os
diff options
context:
space:
mode:
Diffstat (limited to 'include/os')
-rw-r--r--include/os/freebsd/spl/sys/mutex.h1
-rw-r--r--include/os/freebsd/spl/sys/param.h1
-rw-r--r--include/os/freebsd/spl/sys/uio.h31
-rw-r--r--include/os/freebsd/zfs/sys/abd_os.h11
-rw-r--r--include/os/linux/kernel/linux/kmap_compat.h47
-rw-r--r--include/os/linux/spl/sys/uio.h47
-rw-r--r--include/os/linux/zfs/sys/abd_os.h3
-rw-r--r--include/os/linux/zfs/sys/zfs_znode_impl.h6
-rw-r--r--include/os/linux/zfs/sys/zpl.h1
9 files changed, 131 insertions, 17 deletions
diff --git a/include/os/freebsd/spl/sys/mutex.h b/include/os/freebsd/spl/sys/mutex.h
index 8cfe56c75..bbff9fe80 100644
--- a/include/os/freebsd/spl/sys/mutex.h
+++ b/include/os/freebsd/spl/sys/mutex.h
@@ -70,4 +70,5 @@ typedef enum {
#define mutex_exit(lock) sx_xunlock(lock)
#define mutex_owned(lock) sx_xlocked(lock)
#define mutex_owner(lock) sx_xholder(lock)
+
#endif /* _OPENSOLARIS_SYS_MUTEX_H_ */
diff --git a/include/os/freebsd/spl/sys/param.h b/include/os/freebsd/spl/sys/param.h
index 92724e332..96440dce0 100644
--- a/include/os/freebsd/spl/sys/param.h
+++ b/include/os/freebsd/spl/sys/param.h
@@ -33,6 +33,7 @@
#include <sys/types.h>
#include_next <sys/param.h>
#define PAGESIZE PAGE_SIZE
+#define PAGESHIFT PAGE_SHIFT
#define ptob(x) ((uint64_t)(x) << PAGE_SHIFT)
#ifdef _KERNEL
#include <sys/systm.h>
diff --git a/include/os/freebsd/spl/sys/uio.h b/include/os/freebsd/spl/sys/uio.h
index b9d41903e..2bd5bdb80 100644
--- a/include/os/freebsd/spl/sys/uio.h
+++ b/include/os/freebsd/spl/sys/uio.h
@@ -34,13 +34,30 @@
#include_next <sys/uio.h>
#include <sys/_uio.h>
#include <sys/debug.h>
+#include <sys/sysmacros.h>
+
+/*
+ * uio_extflg: extended flags
+ */
+#define UIO_DIRECT 0x0001 /* Direct I/O requset */
typedef struct iovec iovec_t;
typedef enum uio_seg zfs_uio_seg_t;
typedef enum uio_rw zfs_uio_rw_t;
+/*
+ * This structure is used when doing Direct I/O.
+ */
+typedef struct {
+ vm_page_t *pages;
+ int npages;
+} zfs_uio_dio_t;
+
typedef struct zfs_uio {
struct uio *uio;
+ offset_t uio_soffset;
+ uint16_t uio_extflg;
+ zfs_uio_dio_t uio_dio;
} zfs_uio_t;
#define GET_UIO_STRUCT(u) (u)->uio
@@ -52,6 +69,7 @@ typedef struct zfs_uio {
#define zfs_uio_iovbase(u, idx) GET_UIO_STRUCT(u)->uio_iov[(idx)].iov_base
#define zfs_uio_td(u) GET_UIO_STRUCT(u)->uio_td
#define zfs_uio_rw(u) GET_UIO_STRUCT(u)->uio_rw
+#define zfs_uio_soffset(u) (u)->uio_soffset
#define zfs_uio_fault_disable(u, set)
#define zfs_uio_prefaultpages(size, u) (0)
@@ -62,6 +80,13 @@ zfs_uio_setoffset(zfs_uio_t *uio, offset_t off)
}
static inline void
+zfs_uio_setsoffset(zfs_uio_t *uio, offset_t off)
+{
+ ASSERT3U(zfs_uio_offset(uio), ==, off);
+ zfs_uio_soffset(uio) = off;
+}
+
+static inline void
zfs_uio_advance(zfs_uio_t *uio, ssize_t size)
{
zfs_uio_resid(uio) -= size;
@@ -71,7 +96,11 @@ zfs_uio_advance(zfs_uio_t *uio, ssize_t size)
static __inline void
zfs_uio_init(zfs_uio_t *uio, struct uio *uio_s)
{
- GET_UIO_STRUCT(uio) = uio_s;
+ memset(uio, 0, sizeof (zfs_uio_t));
+ if (uio_s != NULL) {
+ GET_UIO_STRUCT(uio) = uio_s;
+ zfs_uio_soffset(uio) = uio_s->uio_offset;
+ }
}
int zfs_uio_fault_move(void *p, size_t n, zfs_uio_rw_t dir, zfs_uio_t *uio);
diff --git a/include/os/freebsd/zfs/sys/abd_os.h b/include/os/freebsd/zfs/sys/abd_os.h
index 57122ee83..be825b3b8 100644
--- a/include/os/freebsd/zfs/sys/abd_os.h
+++ b/include/os/freebsd/zfs/sys/abd_os.h
@@ -26,10 +26,15 @@
#ifndef _ABD_OS_H
#define _ABD_OS_H
+#include <sys/vm.h>
+#include <vm/vm_page.h>
+
#ifdef __cplusplus
extern "C" {
#endif
+struct abd;
+
struct abd_scatter {
uint_t abd_offset;
void *abd_chunks[1]; /* actually variable-length */
@@ -37,8 +42,14 @@ struct abd_scatter {
struct abd_linear {
void *abd_buf;
+#if defined(_KERNEL)
+ struct sf_buf *sf; /* for LINEAR_PAGE FreeBSD */
+#endif
};
+__attribute__((malloc))
+struct abd *abd_alloc_from_pages(vm_page_t *, unsigned long, uint64_t);
+
#ifdef __cplusplus
}
#endif
diff --git a/include/os/linux/kernel/linux/kmap_compat.h b/include/os/linux/kernel/linux/kmap_compat.h
index fb59c5f02..432c0e991 100644
--- a/include/os/linux/kernel/linux/kmap_compat.h
+++ b/include/os/linux/kernel/linux/kmap_compat.h
@@ -38,6 +38,8 @@
#define zfs_kmap_local(page) kmap_atomic(page)
#define zfs_kunmap_local(addr) kunmap_atomic(addr)
#endif
+#define zfs_kmap(page) kmap(page)
+#define zfs_kunmap(page) kunmap(page)
/* 5.0 API change - no more 'type' argument for access_ok() */
#ifdef HAVE_ACCESS_OK_TYPE
@@ -46,4 +48,49 @@
#define zfs_access_ok(type, addr, size) access_ok(addr, size)
#endif
+/*
+ * read returning FOLL_WRITE is due to the fact that we are stating
+ * that the kernel will have write access to the user pages. So, when
+ * a Direct I/O read request is issued, the kernel must write to the user
+ * pages.
+ *
+ * get_user_pages_unlocked was not available to 4.0, so we also check
+ * for get_user_pages on older kernels.
+ */
+/* 4.9 API change - for and read flag is passed as gup flags */
+#if defined(HAVE_GET_USER_PAGES_UNLOCKED_GUP_FLAGS)
+#define zfs_get_user_pages(addr, numpages, read, pages) \
+ get_user_pages_unlocked(addr, numpages, pages, read ? FOLL_WRITE : 0)
+
+/* 4.8 API change - no longer takes struct task_struct as arguement */
+#elif defined(HAVE_GET_USER_PAGES_UNLOCKED_WRITE_FLAG)
+#define zfs_get_user_pages(addr, numpages, read, pages) \
+ get_user_pages_unlocked(addr, numpages, read, 0, pages)
+
+/* 4.0-4.3, 4.5-4.7 API */
+#elif defined(HAVE_GET_USER_PAGES_UNLOCKED_TASK_STRUCT)
+#define zfs_get_user_pages(addr, numpages, read, pages) \
+ get_user_pages_unlocked(current, current->mm, addr, numpages, read, 0, \
+ pages)
+
+/* 4.4 API */
+#elif defined(HAVE_GET_USER_PAGES_UNLOCKED_TASK_STRUCT_GUP_FLAGS)
+#define zfs_get_user_pages(addr, numpages, read, pages) \
+ get_user_pages_unlocked(current, current->mm, addr, numpages, pages, \
+ read ? FOLL_WRITE : 0)
+
+/* Using get_user_pages if kernel is < 4.0 */
+#elif defined(HAVE_GET_USER_PAGES_TASK_STRUCT)
+#define zfs_get_user_pages(addr, numpages, read, pages) \
+ get_user_pages(current, current->mm, addr, numpages, read, 0, pages, \
+ NULL)
+#else
+/*
+ * This case is unreachable. We must be able to use either
+ * get_user_pages_unlocked() or get_user_pages() to map user pages into
+ * the kernel.
+ */
+#error "Unknown Direct I/O interface"
+#endif
+
#endif /* _ZFS_KMAP_H */
diff --git a/include/os/linux/spl/sys/uio.h b/include/os/linux/spl/sys/uio.h
index 5e6ea8d3c..5d483685e 100644
--- a/include/os/linux/spl/sys/uio.h
+++ b/include/os/linux/spl/sys/uio.h
@@ -33,6 +33,12 @@
#include <linux/bio.h>
#include <asm/uaccess.h>
#include <sys/types.h>
+#include <sys/string.h>
+
+/*
+ * uio_extflg: extended flags
+ */
+#define UIO_DIRECT 0x0001 /* Direct I/O request */
#if defined(HAVE_VFS_IOV_ITER) && defined(HAVE_FAULT_IN_IOV_ITER_READABLE)
#define iov_iter_fault_in_readable(a, b) fault_in_iov_iter_readable(a, b)
@@ -54,6 +60,14 @@ typedef enum zfs_uio_seg {
#endif
} zfs_uio_seg_t;
+/*
+ * This structures is used when doing Direct I/O.
+ */
+typedef struct {
+ struct page **pages; /* Mapped pages */
+ long npages; /* Number of mapped pages */
+} zfs_uio_dio_t;
+
typedef struct zfs_uio {
union {
const struct iovec *uio_iov;
@@ -62,15 +76,16 @@ typedef struct zfs_uio {
struct iov_iter *uio_iter;
#endif
};
- int uio_iovcnt;
- offset_t uio_loffset;
- zfs_uio_seg_t uio_segflg;
+ int uio_iovcnt; /* Number of iovecs */
+ offset_t uio_soffset; /* Starting logical offset */
+ offset_t uio_loffset; /* Current logical offset */
+ zfs_uio_seg_t uio_segflg; /* Segment type */
boolean_t uio_fault_disable;
- uint16_t uio_fmode;
- uint16_t uio_extflg;
- ssize_t uio_resid;
-
- size_t uio_skip;
+ uint16_t uio_fmode; /* Access mode (unused) */
+ uint16_t uio_extflg; /* Extra flags (UIO_DIRECT) */
+ ssize_t uio_resid; /* Residual unprocessed bytes */
+ size_t uio_skip; /* Skipped bytes in current iovec */
+ zfs_uio_dio_t uio_dio; /* Direct I/O user pages */
struct request *rq;
} zfs_uio_t;
@@ -83,6 +98,7 @@ typedef struct zfs_uio {
#define zfs_uio_iovlen(u, idx) (u)->uio_iov[(idx)].iov_len
#define zfs_uio_iovbase(u, idx) (u)->uio_iov[(idx)].iov_base
#define zfs_uio_fault_disable(u, set) (u)->uio_fault_disable = set
+#define zfs_uio_soffset(u) (u)->uio_soffset
#define zfs_uio_rlimit_fsize(z, u) (0)
#define zfs_uio_fault_move(p, n, rw, u) zfs_uiomove((p), (n), (rw), (u))
@@ -95,6 +111,13 @@ zfs_uio_setoffset(zfs_uio_t *uio, offset_t off)
}
static inline void
+zfs_uio_setsoffset(zfs_uio_t *uio, offset_t off)
+{
+ ASSERT3U(zfs_uio_offset(uio), ==, off);
+ zfs_uio_soffset(uio) = off;
+}
+
+static inline void
zfs_uio_advance(zfs_uio_t *uio, ssize_t size)
{
uio->uio_resid -= size;
@@ -117,6 +140,8 @@ zfs_uio_iovec_init(zfs_uio_t *uio, const struct iovec *iov,
uio->uio_extflg = 0;
uio->uio_resid = resid;
uio->uio_skip = skip;
+ uio->uio_soffset = uio->uio_loffset;
+ memset(&uio->uio_dio, 0, sizeof (zfs_uio_dio_t));
}
static inline void
@@ -146,6 +171,8 @@ zfs_uio_bvec_init(zfs_uio_t *uio, struct bio *bio, struct request *rq)
}
uio->rq = rq;
+ uio->uio_soffset = uio->uio_loffset;
+ memset(&uio->uio_dio, 0, sizeof (zfs_uio_dio_t));
}
#if defined(HAVE_VFS_IOV_ITER)
@@ -162,8 +189,10 @@ zfs_uio_iov_iter_init(zfs_uio_t *uio, struct iov_iter *iter, offset_t offset,
uio->uio_extflg = 0;
uio->uio_resid = resid;
uio->uio_skip = skip;
+ uio->uio_soffset = uio->uio_loffset;
+ memset(&uio->uio_dio, 0, sizeof (zfs_uio_dio_t));
}
-#endif
+#endif /* HAVE_VFS_IOV_ITER */
#if defined(HAVE_ITER_IOV)
#define zfs_uio_iter_iov(iter) iter_iov((iter))
diff --git a/include/os/linux/zfs/sys/abd_os.h b/include/os/linux/zfs/sys/abd_os.h
index ce4f5a2bd..606e8bf68 100644
--- a/include/os/linux/zfs/sys/abd_os.h
+++ b/include/os/linux/zfs/sys/abd_os.h
@@ -55,6 +55,9 @@ int abd_iterate_page_func(abd_t *, size_t, size_t, abd_iter_page_func_t *,
unsigned int abd_bio_map_off(struct bio *, abd_t *, unsigned int, size_t);
unsigned long abd_nr_pages_off(abd_t *, unsigned int, size_t);
+__attribute__((malloc))
+abd_t *abd_alloc_from_pages(struct page **, unsigned long, uint64_t);
+
#ifdef __cplusplus
}
#endif
diff --git a/include/os/linux/zfs/sys/zfs_znode_impl.h b/include/os/linux/zfs/sys/zfs_znode_impl.h
index 0be2c445a..e02886518 100644
--- a/include/os/linux/zfs/sys/zfs_znode_impl.h
+++ b/include/os/linux/zfs/sys/zfs_znode_impl.h
@@ -184,12 +184,6 @@ extern int zfs_inode_alloc(struct super_block *, struct inode **ip);
extern void zfs_inode_destroy(struct inode *);
extern void zfs_mark_inode_dirty(struct inode *);
extern boolean_t zfs_relatime_need_update(const struct inode *);
-
-#if defined(HAVE_UIO_RW)
-extern caddr_t zfs_map_page(page_t *, enum seg_rw);
-extern void zfs_unmap_page(page_t *, caddr_t);
-#endif /* HAVE_UIO_RW */
-
extern zil_replay_func_t *const zfs_replay_vector[TX_MAX_TYPE];
#ifdef __cplusplus
diff --git a/include/os/linux/zfs/sys/zpl.h b/include/os/linux/zfs/sys/zpl.h
index 91a4751ff..c8eefe4fe 100644
--- a/include/os/linux/zfs/sys/zpl.h
+++ b/include/os/linux/zfs/sys/zpl.h
@@ -32,7 +32,6 @@
#include <linux/exportfs.h>
#include <linux/falloc.h>
#include <linux/parser.h>
-#include <linux/task_io_accounting_ops.h>
#include <linux/vfs_compat.h>
#include <linux/writeback.h>
#include <linux/xattr_compat.h>