diff options
Diffstat (limited to 'fs/btrfs')
| -rw-r--r-- | fs/btrfs/Makefile | 1 | ||||
| -rw-r--r-- | fs/btrfs/compression.c | 18 | ||||
| -rw-r--r-- | fs/btrfs/ctree.h | 3 | ||||
| -rw-r--r-- | fs/btrfs/disk-io.c | 9 | ||||
| -rw-r--r-- | fs/btrfs/export.c | 1 | ||||
| -rw-r--r-- | fs/btrfs/export.h | 1 | ||||
| -rw-r--r-- | fs/btrfs/extent_io.c | 11 | ||||
| -rw-r--r-- | fs/btrfs/extent_io.h | 1 | ||||
| -rw-r--r-- | fs/btrfs/extent_map.c | 1 | ||||
| -rw-r--r-- | fs/btrfs/extent_map.h | 1 | ||||
| -rw-r--r-- | fs/btrfs/inode-map.h | 1 | ||||
| -rw-r--r-- | fs/btrfs/inode.c | 27 | ||||
| -rw-r--r-- | fs/btrfs/ioctl.c | 12 | ||||
| -rw-r--r-- | fs/btrfs/qgroup.c | 6 | ||||
| -rw-r--r-- | fs/btrfs/relocation.c | 2 | ||||
| -rw-r--r-- | fs/btrfs/send.c | 2 | ||||
| -rw-r--r-- | fs/btrfs/super.c | 2 | ||||
| -rw-r--r-- | fs/btrfs/sysfs.h | 1 | ||||
| -rw-r--r-- | fs/btrfs/tree-log.c | 12 | ||||
| -rw-r--r-- | fs/btrfs/volumes.c | 2 | 
20 files changed, 84 insertions, 30 deletions
| diff --git a/fs/btrfs/Makefile b/fs/btrfs/Makefile index 962a95aefb81..f2cd9dedb037 100644 --- a/fs/btrfs/Makefile +++ b/fs/btrfs/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0  obj-$(CONFIG_BTRFS_FS) := btrfs.o diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index b51d23f5cafa..280384bf34f1 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c @@ -107,7 +107,8 @@ static void end_compressed_bio_read(struct bio *bio)  	struct inode *inode;  	struct page *page;  	unsigned long index; -	int ret; +	unsigned int mirror = btrfs_io_bio(bio)->mirror_num; +	int ret = 0;  	if (bio->bi_status)  		cb->errors = 1; @@ -118,6 +119,21 @@ static void end_compressed_bio_read(struct bio *bio)  	if (!refcount_dec_and_test(&cb->pending_bios))  		goto out; +	/* +	 * Record the correct mirror_num in cb->orig_bio so that +	 * read-repair can work properly. +	 */ +	ASSERT(btrfs_io_bio(cb->orig_bio)); +	btrfs_io_bio(cb->orig_bio)->mirror_num = mirror; +	cb->mirror_num = mirror; + +	/* +	 * Some IO in this cb have failed, just skip checksum as there +	 * is no way it could be correct. +	 */ +	if (cb->errors == 1) +		goto csum_failed; +  	inode = cb->inode;  	ret = check_compressed_csum(BTRFS_I(inode), cb,  				    (u64)bio->bi_iter.bi_sector << 9); diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 5a8933da39a7..8fc690384c58 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -709,7 +709,6 @@ struct btrfs_delayed_root;  #define BTRFS_FS_OPEN				5  #define BTRFS_FS_QUOTA_ENABLED			6  #define BTRFS_FS_QUOTA_ENABLING			7 -#define BTRFS_FS_QUOTA_DISABLING		8  #define BTRFS_FS_UPDATE_UUID_TREE_GEN		9  #define BTRFS_FS_CREATING_FREE_SPACE_TREE	10  #define BTRFS_FS_BTREE_ERR			11 @@ -723,7 +722,7 @@ struct btrfs_delayed_root;   * Indicate that a whole-filesystem exclusive operation is running   * (device replace, resize, device add/delete, balance)   */ -#define BTRFS_FS_EXCL_OP			14 +#define BTRFS_FS_EXCL_OP			16  struct btrfs_fs_info {  	u8 fsid[BTRFS_FSID_SIZE]; diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 487bbe4fb3c6..dfdab849037b 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -3643,7 +3643,14 @@ int write_all_supers(struct btrfs_fs_info *fs_info, int max_mirrors)  	u64 flags;  	do_barriers = !btrfs_test_opt(fs_info, NOBARRIER); -	backup_super_roots(fs_info); + +	/* +	 * max_mirrors == 0 indicates we're from commit_transaction, +	 * not from fsync where the tree roots in fs_info have not +	 * been consistent on disk. +	 */ +	if (max_mirrors == 0) +		backup_super_roots(fs_info);  	sb = fs_info->super_for_commit;  	dev_item = &sb->dev_item; diff --git a/fs/btrfs/export.c b/fs/btrfs/export.c index fa66980726c9..3aeb5770f896 100644 --- a/fs/btrfs/export.c +++ b/fs/btrfs/export.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #include <linux/fs.h>  #include <linux/types.h>  #include "ctree.h" diff --git a/fs/btrfs/export.h b/fs/btrfs/export.h index 074348a95841..91b3908e7c54 100644 --- a/fs/btrfs/export.h +++ b/fs/btrfs/export.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */  #ifndef BTRFS_EXPORT_H  #define BTRFS_EXPORT_H diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 3e5bb0cdd3cd..7fa50e12f18e 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #include <linux/bitops.h>  #include <linux/slab.h>  #include <linux/bio.h> @@ -2801,7 +2802,7 @@ static int submit_extent_page(unsigned int opf, struct extent_io_tree *tree,  		}  	} -	bio = btrfs_bio_alloc(bdev, sector << 9); +	bio = btrfs_bio_alloc(bdev, (u64)sector << 9);  	bio_add_page(bio, page, page_size, offset);  	bio->bi_end_io = end_io_func;  	bio->bi_private = tree; @@ -3471,8 +3472,7 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc,  	unsigned int write_flags = 0;  	unsigned long nr_written = 0; -	if (wbc->sync_mode == WB_SYNC_ALL) -		write_flags = REQ_SYNC; +	write_flags = wbc_to_write_flags(wbc);  	trace___extent_writepage(page, inode, wbc); @@ -3718,7 +3718,7 @@ static noinline_for_stack int write_one_eb(struct extent_buffer *eb,  	unsigned long i, num_pages;  	unsigned long bio_flags = 0;  	unsigned long start, end; -	unsigned int write_flags = (epd->sync_io ? REQ_SYNC : 0) | REQ_META; +	unsigned int write_flags = wbc_to_write_flags(wbc) | REQ_META;  	int ret = 0;  	clear_bit(EXTENT_BUFFER_WRITE_ERR, &eb->bflags); @@ -4063,9 +4063,6 @@ static void flush_epd_write_bio(struct extent_page_data *epd)  	if (epd->bio) {  		int ret; -		bio_set_op_attrs(epd->bio, REQ_OP_WRITE, -				 epd->sync_io ? REQ_SYNC : 0); -  		ret = submit_one_bio(epd->bio, 0, epd->bio_flags);  		BUG_ON(ret < 0); /* -ENOMEM */  		epd->bio = NULL; diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index faffa28ba707..e5535bbe6953 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */  #ifndef __EXTENTIO__  #define __EXTENTIO__ diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c index 69850155870c..2e348fb0b280 100644 --- a/fs/btrfs/extent_map.c +++ b/fs/btrfs/extent_map.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #include <linux/err.h>  #include <linux/slab.h>  #include <linux/spinlock.h> diff --git a/fs/btrfs/extent_map.h b/fs/btrfs/extent_map.h index a67b2def5413..64365bbc9b16 100644 --- a/fs/btrfs/extent_map.h +++ b/fs/btrfs/extent_map.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */  #ifndef __EXTENTMAP__  #define __EXTENTMAP__ diff --git a/fs/btrfs/inode-map.h b/fs/btrfs/inode-map.h index c8e864b2d530..6734ec92a1e9 100644 --- a/fs/btrfs/inode-map.h +++ b/fs/btrfs/inode-map.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */  #ifndef __BTRFS_INODE_MAP  #define __BTRFS_INODE_MAP diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 128f3e58634f..d94e3f68b9b1 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -135,6 +135,18 @@ static inline void btrfs_cleanup_ordered_extents(struct inode *inode,  						 const u64 offset,  						 const u64 bytes)  { +	unsigned long index = offset >> PAGE_SHIFT; +	unsigned long end_index = (offset + bytes - 1) >> PAGE_SHIFT; +	struct page *page; + +	while (index <= end_index) { +		page = find_get_page(inode->i_mapping, index); +		index++; +		if (!page) +			continue; +		ClearPagePrivate2(page); +		put_page(page); +	}  	return __endio_write_update_ordered(inode, offset + PAGE_SIZE,  					    bytes - PAGE_SIZE, false);  } @@ -8357,11 +8369,8 @@ static void btrfs_endio_direct_read(struct bio *bio)  	struct btrfs_io_bio *io_bio = btrfs_io_bio(bio);  	blk_status_t err = bio->bi_status; -	if (dip->flags & BTRFS_DIO_ORIG_BIO_SUBMITTED) { +	if (dip->flags & BTRFS_DIO_ORIG_BIO_SUBMITTED)  		err = btrfs_subio_endio_read(inode, io_bio, err); -		if (!err) -			bio->bi_status = 0; -	}  	unlock_extent(&BTRFS_I(inode)->io_tree, dip->logical_offset,  		      dip->logical_offset + dip->bytes - 1); @@ -8369,7 +8378,7 @@ static void btrfs_endio_direct_read(struct bio *bio)  	kfree(dip); -	dio_bio->bi_status = bio->bi_status; +	dio_bio->bi_status = err;  	dio_end_io(dio_bio);  	if (io_bio->end_io) @@ -8387,6 +8396,7 @@ static void __endio_write_update_ordered(struct inode *inode,  	btrfs_work_func_t func;  	u64 ordered_offset = offset;  	u64 ordered_bytes = bytes; +	u64 last_offset;  	int ret;  	if (btrfs_is_free_space_inode(BTRFS_I(inode))) { @@ -8398,6 +8408,7 @@ static void __endio_write_update_ordered(struct inode *inode,  	}  again: +	last_offset = ordered_offset;  	ret = btrfs_dec_test_first_ordered_pending(inode, &ordered,  						   &ordered_offset,  						   ordered_bytes, @@ -8409,6 +8420,12 @@ again:  	btrfs_queue_work(wq, &ordered->work);  out_test:  	/* +	 * If btrfs_dec_test_ordered_pending does not find any ordered extent +	 * in the range, we can exit. +	 */ +	if (ordered_offset == last_offset) +		return; +	/*  	 * our bio might span multiple ordered extents.  If we haven't  	 * completed the accounting for the whole dio, go back and try again  	 */ diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index d6715c2bcdc4..6c7a49faf4e0 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -2773,9 +2773,9 @@ static long btrfs_ioctl_fs_info(struct btrfs_fs_info *fs_info,  	}  	mutex_unlock(&fs_devices->device_list_mutex); -	fi_args->nodesize = fs_info->super_copy->nodesize; -	fi_args->sectorsize = fs_info->super_copy->sectorsize; -	fi_args->clone_alignment = fs_info->super_copy->sectorsize; +	fi_args->nodesize = fs_info->nodesize; +	fi_args->sectorsize = fs_info->sectorsize; +	fi_args->clone_alignment = fs_info->sectorsize;  	if (copy_to_user(arg, fi_args, sizeof(*fi_args)))  		ret = -EFAULT; @@ -3032,7 +3032,7 @@ static int btrfs_cmp_data_prepare(struct inode *src, u64 loff,  out:  	if (ret)  		btrfs_cmp_data_free(cmp); -	return 0; +	return ret;  }  static int btrfs_cmp_data(u64 len, struct cmp_pages *cmp) @@ -4061,6 +4061,10 @@ static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp)  		ret = PTR_ERR(new_root);  		goto out;  	} +	if (!is_fstree(new_root->objectid)) { +		ret = -ENOENT; +		goto out; +	}  	path = btrfs_alloc_path();  	if (!path) { diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index 5c8b61c86e61..e172d4843eae 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c @@ -807,7 +807,6 @@ static int btrfs_clean_quota_tree(struct btrfs_trans_handle *trans,  	}  	ret = 0;  out: -	set_bit(BTRFS_FS_QUOTA_DISABLING, &root->fs_info->flags);  	btrfs_free_path(path);  	return ret;  } @@ -953,7 +952,6 @@ int btrfs_quota_disable(struct btrfs_trans_handle *trans,  	if (!fs_info->quota_root)  		goto out;  	clear_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags); -	set_bit(BTRFS_FS_QUOTA_DISABLING, &fs_info->flags);  	btrfs_qgroup_wait_for_completion(fs_info, false);  	spin_lock(&fs_info->qgroup_lock);  	quota_root = fs_info->quota_root; @@ -1307,6 +1305,8 @@ int btrfs_remove_qgroup(struct btrfs_trans_handle *trans,  		}  	}  	ret = del_qgroup_item(trans, quota_root, qgroupid); +	if (ret && ret != -ENOENT) +		goto out;  	while (!list_empty(&qgroup->groups)) {  		list = list_first_entry(&qgroup->groups, @@ -2086,8 +2086,6 @@ int btrfs_run_qgroups(struct btrfs_trans_handle *trans,  	if (test_and_clear_bit(BTRFS_FS_QUOTA_ENABLING, &fs_info->flags))  		set_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags); -	if (test_and_clear_bit(BTRFS_FS_QUOTA_DISABLING, &fs_info->flags)) -		clear_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);  	spin_lock(&fs_info->qgroup_lock);  	while (!list_empty(&fs_info->dirty_qgroups)) { diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 3a49a3c2fca4..9841faef08ea 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -2400,11 +2400,11 @@ void free_reloc_roots(struct list_head *list)  	while (!list_empty(list)) {  		reloc_root = list_entry(list->next, struct btrfs_root,  					root_list); +		__del_reloc_root(reloc_root);  		free_extent_buffer(reloc_root->node);  		free_extent_buffer(reloc_root->commit_root);  		reloc_root->node = NULL;  		reloc_root->commit_root = NULL; -		__del_reloc_root(reloc_root);  	}  } diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index 32b043ef8ac9..8fd195cfe81b 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c @@ -2630,7 +2630,7 @@ static int send_create_inode(struct send_ctx *sctx, u64 ino)  	} else {  		btrfs_warn(sctx->send_root->fs_info, "unexpected inode type %o",  				(int)(mode & S_IFMT)); -		ret = -ENOTSUPP; +		ret = -EOPNOTSUPP;  		goto out;  	} diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 35a128acfbd1..161694b66038 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -1135,7 +1135,7 @@ static int btrfs_fill_super(struct super_block *sb,  #ifdef CONFIG_BTRFS_FS_POSIX_ACL  	sb->s_flags |= MS_POSIXACL;  #endif -	sb->s_flags |= MS_I_VERSION; +	sb->s_flags |= SB_I_VERSION;  	sb->s_iflags |= SB_I_CGROUPWB;  	err = super_setup_bdi(sb); diff --git a/fs/btrfs/sysfs.h b/fs/btrfs/sysfs.h index d7da1a4c2f6c..4cb908305e5d 100644 --- a/fs/btrfs/sysfs.h +++ b/fs/btrfs/sysfs.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */  #ifndef _BTRFS_SYSFS_H_  #define _BTRFS_SYSFS_H_ diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index ad7f4bab640b..c800d067fcbf 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -4181,6 +4181,7 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans,  	struct extent_map *em, *n;  	struct list_head extents;  	struct extent_map_tree *tree = &inode->extent_tree; +	u64 logged_start, logged_end;  	u64 test_gen;  	int ret = 0;  	int num = 0; @@ -4190,10 +4191,11 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans,  	down_write(&inode->dio_sem);  	write_lock(&tree->lock);  	test_gen = root->fs_info->last_trans_committed; +	logged_start = start; +	logged_end = end;  	list_for_each_entry_safe(em, n, &tree->modified_extents, list) {  		list_del_init(&em->list); -  		/*  		 * Just an arbitrary number, this can be really CPU intensive  		 * once we start getting a lot of extents, and really once we @@ -4208,6 +4210,12 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans,  		if (em->generation <= test_gen)  			continue; + +		if (em->start < logged_start) +			logged_start = em->start; +		if ((em->start + em->len - 1) > logged_end) +			logged_end = em->start + em->len - 1; +  		/* Need a ref to keep it from getting evicted from cache */  		refcount_inc(&em->refs);  		set_bit(EXTENT_FLAG_LOGGING, &em->flags); @@ -4216,7 +4224,7 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans,  	}  	list_sort(NULL, &extents, extent_cmp); -	btrfs_get_logged_extents(inode, logged_list, start, end); +	btrfs_get_logged_extents(inode, logged_list, logged_start, logged_end);  	/*  	 * Some ordered extents started by fsync might have completed  	 * before we could collect them into the list logged_list, which diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 0e8f16c305df..b39737568c22 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -6166,7 +6166,7 @@ blk_status_t btrfs_map_bio(struct btrfs_fs_info *fs_info, struct bio *bio,  	map_length = length;  	btrfs_bio_counter_inc_blocked(fs_info); -	ret = __btrfs_map_block(fs_info, bio_op(bio), logical, +	ret = __btrfs_map_block(fs_info, btrfs_op(bio), logical,  				&map_length, &bbio, mirror_num, 1);  	if (ret) {  		btrfs_bio_counter_dec(fs_info); |