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

Commit 4ebf6623 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable:
  Btrfs: look for acls during btrfs_read_locked_inode
  Btrfs: fix acl caching
  Btrfs: Fix a bunch of printk() warnings.
  Btrfs: Fix a trivial warning using max() of u64 vs ULL.
  Btrfs: remove unused btrfs_bit_radix slab
  Btrfs: ratelimit IO error printks
  Btrfs: remove #if 0 code
  Btrfs: When shrinking, only update disk size on success
  Btrfs: fix deadlocks and stalls on dead root removal
  Btrfs: fix fallocate deadlock on inode extent lock
  Btrfs: kill btrfs_cache_create
  Btrfs: don't export symbols
  Btrfs: simplify makefile
  Btrfs: try to keep a healthy ratio of metadata vs data block groups
parents 14b6084d 46a53cca
Loading
Loading
Loading
Loading
+2 −17
Original line number Original line Diff line number Diff line
ifneq ($(KERNELRELEASE),)
# kbuild part of makefile


obj-$(CONFIG_BTRFS_FS) := btrfs.o
obj-$(CONFIG_BTRFS_FS) := btrfs.o
btrfs-y := super.o ctree.o extent-tree.o print-tree.o root-tree.o dir-item.o \

btrfs-y += super.o ctree.o extent-tree.o print-tree.o root-tree.o dir-item.o \
	   file-item.o inode-item.o inode-map.o disk-io.o \
	   file-item.o inode-item.o inode-map.o disk-io.o \
	   transaction.o inode.o file.o tree-defrag.o \
	   transaction.o inode.o file.o tree-defrag.o \
	   extent_map.o sysfs.o struct-funcs.o xattr.o ordered-data.o \
	   extent_map.o sysfs.o struct-funcs.o xattr.o ordered-data.o \
	   extent_io.o volumes.o async-thread.o ioctl.o locking.o orphan.o \
	   extent_io.o volumes.o async-thread.o ioctl.o locking.o orphan.o \
	   ref-cache.o export.o tree-log.o acl.o free-space-cache.o zlib.o \
	   ref-cache.o export.o tree-log.o acl.o free-space-cache.o zlib.o \
	   compression.o delayed-ref.o
	   compression.o delayed-ref.o
else

# Normal Makefile

KERNELDIR := /lib/modules/`uname -r`/build
all:
	$(MAKE) -C $(KERNELDIR) M=`pwd` CONFIG_BTRFS_FS=m modules

modules_install:
	$(MAKE) -C $(KERNELDIR) M=`pwd` modules_install
clean:
	$(MAKE) -C $(KERNELDIR) M=`pwd` clean

endif
+13 −5
Original line number Original line Diff line number Diff line
@@ -60,15 +60,20 @@ static struct posix_acl *btrfs_get_acl(struct inode *inode, int type)
		return ERR_PTR(-EINVAL);
		return ERR_PTR(-EINVAL);
	}
	}


	/* Handle the cached NULL acl case without locking */
	acl = ACCESS_ONCE(*p_acl);
	if (!acl)
		return acl;

	spin_lock(&inode->i_lock);
	spin_lock(&inode->i_lock);
	if (*p_acl != BTRFS_ACL_NOT_CACHED)
	acl = *p_acl;
		acl = posix_acl_dup(*p_acl);
	if (acl != BTRFS_ACL_NOT_CACHED)
		acl = posix_acl_dup(acl);
	spin_unlock(&inode->i_lock);
	spin_unlock(&inode->i_lock);


	if (acl)
	if (acl != BTRFS_ACL_NOT_CACHED)
		return acl;
		return acl;



	size = __btrfs_getxattr(inode, name, "", 0);
	size = __btrfs_getxattr(inode, name, "", 0);
	if (size > 0) {
	if (size > 0) {
		value = kzalloc(size, GFP_NOFS);
		value = kzalloc(size, GFP_NOFS);
@@ -80,9 +85,12 @@ static struct posix_acl *btrfs_get_acl(struct inode *inode, int type)
			btrfs_update_cached_acl(inode, p_acl, acl);
			btrfs_update_cached_acl(inode, p_acl, acl);
		}
		}
		kfree(value);
		kfree(value);
	} else if (size == -ENOENT) {
	} else if (size == -ENOENT || size == -ENODATA || size == 0) {
		/* FIXME, who returns -ENOENT?  I think nobody */
		acl = NULL;
		acl = NULL;
		btrfs_update_cached_acl(inode, p_acl, acl);
		btrfs_update_cached_acl(inode, p_acl, acl);
	} else {
		acl = ERR_PTR(-EIO);
	}
	}


	return acl;
	return acl;
+5 −1
Original line number Original line Diff line number Diff line
@@ -881,6 +881,9 @@ struct btrfs_fs_info {
	u64 metadata_alloc_profile;
	u64 metadata_alloc_profile;
	u64 system_alloc_profile;
	u64 system_alloc_profile;


	unsigned data_chunk_allocations;
	unsigned metadata_ratio;

	void *bdev_holder;
	void *bdev_holder;
};
};


@@ -2174,7 +2177,8 @@ int btrfs_check_file(struct btrfs_root *root, struct inode *inode);
extern struct file_operations btrfs_file_operations;
extern struct file_operations btrfs_file_operations;
int btrfs_drop_extents(struct btrfs_trans_handle *trans,
int btrfs_drop_extents(struct btrfs_trans_handle *trans,
		       struct btrfs_root *root, struct inode *inode,
		       struct btrfs_root *root, struct inode *inode,
		       u64 start, u64 end, u64 inline_limit, u64 *hint_block);
		       u64 start, u64 end, u64 locked_end,
		       u64 inline_limit, u64 *hint_block);
int btrfs_mark_extent_written(struct btrfs_trans_handle *trans,
int btrfs_mark_extent_written(struct btrfs_trans_handle *trans,
			      struct btrfs_root *root,
			      struct btrfs_root *root,
			      struct inode *inode, u64 start, u64 end);
			      struct inode *inode, u64 start, u64 end);
+30 −63
Original line number Original line Diff line number Diff line
@@ -232,10 +232,14 @@ static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf,
			memcpy(&found, result, csum_size);
			memcpy(&found, result, csum_size);


			read_extent_buffer(buf, &val, 0, csum_size);
			read_extent_buffer(buf, &val, 0, csum_size);
			printk(KERN_INFO "btrfs: %s checksum verify failed "
			if (printk_ratelimit()) {
			       "on %llu wanted %X found %X level %d\n",
				printk(KERN_INFO "btrfs: %s checksum verify "
				       "failed on %llu wanted %X found %X "
				       "level %d\n",
				       root->fs_info->sb->s_id,
				       root->fs_info->sb->s_id,
			       buf->start, val, found, btrfs_header_level(buf));
				       (unsigned long long)buf->start, val, found,
				       btrfs_header_level(buf));
			}
			if (result != (char *)&inline_result)
			if (result != (char *)&inline_result)
				kfree(result);
				kfree(result);
			return 1;
			return 1;
@@ -268,10 +272,13 @@ static int verify_parent_transid(struct extent_io_tree *io_tree,
		ret = 0;
		ret = 0;
		goto out;
		goto out;
	}
	}
	printk("parent transid verify failed on %llu wanted %llu found %llu\n",
	if (printk_ratelimit()) {
		printk("parent transid verify failed on %llu wanted %llu "
		       "found %llu\n",
		       (unsigned long long)eb->start,
		       (unsigned long long)eb->start,
		       (unsigned long long)parent_transid,
		       (unsigned long long)parent_transid,
		       (unsigned long long)btrfs_header_generation(eb));
		       (unsigned long long)btrfs_header_generation(eb));
	}
	ret = 1;
	ret = 1;
	clear_extent_buffer_uptodate(io_tree, eb);
	clear_extent_buffer_uptodate(io_tree, eb);
out:
out:
@@ -415,9 +422,12 @@ static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end,


	found_start = btrfs_header_bytenr(eb);
	found_start = btrfs_header_bytenr(eb);
	if (found_start != start) {
	if (found_start != start) {
		printk(KERN_INFO "btrfs bad tree block start %llu %llu\n",
		if (printk_ratelimit()) {
			printk(KERN_INFO "btrfs bad tree block start "
			       "%llu %llu\n",
			       (unsigned long long)found_start,
			       (unsigned long long)found_start,
			       (unsigned long long)eb->start);
			       (unsigned long long)eb->start);
		}
		ret = -EIO;
		ret = -EIO;
		goto err;
		goto err;
	}
	}
@@ -429,8 +439,10 @@ static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end,
		goto err;
		goto err;
	}
	}
	if (check_tree_block_fsid(root, eb)) {
	if (check_tree_block_fsid(root, eb)) {
		if (printk_ratelimit()) {
			printk(KERN_INFO "btrfs bad fsid on block %llu\n",
			printk(KERN_INFO "btrfs bad fsid on block %llu\n",
			       (unsigned long long)eb->start);
			       (unsigned long long)eb->start);
		}
		ret = -EIO;
		ret = -EIO;
		goto err;
		goto err;
	}
	}
@@ -584,18 +596,7 @@ int btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct inode *inode,
		btrfs_set_work_high_prio(&async->work);
		btrfs_set_work_high_prio(&async->work);


	btrfs_queue_worker(&fs_info->workers, &async->work);
	btrfs_queue_worker(&fs_info->workers, &async->work);
#if 0
	int limit = btrfs_async_submit_limit(fs_info);
	if (atomic_read(&fs_info->nr_async_submits) > limit) {
		wait_event_timeout(fs_info->async_submit_wait,
			   (atomic_read(&fs_info->nr_async_submits) < limit),
			   HZ/10);


		wait_event_timeout(fs_info->async_submit_wait,
			   (atomic_read(&fs_info->nr_async_bios) < limit),
			   HZ/10);
	}
#endif
	while (atomic_read(&fs_info->async_submit_draining) &&
	while (atomic_read(&fs_info->async_submit_draining) &&
	      atomic_read(&fs_info->nr_async_submits)) {
	      atomic_read(&fs_info->nr_async_submits)) {
		wait_event(fs_info->async_submit_wait,
		wait_event(fs_info->async_submit_wait,
@@ -770,27 +771,6 @@ static void btree_invalidatepage(struct page *page, unsigned long offset)
	}
	}
}
}


#if 0
static int btree_writepage(struct page *page, struct writeback_control *wbc)
{
	struct buffer_head *bh;
	struct btrfs_root *root = BTRFS_I(page->mapping->host)->root;
	struct buffer_head *head;
	if (!page_has_buffers(page)) {
		create_empty_buffers(page, root->fs_info->sb->s_blocksize,
					(1 << BH_Dirty)|(1 << BH_Uptodate));
	}
	head = page_buffers(page);
	bh = head;
	do {
		if (buffer_dirty(bh))
			csum_tree_block(root, bh, 0);
		bh = bh->b_this_page;
	} while (bh != head);
	return block_write_full_page(page, btree_get_block, wbc);
}
#endif

static struct address_space_operations btree_aops = {
static struct address_space_operations btree_aops = {
	.readpage	= btree_readpage,
	.readpage	= btree_readpage,
	.writepage	= btree_writepage,
	.writepage	= btree_writepage,
@@ -1278,11 +1258,7 @@ static int btrfs_congested_fn(void *congested_data, int bdi_bits)
	int ret = 0;
	int ret = 0;
	struct btrfs_device *device;
	struct btrfs_device *device;
	struct backing_dev_info *bdi;
	struct backing_dev_info *bdi;
#if 0

	if ((bdi_bits & (1 << BDI_write_congested)) &&
	    btrfs_congested_async(info, 0))
		return 1;
#endif
	list_for_each_entry(device, &info->fs_devices->devices, dev_list) {
	list_for_each_entry(device, &info->fs_devices->devices, dev_list) {
		if (!device->bdev)
		if (!device->bdev)
			continue;
			continue;
@@ -1604,6 +1580,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
	fs_info->btree_inode = new_inode(sb);
	fs_info->btree_inode = new_inode(sb);
	fs_info->btree_inode->i_ino = 1;
	fs_info->btree_inode->i_ino = 1;
	fs_info->btree_inode->i_nlink = 1;
	fs_info->btree_inode->i_nlink = 1;
	fs_info->metadata_ratio = 8;


	fs_info->thread_pool_size = min_t(unsigned long,
	fs_info->thread_pool_size = min_t(unsigned long,
					  num_online_cpus() + 2, 8);
					  num_online_cpus() + 2, 8);
@@ -1694,7 +1671,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
	if (features) {
	if (features) {
		printk(KERN_ERR "BTRFS: couldn't mount because of "
		printk(KERN_ERR "BTRFS: couldn't mount because of "
		       "unsupported optional features (%Lx).\n",
		       "unsupported optional features (%Lx).\n",
		       features);
		       (unsigned long long)features);
		err = -EINVAL;
		err = -EINVAL;
		goto fail_iput;
		goto fail_iput;
	}
	}
@@ -1704,7 +1681,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
	if (!(sb->s_flags & MS_RDONLY) && features) {
	if (!(sb->s_flags & MS_RDONLY) && features) {
		printk(KERN_ERR "BTRFS: couldn't mount RDWR because of "
		printk(KERN_ERR "BTRFS: couldn't mount RDWR because of "
		       "unsupported option features (%Lx).\n",
		       "unsupported option features (%Lx).\n",
		       features);
		       (unsigned long long)features);
		err = -EINVAL;
		err = -EINVAL;
		goto fail_iput;
		goto fail_iput;
	}
	}
@@ -2296,7 +2273,7 @@ int close_ctree(struct btrfs_root *root)


	if (fs_info->delalloc_bytes) {
	if (fs_info->delalloc_bytes) {
		printk(KERN_INFO "btrfs: at unmount delalloc count %llu\n",
		printk(KERN_INFO "btrfs: at unmount delalloc count %llu\n",
		       fs_info->delalloc_bytes);
		       (unsigned long long)fs_info->delalloc_bytes);
	}
	}
	if (fs_info->total_ref_cache_size) {
	if (fs_info->total_ref_cache_size) {
		printk(KERN_INFO "btrfs: at umount reference cache size %llu\n",
		printk(KERN_INFO "btrfs: at umount reference cache size %llu\n",
@@ -2333,16 +2310,6 @@ int close_ctree(struct btrfs_root *root)
	btrfs_stop_workers(&fs_info->endio_write_workers);
	btrfs_stop_workers(&fs_info->endio_write_workers);
	btrfs_stop_workers(&fs_info->submit_workers);
	btrfs_stop_workers(&fs_info->submit_workers);


#if 0
	while (!list_empty(&fs_info->hashers)) {
		struct btrfs_hasher *hasher;
		hasher = list_entry(fs_info->hashers.next, struct btrfs_hasher,
				    hashers);
		list_del(&hasher->hashers);
		crypto_free_hash(&fs_info->hash_tfm);
		kfree(hasher);
	}
#endif
	btrfs_close_devices(fs_info->fs_devices);
	btrfs_close_devices(fs_info->fs_devices);
	btrfs_mapping_tree_free(&fs_info->mapping_tree);
	btrfs_mapping_tree_free(&fs_info->mapping_tree);


+41 −8
Original line number Original line Diff line number Diff line
@@ -1844,10 +1844,14 @@ again:
		printk(KERN_ERR "no space left, need %llu, %llu delalloc bytes"
		printk(KERN_ERR "no space left, need %llu, %llu delalloc bytes"
		       ", %llu bytes_used, %llu bytes_reserved, "
		       ", %llu bytes_used, %llu bytes_reserved, "
		       "%llu bytes_pinned, %llu bytes_readonly, %llu may use"
		       "%llu bytes_pinned, %llu bytes_readonly, %llu may use"
		       "%llu total\n", bytes, data_sinfo->bytes_delalloc,
		       "%llu total\n", (unsigned long long)bytes,
		       data_sinfo->bytes_used, data_sinfo->bytes_reserved,
		       (unsigned long long)data_sinfo->bytes_delalloc,
		       data_sinfo->bytes_pinned, data_sinfo->bytes_readonly,
		       (unsigned long long)data_sinfo->bytes_used,
		       data_sinfo->bytes_may_use, data_sinfo->total_bytes);
		       (unsigned long long)data_sinfo->bytes_reserved,
		       (unsigned long long)data_sinfo->bytes_pinned,
		       (unsigned long long)data_sinfo->bytes_readonly,
		       (unsigned long long)data_sinfo->bytes_may_use,
		       (unsigned long long)data_sinfo->total_bytes);
		return -ENOSPC;
		return -ENOSPC;
	}
	}
	data_sinfo->bytes_may_use += bytes;
	data_sinfo->bytes_may_use += bytes;
@@ -1918,15 +1922,29 @@ void btrfs_delalloc_free_space(struct btrfs_root *root, struct inode *inode,
	spin_unlock(&info->lock);
	spin_unlock(&info->lock);
}
}


static void force_metadata_allocation(struct btrfs_fs_info *info)
{
	struct list_head *head = &info->space_info;
	struct btrfs_space_info *found;

	rcu_read_lock();
	list_for_each_entry_rcu(found, head, list) {
		if (found->flags & BTRFS_BLOCK_GROUP_METADATA)
			found->force_alloc = 1;
	}
	rcu_read_unlock();
}

static int do_chunk_alloc(struct btrfs_trans_handle *trans,
static int do_chunk_alloc(struct btrfs_trans_handle *trans,
			  struct btrfs_root *extent_root, u64 alloc_bytes,
			  struct btrfs_root *extent_root, u64 alloc_bytes,
			  u64 flags, int force)
			  u64 flags, int force)
{
{
	struct btrfs_space_info *space_info;
	struct btrfs_space_info *space_info;
	struct btrfs_fs_info *fs_info = extent_root->fs_info;
	u64 thresh;
	u64 thresh;
	int ret = 0;
	int ret = 0;


	mutex_lock(&extent_root->fs_info->chunk_mutex);
	mutex_lock(&fs_info->chunk_mutex);


	flags = btrfs_reduce_alloc_profile(extent_root, flags);
	flags = btrfs_reduce_alloc_profile(extent_root, flags);


@@ -1958,6 +1976,18 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,
	}
	}
	spin_unlock(&space_info->lock);
	spin_unlock(&space_info->lock);


	/*
	 * if we're doing a data chunk, go ahead and make sure that
	 * we keep a reasonable number of metadata chunks allocated in the
	 * FS as well.
	 */
	if (flags & BTRFS_BLOCK_GROUP_DATA) {
		fs_info->data_chunk_allocations++;
		if (!(fs_info->data_chunk_allocations %
		      fs_info->metadata_ratio))
			force_metadata_allocation(fs_info);
	}

	ret = btrfs_alloc_chunk(trans, extent_root, flags);
	ret = btrfs_alloc_chunk(trans, extent_root, flags);
	if (ret)
	if (ret)
		space_info->full = 1;
		space_info->full = 1;
@@ -2798,9 +2828,12 @@ static void dump_space_info(struct btrfs_space_info *info, u64 bytes)
				    info->bytes_pinned - info->bytes_reserved),
				    info->bytes_pinned - info->bytes_reserved),
	       (info->full) ? "" : "not ");
	       (info->full) ? "" : "not ");
	printk(KERN_INFO "space_info total=%llu, pinned=%llu, delalloc=%llu,"
	printk(KERN_INFO "space_info total=%llu, pinned=%llu, delalloc=%llu,"
	       " may_use=%llu, used=%llu\n", info->total_bytes,
	       " may_use=%llu, used=%llu\n",
	       info->bytes_pinned, info->bytes_delalloc, info->bytes_may_use,
	       (unsigned long long)info->total_bytes,
	       info->bytes_used);
	       (unsigned long long)info->bytes_pinned,
	       (unsigned long long)info->bytes_delalloc,
	       (unsigned long long)info->bytes_may_use,
	       (unsigned long long)info->bytes_used);


	down_read(&info->groups_sem);
	down_read(&info->groups_sem);
	list_for_each_entry(cache, &info->block_groups, list) {
	list_for_each_entry(cache, &info->block_groups, list) {
Loading