diff options
Diffstat (limited to 'sys/contrib/openzfs/module/os')
8 files changed, 131 insertions, 16 deletions
| diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/zio_crypt.c b/sys/contrib/openzfs/module/os/freebsd/zfs/zio_crypt.c index 91cf38016e00..8562c42b3220 100644 --- a/sys/contrib/openzfs/module/os/freebsd/zfs/zio_crypt.c +++ b/sys/contrib/openzfs/module/os/freebsd/zfs/zio_crypt.c @@ -437,6 +437,7 @@ zio_crypt_key_wrap(crypto_key_t *cwkey, zio_crypt_key_t *key, uint8_t *iv,  	ASSERT3U(crypt, <, ZIO_CRYPT_FUNCTIONS); +	memset(&cuio_s, 0, sizeof (cuio_s));  	zfs_uio_init(&cuio, &cuio_s);  	keydata_len = zio_crypt_table[crypt].ci_keylen; @@ -519,6 +520,7 @@ zio_crypt_key_unwrap(crypto_key_t *cwkey, uint64_t crypt, uint64_t version,  	keydata_len = zio_crypt_table[crypt].ci_keylen;  	rw_init(&key->zk_salt_lock, NULL, RW_DEFAULT, NULL); +	memset(&cuio_s, 0, sizeof (cuio_s));  	zfs_uio_init(&cuio, &cuio_s);  	/* diff --git a/sys/contrib/openzfs/module/os/linux/spl/spl-zone.c b/sys/contrib/openzfs/module/os/linux/spl/spl-zone.c index 45c2999a4bb1..b2eae5d00b10 100644 --- a/sys/contrib/openzfs/module/os/linux/spl/spl-zone.c +++ b/sys/contrib/openzfs/module/os/linux/spl/spl-zone.c @@ -25,6 +25,10 @@   * SUCH DAMAGE.   */ +/* + * Copyright (c) 2025, Rob Norris <robn@despairlabs.com> + */ +  #include <sys/types.h>  #include <sys/sysmacros.h>  #include <sys/kmem.h> @@ -56,6 +60,19 @@ typedef struct zone_dataset {  } zone_dataset_t;  #ifdef CONFIG_USER_NS + +/* + * Linux 6.18 moved the generic namespace type away from ns->ops->type onto + * ns_common itself. + */ +#ifdef HAVE_NS_COMMON_TYPE +#define	ns_is_newuser(ns)	\ +	((ns)->ns_type == CLONE_NEWUSER) +#else +#define	ns_is_newuser(ns)	\ +	((ns)->ops != NULL && (ns)->ops->type == CLONE_NEWUSER) +#endif +  /*   * Returns:   * - 0 on success @@ -84,7 +101,7 @@ user_ns_get(int fd, struct user_namespace **userns)  		goto done;  	}  	ns = get_proc_ns(file_inode(nsfile)); -	if (ns->ops->type != CLONE_NEWUSER) { +	if (!ns_is_newuser(ns)) {  		error = ENOTTY;  		goto done;  	} diff --git a/sys/contrib/openzfs/module/os/linux/zfs/abd_os.c b/sys/contrib/openzfs/module/os/linux/zfs/abd_os.c index 8a8316f63c48..18f2426fbbfc 100644 --- a/sys/contrib/openzfs/module/os/linux/zfs/abd_os.c +++ b/sys/contrib/openzfs/module/os/linux/zfs/abd_os.c @@ -23,6 +23,7 @@   * Copyright (c) 2014 by Chunwei Chen. All rights reserved.   * Copyright (c) 2019 by Delphix. All rights reserved.   * Copyright (c) 2023, 2024, Klara Inc. + * Copyright (c) 2025, Rob Norris <robn@despairlabs.com>   */  /* @@ -1109,6 +1110,14 @@ abd_return_buf_copy(abd_t *abd, void *buf, size_t n)  #define	ABD_ITER_PAGE_SIZE(page)	(PAGESIZE)  #endif +#ifndef nth_page +/* + * Since 6.18 nth_page() no longer exists, and is no longer required to iterate + * within a single SG entry, so we replace it with a simple addition. + */ +#define	nth_page(p, n)	((p)+(n)) +#endif +  void  abd_iter_page(struct abd_iter *aiter)  { diff --git a/sys/contrib/openzfs/module/os/linux/zfs/zfs_acl.c b/sys/contrib/openzfs/module/os/linux/zfs/zfs_acl.c index daa4b5776837..934d74a112fd 100644 --- a/sys/contrib/openzfs/module/os/linux/zfs/zfs_acl.c +++ b/sys/contrib/openzfs/module/os/linux/zfs/zfs_acl.c @@ -2524,7 +2524,7 @@ zfs_zaccess_common(znode_t *zp, uint32_t v4_mode, uint32_t *working_mode,  	 * Also note: DOS R/O is ignored for directories.  	 */  	if ((v4_mode & WRITE_MASK_DATA) && -	    S_ISDIR(ZTOI(zp)->i_mode) && +	    !S_ISDIR(ZTOI(zp)->i_mode) &&  	    (zp->z_pflags & ZFS_READONLY)) {  		return (SET_ERROR(EPERM));  	} diff --git a/sys/contrib/openzfs/module/os/linux/zfs/zfs_vnops_os.c b/sys/contrib/openzfs/module/os/linux/zfs/zfs_vnops_os.c index 6106726651a3..e845ad69ad78 100644 --- a/sys/contrib/openzfs/module/os/linux/zfs/zfs_vnops_os.c +++ b/sys/contrib/openzfs/module/os/linux/zfs/zfs_vnops_os.c @@ -2033,10 +2033,7 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr, zidmap_t *mnt_ns)  		goto out3;  	} -	if ((mask & ATTR_SIZE) && (zp->z_pflags & ZFS_READONLY)) { -		err = SET_ERROR(EPERM); -		goto out3; -	} +	/* ZFS_READONLY will be handled in zfs_zaccess() */  	/*  	 * Verify timestamps doesn't overflow 32 bits. diff --git a/sys/contrib/openzfs/module/os/linux/zfs/zpl_file.c b/sys/contrib/openzfs/module/os/linux/zfs/zpl_file.c index d07317b0d910..02965ac8cbee 100644 --- a/sys/contrib/openzfs/module/os/linux/zfs/zpl_file.c +++ b/sys/contrib/openzfs/module/os/linux/zfs/zpl_file.c @@ -23,6 +23,7 @@   * Copyright (c) 2011, Lawrence Livermore National Security, LLC.   * Copyright (c) 2015 by Chunwei Chen. All rights reserved.   * Copyright (c) 2025, Klara, Inc. + * Copyright (c) 2025, Rob Norris <robn@despairlabs.com>   */ @@ -478,6 +479,7 @@ zpl_putpage(struct page *pp, struct writeback_control *wbc, void *data)  	return (ret);  } +#ifdef HAVE_WRITE_CACHE_PAGES  #ifdef HAVE_WRITEPAGE_T_FOLIO  static int  zpl_putfolio(struct folio *pp, struct writeback_control *wbc, void *data) @@ -499,6 +501,78 @@ zpl_write_cache_pages(struct address_space *mapping,  #endif  	return (result);  } +#else +static inline int +zpl_write_cache_pages(struct address_space *mapping, +    struct writeback_control *wbc, void *data) +{ +	pgoff_t start = wbc->range_start >> PAGE_SHIFT; +	pgoff_t end = wbc->range_end >> PAGE_SHIFT; + +	struct folio_batch fbatch; +	folio_batch_init(&fbatch); + +	/* +	 * This atomically (-ish) tags all DIRTY pages in the range with +	 * TOWRITE, allowing users to continue dirtying or undirtying pages +	 * while we get on with writeback, without us treading on each other. +	 */ +	tag_pages_for_writeback(mapping, start, end); + +	int err = 0; +	unsigned int npages; + +	/* +	 * Grab references to the TOWRITE pages just flagged. This may not get +	 * all of them, so we do it in a loop until there are none left. +	 */ +	while ((npages = filemap_get_folios_tag(mapping, &start, end, +	    PAGECACHE_TAG_TOWRITE, &fbatch)) != 0) { + +		/* Loop over each page and write it out. */ +		struct folio *folio; +		while ((folio = folio_batch_next(&fbatch)) != NULL) { +			folio_lock(folio); + +			/* +			 * If the folio has been remapped, or is no longer +			 * dirty, then there's nothing to do. +			 */ +			if (folio->mapping != mapping || +			    !folio_test_dirty(folio)) { +				folio_unlock(folio); +				continue; +			} + +			/* +			 * If writeback is already in progress, wait for it to +			 * finish. We continue after this even if the page +			 * ends up clean; zfs_putpage() will skip it if no +			 * further work is required. +			 */ +			while (folio_test_writeback(folio)) +				folio_wait_bit(folio, PG_writeback); + +			/* +			 * Write it out and collect any error. zfs_putpage() +			 * will clear the TOWRITE and DIRTY flags, and return +			 * with the page unlocked. +			 */ +			int ferr = zpl_putpage(&folio->page, wbc, data); +			if (err == 0 && ferr != 0) +				err = ferr; + +			/* Housekeeping for the caller. */ +			wbc->nr_to_write -= folio_nr_pages(folio); +		} + +		/* Release any remaining references on the batch. */ +		folio_batch_release(&fbatch); +	} + +	return (err); +} +#endif  static int  zpl_writepages(struct address_space *mapping, struct writeback_control *wbc) diff --git a/sys/contrib/openzfs/module/os/linux/zfs/zpl_super.c b/sys/contrib/openzfs/module/os/linux/zfs/zpl_super.c index 444948d03cb3..347b352506e5 100644 --- a/sys/contrib/openzfs/module/os/linux/zfs/zpl_super.c +++ b/sys/contrib/openzfs/module/os/linux/zfs/zpl_super.c @@ -23,6 +23,7 @@   * Copyright (c) 2011, Lawrence Livermore National Security, LLC.   * Copyright (c) 2023, Datto Inc. All rights reserved.   * Copyright (c) 2025, Klara, Inc. + * Copyright (c) 2025, Rob Norris <robn@despairlabs.com>   */ @@ -33,6 +34,7 @@  #include <sys/zpl.h>  #include <linux/iversion.h>  #include <linux/version.h> +#include <linux/vfs_compat.h>  /*   * What to do when the last reference to an inode is released. If 0, the kernel @@ -104,7 +106,7 @@ zpl_dirty_inode(struct inode *ip, int flags)   * reporting memory pressure and requests OpenZFS release some memory (see   * zfs_prune()).   * - * When set to 1, we call generic_delete_node(), which always returns "destroy + * When set to 1, we call generic_delete_inode(), which always returns "destroy   * immediately", resulting in inodes being destroyed immediately, releasing   * their associated dnodes and dbufs to the dbuf cached and the ARC to be   * evicted as normal. diff --git a/sys/contrib/openzfs/module/os/linux/zfs/zvol_os.c b/sys/contrib/openzfs/module/os/linux/zfs/zvol_os.c index 4e66bee7744d..fe939150b641 100644 --- a/sys/contrib/openzfs/module/os/linux/zfs/zvol_os.c +++ b/sys/contrib/openzfs/module/os/linux/zfs/zvol_os.c @@ -21,7 +21,7 @@   */  /*   * Copyright (c) 2012, 2020 by Delphix. All rights reserved. - * Copyright (c) 2024, Rob Norris <robn@despairlabs.com> + * Copyright (c) 2024, 2025, Rob Norris <robn@despairlabs.com>   * Copyright (c) 2024, 2025, Klara, Inc.   */ @@ -1032,12 +1032,12 @@ zvol_os_update_volsize(zvol_state_t *zv, uint64_t volsize)   * tiny devices.  For devices over 1 Mib a standard head and sector count   * is used to keep the cylinders count reasonable.   */ -static int -zvol_getgeo(struct block_device *bdev, struct hd_geometry *geo) +static inline int +zvol_getgeo_impl(struct gendisk *disk, struct hd_geometry *geo)  { +	zvol_state_t *zv = atomic_load_ptr(&disk->private_data);  	sector_t sectors; -	zvol_state_t *zv = atomic_load_ptr(&bdev->bd_disk->private_data);  	ASSERT3P(zv, !=, NULL);  	ASSERT3U(zv->zv_open_count, >, 0); @@ -1057,6 +1057,20 @@ zvol_getgeo(struct block_device *bdev, struct hd_geometry *geo)  	return (0);  } +#ifdef HAVE_BLOCK_DEVICE_OPERATIONS_GETGEO_GENDISK +static int +zvol_getgeo(struct gendisk *disk, struct hd_geometry *geo) +{ +	return (zvol_getgeo_impl(disk, geo)); +} +#else +static int +zvol_getgeo(struct block_device *bdev, struct hd_geometry *geo) +{ +	return (zvol_getgeo_impl(bdev->bd_disk, geo)); +} +#endif +  /*   * Why have two separate block_device_operations structs?   * @@ -1500,7 +1514,7 @@ zvol_os_remove_minor(zvol_state_t *zv)  	if (zso->use_blk_mq)  		blk_mq_free_tag_set(&zso->tag_set); -	ida_simple_remove(&zvol_ida, MINOR(zso->zvo_dev) >> ZVOL_MINOR_BITS); +	ida_free(&zvol_ida, MINOR(zso->zvo_dev) >> ZVOL_MINOR_BITS);  	kmem_free(zso, sizeof (struct zvol_state_os)); @@ -1655,7 +1669,7 @@ zvol_os_create_minor(const char *name)  	if (zvol_inhibit_dev)  		return (0); -	idx = ida_simple_get(&zvol_ida, 0, 0, kmem_flags_convert(KM_SLEEP)); +	idx = ida_alloc(&zvol_ida, kmem_flags_convert(KM_SLEEP));  	if (idx < 0)  		return (SET_ERROR(-idx));  	minor = idx << ZVOL_MINOR_BITS; @@ -1663,7 +1677,7 @@ zvol_os_create_minor(const char *name)  		/* too many partitions can cause an overflow */  		zfs_dbgmsg("zvol: create minor overflow: %s, minor %u/%u",  		    name, minor, MINOR(minor)); -		ida_simple_remove(&zvol_ida, idx); +		ida_free(&zvol_ida, idx);  		return (SET_ERROR(EINVAL));  	} @@ -1671,7 +1685,7 @@ zvol_os_create_minor(const char *name)  	if (zv) {  		ASSERT(MUTEX_HELD(&zv->zv_state_lock));  		mutex_exit(&zv->zv_state_lock); -		ida_simple_remove(&zvol_ida, idx); +		ida_free(&zvol_ida, idx);  		return (SET_ERROR(EEXIST));  	} @@ -1771,7 +1785,7 @@ out_doi:  		rw_exit(&zvol_state_lock);  		error = zvol_os_add_disk(zv->zv_zso->zvo_disk);  	} else { -		ida_simple_remove(&zvol_ida, idx); +		ida_free(&zvol_ida, idx);  	}  	return (error); | 
