diff options
Diffstat (limited to 'include/os/linux')
105 files changed, 10894 insertions, 0 deletions
diff --git a/include/os/linux/Makefile.am b/include/os/linux/Makefile.am new file mode 100644 index 000000000000..605a1fcb7506 --- /dev/null +++ b/include/os/linux/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = kernel spl zfs diff --git a/include/os/linux/kernel/Makefile.am b/include/os/linux/kernel/Makefile.am new file mode 100644 index 000000000000..08b2f5fc5c99 --- /dev/null +++ b/include/os/linux/kernel/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = linux diff --git a/include/os/linux/kernel/linux/Makefile.am b/include/os/linux/kernel/linux/Makefile.am new file mode 100644 index 000000000000..6ff0df506d9c --- /dev/null +++ b/include/os/linux/kernel/linux/Makefile.am @@ -0,0 +1,22 @@ +KERNEL_H = \ + dcache_compat.h \ + xattr_compat.h \ + vfs_compat.h \ + blkdev_compat.h \ + utsname_compat.h \ + kmap_compat.h \ + percpu_compat.h \ + simd.h \ + simd_x86.h \ + simd_aarch64.h \ + simd_powerpc.h \ + mod_compat.h \ + page_compat.h \ + compiler_compat.h + +if CONFIG_KERNEL +if BUILD_LINUX +kerneldir = @prefix@/src/zfs-$(VERSION)/include/linux +kernel_HEADERS = $(KERNEL_H) +endif +endif diff --git a/include/os/linux/kernel/linux/blkdev_compat.h b/include/os/linux/kernel/linux/blkdev_compat.h new file mode 100644 index 000000000000..1cdc300a6f85 --- /dev/null +++ b/include/os/linux/kernel/linux/blkdev_compat.h @@ -0,0 +1,506 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright (C) 2011 Lawrence Livermore National Security, LLC. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * LLNL-CODE-403049. + */ + +#ifndef _ZFS_BLKDEV_H +#define _ZFS_BLKDEV_H + +#include <linux/blkdev.h> +#include <linux/elevator.h> +#include <linux/backing-dev.h> +#include <linux/hdreg.h> +#include <linux/msdos_fs.h> /* for SECTOR_* */ + +#ifndef HAVE_BLK_QUEUE_FLAG_SET +static inline void +blk_queue_flag_set(unsigned int flag, struct request_queue *q) +{ + queue_flag_set(flag, q); +} +#endif + +#ifndef HAVE_BLK_QUEUE_FLAG_CLEAR +static inline void +blk_queue_flag_clear(unsigned int flag, struct request_queue *q) +{ + queue_flag_clear(flag, q); +} +#endif + +/* + * 4.7 - 4.x API, + * The blk_queue_write_cache() interface has replaced blk_queue_flush() + * interface. However, the new interface is GPL-only thus we implement + * our own trivial wrapper when the GPL-only version is detected. + * + * 2.6.36 - 4.6 API, + * The blk_queue_flush() interface has replaced blk_queue_ordered() + * interface. However, while the old interface was available to all the + * new one is GPL-only. Thus if the GPL-only version is detected we + * implement our own trivial helper. + */ +static inline void +blk_queue_set_write_cache(struct request_queue *q, bool wc, bool fua) +{ +#if defined(HAVE_BLK_QUEUE_WRITE_CACHE_GPL_ONLY) + if (wc) + blk_queue_flag_set(QUEUE_FLAG_WC, q); + else + blk_queue_flag_clear(QUEUE_FLAG_WC, q); + if (fua) + blk_queue_flag_set(QUEUE_FLAG_FUA, q); + else + blk_queue_flag_clear(QUEUE_FLAG_FUA, q); +#elif defined(HAVE_BLK_QUEUE_WRITE_CACHE) + blk_queue_write_cache(q, wc, fua); +#elif defined(HAVE_BLK_QUEUE_FLUSH_GPL_ONLY) + if (wc) + q->flush_flags |= REQ_FLUSH; + if (fua) + q->flush_flags |= REQ_FUA; +#elif defined(HAVE_BLK_QUEUE_FLUSH) + blk_queue_flush(q, (wc ? REQ_FLUSH : 0) | (fua ? REQ_FUA : 0)); +#else +#error "Unsupported kernel" +#endif +} + +static inline void +blk_queue_set_read_ahead(struct request_queue *q, unsigned long ra_pages) +{ +#ifdef HAVE_BLK_QUEUE_BDI_DYNAMIC + q->backing_dev_info->ra_pages = ra_pages; +#else + q->backing_dev_info.ra_pages = ra_pages; +#endif +} + +#if !defined(HAVE_GET_DISK_AND_MODULE) +static inline struct kobject * +get_disk_and_module(struct gendisk *disk) +{ + return (get_disk(disk)); +} +#endif + +#ifdef HAVE_BIO_BVEC_ITER +#define BIO_BI_SECTOR(bio) (bio)->bi_iter.bi_sector +#define BIO_BI_SIZE(bio) (bio)->bi_iter.bi_size +#define BIO_BI_IDX(bio) (bio)->bi_iter.bi_idx +#define BIO_BI_SKIP(bio) (bio)->bi_iter.bi_bvec_done +#define bio_for_each_segment4(bv, bvp, b, i) \ + bio_for_each_segment((bv), (b), (i)) +typedef struct bvec_iter bvec_iterator_t; +#else +#define BIO_BI_SECTOR(bio) (bio)->bi_sector +#define BIO_BI_SIZE(bio) (bio)->bi_size +#define BIO_BI_IDX(bio) (bio)->bi_idx +#define BIO_BI_SKIP(bio) (0) +#define bio_for_each_segment4(bv, bvp, b, i) \ + bio_for_each_segment((bvp), (b), (i)) +typedef int bvec_iterator_t; +#endif + +static inline void +bio_set_flags_failfast(struct block_device *bdev, int *flags) +{ +#ifdef CONFIG_BUG + /* + * Disable FAILFAST for loopback devices because of the + * following incorrect BUG_ON() in loop_make_request(). + * This support is also disabled for md devices because the + * test suite layers md devices on top of loopback devices. + * This may be removed when the loopback driver is fixed. + * + * BUG_ON(!lo || (rw != READ && rw != WRITE)); + */ + if ((MAJOR(bdev->bd_dev) == LOOP_MAJOR) || + (MAJOR(bdev->bd_dev) == MD_MAJOR)) + return; + +#ifdef BLOCK_EXT_MAJOR + if (MAJOR(bdev->bd_dev) == BLOCK_EXT_MAJOR) + return; +#endif /* BLOCK_EXT_MAJOR */ +#endif /* CONFIG_BUG */ + + *flags |= REQ_FAILFAST_MASK; +} + +/* + * Maximum disk label length, it may be undefined for some kernels. + */ +#if !defined(DISK_NAME_LEN) +#define DISK_NAME_LEN 32 +#endif /* DISK_NAME_LEN */ + +#ifdef HAVE_BIO_BI_STATUS +static inline int +bi_status_to_errno(blk_status_t status) +{ + switch (status) { + case BLK_STS_OK: + return (0); + case BLK_STS_NOTSUPP: + return (EOPNOTSUPP); + case BLK_STS_TIMEOUT: + return (ETIMEDOUT); + case BLK_STS_NOSPC: + return (ENOSPC); + case BLK_STS_TRANSPORT: + return (ENOLINK); + case BLK_STS_TARGET: + return (EREMOTEIO); + case BLK_STS_NEXUS: + return (EBADE); + case BLK_STS_MEDIUM: + return (ENODATA); + case BLK_STS_PROTECTION: + return (EILSEQ); + case BLK_STS_RESOURCE: + return (ENOMEM); + case BLK_STS_AGAIN: + return (EAGAIN); + case BLK_STS_IOERR: + return (EIO); + default: + return (EIO); + } +} + +static inline blk_status_t +errno_to_bi_status(int error) +{ + switch (error) { + case 0: + return (BLK_STS_OK); + case EOPNOTSUPP: + return (BLK_STS_NOTSUPP); + case ETIMEDOUT: + return (BLK_STS_TIMEOUT); + case ENOSPC: + return (BLK_STS_NOSPC); + case ENOLINK: + return (BLK_STS_TRANSPORT); + case EREMOTEIO: + return (BLK_STS_TARGET); + case EBADE: + return (BLK_STS_NEXUS); + case ENODATA: + return (BLK_STS_MEDIUM); + case EILSEQ: + return (BLK_STS_PROTECTION); + case ENOMEM: + return (BLK_STS_RESOURCE); + case EAGAIN: + return (BLK_STS_AGAIN); + case EIO: + return (BLK_STS_IOERR); + default: + return (BLK_STS_IOERR); + } +} +#endif /* HAVE_BIO_BI_STATUS */ + +/* + * 4.3 API change + * The bio_endio() prototype changed slightly. These are helper + * macro's to ensure the prototype and invocation are handled. + */ +#ifdef HAVE_1ARG_BIO_END_IO_T +#ifdef HAVE_BIO_BI_STATUS +#define BIO_END_IO_ERROR(bio) bi_status_to_errno(bio->bi_status) +#define BIO_END_IO_PROTO(fn, x, z) static void fn(struct bio *x) +#define BIO_END_IO(bio, error) bio_set_bi_status(bio, error) +static inline void +bio_set_bi_status(struct bio *bio, int error) +{ + ASSERT3S(error, <=, 0); + bio->bi_status = errno_to_bi_status(-error); + bio_endio(bio); +} +#else +#define BIO_END_IO_ERROR(bio) (-(bio->bi_error)) +#define BIO_END_IO_PROTO(fn, x, z) static void fn(struct bio *x) +#define BIO_END_IO(bio, error) bio_set_bi_error(bio, error) +static inline void +bio_set_bi_error(struct bio *bio, int error) +{ + ASSERT3S(error, <=, 0); + bio->bi_error = error; + bio_endio(bio); +} +#endif /* HAVE_BIO_BI_STATUS */ + +#else +#define BIO_END_IO_PROTO(fn, x, z) static void fn(struct bio *x, int z) +#define BIO_END_IO(bio, error) bio_endio(bio, error); +#endif /* HAVE_1ARG_BIO_END_IO_T */ + +/* + * 4.1 - x.y.z API, + * 3.10.0 CentOS 7.x API, + * blkdev_reread_part() + * + * For older kernels trigger a re-reading of the partition table by calling + * check_disk_change() which calls flush_disk() to invalidate the device. + */ +#ifdef HAVE_BLKDEV_REREAD_PART +#define vdev_bdev_reread_part(bdev) blkdev_reread_part(bdev) +#else +#define vdev_bdev_reread_part(bdev) check_disk_change(bdev) +#endif /* HAVE_BLKDEV_REREAD_PART */ + +/* + * 2.6.27 API change + * The function was exported for use, prior to this it existed but the + * symbol was not exported. + * + * 4.4.0-6.21 API change for Ubuntu + * lookup_bdev() gained a second argument, FMODE_*, to check inode permissions. + */ +#ifdef HAVE_1ARG_LOOKUP_BDEV +#define vdev_lookup_bdev(path) lookup_bdev(path) +#else +#ifdef HAVE_2ARGS_LOOKUP_BDEV +#define vdev_lookup_bdev(path) lookup_bdev(path, 0) +#else +#error "Unsupported kernel" +#endif /* HAVE_2ARGS_LOOKUP_BDEV */ +#endif /* HAVE_1ARG_LOOKUP_BDEV */ + +/* + * Kernels without bio_set_op_attrs use bi_rw for the bio flags. + */ +#if !defined(HAVE_BIO_SET_OP_ATTRS) +static inline void +bio_set_op_attrs(struct bio *bio, unsigned rw, unsigned flags) +{ + bio->bi_rw |= rw | flags; +} +#endif + +/* + * bio_set_flush - Set the appropriate flags in a bio to guarantee + * data are on non-volatile media on completion. + * + * 2.6.37 - 4.8 API, + * Introduce WRITE_FLUSH, WRITE_FUA, and WRITE_FLUSH_FUA flags as a + * replacement for WRITE_BARRIER to allow expressing richer semantics + * to the block layer. It's up to the block layer to implement the + * semantics correctly. Use the WRITE_FLUSH_FUA flag combination. + * + * 4.8 - 4.9 API, + * REQ_FLUSH was renamed to REQ_PREFLUSH. For consistency with previous + * ZoL releases, prefer the WRITE_FLUSH_FUA flag set if it's available. + * + * 4.10 API, + * The read/write flags and their modifiers, including WRITE_FLUSH, + * WRITE_FUA and WRITE_FLUSH_FUA were removed from fs.h in + * torvalds/linux@70fd7614 and replaced by direct flag modification + * of the REQ_ flags in bio->bi_opf. Use REQ_PREFLUSH. + */ +static inline void +bio_set_flush(struct bio *bio) +{ +#if defined(HAVE_REQ_PREFLUSH) /* >= 4.10 */ + bio_set_op_attrs(bio, 0, REQ_PREFLUSH); +#elif defined(WRITE_FLUSH_FUA) /* >= 2.6.37 and <= 4.9 */ + bio_set_op_attrs(bio, 0, WRITE_FLUSH_FUA); +#else +#error "Allowing the build will cause bio_set_flush requests to be ignored." +#endif +} + +/* + * 4.8 - 4.x API, + * REQ_OP_FLUSH + * + * 4.8-rc0 - 4.8-rc1, + * REQ_PREFLUSH + * + * 2.6.36 - 4.7 API, + * REQ_FLUSH + * + * in all cases but may have a performance impact for some kernels. It + * has the advantage of minimizing kernel specific changes in the zvol code. + * + */ +static inline boolean_t +bio_is_flush(struct bio *bio) +{ +#if defined(HAVE_REQ_OP_FLUSH) && defined(HAVE_BIO_BI_OPF) + return ((bio_op(bio) == REQ_OP_FLUSH) || (bio->bi_opf & REQ_PREFLUSH)); +#elif defined(HAVE_REQ_PREFLUSH) && defined(HAVE_BIO_BI_OPF) + return (bio->bi_opf & REQ_PREFLUSH); +#elif defined(HAVE_REQ_PREFLUSH) && !defined(HAVE_BIO_BI_OPF) + return (bio->bi_rw & REQ_PREFLUSH); +#elif defined(HAVE_REQ_FLUSH) + return (bio->bi_rw & REQ_FLUSH); +#else +#error "Unsupported kernel" +#endif +} + +/* + * 4.8 - 4.x API, + * REQ_FUA flag moved to bio->bi_opf + * + * 2.6.x - 4.7 API, + * REQ_FUA + */ +static inline boolean_t +bio_is_fua(struct bio *bio) +{ +#if defined(HAVE_BIO_BI_OPF) + return (bio->bi_opf & REQ_FUA); +#elif defined(REQ_FUA) + return (bio->bi_rw & REQ_FUA); +#else +#error "Allowing the build will cause fua requests to be ignored." +#endif +} + +/* + * 4.8 - 4.x API, + * REQ_OP_DISCARD + * + * 2.6.36 - 4.7 API, + * REQ_DISCARD + * + * In all cases the normal I/O path is used for discards. The only + * difference is how the kernel tags individual I/Os as discards. + */ +static inline boolean_t +bio_is_discard(struct bio *bio) +{ +#if defined(HAVE_REQ_OP_DISCARD) + return (bio_op(bio) == REQ_OP_DISCARD); +#elif defined(HAVE_REQ_DISCARD) + return (bio->bi_rw & REQ_DISCARD); +#else +#error "Unsupported kernel" +#endif +} + +/* + * 4.8 - 4.x API, + * REQ_OP_SECURE_ERASE + * + * 2.6.36 - 4.7 API, + * REQ_SECURE + */ +static inline boolean_t +bio_is_secure_erase(struct bio *bio) +{ +#if defined(HAVE_REQ_OP_SECURE_ERASE) + return (bio_op(bio) == REQ_OP_SECURE_ERASE); +#elif defined(REQ_SECURE) + return (bio->bi_rw & REQ_SECURE); +#else + return (0); +#endif +} + +/* + * 2.6.33 API change + * Discard granularity and alignment restrictions may now be set. For + * older kernels which do not support this it is safe to skip it. + */ +static inline void +blk_queue_discard_granularity(struct request_queue *q, unsigned int dg) +{ + q->limits.discard_granularity = dg; +} + +/* + * 4.8 - 4.x API, + * blk_queue_secure_erase() + * + * 2.6.36 - 4.7 API, + * blk_queue_secdiscard() + */ +static inline int +blk_queue_discard_secure(struct request_queue *q) +{ +#if defined(HAVE_BLK_QUEUE_SECURE_ERASE) + return (blk_queue_secure_erase(q)); +#elif defined(HAVE_BLK_QUEUE_SECDISCARD) + return (blk_queue_secdiscard(q)); +#else + return (0); +#endif +} + +/* + * A common holder for vdev_bdev_open() is used to relax the exclusive open + * semantics slightly. Internal vdev disk callers may pass VDEV_HOLDER to + * allow them to open the device multiple times. Other kernel callers and + * user space processes which don't pass this value will get EBUSY. This is + * currently required for the correct operation of hot spares. + */ +#define VDEV_HOLDER ((void *)0x2401de7) + +static inline void +blk_generic_start_io_acct(struct request_queue *q, int rw, + unsigned long sectors, struct hd_struct *part) +{ +#if defined(HAVE_GENERIC_IO_ACCT_3ARG) + generic_start_io_acct(rw, sectors, part); +#elif defined(HAVE_GENERIC_IO_ACCT_4ARG) + generic_start_io_acct(q, rw, sectors, part); +#endif +} + +static inline void +blk_generic_end_io_acct(struct request_queue *q, int rw, + struct hd_struct *part, unsigned long start_time) +{ +#if defined(HAVE_GENERIC_IO_ACCT_3ARG) + generic_end_io_acct(rw, part, start_time); +#elif defined(HAVE_GENERIC_IO_ACCT_4ARG) + generic_end_io_acct(q, rw, part, start_time); +#endif +} + +#ifndef HAVE_SUBMIT_BIO_IN_BLOCK_DEVICE_OPERATIONS +static inline struct request_queue * +blk_generic_alloc_queue(make_request_fn make_request, int node_id) +{ +#if defined(HAVE_BLK_ALLOC_QUEUE_REQUEST_FN) + return (blk_alloc_queue(make_request, node_id)); +#else + struct request_queue *q = blk_alloc_queue(GFP_KERNEL); + if (q != NULL) + blk_queue_make_request(q, make_request); + + return (q); +#endif +} +#endif /* !HAVE_SUBMIT_BIO_IN_BLOCK_DEVICE_OPERATIONS */ + +#endif /* _ZFS_BLKDEV_H */ diff --git a/include/os/linux/kernel/linux/compiler_compat.h b/include/os/linux/kernel/linux/compiler_compat.h new file mode 100644 index 000000000000..921d32f246c5 --- /dev/null +++ b/include/os/linux/kernel/linux/compiler_compat.h @@ -0,0 +1,35 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright (C) 2018 Lawrence Livermore National Security, LLC. + */ + +#ifndef _ZFS_COMPILER_COMPAT_H +#define _ZFS_COMPILER_COMPAT_H + +#include <linux/compiler.h> + +#if !defined(READ_ONCE) +#define READ_ONCE(x) ACCESS_ONCE(x) +#endif + +#endif /* _ZFS_COMPILER_COMPAT_H */ diff --git a/include/os/linux/kernel/linux/dcache_compat.h b/include/os/linux/kernel/linux/dcache_compat.h new file mode 100644 index 000000000000..d0588a82e9ad --- /dev/null +++ b/include/os/linux/kernel/linux/dcache_compat.h @@ -0,0 +1,64 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright (C) 2011 Lawrence Livermore National Security, LLC. + */ + +#ifndef _ZFS_DCACHE_H +#define _ZFS_DCACHE_H + +#include <linux/dcache.h> + +#define dname(dentry) ((char *)((dentry)->d_name.name)) +#define dlen(dentry) ((int)((dentry)->d_name.len)) + +#ifndef HAVE_D_MAKE_ROOT +#define d_make_root(inode) d_alloc_root(inode) +#endif /* HAVE_D_MAKE_ROOT */ + +/* + * 2.6.30 API change, + * The const keyword was added to the 'struct dentry_operations' in + * the dentry structure. To handle this we define an appropriate + * dentry_operations_t typedef which can be used. + */ +typedef const struct dentry_operations dentry_operations_t; + +/* + * 2.6.38 API addition, + * Added d_clear_d_op() helper function which clears some flags and the + * registered dentry->d_op table. This is required because d_set_d_op() + * issues a warning when the dentry operations table is already set. + * For the .zfs control directory to work properly we must be able to + * override the default operations table and register custom .d_automount + * and .d_revalidate callbacks. + */ +static inline void +d_clear_d_op(struct dentry *dentry) +{ + dentry->d_op = NULL; + dentry->d_flags &= ~( + DCACHE_OP_HASH | DCACHE_OP_COMPARE | + DCACHE_OP_REVALIDATE | DCACHE_OP_DELETE); +} + +#endif /* _ZFS_DCACHE_H */ diff --git a/include/os/linux/kernel/linux/kmap_compat.h b/include/os/linux/kernel/linux/kmap_compat.h new file mode 100644 index 000000000000..a7e63944ea16 --- /dev/null +++ b/include/os/linux/kernel/linux/kmap_compat.h @@ -0,0 +1,43 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 2015 by Chunwei Chen. All rights reserved. + */ + +#ifndef _ZFS_KMAP_H +#define _ZFS_KMAP_H + +#include <linux/highmem.h> +#include <linux/uaccess.h> + +/* 2.6.37 API change */ +#define zfs_kmap_atomic(page, km_type) kmap_atomic(page) +#define zfs_kunmap_atomic(addr, km_type) kunmap_atomic(addr) + +/* 5.0 API change - no more 'type' argument for access_ok() */ +#ifdef HAVE_ACCESS_OK_TYPE +#define zfs_access_ok(type, addr, size) access_ok(type, addr, size) +#else +#define zfs_access_ok(type, addr, size) access_ok(addr, size) +#endif + +#endif /* _ZFS_KMAP_H */ diff --git a/include/os/linux/kernel/linux/mod_compat.h b/include/os/linux/kernel/linux/mod_compat.h new file mode 100644 index 000000000000..4b83fe413334 --- /dev/null +++ b/include/os/linux/kernel/linux/mod_compat.h @@ -0,0 +1,151 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright (C) 2016 Gvozden Neskovic <neskovic@gmail.com>. + */ + +#ifndef _MOD_COMPAT_H +#define _MOD_COMPAT_H + +#include <linux/module.h> +#include <linux/moduleparam.h> + +/* Grsecurity kernel API change */ +#ifdef MODULE_PARAM_CALL_CONST +typedef const struct kernel_param zfs_kernel_param_t; +#else +typedef struct kernel_param zfs_kernel_param_t; +#endif + +#define ZMOD_RW 0644 +#define ZMOD_RD 0444 + +/* BEGIN CSTYLED */ +#define INT int +#define UINT uint +#define ULONG ulong +#define LONG long +#define STRING charp +/* END CSTYLED */ + +enum scope_prefix_types { + zfs, + zfs_arc, + zfs_condense, + zfs_dbuf, + zfs_dbuf_cache, + zfs_deadman, + zfs_dedup, + zfs_l2arc, + zfs_livelist, + zfs_livelist_condense, + zfs_lua, + zfs_metaslab, + zfs_mg, + zfs_multihost, + zfs_prefetch, + zfs_reconstruct, + zfs_recv, + zfs_send, + zfs_spa, + zfs_trim, + zfs_txg, + zfs_vdev, + zfs_vdev_cache, + zfs_vdev_mirror, + zfs_zevent, + zfs_zio, + zfs_zil +}; + +/* + * Declare a module parameter / sysctl node + * + * "scope_prefix" the part of the the sysctl / sysfs tree the node resides under + * (currently a no-op on Linux) + * "name_prefix" the part of the variable name that will be excluded from the + * exported names on platforms with a hierarchical namespace + * "name" the part of the variable that will be exposed on platforms with a + * hierarchical namespace, or as name_prefix ## name on Linux + * "type" the variable type + * "perm" the permissions (read/write or read only) + * "desc" a brief description of the option + * + * Examples: + * ZFS_MODULE_PARAM(zfs_vdev_mirror, zfs_vdev_mirror_, rotating_inc, UINT, + * ZMOD_RW, "Rotating media load increment for non-seeking I/O's"); + * on FreeBSD: + * vfs.zfs.vdev.mirror.rotating_inc + * on Linux: + * zfs_vdev_mirror_rotating_inc + * + * ZFS_MODULE_PARAM(zfs, , dmu_prefetch_max, UINT, ZMOD_RW, + * "Limit one prefetch call to this size"); + * on FreeBSD: + * vfs.zfs.dmu_prefetch_max + * on Linux: + * dmu_prefetch_max + */ +/* BEGIN CSTYLED */ +#define ZFS_MODULE_PARAM(scope_prefix, name_prefix, name, type, perm, desc) \ + CTASSERT_GLOBAL((sizeof (scope_prefix) == sizeof (enum scope_prefix_types))); \ + module_param(name_prefix ## name, type, perm); \ + MODULE_PARM_DESC(name_prefix ## name, desc) +/* END CSTYLED */ + +/* + * Declare a module parameter / sysctl node + * + * "scope_prefix" the part of the the sysctl / sysfs tree the node resides under + * (currently a no-op on Linux) + * "name_prefix" the part of the variable name that will be excluded from the + * exported names on platforms with a hierarchical namespace + * "name" the part of the variable that will be exposed on platforms with a + * hierarchical namespace, or as name_prefix ## name on Linux + * "setfunc" setter function + * "getfunc" getter function + * "perm" the permissions (read/write or read only) + * "desc" a brief description of the option + * + * Examples: + * ZFS_MODULE_PARAM_CALL(zfs_spa, spa_, slop_shift, param_set_slop_shift, + * param_get_int, ZMOD_RW, "Reserved free space in pool"); + * on FreeBSD: + * vfs.zfs.spa_slop_shift + * on Linux: + * spa_slop_shift + */ +/* BEGIN CSTYLED */ +#define ZFS_MODULE_PARAM_CALL(scope_prefix, name_prefix, name, setfunc, getfunc, perm, desc) \ + CTASSERT_GLOBAL((sizeof (scope_prefix) == sizeof (enum scope_prefix_types))); \ + module_param_call(name_prefix ## name, setfunc, getfunc, &name_prefix ## name, perm); \ + MODULE_PARM_DESC(name_prefix ## name, desc) +/* END CSTYLED */ + +#define ZFS_MODULE_PARAM_ARGS const char *buf, zfs_kernel_param_t *kp + +#define ZFS_MODULE_DESCRIPTION(s) MODULE_DESCRIPTION(s) +#define ZFS_MODULE_AUTHOR(s) MODULE_AUTHOR(s) +#define ZFS_MODULE_LICENSE(s) MODULE_LICENSE(s) +#define ZFS_MODULE_VERSION(s) MODULE_VERSION(s) + +#endif /* _MOD_COMPAT_H */ diff --git a/include/os/linux/kernel/linux/page_compat.h b/include/os/linux/kernel/linux/page_compat.h new file mode 100644 index 000000000000..8ad04f9bbfc6 --- /dev/null +++ b/include/os/linux/kernel/linux/page_compat.h @@ -0,0 +1,92 @@ +#ifndef _ZFS_PAGE_COMPAT_H +#define _ZFS_PAGE_COMPAT_H + +/* + * We have various enum members moving between two separate enum types, + * and accessed by different functions at various times. Centralise the + * insanity. + * + * < v4.8: all enums in zone_stat_item, via global_page_state() + * v4.8: some enums moved to node_stat_item, global_node_page_state() introduced + * v4.13: some enums moved from zone_stat_item to node_state_item + * v4.14: global_page_state() rename to global_zone_page_state() + * + * The defines used here are created by config/kernel-global_page_state.m4 + */ + +/* + * Create our own accessor functions to follow the Linux API changes + */ +#if defined(ZFS_GLOBAL_ZONE_PAGE_STATE) + +/* global_zone_page_state() introduced */ +#if defined(ZFS_ENUM_NODE_STAT_ITEM_NR_FILE_PAGES) +#define nr_file_pages() global_node_page_state(NR_FILE_PAGES) +#else +#define nr_file_pages() global_zone_page_state(NR_FILE_PAGES) +#endif +#if defined(ZFS_ENUM_NODE_STAT_ITEM_NR_INACTIVE_ANON) +#define nr_inactive_anon_pages() global_node_page_state(NR_INACTIVE_ANON) +#else +#define nr_inactive_anon_pages() global_zone_page_state(NR_INACTIVE_ANON) +#endif +#if defined(ZFS_ENUM_NODE_STAT_ITEM_NR_INACTIVE_FILE) +#define nr_inactive_file_pages() global_node_page_state(NR_INACTIVE_FILE) +#else +#define nr_inactive_file_pages() global_zone_page_state(NR_INACTIVE_FILE) +#endif +#if defined(ZFS_ENUM_NODE_STAT_ITEM_NR_SLAB_RECLAIMABLE_B) +#define nr_slab_reclaimable_pages() \ + global_node_page_state(NR_SLAB_RECLAIMABLE_B) +#else +#if defined(ZFS_ENUM_NODE_STAT_ITEM_NR_SLAB_RECLAIMABLE) +#define nr_slab_reclaimable_pages() global_node_page_state(NR_SLAB_RECLAIMABLE) +#else +#define nr_slab_reclaimable_pages() global_zone_page_state(NR_SLAB_RECLAIMABLE) +#endif +#endif + +#elif defined(ZFS_GLOBAL_NODE_PAGE_STATE) + +/* global_node_page_state() introduced */ +#if defined(ZFS_ENUM_NODE_STAT_ITEM_NR_FILE_PAGES) +#define nr_file_pages() global_node_page_state(NR_FILE_PAGES) +#else +#define nr_file_pages() global_page_state(NR_FILE_PAGES) +#endif +#if defined(ZFS_ENUM_NODE_STAT_ITEM_NR_INACTIVE_ANON) +#define nr_inactive_anon_pages() global_node_page_state(NR_INACTIVE_ANON) +#else +#define nr_inactive_anon_pages() global_page_state(NR_INACTIVE_ANON) +#endif +#if defined(ZFS_ENUM_NODE_STAT_ITEM_NR_INACTIVE_FILE) +#define nr_inactive_file_pages() global_node_page_state(NR_INACTIVE_FILE) +#else +#define nr_inactive_file_pages() global_page_state(NR_INACTIVE_FILE) +#endif +#if defined(ZFS_ENUM_NODE_STAT_ITEM_NR_SLAB_RECLAIMABLE_B) +#define nr_slab_reclaimable_pages() \ + global_node_page_state(NR_SLAB_RECLAIMABLE_B) +#else +#if defined(ZFS_ENUM_NODE_STAT_ITEM_NR_SLAB_RECLAIMABLE) +#define nr_slab_reclaimable_pages() global_node_page_state(NR_SLAB_RECLAIMABLE) +#else +#define nr_slab_reclaimable_pages() global_page_state(NR_SLAB_RECLAIMABLE) +#endif +#endif + +#else + +/* global_page_state() only */ +#define nr_file_pages() global_page_state(NR_FILE_PAGES) +#define nr_inactive_anon_pages() global_page_state(NR_INACTIVE_ANON) +#define nr_inactive_file_pages() global_page_state(NR_INACTIVE_FILE) +#ifdef ZFS_ENUM_NODE_STAT_ITEM_NR_SLAB_RECLAIMABLE_B +#define nr_slab_reclaimable_pages() global_page_state(NR_SLAB_RECLAIMABLE_B) +#else +#define nr_slab_reclaimable_pages() global_page_state(NR_SLAB_RECLAIMABLE) +#endif /* ZFS_ENUM_NODE_STAT_ITEM_NR_SLAB_RECLAIMABLE_B */ + +#endif /* ZFS_GLOBAL_ZONE_PAGE_STATE */ + +#endif /* _ZFS_PAGE_COMPAT_H */ diff --git a/include/os/linux/kernel/linux/percpu_compat.h b/include/os/linux/kernel/linux/percpu_compat.h new file mode 100644 index 000000000000..e7a4242c466c --- /dev/null +++ b/include/os/linux/kernel/linux/percpu_compat.h @@ -0,0 +1,44 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 2020 by Delphix. All rights reserved. + */ + +#ifndef _ZFS_PERCPU_H +#define _ZFS_PERCPU_H + +#include <linux/percpu_counter.h> + +/* + * 3.18 API change, + * percpu_counter_init() now must be passed a gfp mask which will be + * used for the dynamic allocation of the actual counter. + */ +#ifdef HAVE_PERCPU_COUNTER_INIT_WITH_GFP +#define percpu_counter_init_common(counter, n, gfp) \ + percpu_counter_init(counter, n, gfp) +#else +#define percpu_counter_init_common(counter, n, gfp) \ + percpu_counter_init(counter, n) +#endif + +#endif /* _ZFS_PERCPU_H */ diff --git a/include/os/linux/kernel/linux/simd.h b/include/os/linux/kernel/linux/simd.h new file mode 100644 index 000000000000..4cde248e200c --- /dev/null +++ b/include/os/linux/kernel/linux/simd.h @@ -0,0 +1,45 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (C) 2019 Lawrence Livermore National Security, LLC. + */ + +#ifndef _LINUX_SIMD_H +#define _LINUX_SIMD_H + +#if defined(__x86) +#include <linux/simd_x86.h> + +#elif defined(__aarch64__) +#include <linux/simd_aarch64.h> + +#elif defined(__powerpc__) +#include <linux/simd_powerpc.h> +#else + +#define kfpu_allowed() 0 +#define kfpu_begin() do {} while (0) +#define kfpu_end() do {} while (0) +#define kfpu_init() 0 +#define kfpu_fini() ((void) 0) + +#endif +#endif /* _LINUX_SIMD_H */ diff --git a/include/os/linux/kernel/linux/simd_aarch64.h b/include/os/linux/kernel/linux/simd_aarch64.h new file mode 100644 index 000000000000..50937e97ced1 --- /dev/null +++ b/include/os/linux/kernel/linux/simd_aarch64.h @@ -0,0 +1,54 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (C) 2016 Romain Dolbeau <romain@dolbeau.org>. + */ + +/* + * USER API: + * + * Kernel fpu methods: + * kfpu_allowed() + * kfpu_begin() + * kfpu_end() + * kfpu_init() + * kfpu_fini() + */ + +#ifndef _LINUX_SIMD_AARCH64_H +#define _LINUX_SIMD_AARCH64_H + +#include <sys/isa_defs.h> + +#if defined(__aarch64__) + +#include <sys/types.h> +#include <asm/neon.h> + +#define kfpu_allowed() 1 +#define kfpu_begin() kernel_neon_begin() +#define kfpu_end() kernel_neon_end() +#define kfpu_init() 0 +#define kfpu_fini() ((void) 0) + +#endif /* __aarch64__ */ + +#endif /* _LINUX_SIMD_AARCH64_H */ diff --git a/include/os/linux/kernel/linux/simd_powerpc.h b/include/os/linux/kernel/linux/simd_powerpc.h new file mode 100644 index 000000000000..108cef22f56f --- /dev/null +++ b/include/os/linux/kernel/linux/simd_powerpc.h @@ -0,0 +1,109 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (C) 2019 Romain Dolbeau + * <romain.dolbeau@european-processor-initiative.eu> + */ + +/* + * USER API: + * + * Kernel fpu methods: + * kfpu_allowed() + * kfpu_begin() + * kfpu_end() + * kfpu_init() + * kfpu_fini() + * + * SIMD support: + * + * Following functions should be called to determine whether CPU feature + * is supported. All functions are usable in kernel and user space. + * If a SIMD algorithm is using more than one instruction set + * all relevant feature test functions should be called. + * + * Supported features: + * zfs_altivec_available() + */ + +#ifndef _LINUX_SIMD_POWERPC_H +#define _LINUX_SIMD_POWERPC_H + +/* only for __powerpc__ */ +#if defined(__powerpc__) + +#include <linux/preempt.h> +#include <linux/export.h> +#include <linux/sched.h> +#include <asm/switch_to.h> +#include <sys/types.h> +#include <linux/version.h> + +#define kfpu_allowed() 1 +#define kfpu_begin() \ + { \ + preempt_disable(); \ + enable_kernel_altivec(); \ + } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0) +#define kfpu_end() \ + { \ + disable_kernel_altivec(); \ + preempt_enable(); \ + } +#else +/* seems that before 4.5 no-one bothered disabling ... */ +#define kfpu_end() preempt_enable() +#endif +#define kfpu_init() 0 +#define kfpu_fini() ((void) 0) + +/* + * Check if AltiVec instruction set is available + */ +static inline boolean_t +zfs_altivec_available(void) +{ + boolean_t res; + /* suggested by macallan at netbsd dot org */ +#if defined(__powerpc64__) + u64 msr; +#else + u32 msr; +#endif + kfpu_begin(); + __asm volatile("mfmsr %0" : "=r"(msr)); + /* + * 64 bits -> need to check bit 38 + * Power ISA Version 3.0B + * p944 + * 32 bits -> Need to check bit 6 + * AltiVec Technology Programming Environments Manual + * p49 (2-9) + * They are the same, as ppc counts 'backward' ... + */ + res = (msr & 0x2000000) != 0; + kfpu_end(); + return (res); +} +#endif /* defined(__powerpc) */ + +#endif /* _LINUX_SIMD_POWERPC_H */ diff --git a/include/os/linux/kernel/linux/simd_x86.h b/include/os/linux/kernel/linux/simd_x86.h new file mode 100644 index 000000000000..cdd3286d2147 --- /dev/null +++ b/include/os/linux/kernel/linux/simd_x86.h @@ -0,0 +1,646 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (C) 2016 Gvozden Neskovic <neskovic@compeng.uni-frankfurt.de>. + */ + +/* + * USER API: + * + * Kernel fpu methods: + * kfpu_allowed() + * kfpu_begin() + * kfpu_end() + * kfpu_init() + * kfpu_fini() + * + * SIMD support: + * + * Following functions should be called to determine whether CPU feature + * is supported. All functions are usable in kernel and user space. + * If a SIMD algorithm is using more than one instruction set + * all relevant feature test functions should be called. + * + * Supported features: + * zfs_sse_available() + * zfs_sse2_available() + * zfs_sse3_available() + * zfs_ssse3_available() + * zfs_sse4_1_available() + * zfs_sse4_2_available() + * + * zfs_avx_available() + * zfs_avx2_available() + * + * zfs_bmi1_available() + * zfs_bmi2_available() + * + * zfs_avx512f_available() + * zfs_avx512cd_available() + * zfs_avx512er_available() + * zfs_avx512pf_available() + * zfs_avx512bw_available() + * zfs_avx512dq_available() + * zfs_avx512vl_available() + * zfs_avx512ifma_available() + * zfs_avx512vbmi_available() + * + * NOTE(AVX-512VL): If using AVX-512 instructions with 128Bit registers + * also add zfs_avx512vl_available() to feature check. + */ + +#ifndef _LINUX_SIMD_X86_H +#define _LINUX_SIMD_X86_H + +/* only for __x86 */ +#if defined(__x86) + +#include <sys/types.h> +#include <asm/cpufeature.h> + +/* + * Disable the WARN_ON_FPU() macro to prevent additional dependencies + * when providing the kfpu_* functions. Relevant warnings are included + * as appropriate and are unconditionally enabled. + */ +#if defined(CONFIG_X86_DEBUG_FPU) && !defined(KERNEL_EXPORTS_X86_FPU) +#undef CONFIG_X86_DEBUG_FPU +#endif + +#if defined(HAVE_KERNEL_FPU_API_HEADER) +#include <asm/fpu/api.h> +#include <asm/fpu/internal.h> +#else +#include <asm/i387.h> +#include <asm/xcr.h> +#endif + +/* + * The following cases are for kernels which export either the + * kernel_fpu_* or __kernel_fpu_* functions. + */ +#if defined(KERNEL_EXPORTS_X86_FPU) + +#define kfpu_allowed() 1 +#define kfpu_init() 0 +#define kfpu_fini() ((void) 0) + +#if defined(HAVE_UNDERSCORE_KERNEL_FPU) +#define kfpu_begin() \ +{ \ + preempt_disable(); \ + __kernel_fpu_begin(); \ +} +#define kfpu_end() \ +{ \ + __kernel_fpu_end(); \ + preempt_enable(); \ +} + +#elif defined(HAVE_KERNEL_FPU) +#define kfpu_begin() kernel_fpu_begin() +#define kfpu_end() kernel_fpu_end() + +#else +/* + * This case is unreachable. When KERNEL_EXPORTS_X86_FPU is defined then + * either HAVE_UNDERSCORE_KERNEL_FPU or HAVE_KERNEL_FPU must be defined. + */ +#error "Unreachable kernel configuration" +#endif + +#else /* defined(KERNEL_EXPORTS_X86_FPU) */ + +/* + * When the kernel_fpu_* symbols are unavailable then provide our own + * versions which allow the FPU to be safely used. + */ +#if defined(HAVE_KERNEL_FPU_INTERNAL) + +#include <linux/mm.h> + +extern union fpregs_state **zfs_kfpu_fpregs; + +/* + * Initialize per-cpu variables to store FPU state. + */ +static inline void +kfpu_fini(void) +{ + int cpu; + + for_each_possible_cpu(cpu) { + if (zfs_kfpu_fpregs[cpu] != NULL) { + free_pages((unsigned long)zfs_kfpu_fpregs[cpu], + get_order(sizeof (union fpregs_state))); + } + } + + kfree(zfs_kfpu_fpregs); +} + +static inline int +kfpu_init(void) +{ + zfs_kfpu_fpregs = kzalloc(num_possible_cpus() * + sizeof (union fpregs_state *), GFP_KERNEL); + if (zfs_kfpu_fpregs == NULL) + return (-ENOMEM); + + /* + * The fxsave and xsave operations require 16-/64-byte alignment of + * the target memory. Since kmalloc() provides no alignment + * guarantee instead use alloc_pages_node(). + */ + unsigned int order = get_order(sizeof (union fpregs_state)); + int cpu; + + for_each_possible_cpu(cpu) { + struct page *page = alloc_pages_node(cpu_to_node(cpu), + GFP_KERNEL | __GFP_ZERO, order); + if (page == NULL) { + kfpu_fini(); + return (-ENOMEM); + } + + zfs_kfpu_fpregs[cpu] = page_address(page); + } + + return (0); +} + +#define kfpu_allowed() 1 +#define ex_handler_fprestore ex_handler_default + +/* + * FPU save and restore instructions. + */ +#define __asm __asm__ __volatile__ +#define kfpu_fxsave(addr) __asm("fxsave %0" : "=m" (*(addr))) +#define kfpu_fxsaveq(addr) __asm("fxsaveq %0" : "=m" (*(addr))) +#define kfpu_fnsave(addr) __asm("fnsave %0; fwait" : "=m" (*(addr))) +#define kfpu_fxrstor(addr) __asm("fxrstor %0" : : "m" (*(addr))) +#define kfpu_fxrstorq(addr) __asm("fxrstorq %0" : : "m" (*(addr))) +#define kfpu_frstor(addr) __asm("frstor %0" : : "m" (*(addr))) +#define kfpu_fxsr_clean(rval) __asm("fnclex; emms; fildl %P[addr]" \ + : : [addr] "m" (rval)); + +static inline void +kfpu_save_xsave(struct xregs_state *addr, uint64_t mask) +{ + uint32_t low, hi; + int err; + + low = mask; + hi = mask >> 32; + XSTATE_XSAVE(addr, low, hi, err); + WARN_ON_ONCE(err); +} + +static inline void +kfpu_save_fxsr(struct fxregs_state *addr) +{ + if (IS_ENABLED(CONFIG_X86_32)) + kfpu_fxsave(addr); + else + kfpu_fxsaveq(addr); +} + +static inline void +kfpu_save_fsave(struct fregs_state *addr) +{ + kfpu_fnsave(addr); +} + +static inline void +kfpu_begin(void) +{ + /* + * Preemption and interrupts must be disabled for the critical + * region where the FPU state is being modified. + */ + preempt_disable(); + local_irq_disable(); + + /* + * The current FPU registers need to be preserved by kfpu_begin() + * and restored by kfpu_end(). They are stored in a dedicated + * per-cpu variable, not in the task struct, this allows any user + * FPU state to be correctly preserved and restored. + */ + union fpregs_state *state = zfs_kfpu_fpregs[smp_processor_id()]; + + if (static_cpu_has(X86_FEATURE_XSAVE)) { + kfpu_save_xsave(&state->xsave, ~0); + } else if (static_cpu_has(X86_FEATURE_FXSR)) { + kfpu_save_fxsr(&state->fxsave); + } else { + kfpu_save_fsave(&state->fsave); + } +} + +static inline void +kfpu_restore_xsave(struct xregs_state *addr, uint64_t mask) +{ + uint32_t low, hi; + + low = mask; + hi = mask >> 32; + XSTATE_XRESTORE(addr, low, hi); +} + +static inline void +kfpu_restore_fxsr(struct fxregs_state *addr) +{ + /* + * On AuthenticAMD K7 and K8 processors the fxrstor instruction only + * restores the _x87 FOP, FIP, and FDP registers when an exception + * is pending. Clean the _x87 state to force the restore. + */ + if (unlikely(static_cpu_has_bug(X86_BUG_FXSAVE_LEAK))) + kfpu_fxsr_clean(addr); + + if (IS_ENABLED(CONFIG_X86_32)) { + kfpu_fxrstor(addr); + } else { + kfpu_fxrstorq(addr); + } +} + +static inline void +kfpu_restore_fsave(struct fregs_state *addr) +{ + kfpu_frstor(addr); +} + +static inline void +kfpu_end(void) +{ + union fpregs_state *state = zfs_kfpu_fpregs[smp_processor_id()]; + + if (static_cpu_has(X86_FEATURE_XSAVE)) { + kfpu_restore_xsave(&state->xsave, ~0); + } else if (static_cpu_has(X86_FEATURE_FXSR)) { + kfpu_restore_fxsr(&state->fxsave); + } else { + kfpu_restore_fsave(&state->fsave); + } + + local_irq_enable(); + preempt_enable(); +} + +#else + +/* + * FPU support is unavailable. + */ +#define kfpu_allowed() 0 +#define kfpu_begin() do {} while (0) +#define kfpu_end() do {} while (0) +#define kfpu_init() 0 +#define kfpu_fini() ((void) 0) + +#endif /* defined(HAVE_KERNEL_FPU_INTERNAL) */ +#endif /* defined(KERNEL_EXPORTS_X86_FPU) */ + +/* + * Linux kernel provides an interface for CPU feature testing. + */ + +/* + * Detect register set support + */ +static inline boolean_t +__simd_state_enabled(const uint64_t state) +{ + boolean_t has_osxsave; + uint64_t xcr0; + +#if defined(X86_FEATURE_OSXSAVE) + has_osxsave = !!boot_cpu_has(X86_FEATURE_OSXSAVE); +#else + has_osxsave = B_FALSE; +#endif + if (!has_osxsave) + return (B_FALSE); + + xcr0 = xgetbv(0); + return ((xcr0 & state) == state); +} + +#define _XSTATE_SSE_AVX (0x2 | 0x4) +#define _XSTATE_AVX512 (0xE0 | _XSTATE_SSE_AVX) + +#define __ymm_enabled() __simd_state_enabled(_XSTATE_SSE_AVX) +#define __zmm_enabled() __simd_state_enabled(_XSTATE_AVX512) + +/* + * Check if SSE instruction set is available + */ +static inline boolean_t +zfs_sse_available(void) +{ + return (!!boot_cpu_has(X86_FEATURE_XMM)); +} + +/* + * Check if SSE2 instruction set is available + */ +static inline boolean_t +zfs_sse2_available(void) +{ + return (!!boot_cpu_has(X86_FEATURE_XMM2)); +} + +/* + * Check if SSE3 instruction set is available + */ +static inline boolean_t +zfs_sse3_available(void) +{ + return (!!boot_cpu_has(X86_FEATURE_XMM3)); +} + +/* + * Check if SSSE3 instruction set is available + */ +static inline boolean_t +zfs_ssse3_available(void) +{ + return (!!boot_cpu_has(X86_FEATURE_SSSE3)); +} + +/* + * Check if SSE4.1 instruction set is available + */ +static inline boolean_t +zfs_sse4_1_available(void) +{ + return (!!boot_cpu_has(X86_FEATURE_XMM4_1)); +} + +/* + * Check if SSE4.2 instruction set is available + */ +static inline boolean_t +zfs_sse4_2_available(void) +{ + return (!!boot_cpu_has(X86_FEATURE_XMM4_2)); +} + +/* + * Check if AVX instruction set is available + */ +static inline boolean_t +zfs_avx_available(void) +{ + return (boot_cpu_has(X86_FEATURE_AVX) && __ymm_enabled()); +} + +/* + * Check if AVX2 instruction set is available + */ +static inline boolean_t +zfs_avx2_available(void) +{ + return (boot_cpu_has(X86_FEATURE_AVX2) && __ymm_enabled()); +} + +/* + * Check if BMI1 instruction set is available + */ +static inline boolean_t +zfs_bmi1_available(void) +{ +#if defined(X86_FEATURE_BMI1) + return (!!boot_cpu_has(X86_FEATURE_BMI1)); +#else + return (B_FALSE); +#endif +} + +/* + * Check if BMI2 instruction set is available + */ +static inline boolean_t +zfs_bmi2_available(void) +{ +#if defined(X86_FEATURE_BMI2) + return (!!boot_cpu_has(X86_FEATURE_BMI2)); +#else + return (B_FALSE); +#endif +} + +/* + * Check if AES instruction set is available + */ +static inline boolean_t +zfs_aes_available(void) +{ +#if defined(X86_FEATURE_AES) + return (!!boot_cpu_has(X86_FEATURE_AES)); +#else + return (B_FALSE); +#endif +} + +/* + * Check if PCLMULQDQ instruction set is available + */ +static inline boolean_t +zfs_pclmulqdq_available(void) +{ +#if defined(X86_FEATURE_PCLMULQDQ) + return (!!boot_cpu_has(X86_FEATURE_PCLMULQDQ)); +#else + return (B_FALSE); +#endif +} + +/* + * Check if MOVBE instruction is available + */ +static inline boolean_t +zfs_movbe_available(void) +{ +#if defined(X86_FEATURE_MOVBE) + return (!!boot_cpu_has(X86_FEATURE_MOVBE)); +#else + return (B_FALSE); +#endif +} + +/* + * AVX-512 family of instruction sets: + * + * AVX512F Foundation + * AVX512CD Conflict Detection Instructions + * AVX512ER Exponential and Reciprocal Instructions + * AVX512PF Prefetch Instructions + * + * AVX512BW Byte and Word Instructions + * AVX512DQ Double-word and Quadword Instructions + * AVX512VL Vector Length Extensions + * + * AVX512IFMA Integer Fused Multiply Add (Not supported by kernel 4.4) + * AVX512VBMI Vector Byte Manipulation Instructions + */ + +/* + * Check if AVX512F instruction set is available + */ +static inline boolean_t +zfs_avx512f_available(void) +{ + boolean_t has_avx512 = B_FALSE; + +#if defined(X86_FEATURE_AVX512F) + has_avx512 = !!boot_cpu_has(X86_FEATURE_AVX512F); +#endif + return (has_avx512 && __zmm_enabled()); +} + +/* + * Check if AVX512CD instruction set is available + */ +static inline boolean_t +zfs_avx512cd_available(void) +{ + boolean_t has_avx512 = B_FALSE; + +#if defined(X86_FEATURE_AVX512CD) + has_avx512 = boot_cpu_has(X86_FEATURE_AVX512F) && + boot_cpu_has(X86_FEATURE_AVX512CD); +#endif + return (has_avx512 && __zmm_enabled()); +} + +/* + * Check if AVX512ER instruction set is available + */ +static inline boolean_t +zfs_avx512er_available(void) +{ + boolean_t has_avx512 = B_FALSE; + +#if defined(X86_FEATURE_AVX512ER) + has_avx512 = boot_cpu_has(X86_FEATURE_AVX512F) && + boot_cpu_has(X86_FEATURE_AVX512ER); +#endif + return (has_avx512 && __zmm_enabled()); +} + +/* + * Check if AVX512PF instruction set is available + */ +static inline boolean_t +zfs_avx512pf_available(void) +{ + boolean_t has_avx512 = B_FALSE; + +#if defined(X86_FEATURE_AVX512PF) + has_avx512 = boot_cpu_has(X86_FEATURE_AVX512F) && + boot_cpu_has(X86_FEATURE_AVX512PF); +#endif + return (has_avx512 && __zmm_enabled()); +} + +/* + * Check if AVX512BW instruction set is available + */ +static inline boolean_t +zfs_avx512bw_available(void) +{ + boolean_t has_avx512 = B_FALSE; + +#if defined(X86_FEATURE_AVX512BW) + has_avx512 = boot_cpu_has(X86_FEATURE_AVX512F) && + boot_cpu_has(X86_FEATURE_AVX512BW); +#endif + + return (has_avx512 && __zmm_enabled()); +} + +/* + * Check if AVX512DQ instruction set is available + */ +static inline boolean_t +zfs_avx512dq_available(void) +{ + boolean_t has_avx512 = B_FALSE; + +#if defined(X86_FEATURE_AVX512DQ) + has_avx512 = boot_cpu_has(X86_FEATURE_AVX512F) && + boot_cpu_has(X86_FEATURE_AVX512DQ); +#endif + return (has_avx512 && __zmm_enabled()); +} + +/* + * Check if AVX512VL instruction set is available + */ +static inline boolean_t +zfs_avx512vl_available(void) +{ + boolean_t has_avx512 = B_FALSE; + +#if defined(X86_FEATURE_AVX512VL) + has_avx512 = boot_cpu_has(X86_FEATURE_AVX512F) && + boot_cpu_has(X86_FEATURE_AVX512VL); +#endif + return (has_avx512 && __zmm_enabled()); +} + +/* + * Check if AVX512IFMA instruction set is available + */ +static inline boolean_t +zfs_avx512ifma_available(void) +{ + boolean_t has_avx512 = B_FALSE; + +#if defined(X86_FEATURE_AVX512IFMA) + has_avx512 = boot_cpu_has(X86_FEATURE_AVX512F) && + boot_cpu_has(X86_FEATURE_AVX512IFMA); +#endif + return (has_avx512 && __zmm_enabled()); +} + +/* + * Check if AVX512VBMI instruction set is available + */ +static inline boolean_t +zfs_avx512vbmi_available(void) +{ + boolean_t has_avx512 = B_FALSE; + +#if defined(X86_FEATURE_AVX512VBMI) + has_avx512 = boot_cpu_has(X86_FEATURE_AVX512F) && + boot_cpu_has(X86_FEATURE_AVX512VBMI); +#endif + return (has_avx512 && __zmm_enabled()); +} + +#endif /* defined(__x86) */ + +#endif /* _LINUX_SIMD_X86_H */ diff --git a/include/os/linux/kernel/linux/utsname_compat.h b/include/os/linux/kernel/linux/utsname_compat.h new file mode 100644 index 000000000000..88da45cf504e --- /dev/null +++ b/include/os/linux/kernel/linux/utsname_compat.h @@ -0,0 +1,29 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +#ifndef _ZFS_UTSNAME_H +#define _ZFS_UTSNAME_H + +#include <linux/utsname.h> + +typedef struct new_utsname utsname_t; + +#endif /* _ZFS_UTSNAME_H */ diff --git a/include/os/linux/kernel/linux/vfs_compat.h b/include/os/linux/kernel/linux/vfs_compat.h new file mode 100644 index 000000000000..c35e80d31cd7 --- /dev/null +++ b/include/os/linux/kernel/linux/vfs_compat.h @@ -0,0 +1,439 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright (C) 2011 Lawrence Livermore National Security, LLC. + * Copyright (C) 2015 Jörg Thalheim. + */ + +#ifndef _ZFS_VFS_H +#define _ZFS_VFS_H + +#include <sys/taskq.h> +#include <sys/cred.h> +#include <linux/backing-dev.h> +#include <linux/compat.h> + +/* + * 2.6.34 - 3.19, bdi_setup_and_register() takes 3 arguments. + * 4.0 - 4.11, bdi_setup_and_register() takes 2 arguments. + * 4.12 - x.y, super_setup_bdi_name() new interface. + */ +#if defined(HAVE_SUPER_SETUP_BDI_NAME) +extern atomic_long_t zfs_bdi_seq; + +static inline int +zpl_bdi_setup(struct super_block *sb, char *name) +{ + return super_setup_bdi_name(sb, "%.28s-%ld", name, + atomic_long_inc_return(&zfs_bdi_seq)); +} +static inline void +zpl_bdi_destroy(struct super_block *sb) +{ +} +#elif defined(HAVE_2ARGS_BDI_SETUP_AND_REGISTER) +static inline int +zpl_bdi_setup(struct super_block *sb, char *name) +{ + struct backing_dev_info *bdi; + int error; + + bdi = kmem_zalloc(sizeof (struct backing_dev_info), KM_SLEEP); + error = bdi_setup_and_register(bdi, name); + if (error) { + kmem_free(bdi, sizeof (struct backing_dev_info)); + return (error); + } + + sb->s_bdi = bdi; + + return (0); +} +static inline void +zpl_bdi_destroy(struct super_block *sb) +{ + struct backing_dev_info *bdi = sb->s_bdi; + + bdi_destroy(bdi); + kmem_free(bdi, sizeof (struct backing_dev_info)); + sb->s_bdi = NULL; +} +#elif defined(HAVE_3ARGS_BDI_SETUP_AND_REGISTER) +static inline int +zpl_bdi_setup(struct super_block *sb, char *name) +{ + struct backing_dev_info *bdi; + int error; + + bdi = kmem_zalloc(sizeof (struct backing_dev_info), KM_SLEEP); + error = bdi_setup_and_register(bdi, name, BDI_CAP_MAP_COPY); + if (error) { + kmem_free(sb->s_bdi, sizeof (struct backing_dev_info)); + return (error); + } + + sb->s_bdi = bdi; + + return (0); +} +static inline void +zpl_bdi_destroy(struct super_block *sb) +{ + struct backing_dev_info *bdi = sb->s_bdi; + + bdi_destroy(bdi); + kmem_free(bdi, sizeof (struct backing_dev_info)); + sb->s_bdi = NULL; +} +#else +#error "Unsupported kernel" +#endif + +/* + * 4.14 adds SB_* flag definitions, define them to MS_* equivalents + * if not set. + */ +#ifndef SB_RDONLY +#define SB_RDONLY MS_RDONLY +#endif + +#ifndef SB_SILENT +#define SB_SILENT MS_SILENT +#endif + +#ifndef SB_ACTIVE +#define SB_ACTIVE MS_ACTIVE +#endif + +#ifndef SB_POSIXACL +#define SB_POSIXACL MS_POSIXACL +#endif + +#ifndef SB_MANDLOCK +#define SB_MANDLOCK MS_MANDLOCK +#endif + +#ifndef SB_NOATIME +#define SB_NOATIME MS_NOATIME +#endif + +/* + * 3.5 API change, + * The clear_inode() function replaces end_writeback() and introduces an + * ordering change regarding when the inode_sync_wait() occurs. See the + * configure check in config/kernel-clear-inode.m4 for full details. + */ +#if defined(HAVE_EVICT_INODE) && !defined(HAVE_CLEAR_INODE) +#define clear_inode(ip) end_writeback(ip) +#endif /* HAVE_EVICT_INODE && !HAVE_CLEAR_INODE */ + +#if defined(SEEK_HOLE) && defined(SEEK_DATA) && !defined(HAVE_LSEEK_EXECUTE) +static inline loff_t +lseek_execute( + struct file *filp, + struct inode *inode, + loff_t offset, + loff_t maxsize) +{ + if (offset < 0 && !(filp->f_mode & FMODE_UNSIGNED_OFFSET)) + return (-EINVAL); + + if (offset > maxsize) + return (-EINVAL); + + if (offset != filp->f_pos) { + spin_lock(&filp->f_lock); + filp->f_pos = offset; + filp->f_version = 0; + spin_unlock(&filp->f_lock); + } + + return (offset); +} +#endif /* SEEK_HOLE && SEEK_DATA && !HAVE_LSEEK_EXECUTE */ + +#if defined(CONFIG_FS_POSIX_ACL) +/* + * These functions safely approximates the behavior of posix_acl_release() + * which cannot be used because it calls the GPL-only symbol kfree_rcu(). + * The in-kernel version, which can access the RCU, frees the ACLs after + * the grace period expires. Because we're unsure how long that grace + * period may be this implementation conservatively delays for 60 seconds. + * This is several orders of magnitude larger than expected grace period. + * At 60 seconds the kernel will also begin issuing RCU stall warnings. + */ + +#include <linux/posix_acl.h> + +#if defined(HAVE_POSIX_ACL_RELEASE) && !defined(HAVE_POSIX_ACL_RELEASE_GPL_ONLY) +#define zpl_posix_acl_release(arg) posix_acl_release(arg) +#else +void zpl_posix_acl_release_impl(struct posix_acl *); + +static inline void +zpl_posix_acl_release(struct posix_acl *acl) +{ + if ((acl == NULL) || (acl == ACL_NOT_CACHED)) + return; +#ifdef HAVE_ACL_REFCOUNT + if (refcount_dec_and_test(&acl->a_refcount)) + zpl_posix_acl_release_impl(acl); +#else + if (atomic_dec_and_test(&acl->a_refcount)) + zpl_posix_acl_release_impl(acl); +#endif +} +#endif /* HAVE_POSIX_ACL_RELEASE */ + +#ifdef HAVE_SET_CACHED_ACL_USABLE +#define zpl_set_cached_acl(ip, ty, n) set_cached_acl(ip, ty, n) +#define zpl_forget_cached_acl(ip, ty) forget_cached_acl(ip, ty) +#else +static inline void +zpl_set_cached_acl(struct inode *ip, int type, struct posix_acl *newer) +{ + struct posix_acl *older = NULL; + + spin_lock(&ip->i_lock); + + if ((newer != ACL_NOT_CACHED) && (newer != NULL)) + posix_acl_dup(newer); + + switch (type) { + case ACL_TYPE_ACCESS: + older = ip->i_acl; + rcu_assign_pointer(ip->i_acl, newer); + break; + case ACL_TYPE_DEFAULT: + older = ip->i_default_acl; + rcu_assign_pointer(ip->i_default_acl, newer); + break; + } + + spin_unlock(&ip->i_lock); + + zpl_posix_acl_release(older); +} + +static inline void +zpl_forget_cached_acl(struct inode *ip, int type) +{ + zpl_set_cached_acl(ip, type, (struct posix_acl *)ACL_NOT_CACHED); +} +#endif /* HAVE_SET_CACHED_ACL_USABLE */ + +/* + * 3.1 API change, + * posix_acl_chmod() was added as the preferred interface. + * + * 3.14 API change, + * posix_acl_chmod() was changed to __posix_acl_chmod() + */ +#ifndef HAVE___POSIX_ACL_CHMOD +#ifdef HAVE_POSIX_ACL_CHMOD +#define __posix_acl_chmod(acl, gfp, mode) posix_acl_chmod(acl, gfp, mode) +#define __posix_acl_create(acl, gfp, mode) posix_acl_create(acl, gfp, mode) +#else +#error "Unsupported kernel" +#endif /* HAVE_POSIX_ACL_CHMOD */ +#endif /* HAVE___POSIX_ACL_CHMOD */ + +/* + * 4.8 API change, + * posix_acl_valid() now must be passed a namespace, the namespace from + * from super block associated with the given inode is used for this purpose. + */ +#ifdef HAVE_POSIX_ACL_VALID_WITH_NS +#define zpl_posix_acl_valid(ip, acl) posix_acl_valid(ip->i_sb->s_user_ns, acl) +#else +#define zpl_posix_acl_valid(ip, acl) posix_acl_valid(acl) +#endif + +#endif /* CONFIG_FS_POSIX_ACL */ + +/* + * 3.19 API change + * struct access f->f_dentry->d_inode was replaced by accessor function + * file_inode(f) + */ +#ifndef HAVE_FILE_INODE +static inline struct inode *file_inode(const struct file *f) +{ + return (f->f_dentry->d_inode); +} +#endif /* HAVE_FILE_INODE */ + +/* + * 4.1 API change + * struct access file->f_path.dentry was replaced by accessor function + * file_dentry(f) + */ +#ifndef HAVE_FILE_DENTRY +static inline struct dentry *file_dentry(const struct file *f) +{ + return (f->f_path.dentry); +} +#endif /* HAVE_FILE_DENTRY */ + +static inline uid_t zfs_uid_read_impl(struct inode *ip) +{ +#ifdef HAVE_SUPER_USER_NS + return (from_kuid(ip->i_sb->s_user_ns, ip->i_uid)); +#else + return (from_kuid(kcred->user_ns, ip->i_uid)); +#endif +} + +static inline uid_t zfs_uid_read(struct inode *ip) +{ + return (zfs_uid_read_impl(ip)); +} + +static inline gid_t zfs_gid_read_impl(struct inode *ip) +{ +#ifdef HAVE_SUPER_USER_NS + return (from_kgid(ip->i_sb->s_user_ns, ip->i_gid)); +#else + return (from_kgid(kcred->user_ns, ip->i_gid)); +#endif +} + +static inline gid_t zfs_gid_read(struct inode *ip) +{ + return (zfs_gid_read_impl(ip)); +} + +static inline void zfs_uid_write(struct inode *ip, uid_t uid) +{ +#ifdef HAVE_SUPER_USER_NS + ip->i_uid = make_kuid(ip->i_sb->s_user_ns, uid); +#else + ip->i_uid = make_kuid(kcred->user_ns, uid); +#endif +} + +static inline void zfs_gid_write(struct inode *ip, gid_t gid) +{ +#ifdef HAVE_SUPER_USER_NS + ip->i_gid = make_kgid(ip->i_sb->s_user_ns, gid); +#else + ip->i_gid = make_kgid(kcred->user_ns, gid); +#endif +} + +/* + * 4.9 API change + */ +#ifndef HAVE_SETATTR_PREPARE +static inline int +setattr_prepare(struct dentry *dentry, struct iattr *ia) +{ + return (inode_change_ok(dentry->d_inode, ia)); +} +#endif + +/* + * 4.11 API change + * These macros are defined by kernel 4.11. We define them so that the same + * code builds under kernels < 4.11 and >= 4.11. The macros are set to 0 so + * that it will create obvious failures if they are accidentally used when built + * against a kernel >= 4.11. + */ + +#ifndef STATX_BASIC_STATS +#define STATX_BASIC_STATS 0 +#endif + +#ifndef AT_STATX_SYNC_AS_STAT +#define AT_STATX_SYNC_AS_STAT 0 +#endif + +/* + * 4.11 API change + * 4.11 takes struct path *, < 4.11 takes vfsmount * + */ + +#ifdef HAVE_VFSMOUNT_IOPS_GETATTR +#define ZPL_GETATTR_WRAPPER(func) \ +static int \ +func(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) \ +{ \ + struct path path = { .mnt = mnt, .dentry = dentry }; \ + return func##_impl(&path, stat, STATX_BASIC_STATS, \ + AT_STATX_SYNC_AS_STAT); \ +} +#elif defined(HAVE_PATH_IOPS_GETATTR) +#define ZPL_GETATTR_WRAPPER(func) \ +static int \ +func(const struct path *path, struct kstat *stat, u32 request_mask, \ + unsigned int query_flags) \ +{ \ + return (func##_impl(path, stat, request_mask, query_flags)); \ +} +#else +#error +#endif + +/* + * 4.9 API change + * Preferred interface to get the current FS time. + */ +#if !defined(HAVE_CURRENT_TIME) +static inline struct timespec +current_time(struct inode *ip) +{ + return (timespec_trunc(current_kernel_time(), ip->i_sb->s_time_gran)); +} +#endif + +/* + * 4.16 API change + * Added iversion interface for managing inode version field. + */ +#ifdef HAVE_INODE_SET_IVERSION +#include <linux/iversion.h> +#else +static inline void +inode_set_iversion(struct inode *ip, u64 val) +{ + ip->i_version = val; +} +#endif + +/* + * Returns true when called in the context of a 32-bit system call. + */ +static inline int +zpl_is_32bit_api(void) +{ +#ifdef CONFIG_COMPAT +#ifdef HAVE_IN_COMPAT_SYSCALL + return (in_compat_syscall()); +#else + return (is_compat_task()); +#endif +#else + return (BITS_PER_LONG == 32); +#endif +} + +#endif /* _ZFS_VFS_H */ diff --git a/include/os/linux/kernel/linux/xattr_compat.h b/include/os/linux/kernel/linux/xattr_compat.h new file mode 100644 index 000000000000..8348e99198af --- /dev/null +++ b/include/os/linux/kernel/linux/xattr_compat.h @@ -0,0 +1,184 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright (C) 2011 Lawrence Livermore National Security, LLC. + */ + +#ifndef _ZFS_XATTR_H +#define _ZFS_XATTR_H + +#include <linux/posix_acl_xattr.h> + +/* + * 2.6.35 API change, + * The const keyword was added to the 'struct xattr_handler' in the + * generic Linux super_block structure. To handle this we define an + * appropriate xattr_handler_t typedef which can be used. This was + * the preferred solution because it keeps the code clean and readable. + */ +typedef const struct xattr_handler xattr_handler_t; + +/* + * 4.5 API change, + */ +#if defined(HAVE_XATTR_LIST_SIMPLE) +#define ZPL_XATTR_LIST_WRAPPER(fn) \ +static bool \ +fn(struct dentry *dentry) \ +{ \ + return (!!__ ## fn(dentry->d_inode, NULL, 0, NULL, 0)); \ +} +/* + * 4.4 API change, + */ +#elif defined(HAVE_XATTR_LIST_DENTRY) +#define ZPL_XATTR_LIST_WRAPPER(fn) \ +static size_t \ +fn(struct dentry *dentry, char *list, size_t list_size, \ + const char *name, size_t name_len, int type) \ +{ \ + return (__ ## fn(dentry->d_inode, \ + list, list_size, name, name_len)); \ +} +/* + * 2.6.33 API change, + */ +#elif defined(HAVE_XATTR_LIST_HANDLER) +#define ZPL_XATTR_LIST_WRAPPER(fn) \ +static size_t \ +fn(const struct xattr_handler *handler, struct dentry *dentry, \ + char *list, size_t list_size, const char *name, size_t name_len) \ +{ \ + return (__ ## fn(dentry->d_inode, \ + list, list_size, name, name_len)); \ +} +#else +#error "Unsupported kernel" +#endif + +/* + * 4.7 API change, + * The xattr_handler->get() callback was changed to take a both dentry and + * inode, because the dentry might not be attached to an inode yet. + */ +#if defined(HAVE_XATTR_GET_DENTRY_INODE) +#define ZPL_XATTR_GET_WRAPPER(fn) \ +static int \ +fn(const struct xattr_handler *handler, struct dentry *dentry, \ + struct inode *inode, const char *name, void *buffer, size_t size) \ +{ \ + return (__ ## fn(inode, name, buffer, size)); \ +} +/* + * 4.4 API change, + * The xattr_handler->get() callback was changed to take a xattr_handler, + * and handler_flags argument was removed and should be accessed by + * handler->flags. + */ +#elif defined(HAVE_XATTR_GET_HANDLER) +#define ZPL_XATTR_GET_WRAPPER(fn) \ +static int \ +fn(const struct xattr_handler *handler, struct dentry *dentry, \ + const char *name, void *buffer, size_t size) \ +{ \ + return (__ ## fn(dentry->d_inode, name, buffer, size)); \ +} +/* + * 2.6.33 API change, + * The xattr_handler->get() callback was changed to take a dentry + * instead of an inode, and a handler_flags argument was added. + */ +#elif defined(HAVE_XATTR_GET_DENTRY) +#define ZPL_XATTR_GET_WRAPPER(fn) \ +static int \ +fn(struct dentry *dentry, const char *name, void *buffer, size_t size, \ + int unused_handler_flags) \ +{ \ + return (__ ## fn(dentry->d_inode, name, buffer, size)); \ +} +#else +#error "Unsupported kernel" +#endif + +/* + * 4.7 API change, + * The xattr_handler->set() callback was changed to take a both dentry and + * inode, because the dentry might not be attached to an inode yet. + */ +#if defined(HAVE_XATTR_SET_DENTRY_INODE) +#define ZPL_XATTR_SET_WRAPPER(fn) \ +static int \ +fn(const struct xattr_handler *handler, struct dentry *dentry, \ + struct inode *inode, const char *name, const void *buffer, \ + size_t size, int flags) \ +{ \ + return (__ ## fn(inode, name, buffer, size, flags)); \ +} +/* + * 4.4 API change, + * The xattr_handler->set() callback was changed to take a xattr_handler, + * and handler_flags argument was removed and should be accessed by + * handler->flags. + */ +#elif defined(HAVE_XATTR_SET_HANDLER) +#define ZPL_XATTR_SET_WRAPPER(fn) \ +static int \ +fn(const struct xattr_handler *handler, struct dentry *dentry, \ + const char *name, const void *buffer, size_t size, int flags) \ +{ \ + return (__ ## fn(dentry->d_inode, name, buffer, size, flags)); \ +} +/* + * 2.6.33 API change, + * The xattr_handler->set() callback was changed to take a dentry + * instead of an inode, and a handler_flags argument was added. + */ +#elif defined(HAVE_XATTR_SET_DENTRY) +#define ZPL_XATTR_SET_WRAPPER(fn) \ +static int \ +fn(struct dentry *dentry, const char *name, const void *buffer, \ + size_t size, int flags, int unused_handler_flags) \ +{ \ + return (__ ## fn(dentry->d_inode, name, buffer, size, flags)); \ +} +#else +#error "Unsupported kernel" +#endif + +/* + * Linux 3.7 API change. posix_acl_{from,to}_xattr gained the user_ns + * parameter. All callers are expected to pass the &init_user_ns which + * is available through the init credential (kcred). + */ +static inline struct posix_acl * +zpl_acl_from_xattr(const void *value, int size) +{ + return (posix_acl_from_xattr(kcred->user_ns, value, size)); +} + +static inline int +zpl_acl_to_xattr(struct posix_acl *acl, void *value, int size) +{ + return (posix_acl_to_xattr(kcred->user_ns, acl, value, size)); +} + +#endif /* _ZFS_XATTR_H */ diff --git a/include/os/linux/spl/Makefile.am b/include/os/linux/spl/Makefile.am new file mode 100644 index 000000000000..bd781c08f143 --- /dev/null +++ b/include/os/linux/spl/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = rpc sys diff --git a/include/os/linux/spl/rpc/Makefile.am b/include/os/linux/spl/rpc/Makefile.am new file mode 100644 index 000000000000..13d804fce9b6 --- /dev/null +++ b/include/os/linux/spl/rpc/Makefile.am @@ -0,0 +1,7 @@ +KERNEL_H = \ + xdr.h + +if CONFIG_KERNEL +kerneldir = @prefix@/src/zfs-$(VERSION)/include/spl/rpc +kernel_HEADERS = $(KERNEL_H) +endif diff --git a/include/os/linux/spl/rpc/xdr.h b/include/os/linux/spl/rpc/xdr.h new file mode 100644 index 000000000000..0b39b46cf6a2 --- /dev/null +++ b/include/os/linux/spl/rpc/xdr.h @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. + * Written by Ricardo Correia <Ricardo.M.Correia@Sun.COM> + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_RPC_XDR_H +#define _SPL_RPC_XDR_H + +#include <sys/types.h> + +typedef int bool_t; + +/* + * XDR enums and types. + */ +enum xdr_op { + XDR_ENCODE, + XDR_DECODE +}; + +struct xdr_ops; + +typedef struct { + struct xdr_ops *x_ops; /* Let caller know xdrmem_create() succeeds */ + caddr_t x_addr; /* Current buffer addr */ + caddr_t x_addr_end; /* End of the buffer */ + enum xdr_op x_op; /* Stream direction */ +} XDR; + +typedef bool_t (*xdrproc_t)(XDR *xdrs, void *ptr); + +struct xdr_ops { + bool_t (*xdr_control)(XDR *, int, void *); + + bool_t (*xdr_char)(XDR *, char *); + bool_t (*xdr_u_short)(XDR *, unsigned short *); + bool_t (*xdr_u_int)(XDR *, unsigned *); + bool_t (*xdr_u_longlong_t)(XDR *, u_longlong_t *); + + bool_t (*xdr_opaque)(XDR *, caddr_t, const uint_t); + bool_t (*xdr_string)(XDR *, char **, const uint_t); + bool_t (*xdr_array)(XDR *, caddr_t *, uint_t *, const uint_t, + const uint_t, const xdrproc_t); +}; + +/* + * XDR control operator. + */ +#define XDR_GET_BYTES_AVAIL 1 + +struct xdr_bytesrec { + bool_t xc_is_last_record; + size_t xc_num_avail; +}; + +/* + * XDR functions. + */ +void xdrmem_create(XDR *xdrs, const caddr_t addr, const uint_t size, + const enum xdr_op op); + +/* Currently not needed. If needed later, we'll add it to struct xdr_ops */ +#define xdr_destroy(xdrs) ((void) 0) + +#define xdr_control(xdrs, req, info) \ + (xdrs)->x_ops->xdr_control((xdrs), (req), (info)) + +/* + * For precaution, the following are defined as static inlines instead of macros + * to get some amount of type safety. + * + * Also, macros wouldn't work in the case where typecasting is done, because it + * must be possible to reference the functions' addresses by these names. + */ +static inline bool_t xdr_char(XDR *xdrs, char *cp) +{ + return (xdrs->x_ops->xdr_char(xdrs, cp)); +} + +static inline bool_t xdr_u_short(XDR *xdrs, unsigned short *usp) +{ + return (xdrs->x_ops->xdr_u_short(xdrs, usp)); +} + +static inline bool_t xdr_short(XDR *xdrs, short *sp) +{ + BUILD_BUG_ON(sizeof (short) != 2); + return (xdrs->x_ops->xdr_u_short(xdrs, (unsigned short *) sp)); +} + +static inline bool_t xdr_u_int(XDR *xdrs, unsigned *up) +{ + return (xdrs->x_ops->xdr_u_int(xdrs, up)); +} + +static inline bool_t xdr_int(XDR *xdrs, int *ip) +{ + BUILD_BUG_ON(sizeof (int) != 4); + return (xdrs->x_ops->xdr_u_int(xdrs, (unsigned *)ip)); +} + +static inline bool_t xdr_u_longlong_t(XDR *xdrs, u_longlong_t *ullp) +{ + return (xdrs->x_ops->xdr_u_longlong_t(xdrs, ullp)); +} + +static inline bool_t xdr_longlong_t(XDR *xdrs, longlong_t *llp) +{ + BUILD_BUG_ON(sizeof (longlong_t) != 8); + return (xdrs->x_ops->xdr_u_longlong_t(xdrs, (u_longlong_t *)llp)); +} + +/* + * Fixed-length opaque data. + */ +static inline bool_t xdr_opaque(XDR *xdrs, caddr_t cp, const uint_t cnt) +{ + return (xdrs->x_ops->xdr_opaque(xdrs, cp, cnt)); +} + +/* + * Variable-length string. + * The *sp buffer must have (maxsize + 1) bytes. + */ +static inline bool_t xdr_string(XDR *xdrs, char **sp, const uint_t maxsize) +{ + return (xdrs->x_ops->xdr_string(xdrs, sp, maxsize)); +} + +/* + * Variable-length arrays. + */ +static inline bool_t xdr_array(XDR *xdrs, caddr_t *arrp, uint_t *sizep, + const uint_t maxsize, const uint_t elsize, const xdrproc_t elproc) +{ + return xdrs->x_ops->xdr_array(xdrs, arrp, sizep, maxsize, elsize, + elproc); +} + +#endif /* SPL_RPC_XDR_H */ diff --git a/include/os/linux/spl/sys/Makefile.am b/include/os/linux/spl/sys/Makefile.am new file mode 100644 index 000000000000..0fd4cd37a7ec --- /dev/null +++ b/include/os/linux/spl/sys/Makefile.am @@ -0,0 +1,64 @@ +KERNEL_H = \ + acl.h \ + atomic.h \ + byteorder.h \ + callb.h \ + callo.h \ + cmn_err.h \ + condvar.h \ + console.h \ + cred.h \ + ctype.h \ + debug.h \ + disp.h \ + dkio.h \ + errno.h \ + fcntl.h \ + file.h \ + inttypes.h \ + isa_defs.h \ + kmem_cache.h \ + kmem.h \ + kstat.h \ + list.h \ + mod_os.h \ + mutex.h \ + param.h \ + processor.h \ + proc.h \ + procfs_list.h \ + random.h \ + rwlock.h \ + shrinker.h \ + sid.h \ + signal.h \ + simd.h \ + stat.h \ + strings.h \ + sunddi.h \ + sysmacros.h \ + systeminfo.h \ + taskq.h \ + thread.h \ + time.h \ + timer.h \ + trace.h \ + trace_spl.h \ + trace_taskq.h \ + tsd.h \ + types32.h \ + types.h \ + uio.h \ + user.h \ + vfs.h \ + vmem.h \ + vmsystm.h \ + vnode.h \ + wait.h \ + zmod.h \ + zone.h + +if CONFIG_KERNEL +kerneldir = @prefix@/src/zfs-$(VERSION)/include/spl/sys +kernel_HEADERS = $(KERNEL_H) +endif diff --git a/include/os/linux/spl/sys/acl.h b/include/os/linux/spl/sys/acl.h new file mode 100644 index 000000000000..9fc79c025caf --- /dev/null +++ b/include/os/linux/spl/sys/acl.h @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_ACL_H +#define _SPL_ACL_H + +#include <sys/types.h> + +typedef struct ace { + uid_t a_who; + uint32_t a_access_mask; + uint16_t a_flags; + uint16_t a_type; +} ace_t; + +typedef struct ace_object { + uid_t a_who; /* uid or gid */ + uint32_t a_access_mask; /* read,write,... */ + uint16_t a_flags; /* see below */ + uint16_t a_type; /* allow or deny */ + uint8_t a_obj_type[16]; /* obj type */ + uint8_t a_inherit_obj_type[16]; /* inherit obj */ +} ace_object_t; + +#define MAX_ACL_ENTRIES 1024 + +#define ACE_READ_DATA 0x00000001 +#define ACE_LIST_DIRECTORY 0x00000001 +#define ACE_WRITE_DATA 0x00000002 +#define ACE_ADD_FILE 0x00000002 +#define ACE_APPEND_DATA 0x00000004 +#define ACE_ADD_SUBDIRECTORY 0x00000004 +#define ACE_READ_NAMED_ATTRS 0x00000008 +#define ACE_WRITE_NAMED_ATTRS 0x00000010 +#define ACE_EXECUTE 0x00000020 +#define ACE_DELETE_CHILD 0x00000040 +#define ACE_READ_ATTRIBUTES 0x00000080 +#define ACE_WRITE_ATTRIBUTES 0x00000100 +#define ACE_DELETE 0x00010000 +#define ACE_READ_ACL 0x00020000 +#define ACE_WRITE_ACL 0x00040000 +#define ACE_WRITE_OWNER 0x00080000 +#define ACE_SYNCHRONIZE 0x00100000 + +#define ACE_FILE_INHERIT_ACE 0x0001 +#define ACE_DIRECTORY_INHERIT_ACE 0x0002 +#define ACE_NO_PROPAGATE_INHERIT_ACE 0x0004 +#define ACE_INHERIT_ONLY_ACE 0x0008 +#define ACE_SUCCESSFUL_ACCESS_ACE_FLAG 0x0010 +#define ACE_FAILED_ACCESS_ACE_FLAG 0x0020 +#define ACE_IDENTIFIER_GROUP 0x0040 +#define ACE_INHERITED_ACE 0x0080 +#define ACE_OWNER 0x1000 +#define ACE_GROUP 0x2000 +#define ACE_EVERYONE 0x4000 + +#define ACE_ACCESS_ALLOWED_ACE_TYPE 0x0000 +#define ACE_ACCESS_DENIED_ACE_TYPE 0x0001 +#define ACE_SYSTEM_AUDIT_ACE_TYPE 0x0002 +#define ACE_SYSTEM_ALARM_ACE_TYPE 0x0003 + +#define ACL_AUTO_INHERIT 0x0001 +#define ACL_PROTECTED 0x0002 +#define ACL_DEFAULTED 0x0004 +#define ACL_FLAGS_ALL (ACL_AUTO_INHERIT|ACL_PROTECTED|ACL_DEFAULTED) + +#define ACE_ACCESS_ALLOWED_COMPOUND_ACE_TYPE 0x04 +#define ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE 0x05 +#define ACE_ACCESS_DENIED_OBJECT_ACE_TYPE 0x06 +#define ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE 0x07 +#define ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE 0x08 +#define ACE_ACCESS_ALLOWED_CALLBACK_ACE_TYPE 0x09 +#define ACE_ACCESS_DENIED_CALLBACK_ACE_TYPE 0x0A +#define ACE_ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE 0x0B +#define ACE_ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE 0x0C +#define ACE_SYSTEM_AUDIT_CALLBACK_ACE_TYPE 0x0D +#define ACE_SYSTEM_ALARM_CALLBACK_ACE_TYPE 0x0E +#define ACE_SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE 0x0F +#define ACE_SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE 0x10 + +#define ACE_ALL_TYPES 0x001F + +#define ACE_TYPE_FLAGS (ACE_OWNER|ACE_GROUP|ACE_EVERYONE|ACE_IDENTIFIER_GROUP) + +/* BEGIN CSTYLED */ +#define ACE_ALL_PERMS (ACE_READ_DATA|ACE_LIST_DIRECTORY|ACE_WRITE_DATA| \ + ACE_ADD_FILE|ACE_APPEND_DATA|ACE_ADD_SUBDIRECTORY|ACE_READ_NAMED_ATTRS| \ + ACE_WRITE_NAMED_ATTRS|ACE_EXECUTE|ACE_DELETE_CHILD|ACE_READ_ATTRIBUTES| \ + ACE_WRITE_ATTRIBUTES|ACE_DELETE|ACE_READ_ACL|ACE_WRITE_ACL| \ + ACE_WRITE_OWNER|ACE_SYNCHRONIZE) +/* END CSTYLED */ + +#define VSA_ACE 0x0010 +#define VSA_ACECNT 0x0020 +#define VSA_ACE_ALLTYPES 0x0040 +#define VSA_ACE_ACLFLAGS 0x0080 + +#endif /* _SPL_ACL_H */ diff --git a/include/os/linux/spl/sys/atomic.h b/include/os/linux/spl/sys/atomic.h new file mode 100644 index 000000000000..51b5479235ab --- /dev/null +++ b/include/os/linux/spl/sys/atomic.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_ATOMIC_H +#define _SPL_ATOMIC_H + +#include <linux/module.h> +#include <linux/spinlock.h> +#include <sys/types.h> + +/* + * Map the atomic_* functions to the Linux counterparts. This relies on the + * fact that the atomic types are internally really a uint32 or uint64. If + * this were to change an alternate approach would be needed. + * + * N.B. Due to the limitations of the original API atomicity is not strictly + * preserved when using the 64-bit functions on a 32-bit system. In order + * to support this all consumers would need to be updated to use the Linux + * provided atomic_t and atomic64_t types. + */ +#define atomic_inc_32(v) atomic_inc((atomic_t *)(v)) +#define atomic_dec_32(v) atomic_dec((atomic_t *)(v)) +#define atomic_add_32(v, i) atomic_add((i), (atomic_t *)(v)) +#define atomic_sub_32(v, i) atomic_sub((i), (atomic_t *)(v)) +#define atomic_inc_32_nv(v) atomic_inc_return((atomic_t *)(v)) +#define atomic_dec_32_nv(v) atomic_dec_return((atomic_t *)(v)) +#define atomic_add_32_nv(v, i) atomic_add_return((i), (atomic_t *)(v)) +#define atomic_sub_32_nv(v, i) atomic_sub_return((i), (atomic_t *)(v)) +#define atomic_cas_32(v, x, y) atomic_cmpxchg((atomic_t *)(v), x, y) +#define atomic_swap_32(v, x) atomic_xchg((atomic_t *)(v), x) +#define atomic_inc_64(v) atomic64_inc((atomic64_t *)(v)) +#define atomic_dec_64(v) atomic64_dec((atomic64_t *)(v)) +#define atomic_add_64(v, i) atomic64_add((i), (atomic64_t *)(v)) +#define atomic_sub_64(v, i) atomic64_sub((i), (atomic64_t *)(v)) +#define atomic_inc_64_nv(v) atomic64_inc_return((atomic64_t *)(v)) +#define atomic_dec_64_nv(v) atomic64_dec_return((atomic64_t *)(v)) +#define atomic_add_64_nv(v, i) atomic64_add_return((i), (atomic64_t *)(v)) +#define atomic_sub_64_nv(v, i) atomic64_sub_return((i), (atomic64_t *)(v)) +#define atomic_cas_64(v, x, y) atomic64_cmpxchg((atomic64_t *)(v), x, y) +#define atomic_swap_64(v, x) atomic64_xchg((atomic64_t *)(v), x) + +#ifdef _LP64 +static __inline__ void * +atomic_cas_ptr(volatile void *target, void *cmp, void *newval) +{ + return ((void *)atomic_cas_64((volatile uint64_t *)target, + (uint64_t)cmp, (uint64_t)newval)); +} +#else /* _LP64 */ +static __inline__ void * +atomic_cas_ptr(volatile void *target, void *cmp, void *newval) +{ + return ((void *)atomic_cas_32((volatile uint32_t *)target, + (uint32_t)cmp, (uint32_t)newval)); +} +#endif /* _LP64 */ + +#endif /* _SPL_ATOMIC_H */ diff --git a/include/os/linux/spl/sys/byteorder.h b/include/os/linux/spl/sys/byteorder.h new file mode 100644 index 000000000000..70847edbc8a9 --- /dev/null +++ b/include/os/linux/spl/sys/byteorder.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_BYTEORDER_H +#define _SPL_BYTEORDER_H + +#include <asm/byteorder.h> + +#if defined(__BIG_ENDIAN) && !defined(_ZFS_BIG_ENDIAN) +#define _ZFS_BIG_ENDIAN +#endif + +#if defined(__LITTLE_ENDIAN) && !defined(_ZFS_LITTLE_ENDIAN) +#define _ZFS_LITTLE_ENDIAN +#endif + +#include <sys/isa_defs.h> + +#define BSWAP_8(x) ((x) & 0xff) +#define BSWAP_16(x) ((BSWAP_8(x) << 8) | BSWAP_8((x) >> 8)) +#define BSWAP_32(x) ((BSWAP_16(x) << 16) | BSWAP_16((x) >> 16)) +#define BSWAP_64(x) ((BSWAP_32(x) << 32) | BSWAP_32((x) >> 32)) + +#define LE_16(x) cpu_to_le16(x) +#define LE_32(x) cpu_to_le32(x) +#define LE_64(x) cpu_to_le64(x) +#define BE_16(x) cpu_to_be16(x) +#define BE_32(x) cpu_to_be32(x) +#define BE_64(x) cpu_to_be64(x) + +#define BE_IN8(xa) \ + *((uint8_t *)(xa)) + +#define BE_IN16(xa) \ + (((uint16_t)BE_IN8(xa) << 8) | BE_IN8((uint8_t *)(xa)+1)) + +#define BE_IN32(xa) \ + (((uint32_t)BE_IN16(xa) << 16) | BE_IN16((uint8_t *)(xa)+2)) + +#ifdef _ZFS_BIG_ENDIAN +static __inline__ uint64_t +htonll(uint64_t n) +{ + return (n); +} + +static __inline__ uint64_t +ntohll(uint64_t n) +{ + return (n); +} +#else +static __inline__ uint64_t +htonll(uint64_t n) +{ + return ((((uint64_t)htonl(n)) << 32) + htonl(n >> 32)); +} + +static __inline__ uint64_t +ntohll(uint64_t n) +{ + return ((((uint64_t)ntohl(n)) << 32) + ntohl(n >> 32)); +} +#endif + +#endif /* SPL_BYTEORDER_H */ diff --git a/include/os/linux/spl/sys/callb.h b/include/os/linux/spl/sys/callb.h new file mode 100644 index 000000000000..f1826bfd353a --- /dev/null +++ b/include/os/linux/spl/sys/callb.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_CALLB_H +#define _SPL_CALLB_H + +#include <linux/module.h> +#include <sys/mutex.h> + +#define CALLB_CPR_ASSERT(cp) ASSERT(MUTEX_HELD((cp)->cc_lockp)); + +typedef struct callb_cpr { + kmutex_t *cc_lockp; +} callb_cpr_t; + +#define CALLB_CPR_INIT(cp, lockp, func, name) { \ + (cp)->cc_lockp = lockp; \ +} + +#define CALLB_CPR_SAFE_BEGIN(cp) { \ + CALLB_CPR_ASSERT(cp); \ +} + +#define CALLB_CPR_SAFE_END(cp, lockp) { \ + CALLB_CPR_ASSERT(cp); \ +} + +#define CALLB_CPR_EXIT(cp) { \ + ASSERT(MUTEX_HELD((cp)->cc_lockp)); \ + mutex_exit((cp)->cc_lockp); \ +} + +#endif /* _SPL_CALLB_H */ diff --git a/include/os/linux/spl/sys/callo.h b/include/os/linux/spl/sys/callo.h new file mode 100644 index 000000000000..c43ac92e7c32 --- /dev/null +++ b/include/os/linux/spl/sys/callo.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2007-2013 Lawrence Livermore National Security, LLC. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_CALLO_H +#define _SPL_CALLO_H + +/* + * Callout flags: + * + * CALLOUT_FLAG_ROUNDUP + * Roundup the expiration time to the next resolution boundary. + * If this flag is not specified, the expiration time is rounded down. + * CALLOUT_FLAG_ABSOLUTE + * Normally, the expiration passed to the timeout API functions is an + * expiration interval. If this flag is specified, then it is + * interpreted as the expiration time itself. + * CALLOUT_FLAG_HRESTIME + * Normally, callouts are not affected by changes to system time + * (hrestime). This flag is used to create a callout that is affected + * by system time. If system time changes, these timers must be + * handled in a special way (see callout.c). These are used by condition + * variables and LWP timers that need this behavior. + * CALLOUT_FLAG_32BIT + * Legacy interfaces timeout() and realtime_timeout() pass this flag + * to timeout_generic() to indicate that a 32-bit ID should be allocated. + */ +#define CALLOUT_FLAG_ROUNDUP 0x1 +#define CALLOUT_FLAG_ABSOLUTE 0x2 +#define CALLOUT_FLAG_HRESTIME 0x4 +#define CALLOUT_FLAG_32BIT 0x8 + +#endif /* _SPL_CALLB_H */ diff --git a/include/os/linux/spl/sys/cmn_err.h b/include/os/linux/spl/sys/cmn_err.h new file mode 100644 index 000000000000..be57358b0a8a --- /dev/null +++ b/include/os/linux/spl/sys/cmn_err.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_CMN_ERR_H +#define _SPL_CMN_ERR_H + +#include <stdarg.h> + +#define CE_CONT 0 /* continuation */ +#define CE_NOTE 1 /* notice */ +#define CE_WARN 2 /* warning */ +#define CE_PANIC 3 /* panic */ +#define CE_IGNORE 4 /* print nothing */ + +extern void cmn_err(int, const char *, ...); +extern void vcmn_err(int, const char *, va_list); +extern void vpanic(const char *, va_list); + +#define fm_panic panic + +#endif /* SPL_CMN_ERR_H */ diff --git a/include/os/linux/spl/sys/condvar.h b/include/os/linux/spl/sys/condvar.h new file mode 100644 index 000000000000..22408824f85b --- /dev/null +++ b/include/os/linux/spl/sys/condvar.h @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_CONDVAR_H +#define _SPL_CONDVAR_H + +#include <linux/module.h> +#include <sys/kmem.h> +#include <sys/mutex.h> +#include <sys/callo.h> +#include <sys/wait.h> +#include <sys/time.h> + +/* + * cv_timedwait() is similar to cv_wait() except that it additionally expects + * a timeout value specified in ticks. When woken by cv_signal() or + * cv_broadcast() it returns 1, otherwise when the timeout is reached -1 is + * returned. + * + * cv_timedwait_sig() behaves the same as cv_timedwait() but blocks + * interruptibly and can be woken by a signal (EINTR, ERESTART). When + * this occurs 0 is returned. + * + * cv_timedwait_io() and cv_timedwait_sig_io() are variants of cv_timedwait() + * and cv_timedwait_sig() which should be used when waiting for outstanding + * IO to complete. They are responsible for updating the iowait accounting + * when this is supported by the platform. + * + * cv_timedwait_hires() and cv_timedwait_sig_hires() are high resolution + * versions of cv_timedwait() and cv_timedwait_sig(). They expect the timeout + * to be specified as a hrtime_t allowing for timeouts of less than a tick. + * + * N.B. The return values differ slightly from the illumos implementation + * which returns the time remaining, instead of 1, when woken. They both + * return -1 on timeout. Consumers which need to know the time remaining + * are responsible for tracking it themselves. + */ + + +/* + * The kcondvar_t struct is protected by mutex taken externally before + * calling any of the wait/signal funs, and passed into the wait funs. + */ +#define CV_MAGIC 0x346545f4 +#define CV_DESTROY 0x346545f5 + +typedef struct { + int cv_magic; + spl_wait_queue_head_t cv_event; + spl_wait_queue_head_t cv_destroy; + atomic_t cv_refs; + atomic_t cv_waiters; + kmutex_t *cv_mutex; +} kcondvar_t; + +typedef enum { CV_DEFAULT = 0, CV_DRIVER } kcv_type_t; + +extern void __cv_init(kcondvar_t *, char *, kcv_type_t, void *); +extern void __cv_destroy(kcondvar_t *); +extern void __cv_wait(kcondvar_t *, kmutex_t *); +extern void __cv_wait_io(kcondvar_t *, kmutex_t *); +extern int __cv_wait_io_sig(kcondvar_t *, kmutex_t *); +extern int __cv_wait_sig(kcondvar_t *, kmutex_t *); +extern int __cv_timedwait(kcondvar_t *, kmutex_t *, clock_t); +extern int __cv_timedwait_io(kcondvar_t *, kmutex_t *, clock_t); +extern int __cv_timedwait_sig(kcondvar_t *, kmutex_t *, clock_t); +extern int cv_timedwait_hires(kcondvar_t *, kmutex_t *, hrtime_t, + hrtime_t res, int flag); +extern int cv_timedwait_sig_hires(kcondvar_t *, kmutex_t *, hrtime_t, + hrtime_t res, int flag); +extern void __cv_signal(kcondvar_t *); +extern void __cv_broadcast(kcondvar_t *c); + +#define cv_init(cvp, name, type, arg) __cv_init(cvp, name, type, arg) +#define cv_destroy(cvp) __cv_destroy(cvp) +#define cv_wait(cvp, mp) __cv_wait(cvp, mp) +#define cv_wait_io(cvp, mp) __cv_wait_io(cvp, mp) +#define cv_wait_io_sig(cvp, mp) __cv_wait_io_sig(cvp, mp) +#define cv_wait_sig(cvp, mp) __cv_wait_sig(cvp, mp) +#define cv_signal(cvp) __cv_signal(cvp) +#define cv_broadcast(cvp) __cv_broadcast(cvp) + +/* + * NB: There is no way to reliably distinguish between having been signalled + * and having timed out on Linux. If the client code needs to reliably + * distinguish between the two it should use the hires variant. + */ +#define cv_timedwait(cvp, mp, t) __cv_timedwait(cvp, mp, t) +#define cv_timedwait_io(cvp, mp, t) __cv_timedwait_io(cvp, mp, t) +#define cv_timedwait_sig(cvp, mp, t) __cv_timedwait_sig(cvp, mp, t) + +#endif /* _SPL_CONDVAR_H */ diff --git a/include/os/linux/spl/sys/console.h b/include/os/linux/spl/sys/console.h new file mode 100644 index 000000000000..33c8b3c6b4d7 --- /dev/null +++ b/include/os/linux/spl/sys/console.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_CONSOLE_H +#define _SPL_CONSOLE_H + +#define console_vprintf vprintk +#define console_printf printk + +#endif /* _SPL_CONSOLE_H */ diff --git a/include/os/linux/spl/sys/cred.h b/include/os/linux/spl/sys/cred.h new file mode 100644 index 000000000000..0b07c4369940 --- /dev/null +++ b/include/os/linux/spl/sys/cred.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_CRED_H +#define _SPL_CRED_H + +#include <linux/module.h> +#include <linux/cred.h> +#include <sys/types.h> +#include <sys/vfs.h> + +typedef struct cred cred_t; + +#define kcred ((cred_t *)(init_task.cred)) +#define CRED() ((cred_t *)current_cred()) + +/* Linux 4.9 API change, GROUP_AT was removed */ +#ifndef GROUP_AT +#define GROUP_AT(gi, i) ((gi)->gid[i]) +#endif + +#define KUID_TO_SUID(x) (__kuid_val(x)) +#define KGID_TO_SGID(x) (__kgid_val(x)) +#define SUID_TO_KUID(x) (KUIDT_INIT(x)) +#define SGID_TO_KGID(x) (KGIDT_INIT(x)) +#define KGIDP_TO_SGIDP(x) (&(x)->val) + +extern void crhold(cred_t *cr); +extern void crfree(cred_t *cr); +extern uid_t crgetuid(const cred_t *cr); +extern uid_t crgetruid(const cred_t *cr); +extern uid_t crgetsuid(const cred_t *cr); +extern uid_t crgetfsuid(const cred_t *cr); +extern gid_t crgetgid(const cred_t *cr); +extern gid_t crgetrgid(const cred_t *cr); +extern gid_t crgetsgid(const cred_t *cr); +extern gid_t crgetfsgid(const cred_t *cr); +extern int crgetngroups(const cred_t *cr); +extern gid_t *crgetgroups(const cred_t *cr); +extern int groupmember(gid_t gid, const cred_t *cr); + +#endif /* _SPL_CRED_H */ diff --git a/include/os/linux/spl/sys/ctype.h b/include/os/linux/spl/sys/ctype.h new file mode 100644 index 000000000000..18beb1daa5d9 --- /dev/null +++ b/include/os/linux/spl/sys/ctype.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_CTYPE_H +#define _SPL_CTYPE_H + +#include <linux/ctype.h> + +#endif /* SPL_CTYPE_H */ diff --git a/include/os/linux/spl/sys/debug.h b/include/os/linux/spl/sys/debug.h new file mode 100644 index 000000000000..e2dbd6804056 --- /dev/null +++ b/include/os/linux/spl/sys/debug.h @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +/* + * Available Solaris debug functions. All of the ASSERT() macros will be + * compiled out when NDEBUG is defined, this is the default behavior for + * the SPL. To enable assertions use the --enable-debug with configure. + * The VERIFY() functions are never compiled out and cannot be disabled. + * + * PANIC() - Panic the node and print message. + * ASSERT() - Assert X is true, if not panic. + * ASSERT3B() - Assert boolean X OP Y is true, if not panic. + * ASSERT3S() - Assert signed X OP Y is true, if not panic. + * ASSERT3U() - Assert unsigned X OP Y is true, if not panic. + * ASSERT3P() - Assert pointer X OP Y is true, if not panic. + * ASSERT0() - Assert value is zero, if not panic. + * VERIFY() - Verify X is true, if not panic. + * VERIFY3B() - Verify boolean X OP Y is true, if not panic. + * VERIFY3S() - Verify signed X OP Y is true, if not panic. + * VERIFY3U() - Verify unsigned X OP Y is true, if not panic. + * VERIFY3P() - Verify pointer X OP Y is true, if not panic. + * VERIFY0() - Verify value is zero, if not panic. + */ + +#ifndef _SPL_DEBUG_H +#define _SPL_DEBUG_H + +/* + * Common DEBUG functionality. + */ +#define __printflike(a, b) __printf(a, b) + +#ifndef __maybe_unused +#define __maybe_unused __attribute__((unused)) +#endif + +int spl_panic(const char *file, const char *func, int line, + const char *fmt, ...); +void spl_dumpstack(void); + +/* BEGIN CSTYLED */ +#define PANIC(fmt, a...) \ + spl_panic(__FILE__, __FUNCTION__, __LINE__, fmt, ## a) + +#define VERIFY(cond) \ + (void) (unlikely(!(cond)) && \ + spl_panic(__FILE__, __FUNCTION__, __LINE__, \ + "%s", "VERIFY(" #cond ") failed\n")) + +#define VERIFY3B(LEFT, OP, RIGHT) do { \ + boolean_t _verify3_left = (boolean_t)(LEFT); \ + boolean_t _verify3_right = (boolean_t)(RIGHT); \ + if (!(_verify3_left OP _verify3_right)) \ + spl_panic(__FILE__, __FUNCTION__, __LINE__, \ + "VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \ + "failed (%d " #OP " %d)\n", \ + (boolean_t) (_verify3_left), \ + (boolean_t) (_verify3_right)); \ + } while (0) + +#define VERIFY3S(LEFT, OP, RIGHT) do { \ + int64_t _verify3_left = (int64_t)(LEFT); \ + int64_t _verify3_right = (int64_t)(RIGHT); \ + if (!(_verify3_left OP _verify3_right)) \ + spl_panic(__FILE__, __FUNCTION__, __LINE__, \ + "VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \ + "failed (%lld " #OP " %lld)\n", \ + (long long) (_verify3_left), \ + (long long) (_verify3_right)); \ + } while (0) + +#define VERIFY3U(LEFT, OP, RIGHT) do { \ + uint64_t _verify3_left = (uint64_t)(LEFT); \ + uint64_t _verify3_right = (uint64_t)(RIGHT); \ + if (!(_verify3_left OP _verify3_right)) \ + spl_panic(__FILE__, __FUNCTION__, __LINE__, \ + "VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \ + "failed (%llu " #OP " %llu)\n", \ + (unsigned long long) (_verify3_left), \ + (unsigned long long) (_verify3_right)); \ + } while (0) + +#define VERIFY3P(LEFT, OP, RIGHT) do { \ + uintptr_t _verify3_left = (uintptr_t)(LEFT); \ + uintptr_t _verify3_right = (uintptr_t)(RIGHT); \ + if (!(_verify3_left OP _verify3_right)) \ + spl_panic(__FILE__, __FUNCTION__, __LINE__, \ + "VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \ + "failed (%px " #OP " %px)\n", \ + (void *) (_verify3_left), \ + (void *) (_verify3_right)); \ + } while (0) + +#define VERIFY0(RIGHT) do { \ + int64_t _verify3_left = (int64_t)(0); \ + int64_t _verify3_right = (int64_t)(RIGHT); \ + if (!(_verify3_left == _verify3_right)) \ + spl_panic(__FILE__, __FUNCTION__, __LINE__, \ + "VERIFY3(0 == " #RIGHT ") " \ + "failed (0 == %lld)\n", \ + (long long) (_verify3_right)); \ + } while (0) + +#define CTASSERT_GLOBAL(x) _CTASSERT(x, __LINE__) +#define CTASSERT(x) { _CTASSERT(x, __LINE__); } +#define _CTASSERT(x, y) __CTASSERT(x, y) +#define __CTASSERT(x, y) \ + typedef char __attribute__ ((unused)) \ + __compile_time_assertion__ ## y[(x) ? 1 : -1] + +/* + * Debugging disabled (--disable-debug) + */ +#ifdef NDEBUG + +#define ASSERT(x) ((void)0) +#define ASSERT3B(x,y,z) ((void)0) +#define ASSERT3S(x,y,z) ((void)0) +#define ASSERT3U(x,y,z) ((void)0) +#define ASSERT3P(x,y,z) ((void)0) +#define ASSERT0(x) ((void)0) +#define IMPLY(A, B) ((void)0) +#define EQUIV(A, B) ((void)0) + +/* + * Debugging enabled (--enable-debug) + */ +#else + +#define ASSERT3B VERIFY3B +#define ASSERT3S VERIFY3S +#define ASSERT3U VERIFY3U +#define ASSERT3P VERIFY3P +#define ASSERT0 VERIFY0 +#define ASSERT VERIFY +#define IMPLY(A, B) \ + ((void)(((!(A)) || (B)) || \ + spl_panic(__FILE__, __FUNCTION__, __LINE__, \ + "(" #A ") implies (" #B ")"))) +#define EQUIV(A, B) \ + ((void)((!!(A) == !!(B)) || \ + spl_panic(__FILE__, __FUNCTION__, __LINE__, \ + "(" #A ") is equivalent to (" #B ")"))) +/* END CSTYLED */ + +#endif /* NDEBUG */ + +#endif /* SPL_DEBUG_H */ diff --git a/include/os/linux/spl/sys/disp.h b/include/os/linux/spl/sys/disp.h new file mode 100644 index 000000000000..413b623c8145 --- /dev/null +++ b/include/os/linux/spl/sys/disp.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_DISP_H +#define _SPL_DISP_H + +#include <linux/preempt.h> + +#define kpreempt(unused) schedule() +#define kpreempt_disable() preempt_disable() +#define kpreempt_enable() preempt_enable() + +#endif /* SPL_DISP_H */ diff --git a/include/os/linux/spl/sys/dkio.h b/include/os/linux/spl/sys/dkio.h new file mode 100644 index 000000000000..49f166a9c4aa --- /dev/null +++ b/include/os/linux/spl/sys/dkio.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_DKIO_H +#define _SPL_DKIO_H + +#define DFL_SZ(num_exts) \ + (sizeof (dkioc_free_list_t) + (num_exts - 1) * 16) + +#define DKIOC (0x04 << 8) +#define DKIOCFLUSHWRITECACHE (DKIOC|34) /* flush cache to phys medium */ + +/* + * ioctl to free space (e.g. SCSI UNMAP) off a disk. + * Pass a dkioc_free_list_t containing a list of extents to be freed. + */ +#define DKIOCFREE (DKIOC|50) + +#endif /* _SPL_DKIO_H */ diff --git a/include/os/linux/spl/sys/errno.h b/include/os/linux/spl/sys/errno.h new file mode 100644 index 000000000000..f6d9212a613f --- /dev/null +++ b/include/os/linux/spl/sys/errno.h @@ -0,0 +1,57 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2000 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ +/* All Rights Reserved */ + +/* + * University Copyright- Copyright (c) 1982, 1986, 1988 + * The Regents of the University of California + * All Rights Reserved + * + * University Acknowledgment- Portions of this document are derived from + * software developed by the University of California, Berkeley, and its + * contributors. + */ + +#ifndef _SYS_ERRNO_H +#define _SYS_ERRNO_H + +#include <linux/errno.h> + +#define ENOTSUP EOPNOTSUPP + +/* + * We'll take the unused errnos, 'EBADE' and 'EBADR' (from the Convergent + * graveyard) to indicate checksum errors and fragmentation. + */ +#define ECKSUM EBADE +#define EFRAGS EBADR + +/* Similar for ENOACTIVE */ +#define ENOTACTIVE ENOANO + +#endif /* _SYS_ERRNO_H */ diff --git a/include/os/linux/spl/sys/fcntl.h b/include/os/linux/spl/sys/fcntl.h new file mode 100644 index 000000000000..3faa5dad78cb --- /dev/null +++ b/include/os/linux/spl/sys/fcntl.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2010 Lawrence Livermore National Security, LLC. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_FCNTL_H +#define _SPL_FCNTL_H + +#include <asm/fcntl.h> + +#define F_FREESP 11 + +#ifdef CONFIG_64BIT +typedef struct flock flock64_t; +#else +typedef struct flock64 flock64_t; +#endif /* CONFIG_64BIT */ + +#endif /* _SPL_FCNTL_H */ diff --git a/include/os/linux/spl/sys/file.h b/include/os/linux/spl/sys/file.h new file mode 100644 index 000000000000..05dbc0814296 --- /dev/null +++ b/include/os/linux/spl/sys/file.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_FILE_H +#define _SPL_FILE_H + +#define FIGNORECASE 0x00080000 +#define FKIOCTL 0x80000000 +#define ED_CASE_CONFLICT 0x10 + +#ifdef HAVE_INODE_LOCK_SHARED +#define spl_inode_lock(ip) inode_lock(ip) +#define spl_inode_unlock(ip) inode_unlock(ip) +#define spl_inode_lock_shared(ip) inode_lock_shared(ip) +#define spl_inode_unlock_shared(ip) inode_unlock_shared(ip) +#define spl_inode_trylock(ip) inode_trylock(ip) +#define spl_inode_trylock_shared(ip) inode_trylock_shared(ip) +#define spl_inode_is_locked(ip) inode_is_locked(ip) +#define spl_inode_lock_nested(ip, s) inode_lock_nested(ip, s) +#else +#define spl_inode_lock(ip) mutex_lock(&(ip)->i_mutex) +#define spl_inode_unlock(ip) mutex_unlock(&(ip)->i_mutex) +#define spl_inode_lock_shared(ip) mutex_lock(&(ip)->i_mutex) +#define spl_inode_unlock_shared(ip) mutex_unlock(&(ip)->i_mutex) +#define spl_inode_trylock(ip) mutex_trylock(&(ip)->i_mutex) +#define spl_inode_trylock_shared(ip) mutex_trylock(&(ip)->i_mutex) +#define spl_inode_is_locked(ip) mutex_is_locked(&(ip)->i_mutex) +#define spl_inode_lock_nested(ip, s) mutex_lock_nested(&(ip)->i_mutex, s) +#endif + +#endif /* SPL_FILE_H */ diff --git a/include/os/linux/spl/sys/inttypes.h b/include/os/linux/spl/sys/inttypes.h new file mode 100644 index 000000000000..92e76206ba52 --- /dev/null +++ b/include/os/linux/spl/sys/inttypes.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_INTTYPES_H +#define _SPL_INTTYPES_H + +#endif /* SPL_INTTYPES_H */ diff --git a/include/os/linux/spl/sys/isa_defs.h b/include/os/linux/spl/sys/isa_defs.h new file mode 100644 index 000000000000..af064e567e13 --- /dev/null +++ b/include/os/linux/spl/sys/isa_defs.h @@ -0,0 +1,254 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_ISA_DEFS_H +#define _SPL_ISA_DEFS_H + +/* x86_64 arch specific defines */ +#if defined(__x86_64) || defined(__x86_64__) + +#if !defined(__x86_64) +#define __x86_64 +#endif + +#if !defined(__amd64) +#define __amd64 +#endif + +#if !defined(__x86) +#define __x86 +#endif + +#if defined(_ILP32) +/* x32-specific defines; careful to *not* define _LP64 here */ +#else +#if !defined(_LP64) +#define _LP64 +#endif +#endif + +#define _ALIGNMENT_REQUIRED 1 + + +/* i386 arch specific defines */ +#elif defined(__i386) || defined(__i386__) + +#if !defined(__i386) +#define __i386 +#endif + +#if !defined(__x86) +#define __x86 +#endif + +#if !defined(_ILP32) +#define _ILP32 +#endif + +#define _ALIGNMENT_REQUIRED 0 + +/* powerpc (ppc64) arch specific defines */ +#elif defined(__powerpc) || defined(__powerpc__) || defined(__powerpc64__) + +#if !defined(__powerpc) +#define __powerpc +#endif + +#if !defined(__powerpc__) +#define __powerpc__ +#endif + +#if defined(__powerpc64__) +#if !defined(_LP64) +#define _LP64 +#endif +#else +#if !defined(_ILP32) +#define _ILP32 +#endif +#endif + +/* + * Illumos doesn't define _ALIGNMENT_REQUIRED for PPC, so default to 1 + * out of paranoia. + */ +#define _ALIGNMENT_REQUIRED 1 + +/* arm arch specific defines */ +#elif defined(__arm) || defined(__arm__) || defined(__aarch64__) + +#if !defined(__arm) +#define __arm +#endif + +#if !defined(__arm__) +#define __arm__ +#endif + +#if defined(__aarch64__) +#if !defined(_LP64) +#define _LP64 +#endif +#else +#if !defined(_ILP32) +#define _ILP32 +#endif +#endif + +#if defined(__ARMEL__) || defined(__AARCH64EL__) +#define _ZFS_LITTLE_ENDIAN +#else +#define _ZFS_BIG_ENDIAN +#endif + +/* + * Illumos doesn't define _ALIGNMENT_REQUIRED for ARM, so default to 1 + * out of paranoia. + */ +#define _ALIGNMENT_REQUIRED 1 + +/* sparc arch specific defines */ +#elif defined(__sparc) || defined(__sparc__) + +#if !defined(__sparc) +#define __sparc +#endif + +#if !defined(__sparc__) +#define __sparc__ +#endif + +#if defined(__arch64__) +#if !defined(_LP64) +#define _LP64 +#endif +#else +#if !defined(_ILP32) +#define _ILP32 +#endif +#endif + +#define _ZFS_BIG_ENDIAN +#define _SUNOS_VTOC_16 +#define _ALIGNMENT_REQUIRED 1 + +/* s390 arch specific defines */ +#elif defined(__s390__) +#if defined(__s390x__) +#if !defined(_LP64) +#define _LP64 +#endif +#else +#if !defined(_ILP32) +#define _ILP32 +#endif +#endif + +#define _ZFS_BIG_ENDIAN + +/* + * Illumos doesn't define _ALIGNMENT_REQUIRED for s390, so default to 1 + * out of paranoia. + */ +#define _ALIGNMENT_REQUIRED 1 + +/* MIPS arch specific defines */ +#elif defined(__mips__) + +#if defined(__MIPSEB__) +#define _ZFS_BIG_ENDIAN +#elif defined(__MIPSEL__) +#define _ZFS_LITTLE_ENDIAN +#else +#error MIPS no endian specified +#endif + +#ifndef _LP64 +#define _ILP32 +#endif + +#define _SUNOS_VTOC_16 + +/* + * Illumos doesn't define _ALIGNMENT_REQUIRED for MIPS, so default to 1 + * out of paranoia. + */ +#define _ALIGNMENT_REQUIRED 1 + +/* + * RISC-V arch specific defines + * only RV64G (including atomic) LP64 is supported yet + */ +#elif defined(__riscv) && defined(_LP64) && _LP64 && \ + defined(__riscv_atomic) && __riscv_atomic + +#ifndef __riscv__ +#define __riscv__ +#endif + +#ifndef __rv64g__ +#define __rv64g__ +#endif + +#define _ZFS_LITTLE_ENDIAN + +#define _SUNOS_VTOC_16 + +#define _ALIGNMENT_REQUIRED 1 + +#else +/* + * Currently supported: + * x86_64, x32, i386, arm, powerpc, s390, sparc, mips, and RV64G + */ +#error "Unsupported ISA type" +#endif + +#if defined(_ILP32) && defined(_LP64) +#error "Both _ILP32 and _LP64 are defined" +#endif + +#if !defined(_ILP32) && !defined(_LP64) +#error "Neither _ILP32 or _LP64 are defined" +#endif + +#include <sys/byteorder.h> + +/* + * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS will be defined by the Linux + * kernel for architectures which support efficient unaligned access. + */ +#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) +#define HAVE_EFFICIENT_UNALIGNED_ACCESS +#endif + +#if defined(_ZFS_LITTLE_ENDIAN) && defined(_ZFS_BIG_ENDIAN) +#error "Both _ZFS_LITTLE_ENDIAN and _ZFS_BIG_ENDIAN are defined" +#endif + +#if !defined(_ZFS_LITTLE_ENDIAN) && !defined(_ZFS_BIG_ENDIAN) +#error "Neither _ZFS_LITTLE_ENDIAN or _ZFS_BIG_ENDIAN are defined" +#endif + +#endif /* _SPL_ISA_DEFS_H */ diff --git a/include/os/linux/spl/sys/kmem.h b/include/os/linux/spl/sys/kmem.h new file mode 100644 index 000000000000..c09c40fa34b9 --- /dev/null +++ b/include/os/linux/spl/sys/kmem.h @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_KMEM_H +#define _SPL_KMEM_H + +#include <sys/debug.h> +#include <linux/slab.h> +#include <linux/sched.h> +#include <linux/mm.h> +#include <linux/vmalloc.h> + +extern int kmem_debugging(void); +extern char *kmem_vasprintf(const char *fmt, va_list ap); +extern char *kmem_asprintf(const char *fmt, ...); +extern char *kmem_strdup(const char *str); +extern void kmem_strfree(char *str); + +/* + * Memory allocation interfaces + */ +#define KM_SLEEP 0x0000 /* can block for memory; success guaranteed */ +#define KM_NOSLEEP 0x0001 /* cannot block for memory; may fail */ +#define KM_PUSHPAGE 0x0004 /* can block for memory; may use reserve */ +#define KM_ZERO 0x1000 /* zero the allocation */ +#define KM_VMEM 0x2000 /* caller is vmem_* wrapper */ + +#define KM_PUBLIC_MASK (KM_SLEEP | KM_NOSLEEP | KM_PUSHPAGE) + +static int spl_fstrans_check(void); +void *spl_kvmalloc(size_t size, gfp_t flags); + +/* + * Convert a KM_* flags mask to its Linux GFP_* counterpart. The conversion + * function is context aware which means that KM_SLEEP allocations can be + * safely used in syncing contexts which have set PF_FSTRANS. + */ +static inline gfp_t +kmem_flags_convert(int flags) +{ + gfp_t lflags = __GFP_NOWARN | __GFP_COMP; + + if (flags & KM_NOSLEEP) { + lflags |= GFP_ATOMIC | __GFP_NORETRY; + } else { + lflags |= GFP_KERNEL; + if (spl_fstrans_check()) + lflags &= ~(__GFP_IO|__GFP_FS); + } + + if (flags & KM_PUSHPAGE) + lflags |= __GFP_HIGH; + + if (flags & KM_ZERO) + lflags |= __GFP_ZERO; + + return (lflags); +} + +typedef struct { + struct task_struct *fstrans_thread; + unsigned int saved_flags; +} fstrans_cookie_t; + +/* + * Introduced in Linux 3.9, however this cannot be solely relied on before + * Linux 3.18 as it doesn't turn off __GFP_FS as it should. + */ +#ifdef PF_MEMALLOC_NOIO +#define __SPL_PF_MEMALLOC_NOIO (PF_MEMALLOC_NOIO) +#else +#define __SPL_PF_MEMALLOC_NOIO (0) +#endif + +/* + * PF_FSTRANS is removed from Linux 4.12 + */ +#ifdef PF_FSTRANS +#define __SPL_PF_FSTRANS (PF_FSTRANS) +#else +#define __SPL_PF_FSTRANS (0) +#endif + +#define SPL_FSTRANS (__SPL_PF_FSTRANS|__SPL_PF_MEMALLOC_NOIO) + +static inline fstrans_cookie_t +spl_fstrans_mark(void) +{ + fstrans_cookie_t cookie; + + BUILD_BUG_ON(SPL_FSTRANS == 0); + + cookie.fstrans_thread = current; + cookie.saved_flags = current->flags & SPL_FSTRANS; + current->flags |= SPL_FSTRANS; + + return (cookie); +} + +static inline void +spl_fstrans_unmark(fstrans_cookie_t cookie) +{ + ASSERT3P(cookie.fstrans_thread, ==, current); + ASSERT((current->flags & SPL_FSTRANS) == SPL_FSTRANS); + + current->flags &= ~SPL_FSTRANS; + current->flags |= cookie.saved_flags; +} + +static inline int +spl_fstrans_check(void) +{ + return (current->flags & SPL_FSTRANS); +} + +/* + * specifically used to check PF_FSTRANS flag, cannot be relied on for + * checking spl_fstrans_mark(). + */ +static inline int +__spl_pf_fstrans_check(void) +{ + return (current->flags & __SPL_PF_FSTRANS); +} + +/* + * Kernel compatibility for GFP flags + */ +/* < 4.13 */ +#ifndef __GFP_RETRY_MAYFAIL +#define __GFP_RETRY_MAYFAIL __GFP_REPEAT +#endif +/* < 4.4 */ +#ifndef __GFP_RECLAIM +#define __GFP_RECLAIM __GFP_WAIT +#endif + +#ifdef HAVE_ATOMIC64_T +#define kmem_alloc_used_add(size) atomic64_add(size, &kmem_alloc_used) +#define kmem_alloc_used_sub(size) atomic64_sub(size, &kmem_alloc_used) +#define kmem_alloc_used_read() atomic64_read(&kmem_alloc_used) +#define kmem_alloc_used_set(size) atomic64_set(&kmem_alloc_used, size) +extern atomic64_t kmem_alloc_used; +extern unsigned long long kmem_alloc_max; +#else /* HAVE_ATOMIC64_T */ +#define kmem_alloc_used_add(size) atomic_add(size, &kmem_alloc_used) +#define kmem_alloc_used_sub(size) atomic_sub(size, &kmem_alloc_used) +#define kmem_alloc_used_read() atomic_read(&kmem_alloc_used) +#define kmem_alloc_used_set(size) atomic_set(&kmem_alloc_used, size) +extern atomic_t kmem_alloc_used; +extern unsigned long long kmem_alloc_max; +#endif /* HAVE_ATOMIC64_T */ + +extern unsigned int spl_kmem_alloc_warn; +extern unsigned int spl_kmem_alloc_max; + +#define kmem_alloc(sz, fl) spl_kmem_alloc((sz), (fl), __func__, __LINE__) +#define kmem_zalloc(sz, fl) spl_kmem_zalloc((sz), (fl), __func__, __LINE__) +#define kmem_free(ptr, sz) spl_kmem_free((ptr), (sz)) +#define kmem_cache_reap_active spl_kmem_cache_reap_active + +extern void *spl_kmem_alloc(size_t sz, int fl, const char *func, int line); +extern void *spl_kmem_zalloc(size_t sz, int fl, const char *func, int line); +extern void spl_kmem_free(const void *ptr, size_t sz); + +/* + * 5.8 API change, pgprot_t argument removed. + */ +#ifdef HAVE_VMALLOC_PAGE_KERNEL +#define spl_vmalloc(size, flags) __vmalloc(size, flags, PAGE_KERNEL) +#else +#define spl_vmalloc(size, flags) __vmalloc(size, flags) +#endif + +/* + * The following functions are only available for internal use. + */ +extern void *spl_kmem_alloc_impl(size_t size, int flags, int node); +extern void *spl_kmem_alloc_debug(size_t size, int flags, int node); +extern void *spl_kmem_alloc_track(size_t size, int flags, + const char *func, int line, int node); +extern void spl_kmem_free_impl(const void *buf, size_t size); +extern void spl_kmem_free_debug(const void *buf, size_t size); +extern void spl_kmem_free_track(const void *buf, size_t size); + +extern int spl_kmem_init(void); +extern void spl_kmem_fini(void); +extern int spl_kmem_cache_reap_active(void); + +#endif /* _SPL_KMEM_H */ diff --git a/include/os/linux/spl/sys/kmem_cache.h b/include/os/linux/spl/sys/kmem_cache.h new file mode 100644 index 000000000000..ffb8c97c9c91 --- /dev/null +++ b/include/os/linux/spl/sys/kmem_cache.h @@ -0,0 +1,216 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_KMEM_CACHE_H +#define _SPL_KMEM_CACHE_H + +#include <sys/taskq.h> + +/* + * Slab allocation interfaces. The SPL slab differs from the standard + * Linux SLAB or SLUB primarily in that each cache may be backed by slabs + * allocated from the physical or virtual memory address space. The virtual + * slabs allow for good behavior when allocation large objects of identical + * size. This slab implementation also supports both constructors and + * destructors which the Linux slab does not. + */ +typedef enum kmc_bit { + KMC_BIT_NODEBUG = 1, /* Default behavior */ + KMC_BIT_KVMEM = 7, /* Use kvmalloc linux allocator */ + KMC_BIT_SLAB = 8, /* Use Linux slab cache */ + KMC_BIT_DEADLOCKED = 14, /* Deadlock detected */ + KMC_BIT_GROWING = 15, /* Growing in progress */ + KMC_BIT_REAPING = 16, /* Reaping in progress */ + KMC_BIT_DESTROY = 17, /* Destroy in progress */ + KMC_BIT_TOTAL = 18, /* Proc handler helper bit */ + KMC_BIT_ALLOC = 19, /* Proc handler helper bit */ + KMC_BIT_MAX = 20, /* Proc handler helper bit */ +} kmc_bit_t; + +/* kmem move callback return values */ +typedef enum kmem_cbrc { + KMEM_CBRC_YES = 0, /* Object moved */ + KMEM_CBRC_NO = 1, /* Object not moved */ + KMEM_CBRC_LATER = 2, /* Object not moved, try again later */ + KMEM_CBRC_DONT_NEED = 3, /* Neither object is needed */ + KMEM_CBRC_DONT_KNOW = 4, /* Object unknown */ +} kmem_cbrc_t; + +#define KMC_NODEBUG (1 << KMC_BIT_NODEBUG) +#define KMC_KVMEM (1 << KMC_BIT_KVMEM) +#define KMC_SLAB (1 << KMC_BIT_SLAB) +#define KMC_DEADLOCKED (1 << KMC_BIT_DEADLOCKED) +#define KMC_GROWING (1 << KMC_BIT_GROWING) +#define KMC_REAPING (1 << KMC_BIT_REAPING) +#define KMC_DESTROY (1 << KMC_BIT_DESTROY) +#define KMC_TOTAL (1 << KMC_BIT_TOTAL) +#define KMC_ALLOC (1 << KMC_BIT_ALLOC) +#define KMC_MAX (1 << KMC_BIT_MAX) + +#define KMC_REAP_CHUNK INT_MAX +#define KMC_DEFAULT_SEEKS 1 + +#define KMC_RECLAIM_ONCE 0x1 /* Force a single shrinker pass */ + +extern struct list_head spl_kmem_cache_list; +extern struct rw_semaphore spl_kmem_cache_sem; + +#define SKM_MAGIC 0x2e2e2e2e +#define SKO_MAGIC 0x20202020 +#define SKS_MAGIC 0x22222222 +#define SKC_MAGIC 0x2c2c2c2c + +#define SPL_KMEM_CACHE_OBJ_PER_SLAB 8 /* Target objects per slab */ +#define SPL_KMEM_CACHE_ALIGN 8 /* Default object alignment */ +#ifdef _LP64 +#define SPL_KMEM_CACHE_MAX_SIZE 32 /* Max slab size in MB */ +#else +#define SPL_KMEM_CACHE_MAX_SIZE 4 /* Max slab size in MB */ +#endif + +#define SPL_MAX_ORDER (MAX_ORDER - 3) +#define SPL_MAX_ORDER_NR_PAGES (1 << (SPL_MAX_ORDER - 1)) + +#ifdef CONFIG_SLUB +#define SPL_MAX_KMEM_CACHE_ORDER PAGE_ALLOC_COSTLY_ORDER +#define SPL_MAX_KMEM_ORDER_NR_PAGES (1 << (SPL_MAX_KMEM_CACHE_ORDER - 1)) +#else +#define SPL_MAX_KMEM_ORDER_NR_PAGES (KMALLOC_MAX_SIZE >> PAGE_SHIFT) +#endif + +#define POINTER_IS_VALID(p) 0 /* Unimplemented */ +#define POINTER_INVALIDATE(pp) /* Unimplemented */ + +typedef int (*spl_kmem_ctor_t)(void *, void *, int); +typedef void (*spl_kmem_dtor_t)(void *, void *); + +typedef struct spl_kmem_magazine { + uint32_t skm_magic; /* Sanity magic */ + uint32_t skm_avail; /* Available objects */ + uint32_t skm_size; /* Magazine size */ + uint32_t skm_refill; /* Batch refill size */ + struct spl_kmem_cache *skm_cache; /* Owned by cache */ + unsigned int skm_cpu; /* Owned by cpu */ + void *skm_objs[0]; /* Object pointers */ +} spl_kmem_magazine_t; + +typedef struct spl_kmem_obj { + uint32_t sko_magic; /* Sanity magic */ + void *sko_addr; /* Buffer address */ + struct spl_kmem_slab *sko_slab; /* Owned by slab */ + struct list_head sko_list; /* Free object list linkage */ +} spl_kmem_obj_t; + +typedef struct spl_kmem_slab { + uint32_t sks_magic; /* Sanity magic */ + uint32_t sks_objs; /* Objects per slab */ + struct spl_kmem_cache *sks_cache; /* Owned by cache */ + struct list_head sks_list; /* Slab list linkage */ + struct list_head sks_free_list; /* Free object list */ + unsigned long sks_age; /* Last modify jiffie */ + uint32_t sks_ref; /* Ref count used objects */ +} spl_kmem_slab_t; + +typedef struct spl_kmem_alloc { + struct spl_kmem_cache *ska_cache; /* Owned by cache */ + int ska_flags; /* Allocation flags */ + taskq_ent_t ska_tqe; /* Task queue entry */ +} spl_kmem_alloc_t; + +typedef struct spl_kmem_emergency { + struct rb_node ske_node; /* Emergency tree linkage */ + unsigned long ske_obj; /* Buffer address */ +} spl_kmem_emergency_t; + +typedef struct spl_kmem_cache { + uint32_t skc_magic; /* Sanity magic */ + uint32_t skc_name_size; /* Name length */ + char *skc_name; /* Name string */ + spl_kmem_magazine_t **skc_mag; /* Per-CPU warm cache */ + uint32_t skc_mag_size; /* Magazine size */ + uint32_t skc_mag_refill; /* Magazine refill count */ + spl_kmem_ctor_t skc_ctor; /* Constructor */ + spl_kmem_dtor_t skc_dtor; /* Destructor */ + void *skc_private; /* Private data */ + void *skc_vmp; /* Unused */ + struct kmem_cache *skc_linux_cache; /* Linux slab cache if used */ + unsigned long skc_flags; /* Flags */ + uint32_t skc_obj_size; /* Object size */ + uint32_t skc_obj_align; /* Object alignment */ + uint32_t skc_slab_objs; /* Objects per slab */ + uint32_t skc_slab_size; /* Slab size */ + atomic_t skc_ref; /* Ref count callers */ + taskqid_t skc_taskqid; /* Slab reclaim task */ + struct list_head skc_list; /* List of caches linkage */ + struct list_head skc_complete_list; /* Completely alloc'ed */ + struct list_head skc_partial_list; /* Partially alloc'ed */ + struct rb_root skc_emergency_tree; /* Min sized objects */ + spinlock_t skc_lock; /* Cache lock */ + spl_wait_queue_head_t skc_waitq; /* Allocation waiters */ + uint64_t skc_slab_fail; /* Slab alloc failures */ + uint64_t skc_slab_create; /* Slab creates */ + uint64_t skc_slab_destroy; /* Slab destroys */ + uint64_t skc_slab_total; /* Slab total current */ + uint64_t skc_slab_alloc; /* Slab alloc current */ + uint64_t skc_slab_max; /* Slab max historic */ + uint64_t skc_obj_total; /* Obj total current */ + uint64_t skc_obj_alloc; /* Obj alloc current */ + struct percpu_counter skc_linux_alloc; /* Linux-backed Obj alloc */ + uint64_t skc_obj_max; /* Obj max historic */ + uint64_t skc_obj_deadlock; /* Obj emergency deadlocks */ + uint64_t skc_obj_emergency; /* Obj emergency current */ + uint64_t skc_obj_emergency_max; /* Obj emergency max */ +} spl_kmem_cache_t; +#define kmem_cache_t spl_kmem_cache_t + +extern spl_kmem_cache_t *spl_kmem_cache_create(char *name, size_t size, + size_t align, spl_kmem_ctor_t ctor, spl_kmem_dtor_t dtor, + void *reclaim, void *priv, void *vmp, int flags); +extern void spl_kmem_cache_set_move(spl_kmem_cache_t *, + kmem_cbrc_t (*)(void *, void *, size_t, void *)); +extern void spl_kmem_cache_destroy(spl_kmem_cache_t *skc); +extern void *spl_kmem_cache_alloc(spl_kmem_cache_t *skc, int flags); +extern void spl_kmem_cache_free(spl_kmem_cache_t *skc, void *obj); +extern void spl_kmem_cache_set_allocflags(spl_kmem_cache_t *skc, gfp_t flags); +extern void spl_kmem_cache_reap_now(spl_kmem_cache_t *skc); +extern void spl_kmem_reap(void); +extern uint64_t spl_kmem_cache_inuse(kmem_cache_t *cache); +extern uint64_t spl_kmem_cache_entry_size(kmem_cache_t *cache); + +#define kmem_cache_create(name, size, align, ctor, dtor, rclm, priv, vmp, fl) \ + spl_kmem_cache_create(name, size, align, ctor, dtor, rclm, priv, vmp, fl) +#define kmem_cache_set_move(skc, move) spl_kmem_cache_set_move(skc, move) +#define kmem_cache_destroy(skc) spl_kmem_cache_destroy(skc) +#define kmem_cache_alloc(skc, flags) spl_kmem_cache_alloc(skc, flags) +#define kmem_cache_free(skc, obj) spl_kmem_cache_free(skc, obj) +#define kmem_cache_reap_now(skc) spl_kmem_cache_reap_now(skc) +#define kmem_reap() spl_kmem_reap() + +/* + * The following functions are only available for internal use. + */ +extern int spl_kmem_cache_init(void); +extern void spl_kmem_cache_fini(void); + +#endif /* _SPL_KMEM_CACHE_H */ diff --git a/include/os/linux/spl/sys/kstat.h b/include/os/linux/spl/sys/kstat.h new file mode 100644 index 000000000000..c93c53171d88 --- /dev/null +++ b/include/os/linux/spl/sys/kstat.h @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_KSTAT_H +#define _SPL_KSTAT_H + +#include <linux/module.h> +#include <sys/types.h> +#include <sys/time.h> +#include <sys/kmem.h> +#include <sys/mutex.h> +#include <sys/proc.h> + +#define KSTAT_STRLEN 255 +#define KSTAT_RAW_MAX (128*1024) + +/* + * For reference valid classes are: + * disk, tape, net, controller, vm, kvm, hat, streams, kstat, misc + */ + +#define KSTAT_TYPE_RAW 0 /* can be anything; ks_ndata >= 1 */ +#define KSTAT_TYPE_NAMED 1 /* name/value pair; ks_ndata >= 1 */ +#define KSTAT_TYPE_INTR 2 /* interrupt stats; ks_ndata == 1 */ +#define KSTAT_TYPE_IO 3 /* I/O stats; ks_ndata == 1 */ +#define KSTAT_TYPE_TIMER 4 /* event timer; ks_ndata >= 1 */ +#define KSTAT_NUM_TYPES 5 + +#define KSTAT_DATA_CHAR 0 +#define KSTAT_DATA_INT32 1 +#define KSTAT_DATA_UINT32 2 +#define KSTAT_DATA_INT64 3 +#define KSTAT_DATA_UINT64 4 +#define KSTAT_DATA_LONG 5 +#define KSTAT_DATA_ULONG 6 +#define KSTAT_DATA_STRING 7 +#define KSTAT_NUM_DATAS 8 + +#define KSTAT_INTR_HARD 0 +#define KSTAT_INTR_SOFT 1 +#define KSTAT_INTR_WATCHDOG 2 +#define KSTAT_INTR_SPURIOUS 3 +#define KSTAT_INTR_MULTSVC 4 +#define KSTAT_NUM_INTRS 5 + +#define KSTAT_FLAG_VIRTUAL 0x01 +#define KSTAT_FLAG_VAR_SIZE 0x02 +#define KSTAT_FLAG_WRITABLE 0x04 +#define KSTAT_FLAG_PERSISTENT 0x08 +#define KSTAT_FLAG_DORMANT 0x10 +#define KSTAT_FLAG_INVALID 0x20 +#define KSTAT_FLAG_LONGSTRINGS 0x40 +#define KSTAT_FLAG_NO_HEADERS 0x80 + +#define KS_MAGIC 0x9d9d9d9d + +/* Dynamic updates */ +#define KSTAT_READ 0 +#define KSTAT_WRITE 1 + +struct kstat_s; +typedef struct kstat_s kstat_t; + +typedef int kid_t; /* unique kstat id */ +typedef int kstat_update_t(struct kstat_s *, int); /* dynamic update cb */ + +typedef struct kstat_module { + char ksm_name[KSTAT_STRLEN+1]; /* module name */ + struct list_head ksm_module_list; /* module linkage */ + struct list_head ksm_kstat_list; /* list of kstat entries */ + struct proc_dir_entry *ksm_proc; /* proc entry */ +} kstat_module_t; + +typedef struct kstat_raw_ops { + int (*headers)(char *buf, size_t size); + int (*data)(char *buf, size_t size, void *data); + void *(*addr)(kstat_t *ksp, loff_t index); +} kstat_raw_ops_t; + +typedef struct kstat_proc_entry { + char kpe_name[KSTAT_STRLEN+1]; /* kstat name */ + char kpe_module[KSTAT_STRLEN+1]; /* provider module name */ + kstat_module_t *kpe_owner; /* kstat module linkage */ + struct list_head kpe_list; /* kstat linkage */ + struct proc_dir_entry *kpe_proc; /* procfs entry */ +} kstat_proc_entry_t; + +struct kstat_s { + int ks_magic; /* magic value */ + kid_t ks_kid; /* unique kstat ID */ + hrtime_t ks_crtime; /* creation time */ + hrtime_t ks_snaptime; /* last access time */ + int ks_instance; /* provider module instance */ + char ks_class[KSTAT_STRLEN+1]; /* kstat class */ + uchar_t ks_type; /* kstat data type */ + uchar_t ks_flags; /* kstat flags */ + void *ks_data; /* kstat type-specific data */ + uint_t ks_ndata; /* # of data records */ + size_t ks_data_size; /* size of kstat data section */ + kstat_update_t *ks_update; /* dynamic updates */ + void *ks_private; /* private data */ + kmutex_t ks_private_lock; /* kstat private data lock */ + kmutex_t *ks_lock; /* kstat data lock */ + kstat_raw_ops_t ks_raw_ops; /* ops table for raw type */ + char *ks_raw_buf; /* buf used for raw ops */ + size_t ks_raw_bufsize; /* size of raw ops buffer */ + kstat_proc_entry_t ks_proc; /* data for procfs entry */ +}; + +typedef struct kstat_named_s { + char name[KSTAT_STRLEN]; /* name of counter */ + uchar_t data_type; /* data type */ + union { + char c[16]; /* 128-bit int */ + int32_t i32; /* 32-bit signed int */ + uint32_t ui32; /* 32-bit unsigned int */ + int64_t i64; /* 64-bit signed int */ + uint64_t ui64; /* 64-bit unsigned int */ + long l; /* native signed long */ + ulong_t ul; /* native unsigned long */ + struct { + union { + char *ptr; /* NULL-term string */ + char __pad[8]; /* 64-bit padding */ + } addr; + uint32_t len; /* # bytes for strlen + '\0' */ + } string; + } value; +} kstat_named_t; + +#define KSTAT_NAMED_STR_PTR(knptr) ((knptr)->value.string.addr.ptr) +#define KSTAT_NAMED_STR_BUFLEN(knptr) ((knptr)->value.string.len) + +#ifdef HAVE_PROC_OPS_STRUCT +typedef struct proc_ops kstat_proc_op_t; +#else +typedef struct file_operations kstat_proc_op_t; +#endif + +typedef struct kstat_intr { + uint_t intrs[KSTAT_NUM_INTRS]; +} kstat_intr_t; + +typedef struct kstat_io { + u_longlong_t nread; /* number of bytes read */ + u_longlong_t nwritten; /* number of bytes written */ + uint_t reads; /* number of read operations */ + uint_t writes; /* number of write operations */ + hrtime_t wtime; /* cumulative wait (pre-service) time */ + hrtime_t wlentime; /* cumulative wait len*time product */ + hrtime_t wlastupdate; /* last time wait queue changed */ + hrtime_t rtime; /* cumulative run (service) time */ + hrtime_t rlentime; /* cumulative run length*time product */ + hrtime_t rlastupdate; /* last time run queue changed */ + uint_t wcnt; /* count of elements in wait state */ + uint_t rcnt; /* count of elements in run state */ +} kstat_io_t; + +typedef struct kstat_timer { + char name[KSTAT_STRLEN+1]; /* event name */ + u_longlong_t num_events; /* number of events */ + hrtime_t elapsed_time; /* cumulative elapsed time */ + hrtime_t min_time; /* shortest event duration */ + hrtime_t max_time; /* longest event duration */ + hrtime_t start_time; /* previous event start time */ + hrtime_t stop_time; /* previous event stop time */ +} kstat_timer_t; + +int spl_kstat_init(void); +void spl_kstat_fini(void); + +extern void __kstat_set_raw_ops(kstat_t *ksp, + int (*headers)(char *buf, size_t size), + int (*data)(char *buf, size_t size, void *data), + void* (*addr)(kstat_t *ksp, loff_t index)); + +extern kstat_t *__kstat_create(const char *ks_module, int ks_instance, + const char *ks_name, const char *ks_class, uchar_t ks_type, + uint_t ks_ndata, uchar_t ks_flags); + +extern void kstat_proc_entry_init(kstat_proc_entry_t *kpep, + const char *module, const char *name); +extern void kstat_proc_entry_delete(kstat_proc_entry_t *kpep); +extern void kstat_proc_entry_install(kstat_proc_entry_t *kpep, mode_t mode, + const kstat_proc_op_t *file_ops, void *data); + +extern void __kstat_install(kstat_t *ksp); +extern void __kstat_delete(kstat_t *ksp); +extern void kstat_waitq_enter(kstat_io_t *); +extern void kstat_waitq_exit(kstat_io_t *); +extern void kstat_runq_enter(kstat_io_t *); +extern void kstat_runq_exit(kstat_io_t *); + +#define kstat_set_raw_ops(k, h, d, a) \ + __kstat_set_raw_ops(k, h, d, a) +#define kstat_create(m, i, n, c, t, s, f) \ + __kstat_create(m, i, n, c, t, s, f) + +#define kstat_install(k) __kstat_install(k) +#define kstat_delete(k) __kstat_delete(k) + +#endif /* _SPL_KSTAT_H */ diff --git a/include/os/linux/spl/sys/list.h b/include/os/linux/spl/sys/list.h new file mode 100644 index 000000000000..be38f328fc65 --- /dev/null +++ b/include/os/linux/spl/sys/list.h @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_LIST_H +#define _SPL_LIST_H + +#include <sys/types.h> +#include <sys/debug.h> +#include <linux/list.h> + +/* + * NOTE: I have implemented the Solaris list API in terms of the native + * linux API. This has certain advantages in terms of leveraging the linux + * list debugging infrastructure, but it also means that the internals of a + * list differ slightly than on Solaris. This is not a problem as long as + * all callers stick to the published API. The two major differences are: + * + * 1) A list_node_t is mapped to a linux list_head struct which changes + * the name of the list_next/list_prev pointers to next/prev respectively. + * + * 2) A list_node_t which is not attached to a list on Solaris is denoted + * by having its list_next/list_prev pointers set to NULL. Under linux + * the next/prev pointers are set to LIST_POISON1 and LIST_POISON2 + * respectively. At this moment this only impacts the implementation + * of the list_link_init() and list_link_active() functions. + */ + +typedef struct list_head list_node_t; + +typedef struct list { + size_t list_size; + size_t list_offset; + list_node_t list_head; +} list_t; + +#define list_d2l(a, obj) ((list_node_t *)(((char *)obj) + (a)->list_offset)) +#define list_object(a, node) ((void *)(((char *)node) - (a)->list_offset)) + +static inline int +list_is_empty(list_t *list) +{ + return (list_empty(&list->list_head)); +} + +static inline void +list_link_init(list_node_t *node) +{ + node->next = LIST_POISON1; + node->prev = LIST_POISON2; +} + +static inline void +list_create(list_t *list, size_t size, size_t offset) +{ + list->list_size = size; + list->list_offset = offset; + INIT_LIST_HEAD(&list->list_head); +} + +static inline void +list_destroy(list_t *list) +{ + list_del(&list->list_head); +} + +static inline void +list_insert_head(list_t *list, void *object) +{ + list_add(list_d2l(list, object), &list->list_head); +} + +static inline void +list_insert_tail(list_t *list, void *object) +{ + list_add_tail(list_d2l(list, object), &list->list_head); +} + +static inline void +list_insert_after(list_t *list, void *object, void *nobject) +{ + if (object == NULL) + list_insert_head(list, nobject); + else + list_add(list_d2l(list, nobject), list_d2l(list, object)); +} + +static inline void +list_insert_before(list_t *list, void *object, void *nobject) +{ + if (object == NULL) + list_insert_tail(list, nobject); + else + list_add_tail(list_d2l(list, nobject), list_d2l(list, object)); +} + +static inline void +list_remove(list_t *list, void *object) +{ + list_del(list_d2l(list, object)); +} + +static inline void * +list_remove_head(list_t *list) +{ + list_node_t *head = list->list_head.next; + if (head == &list->list_head) + return (NULL); + + list_del(head); + return (list_object(list, head)); +} + +static inline void * +list_remove_tail(list_t *list) +{ + list_node_t *tail = list->list_head.prev; + if (tail == &list->list_head) + return (NULL); + + list_del(tail); + return (list_object(list, tail)); +} + +static inline void * +list_head(list_t *list) +{ + if (list_is_empty(list)) + return (NULL); + + return (list_object(list, list->list_head.next)); +} + +static inline void * +list_tail(list_t *list) +{ + if (list_is_empty(list)) + return (NULL); + + return (list_object(list, list->list_head.prev)); +} + +static inline void * +list_next(list_t *list, void *object) +{ + list_node_t *node = list_d2l(list, object); + + if (node->next != &list->list_head) + return (list_object(list, node->next)); + + return (NULL); +} + +static inline void * +list_prev(list_t *list, void *object) +{ + list_node_t *node = list_d2l(list, object); + + if (node->prev != &list->list_head) + return (list_object(list, node->prev)); + + return (NULL); +} + +static inline int +list_link_active(list_node_t *node) +{ + EQUIV(node->next == LIST_POISON1, node->prev == LIST_POISON2); + return (node->next != LIST_POISON1); +} + +static inline void +spl_list_move_tail(list_t *dst, list_t *src) +{ + list_splice_init(&src->list_head, dst->list_head.prev); +} + +#define list_move_tail(dst, src) spl_list_move_tail(dst, src) + +static inline void +list_link_replace(list_node_t *old_node, list_node_t *new_node) +{ + new_node->next = old_node->next; + new_node->prev = old_node->prev; + old_node->prev->next = new_node; + old_node->next->prev = new_node; + list_link_init(old_node); +} + +#endif /* SPL_LIST_H */ diff --git a/include/os/linux/spl/sys/mod_os.h b/include/os/linux/spl/sys/mod_os.h new file mode 100644 index 000000000000..8adf6212907f --- /dev/null +++ b/include/os/linux/spl/sys/mod_os.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ +#ifndef _SPL_MOD_H +#define _SPL_MOD_H +#include <linux/mod_compat.h> + +#endif /* SPL_MOD_H */ diff --git a/include/os/linux/spl/sys/mutex.h b/include/os/linux/spl/sys/mutex.h new file mode 100644 index 000000000000..93f3af8fe016 --- /dev/null +++ b/include/os/linux/spl/sys/mutex.h @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_MUTEX_H +#define _SPL_MUTEX_H + +#include <sys/types.h> +#include <linux/sched.h> +#include <linux/mutex.h> +#include <linux/lockdep.h> +#include <linux/compiler_compat.h> + +typedef enum { + MUTEX_DEFAULT = 0, + MUTEX_SPIN = 1, + MUTEX_ADAPTIVE = 2, + MUTEX_NOLOCKDEP = 3 +} kmutex_type_t; + +typedef struct { + struct mutex m_mutex; + spinlock_t m_lock; /* used for serializing mutex_exit */ + kthread_t *m_owner; +#ifdef CONFIG_LOCKDEP + kmutex_type_t m_type; +#endif /* CONFIG_LOCKDEP */ +} kmutex_t; + +#define MUTEX(mp) (&((mp)->m_mutex)) + +static inline void +spl_mutex_set_owner(kmutex_t *mp) +{ + mp->m_owner = current; +} + +static inline void +spl_mutex_clear_owner(kmutex_t *mp) +{ + mp->m_owner = NULL; +} + +#define mutex_owner(mp) (READ_ONCE((mp)->m_owner)) +#define mutex_owned(mp) (mutex_owner(mp) == current) +#define MUTEX_HELD(mp) mutex_owned(mp) +#define MUTEX_NOT_HELD(mp) (!MUTEX_HELD(mp)) + +#ifdef CONFIG_LOCKDEP +static inline void +spl_mutex_set_type(kmutex_t *mp, kmutex_type_t type) +{ + mp->m_type = type; +} +static inline void +spl_mutex_lockdep_off_maybe(kmutex_t *mp) \ +{ \ + if (mp && mp->m_type == MUTEX_NOLOCKDEP) \ + lockdep_off(); \ +} +static inline void +spl_mutex_lockdep_on_maybe(kmutex_t *mp) \ +{ \ + if (mp && mp->m_type == MUTEX_NOLOCKDEP) \ + lockdep_on(); \ +} +#else /* CONFIG_LOCKDEP */ +#define spl_mutex_set_type(mp, type) +#define spl_mutex_lockdep_off_maybe(mp) +#define spl_mutex_lockdep_on_maybe(mp) +#endif /* CONFIG_LOCKDEP */ + +/* + * The following functions must be a #define and not static inline. + * This ensures that the native linux mutex functions (lock/unlock) + * will be correctly located in the users code which is important + * for the built in kernel lock analysis tools + */ +#undef mutex_init +#define mutex_init(mp, name, type, ibc) \ +{ \ + static struct lock_class_key __key; \ + ASSERT(type == MUTEX_DEFAULT || type == MUTEX_NOLOCKDEP); \ + \ + __mutex_init(MUTEX(mp), (name) ? (#name) : (#mp), &__key); \ + spin_lock_init(&(mp)->m_lock); \ + spl_mutex_clear_owner(mp); \ + spl_mutex_set_type(mp, type); \ +} + +#undef mutex_destroy +#define mutex_destroy(mp) \ +{ \ + VERIFY3P(mutex_owner(mp), ==, NULL); \ +} + +/* BEGIN CSTYLED */ +#define mutex_tryenter(mp) \ +({ \ + int _rc_; \ + \ + spl_mutex_lockdep_off_maybe(mp); \ + if ((_rc_ = mutex_trylock(MUTEX(mp))) == 1) \ + spl_mutex_set_owner(mp); \ + spl_mutex_lockdep_on_maybe(mp); \ + \ + _rc_; \ +}) +/* END CSTYLED */ + +#define NESTED_SINGLE 1 + +#ifdef CONFIG_DEBUG_LOCK_ALLOC +#define mutex_enter_nested(mp, subclass) \ +{ \ + ASSERT3P(mutex_owner(mp), !=, current); \ + spl_mutex_lockdep_off_maybe(mp); \ + mutex_lock_nested(MUTEX(mp), (subclass)); \ + spl_mutex_lockdep_on_maybe(mp); \ + spl_mutex_set_owner(mp); \ +} +#else /* CONFIG_DEBUG_LOCK_ALLOC */ +#define mutex_enter_nested(mp, subclass) \ +{ \ + ASSERT3P(mutex_owner(mp), !=, current); \ + spl_mutex_lockdep_off_maybe(mp); \ + mutex_lock(MUTEX(mp)); \ + spl_mutex_lockdep_on_maybe(mp); \ + spl_mutex_set_owner(mp); \ +} +#endif /* CONFIG_DEBUG_LOCK_ALLOC */ + +#define mutex_enter(mp) mutex_enter_nested((mp), 0) + +/* + * The reason for the spinlock: + * + * The Linux mutex is designed with a fast-path/slow-path design such that it + * does not guarantee serialization upon itself, allowing a race where latter + * acquirers finish mutex_unlock before former ones. + * + * The race renders it unsafe to be used for serializing the freeing of an + * object in which the mutex is embedded, where the latter acquirer could go + * on to free the object while the former one is still doing mutex_unlock and + * causing memory corruption. + * + * However, there are many places in ZFS where the mutex is used for + * serializing object freeing, and the code is shared among other OSes without + * this issue. Thus, we need the spinlock to force the serialization on + * mutex_exit(). + * + * See http://lwn.net/Articles/575477/ for the information about the race. + */ +#define mutex_exit(mp) \ +{ \ + spl_mutex_clear_owner(mp); \ + spin_lock(&(mp)->m_lock); \ + spl_mutex_lockdep_off_maybe(mp); \ + mutex_unlock(MUTEX(mp)); \ + spl_mutex_lockdep_on_maybe(mp); \ + spin_unlock(&(mp)->m_lock); \ + /* NOTE: do not dereference mp after this point */ \ +} + +#endif /* _SPL_MUTEX_H */ diff --git a/include/os/linux/spl/sys/param.h b/include/os/linux/spl/sys/param.h new file mode 100644 index 000000000000..4ef929151ae4 --- /dev/null +++ b/include/os/linux/spl/sys/param.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_PARAM_H +#define _SPL_PARAM_H + +#include <asm/page.h> + +/* Pages to bytes and back */ +#define ptob(pages) ((pages) << PAGE_SHIFT) +#define btop(bytes) ((bytes) >> PAGE_SHIFT) + +#define MAXUID UINT32_MAX + +#endif /* SPL_PARAM_H */ diff --git a/include/os/linux/spl/sys/proc.h b/include/os/linux/spl/sys/proc.h new file mode 100644 index 000000000000..fefce515eb24 --- /dev/null +++ b/include/os/linux/spl/sys/proc.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_PROC_H +#define _SPL_PROC_H + +#include <linux/proc_fs.h> +#include <linux/sched.h> + +extern struct proc_dir_entry *proc_spl_kstat; + +int spl_proc_init(void); +void spl_proc_fini(void); + +static inline boolean_t +zfs_proc_is_caller(struct task_struct *t) +{ + return (t->group_leader == current->group_leader); +} + +#endif /* SPL_PROC_H */ diff --git a/include/os/linux/spl/sys/processor.h b/include/os/linux/spl/sys/processor.h new file mode 100644 index 000000000000..a70101fa2f90 --- /dev/null +++ b/include/os/linux/spl/sys/processor.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_PROCESSOR_H +#define _SPL_PROCESSOR_H + +#define getcpuid() smp_processor_id() + +typedef int processorid_t; + +#endif /* _SPL_PROCESSOR_H */ diff --git a/include/os/linux/spl/sys/procfs_list.h b/include/os/linux/spl/sys/procfs_list.h new file mode 100644 index 000000000000..eb1519c0ad63 --- /dev/null +++ b/include/os/linux/spl/sys/procfs_list.h @@ -0,0 +1,72 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2018 by Delphix. All rights reserved. + */ + +#ifndef _SPL_PROCFS_LIST_H +#define _SPL_PROCFS_LIST_H + +#include <sys/kstat.h> +#include <sys/mutex.h> +#include <linux/proc_fs.h> +#include <linux/seq_file.h> + +typedef struct procfs_list procfs_list_t; +struct procfs_list { + /* Accessed only by user of a procfs_list */ + void *pl_private; + + /* + * Accessed both by user of a procfs_list and by procfs_list + * implementation + */ + kmutex_t pl_lock; + list_t pl_list; + + /* Accessed only by procfs_list implementation */ + uint64_t pl_next_id; + int (*pl_show)(struct seq_file *f, void *p); + int (*pl_show_header)(struct seq_file *f); + int (*pl_clear)(procfs_list_t *procfs_list); + size_t pl_node_offset; + kstat_proc_entry_t pl_kstat_entry; +}; + +typedef struct procfs_list_node { + list_node_t pln_link; + uint64_t pln_id; +} procfs_list_node_t; + +void procfs_list_install(const char *module, + const char *name, + mode_t mode, + procfs_list_t *procfs_list, + int (*show)(struct seq_file *f, void *p), + int (*show_header)(struct seq_file *f), + int (*clear)(procfs_list_t *procfs_list), + size_t procfs_list_node_off); +void procfs_list_uninstall(procfs_list_t *procfs_list); +void procfs_list_destroy(procfs_list_t *procfs_list); + +void procfs_list_add(procfs_list_t *procfs_list, void *p); + +#endif /* _SPL_PROCFS_LIST_H */ diff --git a/include/os/linux/spl/sys/random.h b/include/os/linux/spl/sys/random.h new file mode 100644 index 000000000000..93e244f566be --- /dev/null +++ b/include/os/linux/spl/sys/random.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_RANDOM_H +#define _SPL_RANDOM_H + +#include <linux/module.h> +#include <linux/random.h> + +static __inline__ int +random_get_bytes(uint8_t *ptr, size_t len) +{ + get_random_bytes((void *)ptr, (int)len); + return (0); +} + +extern int random_get_pseudo_bytes(uint8_t *ptr, size_t len); + +#endif /* _SPL_RANDOM_H */ diff --git a/include/os/linux/spl/sys/rwlock.h b/include/os/linux/spl/sys/rwlock.h new file mode 100644 index 000000000000..60f5bfd986b4 --- /dev/null +++ b/include/os/linux/spl/sys/rwlock.h @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_RWLOCK_H +#define _SPL_RWLOCK_H + +#include <sys/types.h> +#include <linux/rwsem.h> +#include <linux/sched.h> + +typedef enum { + RW_DRIVER = 2, + RW_DEFAULT = 4, + RW_NOLOCKDEP = 5 +} krw_type_t; + +typedef enum { + RW_NONE = 0, + RW_WRITER = 1, + RW_READER = 2 +} krw_t; + +typedef struct { + struct rw_semaphore rw_rwlock; + kthread_t *rw_owner; +#ifdef CONFIG_LOCKDEP + krw_type_t rw_type; +#endif /* CONFIG_LOCKDEP */ +} krwlock_t; + +#define SEM(rwp) (&(rwp)->rw_rwlock) + +static inline void +spl_rw_set_owner(krwlock_t *rwp) +{ + rwp->rw_owner = current; +} + +static inline void +spl_rw_clear_owner(krwlock_t *rwp) +{ + rwp->rw_owner = NULL; +} + +static inline kthread_t * +rw_owner(krwlock_t *rwp) +{ + return (rwp->rw_owner); +} + +#ifdef CONFIG_LOCKDEP +static inline void +spl_rw_set_type(krwlock_t *rwp, krw_type_t type) +{ + rwp->rw_type = type; +} +static inline void +spl_rw_lockdep_off_maybe(krwlock_t *rwp) \ +{ \ + if (rwp && rwp->rw_type == RW_NOLOCKDEP) \ + lockdep_off(); \ +} +static inline void +spl_rw_lockdep_on_maybe(krwlock_t *rwp) \ +{ \ + if (rwp && rwp->rw_type == RW_NOLOCKDEP) \ + lockdep_on(); \ +} +#else /* CONFIG_LOCKDEP */ +#define spl_rw_set_type(rwp, type) +#define spl_rw_lockdep_off_maybe(rwp) +#define spl_rw_lockdep_on_maybe(rwp) +#endif /* CONFIG_LOCKDEP */ + +static inline int +RW_LOCK_HELD(krwlock_t *rwp) +{ + return (rwsem_is_locked(SEM(rwp))); +} + +static inline int +RW_WRITE_HELD(krwlock_t *rwp) +{ + return (rw_owner(rwp) == current); +} + +static inline int +RW_READ_HELD(krwlock_t *rwp) +{ + return (RW_LOCK_HELD(rwp) && rw_owner(rwp) == NULL); +} + +/* + * The following functions must be a #define and not static inline. + * This ensures that the native linux semaphore functions (down/up) + * will be correctly located in the users code which is important + * for the built in kernel lock analysis tools + */ +/* BEGIN CSTYLED */ +#define rw_init(rwp, name, type, arg) \ +({ \ + static struct lock_class_key __key; \ + ASSERT(type == RW_DEFAULT || type == RW_NOLOCKDEP); \ + \ + __init_rwsem(SEM(rwp), #rwp, &__key); \ + spl_rw_clear_owner(rwp); \ + spl_rw_set_type(rwp, type); \ +}) + +/* + * The Linux rwsem implementation does not require a matching destroy. + */ +#define rw_destroy(rwp) ((void) 0) + +/* + * Upgrading a rwsem from a reader to a writer is not supported by the + * Linux kernel. The lock must be dropped and reacquired as a writer. + */ +#define rw_tryupgrade(rwp) RW_WRITE_HELD(rwp) + +#define rw_tryenter(rwp, rw) \ +({ \ + int _rc_ = 0; \ + \ + spl_rw_lockdep_off_maybe(rwp); \ + switch (rw) { \ + case RW_READER: \ + _rc_ = down_read_trylock(SEM(rwp)); \ + break; \ + case RW_WRITER: \ + if ((_rc_ = down_write_trylock(SEM(rwp)))) \ + spl_rw_set_owner(rwp); \ + break; \ + default: \ + VERIFY(0); \ + } \ + spl_rw_lockdep_on_maybe(rwp); \ + _rc_; \ +}) + +#define rw_enter(rwp, rw) \ +({ \ + spl_rw_lockdep_off_maybe(rwp); \ + switch (rw) { \ + case RW_READER: \ + down_read(SEM(rwp)); \ + break; \ + case RW_WRITER: \ + down_write(SEM(rwp)); \ + spl_rw_set_owner(rwp); \ + break; \ + default: \ + VERIFY(0); \ + } \ + spl_rw_lockdep_on_maybe(rwp); \ +}) + +#define rw_exit(rwp) \ +({ \ + spl_rw_lockdep_off_maybe(rwp); \ + if (RW_WRITE_HELD(rwp)) { \ + spl_rw_clear_owner(rwp); \ + up_write(SEM(rwp)); \ + } else { \ + ASSERT(RW_READ_HELD(rwp)); \ + up_read(SEM(rwp)); \ + } \ + spl_rw_lockdep_on_maybe(rwp); \ +}) + +#define rw_downgrade(rwp) \ +({ \ + spl_rw_lockdep_off_maybe(rwp); \ + spl_rw_clear_owner(rwp); \ + downgrade_write(SEM(rwp)); \ + spl_rw_lockdep_on_maybe(rwp); \ +}) +/* END CSTYLED */ + +#endif /* _SPL_RWLOCK_H */ diff --git a/include/os/linux/spl/sys/shrinker.h b/include/os/linux/spl/sys/shrinker.h new file mode 100644 index 000000000000..cc34d8ab1931 --- /dev/null +++ b/include/os/linux/spl/sys/shrinker.h @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_SHRINKER_H +#define _SPL_SHRINKER_H + +#include <linux/mm.h> +#include <linux/fs.h> + +/* + * Due to frequent changes in the shrinker API the following + * compatibility wrappers should be used. They are as follows: + * + * SPL_SHRINKER_DECLARE(varname, countfunc, scanfunc, seek_cost); + * + * SPL_SHRINKER_DECLARE is used to declare a shrinker with the name varname, + * which is passed to spl_register_shrinker()/spl_unregister_shrinker(). + * The countfunc returns the number of free-able objects. + * The scanfunc returns the number of objects that were freed. + * The callbacks can return SHRINK_STOP if further calls can't make any more + * progress. Note that a return value of SHRINK_EMPTY is currently not + * supported. + * + * Example: + * + * static unsigned long + * my_count(struct shrinker *shrink, struct shrink_control *sc) + * { + * ...calculate number of objects in the cache... + * + * return (number of objects in the cache); + * } + * + * static unsigned long + * my_scan(struct shrinker *shrink, struct shrink_control *sc) + * { + * ...scan objects in the cache and reclaim them... + * } + * + * SPL_SHRINKER_DECLARE(my_shrinker, my_count, my_scan, DEFAULT_SEEKS); + * + * void my_init_func(void) { + * spl_register_shrinker(&my_shrinker); + * } + */ + +#define spl_register_shrinker(x) register_shrinker(x) +#define spl_unregister_shrinker(x) unregister_shrinker(x) + +/* + * Linux 3.0 to 3.11 Shrinker API Compatibility. + */ +#if defined(HAVE_SINGLE_SHRINKER_CALLBACK) +#define SPL_SHRINKER_DECLARE(varname, countfunc, scanfunc, seek_cost) \ +static int \ +__ ## varname ## _wrapper(struct shrinker *shrink, struct shrink_control *sc)\ +{ \ + if (sc->nr_to_scan != 0) { \ + (void) scanfunc(shrink, sc); \ + } \ + return (countfunc(shrink, sc)); \ +} \ + \ +static struct shrinker varname = { \ + .shrink = __ ## varname ## _wrapper, \ + .seeks = seek_cost, \ +} + +#define SHRINK_STOP (-1) + +/* + * Linux 3.12 and later Shrinker API Compatibility. + */ +#elif defined(HAVE_SPLIT_SHRINKER_CALLBACK) +#define SPL_SHRINKER_DECLARE(varname, countfunc, scanfunc, seek_cost) \ +static struct shrinker varname = { \ + .count_objects = countfunc, \ + .scan_objects = scanfunc, \ + .seeks = seek_cost, \ +} + +#else +/* + * Linux 2.x to 2.6.22, or a newer shrinker API has been introduced. + */ +#error "Unknown shrinker callback" +#endif + +#endif /* SPL_SHRINKER_H */ diff --git a/include/os/linux/spl/sys/sid.h b/include/os/linux/spl/sys/sid.h new file mode 100644 index 000000000000..731b62c47e70 --- /dev/null +++ b/include/os/linux/spl/sys/sid.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_SID_H +#define _SPL_SID_H + +typedef struct ksiddomain { + char *kd_name; +} ksiddomain_t; + +typedef enum ksid_index { + KSID_USER, + KSID_GROUP, + KSID_OWNER, + KSID_COUNT +} ksid_index_t; + +typedef int ksid_t; + +static inline ksiddomain_t * +ksid_lookupdomain(const char *dom) +{ + ksiddomain_t *kd; + int len = strlen(dom); + + kd = kmem_zalloc(sizeof (ksiddomain_t), KM_SLEEP); + kd->kd_name = kmem_zalloc(len + 1, KM_SLEEP); + memcpy(kd->kd_name, dom, len); + + return (kd); +} + +static inline void +ksiddomain_rele(ksiddomain_t *ksid) +{ + kmem_free(ksid->kd_name, strlen(ksid->kd_name) + 1); + kmem_free(ksid, sizeof (ksiddomain_t)); +} + +#endif /* _SPL_SID_H */ diff --git a/include/os/linux/spl/sys/signal.h b/include/os/linux/spl/sys/signal.h new file mode 100644 index 000000000000..36b8b5d985a9 --- /dev/null +++ b/include/os/linux/spl/sys/signal.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_SIGNAL_H +#define _SPL_SIGNAL_H + +#include <linux/sched.h> + +#ifdef HAVE_SCHED_SIGNAL_HEADER +#include <linux/sched/signal.h> +#endif + +#define FORREAL 0 /* Usual side-effects */ +#define JUSTLOOKING 1 /* Don't stop the process */ + +/* + * The "why" argument indicates the allowable side-effects of the call: + * + * FORREAL: Extract the next pending signal from p_sig into p_cursig; + * stop the process if a stop has been requested or if a traced signal + * is pending. + * + * JUSTLOOKING: Don't stop the process, just indicate whether or not + * a signal might be pending (FORREAL is needed to tell for sure). + */ +static __inline__ int +issig(int why) +{ + ASSERT(why == FORREAL || why == JUSTLOOKING); + + return (signal_pending(current)); +} + +#endif /* SPL_SIGNAL_H */ diff --git a/include/os/linux/spl/sys/simd.h b/include/os/linux/spl/sys/simd.h new file mode 100644 index 000000000000..f2048d9e121c --- /dev/null +++ b/include/os/linux/spl/sys/simd.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_SYS_SIMD_H +#define _SPL_SYS_SIMD_H + +#include <sys/isa_defs.h> +#include <linux/simd.h> + +#endif /* _SPL_SYS_SIMD_H */ diff --git a/include/os/linux/spl/sys/stat.h b/include/os/linux/spl/sys/stat.h new file mode 100644 index 000000000000..83018e89442f --- /dev/null +++ b/include/os/linux/spl/sys/stat.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_STAT_H +#define _SPL_STAT_H + +#include <linux/stat.h> + +#endif /* SPL_STAT_H */ diff --git a/include/os/linux/spl/sys/strings.h b/include/os/linux/spl/sys/strings.h new file mode 100644 index 000000000000..4fb80320635c --- /dev/null +++ b/include/os/linux/spl/sys/strings.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2018 Lawrence Livermore National Security, LLC. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ +#ifndef _SPL_SYS_STRINGS_H +#define _SPL_SYS_STRINGS_H + +#include <linux/string.h> + +#define bzero(ptr, size) memset(ptr, 0, size) +#define bcopy(src, dest, size) memmove(dest, src, size) +#define bcmp(src, dest, size) memcmp((src), (dest), (size_t)(size)) + +#endif /* _SPL_SYS_STRINGS_H */ diff --git a/include/os/linux/spl/sys/sunddi.h b/include/os/linux/spl/sys/sunddi.h new file mode 100644 index 000000000000..29a6fe00d1f4 --- /dev/null +++ b/include/os/linux/spl/sys/sunddi.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_SUNDDI_H +#define _SPL_SUNDDI_H + +#include <sys/cred.h> +#include <sys/uio.h> +#include <sys/mutex.h> +#include <sys/u8_textprep.h> +#include <sys/vnode.h> + +typedef int ddi_devid_t; + +#define DDI_DEV_T_NONE ((dev_t)-1) +#define DDI_DEV_T_ANY ((dev_t)-2) +#define DI_MAJOR_T_UNKNOWN ((major_t)0) + +#define DDI_PROP_DONTPASS 0x0001 +#define DDI_PROP_CANSLEEP 0x0002 + +#define DDI_SUCCESS 0 +#define DDI_FAILURE -1 + +#define ddi_prop_lookup_string(x1, x2, x3, x4, x5) (*x5 = NULL) +#define ddi_prop_free(x) (void)0 +#define ddi_root_node() (void)0 + +extern int ddi_strtoul(const char *, char **, int, unsigned long *); +extern int ddi_strtol(const char *, char **, int, long *); +extern int ddi_strtoull(const char *, char **, int, unsigned long long *); +extern int ddi_strtoll(const char *, char **, int, long long *); + +extern int ddi_copyin(const void *from, void *to, size_t len, int flags); +extern int ddi_copyout(const void *from, void *to, size_t len, int flags); + +#endif /* SPL_SUNDDI_H */ diff --git a/include/os/linux/spl/sys/sysmacros.h b/include/os/linux/spl/sys/sysmacros.h new file mode 100644 index 000000000000..7314588bcf82 --- /dev/null +++ b/include/os/linux/spl/sys/sysmacros.h @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_SYSMACROS_H +#define _SPL_SYSMACROS_H + +#include <linux/module.h> +#include <linux/sched.h> +#include <linux/sched/rt.h> +#include <linux/cpumask.h> +#include <sys/debug.h> +#include <sys/zone.h> +#include <sys/signal.h> +#include <asm/page.h> + + +#ifndef _KERNEL +#define _KERNEL __KERNEL__ +#endif + +#define FALSE 0 +#define TRUE 1 + +#define INT8_MAX (127) +#define INT8_MIN (-128) +#define UINT8_MAX (255) +#define UINT8_MIN (0) + +#define INT16_MAX (32767) +#define INT16_MIN (-32768) +#define UINT16_MAX (65535) +#define UINT16_MIN (0) + +#define INT32_MAX INT_MAX +#define INT32_MIN INT_MIN +#define UINT32_MAX UINT_MAX +#define UINT32_MIN UINT_MIN + +#define INT64_MAX LLONG_MAX +#define INT64_MIN LLONG_MIN +#define UINT64_MAX ULLONG_MAX +#define UINT64_MIN ULLONG_MIN + +#define NBBY 8 + +#define MAXMSGLEN 256 +#define MAXNAMELEN 256 +#define MAXPATHLEN 4096 +#define MAXOFFSET_T LLONG_MAX +#define MAXBSIZE 8192 +#define DEV_BSIZE 512 +#define DEV_BSHIFT 9 /* log2(DEV_BSIZE) */ + +#define proc_pageout NULL +#define curproc current +#define max_ncpus num_possible_cpus() +#define boot_ncpus num_online_cpus() +#define CPU_SEQID smp_processor_id() +#define is_system_labeled() 0 + +#ifndef RLIM64_INFINITY +#define RLIM64_INFINITY (~0ULL) +#endif + +/* + * 0..MAX_PRIO-1: Process priority + * 0..MAX_RT_PRIO-1: RT priority tasks + * MAX_RT_PRIO..MAX_PRIO-1: SCHED_NORMAL tasks + * + * Treat shim tasks as SCHED_NORMAL tasks + */ +#define minclsyspri (MAX_PRIO-1) +#define maxclsyspri (MAX_RT_PRIO) +#define defclsyspri (DEFAULT_PRIO) + +#ifndef NICE_TO_PRIO +#define NICE_TO_PRIO(nice) (MAX_RT_PRIO + (nice) + 20) +#endif +#ifndef PRIO_TO_NICE +#define PRIO_TO_NICE(prio) ((prio) - MAX_RT_PRIO - 20) +#endif + +/* + * Missing macros + */ +#ifndef PAGESIZE +#define PAGESIZE PAGE_SIZE +#endif + +#ifndef PAGESHIFT +#define PAGESHIFT PAGE_SHIFT +#endif + +/* Missing globals */ +extern char spl_gitrev[64]; +extern unsigned long spl_hostid; + +/* Missing misc functions */ +extern uint32_t zone_get_hostid(void *zone); +extern void spl_setup(void); +extern void spl_cleanup(void); + +#define highbit(x) __fls(x) +#define lowbit(x) __ffs(x) + +#define highbit64(x) fls64(x) +#define makedevice(maj, min) makedev(maj, min) + +/* common macros */ +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif +#ifndef MAX +#define MAX(a, b) ((a) < (b) ? (b) : (a)) +#endif +#ifndef ABS +#define ABS(a) ((a) < 0 ? -(a) : (a)) +#endif +#ifndef DIV_ROUND_UP +#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) +#endif +#ifndef roundup +#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) +#endif +#ifndef howmany +#define howmany(x, y) (((x) + ((y) - 1)) / (y)) +#endif + +/* + * Compatibility macros/typedefs needed for Solaris -> Linux port + */ +#define P2ALIGN(x, align) ((x) & -(align)) +#define P2CROSS(x, y, align) (((x) ^ (y)) > (align) - 1) +#define P2ROUNDUP(x, align) ((((x) - 1) | ((align) - 1)) + 1) +#define P2PHASE(x, align) ((x) & ((align) - 1)) +#define P2NPHASE(x, align) (-(x) & ((align) - 1)) +#define ISP2(x) (((x) & ((x) - 1)) == 0) +#define IS_P2ALIGNED(v, a) ((((uintptr_t)(v)) & ((uintptr_t)(a) - 1)) == 0) +#define P2BOUNDARY(off, len, align) \ + (((off) ^ ((off) + (len) - 1)) > (align) - 1) + +/* + * Typed version of the P2* macros. These macros should be used to ensure + * that the result is correctly calculated based on the data type of (x), + * which is passed in as the last argument, regardless of the data + * type of the alignment. For example, if (x) is of type uint64_t, + * and we want to round it up to a page boundary using "PAGESIZE" as + * the alignment, we can do either + * + * P2ROUNDUP(x, (uint64_t)PAGESIZE) + * or + * P2ROUNDUP_TYPED(x, PAGESIZE, uint64_t) + */ +#define P2ALIGN_TYPED(x, align, type) \ + ((type)(x) & -(type)(align)) +#define P2PHASE_TYPED(x, align, type) \ + ((type)(x) & ((type)(align) - 1)) +#define P2NPHASE_TYPED(x, align, type) \ + (-(type)(x) & ((type)(align) - 1)) +#define P2ROUNDUP_TYPED(x, align, type) \ + ((((type)(x) - 1) | ((type)(align) - 1)) + 1) +#define P2END_TYPED(x, align, type) \ + (-(~(type)(x) & -(type)(align))) +#define P2PHASEUP_TYPED(x, align, phase, type) \ + ((type)(phase) - (((type)(phase) - (type)(x)) & -(type)(align))) +#define P2CROSS_TYPED(x, y, align, type) \ + (((type)(x) ^ (type)(y)) > (type)(align) - 1) +#define P2SAMEHIGHBIT_TYPED(x, y, type) \ + (((type)(x) ^ (type)(y)) < ((type)(x) & (type)(y))) + +#define SET_ERROR(err) \ + (__set_error(__FILE__, __func__, __LINE__, err), err) + +#include <linux/sort.h> +#define qsort(base, num, size, cmp) \ + sort(base, num, size, cmp, NULL) + +#if !defined(_KMEMUSER) && !defined(offsetof) + +/* avoid any possibility of clashing with <stddef.h> version */ + +#define offsetof(s, m) ((size_t)(&(((s *)0)->m))) +#endif + +#endif /* _SPL_SYSMACROS_H */ diff --git a/include/os/linux/spl/sys/systeminfo.h b/include/os/linux/spl/sys/systeminfo.h new file mode 100644 index 000000000000..2255691580f9 --- /dev/null +++ b/include/os/linux/spl/sys/systeminfo.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_SYSTEMINFO_H +#define _SPL_SYSTEMINFO_H + +#define HW_HOSTID_LEN 11 /* minimum buffer size needed */ + /* to hold a decimal or hex */ + /* hostid string */ + +/* Supplemental definitions for Linux. */ +#define HW_HOSTID_PATH "/etc/hostid" /* binary configuration file */ +#define HW_HOSTID_MASK 0xFFFFFFFF /* significant hostid bits */ + +#endif /* SPL_SYSTEMINFO_H */ diff --git a/include/os/linux/spl/sys/taskq.h b/include/os/linux/spl/sys/taskq.h new file mode 100644 index 000000000000..7a1ee9ec4f1b --- /dev/null +++ b/include/os/linux/spl/sys/taskq.h @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_TASKQ_H +#define _SPL_TASKQ_H + +#include <linux/module.h> +#include <linux/gfp.h> +#include <linux/slab.h> +#include <linux/interrupt.h> +#include <linux/kthread.h> +#include <sys/types.h> +#include <sys/thread.h> +#include <sys/rwlock.h> +#include <sys/wait.h> + +#define TASKQ_NAMELEN 31 + +#define TASKQ_PREPOPULATE 0x00000001 +#define TASKQ_CPR_SAFE 0x00000002 +#define TASKQ_DYNAMIC 0x00000004 +#define TASKQ_THREADS_CPU_PCT 0x00000008 +#define TASKQ_DC_BATCH 0x00000010 +#define TASKQ_ACTIVE 0x80000000 + +/* + * Flags for taskq_dispatch. TQ_SLEEP/TQ_NOSLEEP should be same as + * KM_SLEEP/KM_NOSLEEP. TQ_NOQUEUE/TQ_NOALLOC are set particularly + * large so as not to conflict with already used GFP_* defines. + */ +#define TQ_SLEEP 0x00000000 +#define TQ_NOSLEEP 0x00000001 +#define TQ_PUSHPAGE 0x00000002 +#define TQ_NOQUEUE 0x01000000 +#define TQ_NOALLOC 0x02000000 +#define TQ_NEW 0x04000000 +#define TQ_FRONT 0x08000000 + +/* + * Reserved taskqid values. + */ +#define TASKQID_INVALID ((taskqid_t)0) +#define TASKQID_INITIAL ((taskqid_t)1) + +/* + * spin_lock(lock) and spin_lock_nested(lock,0) are equivalent, + * so TQ_LOCK_DYNAMIC must not evaluate to 0 + */ +typedef enum tq_lock_role { + TQ_LOCK_GENERAL = 0, + TQ_LOCK_DYNAMIC = 1, +} tq_lock_role_t; + +typedef unsigned long taskqid_t; +typedef void (task_func_t)(void *); + +typedef struct taskq { + spinlock_t tq_lock; /* protects taskq_t */ + char *tq_name; /* taskq name */ + int tq_instance; /* instance of tq_name */ + struct list_head tq_thread_list; /* list of all threads */ + struct list_head tq_active_list; /* list of active threads */ + int tq_nactive; /* # of active threads */ + int tq_nthreads; /* # of existing threads */ + int tq_nspawn; /* # of threads being spawned */ + int tq_maxthreads; /* # of threads maximum */ + int tq_pri; /* priority */ + int tq_minalloc; /* min taskq_ent_t pool size */ + int tq_maxalloc; /* max taskq_ent_t pool size */ + int tq_nalloc; /* cur taskq_ent_t pool size */ + uint_t tq_flags; /* flags */ + taskqid_t tq_next_id; /* next pend/work id */ + taskqid_t tq_lowest_id; /* lowest pend/work id */ + struct list_head tq_free_list; /* free taskq_ent_t's */ + struct list_head tq_pend_list; /* pending taskq_ent_t's */ + struct list_head tq_prio_list; /* priority taskq_ent_t's */ + struct list_head tq_delay_list; /* delayed taskq_ent_t's */ + struct list_head tq_taskqs; /* all taskq_t's */ + spl_wait_queue_head_t tq_work_waitq; /* new work waitq */ + spl_wait_queue_head_t tq_wait_waitq; /* wait waitq */ + tq_lock_role_t tq_lock_class; /* class when taking tq_lock */ +} taskq_t; + +typedef struct taskq_ent { + spinlock_t tqent_lock; + spl_wait_queue_head_t tqent_waitq; + struct timer_list tqent_timer; + struct list_head tqent_list; + taskqid_t tqent_id; + task_func_t *tqent_func; + void *tqent_arg; + taskq_t *tqent_taskq; + uintptr_t tqent_flags; + unsigned long tqent_birth; +} taskq_ent_t; + +#define TQENT_FLAG_PREALLOC 0x1 +#define TQENT_FLAG_CANCEL 0x2 + +typedef struct taskq_thread { + struct list_head tqt_thread_list; + struct list_head tqt_active_list; + struct task_struct *tqt_thread; + taskq_t *tqt_tq; + taskqid_t tqt_id; + taskq_ent_t *tqt_task; + uintptr_t tqt_flags; +} taskq_thread_t; + +/* Global system-wide dynamic task queue available for all consumers */ +extern taskq_t *system_taskq; +/* Global dynamic task queue for long delay */ +extern taskq_t *system_delay_taskq; + +/* List of all taskqs */ +extern struct list_head tq_list; +extern struct rw_semaphore tq_list_sem; + +extern taskqid_t taskq_dispatch(taskq_t *, task_func_t, void *, uint_t); +extern taskqid_t taskq_dispatch_delay(taskq_t *, task_func_t, void *, + uint_t, clock_t); +extern void taskq_dispatch_ent(taskq_t *, task_func_t, void *, uint_t, + taskq_ent_t *); +extern int taskq_empty_ent(taskq_ent_t *); +extern void taskq_init_ent(taskq_ent_t *); +extern taskq_t *taskq_create(const char *, int, pri_t, int, int, uint_t); +extern void taskq_destroy(taskq_t *); +extern void taskq_wait_id(taskq_t *, taskqid_t); +extern void taskq_wait_outstanding(taskq_t *, taskqid_t); +extern void taskq_wait(taskq_t *); +extern int taskq_cancel_id(taskq_t *, taskqid_t); +extern int taskq_member(taskq_t *, kthread_t *); +extern taskq_t *taskq_of_curthread(void); + +#define taskq_create_proc(name, nthreads, pri, min, max, proc, flags) \ + taskq_create(name, nthreads, pri, min, max, flags) +#define taskq_create_sysdc(name, nthreads, min, max, proc, dc, flags) \ + taskq_create(name, nthreads, maxclsyspri, min, max, flags) + +int spl_taskq_init(void); +void spl_taskq_fini(void); + +#endif /* _SPL_TASKQ_H */ diff --git a/include/os/linux/spl/sys/thread.h b/include/os/linux/spl/sys/thread.h new file mode 100644 index 000000000000..72dcf9f05d0d --- /dev/null +++ b/include/os/linux/spl/sys/thread.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_THREAD_H +#define _SPL_THREAD_H + +#include <linux/module.h> +#include <linux/mm.h> +#include <linux/spinlock.h> +#include <linux/kthread.h> +#include <sys/types.h> +#include <sys/sysmacros.h> +#include <sys/tsd.h> + +/* + * Thread interfaces + */ +#define TP_MAGIC 0x53535353 + +#define TS_SLEEP TASK_INTERRUPTIBLE +#define TS_RUN TASK_RUNNING +#define TS_ZOMB EXIT_ZOMBIE +#define TS_STOPPED TASK_STOPPED + +typedef void (*thread_func_t)(void *); + +#define thread_create_named(name, stk, stksize, func, arg, len, \ + pp, state, pri) \ + __thread_create(stk, stksize, (thread_func_t)func, \ + name, arg, len, pp, state, pri) + +/* BEGIN CSTYLED */ +#define thread_create(stk, stksize, func, arg, len, pp, state, pri) \ + __thread_create(stk, stksize, (thread_func_t)func, \ + #func, arg, len, pp, state, pri) +/* END CSTYLED */ + +#define thread_exit() __thread_exit() +#define thread_join(t) VERIFY(0) +#define curthread current +#define getcomm() current->comm +#define getpid() current->pid + +extern kthread_t *__thread_create(caddr_t stk, size_t stksize, + thread_func_t func, const char *name, void *args, size_t len, proc_t *pp, + int state, pri_t pri); +extern void __thread_exit(void); +extern struct task_struct *spl_kthread_create(int (*func)(void *), + void *data, const char namefmt[], ...); + +extern proc_t p0; + +#endif /* _SPL_THREAD_H */ diff --git a/include/os/linux/spl/sys/time.h b/include/os/linux/spl/sys/time.h new file mode 100644 index 000000000000..4309c300b268 --- /dev/null +++ b/include/os/linux/spl/sys/time.h @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_TIME_H +#define _SPL_TIME_H + +#include <linux/module.h> +#include <linux/time.h> +#include <sys/types.h> +#include <sys/timer.h> + +#if defined(CONFIG_64BIT) +#define TIME_MAX INT64_MAX +#define TIME_MIN INT64_MIN +#else +#define TIME_MAX INT32_MAX +#define TIME_MIN INT32_MIN +#endif + +#define SEC 1 +#define MILLISEC 1000 +#define MICROSEC 1000000 +#define NANOSEC 1000000000 + +#define MSEC2NSEC(m) ((hrtime_t)(m) * (NANOSEC / MILLISEC)) +#define NSEC2MSEC(n) ((n) / (NANOSEC / MILLISEC)) + +#define USEC2NSEC(m) ((hrtime_t)(m) * (NANOSEC / MICROSEC)) +#define NSEC2USEC(n) ((n) / (NANOSEC / MICROSEC)) + +#define NSEC2SEC(n) ((n) / (NANOSEC / SEC)) +#define SEC2NSEC(m) ((hrtime_t)(m) * (NANOSEC / SEC)) + +static const int hz = HZ; + +typedef longlong_t hrtime_t; +typedef struct timespec timespec_t; + +#define TIMESPEC_OVERFLOW(ts) \ + ((ts)->tv_sec < TIME_MIN || (ts)->tv_sec > TIME_MAX) + +#if defined(HAVE_INODE_TIMESPEC64_TIMES) +typedef struct timespec64 inode_timespec_t; +#else +typedef struct timespec inode_timespec_t; +#endif + +/* Include for Lustre compatibility */ +#define timestruc_t inode_timespec_t + +static inline void +gethrestime(inode_timespec_t *ts) +{ +#if defined(HAVE_INODE_TIMESPEC64_TIMES) + +#if defined(HAVE_KTIME_GET_COARSE_REAL_TS64) + ktime_get_coarse_real_ts64(ts); +#else + *ts = current_kernel_time64(); +#endif /* HAVE_KTIME_GET_COARSE_REAL_TS64 */ + +#else + *ts = current_kernel_time(); +#endif +} + +static inline uint64_t +gethrestime_sec(void) +{ +#if defined(HAVE_INODE_TIMESPEC64_TIMES) +#if defined(HAVE_KTIME_GET_COARSE_REAL_TS64) + inode_timespec_t ts; + ktime_get_coarse_real_ts64(&ts); +#else + inode_timespec_t ts = current_kernel_time64(); +#endif /* HAVE_KTIME_GET_COARSE_REAL_TS64 */ + +#else + inode_timespec_t ts = current_kernel_time(); +#endif + return (ts.tv_sec); +} + +static inline hrtime_t +gethrtime(void) +{ +#if defined(HAVE_KTIME_GET_RAW_TS64) + struct timespec64 ts; + ktime_get_raw_ts64(&ts); +#else + struct timespec ts; + getrawmonotonic(&ts); +#endif + return (((hrtime_t)ts.tv_sec * NSEC_PER_SEC) + ts.tv_nsec); +} + +#endif /* _SPL_TIME_H */ diff --git a/include/os/linux/spl/sys/timer.h b/include/os/linux/spl/sys/timer.h new file mode 100644 index 000000000000..40be12047ae4 --- /dev/null +++ b/include/os/linux/spl/sys/timer.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_TIMER_H +#define _SPL_TIMER_H + +#include <linux/module.h> +#include <linux/delay.h> +#include <linux/sched.h> +#include <linux/time.h> +#include <linux/timer.h> + +#define lbolt ((clock_t)jiffies) +#define lbolt64 ((int64_t)get_jiffies_64()) + +#define ddi_get_lbolt() ((clock_t)jiffies) +#define ddi_get_lbolt64() ((int64_t)get_jiffies_64()) + +#define ddi_time_before(a, b) (typecheck(clock_t, a) && \ + typecheck(clock_t, b) && \ + ((a) - (b) < 0)) +#define ddi_time_after(a, b) ddi_time_before(b, a) +#define ddi_time_before_eq(a, b) (!ddi_time_after(a, b)) +#define ddi_time_after_eq(a, b) ddi_time_before_eq(b, a) + +#define ddi_time_before64(a, b) (typecheck(int64_t, a) && \ + typecheck(int64_t, b) && \ + ((a) - (b) < 0)) +#define ddi_time_after64(a, b) ddi_time_before64(b, a) +#define ddi_time_before_eq64(a, b) (!ddi_time_after64(a, b)) +#define ddi_time_after_eq64(a, b) ddi_time_before_eq64(b, a) + +#define delay(ticks) schedule_timeout_uninterruptible(ticks) + +#define SEC_TO_TICK(sec) ((sec) * HZ) +#define MSEC_TO_TICK(ms) msecs_to_jiffies(ms) +#define USEC_TO_TICK(us) usecs_to_jiffies(us) +#define NSEC_TO_TICK(ns) usecs_to_jiffies(ns / NSEC_PER_USEC) + +#ifndef from_timer +#define from_timer(var, timer, timer_field) \ + container_of(timer, typeof(*var), timer_field) +#endif + +#ifdef HAVE_KERNEL_TIMER_FUNCTION_TIMER_LIST +typedef struct timer_list *spl_timer_list_t; +#else +typedef unsigned long spl_timer_list_t; +#endif + +#ifndef HAVE_KERNEL_TIMER_SETUP + +static inline void +timer_setup(struct timer_list *timer, void (*func)(spl_timer_list_t), u32 fl) +{ +#ifdef HAVE_KERNEL_TIMER_LIST_FLAGS + (timer)->flags = fl; +#endif + init_timer(timer); + setup_timer(timer, func, (spl_timer_list_t)(timer)); +} + +#endif /* HAVE_KERNEL_TIMER_SETUP */ + +#endif /* _SPL_TIMER_H */ diff --git a/include/os/linux/spl/sys/trace.h b/include/os/linux/spl/sys/trace.h new file mode 100644 index 000000000000..b148ace6abd3 --- /dev/null +++ b/include/os/linux/spl/sys/trace.h @@ -0,0 +1,175 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +#if defined(_KERNEL) + +/* + * Calls to DTRACE_PROBE* are mapped to standard Linux kernel trace points + * when they are available(when HAVE_DECLARE_EVENT_CLASS is defined). The + * tracepoint event class definitions are found in the general tracing + * header file: include/sys/trace_*.h. See include/sys/trace_vdev.h for + * a good example. + * + * If tracepoints are not available, stub functions are generated which can + * be traced using kprobes. In this case, the DEFINE_DTRACE_PROBE* macros + * are used to provide the stub functions and also the prototypes for + * those functions. The mechanism to do this relies on DEFINE_DTRACE_PROBE + * macros defined in the general tracing headers(see trace_vdev.h) and + * CREATE_TRACE_POINTS being defined only in module/zfs/trace.c. When ZFS + * source files include the general tracing headers, e.g. + * module/zfs/vdev_removal.c including trace_vdev.h, DTRACE_PROBE calls + * are mapped to stub functions calls and prototypes for those calls are + * declared via DEFINE_DTRACE_PROBE*. Only module/zfs/trace.c defines + * CREATE_TRACE_POINTS. That is followed by includes of all the general + * tracing headers thereby defining all stub functions in one place via + * the DEFINE_DTRACE_PROBE macros. + * + * When adding new DTRACE_PROBEs to zfs source, both a tracepoint event + * class definition and a DEFINE_DTRACE_PROBE definition are needed to + * avoid undefined function errors. + */ + +#if defined(HAVE_DECLARE_EVENT_CLASS) + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM zfs + +#if !defined(_TRACE_ZFS_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_ZFS_H + +#include <linux/tracepoint.h> +#include <sys/types.h> + +/* + * DTRACE_PROBE with 0 arguments is not currently available with + * tracepoint events + */ +#define DTRACE_PROBE(name) \ + ((void)0) + +#define DTRACE_PROBE1(name, t1, arg1) \ + trace_zfs_##name((arg1)) + +#define DTRACE_PROBE2(name, t1, arg1, t2, arg2) \ + trace_zfs_##name((arg1), (arg2)) + +#define DTRACE_PROBE3(name, t1, arg1, t2, arg2, t3, arg3) \ + trace_zfs_##name((arg1), (arg2), (arg3)) + +#define DTRACE_PROBE4(name, t1, arg1, t2, arg2, t3, arg3, t4, arg4) \ + trace_zfs_##name((arg1), (arg2), (arg3), (arg4)) + +#endif /* _TRACE_ZFS_H */ + +#undef TRACE_INCLUDE_PATH +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_PATH sys +#define TRACE_INCLUDE_FILE trace +#include <trace/define_trace.h> + +#else /* HAVE_DECLARE_EVENT_CLASS */ + +#define DTRACE_PROBE(name) \ + trace_zfs_##name() + +#define DTRACE_PROBE1(name, t1, arg1) \ + trace_zfs_##name((uintptr_t)(arg1)) + +#define DTRACE_PROBE2(name, t1, arg1, t2, arg2) \ + trace_zfs_##name((uintptr_t)(arg1), (uintptr_t)(arg2)) + +#define DTRACE_PROBE3(name, t1, arg1, t2, arg2, t3, arg3) \ + trace_zfs_##name((uintptr_t)(arg1), (uintptr_t)(arg2), \ + (uintptr_t)(arg3)) + +#define DTRACE_PROBE4(name, t1, arg1, t2, arg2, t3, arg3, t4, arg4) \ + trace_zfs_##name((uintptr_t)(arg1), (uintptr_t)(arg2), \ + (uintptr_t)(arg3), (uintptr_t)(arg4)) + +#define PROTO_DTRACE_PROBE(name) \ + noinline void trace_zfs_##name(void) +#define PROTO_DTRACE_PROBE1(name) \ + noinline void trace_zfs_##name(uintptr_t) +#define PROTO_DTRACE_PROBE2(name) \ + noinline void trace_zfs_##name(uintptr_t, uintptr_t) +#define PROTO_DTRACE_PROBE3(name) \ + noinline void trace_zfs_##name(uintptr_t, uintptr_t, \ + uintptr_t) +#define PROTO_DTRACE_PROBE4(name) \ + noinline void trace_zfs_##name(uintptr_t, uintptr_t, \ + uintptr_t, uintptr_t) + +#if defined(CREATE_TRACE_POINTS) + +#define FUNC_DTRACE_PROBE(name) \ +PROTO_DTRACE_PROBE(name); \ +noinline void trace_zfs_##name(void) { } \ +EXPORT_SYMBOL(trace_zfs_##name) + +#define FUNC_DTRACE_PROBE1(name) \ +PROTO_DTRACE_PROBE1(name); \ +noinline void trace_zfs_##name(uintptr_t arg1) { } \ +EXPORT_SYMBOL(trace_zfs_##name) + +#define FUNC_DTRACE_PROBE2(name) \ +PROTO_DTRACE_PROBE2(name); \ +noinline void trace_zfs_##name(uintptr_t arg1, \ + uintptr_t arg2) { } \ +EXPORT_SYMBOL(trace_zfs_##name) + +#define FUNC_DTRACE_PROBE3(name) \ +PROTO_DTRACE_PROBE3(name); \ +noinline void trace_zfs_##name(uintptr_t arg1, \ + uintptr_t arg2, uintptr_t arg3) { } \ +EXPORT_SYMBOL(trace_zfs_##name) + +#define FUNC_DTRACE_PROBE4(name) \ +PROTO_DTRACE_PROBE4(name); \ +noinline void trace_zfs_##name(uintptr_t arg1, \ + uintptr_t arg2, uintptr_t arg3, uintptr_t arg4) { } \ +EXPORT_SYMBOL(trace_zfs_##name) + +#undef DEFINE_DTRACE_PROBE +#define DEFINE_DTRACE_PROBE(name) FUNC_DTRACE_PROBE(name) + +#undef DEFINE_DTRACE_PROBE1 +#define DEFINE_DTRACE_PROBE1(name) FUNC_DTRACE_PROBE1(name) + +#undef DEFINE_DTRACE_PROBE2 +#define DEFINE_DTRACE_PROBE2(name) FUNC_DTRACE_PROBE2(name) + +#undef DEFINE_DTRACE_PROBE3 +#define DEFINE_DTRACE_PROBE3(name) FUNC_DTRACE_PROBE3(name) + +#undef DEFINE_DTRACE_PROBE4 +#define DEFINE_DTRACE_PROBE4(name) FUNC_DTRACE_PROBE4(name) + +#else /* CREATE_TRACE_POINTS */ + +#define DEFINE_DTRACE_PROBE(name) PROTO_DTRACE_PROBE(name) +#define DEFINE_DTRACE_PROBE1(name) PROTO_DTRACE_PROBE1(name) +#define DEFINE_DTRACE_PROBE2(name) PROTO_DTRACE_PROBE2(name) +#define DEFINE_DTRACE_PROBE3(name) PROTO_DTRACE_PROBE3(name) +#define DEFINE_DTRACE_PROBE4(name) PROTO_DTRACE_PROBE4(name) + +#endif /* CREATE_TRACE_POINTS */ +#endif /* HAVE_DECLARE_EVENT_CLASS */ +#endif /* _KERNEL */ diff --git a/include/os/linux/spl/sys/trace_spl.h b/include/os/linux/spl/sys/trace_spl.h new file mode 100644 index 000000000000..bffd91d9129b --- /dev/null +++ b/include/os/linux/spl/sys/trace_spl.h @@ -0,0 +1,30 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +#ifndef _OS_LINUX_SPL_TRACE_H +#define _OS_LINUX_SPL_TRACE_H + +#include <sys/taskq.h> + +#include <sys/trace.h> +#include <sys/trace_taskq.h> + +#endif diff --git a/include/os/linux/spl/sys/trace_taskq.h b/include/os/linux/spl/sys/trace_taskq.h new file mode 100644 index 000000000000..dbbb3c4c7960 --- /dev/null +++ b/include/os/linux/spl/sys/trace_taskq.h @@ -0,0 +1,89 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +#if defined(_KERNEL) +#if defined(HAVE_DECLARE_EVENT_CLASS) + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM zfs + +#undef TRACE_SYSTEM_VAR +#define TRACE_SYSTEM_VAR zfs_taskq + +#if !defined(_TRACE_TASKQ_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_TASKQ_H + +#include <linux/tracepoint.h> +#include <sys/types.h> + +/* + * Generic support for single argument tracepoints of the form: + * + * DTRACE_PROBE1(..., + * taskq_ent_t *, ...); + */ +/* BEGIN CSTYLED */ +DECLARE_EVENT_CLASS(zfs_taskq_ent_class, + TP_PROTO(taskq_ent_t *taskq_ent), + TP_ARGS(taskq_ent), + TP_STRUCT__entry( + __field(taskq_ent_t *, taskq_ent) + ), + TP_fast_assign( + __entry->taskq_ent = taskq_ent; + ), + TP_printk("taskq_ent %p", __entry->taskq_ent) +); +/* END CSTYLED */ + +/* BEGIN CSTYLED */ +#define DEFINE_TASKQ_EVENT(name) \ +DEFINE_EVENT(zfs_taskq_ent_class, name, \ + TP_PROTO(taskq_ent_t *taskq_ent), \ + TP_ARGS(taskq_ent)) +/* END CSTYLED */ +DEFINE_TASKQ_EVENT(zfs_taskq_ent__birth); +DEFINE_TASKQ_EVENT(zfs_taskq_ent__start); +DEFINE_TASKQ_EVENT(zfs_taskq_ent__finish); + +#endif /* _TRACE_TASKQ_H */ + +#undef TRACE_INCLUDE_PATH +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_PATH sys +#define TRACE_INCLUDE_FILE trace_taskq +#include <trace/define_trace.h> + +#else + +/* + * When tracepoints are not available, a DEFINE_DTRACE_PROBE* macro is + * needed for each DTRACE_PROBE. These will be used to generate stub + * tracing functions and prototypes for those functions. See + * include/os/linux/spl/sys/trace.h. + */ + +DEFINE_DTRACE_PROBE1(taskq_ent__birth); +DEFINE_DTRACE_PROBE1(taskq_ent__start); +DEFINE_DTRACE_PROBE1(taskq_ent__finish); + +#endif /* HAVE_DECLARE_EVENT_CLASS */ +#endif /* _KERNEL */ diff --git a/include/os/linux/spl/sys/tsd.h b/include/os/linux/spl/sys/tsd.h new file mode 100644 index 000000000000..39a291bf3dee --- /dev/null +++ b/include/os/linux/spl/sys/tsd.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2010 Lawrence Livermore National Security, LLC. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_TSD_H +#define _SPL_TSD_H + +#include <sys/types.h> + +#define TSD_HASH_TABLE_BITS_DEFAULT 9 +#define TSD_KEYS_MAX 32768 +#define DTOR_PID (PID_MAX_LIMIT+1) +#define PID_KEY (TSD_KEYS_MAX+1) + +typedef void (*dtor_func_t)(void *); + +extern int tsd_set(uint_t, void *); +extern void *tsd_get(uint_t); +extern void *tsd_get_by_thread(uint_t, kthread_t *); +extern void tsd_create(uint_t *, dtor_func_t); +extern void tsd_destroy(uint_t *); +extern void tsd_exit(void); + +int spl_tsd_init(void); +void spl_tsd_fini(void); + +#endif /* _SPL_TSD_H */ diff --git a/include/os/linux/spl/sys/types.h b/include/os/linux/spl/sys/types.h new file mode 100644 index 000000000000..719a44646e6b --- /dev/null +++ b/include/os/linux/spl/sys/types.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_TYPES_H +#define _SPL_TYPES_H + +#include <linux/types.h> + +typedef enum { + B_FALSE = 0, + B_TRUE = 1 +} boolean_t; + +typedef unsigned char uchar_t; +typedef unsigned short ushort_t; +typedef unsigned int uint_t; +typedef unsigned long ulong_t; +typedef unsigned long long u_longlong_t; +typedef long long longlong_t; + +typedef unsigned long intptr_t; +typedef unsigned long long rlim64_t; + +typedef struct task_struct kthread_t; +typedef struct task_struct proc_t; + +typedef int id_t; +typedef short pri_t; +typedef short index_t; +typedef longlong_t offset_t; +typedef u_longlong_t u_offset_t; +typedef ulong_t pgcnt_t; + +typedef int major_t; +typedef int minor_t; + +#endif /* _SPL_TYPES_H */ diff --git a/include/os/linux/spl/sys/types32.h b/include/os/linux/spl/sys/types32.h new file mode 100644 index 000000000000..c60ba8c97019 --- /dev/null +++ b/include/os/linux/spl/sys/types32.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_TYPES32_H +#define _SPL_TYPES32_H + +#include <sys/types.h> + +typedef uint32_t caddr32_t; +typedef int32_t daddr32_t; +typedef int32_t time32_t; +typedef uint32_t size32_t; + +#endif /* _SPL_TYPES32_H */ diff --git a/include/os/linux/spl/sys/uio.h b/include/os/linux/spl/sys/uio.h new file mode 100644 index 000000000000..0e631d6779a2 --- /dev/null +++ b/include/os/linux/spl/sys/uio.h @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Copyright (c) 2015 by Chunwei Chen. All rights reserved. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_UIO_H +#define _SPL_UIO_H + +#include <sys/debug.h> +#include <linux/uio.h> +#include <linux/blkdev.h> +#include <linux/blkdev_compat.h> +#include <linux/mm.h> +#include <linux/bio.h> +#include <asm/uaccess.h> +#include <sys/types.h> + +typedef struct iovec iovec_t; + +typedef enum uio_rw { + UIO_READ = 0, + UIO_WRITE = 1, +} uio_rw_t; + +typedef enum uio_seg { + UIO_USERSPACE = 0, + UIO_SYSSPACE = 1, + UIO_USERISPACE = 2, + UIO_BVEC = 3, +} uio_seg_t; + +typedef struct uio { + union { + const struct iovec *uio_iov; + const struct bio_vec *uio_bvec; + }; + int uio_iovcnt; + offset_t uio_loffset; + uio_seg_t uio_segflg; + boolean_t uio_fault_disable; + uint16_t uio_fmode; + uint16_t uio_extflg; + offset_t uio_limit; + ssize_t uio_resid; + size_t uio_skip; +} uio_t; + +typedef struct aio_req { + uio_t *aio_uio; + void *aio_private; +} aio_req_t; + +typedef enum xuio_type { + UIOTYPE_ASYNCIO, + UIOTYPE_ZEROCOPY, +} xuio_type_t; + + +#define UIOA_IOV_MAX 16 + +typedef struct uioa_page_s { + int uioa_pfncnt; + void **uioa_ppp; + caddr_t uioa_base; + size_t uioa_len; +} uioa_page_t; + +typedef struct xuio { + uio_t xu_uio; + enum xuio_type xu_type; + union { + struct { + uint32_t xu_a_state; + ssize_t xu_a_mbytes; + uioa_page_t *xu_a_lcur; + void **xu_a_lppp; + void *xu_a_hwst[4]; + uioa_page_t xu_a_locked[UIOA_IOV_MAX]; + } xu_aio; + + struct { + int xu_zc_rw; + void *xu_zc_priv; + } xu_zc; + } xu_ext; +} xuio_t; + +#define XUIO_XUZC_PRIV(xuio) xuio->xu_ext.xu_zc.xu_zc_priv +#define XUIO_XUZC_RW(xuio) xuio->xu_ext.xu_zc.xu_zc_rw + +#define uio_segflg(uio) (uio)->uio_segflg +#define uio_offset(uio) (uio)->uio_loffset +#define uio_resid(uio) (uio)->uio_resid +#define uio_iovcnt(uio) (uio)->uio_iovcnt +#define uio_iovlen(uio, idx) (uio)->uio_iov[(idx)].iov_len +#define uio_iovbase(uio, idx) (uio)->uio_iov[(idx)].iov_base + +static inline void +uio_iov_at_index(uio_t *uio, uint_t idx, void **base, uint64_t *len) +{ + *base = uio_iovbase(uio, idx); + *len = uio_iovlen(uio, idx); +} + +static inline void +uio_advance(uio_t *uio, size_t size) +{ + uio->uio_resid -= size; + uio->uio_loffset += size; +} + +static inline offset_t +uio_index_at_offset(uio_t *uio, offset_t off, uint_t *vec_idx) +{ + *vec_idx = 0; + while (*vec_idx < uio_iovcnt(uio) && off >= uio_iovlen(uio, *vec_idx)) { + off -= uio_iovlen(uio, *vec_idx); + (*vec_idx)++; + } + + return (off); +} + +#endif /* SPL_UIO_H */ diff --git a/include/os/linux/spl/sys/user.h b/include/os/linux/spl/sys/user.h new file mode 100644 index 000000000000..b12cb240e39b --- /dev/null +++ b/include/os/linux/spl/sys/user.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2015 Cluster Inc. + * Produced at ClusterHQ Inc (cf, DISCLAIMER). + * Written by Richard Yao <richard.yao@clusterhq.com>. + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_USER_H +#define _SPL_USER_H + +/* + * We have uf_info_t for areleasef(). We implement areleasef() using a global + * linked list of all open file descriptors with the task structs referenced, + * so accessing the correct descriptor from areleasef() only requires knowing + * about the Linux task_struct. Since this is internal to our compatibility + * layer, we make it an opaque type. + * + * XXX: If the descriptor changes under us and we do not do a getf() between + * the change and using it, we would get an incorrect reference. + */ + +struct uf_info; +typedef struct uf_info uf_info_t; + +#define P_FINFO(x) ((uf_info_t *)x) + +#endif /* SPL_USER_H */ diff --git a/include/os/linux/spl/sys/vfs.h b/include/os/linux/spl/sys/vfs.h new file mode 100644 index 000000000000..0d5e1d51d7aa --- /dev/null +++ b/include/os/linux/spl/sys/vfs.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_ZFS_H +#define _SPL_ZFS_H + +#include <linux/mount.h> +#include <linux/fs.h> +#include <linux/dcache.h> +#include <linux/statfs.h> +#include <linux/xattr.h> +#include <linux/security.h> +#include <linux/seq_file.h> + +#define MAXFIDSZ 64 + +typedef struct spl_fid { + union { + long fid_pad; + struct { + ushort_t len; /* length of data in bytes */ + char data[MAXFIDSZ]; /* data (variable len) */ + } _fid; + } un; +} fid_t; + +#define fid_len un._fid.len +#define fid_data un._fid.data + +#endif /* SPL_ZFS_H */ diff --git a/include/os/linux/spl/sys/vmem.h b/include/os/linux/spl/sys/vmem.h new file mode 100644 index 000000000000..a31b4728c367 --- /dev/null +++ b/include/os/linux/spl/sys/vmem.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_VMEM_H +#define _SPL_VMEM_H + +#include <sys/kmem.h> +#include <linux/sched.h> +#include <linux/vmalloc.h> + +typedef struct vmem { } vmem_t; + +/* + * Memory allocation interfaces + */ +#define VMEM_ALLOC 0x01 +#define VMEM_FREE 0x02 + +#ifndef VMALLOC_TOTAL +#define VMALLOC_TOTAL (VMALLOC_END - VMALLOC_START) +#endif + +/* + * vmem_* is an interface to a low level arena-based memory allocator on + * Illumos that is used to allocate virtual address space. The kmem SLAB + * allocator allocates slabs from it. Then the generic allocation functions + * kmem_{alloc,zalloc,free}() are layered on top of SLAB allocators. + * + * On Linux, the primary means of doing allocations is via kmalloc(), which + * is similarly layered on top of something called the buddy allocator. The + * buddy allocator is not available to kernel modules, it uses physical + * memory addresses rather than virtual memory addresses and is prone to + * fragmentation. + * + * Linux sets aside a relatively small address space for in-kernel virtual + * memory from which allocations can be done using vmalloc(). It might seem + * like a good idea to use vmalloc() to implement something similar to + * Illumos' allocator. However, this has the following problems: + * + * 1. Page directory table allocations are hard coded to use GFP_KERNEL. + * Consequently, any KM_PUSHPAGE or KM_NOSLEEP allocations done using + * vmalloc() will not have proper semantics. + * + * 2. Address space exhaustion is a real issue on 32-bit platforms where + * only a few 100MB are available. The kernel will handle it by spinning + * when it runs out of address space. + * + * 3. All vmalloc() allocations and frees are protected by a single global + * lock which serializes all allocations. + * + * 4. Accessing /proc/meminfo and /proc/vmallocinfo will iterate the entire + * list. The former will sum the allocations while the latter will print + * them to user space in a way that user space can keep the lock held + * indefinitely. When the total number of mapped allocations is large + * (several 100,000) a large amount of time will be spent waiting on locks. + * + * 5. Linux has a wait_on_bit() locking primitive that assumes physical + * memory is used, it simply does not work on virtual memory. Certain + * Linux structures (e.g. the superblock) use them and might be embedded + * into a structure from Illumos. This makes using Linux virtual memory + * unsafe in certain situations. + * + * It follows that we cannot obtain identical semantics to those on Illumos. + * Consequently, we implement the kmem_{alloc,zalloc,free}() functions in + * such a way that they can be used as drop-in replacements for small vmem_* + * allocations (8MB in size or smaller) and map vmem_{alloc,zalloc,free}() + * to them. + */ + +#define vmem_alloc(sz, fl) spl_vmem_alloc((sz), (fl), __func__, __LINE__) +#define vmem_zalloc(sz, fl) spl_vmem_zalloc((sz), (fl), __func__, __LINE__) +#define vmem_free(ptr, sz) spl_vmem_free((ptr), (sz)) + +extern void *spl_vmem_alloc(size_t sz, int fl, const char *func, int line); +extern void *spl_vmem_zalloc(size_t sz, int fl, const char *func, int line); +extern void spl_vmem_free(const void *ptr, size_t sz); + +int spl_vmem_init(void); +void spl_vmem_fini(void); + +#endif /* _SPL_VMEM_H */ diff --git a/include/os/linux/spl/sys/vmsystm.h b/include/os/linux/spl/sys/vmsystm.h new file mode 100644 index 000000000000..705339486bc8 --- /dev/null +++ b/include/os/linux/spl/sys/vmsystm.h @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_VMSYSTM_H +#define _SPL_VMSYSTM_H + +#include <linux/mmzone.h> +#include <linux/mm.h> +#include <linux/swap.h> +#include <linux/highmem.h> +#include <linux/vmalloc.h> +#include <sys/types.h> +#include <asm/uaccess.h> + +#ifdef HAVE_TOTALRAM_PAGES_FUNC +#define zfs_totalram_pages totalram_pages() +#else +#define zfs_totalram_pages totalram_pages +#endif + +#ifdef HAVE_TOTALHIGH_PAGES +#define zfs_totalhigh_pages totalhigh_pages() +#else +#define zfs_totalhigh_pages totalhigh_pages +#endif + +#define membar_producer() smp_wmb() +#define physmem zfs_totalram_pages +#ifdef ZFS_ENUM_NODE_STAT_ITEM_NR_SLAB_RECLAIMABLE_B +#define freemem (nr_free_pages() + \ + global_page_state(NR_INACTIVE_FILE) + \ + global_page_state(NR_INACTIVE_ANON) + \ + global_page_state(NR_SLAB_RECLAIMABLE_B)) +#else +#define freemem (nr_free_pages() + \ + global_page_state(NR_INACTIVE_FILE) + \ + global_page_state(NR_INACTIVE_ANON) + \ + global_page_state(NR_SLAB_RECLAIMABLE)) +#endif /* ZFS_ENUM_NODE_STAT_ITEM_NR_SLAB_RECLAIMABLE_B */ + +#define xcopyin(from, to, size) copy_from_user(to, from, size) +#define xcopyout(from, to, size) copy_to_user(to, from, size) + +static __inline__ int +copyin(const void *from, void *to, size_t len) +{ + /* On error copyin routine returns -1 */ + if (xcopyin(from, to, len)) + return (-1); + + return (0); +} + +static __inline__ int +copyout(const void *from, void *to, size_t len) +{ + /* On error copyout routine returns -1 */ + if (xcopyout(from, to, len)) + return (-1); + + return (0); +} + +static __inline__ int +copyinstr(const void *from, void *to, size_t len, size_t *done) +{ + size_t rc; + + if (len == 0) + return (-ENAMETOOLONG); + + /* XXX: Should return ENAMETOOLONG if 'strlen(from) > len' */ + + memset(to, 0, len); + rc = copyin(from, to, len - 1); + if (done != NULL) + *done = rc; + + return (0); +} + +#endif /* SPL_VMSYSTM_H */ diff --git a/include/os/linux/spl/sys/vnode.h b/include/os/linux/spl/sys/vnode.h new file mode 100644 index 000000000000..07eac8e44173 --- /dev/null +++ b/include/os/linux/spl/sys/vnode.h @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_VNODE_H +#define _SPL_VNODE_H + +#include <linux/module.h> +#include <linux/syscalls.h> +#include <linux/fcntl.h> +#include <linux/buffer_head.h> +#include <linux/dcache.h> +#include <linux/namei.h> +#include <linux/file.h> +#include <linux/fs.h> +#include <linux/fs_struct.h> +#include <linux/mount.h> +#include <sys/kmem.h> +#include <sys/mutex.h> +#include <sys/types.h> +#include <sys/time.h> +#include <sys/uio.h> +#include <sys/user.h> + +/* + * Prior to linux-2.6.33 only O_DSYNC semantics were implemented and + * they used the O_SYNC flag. As of linux-2.6.33 the this behavior + * was properly split in to O_SYNC and O_DSYNC respectively. + */ +#ifndef O_DSYNC +#define O_DSYNC O_SYNC +#endif + +#define F_FREESP 11 /* Free file space */ + +/* + * The vnode AT_ flags are mapped to the Linux ATTR_* flags. + * This allows them to be used safely with an iattr structure. + * The AT_XVATTR flag has been added and mapped to the upper + * bit range to avoid conflicting with the standard Linux set. + */ +#undef AT_UID +#undef AT_GID + +#define AT_MODE ATTR_MODE +#define AT_UID ATTR_UID +#define AT_GID ATTR_GID +#define AT_SIZE ATTR_SIZE +#define AT_ATIME ATTR_ATIME +#define AT_MTIME ATTR_MTIME +#define AT_CTIME ATTR_CTIME + +#define ATTR_XVATTR (1U << 31) +#define AT_XVATTR ATTR_XVATTR + +#define ATTR_IATTR_MASK (ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_SIZE | \ + ATTR_ATIME | ATTR_MTIME | ATTR_CTIME | ATTR_FILE) + +#define CRCREAT 0x01 +#define RMFILE 0x02 + +#define B_INVAL 0x01 +#define B_TRUNC 0x02 + +#define LOOKUP_DIR 0x01 +#define LOOKUP_XATTR 0x02 +#define CREATE_XATTR_DIR 0x04 +#define ATTR_NOACLCHECK 0x20 + +typedef struct vattr { + uint32_t va_mask; /* attribute bit-mask */ + ushort_t va_mode; /* acc mode */ + uid_t va_uid; /* owner uid */ + gid_t va_gid; /* owner gid */ + long va_fsid; /* fs id */ + long va_nodeid; /* node # */ + uint32_t va_nlink; /* # links */ + uint64_t va_size; /* file size */ + inode_timespec_t va_atime; /* last acc */ + inode_timespec_t va_mtime; /* last mod */ + inode_timespec_t va_ctime; /* last chg */ + dev_t va_rdev; /* dev */ + uint64_t va_nblocks; /* space used */ + uint32_t va_blksize; /* block size */ + struct dentry *va_dentry; /* dentry to wire */ +} vattr_t; +#endif /* SPL_VNODE_H */ diff --git a/include/os/linux/spl/sys/wait.h b/include/os/linux/spl/sys/wait.h new file mode 100644 index 000000000000..5311ff8b971b --- /dev/null +++ b/include/os/linux/spl/sys/wait.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2007-2014 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_WAIT_H +#define _SPL_WAIT_H + +#include <linux/sched.h> +#include <linux/wait.h> + +#ifndef HAVE_WAIT_ON_BIT_ACTION +#define spl_wait_on_bit(word, bit, mode) wait_on_bit(word, bit, mode) +#else + +static inline int +spl_bit_wait(void *word) +{ + schedule(); + return (0); +} + +#define spl_wait_on_bit(word, bit, mode) \ + wait_on_bit(word, bit, spl_bit_wait, mode) + +#endif /* HAVE_WAIT_ON_BIT_ACTION */ + +#ifdef HAVE_WAIT_QUEUE_ENTRY_T +typedef wait_queue_head_t spl_wait_queue_head_t; +typedef wait_queue_entry_t spl_wait_queue_entry_t; +#else +typedef wait_queue_head_t spl_wait_queue_head_t; +typedef wait_queue_t spl_wait_queue_entry_t; +#endif + +#endif /* SPL_WAIT_H */ diff --git a/include/os/linux/spl/sys/zmod.h b/include/os/linux/spl/sys/zmod.h new file mode 100644 index 000000000000..5380bd6fd022 --- /dev/null +++ b/include/os/linux/spl/sys/zmod.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + * + * + * z_compress_level/z_uncompress are nearly identical copies of the + * compress2/uncompress functions provided by the official zlib package + * available at http://zlib.net/. The only changes made we to slightly + * adapt the functions called to match the linux kernel implementation + * of zlib. The full zlib license follows: + * + * zlib.h -- interface of the 'zlib' general purpose compression library + * version 1.2.5, April 19th, 2010 + * + * Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + * + * Jean-loup Gailly + * Mark Adler + */ + +#ifndef _SPL_ZMOD_H +#define _SPL_ZMOD_H + +#include <sys/types.h> +#include <linux/zlib.h> + +extern int z_compress_level(void *dest, size_t *destLen, const void *source, + size_t sourceLen, int level); +extern int z_uncompress(void *dest, size_t *destLen, const void *source, + size_t sourceLen); + +int spl_zlib_init(void); +void spl_zlib_fini(void); + +#endif /* SPL_ZMOD_H */ diff --git a/include/os/linux/spl/sys/zone.h b/include/os/linux/spl/sys/zone.h new file mode 100644 index 000000000000..b2efd13b8e0d --- /dev/null +++ b/include/os/linux/spl/sys/zone.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <behlendorf1@llnl.gov>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_ZONE_H +#define _SPL_ZONE_H + +#include <sys/byteorder.h> + +#define GLOBAL_ZONEID 0 + +#define zone_dataset_visible(x, y) (1) +#define crgetzoneid(x) (GLOBAL_ZONEID) +#define INGLOBALZONE(z) (1) + +#endif /* SPL_ZONE_H */ diff --git a/include/os/linux/zfs/Makefile.am b/include/os/linux/zfs/Makefile.am new file mode 100644 index 000000000000..081839c48c8f --- /dev/null +++ b/include/os/linux/zfs/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = sys diff --git a/include/os/linux/zfs/sys/Makefile.am b/include/os/linux/zfs/sys/Makefile.am new file mode 100644 index 000000000000..732d94ee804e --- /dev/null +++ b/include/os/linux/zfs/sys/Makefile.am @@ -0,0 +1,30 @@ +KERNEL_H = \ + policy.h \ + sha2.h \ + trace_acl.h \ + trace_arc.h \ + trace_common.h \ + trace_zfs.h \ + trace_dbgmsg.h \ + trace_dbuf.h \ + trace_dmu.h \ + trace_dnode.h \ + trace_multilist.h \ + trace_rrwlock.h \ + trace_txg.h \ + trace_vdev.h \ + trace_zil.h \ + trace_zio.h \ + trace_zrlock.h \ + zfs_context_os.h \ + zfs_ctldir.h \ + zfs_dir.h \ + zfs_vfsops.h \ + zfs_vnops.h \ + zfs_znode_impl.h \ + zpl.h + +if CONFIG_KERNEL +kerneldir = @prefix@/src/zfs-$(VERSION)/include/sys +kernel_HEADERS = $(KERNEL_H) +endif diff --git a/include/os/linux/zfs/sys/policy.h b/include/os/linux/zfs/sys/policy.h new file mode 100644 index 000000000000..77a73ad149c5 --- /dev/null +++ b/include/os/linux/zfs/sys/policy.h @@ -0,0 +1,61 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2015, Joyent, Inc. All rights reserved. + * Copyright (c) 2016, Lawrence Livermore National Security, LLC. + */ + +#ifndef _SYS_POLICY_H +#define _SYS_POLICY_H + +#ifdef _KERNEL + +#include <sys/cred.h> +#include <sys/types.h> +#include <sys/xvattr.h> +#include <sys/zpl.h> + +int secpolicy_nfs(const cred_t *); +int secpolicy_sys_config(const cred_t *, boolean_t); +int secpolicy_vnode_access2(const cred_t *, struct inode *, + uid_t, mode_t, mode_t); +int secpolicy_vnode_any_access(const cred_t *, struct inode *, uid_t); +int secpolicy_vnode_chown(const cred_t *, uid_t); +int secpolicy_vnode_create_gid(const cred_t *); +int secpolicy_vnode_remove(const cred_t *); +int secpolicy_vnode_setdac(const cred_t *, uid_t); +int secpolicy_vnode_setid_retain(const cred_t *, boolean_t); +int secpolicy_vnode_setids_setgids(const cred_t *, gid_t); +int secpolicy_zinject(const cred_t *); +int secpolicy_zfs(const cred_t *); +int secpolicy_zfs_proc(const cred_t *, proc_t *); +void secpolicy_setid_clear(vattr_t *, cred_t *); +int secpolicy_setid_setsticky_clear(struct inode *, vattr_t *, + const vattr_t *, cred_t *); +int secpolicy_xvattr(xvattr_t *, uid_t, cred_t *, mode_t); +int secpolicy_vnode_setattr(cred_t *, struct inode *, struct vattr *, + const struct vattr *, int, int (void *, int, cred_t *), void *); +int secpolicy_basic_link(const cred_t *); + +#endif /* _KERNEL */ +#endif /* _SYS_POLICY_H */ diff --git a/include/os/linux/zfs/sys/sha2.h b/include/os/linux/zfs/sys/sha2.h new file mode 100644 index 000000000000..4dd966b6cab3 --- /dev/null +++ b/include/os/linux/zfs/sys/sha2.h @@ -0,0 +1,151 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* Copyright 2013 Saso Kiselkov. All rights reserved. */ + +#ifndef _SYS_SHA2_H +#define _SYS_SHA2_H + +#include <sys/types.h> /* for uint_* */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define SHA2_HMAC_MIN_KEY_LEN 1 /* SHA2-HMAC min key length in bytes */ +#define SHA2_HMAC_MAX_KEY_LEN INT_MAX /* SHA2-HMAC max key length in bytes */ + +#define SHA256_DIGEST_LENGTH 32 /* SHA256 digest length in bytes */ +#define SHA384_DIGEST_LENGTH 48 /* SHA384 digest length in bytes */ +#define SHA512_DIGEST_LENGTH 64 /* SHA512 digest length in bytes */ + +/* Truncated versions of SHA-512 according to FIPS-180-4, section 5.3.6 */ +#define SHA512_224_DIGEST_LENGTH 28 /* SHA512/224 digest length */ +#define SHA512_256_DIGEST_LENGTH 32 /* SHA512/256 digest length */ + +#define SHA256_HMAC_BLOCK_SIZE 64 /* SHA256-HMAC block size */ +#define SHA512_HMAC_BLOCK_SIZE 128 /* SHA512-HMAC block size */ + +#define SHA256 0 +#define SHA256_HMAC 1 +#define SHA256_HMAC_GEN 2 +#define SHA384 3 +#define SHA384_HMAC 4 +#define SHA384_HMAC_GEN 5 +#define SHA512 6 +#define SHA512_HMAC 7 +#define SHA512_HMAC_GEN 8 +#define SHA512_224 9 +#define SHA512_256 10 + +/* + * SHA2 context. + * The contents of this structure are a private interface between the + * Init/Update/Final calls of the functions defined below. + * Callers must never attempt to read or write any of the fields + * in this structure directly. + */ +typedef struct { + uint32_t algotype; /* Algorithm Type */ + + /* state (ABCDEFGH) */ + union { + uint32_t s32[8]; /* for SHA256 */ + uint64_t s64[8]; /* for SHA384/512 */ + } state; + /* number of bits */ + union { + uint32_t c32[2]; /* for SHA256 , modulo 2^64 */ + uint64_t c64[2]; /* for SHA384/512, modulo 2^128 */ + } count; + union { + uint8_t buf8[128]; /* undigested input */ + uint32_t buf32[32]; /* realigned input */ + uint64_t buf64[16]; /* realigned input */ + } buf_un; +} SHA2_CTX; + +typedef SHA2_CTX SHA256_CTX; +typedef SHA2_CTX SHA384_CTX; +typedef SHA2_CTX SHA512_CTX; + +extern void SHA2Init(uint64_t mech, SHA2_CTX *); + +extern void SHA2Update(SHA2_CTX *, const void *, size_t); + +extern void SHA2Final(void *, SHA2_CTX *); + +extern void SHA256Init(SHA256_CTX *); + +extern void SHA256Update(SHA256_CTX *, const void *, size_t); + +extern void SHA256Final(void *, SHA256_CTX *); + +extern void SHA384Init(SHA384_CTX *); + +extern void SHA384Update(SHA384_CTX *, const void *, size_t); + +extern void SHA384Final(void *, SHA384_CTX *); + +extern void SHA512Init(SHA512_CTX *); + +extern void SHA512Update(SHA512_CTX *, const void *, size_t); + +extern void SHA512Final(void *, SHA512_CTX *); + +#ifdef _SHA2_IMPL +/* + * The following types/functions are all private to the implementation + * of the SHA2 functions and must not be used by consumers of the interface + */ + +/* + * List of support mechanisms in this module. + * + * It is important to note that in the module, division or modulus calculations + * are used on the enumerated type to determine which mechanism is being used; + * therefore, changing the order or additional mechanisms should be done + * carefully + */ +typedef enum sha2_mech_type { + SHA256_MECH_INFO_TYPE, /* SUN_CKM_SHA256 */ + SHA256_HMAC_MECH_INFO_TYPE, /* SUN_CKM_SHA256_HMAC */ + SHA256_HMAC_GEN_MECH_INFO_TYPE, /* SUN_CKM_SHA256_HMAC_GENERAL */ + SHA384_MECH_INFO_TYPE, /* SUN_CKM_SHA384 */ + SHA384_HMAC_MECH_INFO_TYPE, /* SUN_CKM_SHA384_HMAC */ + SHA384_HMAC_GEN_MECH_INFO_TYPE, /* SUN_CKM_SHA384_HMAC_GENERAL */ + SHA512_MECH_INFO_TYPE, /* SUN_CKM_SHA512 */ + SHA512_HMAC_MECH_INFO_TYPE, /* SUN_CKM_SHA512_HMAC */ + SHA512_HMAC_GEN_MECH_INFO_TYPE, /* SUN_CKM_SHA512_HMAC_GENERAL */ + SHA512_224_MECH_INFO_TYPE, /* SUN_CKM_SHA512_224 */ + SHA512_256_MECH_INFO_TYPE /* SUN_CKM_SHA512_256 */ +} sha2_mech_type_t; + +#endif /* _SHA2_IMPL */ + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_SHA2_H */ diff --git a/include/os/linux/zfs/sys/trace_acl.h b/include/os/linux/zfs/sys/trace_acl.h new file mode 100644 index 000000000000..083560952f0b --- /dev/null +++ b/include/os/linux/zfs/sys/trace_acl.h @@ -0,0 +1,164 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +#if defined(_KERNEL) +#if defined(HAVE_DECLARE_EVENT_CLASS) + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM zfs + +#undef TRACE_SYSTEM_VAR +#define TRACE_SYSTEM_VAR zfs_acl + +#if !defined(_TRACE_ACL_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_ACL_H + +#include <linux/tracepoint.h> +#include <linux/vfs_compat.h> +#include <sys/types.h> + +/* + * Generic support for three argument tracepoints of the form: + * + * DTRACE_PROBE3(..., + * znode_t *, ..., + * zfs_ace_hdr_t *, ..., + * uint32_t, ...); + */ +/* BEGIN CSTYLED */ +DECLARE_EVENT_CLASS(zfs_ace_class, + TP_PROTO(znode_t *zn, zfs_ace_hdr_t *ace, uint32_t mask_matched), + TP_ARGS(zn, ace, mask_matched), + TP_STRUCT__entry( + __field(uint64_t, z_id) + __field(uint8_t, z_unlinked) + __field(uint8_t, z_atime_dirty) + __field(uint8_t, z_zn_prefetch) + __field(uint8_t, z_moved) + __field(uint_t, z_blksz) + __field(uint_t, z_seq) + __field(uint64_t, z_mapcnt) + __field(uint64_t, z_size) + __field(uint64_t, z_pflags) + __field(uint32_t, z_sync_cnt) + __field(mode_t, z_mode) + __field(boolean_t, z_is_sa) + __field(boolean_t, z_is_mapped) + __field(boolean_t, z_is_ctldir) + __field(boolean_t, z_is_stale) + + __field(uint32_t, i_uid) + __field(uint32_t, i_gid) + __field(unsigned long, i_ino) + __field(unsigned int, i_nlink) + __field(loff_t, i_size) + __field(unsigned int, i_blkbits) + __field(unsigned short, i_bytes) + __field(umode_t, i_mode) + __field(__u32, i_generation) + + __field(uint16_t, z_type) + __field(uint16_t, z_flags) + __field(uint32_t, z_access_mask) + + __field(uint32_t, mask_matched) + ), + TP_fast_assign( + __entry->z_id = zn->z_id; + __entry->z_unlinked = zn->z_unlinked; + __entry->z_atime_dirty = zn->z_atime_dirty; + __entry->z_zn_prefetch = zn->z_zn_prefetch; + __entry->z_moved = zn->z_moved; + __entry->z_blksz = zn->z_blksz; + __entry->z_seq = zn->z_seq; + __entry->z_mapcnt = zn->z_mapcnt; + __entry->z_size = zn->z_size; + __entry->z_pflags = zn->z_pflags; + __entry->z_sync_cnt = zn->z_sync_cnt; + __entry->z_mode = zn->z_mode; + __entry->z_is_sa = zn->z_is_sa; + __entry->z_is_mapped = zn->z_is_mapped; + __entry->z_is_ctldir = zn->z_is_ctldir; + __entry->z_is_stale = zn->z_is_stale; + + __entry->i_uid = KUID_TO_SUID(ZTOI(zn)->i_uid); + __entry->i_gid = KGID_TO_SGID(ZTOI(zn)->i_gid); + __entry->i_ino = zn->z_inode.i_ino; + __entry->i_nlink = zn->z_inode.i_nlink; + __entry->i_size = zn->z_inode.i_size; + __entry->i_blkbits = zn->z_inode.i_blkbits; + __entry->i_bytes = zn->z_inode.i_bytes; + __entry->i_mode = zn->z_inode.i_mode; + __entry->i_generation = zn->z_inode.i_generation; + + __entry->z_type = ace->z_type; + __entry->z_flags = ace->z_flags; + __entry->z_access_mask = ace->z_access_mask; + + __entry->mask_matched = mask_matched; + ), + TP_printk("zn { id %llu unlinked %u atime_dirty %u " + "zn_prefetch %u moved %u blksz %u seq %u " + "mapcnt %llu size %llu pflags %llu " + "sync_cnt %u mode 0x%x is_sa %d " + "is_mapped %d is_ctldir %d is_stale %d inode { " + "uid %u gid %u ino %lu nlink %u size %lli " + "blkbits %u bytes %u mode 0x%x generation %x } } " + "ace { type %u flags %u access_mask %u } mask_matched %u", + __entry->z_id, __entry->z_unlinked, __entry->z_atime_dirty, + __entry->z_zn_prefetch, __entry->z_moved, __entry->z_blksz, + __entry->z_seq, __entry->z_mapcnt, __entry->z_size, + __entry->z_pflags, __entry->z_sync_cnt, __entry->z_mode, + __entry->z_is_sa, __entry->z_is_mapped, + __entry->z_is_ctldir, __entry->z_is_stale, __entry->i_uid, + __entry->i_gid, __entry->i_ino, __entry->i_nlink, + __entry->i_size, __entry->i_blkbits, + __entry->i_bytes, __entry->i_mode, __entry->i_generation, + __entry->z_type, __entry->z_flags, __entry->z_access_mask, + __entry->mask_matched) +); +/* END CSTYLED */ + +/* BEGIN CSTYLED */ +#define DEFINE_ACE_EVENT(name) \ +DEFINE_EVENT(zfs_ace_class, name, \ + TP_PROTO(znode_t *zn, zfs_ace_hdr_t *ace, uint32_t mask_matched), \ + TP_ARGS(zn, ace, mask_matched)) +/* END CSTYLED */ +DEFINE_ACE_EVENT(zfs_zfs__ace__denies); +DEFINE_ACE_EVENT(zfs_zfs__ace__allows); + +#endif /* _TRACE_ACL_H */ + +#undef TRACE_INCLUDE_PATH +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_PATH sys +#define TRACE_INCLUDE_FILE trace_acl +#include <trace/define_trace.h> + +#else + +DEFINE_DTRACE_PROBE3(zfs__ace__denies); +DEFINE_DTRACE_PROBE3(zfs__ace__allows); +DEFINE_DTRACE_PROBE(zfs__fastpath__execute__access__miss); + +#endif /* HAVE_DECLARE_EVENT_CLASS */ +#endif /* _KERNEL */ diff --git a/include/os/linux/zfs/sys/trace_arc.h b/include/os/linux/zfs/sys/trace_arc.h new file mode 100644 index 000000000000..3df491f8b392 --- /dev/null +++ b/include/os/linux/zfs/sys/trace_arc.h @@ -0,0 +1,419 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +#include <sys/list.h> + +#if defined(_KERNEL) +#if defined(HAVE_DECLARE_EVENT_CLASS) + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM zfs + +#undef TRACE_SYSTEM_VAR +#define TRACE_SYSTEM_VAR zfs_arc + +#if !defined(_TRACE_ARC_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_ARC_H + +#include <linux/tracepoint.h> +#include <sys/types.h> +#include <sys/trace_common.h> /* For ZIO macros */ + +/* + * Generic support for one argument tracepoints of the form: + * + * DTRACE_PROBE1(..., + * arc_buf_hdr_t *, ...); + */ +/* BEGIN CSTYLED */ +DECLARE_EVENT_CLASS(zfs_arc_buf_hdr_class, + TP_PROTO(arc_buf_hdr_t *ab), + TP_ARGS(ab), + TP_STRUCT__entry( + __array(uint64_t, hdr_dva_word, 2) + __field(uint64_t, hdr_birth) + __field(uint32_t, hdr_flags) + __field(uint32_t, hdr_bufcnt) + __field(arc_buf_contents_t, hdr_type) + __field(uint16_t, hdr_psize) + __field(uint16_t, hdr_lsize) + __field(uint64_t, hdr_spa) + __field(arc_state_type_t, hdr_state_type) + __field(clock_t, hdr_access) + __field(uint32_t, hdr_mru_hits) + __field(uint32_t, hdr_mru_ghost_hits) + __field(uint32_t, hdr_mfu_hits) + __field(uint32_t, hdr_mfu_ghost_hits) + __field(uint32_t, hdr_l2_hits) + __field(int64_t, hdr_refcount) + ), + TP_fast_assign( + __entry->hdr_dva_word[0] = ab->b_dva.dva_word[0]; + __entry->hdr_dva_word[1] = ab->b_dva.dva_word[1]; + __entry->hdr_birth = ab->b_birth; + __entry->hdr_flags = ab->b_flags; + __entry->hdr_bufcnt = ab->b_l1hdr.b_bufcnt; + __entry->hdr_psize = ab->b_psize; + __entry->hdr_lsize = ab->b_lsize; + __entry->hdr_spa = ab->b_spa; + __entry->hdr_state_type = ab->b_l1hdr.b_state->arcs_state; + __entry->hdr_access = ab->b_l1hdr.b_arc_access; + __entry->hdr_mru_hits = ab->b_l1hdr.b_mru_hits; + __entry->hdr_mru_ghost_hits = ab->b_l1hdr.b_mru_ghost_hits; + __entry->hdr_mfu_hits = ab->b_l1hdr.b_mfu_hits; + __entry->hdr_mfu_ghost_hits = ab->b_l1hdr.b_mfu_ghost_hits; + __entry->hdr_l2_hits = ab->b_l1hdr.b_l2_hits; + __entry->hdr_refcount = ab->b_l1hdr.b_refcnt.rc_count; + ), + TP_printk("hdr { dva 0x%llx:0x%llx birth %llu " + "flags 0x%x bufcnt %u type %u psize %u lsize %u spa %llu " + "state_type %u access %lu mru_hits %u mru_ghost_hits %u " + "mfu_hits %u mfu_ghost_hits %u l2_hits %u refcount %lli }", + __entry->hdr_dva_word[0], __entry->hdr_dva_word[1], + __entry->hdr_birth, __entry->hdr_flags, + __entry->hdr_bufcnt, __entry->hdr_type, __entry->hdr_psize, + __entry->hdr_lsize, __entry->hdr_spa, __entry->hdr_state_type, + __entry->hdr_access, __entry->hdr_mru_hits, + __entry->hdr_mru_ghost_hits, __entry->hdr_mfu_hits, + __entry->hdr_mfu_ghost_hits, __entry->hdr_l2_hits, + __entry->hdr_refcount) +); +/* END CSTYLED */ + +/* BEGIN CSTYLED */ +#define DEFINE_ARC_BUF_HDR_EVENT(name) \ +DEFINE_EVENT(zfs_arc_buf_hdr_class, name, \ + TP_PROTO(arc_buf_hdr_t *ab), \ + TP_ARGS(ab)) +/* END CSTYLED */ +DEFINE_ARC_BUF_HDR_EVENT(zfs_arc__hit); +DEFINE_ARC_BUF_HDR_EVENT(zfs_arc__evict); +DEFINE_ARC_BUF_HDR_EVENT(zfs_arc__delete); +DEFINE_ARC_BUF_HDR_EVENT(zfs_new_state__mru); +DEFINE_ARC_BUF_HDR_EVENT(zfs_new_state__mfu); +DEFINE_ARC_BUF_HDR_EVENT(zfs_arc__async__upgrade__sync); +DEFINE_ARC_BUF_HDR_EVENT(zfs_arc__demand__hit__predictive__prefetch); +DEFINE_ARC_BUF_HDR_EVENT(zfs_l2arc__hit); +DEFINE_ARC_BUF_HDR_EVENT(zfs_l2arc__miss); + +/* + * Generic support for two argument tracepoints of the form: + * + * DTRACE_PROBE2(..., + * vdev_t *, ..., + * zio_t *, ...); + */ +/* BEGIN CSTYLED */ +DECLARE_EVENT_CLASS(zfs_l2arc_rw_class, + TP_PROTO(vdev_t *vd, zio_t *zio), + TP_ARGS(vd, zio), + TP_STRUCT__entry( + __field(uint64_t, vdev_id) + __field(uint64_t, vdev_guid) + __field(uint64_t, vdev_state) + ZIO_TP_STRUCT_ENTRY + ), + TP_fast_assign( + __entry->vdev_id = vd->vdev_id; + __entry->vdev_guid = vd->vdev_guid; + __entry->vdev_state = vd->vdev_state; + ZIO_TP_FAST_ASSIGN + ), + TP_printk("vdev { id %llu guid %llu state %llu } " + ZIO_TP_PRINTK_FMT, __entry->vdev_id, __entry->vdev_guid, + __entry->vdev_state, ZIO_TP_PRINTK_ARGS) +); +/* END CSTYLED */ + +/* BEGIN CSTYLED */ +#define DEFINE_L2ARC_RW_EVENT(name) \ +DEFINE_EVENT(zfs_l2arc_rw_class, name, \ + TP_PROTO(vdev_t *vd, zio_t *zio), \ + TP_ARGS(vd, zio)) +/* END CSTYLED */ +DEFINE_L2ARC_RW_EVENT(zfs_l2arc__read); +DEFINE_L2ARC_RW_EVENT(zfs_l2arc__write); + + +/* + * Generic support for two argument tracepoints of the form: + * + * DTRACE_PROBE2(..., + * zio_t *, ..., + * l2arc_write_callback_t *, ...); + */ +/* BEGIN CSTYLED */ +DECLARE_EVENT_CLASS(zfs_l2arc_iodone_class, + TP_PROTO(zio_t *zio, l2arc_write_callback_t *cb), + TP_ARGS(zio, cb), + TP_STRUCT__entry(ZIO_TP_STRUCT_ENTRY), + TP_fast_assign(ZIO_TP_FAST_ASSIGN), + TP_printk(ZIO_TP_PRINTK_FMT, ZIO_TP_PRINTK_ARGS) +); +/* END CSTYLED */ + +/* BEGIN CSTYLED */ +#define DEFINE_L2ARC_IODONE_EVENT(name) \ +DEFINE_EVENT(zfs_l2arc_iodone_class, name, \ + TP_PROTO(zio_t *zio, l2arc_write_callback_t *cb), \ + TP_ARGS(zio, cb)) +/* END CSTYLED */ +DEFINE_L2ARC_IODONE_EVENT(zfs_l2arc__iodone); + + +/* + * Generic support for four argument tracepoints of the form: + * + * DTRACE_PROBE4(..., + * arc_buf_hdr_t *, ..., + * const blkptr_t *, + * uint64_t, + * const zbookmark_phys_t *); + */ +/* BEGIN CSTYLED */ +DECLARE_EVENT_CLASS(zfs_arc_miss_class, + TP_PROTO(arc_buf_hdr_t *hdr, + const blkptr_t *bp, uint64_t size, const zbookmark_phys_t *zb), + TP_ARGS(hdr, bp, size, zb), + TP_STRUCT__entry( + __array(uint64_t, hdr_dva_word, 2) + __field(uint64_t, hdr_birth) + __field(uint32_t, hdr_flags) + __field(uint32_t, hdr_bufcnt) + __field(arc_buf_contents_t, hdr_type) + __field(uint16_t, hdr_psize) + __field(uint16_t, hdr_lsize) + __field(uint64_t, hdr_spa) + __field(arc_state_type_t, hdr_state_type) + __field(clock_t, hdr_access) + __field(uint32_t, hdr_mru_hits) + __field(uint32_t, hdr_mru_ghost_hits) + __field(uint32_t, hdr_mfu_hits) + __field(uint32_t, hdr_mfu_ghost_hits) + __field(uint32_t, hdr_l2_hits) + __field(int64_t, hdr_refcount) + + __array(uint64_t, bp_dva0, 2) + __array(uint64_t, bp_dva1, 2) + __array(uint64_t, bp_dva2, 2) + __array(uint64_t, bp_cksum, 4) + + __field(uint64_t, bp_lsize) + + __field(uint64_t, zb_objset) + __field(uint64_t, zb_object) + __field(int64_t, zb_level) + __field(uint64_t, zb_blkid) + ), + TP_fast_assign( + __entry->hdr_dva_word[0] = hdr->b_dva.dva_word[0]; + __entry->hdr_dva_word[1] = hdr->b_dva.dva_word[1]; + __entry->hdr_birth = hdr->b_birth; + __entry->hdr_flags = hdr->b_flags; + __entry->hdr_bufcnt = hdr->b_l1hdr.b_bufcnt; + __entry->hdr_psize = hdr->b_psize; + __entry->hdr_lsize = hdr->b_lsize; + __entry->hdr_spa = hdr->b_spa; + __entry->hdr_state_type = hdr->b_l1hdr.b_state->arcs_state; + __entry->hdr_access = hdr->b_l1hdr.b_arc_access; + __entry->hdr_mru_hits = hdr->b_l1hdr.b_mru_hits; + __entry->hdr_mru_ghost_hits = hdr->b_l1hdr.b_mru_ghost_hits; + __entry->hdr_mfu_hits = hdr->b_l1hdr.b_mfu_hits; + __entry->hdr_mfu_ghost_hits = hdr->b_l1hdr.b_mfu_ghost_hits; + __entry->hdr_l2_hits = hdr->b_l1hdr.b_l2_hits; + __entry->hdr_refcount = hdr->b_l1hdr.b_refcnt.rc_count; + + __entry->bp_dva0[0] = bp->blk_dva[0].dva_word[0]; + __entry->bp_dva0[1] = bp->blk_dva[0].dva_word[1]; + __entry->bp_dva1[0] = bp->blk_dva[1].dva_word[0]; + __entry->bp_dva1[1] = bp->blk_dva[1].dva_word[1]; + __entry->bp_dva2[0] = bp->blk_dva[2].dva_word[0]; + __entry->bp_dva2[1] = bp->blk_dva[2].dva_word[1]; + __entry->bp_cksum[0] = bp->blk_cksum.zc_word[0]; + __entry->bp_cksum[1] = bp->blk_cksum.zc_word[1]; + __entry->bp_cksum[2] = bp->blk_cksum.zc_word[2]; + __entry->bp_cksum[3] = bp->blk_cksum.zc_word[3]; + + __entry->bp_lsize = size; + + __entry->zb_objset = zb->zb_objset; + __entry->zb_object = zb->zb_object; + __entry->zb_level = zb->zb_level; + __entry->zb_blkid = zb->zb_blkid; + ), + TP_printk("hdr { dva 0x%llx:0x%llx birth %llu " + "flags 0x%x bufcnt %u psize %u lsize %u spa %llu state_type %u " + "access %lu mru_hits %u mru_ghost_hits %u mfu_hits %u " + "mfu_ghost_hits %u l2_hits %u refcount %lli } " + "bp { dva0 0x%llx:0x%llx dva1 0x%llx:0x%llx dva2 " + "0x%llx:0x%llx cksum 0x%llx:0x%llx:0x%llx:0x%llx " + "lsize %llu } zb { objset %llu object %llu level %lli " + "blkid %llu }", + __entry->hdr_dva_word[0], __entry->hdr_dva_word[1], + __entry->hdr_birth, __entry->hdr_flags, + __entry->hdr_bufcnt, __entry->hdr_psize, __entry->hdr_lsize, + __entry->hdr_spa, __entry->hdr_state_type, __entry->hdr_access, + __entry->hdr_mru_hits, __entry->hdr_mru_ghost_hits, + __entry->hdr_mfu_hits, __entry->hdr_mfu_ghost_hits, + __entry->hdr_l2_hits, __entry->hdr_refcount, + __entry->bp_dva0[0], __entry->bp_dva0[1], + __entry->bp_dva1[0], __entry->bp_dva1[1], + __entry->bp_dva2[0], __entry->bp_dva2[1], + __entry->bp_cksum[0], __entry->bp_cksum[1], + __entry->bp_cksum[2], __entry->bp_cksum[3], + __entry->bp_lsize, __entry->zb_objset, __entry->zb_object, + __entry->zb_level, __entry->zb_blkid) +); +/* END CSTYLED */ + +/* BEGIN CSTYLED */ +#define DEFINE_ARC_MISS_EVENT(name) \ +DEFINE_EVENT(zfs_arc_miss_class, name, \ + TP_PROTO(arc_buf_hdr_t *hdr, \ + const blkptr_t *bp, uint64_t size, const zbookmark_phys_t *zb), \ + TP_ARGS(hdr, bp, size, zb)) +/* END CSTYLED */ +DEFINE_ARC_MISS_EVENT(zfs_arc__miss); + +/* + * Generic support for four argument tracepoints of the form: + * + * DTRACE_PROBE4(..., + * l2arc_dev_t *, ..., + * list_t *, ..., + * uint64_t, ..., + * boolean_t, ...); + */ +/* BEGIN CSTYLED */ +DECLARE_EVENT_CLASS(zfs_l2arc_evict_class, + TP_PROTO(l2arc_dev_t *dev, + list_t *buflist, uint64_t taddr, boolean_t all), + TP_ARGS(dev, buflist, taddr, all), + TP_STRUCT__entry( + __field(uint64_t, vdev_id) + __field(uint64_t, vdev_guid) + __field(uint64_t, vdev_state) + + __field(uint64_t, l2ad_hand) + __field(uint64_t, l2ad_start) + __field(uint64_t, l2ad_end) + __field(boolean_t, l2ad_first) + __field(boolean_t, l2ad_writing) + + __field(uint64_t, taddr) + __field(boolean_t, all) + ), + TP_fast_assign( + __entry->vdev_id = dev->l2ad_vdev->vdev_id; + __entry->vdev_guid = dev->l2ad_vdev->vdev_guid; + __entry->vdev_state = dev->l2ad_vdev->vdev_state; + + __entry->l2ad_hand = dev->l2ad_hand; + __entry->l2ad_start = dev->l2ad_start; + __entry->l2ad_end = dev->l2ad_end; + __entry->l2ad_first = dev->l2ad_first; + __entry->l2ad_writing = dev->l2ad_writing; + + __entry->taddr = taddr; + __entry->all = all; + ), + TP_printk("l2ad { vdev { id %llu guid %llu state %llu } " + "hand %llu start %llu end %llu " + "first %d writing %d } taddr %llu all %d", + __entry->vdev_id, __entry->vdev_guid, __entry->vdev_state, + __entry->l2ad_hand, __entry->l2ad_start, + __entry->l2ad_end, __entry->l2ad_first, __entry->l2ad_writing, + __entry->taddr, __entry->all) +); +/* END CSTYLED */ + +/* BEGIN CSTYLED */ +#define DEFINE_L2ARC_EVICT_EVENT(name) \ +DEFINE_EVENT(zfs_l2arc_evict_class, name, \ + TP_PROTO(l2arc_dev_t *dev, \ + list_t *buflist, uint64_t taddr, boolean_t all), \ + TP_ARGS(dev, buflist, taddr, all)) +/* END CSTYLED */ +DEFINE_L2ARC_EVICT_EVENT(zfs_l2arc__evict); + +/* + * Generic support for three argument tracepoints of the form: + * + * DTRACE_PROBE3(..., + * uint64_t, ..., + * uint64_t, ..., + * uint64_t, ...); + */ +/* BEGIN CSTYLED */ +DECLARE_EVENT_CLASS(zfs_arc_wait_for_eviction_class, + TP_PROTO(uint64_t amount, uint64_t arc_evict_count, uint64_t aew_count), + TP_ARGS(amount, arc_evict_count, aew_count), + TP_STRUCT__entry( + __field(uint64_t, amount) + __field(uint64_t, arc_evict_count) + __field(uint64_t, aew_count) + ), + TP_fast_assign( + __entry->amount = amount; + __entry->arc_evict_count = arc_evict_count; + __entry->aew_count = aew_count; + ), + TP_printk("amount %llu arc_evict_count %llu aew_count %llu", + __entry->amount, __entry->arc_evict_count, __entry->aew_count) +); +/* END CSTYLED */ + +/* BEGIN CSTYLED */ +#define DEFINE_ARC_WAIT_FOR_EVICTION_EVENT(name) \ +DEFINE_EVENT(zfs_arc_wait_for_eviction_class, name, \ + TP_PROTO(uint64_t amount, uint64_t arc_evict_count, uint64_t aew_count), \ + TP_ARGS(amount, arc_evict_count, aew_count)) +/* END CSTYLED */ +DEFINE_ARC_WAIT_FOR_EVICTION_EVENT(zfs_arc__wait__for__eviction); + +#endif /* _TRACE_ARC_H */ + +#undef TRACE_INCLUDE_PATH +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_PATH sys +#define TRACE_INCLUDE_FILE trace_arc +#include <trace/define_trace.h> + +#else + +DEFINE_DTRACE_PROBE1(arc__hit); +DEFINE_DTRACE_PROBE1(arc__evict); +DEFINE_DTRACE_PROBE1(arc__delete); +DEFINE_DTRACE_PROBE1(new_state__mru); +DEFINE_DTRACE_PROBE1(new_state__mfu); +DEFINE_DTRACE_PROBE1(arc__async__upgrade__sync); +DEFINE_DTRACE_PROBE1(arc__demand__hit__predictive__prefetch); +DEFINE_DTRACE_PROBE1(l2arc__hit); +DEFINE_DTRACE_PROBE1(l2arc__miss); +DEFINE_DTRACE_PROBE2(l2arc__read); +DEFINE_DTRACE_PROBE2(l2arc__write); +DEFINE_DTRACE_PROBE2(l2arc__iodone); +DEFINE_DTRACE_PROBE3(arc__wait__for__eviction); +DEFINE_DTRACE_PROBE4(arc__miss); +DEFINE_DTRACE_PROBE4(l2arc__evict); + +#endif /* HAVE_DECLARE_EVENT_CLASS */ +#endif /* _KERNEL */ diff --git a/include/os/linux/zfs/sys/trace_common.h b/include/os/linux/zfs/sys/trace_common.h new file mode 100644 index 000000000000..6922d1a1810a --- /dev/null +++ b/include/os/linux/zfs/sys/trace_common.h @@ -0,0 +1,112 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * This file contains commonly used trace macros. Feel free to add and use + * them in your tracepoint headers. + */ + +#ifndef _SYS_TRACE_COMMON_H +#define _SYS_TRACE_COMMON_H +#include <linux/tracepoint.h> + +/* ZIO macros */ +#define ZIO_TP_STRUCT_ENTRY \ + __field(zio_type_t, zio_type) \ + __field(int, zio_cmd) \ + __field(zio_priority_t, zio_priority) \ + __field(uint64_t, zio_size) \ + __field(uint64_t, zio_orig_size) \ + __field(uint64_t, zio_offset) \ + __field(hrtime_t, zio_timestamp) \ + __field(hrtime_t, zio_delta) \ + __field(uint64_t, zio_delay) \ + __field(enum zio_flag, zio_flags) \ + __field(enum zio_stage, zio_stage) \ + __field(enum zio_stage, zio_pipeline) \ + __field(enum zio_flag, zio_orig_flags) \ + __field(enum zio_stage, zio_orig_stage) \ + __field(enum zio_stage, zio_orig_pipeline) \ + __field(uint8_t, zio_reexecute) \ + __field(uint64_t, zio_txg) \ + __field(int, zio_error) \ + __field(uint64_t, zio_ena) \ + \ + __field(enum zio_checksum, zp_checksum) \ + __field(enum zio_compress, zp_compress) \ + __field(dmu_object_type_t, zp_type) \ + __field(uint8_t, zp_level) \ + __field(uint8_t, zp_copies) \ + __field(boolean_t, zp_dedup) \ + __field(boolean_t, zp_dedup_verify) \ + __field(boolean_t, zp_nopwrite) + +#define ZIO_TP_FAST_ASSIGN \ + __entry->zio_type = zio->io_type; \ + __entry->zio_cmd = zio->io_cmd; \ + __entry->zio_priority = zio->io_priority; \ + __entry->zio_size = zio->io_size; \ + __entry->zio_orig_size = zio->io_orig_size; \ + __entry->zio_offset = zio->io_offset; \ + __entry->zio_timestamp = zio->io_timestamp; \ + __entry->zio_delta = zio->io_delta; \ + __entry->zio_delay = zio->io_delay; \ + __entry->zio_flags = zio->io_flags; \ + __entry->zio_stage = zio->io_stage; \ + __entry->zio_pipeline = zio->io_pipeline; \ + __entry->zio_orig_flags = zio->io_orig_flags; \ + __entry->zio_orig_stage = zio->io_orig_stage; \ + __entry->zio_orig_pipeline = zio->io_orig_pipeline; \ + __entry->zio_reexecute = zio->io_reexecute; \ + __entry->zio_txg = zio->io_txg; \ + __entry->zio_error = zio->io_error; \ + __entry->zio_ena = zio->io_ena; \ + \ + __entry->zp_checksum = zio->io_prop.zp_checksum; \ + __entry->zp_compress = zio->io_prop.zp_compress; \ + __entry->zp_type = zio->io_prop.zp_type; \ + __entry->zp_level = zio->io_prop.zp_level; \ + __entry->zp_copies = zio->io_prop.zp_copies; \ + __entry->zp_dedup = zio->io_prop.zp_dedup; \ + __entry->zp_nopwrite = zio->io_prop.zp_nopwrite; \ + __entry->zp_dedup_verify = zio->io_prop.zp_dedup_verify; + +#define ZIO_TP_PRINTK_FMT \ + "zio { type %u cmd %i prio %u size %llu orig_size %llu " \ + "offset %llu timestamp %llu delta %llu delay %llu " \ + "flags 0x%x stage 0x%x pipeline 0x%x orig_flags 0x%x " \ + "orig_stage 0x%x orig_pipeline 0x%x reexecute %u " \ + "txg %llu error %d ena %llu prop { checksum %u compress %u " \ + "type %u level %u copies %u dedup %u dedup_verify %u nopwrite %u } }" + +#define ZIO_TP_PRINTK_ARGS \ + __entry->zio_type, __entry->zio_cmd, __entry->zio_priority, \ + __entry->zio_size, __entry->zio_orig_size, __entry->zio_offset, \ + __entry->zio_timestamp, __entry->zio_delta, __entry->zio_delay, \ + __entry->zio_flags, __entry->zio_stage, __entry->zio_pipeline, \ + __entry->zio_orig_flags, __entry->zio_orig_stage, \ + __entry->zio_orig_pipeline, __entry->zio_reexecute, \ + __entry->zio_txg, __entry->zio_error, __entry->zio_ena, \ + __entry->zp_checksum, __entry->zp_compress, __entry->zp_type, \ + __entry->zp_level, __entry->zp_copies, __entry->zp_dedup, \ + __entry->zp_dedup_verify, __entry->zp_nopwrite + +#endif /* _SYS_TRACE_COMMON_H */ diff --git a/include/os/linux/zfs/sys/trace_dbgmsg.h b/include/os/linux/zfs/sys/trace_dbgmsg.h new file mode 100644 index 000000000000..513918d004a4 --- /dev/null +++ b/include/os/linux/zfs/sys/trace_dbgmsg.h @@ -0,0 +1,89 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +#if defined(_KERNEL) +#if defined(HAVE_DECLARE_EVENT_CLASS) + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM zfs + +#undef TRACE_SYSTEM_VAR +#define TRACE_SYSTEM_VAR zfs_dbgmsg + +#if !defined(_TRACE_DBGMSG_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_DBGMSG_H + +#include <linux/tracepoint.h> + +/* + * This file defines tracepoint events for use by the dbgmsg(), + * dprintf(), and SET_ERROR() interfaces. These are grouped here because + * they all provide a way to store simple messages in the debug log (as + * opposed to events used by the DTRACE_PROBE interfaces which typically + * dump structured data). + * + * This header is included inside the trace.h multiple inclusion guard, + * and it is guarded above against direct inclusion, so it and need not + * be guarded separately. + */ + +/* + * Generic support for one argument tracepoints of the form: + * + * DTRACE_PROBE1(..., + * const char *, ...); + */ +/* BEGIN CSTYLED */ +DECLARE_EVENT_CLASS(zfs_dprintf_class, + TP_PROTO(const char *msg), + TP_ARGS(msg), + TP_STRUCT__entry( + __string(msg, msg) + ), + TP_fast_assign( + __assign_str(msg, msg); + ), + TP_printk("%s", __get_str(msg)) +); +/* END CSTYLED */ + +/* BEGIN CSTYLED */ +#define DEFINE_DPRINTF_EVENT(name) \ +DEFINE_EVENT(zfs_dprintf_class, name, \ + TP_PROTO(const char *msg), \ + TP_ARGS(msg)) +/* END CSTYLED */ +DEFINE_DPRINTF_EVENT(zfs_zfs__dprintf); + +#endif /* _TRACE_DBGMSG_H */ + +#undef TRACE_INCLUDE_PATH +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_PATH sys +#define TRACE_INCLUDE_FILE trace_dbgmsg +#include <trace/define_trace.h> + +#else + +DEFINE_DTRACE_PROBE1(zfs__dprintf); + +#endif /* HAVE_DECLARE_EVENT_CLASS */ +#endif /* _KERNEL */ diff --git a/include/os/linux/zfs/sys/trace_dbuf.h b/include/os/linux/zfs/sys/trace_dbuf.h new file mode 100644 index 000000000000..bd7d791a46e7 --- /dev/null +++ b/include/os/linux/zfs/sys/trace_dbuf.h @@ -0,0 +1,169 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +#if defined(_KERNEL) +#if defined(HAVE_DECLARE_EVENT_CLASS) + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM zfs + +#undef TRACE_SYSTEM_VAR +#define TRACE_SYSTEM_VAR zfs_dbuf + +#if !defined(_TRACE_DBUF_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_DBUF_H + +#include <linux/tracepoint.h> +#include <sys/types.h> + +#ifndef TRACE_DBUF_MSG_MAX +#define TRACE_DBUF_MSG_MAX 512 +#endif + +/* + * Generic support for two argument tracepoints of the form: + * + * DTRACE_PROBE2(..., + * dmu_buf_impl_t *, ..., + * zio_t *, ...); + */ + +#define DBUF_TP_STRUCT_ENTRY \ + __dynamic_array(char, os_spa, TRACE_DBUF_MSG_MAX) \ + __field(uint64_t, ds_object) \ + __field(uint64_t, db_object) \ + __field(uint64_t, db_level) \ + __field(uint64_t, db_blkid) \ + __field(uint64_t, db_offset) \ + __field(uint64_t, db_size) \ + __field(uint64_t, db_state) \ + __field(int64_t, db_holds) \ + __dynamic_array(char, msg, TRACE_DBUF_MSG_MAX) + +#define DBUF_TP_FAST_ASSIGN \ + if (db != NULL) { \ + __assign_str(os_spa, \ + spa_name(DB_DNODE(db)->dn_objset->os_spa)); \ + \ + __entry->ds_object = db->db_objset->os_dsl_dataset ? \ + db->db_objset->os_dsl_dataset->ds_object : 0; \ + \ + __entry->db_object = db->db.db_object; \ + __entry->db_level = db->db_level; \ + __entry->db_blkid = db->db_blkid; \ + __entry->db_offset = db->db.db_offset; \ + __entry->db_size = db->db.db_size; \ + __entry->db_state = db->db_state; \ + __entry->db_holds = zfs_refcount_count(&db->db_holds); \ + snprintf(__get_str(msg), TRACE_DBUF_MSG_MAX, \ + DBUF_TP_PRINTK_FMT, DBUF_TP_PRINTK_ARGS); \ + } else { \ + __assign_str(os_spa, "NULL") \ + __entry->ds_object = 0; \ + __entry->db_object = 0; \ + __entry->db_level = 0; \ + __entry->db_blkid = 0; \ + __entry->db_offset = 0; \ + __entry->db_size = 0; \ + __entry->db_state = 0; \ + __entry->db_holds = 0; \ + snprintf(__get_str(msg), TRACE_DBUF_MSG_MAX, \ + "dbuf { NULL }"); \ + } + +#define DBUF_TP_PRINTK_FMT \ + "dbuf { spa \"%s\" objset %llu object %llu level %llu " \ + "blkid %llu offset %llu size %llu state %llu holds %lld }" + +#define DBUF_TP_PRINTK_ARGS \ + __get_str(os_spa), __entry->ds_object, \ + __entry->db_object, __entry->db_level, \ + __entry->db_blkid, __entry->db_offset, \ + __entry->db_size, __entry->db_state, __entry->db_holds + +/* BEGIN CSTYLED */ +DECLARE_EVENT_CLASS(zfs_dbuf_class, + TP_PROTO(dmu_buf_impl_t *db, zio_t *zio), + TP_ARGS(db, zio), + TP_STRUCT__entry(DBUF_TP_STRUCT_ENTRY), + TP_fast_assign(DBUF_TP_FAST_ASSIGN), + TP_printk("%s", __get_str(msg)) +); + +DECLARE_EVENT_CLASS(zfs_dbuf_state_class, + TP_PROTO(dmu_buf_impl_t *db, const char *why), + TP_ARGS(db, why), + TP_STRUCT__entry(DBUF_TP_STRUCT_ENTRY), + TP_fast_assign(DBUF_TP_FAST_ASSIGN), + TP_printk("%s", __get_str(msg)) +); +/* END CSTYLED */ + +/* BEGIN CSTYLED */ +#define DEFINE_DBUF_EVENT(name) \ +DEFINE_EVENT(zfs_dbuf_class, name, \ + TP_PROTO(dmu_buf_impl_t *db, zio_t *zio), \ + TP_ARGS(db, zio)) +/* END CSTYLED */ +DEFINE_DBUF_EVENT(zfs_blocked__read); + +/* BEGIN CSTYLED */ +#define DEFINE_DBUF_STATE_EVENT(name) \ +DEFINE_EVENT(zfs_dbuf_state_class, name, \ + TP_PROTO(dmu_buf_impl_t *db, const char *why), \ + TP_ARGS(db, why)) +/* END CSTYLED */ +DEFINE_DBUF_STATE_EVENT(zfs_dbuf__state_change); + +/* BEGIN CSTYLED */ +DECLARE_EVENT_CLASS(zfs_dbuf_evict_one_class, + TP_PROTO(dmu_buf_impl_t *db, multilist_sublist_t *mls), + TP_ARGS(db, mls), + TP_STRUCT__entry(DBUF_TP_STRUCT_ENTRY), + TP_fast_assign(DBUF_TP_FAST_ASSIGN), + TP_printk("%s", __get_str(msg)) +); +/* END CSTYLED */ + +/* BEGIN CSTYLED */ +#define DEFINE_DBUF_EVICT_ONE_EVENT(name) \ +DEFINE_EVENT(zfs_dbuf_evict_one_class, name, \ + TP_PROTO(dmu_buf_impl_t *db, multilist_sublist_t *mls), \ + TP_ARGS(db, mls)) +/* END CSTYLED */ +DEFINE_DBUF_EVICT_ONE_EVENT(zfs_dbuf__evict__one); + +#endif /* _TRACE_DBUF_H */ + +#undef TRACE_INCLUDE_PATH +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_PATH sys +#define TRACE_INCLUDE_FILE trace_dbuf +#include <trace/define_trace.h> + +#else + +DEFINE_DTRACE_PROBE2(blocked__read); +DEFINE_DTRACE_PROBE2(dbuf__evict__one); +DEFINE_DTRACE_PROBE2(dbuf__state_change); + +#endif /* HAVE_DECLARE_EVENT_CLASS */ +#endif /* _KERNEL */ diff --git a/include/os/linux/zfs/sys/trace_dmu.h b/include/os/linux/zfs/sys/trace_dmu.h new file mode 100644 index 000000000000..3c64a370f842 --- /dev/null +++ b/include/os/linux/zfs/sys/trace_dmu.h @@ -0,0 +1,136 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +#if defined(_KERNEL) +#if defined(HAVE_DECLARE_EVENT_CLASS) + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM zfs + +#undef TRACE_SYSTEM_VAR +#define TRACE_SYSTEM_VAR zfs_dmu + +#if !defined(_TRACE_DMU_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_DMU_H + +#include <linux/tracepoint.h> +#include <sys/types.h> + +/* + * Generic support for three argument tracepoints of the form: + * + * DTRACE_PROBE3(..., + * dmu_tx_t *, ..., + * uint64_t, ..., + * uint64_t, ...); + */ +/* BEGIN CSTYLED */ +DECLARE_EVENT_CLASS(zfs_delay_mintime_class, + TP_PROTO(dmu_tx_t *tx, uint64_t dirty, uint64_t min_tx_time), + TP_ARGS(tx, dirty, min_tx_time), + TP_STRUCT__entry( + __field(uint64_t, tx_txg) + __field(uint64_t, tx_lastsnap_txg) + __field(uint64_t, tx_lasttried_txg) + __field(boolean_t, tx_anyobj) + __field(boolean_t, tx_dirty_delayed) + __field(hrtime_t, tx_start) + __field(boolean_t, tx_wait_dirty) + __field(int, tx_err) + __field(uint64_t, min_tx_time) + __field(uint64_t, dirty) + ), + TP_fast_assign( + __entry->tx_txg = tx->tx_txg; + __entry->tx_lastsnap_txg = tx->tx_lastsnap_txg; + __entry->tx_lasttried_txg = tx->tx_lasttried_txg; + __entry->tx_anyobj = tx->tx_anyobj; + __entry->tx_dirty_delayed = tx->tx_dirty_delayed; + __entry->tx_start = tx->tx_start; + __entry->tx_wait_dirty = tx->tx_wait_dirty; + __entry->tx_err = tx->tx_err; + __entry->dirty = dirty; + __entry->min_tx_time = min_tx_time; + ), + TP_printk("tx { txg %llu lastsnap_txg %llu tx_lasttried_txg %llu " + "anyobj %d dirty_delayed %d start %llu wait_dirty %d err %i " + "} dirty %llu min_tx_time %llu", + __entry->tx_txg, __entry->tx_lastsnap_txg, + __entry->tx_lasttried_txg, __entry->tx_anyobj, + __entry->tx_dirty_delayed, __entry->tx_start, + __entry->tx_wait_dirty, __entry->tx_err, + __entry->dirty, __entry->min_tx_time) +); +/* END CSTYLED */ + +/* BEGIN CSTYLED */ +#define DEFINE_DELAY_MINTIME_EVENT(name) \ +DEFINE_EVENT(zfs_delay_mintime_class, name, \ + TP_PROTO(dmu_tx_t *tx, uint64_t dirty, uint64_t min_tx_time), \ + TP_ARGS(tx, dirty, min_tx_time)) +/* END CSTYLED */ +DEFINE_DELAY_MINTIME_EVENT(zfs_delay__mintime); + +/* BEGIN CSTYLED */ +DECLARE_EVENT_CLASS(zfs_free_long_range_class, + TP_PROTO(uint64_t long_free_dirty_all_txgs, uint64_t chunk_len, \ + uint64_t txg), + TP_ARGS(long_free_dirty_all_txgs, chunk_len, txg), + TP_STRUCT__entry( + __field(uint64_t, long_free_dirty_all_txgs) + __field(uint64_t, chunk_len) + __field(uint64_t, txg) + ), + TP_fast_assign( + __entry->long_free_dirty_all_txgs = long_free_dirty_all_txgs; + __entry->chunk_len = chunk_len; + __entry->txg = txg; + ), + TP_printk("long_free_dirty_all_txgs %llu chunk_len %llu txg %llu", + __entry->long_free_dirty_all_txgs, + __entry->chunk_len, __entry->txg) +); +/* END CSTYLED */ + +/* BEGIN CSTYLED */ +#define DEFINE_FREE_LONG_RANGE_EVENT(name) \ +DEFINE_EVENT(zfs_free_long_range_class, name, \ + TP_PROTO(uint64_t long_free_dirty_all_txgs, \ + uint64_t chunk_len, uint64_t txg), \ + TP_ARGS(long_free_dirty_all_txgs, chunk_len, txg)) +/* END CSTYLED */ +DEFINE_FREE_LONG_RANGE_EVENT(zfs_free__long__range); + +#endif /* _TRACE_DMU_H */ + +#undef TRACE_INCLUDE_PATH +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_PATH sys +#define TRACE_INCLUDE_FILE trace_dmu +#include <trace/define_trace.h> + +#else + +DEFINE_DTRACE_PROBE3(delay__mintime); +DEFINE_DTRACE_PROBE3(free__long__range); + +#endif /* HAVE_DECLARE_EVENT_CLASS */ +#endif /* _KERNEL */ diff --git a/include/os/linux/zfs/sys/trace_dnode.h b/include/os/linux/zfs/sys/trace_dnode.h new file mode 100644 index 000000000000..27ad6cba16d6 --- /dev/null +++ b/include/os/linux/zfs/sys/trace_dnode.h @@ -0,0 +1,129 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +#if defined(_KERNEL) +#if defined(HAVE_DECLARE_EVENT_CLASS) + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM zfs + +#undef TRACE_SYSTEM_VAR +#define TRACE_SYSTEM_VAR zfs_dnode + +#if !defined(_TRACE_DNODE_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_DNODE_H + +#include <linux/tracepoint.h> +#include <sys/types.h> + +/* + * Generic support for three argument tracepoints of the form: + * + * DTRACE_PROBE3(..., + * dnode_t *, ..., + * int64_t, ..., + * uint32_t, ...); + */ +/* BEGIN CSTYLED */ +DECLARE_EVENT_CLASS(zfs_dnode_move_class, + TP_PROTO(dnode_t *dn, int64_t refcount, uint32_t dbufs), + TP_ARGS(dn, refcount, dbufs), + TP_STRUCT__entry( + __field(uint64_t, dn_object) + __field(dmu_object_type_t, dn_type) + __field(uint16_t, dn_bonuslen) + __field(uint8_t, dn_bonustype) + __field(uint8_t, dn_nblkptr) + __field(uint8_t, dn_checksum) + __field(uint8_t, dn_compress) + __field(uint8_t, dn_nlevels) + __field(uint8_t, dn_indblkshift) + __field(uint8_t, dn_datablkshift) + __field(uint8_t, dn_moved) + __field(uint16_t, dn_datablkszsec) + __field(uint32_t, dn_datablksz) + __field(uint64_t, dn_maxblkid) + __field(int64_t, dn_tx_holds) + __field(int64_t, dn_holds) + __field(boolean_t, dn_have_spill) + + __field(int64_t, refcount) + __field(uint32_t, dbufs) + ), + TP_fast_assign( + __entry->dn_object = dn->dn_object; + __entry->dn_type = dn->dn_type; + __entry->dn_bonuslen = dn->dn_bonuslen; + __entry->dn_bonustype = dn->dn_bonustype; + __entry->dn_nblkptr = dn->dn_nblkptr; + __entry->dn_checksum = dn->dn_checksum; + __entry->dn_compress = dn->dn_compress; + __entry->dn_nlevels = dn->dn_nlevels; + __entry->dn_indblkshift = dn->dn_indblkshift; + __entry->dn_datablkshift = dn->dn_datablkshift; + __entry->dn_moved = dn->dn_moved; + __entry->dn_datablkszsec = dn->dn_datablkszsec; + __entry->dn_datablksz = dn->dn_datablksz; + __entry->dn_maxblkid = dn->dn_maxblkid; + __entry->dn_tx_holds = dn->dn_tx_holds.rc_count; + __entry->dn_holds = dn->dn_holds.rc_count; + __entry->dn_have_spill = dn->dn_have_spill; + + __entry->refcount = refcount; + __entry->dbufs = dbufs; + ), + TP_printk("dn { object %llu type %d bonuslen %u bonustype %u " + "nblkptr %u checksum %u compress %u nlevels %u indblkshift %u " + "datablkshift %u moved %u datablkszsec %u datablksz %u " + "maxblkid %llu tx_holds %lli holds %lli have_spill %d } " + "refcount %lli dbufs %u", + __entry->dn_object, __entry->dn_type, __entry->dn_bonuslen, + __entry->dn_bonustype, __entry->dn_nblkptr, __entry->dn_checksum, + __entry->dn_compress, __entry->dn_nlevels, __entry->dn_indblkshift, + __entry->dn_datablkshift, __entry->dn_moved, + __entry->dn_datablkszsec, __entry->dn_datablksz, + __entry->dn_maxblkid, __entry->dn_tx_holds, __entry->dn_holds, + __entry->dn_have_spill, __entry->refcount, __entry->dbufs) +); +/* END CSTYLED */ + +/* BEGIN CSTYLED */ +#define DEFINE_DNODE_MOVE_EVENT(name) \ +DEFINE_EVENT(zfs_dnode_move_class, name, \ + TP_PROTO(dnode_t *dn, int64_t refcount, uint32_t dbufs), \ + TP_ARGS(dn, refcount, dbufs)) +/* END CSTYLED */ +DEFINE_DNODE_MOVE_EVENT(zfs_dnode__move); + +#endif /* _TRACE_DNODE_H */ + +#undef TRACE_INCLUDE_PATH +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_PATH sys +#define TRACE_INCLUDE_FILE trace_dnode +#include <trace/define_trace.h> + +#else + +DEFINE_DTRACE_PROBE3(dnode__move); + +#endif /* HAVE_DECLARE_EVENT_CLASS */ +#endif /* _KERNEL */ diff --git a/include/os/linux/zfs/sys/trace_multilist.h b/include/os/linux/zfs/sys/trace_multilist.h new file mode 100644 index 000000000000..fe68d5296f73 --- /dev/null +++ b/include/os/linux/zfs/sys/trace_multilist.h @@ -0,0 +1,89 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +#if defined(_KERNEL) +#if defined(HAVE_DECLARE_EVENT_CLASS) + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM zfs + +#undef TRACE_SYSTEM_VAR +#define TRACE_SYSTEM_VAR zfs_multilist + +#if !defined(_TRACE_MULTILIST_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_MULTILIST_H + +#include <linux/tracepoint.h> +#include <sys/types.h> + +/* + * Generic support for three argument tracepoints of the form: + * + * DTRACE_PROBE3(..., + * multilist_t *, ..., + * unsigned int, ..., + * void *, ...); + */ +/* BEGIN CSTYLED */ +DECLARE_EVENT_CLASS(zfs_multilist_insert_remove_class, + TP_PROTO(multilist_t *ml, unsigned sublist_idx, void *obj), + TP_ARGS(ml, sublist_idx, obj), + TP_STRUCT__entry( + __field(size_t, ml_offset) + __field(uint64_t, ml_num_sublists) + + __field(unsigned int, sublist_idx) + ), + TP_fast_assign( + __entry->ml_offset = ml->ml_offset; + __entry->ml_num_sublists = ml->ml_num_sublists; + + __entry->sublist_idx = sublist_idx; + ), + TP_printk("ml { offset %ld numsublists %llu sublistidx %u } ", + __entry->ml_offset, __entry->ml_num_sublists, __entry->sublist_idx) +); +/* END CSTYLED */ + +/* BEGIN CSTYLED */ +#define DEFINE_MULTILIST_INSERT_REMOVE_EVENT(name) \ +DEFINE_EVENT(zfs_multilist_insert_remove_class, name, \ + TP_PROTO(multilist_t *ml, unsigned int sublist_idx, void *obj), \ + TP_ARGS(ml, sublist_idx, obj)) +/* END CSTYLED */ +DEFINE_MULTILIST_INSERT_REMOVE_EVENT(zfs_multilist__insert); +DEFINE_MULTILIST_INSERT_REMOVE_EVENT(zfs_multilist__remove); + +#endif /* _TRACE_MULTILIST_H */ + +#undef TRACE_INCLUDE_PATH +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_PATH sys +#define TRACE_INCLUDE_FILE trace_multilist +#include <trace/define_trace.h> + +#else + +DEFINE_DTRACE_PROBE3(multilist__insert); +DEFINE_DTRACE_PROBE3(multilist__remove); + +#endif /* HAVE_DECLARE_EVENT_CLASS */ +#endif /* _KERNEL */ diff --git a/include/os/linux/zfs/sys/trace_rrwlock.h b/include/os/linux/zfs/sys/trace_rrwlock.h new file mode 100644 index 000000000000..4c74d6257309 --- /dev/null +++ b/include/os/linux/zfs/sys/trace_rrwlock.h @@ -0,0 +1,31 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +#if defined(_KERNEL) +#if defined(HAVE_DECLARE_EVENT_CLASS) + +#else + +DEFINE_DTRACE_PROBE(zfs__rrwfastpath__rdmiss); +DEFINE_DTRACE_PROBE(zfs__rrwfastpath__exitmiss); + +#endif /* HAVE_DECLARE_EVENT_CLASS */ +#endif /* _KERNEL */ diff --git a/include/os/linux/zfs/sys/trace_txg.h b/include/os/linux/zfs/sys/trace_txg.h new file mode 100644 index 000000000000..23d5d358bc42 --- /dev/null +++ b/include/os/linux/zfs/sys/trace_txg.h @@ -0,0 +1,89 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +#if defined(_KERNEL) +#if defined(HAVE_DECLARE_EVENT_CLASS) + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM zfs + +#undef TRACE_SYSTEM_VAR +#define TRACE_SYSTEM_VAR zfs_txg + +#if !defined(_TRACE_TXG_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_TXG_H + +#include <linux/tracepoint.h> +#include <sys/types.h> + +/* + * Generic support for two argument tracepoints of the form: + * + * DTRACE_PROBE2(..., + * dsl_pool_t *, ..., + * uint64_t, ...); + */ +/* BEGIN CSTYLED */ +DECLARE_EVENT_CLASS(zfs_txg_class, + TP_PROTO(dsl_pool_t *dp, uint64_t txg), + TP_ARGS(dp, txg), + TP_STRUCT__entry( + __field(uint64_t, txg) + ), + TP_fast_assign( + __entry->txg = txg; + ), + TP_printk("txg %llu", __entry->txg) +); +/* END CSTYLED */ + +/* BEGIN CSTYLED */ +#define DEFINE_TXG_EVENT(name) \ +DEFINE_EVENT(zfs_txg_class, name, \ + TP_PROTO(dsl_pool_t *dp, uint64_t txg), \ + TP_ARGS(dp, txg)) +/* END CSTYLED */ +DEFINE_TXG_EVENT(zfs_dsl_pool_sync__done); +DEFINE_TXG_EVENT(zfs_txg__quiescing); +DEFINE_TXG_EVENT(zfs_txg__opened); +DEFINE_TXG_EVENT(zfs_txg__syncing); +DEFINE_TXG_EVENT(zfs_txg__synced); +DEFINE_TXG_EVENT(zfs_txg__quiesced); + +#endif /* _TRACE_TXG_H */ + +#undef TRACE_INCLUDE_PATH +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_PATH sys +#define TRACE_INCLUDE_FILE trace_txg +#include <trace/define_trace.h> + +#else + +DEFINE_DTRACE_PROBE2(dsl_pool_sync__done); +DEFINE_DTRACE_PROBE2(txg__quiescing); +DEFINE_DTRACE_PROBE2(txg__opened); +DEFINE_DTRACE_PROBE2(txg__syncing); +DEFINE_DTRACE_PROBE2(txg__synced); +DEFINE_DTRACE_PROBE2(txg__quiesced); + +#endif /* HAVE_DECLARE_EVENT_CLASS */ +#endif /* _KERNEL */ diff --git a/include/os/linux/zfs/sys/trace_vdev.h b/include/os/linux/zfs/sys/trace_vdev.h new file mode 100644 index 000000000000..50711446ffa4 --- /dev/null +++ b/include/os/linux/zfs/sys/trace_vdev.h @@ -0,0 +1,140 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +#if defined(_KERNEL) +#if defined(HAVE_DECLARE_EVENT_CLASS) + +/* + * If tracepoints are available define dtrace_probe events for vdev + * related probes. Definitions in include/os/linux/spl/sys/trace.h + * will map DTRACE_PROBE* calls to tracepoints. + */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM zfs + +#undef TRACE_SYSTEM_VAR +#define TRACE_SYSTEM_VAR zfs_vdev + +#if !defined(_TRACE_VDEV_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_VDEV_H + +#include <linux/tracepoint.h> +#include <sys/types.h> + +/* + * Generic support for three argument tracepoints of the form: + * + * DTRACE_PROBE3(..., + * spa_t *, ..., + * uint64_t, ..., + * uint64_t, ...); + */ +/* BEGIN CSTYLED */ +DECLARE_EVENT_CLASS(zfs_removing_class_3, + TP_PROTO(spa_t *spa, uint64_t offset, uint64_t size), + TP_ARGS(spa, offset, size), + TP_STRUCT__entry( + __field(spa_t *, vdev_spa) + __field(uint64_t, vdev_offset) + __field(uint64_t, vdev_size) + ), + TP_fast_assign( + __entry->vdev_spa = spa; + __entry->vdev_offset = offset; + __entry->vdev_size = size; + ), + TP_printk("spa %p offset %llu size %llu", + __entry->vdev_spa, __entry->vdev_offset, + __entry->vdev_size) +); +/* END CSTYLED */ + +/* BEGIN CSTYLED */ +#define DEFINE_REMOVE_FREE_EVENT(name) \ +DEFINE_EVENT(zfs_removing_class_3, name, \ + TP_PROTO(spa_t *spa, uint64_t offset, uint64_t size), \ + TP_ARGS(spa, offset, size)) +/* END CSTYLED */ +DEFINE_REMOVE_FREE_EVENT(zfs_remove__free__synced); +DEFINE_REMOVE_FREE_EVENT(zfs_remove__free__unvisited); + +/* + * Generic support for four argument tracepoints of the form: + * + * DTRACE_PROBE4(..., + * spa_t *, ..., + * uint64_t, ..., + * uint64_t, ..., + * uint64_t, ...); + */ +/* BEGIN CSTYLED */ +DECLARE_EVENT_CLASS(zfs_removing_class_4, + TP_PROTO(spa_t *spa, uint64_t offset, uint64_t size, uint64_t txg), + TP_ARGS(spa, offset, size, txg), + TP_STRUCT__entry( + __field(spa_t *, vdev_spa) + __field(uint64_t, vdev_offset) + __field(uint64_t, vdev_size) + __field(uint64_t, vdev_txg) + ), + TP_fast_assign( + __entry->vdev_spa = spa; + __entry->vdev_offset = offset; + __entry->vdev_size = size; + __entry->vdev_txg = txg; + ), + TP_printk("spa %p offset %llu size %llu txg %llu", + __entry->vdev_spa, __entry->vdev_offset, + __entry->vdev_size, __entry->vdev_txg) +); + +/* BEGIN CSTYLED */ +#define DEFINE_REMOVE_FREE_EVENT_TXG(name) \ +DEFINE_EVENT(zfs_removing_class_4, name, \ + TP_PROTO(spa_t *spa, uint64_t offset, uint64_t size,uint64_t txg), \ + TP_ARGS(spa, offset, size, txg)) +/* END CSTYLED */ +DEFINE_REMOVE_FREE_EVENT_TXG(zfs_remove__free__inflight); + +#endif /* _TRACE_VDEV_H */ + +#undef TRACE_INCLUDE_PATH +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_PATH sys +#define TRACE_INCLUDE_FILE trace_vdev +#include <trace/define_trace.h> + +#else + +/* + * When tracepoints are not available, a DEFINE_DTRACE_PROBE* macro is + * needed for each DTRACE_PROBE. These will be used to generate stub + * tracing functions and prototypes for those functions. See + * include/os/linux/spl/sys/trace.h. + */ + +DEFINE_DTRACE_PROBE3(remove__free__synced); +DEFINE_DTRACE_PROBE3(remove__free__unvisited); +DEFINE_DTRACE_PROBE4(remove__free__inflight); + +#endif /* HAVE_DECLARE_EVENT_CLASS */ +#endif /* _KERNEL */ diff --git a/include/os/linux/zfs/sys/trace_zfs.h b/include/os/linux/zfs/sys/trace_zfs.h new file mode 100644 index 000000000000..0e19f8d186d0 --- /dev/null +++ b/include/os/linux/zfs/sys/trace_zfs.h @@ -0,0 +1,53 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +#ifndef _OS_LINUX_ZFS_TRACE_H +#define _OS_LINUX_ZFS_TRACE_H + +#include <sys/multilist.h> +#include <sys/arc_impl.h> +#include <sys/vdev_impl.h> +#include <sys/zio.h> +#include <sys/dbuf.h> +#include <sys/dmu_objset.h> +#include <sys/dsl_dataset.h> +#include <sys/dmu_tx.h> +#include <sys/dnode.h> +#include <sys/zfs_znode.h> +#include <sys/zil_impl.h> +#include <sys/zrlock.h> + +#include <sys/trace.h> +#include <sys/trace_acl.h> +#include <sys/trace_arc.h> +#include <sys/trace_dbgmsg.h> +#include <sys/trace_dbuf.h> +#include <sys/trace_dmu.h> +#include <sys/trace_dnode.h> +#include <sys/trace_multilist.h> +#include <sys/trace_rrwlock.h> +#include <sys/trace_txg.h> +#include <sys/trace_vdev.h> +#include <sys/trace_zil.h> +#include <sys/trace_zio.h> +#include <sys/trace_zrlock.h> + +#endif diff --git a/include/os/linux/zfs/sys/trace_zil.h b/include/os/linux/zfs/sys/trace_zil.h new file mode 100644 index 000000000000..526846e664b2 --- /dev/null +++ b/include/os/linux/zfs/sys/trace_zil.h @@ -0,0 +1,229 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +#if defined(_KERNEL) +#if defined(HAVE_DECLARE_EVENT_CLASS) + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM zfs + +#undef TRACE_SYSTEM_VAR +#define TRACE_SYSTEM_VAR zfs_zil + +#if !defined(_TRACE_ZIL_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_ZIL_H + +#include <linux/tracepoint.h> +#include <sys/types.h> + +#define ZILOG_TP_STRUCT_ENTRY \ + __field(uint64_t, zl_lr_seq) \ + __field(uint64_t, zl_commit_lr_seq) \ + __field(uint64_t, zl_destroy_txg) \ + __field(uint64_t, zl_replaying_seq) \ + __field(uint32_t, zl_suspend) \ + __field(uint8_t, zl_suspending) \ + __field(uint8_t, zl_keep_first) \ + __field(uint8_t, zl_replay) \ + __field(uint8_t, zl_stop_sync) \ + __field(uint8_t, zl_logbias) \ + __field(uint8_t, zl_sync) \ + __field(int, zl_parse_error) \ + __field(uint64_t, zl_parse_blk_seq) \ + __field(uint64_t, zl_parse_lr_seq) \ + __field(uint64_t, zl_parse_blk_count) \ + __field(uint64_t, zl_parse_lr_count) \ + __field(uint64_t, zl_cur_used) \ + __field(clock_t, zl_replay_time) \ + __field(uint64_t, zl_replay_blks) + +#define ZILOG_TP_FAST_ASSIGN \ + __entry->zl_lr_seq = zilog->zl_lr_seq; \ + __entry->zl_commit_lr_seq = zilog->zl_commit_lr_seq; \ + __entry->zl_destroy_txg = zilog->zl_destroy_txg; \ + __entry->zl_replaying_seq = zilog->zl_replaying_seq; \ + __entry->zl_suspend = zilog->zl_suspend; \ + __entry->zl_suspending = zilog->zl_suspending; \ + __entry->zl_keep_first = zilog->zl_keep_first; \ + __entry->zl_replay = zilog->zl_replay; \ + __entry->zl_stop_sync = zilog->zl_stop_sync; \ + __entry->zl_logbias = zilog->zl_logbias; \ + __entry->zl_sync = zilog->zl_sync; \ + __entry->zl_parse_error = zilog->zl_parse_error; \ + __entry->zl_parse_blk_seq = zilog->zl_parse_blk_seq; \ + __entry->zl_parse_lr_seq = zilog->zl_parse_lr_seq; \ + __entry->zl_parse_blk_count = zilog->zl_parse_blk_count;\ + __entry->zl_parse_lr_count = zilog->zl_parse_lr_count; \ + __entry->zl_cur_used = zilog->zl_cur_used; \ + __entry->zl_replay_time = zilog->zl_replay_time; \ + __entry->zl_replay_blks = zilog->zl_replay_blks; + +#define ZILOG_TP_PRINTK_FMT \ + "zl { lr_seq %llu commit_lr_seq %llu destroy_txg %llu " \ + "replaying_seq %llu suspend %u suspending %u keep_first %u " \ + "replay %u stop_sync %u logbias %u sync %u " \ + "parse_error %u parse_blk_seq %llu parse_lr_seq %llu " \ + "parse_blk_count %llu parse_lr_count %llu " \ + "cur_used %llu replay_time %lu replay_blks %llu }" + +#define ZILOG_TP_PRINTK_ARGS \ + __entry->zl_lr_seq, __entry->zl_commit_lr_seq, \ + __entry->zl_destroy_txg, __entry->zl_replaying_seq, \ + __entry->zl_suspend, __entry->zl_suspending, \ + __entry->zl_keep_first, __entry->zl_replay, \ + __entry->zl_stop_sync, __entry->zl_logbias, __entry->zl_sync, \ + __entry->zl_parse_error, __entry->zl_parse_blk_seq, \ + __entry->zl_parse_lr_seq, __entry->zl_parse_blk_count, \ + __entry->zl_parse_lr_count, __entry->zl_cur_used, \ + __entry->zl_replay_time, __entry->zl_replay_blks + +#define ITX_TP_STRUCT_ENTRY \ + __field(itx_wr_state_t, itx_wr_state) \ + __field(uint8_t, itx_sync) \ + __field(zil_callback_t, itx_callback) \ + __field(void *, itx_callback_data) \ + __field(uint64_t, itx_oid) \ + \ + __field(uint64_t, lrc_txtype) \ + __field(uint64_t, lrc_reclen) \ + __field(uint64_t, lrc_txg) \ + __field(uint64_t, lrc_seq) + +#define ITX_TP_FAST_ASSIGN \ + __entry->itx_wr_state = itx->itx_wr_state; \ + __entry->itx_sync = itx->itx_sync; \ + __entry->itx_callback = itx->itx_callback; \ + __entry->itx_callback_data = itx->itx_callback_data; \ + __entry->itx_oid = itx->itx_oid; \ + \ + __entry->lrc_txtype = itx->itx_lr.lrc_txtype; \ + __entry->lrc_reclen = itx->itx_lr.lrc_reclen; \ + __entry->lrc_txg = itx->itx_lr.lrc_txg; \ + __entry->lrc_seq = itx->itx_lr.lrc_seq; + +#define ITX_TP_PRINTK_FMT \ + "itx { wr_state %u sync %u callback %p callback_data %p oid %llu" \ + " { txtype %llu reclen %llu txg %llu seq %llu } }" + +#define ITX_TP_PRINTK_ARGS \ + __entry->itx_wr_state, __entry->itx_sync, __entry->itx_callback,\ + __entry->itx_callback_data, __entry->itx_oid, \ + __entry->lrc_txtype, __entry->lrc_reclen, __entry->lrc_txg, \ + __entry->lrc_seq + +#define ZCW_TP_STRUCT_ENTRY \ + __field(lwb_t *, zcw_lwb) \ + __field(boolean_t, zcw_done) \ + __field(int, zcw_zio_error) \ + +#define ZCW_TP_FAST_ASSIGN \ + __entry->zcw_lwb = zcw->zcw_lwb; \ + __entry->zcw_done = zcw->zcw_done; \ + __entry->zcw_zio_error = zcw->zcw_zio_error; + +#define ZCW_TP_PRINTK_FMT \ + "zcw { lwb %p done %u error %u }" + +#define ZCW_TP_PRINTK_ARGS \ + __entry->zcw_lwb, __entry->zcw_done, __entry->zcw_zio_error + +/* + * Generic support for two argument tracepoints of the form: + * + * DTRACE_PROBE2(..., + * zilog_t *, ..., + * itx_t *, ...); + */ +/* BEGIN CSTYLED */ +DECLARE_EVENT_CLASS(zfs_zil_process_itx_class, + TP_PROTO(zilog_t *zilog, itx_t *itx), + TP_ARGS(zilog, itx), + TP_STRUCT__entry( + ZILOG_TP_STRUCT_ENTRY + ITX_TP_STRUCT_ENTRY + ), + TP_fast_assign( + ZILOG_TP_FAST_ASSIGN + ITX_TP_FAST_ASSIGN + ), + TP_printk( + ZILOG_TP_PRINTK_FMT " " ITX_TP_PRINTK_FMT, + ZILOG_TP_PRINTK_ARGS, ITX_TP_PRINTK_ARGS) +); +/* END CSTYLED */ + +/* BEGIN CSTYLED */ +#define DEFINE_ZIL_PROCESS_ITX_EVENT(name) \ +DEFINE_EVENT(zfs_zil_process_itx_class, name, \ + TP_PROTO(zilog_t *zilog, itx_t *itx), \ + TP_ARGS(zilog, itx)) +DEFINE_ZIL_PROCESS_ITX_EVENT(zfs_zil__process__commit__itx); +DEFINE_ZIL_PROCESS_ITX_EVENT(zfs_zil__process__normal__itx); +/* END CSTYLED */ + +/* + * Generic support for two argument tracepoints of the form: + * + * DTRACE_PROBE2(..., + * zilog_t *, ..., + * zil_commit_waiter_t *, ...); + */ +/* BEGIN CSTYLED */ +DECLARE_EVENT_CLASS(zfs_zil_commit_io_error_class, + TP_PROTO(zilog_t *zilog, zil_commit_waiter_t *zcw), + TP_ARGS(zilog, zcw), + TP_STRUCT__entry( + ZILOG_TP_STRUCT_ENTRY + ZCW_TP_STRUCT_ENTRY + ), + TP_fast_assign( + ZILOG_TP_FAST_ASSIGN + ZCW_TP_FAST_ASSIGN + ), + TP_printk( + ZILOG_TP_PRINTK_FMT " " ZCW_TP_PRINTK_FMT, + ZILOG_TP_PRINTK_ARGS, ZCW_TP_PRINTK_ARGS) +); + +/* BEGIN CSTYLED */ +#define DEFINE_ZIL_COMMIT_IO_ERROR_EVENT(name) \ +DEFINE_EVENT(zfs_zil_commit_io_error_class, name, \ + TP_PROTO(zilog_t *zilog, zil_commit_waiter_t *zcw), \ + TP_ARGS(zilog, zcw)) +DEFINE_ZIL_COMMIT_IO_ERROR_EVENT(zfs_zil__commit__io__error); +/* END CSTYLED */ + +#endif /* _TRACE_ZIL_H */ + +#undef TRACE_INCLUDE_PATH +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_PATH sys +#define TRACE_INCLUDE_FILE trace_zil +#include <trace/define_trace.h> + +#else + +DEFINE_DTRACE_PROBE2(zil__process__commit__itx); +DEFINE_DTRACE_PROBE2(zil__process__normal__itx); +DEFINE_DTRACE_PROBE2(zil__commit__io__error); + +#endif /* HAVE_DECLARE_EVENT_CLASS */ +#endif /* _KERNEL */ diff --git a/include/os/linux/zfs/sys/trace_zio.h b/include/os/linux/zfs/sys/trace_zio.h new file mode 100644 index 000000000000..8655e245c043 --- /dev/null +++ b/include/os/linux/zfs/sys/trace_zio.h @@ -0,0 +1,97 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +#include <sys/list.h> + +#if defined(_KERNEL) +#if defined(HAVE_DECLARE_EVENT_CLASS) + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM zfs + +#undef TRACE_SYSTEM_VAR +#define TRACE_SYSTEM_VAR zfs_zio + +#if !defined(_TRACE_ZIO_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_ZIO_H + +#include <linux/tracepoint.h> +#include <sys/types.h> +#include <sys/trace_common.h> /* For ZIO macros */ + +/* BEGIN CSTYLED */ +TRACE_EVENT(zfs_zio__delay__miss, + TP_PROTO(zio_t *zio, hrtime_t now), + TP_ARGS(zio, now), + TP_STRUCT__entry( + ZIO_TP_STRUCT_ENTRY + __field(hrtime_t, now) + ), + TP_fast_assign( + ZIO_TP_FAST_ASSIGN + __entry->now = now; + ), + TP_printk("now %llu " ZIO_TP_PRINTK_FMT, __entry->now, + ZIO_TP_PRINTK_ARGS) +); + +TRACE_EVENT(zfs_zio__delay__hit, + TP_PROTO(zio_t *zio, hrtime_t now, hrtime_t diff), + TP_ARGS(zio, now, diff), + TP_STRUCT__entry( + ZIO_TP_STRUCT_ENTRY + __field(hrtime_t, now) + __field(hrtime_t, diff) + ), + TP_fast_assign( + ZIO_TP_FAST_ASSIGN + __entry->now = now; + __entry->diff = diff; + ), + TP_printk("now %llu diff %llu " ZIO_TP_PRINTK_FMT, __entry->now, + __entry->diff, ZIO_TP_PRINTK_ARGS) +); + +TRACE_EVENT(zfs_zio__delay__skip, + TP_PROTO(zio_t *zio), + TP_ARGS(zio), + TP_STRUCT__entry(ZIO_TP_STRUCT_ENTRY), + TP_fast_assign(ZIO_TP_FAST_ASSIGN), + TP_printk(ZIO_TP_PRINTK_FMT, ZIO_TP_PRINTK_ARGS) +); +/* END CSTYLED */ + +#endif /* _TRACE_ZIO_H */ + +#undef TRACE_INCLUDE_PATH +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_PATH sys +#define TRACE_INCLUDE_FILE trace_zio +#include <trace/define_trace.h> + +#else + +DEFINE_DTRACE_PROBE2(zio__delay__miss); +DEFINE_DTRACE_PROBE3(zio__delay__hit); +DEFINE_DTRACE_PROBE1(zio__delay__skip); + +#endif /* HAVE_DECLARE_EVENT_CLASS */ +#endif /* _KERNEL */ diff --git a/include/os/linux/zfs/sys/trace_zrlock.h b/include/os/linux/zfs/sys/trace_zrlock.h new file mode 100644 index 000000000000..23f9577ba15f --- /dev/null +++ b/include/os/linux/zfs/sys/trace_zrlock.h @@ -0,0 +1,94 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +#if defined(_KERNEL) +#if defined(HAVE_DECLARE_EVENT_CLASS) + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM zfs + +#undef TRACE_SYSTEM_VAR +#define TRACE_SYSTEM_VAR zfs_zrlock + +#if !defined(_TRACE_ZRLOCK_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_ZRLOCK_H + +#include <linux/tracepoint.h> +#include <sys/types.h> + +/* + * Generic support for two argument tracepoints of the form: + * + * DTRACE_PROBE2(..., + * zrlock_t *, ..., + * uint32_t, ...); + */ +/* BEGIN CSTYLED */ +DECLARE_EVENT_CLASS(zfs_zrlock_class, + TP_PROTO(zrlock_t *zrl, kthread_t *owner, uint32_t n), + TP_ARGS(zrl, owner, n), + TP_STRUCT__entry( + __field(int32_t, refcount) +#ifdef ZFS_DEBUG + __field(pid_t, owner_pid) + __field(const char *, caller) +#endif + __field(uint32_t, n) + ), + TP_fast_assign( + __entry->refcount = zrl->zr_refcount; +#ifdef ZFS_DEBUG + __entry->owner_pid = owner ? owner->pid : 0; + __entry->caller = zrl->zr_caller ? zrl->zr_caller : "(null)"; +#endif + __entry->n = n; + ), +#ifdef ZFS_DEBUG + TP_printk("zrl { refcount %d owner_pid %d caller %s } n %u", + __entry->refcount, __entry->owner_pid, __entry->caller, + __entry->n) +#else + TP_printk("zrl { refcount %d } n %u", + __entry->refcount, __entry->n) +#endif +); +/* END_CSTYLED */ + +#define DEFINE_ZRLOCK_EVENT(name) \ +DEFINE_EVENT(zfs_zrlock_class, name, \ + TP_PROTO(zrlock_t *zrl, kthread_t *owner, uint32_t n), \ + TP_ARGS(zrl, owner, n)) +DEFINE_ZRLOCK_EVENT(zfs_zrlock__reentry); + +#endif /* _TRACE_ZRLOCK_H */ + +#undef TRACE_INCLUDE_PATH +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_PATH sys +#define TRACE_INCLUDE_FILE trace_zrlock +#include <trace/define_trace.h> + +#else + +DEFINE_DTRACE_PROBE3(zrlock__reentry); + +#endif /* HAVE_DECLARE_EVENT_CLASS */ +#endif /* _KERNEL */ diff --git a/include/os/linux/zfs/sys/zfs_context_os.h b/include/os/linux/zfs/sys/zfs_context_os.h new file mode 100644 index 000000000000..9e5fdd79f019 --- /dev/null +++ b/include/os/linux/zfs/sys/zfs_context_os.h @@ -0,0 +1,30 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +#ifndef ZFS_CONTEXT_OS_H +#define ZFS_CONTEXT_OS_H + +#include <sys/uio_impl.h> +#include <linux/dcache_compat.h> +#include <linux/utsname_compat.h> + +#endif diff --git a/include/os/linux/zfs/sys/zfs_ctldir.h b/include/os/linux/zfs/sys/zfs_ctldir.h new file mode 100644 index 000000000000..51933bc4fe47 --- /dev/null +++ b/include/os/linux/zfs/sys/zfs_ctldir.h @@ -0,0 +1,103 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (C) 2011 Lawrence Livermore National Security, LLC. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * LLNL-CODE-403049. + * Rewritten for Linux by: + * Rohan Puri <rohan.puri15@gmail.com> + * Brian Behlendorf <behlendorf1@llnl.gov> + */ + +#ifndef _ZFS_CTLDIR_H +#define _ZFS_CTLDIR_H + +#include <sys/vnode.h> +#include <sys/pathname.h> +#include <sys/zfs_vfsops.h> +#include <sys/zfs_znode.h> + +#define ZFS_CTLDIR_NAME ".zfs" +#define ZFS_SNAPDIR_NAME "snapshot" +#define ZFS_SHAREDIR_NAME "shares" + +#define zfs_has_ctldir(zdp) \ + ((zdp)->z_id == ZTOZSB(zdp)->z_root && \ + (ZTOZSB(zdp)->z_ctldir != NULL)) +#define zfs_show_ctldir(zdp) \ + (zfs_has_ctldir(zdp) && \ + (ZTOZSB(zdp)->z_show_ctldir)) + +extern int zfs_expire_snapshot; + +/* zfsctl generic functions */ +extern int zfsctl_create(zfsvfs_t *); +extern void zfsctl_destroy(zfsvfs_t *); +extern struct inode *zfsctl_root(znode_t *); +extern void zfsctl_init(void); +extern void zfsctl_fini(void); +extern boolean_t zfsctl_is_node(struct inode *ip); +extern boolean_t zfsctl_is_snapdir(struct inode *ip); +extern int zfsctl_fid(struct inode *ip, fid_t *fidp); + +/* zfsctl '.zfs' functions */ +extern int zfsctl_root_lookup(struct inode *dip, char *name, + struct inode **ipp, int flags, cred_t *cr, int *direntflags, + pathname_t *realpnp); + +/* zfsctl '.zfs/snapshot' functions */ +extern int zfsctl_snapdir_lookup(struct inode *dip, char *name, + struct inode **ipp, int flags, cred_t *cr, int *direntflags, + pathname_t *realpnp); +extern int zfsctl_snapdir_rename(struct inode *sdip, char *sname, + struct inode *tdip, char *tname, cred_t *cr, int flags); +extern int zfsctl_snapdir_remove(struct inode *dip, char *name, cred_t *cr, + int flags); +extern int zfsctl_snapdir_mkdir(struct inode *dip, char *dirname, vattr_t *vap, + struct inode **ipp, cred_t *cr, int flags); +extern int zfsctl_snapshot_mount(struct path *path, int flags); +extern int zfsctl_snapshot_unmount(char *snapname, int flags); +extern int zfsctl_snapshot_unmount_delay(spa_t *spa, uint64_t objsetid, + int delay); +extern int zfsctl_snapdir_vget(struct super_block *sb, uint64_t objsetid, + int gen, struct inode **ipp); + +/* zfsctl '.zfs/shares' functions */ +extern int zfsctl_shares_lookup(struct inode *dip, char *name, + struct inode **ipp, int flags, cred_t *cr, int *direntflags, + pathname_t *realpnp); + +/* + * These inodes numbers are reserved for the .zfs control directory. + * It is important that they be no larger that 48-bits because only + * 6 bytes are reserved in the NFS file handle for the object number. + * However, they should be as large as possible to avoid conflicts + * with the objects which are assigned monotonically by the dmu. + */ +#define ZFSCTL_INO_ROOT 0x0000FFFFFFFFFFFFULL +#define ZFSCTL_INO_SHARES 0x0000FFFFFFFFFFFEULL +#define ZFSCTL_INO_SNAPDIR 0x0000FFFFFFFFFFFDULL +#define ZFSCTL_INO_SNAPDIRS 0x0000FFFFFFFFFFFCULL + +#define ZFSCTL_EXPIRE_SNAPSHOT 300 + +#endif /* _ZFS_CTLDIR_H */ diff --git a/include/os/linux/zfs/sys/zfs_dir.h b/include/os/linux/zfs/sys/zfs_dir.h new file mode 100644 index 000000000000..0f15e43452b2 --- /dev/null +++ b/include/os/linux/zfs/sys/zfs_dir.h @@ -0,0 +1,76 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SYS_FS_ZFS_DIR_H +#define _SYS_FS_ZFS_DIR_H + +#include <sys/pathname.h> +#include <sys/dmu.h> +#include <sys/zfs_znode.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* zfs_dirent_lock() flags */ +#define ZNEW 0x0001 /* entry should not exist */ +#define ZEXISTS 0x0002 /* entry should exist */ +#define ZSHARED 0x0004 /* shared access (zfs_dirlook()) */ +#define ZXATTR 0x0008 /* we want the xattr dir */ +#define ZRENAMING 0x0010 /* znode is being renamed */ +#define ZCILOOK 0x0020 /* case-insensitive lookup requested */ +#define ZCIEXACT 0x0040 /* c-i requires c-s match (rename) */ +#define ZHAVELOCK 0x0080 /* z_name_lock is already held */ + +/* mknode flags */ +#define IS_ROOT_NODE 0x01 /* create a root node */ +#define IS_XATTR 0x02 /* create an extended attribute node */ +#define IS_TMPFILE 0x04 /* create a tmpfile */ + +extern int zfs_dirent_lock(zfs_dirlock_t **, znode_t *, char *, znode_t **, + int, int *, pathname_t *); +extern void zfs_dirent_unlock(zfs_dirlock_t *); +extern int zfs_link_create(zfs_dirlock_t *, znode_t *, dmu_tx_t *, int); +extern int zfs_link_destroy(zfs_dirlock_t *, znode_t *, dmu_tx_t *, int, + boolean_t *); +extern int zfs_dirlook(znode_t *, char *, znode_t **, int, int *, + pathname_t *); +extern void zfs_mknode(znode_t *, vattr_t *, dmu_tx_t *, cred_t *, + uint_t, znode_t **, zfs_acl_ids_t *); +extern void zfs_rmnode(znode_t *); +extern void zfs_dl_name_switch(zfs_dirlock_t *dl, char *new, char **old); +extern boolean_t zfs_dirempty(znode_t *); +extern void zfs_unlinked_add(znode_t *, dmu_tx_t *); +extern void zfs_unlinked_drain(zfsvfs_t *zfsvfs); +extern void zfs_unlinked_drain_stop_wait(zfsvfs_t *zfsvfs); +extern int zfs_sticky_remove_access(znode_t *, znode_t *, cred_t *cr); +extern int zfs_get_xattrdir(znode_t *, znode_t **, cred_t *, int); +extern int zfs_make_xattrdir(znode_t *, vattr_t *, znode_t **, cred_t *); + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_FS_ZFS_DIR_H */ diff --git a/include/os/linux/zfs/sys/zfs_vfsops.h b/include/os/linux/zfs/sys/zfs_vfsops.h new file mode 100644 index 000000000000..24a0a2e6a05f --- /dev/null +++ b/include/os/linux/zfs/sys/zfs_vfsops.h @@ -0,0 +1,227 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2018 by Delphix. All rights reserved. + */ + +#ifndef _SYS_FS_ZFS_VFSOPS_H +#define _SYS_FS_ZFS_VFSOPS_H + +#include <sys/dataset_kstats.h> +#include <sys/isa_defs.h> +#include <sys/types32.h> +#include <sys/list.h> +#include <sys/vfs.h> +#include <sys/zil.h> +#include <sys/sa.h> +#include <sys/rrwlock.h> +#include <sys/dsl_dataset.h> +#include <sys/zfs_ioctl.h> +#include <sys/objlist.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct zfsvfs zfsvfs_t; +struct znode; + +/* + * This structure emulates the vfs_t from other platforms. It's purpose + * is to facilitate the handling of mount options and minimize structural + * differences between the platforms. + */ +typedef struct vfs { + struct zfsvfs *vfs_data; + char *vfs_mntpoint; /* Primary mount point */ + uint64_t vfs_xattr; + boolean_t vfs_readonly; + boolean_t vfs_do_readonly; + boolean_t vfs_setuid; + boolean_t vfs_do_setuid; + boolean_t vfs_exec; + boolean_t vfs_do_exec; + boolean_t vfs_devices; + boolean_t vfs_do_devices; + boolean_t vfs_do_xattr; + boolean_t vfs_atime; + boolean_t vfs_do_atime; + boolean_t vfs_relatime; + boolean_t vfs_do_relatime; + boolean_t vfs_nbmand; + boolean_t vfs_do_nbmand; +} vfs_t; + +typedef struct zfs_mnt { + const char *mnt_osname; /* Objset name */ + char *mnt_data; /* Raw mount options */ +} zfs_mnt_t; + +struct zfsvfs { + vfs_t *z_vfs; /* generic fs struct */ + struct super_block *z_sb; /* generic super_block */ + struct zfsvfs *z_parent; /* parent fs */ + objset_t *z_os; /* objset reference */ + uint64_t z_flags; /* super_block flags */ + uint64_t z_root; /* id of root znode */ + uint64_t z_unlinkedobj; /* id of unlinked zapobj */ + uint64_t z_max_blksz; /* maximum block size for files */ + uint64_t z_fuid_obj; /* fuid table object number */ + uint64_t z_fuid_size; /* fuid table size */ + avl_tree_t z_fuid_idx; /* fuid tree keyed by index */ + avl_tree_t z_fuid_domain; /* fuid tree keyed by domain */ + krwlock_t z_fuid_lock; /* fuid lock */ + boolean_t z_fuid_loaded; /* fuid tables are loaded */ + boolean_t z_fuid_dirty; /* need to sync fuid table ? */ + struct zfs_fuid_info *z_fuid_replay; /* fuid info for replay */ + zilog_t *z_log; /* intent log pointer */ + uint_t z_acl_mode; /* acl chmod/mode behavior */ + uint_t z_acl_inherit; /* acl inheritance behavior */ + uint_t z_acl_type; /* type of ACL usable on this FS */ + zfs_case_t z_case; /* case-sense */ + boolean_t z_utf8; /* utf8-only */ + int z_norm; /* normalization flags */ + boolean_t z_relatime; /* enable relatime mount option */ + boolean_t z_unmounted; /* unmounted */ + rrmlock_t z_teardown_lock; + krwlock_t z_teardown_inactive_lock; + list_t z_all_znodes; /* all znodes in the fs */ + uint64_t z_nr_znodes; /* number of znodes in the fs */ + unsigned long z_rollback_time; /* last online rollback time */ + unsigned long z_snap_defer_time; /* last snapshot unmount deferral */ + kmutex_t z_znodes_lock; /* lock for z_all_znodes */ + arc_prune_t *z_arc_prune; /* called by ARC to prune caches */ + struct inode *z_ctldir; /* .zfs directory inode */ + boolean_t z_show_ctldir; /* expose .zfs in the root dir */ + boolean_t z_issnap; /* true if this is a snapshot */ + boolean_t z_vscan; /* virus scan on/off */ + boolean_t z_use_fuids; /* version allows fuids */ + boolean_t z_replay; /* set during ZIL replay */ + boolean_t z_use_sa; /* version allow system attributes */ + boolean_t z_xattr_sa; /* allow xattrs to be stores as SA */ + boolean_t z_draining; /* is true when drain is active */ + boolean_t z_drain_cancel; /* signal the unlinked drain to stop */ + uint64_t z_version; /* ZPL version */ + uint64_t z_shares_dir; /* hidden shares dir */ + dataset_kstats_t z_kstat; /* fs kstats */ + kmutex_t z_lock; + uint64_t z_userquota_obj; + uint64_t z_groupquota_obj; + uint64_t z_userobjquota_obj; + uint64_t z_groupobjquota_obj; + uint64_t z_projectquota_obj; + uint64_t z_projectobjquota_obj; + uint64_t z_replay_eof; /* New end of file - replay only */ + sa_attr_type_t *z_attr_table; /* SA attr mapping->id */ + uint64_t z_hold_size; /* znode hold array size */ + avl_tree_t *z_hold_trees; /* znode hold trees */ + kmutex_t *z_hold_locks; /* znode hold locks */ + taskqid_t z_drain_task; /* task id for the unlink drain task */ +}; + +#define ZSB_XATTR 0x0001 /* Enable user xattrs */ + +/* + * Allow a maximum number of links. While ZFS does not internally limit + * this the inode->i_nlink member is defined as an unsigned int. To be + * safe we use 2^31-1 as the limit. + */ +#define ZFS_LINK_MAX ((1U << 31) - 1U) + +/* + * Normal filesystems (those not under .zfs/snapshot) have a total + * file ID size limited to 12 bytes (including the length field) due to + * NFSv2 protocol's limitation of 32 bytes for a filehandle. For historical + * reasons, this same limit is being imposed by the Solaris NFSv3 implementation + * (although the NFSv3 protocol actually permits a maximum of 64 bytes). It + * is not possible to expand beyond 12 bytes without abandoning support + * of NFSv2. + * + * For normal filesystems, we partition up the available space as follows: + * 2 bytes fid length (required) + * 6 bytes object number (48 bits) + * 4 bytes generation number (32 bits) + * + * We reserve only 48 bits for the object number, as this is the limit + * currently defined and imposed by the DMU. + */ +typedef struct zfid_short { + uint16_t zf_len; + uint8_t zf_object[6]; /* obj[i] = obj >> (8 * i) */ + uint8_t zf_gen[4]; /* gen[i] = gen >> (8 * i) */ +} zfid_short_t; + +/* + * Filesystems under .zfs/snapshot have a total file ID size of 22 bytes + * (including the length field). This makes files under .zfs/snapshot + * accessible by NFSv3 and NFSv4, but not NFSv2. + * + * For files under .zfs/snapshot, we partition up the available space + * as follows: + * 2 bytes fid length (required) + * 6 bytes object number (48 bits) + * 4 bytes generation number (32 bits) + * 6 bytes objset id (48 bits) + * 4 bytes currently just zero (32 bits) + * + * We reserve only 48 bits for the object number and objset id, as these are + * the limits currently defined and imposed by the DMU. + */ +typedef struct zfid_long { + zfid_short_t z_fid; + uint8_t zf_setid[6]; /* obj[i] = obj >> (8 * i) */ + uint8_t zf_setgen[4]; /* gen[i] = gen >> (8 * i) */ +} zfid_long_t; + +#define SHORT_FID_LEN (sizeof (zfid_short_t) - sizeof (uint16_t)) +#define LONG_FID_LEN (sizeof (zfid_long_t) - sizeof (uint16_t)) + +extern void zfs_init(void); +extern void zfs_fini(void); + +extern int zfs_suspend_fs(zfsvfs_t *zfsvfs); +extern int zfs_resume_fs(zfsvfs_t *zfsvfs, struct dsl_dataset *ds); +extern int zfs_end_fs(zfsvfs_t *zfsvfs, struct dsl_dataset *ds); +extern void zfs_exit_fs(zfsvfs_t *zfsvfs); +extern int zfs_set_version(zfsvfs_t *zfsvfs, uint64_t newvers); +extern int zfsvfs_create(const char *name, boolean_t readony, zfsvfs_t **zfvp); +extern int zfsvfs_create_impl(zfsvfs_t **zfvp, zfsvfs_t *zfsvfs, objset_t *os); +extern void zfsvfs_free(zfsvfs_t *zfsvfs); +extern int zfs_check_global_label(const char *dsname, const char *hexsl); + +extern boolean_t zfs_is_readonly(zfsvfs_t *zfsvfs); +extern int zfs_domount(struct super_block *sb, zfs_mnt_t *zm, int silent); +extern void zfs_preumount(struct super_block *sb); +extern int zfs_umount(struct super_block *sb); +extern int zfs_remount(struct super_block *sb, int *flags, zfs_mnt_t *zm); +extern int zfs_statvfs(struct inode *ip, struct kstatfs *statp); +extern int zfs_vget(struct super_block *sb, struct inode **ipp, fid_t *fidp); +extern int zfs_prune(struct super_block *sb, unsigned long nr_to_scan, + int *objects); +extern int zfs_get_temporary_prop(dsl_dataset_t *ds, zfs_prop_t zfs_prop, + uint64_t *val, char *setpoint); + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_FS_ZFS_VFSOPS_H */ diff --git a/include/os/linux/zfs/sys/zfs_vnops.h b/include/os/linux/zfs/sys/zfs_vnops.h new file mode 100644 index 000000000000..24a2082d35d6 --- /dev/null +++ b/include/os/linux/zfs/sys/zfs_vnops.h @@ -0,0 +1,91 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + */ + +#ifndef _SYS_FS_ZFS_VNOPS_H +#define _SYS_FS_ZFS_VNOPS_H + +#include <sys/vnode.h> +#include <sys/xvattr.h> +#include <sys/uio.h> +#include <sys/cred.h> +#include <sys/fcntl.h> +#include <sys/pathname.h> +#include <sys/zpl.h> +#include <sys/zfs_file.h> + +#ifdef __cplusplus +extern "C" { +#endif + +extern int zfs_open(struct inode *ip, int mode, int flag, cred_t *cr); +extern int zfs_close(struct inode *ip, int flag, cred_t *cr); +extern int zfs_holey(struct inode *ip, int cmd, loff_t *off); +extern int zfs_read(struct inode *ip, uio_t *uio, int ioflag, cred_t *cr); +extern int zfs_write(struct inode *ip, uio_t *uio, int ioflag, cred_t *cr); +extern int zfs_write_simple(znode_t *zp, const void *data, size_t len, + loff_t pos, size_t *resid); +extern int zfs_access(struct inode *ip, int mode, int flag, cred_t *cr); +extern int zfs_lookup(znode_t *dzp, char *nm, znode_t **zpp, + int flags, cred_t *cr, int *direntflags, pathname_t *realpnp); +extern int zfs_create(znode_t *dzp, char *name, vattr_t *vap, int excl, + int mode, znode_t **zpp, cred_t *cr, int flag, vsecattr_t *vsecp); +extern int zfs_tmpfile(struct inode *dip, vattr_t *vapzfs, int excl, + int mode, struct inode **ipp, cred_t *cr, int flag, vsecattr_t *vsecp); +extern int zfs_remove(znode_t *dzp, char *name, cred_t *cr, int flags); +extern int zfs_mkdir(znode_t *dzp, char *dirname, vattr_t *vap, + znode_t **zpp, cred_t *cr, int flags, vsecattr_t *vsecp); +extern int zfs_rmdir(znode_t *dzp, char *name, znode_t *cwd, + cred_t *cr, int flags); +extern int zfs_readdir(struct inode *ip, zpl_dir_context_t *ctx, cred_t *cr); +extern int zfs_fsync(znode_t *zp, int syncflag, cred_t *cr); +extern int zfs_getattr_fast(struct inode *ip, struct kstat *sp); +extern int zfs_setattr(znode_t *zp, vattr_t *vap, int flag, cred_t *cr); +extern int zfs_rename(znode_t *sdzp, char *snm, znode_t *tdzp, + char *tnm, cred_t *cr, int flags); +extern int zfs_symlink(znode_t *dzp, char *name, vattr_t *vap, + char *link, znode_t **zpp, cred_t *cr, int flags); +extern int zfs_readlink(struct inode *ip, uio_t *uio, cred_t *cr); +extern int zfs_link(znode_t *tdzp, znode_t *szp, + char *name, cred_t *cr, int flags); +extern void zfs_inactive(struct inode *ip); +extern int zfs_space(znode_t *zp, int cmd, flock64_t *bfp, int flag, + offset_t offset, cred_t *cr); +extern int zfs_fid(struct inode *ip, fid_t *fidp); +extern int zfs_getsecattr(struct inode *ip, vsecattr_t *vsecp, int flag, + cred_t *cr); +extern int zfs_setsecattr(znode_t *zp, vsecattr_t *vsecp, int flag, + cred_t *cr); +extern int zfs_getpage(struct inode *ip, struct page *pl[], int nr_pages); +extern int zfs_putpage(struct inode *ip, struct page *pp, + struct writeback_control *wbc); +extern int zfs_dirty_inode(struct inode *ip, int flags); +extern int zfs_map(struct inode *ip, offset_t off, caddr_t *addrp, + size_t len, unsigned long vm_flags); +extern void zfs_zrele_async(znode_t *zp); + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_FS_ZFS_VNOPS_H */ diff --git a/include/os/linux/zfs/sys/zfs_znode_impl.h b/include/os/linux/zfs/sys/zfs_znode_impl.h new file mode 100644 index 000000000000..39bbd135ac06 --- /dev/null +++ b/include/os/linux/zfs/sys/zfs_znode_impl.h @@ -0,0 +1,168 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2018 by Delphix. All rights reserved. + * Copyright 2016 Nexenta Systems, Inc. All rights reserved. + */ + +#ifndef _SYS_ZFS_ZNODE_IMPL_H +#define _SYS_ZFS_ZNODE_IMPL_H + +#ifndef _KERNEL +#error "no user serviceable parts within" +#endif + +#include <sys/isa_defs.h> +#include <sys/types32.h> +#include <sys/list.h> +#include <sys/dmu.h> +#include <sys/sa.h> +#include <sys/zfs_vfsops.h> +#include <sys/rrwlock.h> +#include <sys/zfs_sa.h> +#include <sys/zfs_stat.h> +#include <sys/zfs_rlock.h> + + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZNODE_OS_FIELDS \ + struct inode z_inode; + + +/* + * Convert between znode pointers and inode pointers + */ +#define ZTOI(znode) (&((znode)->z_inode)) +#define ITOZ(inode) (container_of((inode), znode_t, z_inode)) +#define ZTOZSB(znode) ((zfsvfs_t *)(ZTOI(znode)->i_sb->s_fs_info)) +#define ITOZSB(inode) ((zfsvfs_t *)((inode)->i_sb->s_fs_info)) + +#define ZTOTYPE(zp) (ZTOI(zp)->i_mode) +#define ZTOGID(zp) (ZTOI(zp)->i_gid) +#define ZTOUID(zp) (ZTOI(zp)->i_uid) +#define ZTONLNK(zp) (ZTOI(zp)->i_nlink) + +#define Z_ISBLK(type) S_ISBLK(type) +#define Z_ISCHR(type) S_ISCHR(type) +#define Z_ISLNK(type) S_ISLNK(type) +#define Z_ISDEV(type) (S_ISCHR(type) || S_ISBLK(type) || S_ISFIFO(type)) + +#define zhold(zp) igrab(ZTOI((zp))) +#define zrele(zp) iput(ZTOI((zp))) + +/* Called on entry to each ZFS inode and vfs operation. */ +#define ZFS_ENTER_ERROR(zfsvfs, error) \ +do { \ + rrm_enter_read(&(zfsvfs)->z_teardown_lock, FTAG); \ + if ((zfsvfs)->z_unmounted) { \ + ZFS_EXIT(zfsvfs); \ + return (error); \ + } \ +} while (0) +#define ZFS_ENTER(zfsvfs) ZFS_ENTER_ERROR(zfsvfs, EIO) +#define ZPL_ENTER(zfsvfs) ZFS_ENTER_ERROR(zfsvfs, -EIO) + +/* Must be called before exiting the operation. */ +#define ZFS_EXIT(zfsvfs) \ +do { \ + zfs_exit_fs(zfsvfs); \ + rrm_exit(&(zfsvfs)->z_teardown_lock, FTAG); \ +} while (0) +#define ZPL_EXIT(zfsvfs) ZFS_EXIT(zfsvfs) + +/* Verifies the znode is valid. */ +#define ZFS_VERIFY_ZP_ERROR(zp, error) \ +do { \ + if ((zp)->z_sa_hdl == NULL) { \ + ZFS_EXIT(ZTOZSB(zp)); \ + return (error); \ + } \ +} while (0) +#define ZFS_VERIFY_ZP(zp) ZFS_VERIFY_ZP_ERROR(zp, EIO) +#define ZPL_VERIFY_ZP(zp) ZFS_VERIFY_ZP_ERROR(zp, -EIO) + +/* + * Macros for dealing with dmu_buf_hold + */ +#define ZFS_OBJ_MTX_SZ 64 +#define ZFS_OBJ_MTX_MAX (1024 * 1024) +#define ZFS_OBJ_HASH(zfsvfs, obj) ((obj) & ((zfsvfs->z_hold_size) - 1)) + +extern unsigned int zfs_object_mutex_size; + +/* + * Encode ZFS stored time values from a struct timespec / struct timespec64. + */ +#define ZFS_TIME_ENCODE(tp, stmp) \ +do { \ + (stmp)[0] = (uint64_t)(tp)->tv_sec; \ + (stmp)[1] = (uint64_t)(tp)->tv_nsec; \ +} while (0) + +#if defined(HAVE_INODE_TIMESPEC64_TIMES) +/* + * Decode ZFS stored time values to a struct timespec64 + * 4.18 and newer kernels. + */ +#define ZFS_TIME_DECODE(tp, stmp) \ +do { \ + (tp)->tv_sec = (time64_t)(stmp)[0]; \ + (tp)->tv_nsec = (long)(stmp)[1]; \ +} while (0) +#else +/* + * Decode ZFS stored time values to a struct timespec + * 4.17 and older kernels. + */ +#define ZFS_TIME_DECODE(tp, stmp) \ +do { \ + (tp)->tv_sec = (time_t)(stmp)[0]; \ + (tp)->tv_nsec = (long)(stmp)[1]; \ +} while (0) +#endif /* HAVE_INODE_TIMESPEC64_TIMES */ + +struct znode; + +extern int zfs_sync(struct super_block *, int, cred_t *); +extern int zfs_inode_alloc(struct super_block *, struct inode **ip); +extern void zfs_inode_destroy(struct inode *); +extern void zfs_inode_update(struct znode *); +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_get_data_t zfs_get_data; +extern zil_replay_func_t *zfs_replay_vector[TX_MAX_TYPE]; +extern int zfsfstype; + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_ZFS_ZNODE_IMPL_H */ diff --git a/include/os/linux/zfs/sys/zpl.h b/include/os/linux/zfs/sys/zpl.h new file mode 100644 index 000000000000..ef5a0b842d09 --- /dev/null +++ b/include/os/linux/zfs/sys/zpl.h @@ -0,0 +1,183 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2011, Lawrence Livermore National Security, LLC. + */ + +#ifndef _SYS_ZPL_H +#define _SYS_ZPL_H + +#include <sys/mntent.h> +#include <sys/vfs.h> +#include <linux/aio.h> +#include <linux/dcache_compat.h> +#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> + +/* zpl_inode.c */ +extern void zpl_vap_init(vattr_t *vap, struct inode *dir, + umode_t mode, cred_t *cr); + +extern const struct inode_operations zpl_inode_operations; +extern const struct inode_operations zpl_dir_inode_operations; +extern const struct inode_operations zpl_symlink_inode_operations; +extern const struct inode_operations zpl_special_inode_operations; +extern dentry_operations_t zpl_dentry_operations; + +/* zpl_file.c */ +extern ssize_t zpl_read_common(struct inode *ip, const char *buf, + size_t len, loff_t *ppos, uio_seg_t segment, int flags, + cred_t *cr); +extern ssize_t zpl_write_common(struct inode *ip, const char *buf, + size_t len, loff_t *ppos, uio_seg_t segment, int flags, + cred_t *cr); + +extern const struct address_space_operations zpl_address_space_operations; +extern const struct file_operations zpl_file_operations; +extern const struct file_operations zpl_dir_file_operations; + +/* zpl_super.c */ +extern void zpl_prune_sb(int64_t nr_to_scan, void *arg); + +extern const struct super_operations zpl_super_operations; +extern const struct export_operations zpl_export_operations; +extern struct file_system_type zpl_fs_type; + +/* zpl_xattr.c */ +extern ssize_t zpl_xattr_list(struct dentry *dentry, char *buf, size_t size); +extern int zpl_xattr_security_init(struct inode *ip, struct inode *dip, + const struct qstr *qstr); +#if defined(CONFIG_FS_POSIX_ACL) +#if defined(HAVE_SET_ACL) +extern int zpl_set_acl(struct inode *ip, struct posix_acl *acl, int type); +#endif /* HAVE_SET_ACL */ +extern struct posix_acl *zpl_get_acl(struct inode *ip, int type); +extern int zpl_init_acl(struct inode *ip, struct inode *dir); +extern int zpl_chmod_acl(struct inode *ip); +#else +static inline int +zpl_init_acl(struct inode *ip, struct inode *dir) +{ + return (0); +} + +static inline int +zpl_chmod_acl(struct inode *ip) +{ + return (0); +} +#endif /* CONFIG_FS_POSIX_ACL */ + +extern xattr_handler_t *zpl_xattr_handlers[]; + +/* zpl_ctldir.c */ +extern const struct file_operations zpl_fops_root; +extern const struct inode_operations zpl_ops_root; + +extern const struct file_operations zpl_fops_snapdir; +extern const struct inode_operations zpl_ops_snapdir; +extern const struct dentry_operations zpl_dops_snapdirs; + +extern const struct file_operations zpl_fops_shares; +extern const struct inode_operations zpl_ops_shares; + +#if defined(HAVE_VFS_ITERATE) || defined(HAVE_VFS_ITERATE_SHARED) + +#define ZPL_DIR_CONTEXT_INIT(_dirent, _actor, _pos) { \ + .actor = _actor, \ + .pos = _pos, \ +} + +typedef struct dir_context zpl_dir_context_t; + +#define zpl_dir_emit dir_emit +#define zpl_dir_emit_dot dir_emit_dot +#define zpl_dir_emit_dotdot dir_emit_dotdot +#define zpl_dir_emit_dots dir_emit_dots + +#else + +typedef struct zpl_dir_context { + void *dirent; + const filldir_t actor; + loff_t pos; +} zpl_dir_context_t; + +#define ZPL_DIR_CONTEXT_INIT(_dirent, _actor, _pos) { \ + .dirent = _dirent, \ + .actor = _actor, \ + .pos = _pos, \ +} + +static inline bool +zpl_dir_emit(zpl_dir_context_t *ctx, const char *name, int namelen, + uint64_t ino, unsigned type) +{ + return (!ctx->actor(ctx->dirent, name, namelen, ctx->pos, ino, type)); +} + +static inline bool +zpl_dir_emit_dot(struct file *file, zpl_dir_context_t *ctx) +{ + return (ctx->actor(ctx->dirent, ".", 1, ctx->pos, + file_inode(file)->i_ino, DT_DIR) == 0); +} + +static inline bool +zpl_dir_emit_dotdot(struct file *file, zpl_dir_context_t *ctx) +{ + return (ctx->actor(ctx->dirent, "..", 2, ctx->pos, + parent_ino(file_dentry(file)), DT_DIR) == 0); +} + +static inline bool +zpl_dir_emit_dots(struct file *file, zpl_dir_context_t *ctx) +{ + if (ctx->pos == 0) { + if (!zpl_dir_emit_dot(file, ctx)) + return (false); + ctx->pos = 1; + } + if (ctx->pos == 1) { + if (!zpl_dir_emit_dotdot(file, ctx)) + return (false); + ctx->pos = 2; + } + return (true); +} +#endif /* HAVE_VFS_ITERATE */ + +#if defined(HAVE_INODE_TIMESTAMP_TRUNCATE) +#define zpl_inode_timestamp_truncate(ts, ip) timestamp_truncate(ts, ip) +#elif defined(HAVE_INODE_TIMESPEC64_TIMES) +#define zpl_inode_timestamp_truncate(ts, ip) \ + timespec64_trunc(ts, (ip)->i_sb->s_time_gran) +#else +#define zpl_inode_timestamp_truncate(ts, ip) \ + timespec_trunc(ts, (ip)->i_sb->s_time_gran) +#endif + +#endif /* _SYS_ZPL_H */ |
