Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5c80c71b authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable:
  Btrfs: set i_size properly when fallocating and we already
  btrfs: unlock on error in btrfs_file_llseek()
  btrfs: btrfs_permission's RO check shouldn't apply to device nodes
  Btrfs: truncate pages from clone ioctl target range
  Btrfs: fix uninitialized sync_pending
  Btrfs: fix wrong free space information
  btrfs: memory leak in btrfs_add_inode_defrag()
  Btrfs: use plain page_address() in header fields setget functions
  Btrfs: forced readonly when btrfs_drop_snapshot() fails
  Btrfs: check if there is enough space for balancing smarter
  Btrfs: fix a bug of balance on full multi-disk partitions
  Btrfs: fix an oops of log replay
  Btrfs: detect wether a device supports discard
  Btrfs: force unplugs when switching from high to regular priority bios
parents 01fa4ba5 81d86e1b
Loading
Loading
Loading
Loading
+4 −6
Original line number Diff line number Diff line
@@ -1415,17 +1415,15 @@ void btrfs_set_##name(struct extent_buffer *eb, type *s, u##bits val);
#define BTRFS_SETGET_HEADER_FUNCS(name, type, member, bits)		\
static inline u##bits btrfs_##name(struct extent_buffer *eb)		\
{									\
	type *p = kmap_atomic(eb->first_page, KM_USER0);		\
	type *p = page_address(eb->first_page);				\
	u##bits res = le##bits##_to_cpu(p->member);			\
	kunmap_atomic(p, KM_USER0);					\
	return res;							\
}									\
static inline void btrfs_set_##name(struct extent_buffer *eb,		\
				    u##bits val)			\
{									\
	type *p = kmap_atomic(eb->first_page, KM_USER0);		\
	type *p = page_address(eb->first_page);				\
	p->member = cpu_to_le##bits(val);				\
	kunmap_atomic(p, KM_USER0);					\
}

#define BTRFS_SETGET_STACK_FUNCS(name, type, member, bits)		\
@@ -2367,7 +2365,7 @@ static inline int btrfs_insert_empty_item(struct btrfs_trans_handle *trans,
int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path);
int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path);
int btrfs_leaf_free_space(struct btrfs_root *root, struct extent_buffer *leaf);
int btrfs_drop_snapshot(struct btrfs_root *root,
void btrfs_drop_snapshot(struct btrfs_root *root,
			 struct btrfs_block_rsv *block_rsv, int update_ref);
int btrfs_drop_subtree(struct btrfs_trans_handle *trans,
			struct btrfs_root *root,
+59 −16
Original line number Diff line number Diff line
@@ -1782,6 +1782,9 @@ static int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr,


		for (i = 0; i < multi->num_stripes; i++, stripe++) {
			if (!stripe->dev->can_discard)
				continue;

			ret = btrfs_issue_discard(stripe->dev->bdev,
						  stripe->physical,
						  stripe->length);
@@ -1789,11 +1792,16 @@ static int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr,
				discarded_bytes += stripe->length;
			else if (ret != -EOPNOTSUPP)
				break;

			/*
			 * Just in case we get back EOPNOTSUPP for some reason,
			 * just ignore the return value so we don't screw up
			 * people calling discard_extent.
			 */
			ret = 0;
		}
		kfree(multi);
	}
	if (discarded_bytes && ret == -EOPNOTSUPP)
		ret = 0;

	if (actual_bytes)
		*actual_bytes = discarded_bytes;
@@ -6269,7 +6277,7 @@ static noinline int walk_up_tree(struct btrfs_trans_handle *trans,
 * also make sure backrefs for the shared block and all lower level
 * blocks are properly updated.
 */
int btrfs_drop_snapshot(struct btrfs_root *root,
void btrfs_drop_snapshot(struct btrfs_root *root,
			 struct btrfs_block_rsv *block_rsv, int update_ref)
{
	struct btrfs_path *path;
@@ -6283,13 +6291,16 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
	int level;

	path = btrfs_alloc_path();
	if (!path)
		return -ENOMEM;
	if (!path) {
		err = -ENOMEM;
		goto out;
	}

	wc = kzalloc(sizeof(*wc), GFP_NOFS);
	if (!wc) {
		btrfs_free_path(path);
		return -ENOMEM;
		err = -ENOMEM;
		goto out;
	}

	trans = btrfs_start_transaction(tree_root, 0);
@@ -6318,7 +6329,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
		path->lowest_level = 0;
		if (ret < 0) {
			err = ret;
			goto out;
			goto out_free;
		}
		WARN_ON(ret > 0);

@@ -6425,11 +6436,14 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
		free_extent_buffer(root->commit_root);
		kfree(root);
	}
out:
out_free:
	btrfs_end_transaction_throttle(trans, tree_root);
	kfree(wc);
	btrfs_free_path(path);
	return err;
out:
	if (err)
		btrfs_std_error(root->fs_info, err);
	return;
}

/*
@@ -6720,6 +6734,10 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr)
	struct btrfs_space_info *space_info;
	struct btrfs_fs_devices *fs_devices = root->fs_info->fs_devices;
	struct btrfs_device *device;
	u64 min_free;
	int index;
	int dev_nr = 0;
	int dev_min = 1;
	int full = 0;
	int ret = 0;

@@ -6729,8 +6747,10 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr)
	if (!block_group)
		return -1;

	min_free = btrfs_block_group_used(&block_group->item);

	/* no bytes used, we're good */
	if (!btrfs_block_group_used(&block_group->item))
	if (!min_free)
		goto out;

	space_info = block_group->space_info;
@@ -6748,8 +6768,7 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr)
	if ((space_info->total_bytes != block_group->key.offset) &&
	    (space_info->bytes_used + space_info->bytes_reserved +
	     space_info->bytes_pinned + space_info->bytes_readonly +
	    btrfs_block_group_used(&block_group->item) <
	    space_info->total_bytes)) {
	     min_free < space_info->total_bytes)) {
		spin_unlock(&space_info->lock);
		goto out;
	}
@@ -6766,9 +6785,29 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr)
	if (full)
		goto out;

	/*
	 * index:
	 *      0: raid10
	 *      1: raid1
	 *      2: dup
	 *      3: raid0
	 *      4: single
	 */
	index = get_block_group_index(block_group);
	if (index == 0) {
		dev_min = 4;
		min_free /= 2;
	} else if (index == 1) {
		dev_min = 2;
	} else if (index == 2) {
		min_free *= 2;
	} else if (index == 3) {
		dev_min = fs_devices->rw_devices;
		min_free /= dev_min;
	}

	mutex_lock(&root->fs_info->chunk_mutex);
	list_for_each_entry(device, &fs_devices->alloc_list, dev_alloc_list) {
		u64 min_free = btrfs_block_group_used(&block_group->item);
		u64 dev_offset;

		/*
@@ -6779,7 +6818,11 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr)
			ret = find_free_dev_extent(NULL, device, min_free,
						   &dev_offset, NULL);
			if (!ret)
				dev_nr++;

			if (dev_nr >= dev_min)
				break;

			ret = -1;
		}
	}
+24 −4
Original line number Diff line number Diff line
@@ -150,6 +150,8 @@ int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans,
	spin_lock(&root->fs_info->defrag_inodes_lock);
	if (!BTRFS_I(inode)->in_defrag)
		__btrfs_add_inode_defrag(inode, defrag);
	else
		kfree(defrag);
	spin_unlock(&root->fs_info->defrag_inodes_lock);
	return 0;
}
@@ -1638,11 +1640,15 @@ static long btrfs_fallocate(struct file *file, int mode,

	cur_offset = alloc_start;
	while (1) {
		u64 actual_end;

		em = btrfs_get_extent(inode, NULL, 0, cur_offset,
				      alloc_end - cur_offset, 0);
		BUG_ON(IS_ERR_OR_NULL(em));
		last_byte = min(extent_map_end(em), alloc_end);
		actual_end = min_t(u64, extent_map_end(em), offset + len);
		last_byte = (last_byte + mask) & ~mask;

		if (em->block_start == EXTENT_MAP_HOLE ||
		    (cur_offset >= inode->i_size &&
		     !test_bit(EXTENT_FLAG_PREALLOC, &em->flags))) {
@@ -1655,6 +1661,16 @@ static long btrfs_fallocate(struct file *file, int mode,
				free_extent_map(em);
				break;
			}
		} else if (actual_end > inode->i_size &&
			   !(mode & FALLOC_FL_KEEP_SIZE)) {
			/*
			 * We didn't need to allocate any more space, but we
			 * still extended the size of the file so we need to
			 * update i_size.
			 */
			inode->i_ctime = CURRENT_TIME;
			i_size_write(inode, actual_end);
			btrfs_ordered_update_i_size(inode, actual_end, NULL);
		}
		free_extent_map(em);

@@ -1804,10 +1820,14 @@ static loff_t btrfs_file_llseek(struct file *file, loff_t offset, int origin)
		}
	}

	if (offset < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET))
		return -EINVAL;
	if (offset > inode->i_sb->s_maxbytes)
		return -EINVAL;
	if (offset < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET)) {
		ret = -EINVAL;
		goto out;
	}
	if (offset > inode->i_sb->s_maxbytes) {
		ret = -EINVAL;
		goto out;
	}

	/* Special lock needed here? */
	if (offset != file->f_pos) {
+11 −5
Original line number Diff line number Diff line
@@ -1168,9 +1168,9 @@ static void recalculate_thresholds(struct btrfs_free_space_ctl *ctl)
		div64_u64(extent_bytes, (sizeof(struct btrfs_free_space)));
}

static void bitmap_clear_bits(struct btrfs_free_space_ctl *ctl,
			      struct btrfs_free_space *info, u64 offset,
			      u64 bytes)
static inline void __bitmap_clear_bits(struct btrfs_free_space_ctl *ctl,
				       struct btrfs_free_space *info,
				       u64 offset, u64 bytes)
{
	unsigned long start, count;

@@ -1181,6 +1181,13 @@ static void bitmap_clear_bits(struct btrfs_free_space_ctl *ctl,
	bitmap_clear(info->bitmap, start, count);

	info->bytes -= bytes;
}

static void bitmap_clear_bits(struct btrfs_free_space_ctl *ctl,
			      struct btrfs_free_space *info, u64 offset,
			      u64 bytes)
{
	__bitmap_clear_bits(ctl, info, offset, bytes);
	ctl->free_space -= bytes;
}

@@ -1984,7 +1991,7 @@ static u64 btrfs_alloc_from_bitmap(struct btrfs_block_group_cache *block_group,
		return 0;

	ret = search_start;
	bitmap_clear_bits(ctl, entry, ret, bytes);
	__bitmap_clear_bits(ctl, entry, ret, bytes);

	return ret;
}
@@ -2039,7 +2046,6 @@ u64 btrfs_alloc_from_cluster(struct btrfs_block_group_cache *block_group,
				continue;
			}
		} else {

			ret = entry->offset;

			entry->offset += bytes;
+8 −4
Original line number Diff line number Diff line
@@ -7354,11 +7354,15 @@ static int btrfs_set_page_dirty(struct page *page)
static int btrfs_permission(struct inode *inode, int mask)
{
	struct btrfs_root *root = BTRFS_I(inode)->root;
	umode_t mode = inode->i_mode;

	if (btrfs_root_readonly(root) && (mask & MAY_WRITE))
	if (mask & MAY_WRITE &&
	    (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) {
		if (btrfs_root_readonly(root))
			return -EROFS;
	if ((BTRFS_I(inode)->flags & BTRFS_INODE_READONLY) && (mask & MAY_WRITE))
		if (BTRFS_I(inode)->flags & BTRFS_INODE_READONLY)
			return -EACCES;
	}
	return generic_permission(inode, mask);
}

Loading