Merge git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable
* 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
This commit is contained in:
commit
4ebf662337
|
@ -1,25 +1,10 @@
|
|||
ifneq ($(KERNELRELEASE),)
|
||||
# kbuild part of makefile
|
||||
|
||||
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 \
|
||||
transaction.o inode.o file.o tree-defrag.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 \
|
||||
ref-cache.o export.o tree-log.o acl.o free-space-cache.o zlib.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
|
||||
|
|
|
@ -60,14 +60,19 @@ static struct posix_acl *btrfs_get_acl(struct inode *inode, int type)
|
|||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
spin_lock(&inode->i_lock);
|
||||
if (*p_acl != BTRFS_ACL_NOT_CACHED)
|
||||
acl = posix_acl_dup(*p_acl);
|
||||
spin_unlock(&inode->i_lock);
|
||||
|
||||
if (acl)
|
||||
/* Handle the cached NULL acl case without locking */
|
||||
acl = ACCESS_ONCE(*p_acl);
|
||||
if (!acl)
|
||||
return acl;
|
||||
|
||||
spin_lock(&inode->i_lock);
|
||||
acl = *p_acl;
|
||||
if (acl != BTRFS_ACL_NOT_CACHED)
|
||||
acl = posix_acl_dup(acl);
|
||||
spin_unlock(&inode->i_lock);
|
||||
|
||||
if (acl != BTRFS_ACL_NOT_CACHED)
|
||||
return acl;
|
||||
|
||||
size = __btrfs_getxattr(inode, name, "", 0);
|
||||
if (size > 0) {
|
||||
|
@ -80,9 +85,12 @@ static struct posix_acl *btrfs_get_acl(struct inode *inode, int type)
|
|||
btrfs_update_cached_acl(inode, p_acl, acl);
|
||||
}
|
||||
kfree(value);
|
||||
} else if (size == -ENOENT) {
|
||||
} else if (size == -ENOENT || size == -ENODATA || size == 0) {
|
||||
/* FIXME, who returns -ENOENT? I think nobody */
|
||||
acl = NULL;
|
||||
btrfs_update_cached_acl(inode, p_acl, acl);
|
||||
} else {
|
||||
acl = ERR_PTR(-EIO);
|
||||
}
|
||||
|
||||
return acl;
|
||||
|
|
|
@ -881,6 +881,9 @@ struct btrfs_fs_info {
|
|||
u64 metadata_alloc_profile;
|
||||
u64 system_alloc_profile;
|
||||
|
||||
unsigned data_chunk_allocations;
|
||||
unsigned metadata_ratio;
|
||||
|
||||
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;
|
||||
int btrfs_drop_extents(struct btrfs_trans_handle *trans,
|
||||
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,
|
||||
struct btrfs_root *root,
|
||||
struct inode *inode, u64 start, u64 end);
|
||||
|
|
|
@ -232,10 +232,14 @@ static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf,
|
|||
memcpy(&found, result, csum_size);
|
||||
|
||||
read_extent_buffer(buf, &val, 0, csum_size);
|
||||
printk(KERN_INFO "btrfs: %s checksum verify failed "
|
||||
"on %llu wanted %X found %X level %d\n",
|
||||
root->fs_info->sb->s_id,
|
||||
buf->start, val, found, btrfs_header_level(buf));
|
||||
if (printk_ratelimit()) {
|
||||
printk(KERN_INFO "btrfs: %s checksum verify "
|
||||
"failed on %llu wanted %X found %X "
|
||||
"level %d\n",
|
||||
root->fs_info->sb->s_id,
|
||||
(unsigned long long)buf->start, val, found,
|
||||
btrfs_header_level(buf));
|
||||
}
|
||||
if (result != (char *)&inline_result)
|
||||
kfree(result);
|
||||
return 1;
|
||||
|
@ -268,10 +272,13 @@ static int verify_parent_transid(struct extent_io_tree *io_tree,
|
|||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
printk("parent transid verify failed on %llu wanted %llu found %llu\n",
|
||||
(unsigned long long)eb->start,
|
||||
(unsigned long long)parent_transid,
|
||||
(unsigned long long)btrfs_header_generation(eb));
|
||||
if (printk_ratelimit()) {
|
||||
printk("parent transid verify failed on %llu wanted %llu "
|
||||
"found %llu\n",
|
||||
(unsigned long long)eb->start,
|
||||
(unsigned long long)parent_transid,
|
||||
(unsigned long long)btrfs_header_generation(eb));
|
||||
}
|
||||
ret = 1;
|
||||
clear_extent_buffer_uptodate(io_tree, eb);
|
||||
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);
|
||||
if (found_start != start) {
|
||||
printk(KERN_INFO "btrfs bad tree block start %llu %llu\n",
|
||||
(unsigned long long)found_start,
|
||||
(unsigned long long)eb->start);
|
||||
if (printk_ratelimit()) {
|
||||
printk(KERN_INFO "btrfs bad tree block start "
|
||||
"%llu %llu\n",
|
||||
(unsigned long long)found_start,
|
||||
(unsigned long long)eb->start);
|
||||
}
|
||||
ret = -EIO;
|
||||
goto err;
|
||||
}
|
||||
|
@ -429,8 +439,10 @@ static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end,
|
|||
goto err;
|
||||
}
|
||||
if (check_tree_block_fsid(root, eb)) {
|
||||
printk(KERN_INFO "btrfs bad fsid on block %llu\n",
|
||||
(unsigned long long)eb->start);
|
||||
if (printk_ratelimit()) {
|
||||
printk(KERN_INFO "btrfs bad fsid on block %llu\n",
|
||||
(unsigned long long)eb->start);
|
||||
}
|
||||
ret = -EIO;
|
||||
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_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) &&
|
||||
atomic_read(&fs_info->nr_async_submits)) {
|
||||
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 = {
|
||||
.readpage = btree_readpage,
|
||||
.writepage = btree_writepage,
|
||||
|
@ -1278,11 +1258,7 @@ static int btrfs_congested_fn(void *congested_data, int bdi_bits)
|
|||
int ret = 0;
|
||||
struct btrfs_device *device;
|
||||
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) {
|
||||
if (!device->bdev)
|
||||
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->i_ino = 1;
|
||||
fs_info->btree_inode->i_nlink = 1;
|
||||
fs_info->metadata_ratio = 8;
|
||||
|
||||
fs_info->thread_pool_size = min_t(unsigned long,
|
||||
num_online_cpus() + 2, 8);
|
||||
|
@ -1694,7 +1671,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
|
|||
if (features) {
|
||||
printk(KERN_ERR "BTRFS: couldn't mount because of "
|
||||
"unsupported optional features (%Lx).\n",
|
||||
features);
|
||||
(unsigned long long)features);
|
||||
err = -EINVAL;
|
||||
goto fail_iput;
|
||||
}
|
||||
|
@ -1704,7 +1681,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
|
|||
if (!(sb->s_flags & MS_RDONLY) && features) {
|
||||
printk(KERN_ERR "BTRFS: couldn't mount RDWR because of "
|
||||
"unsupported option features (%Lx).\n",
|
||||
features);
|
||||
(unsigned long long)features);
|
||||
err = -EINVAL;
|
||||
goto fail_iput;
|
||||
}
|
||||
|
@ -2296,7 +2273,7 @@ int close_ctree(struct btrfs_root *root)
|
|||
|
||||
if (fs_info->delalloc_bytes) {
|
||||
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) {
|
||||
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->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_mapping_tree_free(&fs_info->mapping_tree);
|
||||
|
||||
|
|
|
@ -1844,10 +1844,14 @@ again:
|
|||
printk(KERN_ERR "no space left, need %llu, %llu delalloc bytes"
|
||||
", %llu bytes_used, %llu bytes_reserved, "
|
||||
"%llu bytes_pinned, %llu bytes_readonly, %llu may use"
|
||||
"%llu total\n", bytes, data_sinfo->bytes_delalloc,
|
||||
data_sinfo->bytes_used, data_sinfo->bytes_reserved,
|
||||
data_sinfo->bytes_pinned, data_sinfo->bytes_readonly,
|
||||
data_sinfo->bytes_may_use, data_sinfo->total_bytes);
|
||||
"%llu total\n", (unsigned long long)bytes,
|
||||
(unsigned long long)data_sinfo->bytes_delalloc,
|
||||
(unsigned long long)data_sinfo->bytes_used,
|
||||
(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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
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,
|
||||
struct btrfs_root *extent_root, u64 alloc_bytes,
|
||||
u64 flags, int force)
|
||||
{
|
||||
struct btrfs_space_info *space_info;
|
||||
struct btrfs_fs_info *fs_info = extent_root->fs_info;
|
||||
u64 thresh;
|
||||
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);
|
||||
|
||||
|
@ -1958,6 +1976,18 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,
|
|||
}
|
||||
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);
|
||||
if (ret)
|
||||
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->full) ? "" : "not ");
|
||||
printk(KERN_INFO "space_info total=%llu, pinned=%llu, delalloc=%llu,"
|
||||
" may_use=%llu, used=%llu\n", info->total_bytes,
|
||||
info->bytes_pinned, info->bytes_delalloc, info->bytes_may_use,
|
||||
info->bytes_used);
|
||||
" may_use=%llu, used=%llu\n",
|
||||
(unsigned long long)info->total_bytes,
|
||||
(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);
|
||||
list_for_each_entry(cache, &info->block_groups, list) {
|
||||
|
|
|
@ -17,12 +17,6 @@
|
|||
#include "ctree.h"
|
||||
#include "btrfs_inode.h"
|
||||
|
||||
/* temporary define until extent_map moves out of btrfs */
|
||||
struct kmem_cache *btrfs_cache_create(const char *name, size_t size,
|
||||
unsigned long extra_flags,
|
||||
void (*ctor)(void *, struct kmem_cache *,
|
||||
unsigned long));
|
||||
|
||||
static struct kmem_cache *extent_state_cache;
|
||||
static struct kmem_cache *extent_buffer_cache;
|
||||
|
||||
|
@ -58,15 +52,15 @@ struct extent_page_data {
|
|||
|
||||
int __init extent_io_init(void)
|
||||
{
|
||||
extent_state_cache = btrfs_cache_create("extent_state",
|
||||
sizeof(struct extent_state), 0,
|
||||
NULL);
|
||||
extent_state_cache = kmem_cache_create("extent_state",
|
||||
sizeof(struct extent_state), 0,
|
||||
SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
|
||||
if (!extent_state_cache)
|
||||
return -ENOMEM;
|
||||
|
||||
extent_buffer_cache = btrfs_cache_create("extent_buffers",
|
||||
sizeof(struct extent_buffer), 0,
|
||||
NULL);
|
||||
extent_buffer_cache = kmem_cache_create("extent_buffers",
|
||||
sizeof(struct extent_buffer), 0,
|
||||
SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
|
||||
if (!extent_buffer_cache)
|
||||
goto free_state_cache;
|
||||
return 0;
|
||||
|
@ -1407,69 +1401,6 @@ out:
|
|||
return total_bytes;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* helper function to lock both pages and extents in the tree.
|
||||
* pages must be locked first.
|
||||
*/
|
||||
static int lock_range(struct extent_io_tree *tree, u64 start, u64 end)
|
||||
{
|
||||
unsigned long index = start >> PAGE_CACHE_SHIFT;
|
||||
unsigned long end_index = end >> PAGE_CACHE_SHIFT;
|
||||
struct page *page;
|
||||
int err;
|
||||
|
||||
while (index <= end_index) {
|
||||
page = grab_cache_page(tree->mapping, index);
|
||||
if (!page) {
|
||||
err = -ENOMEM;
|
||||
goto failed;
|
||||
}
|
||||
if (IS_ERR(page)) {
|
||||
err = PTR_ERR(page);
|
||||
goto failed;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
lock_extent(tree, start, end, GFP_NOFS);
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
/*
|
||||
* we failed above in getting the page at 'index', so we undo here
|
||||
* up to but not including the page at 'index'
|
||||
*/
|
||||
end_index = index;
|
||||
index = start >> PAGE_CACHE_SHIFT;
|
||||
while (index < end_index) {
|
||||
page = find_get_page(tree->mapping, index);
|
||||
unlock_page(page);
|
||||
page_cache_release(page);
|
||||
index++;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* helper function to unlock both pages and extents in the tree.
|
||||
*/
|
||||
static int unlock_range(struct extent_io_tree *tree, u64 start, u64 end)
|
||||
{
|
||||
unsigned long index = start >> PAGE_CACHE_SHIFT;
|
||||
unsigned long end_index = end >> PAGE_CACHE_SHIFT;
|
||||
struct page *page;
|
||||
|
||||
while (index <= end_index) {
|
||||
page = find_get_page(tree->mapping, index);
|
||||
unlock_page(page);
|
||||
page_cache_release(page);
|
||||
index++;
|
||||
}
|
||||
unlock_extent(tree, start, end, GFP_NOFS);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* set the private field for a given byte offset in the tree. If there isn't
|
||||
* an extent_state there already, this does nothing.
|
||||
|
|
|
@ -6,19 +6,14 @@
|
|||
#include <linux/hardirq.h>
|
||||
#include "extent_map.h"
|
||||
|
||||
/* temporary define until extent_map moves out of btrfs */
|
||||
struct kmem_cache *btrfs_cache_create(const char *name, size_t size,
|
||||
unsigned long extra_flags,
|
||||
void (*ctor)(void *, struct kmem_cache *,
|
||||
unsigned long));
|
||||
|
||||
static struct kmem_cache *extent_map_cache;
|
||||
|
||||
int __init extent_map_init(void)
|
||||
{
|
||||
extent_map_cache = btrfs_cache_create("extent_map",
|
||||
sizeof(struct extent_map), 0,
|
||||
NULL);
|
||||
extent_map_cache = kmem_cache_create("extent_map",
|
||||
sizeof(struct extent_map), 0,
|
||||
SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
|
||||
if (!extent_map_cache)
|
||||
return -ENOMEM;
|
||||
return 0;
|
||||
|
@ -43,7 +38,6 @@ void extent_map_tree_init(struct extent_map_tree *tree, gfp_t mask)
|
|||
tree->map.rb_node = NULL;
|
||||
spin_lock_init(&tree->lock);
|
||||
}
|
||||
EXPORT_SYMBOL(extent_map_tree_init);
|
||||
|
||||
/**
|
||||
* alloc_extent_map - allocate new extent map structure
|
||||
|
@ -64,7 +58,6 @@ struct extent_map *alloc_extent_map(gfp_t mask)
|
|||
atomic_set(&em->refs, 1);
|
||||
return em;
|
||||
}
|
||||
EXPORT_SYMBOL(alloc_extent_map);
|
||||
|
||||
/**
|
||||
* free_extent_map - drop reference count of an extent_map
|
||||
|
@ -83,7 +76,6 @@ void free_extent_map(struct extent_map *em)
|
|||
kmem_cache_free(extent_map_cache, em);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(free_extent_map);
|
||||
|
||||
static struct rb_node *tree_insert(struct rb_root *root, u64 offset,
|
||||
struct rb_node *node)
|
||||
|
@ -264,7 +256,6 @@ int add_extent_mapping(struct extent_map_tree *tree,
|
|||
out:
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(add_extent_mapping);
|
||||
|
||||
/* simple helper to do math around the end of an extent, handling wrap */
|
||||
static u64 range_end(u64 start, u64 len)
|
||||
|
@ -326,7 +317,6 @@ found:
|
|||
out:
|
||||
return em;
|
||||
}
|
||||
EXPORT_SYMBOL(lookup_extent_mapping);
|
||||
|
||||
/**
|
||||
* remove_extent_mapping - removes an extent_map from the extent tree
|
||||
|
@ -346,4 +336,3 @@ int remove_extent_mapping(struct extent_map_tree *tree, struct extent_map *em)
|
|||
em->in_tree = 0;
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(remove_extent_mapping);
|
||||
|
|
|
@ -272,83 +272,6 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int btrfs_check_file(struct btrfs_root *root, struct inode *inode)
|
||||
{
|
||||
return 0;
|
||||
#if 0
|
||||
struct btrfs_path *path;
|
||||
struct btrfs_key found_key;
|
||||
struct extent_buffer *leaf;
|
||||
struct btrfs_file_extent_item *extent;
|
||||
u64 last_offset = 0;
|
||||
int nritems;
|
||||
int slot;
|
||||
int found_type;
|
||||
int ret;
|
||||
int err = 0;
|
||||
u64 extent_end = 0;
|
||||
|
||||
path = btrfs_alloc_path();
|
||||
ret = btrfs_lookup_file_extent(NULL, root, path, inode->i_ino,
|
||||
last_offset, 0);
|
||||
while (1) {
|
||||
nritems = btrfs_header_nritems(path->nodes[0]);
|
||||
if (path->slots[0] >= nritems) {
|
||||
ret = btrfs_next_leaf(root, path);
|
||||
if (ret)
|
||||
goto out;
|
||||
nritems = btrfs_header_nritems(path->nodes[0]);
|
||||
}
|
||||
slot = path->slots[0];
|
||||
leaf = path->nodes[0];
|
||||
btrfs_item_key_to_cpu(leaf, &found_key, slot);
|
||||
if (found_key.objectid != inode->i_ino)
|
||||
break;
|
||||
if (found_key.type != BTRFS_EXTENT_DATA_KEY)
|
||||
goto out;
|
||||
|
||||
if (found_key.offset < last_offset) {
|
||||
WARN_ON(1);
|
||||
btrfs_print_leaf(root, leaf);
|
||||
printk(KERN_ERR "inode %lu found offset %llu "
|
||||
"expected %llu\n", inode->i_ino,
|
||||
(unsigned long long)found_key.offset,
|
||||
(unsigned long long)last_offset);
|
||||
err = 1;
|
||||
goto out;
|
||||
}
|
||||
extent = btrfs_item_ptr(leaf, slot,
|
||||
struct btrfs_file_extent_item);
|
||||
found_type = btrfs_file_extent_type(leaf, extent);
|
||||
if (found_type == BTRFS_FILE_EXTENT_REG) {
|
||||
extent_end = found_key.offset +
|
||||
btrfs_file_extent_num_bytes(leaf, extent);
|
||||
} else if (found_type == BTRFS_FILE_EXTENT_INLINE) {
|
||||
struct btrfs_item *item;
|
||||
item = btrfs_item_nr(leaf, slot);
|
||||
extent_end = found_key.offset +
|
||||
btrfs_file_extent_inline_len(leaf, extent);
|
||||
extent_end = (extent_end + root->sectorsize - 1) &
|
||||
~((u64)root->sectorsize - 1);
|
||||
}
|
||||
last_offset = extent_end;
|
||||
path->slots[0]++;
|
||||
}
|
||||
if (0 && last_offset < inode->i_size) {
|
||||
WARN_ON(1);
|
||||
btrfs_print_leaf(root, leaf);
|
||||
printk(KERN_ERR "inode %lu found offset %llu size %llu\n",
|
||||
inode->i_ino, (unsigned long long)last_offset,
|
||||
(unsigned long long)inode->i_size);
|
||||
err = 1;
|
||||
|
||||
}
|
||||
out:
|
||||
btrfs_free_path(path);
|
||||
return err;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* this is very complex, but the basic idea is to drop all extents
|
||||
* in the range start - end. hint_block is filled in with a block number
|
||||
|
@ -363,15 +286,16 @@ out:
|
|||
*/
|
||||
noinline int btrfs_drop_extents(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *root, struct inode *inode,
|
||||
u64 start, u64 end, u64 inline_limit, u64 *hint_byte)
|
||||
u64 start, u64 end, u64 locked_end,
|
||||
u64 inline_limit, u64 *hint_byte)
|
||||
{
|
||||
u64 extent_end = 0;
|
||||
u64 locked_end = end;
|
||||
u64 search_start = start;
|
||||
u64 leaf_start;
|
||||
u64 ram_bytes = 0;
|
||||
u64 orig_parent = 0;
|
||||
u64 disk_bytenr = 0;
|
||||
u64 orig_locked_end = locked_end;
|
||||
u8 compression;
|
||||
u8 encryption;
|
||||
u16 other_encoding = 0;
|
||||
|
@ -684,11 +608,10 @@ next_slot:
|
|||
}
|
||||
out:
|
||||
btrfs_free_path(path);
|
||||
if (locked_end > end) {
|
||||
unlock_extent(&BTRFS_I(inode)->io_tree, end, locked_end - 1,
|
||||
GFP_NOFS);
|
||||
if (locked_end > orig_locked_end) {
|
||||
unlock_extent(&BTRFS_I(inode)->io_tree, orig_locked_end,
|
||||
locked_end - 1, GFP_NOFS);
|
||||
}
|
||||
btrfs_check_file(root, inode);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -332,13 +332,17 @@ int btrfs_remove_free_space(struct btrfs_block_group_cache *block_group,
|
|||
printk(KERN_ERR "couldn't find space %llu to free\n",
|
||||
(unsigned long long)offset);
|
||||
printk(KERN_ERR "cached is %d, offset %llu bytes %llu\n",
|
||||
block_group->cached, block_group->key.objectid,
|
||||
block_group->key.offset);
|
||||
block_group->cached,
|
||||
(unsigned long long)block_group->key.objectid,
|
||||
(unsigned long long)block_group->key.offset);
|
||||
btrfs_dump_free_space(block_group, bytes);
|
||||
} else if (info) {
|
||||
printk(KERN_ERR "hmm, found offset=%llu bytes=%llu, "
|
||||
"but wanted offset=%llu bytes=%llu\n",
|
||||
info->offset, info->bytes, offset, bytes);
|
||||
(unsigned long long)info->offset,
|
||||
(unsigned long long)info->bytes,
|
||||
(unsigned long long)offset,
|
||||
(unsigned long long)bytes);
|
||||
}
|
||||
WARN_ON(1);
|
||||
}
|
||||
|
@ -357,8 +361,9 @@ void btrfs_dump_free_space(struct btrfs_block_group_cache *block_group,
|
|||
info = rb_entry(n, struct btrfs_free_space, offset_index);
|
||||
if (info->bytes >= bytes)
|
||||
count++;
|
||||
printk(KERN_ERR "entry offset %llu, bytes %llu\n", info->offset,
|
||||
info->bytes);
|
||||
printk(KERN_ERR "entry offset %llu, bytes %llu\n",
|
||||
(unsigned long long)info->offset,
|
||||
(unsigned long long)info->bytes);
|
||||
}
|
||||
printk(KERN_INFO "%d blocks of free space at or bigger than bytes is"
|
||||
"\n", count);
|
||||
|
|
|
@ -79,7 +79,7 @@ int btrfs_find_free_objectid(struct btrfs_trans_handle *trans,
|
|||
}
|
||||
path = btrfs_alloc_path();
|
||||
BUG_ON(!path);
|
||||
search_start = max(search_start, BTRFS_FIRST_FREE_OBJECTID);
|
||||
search_start = max(search_start, (u64)BTRFS_FIRST_FREE_OBJECTID);
|
||||
search_key.objectid = search_start;
|
||||
search_key.type = 0;
|
||||
search_key.offset = 0;
|
||||
|
|
147
fs/btrfs/inode.c
147
fs/btrfs/inode.c
|
@ -70,7 +70,6 @@ static struct extent_io_ops btrfs_extent_io_ops;
|
|||
static struct kmem_cache *btrfs_inode_cachep;
|
||||
struct kmem_cache *btrfs_trans_handle_cachep;
|
||||
struct kmem_cache *btrfs_transaction_cachep;
|
||||
struct kmem_cache *btrfs_bit_radix_cachep;
|
||||
struct kmem_cache *btrfs_path_cachep;
|
||||
|
||||
#define S_SHIFT 12
|
||||
|
@ -234,7 +233,7 @@ static noinline int cow_file_range_inline(struct btrfs_trans_handle *trans,
|
|||
}
|
||||
|
||||
ret = btrfs_drop_extents(trans, root, inode, start,
|
||||
aligned_end, start, &hint_byte);
|
||||
aligned_end, aligned_end, start, &hint_byte);
|
||||
BUG_ON(ret);
|
||||
|
||||
if (isize > actual_end)
|
||||
|
@ -1439,6 +1438,7 @@ static int insert_reserved_file_extent(struct btrfs_trans_handle *trans,
|
|||
struct inode *inode, u64 file_pos,
|
||||
u64 disk_bytenr, u64 disk_num_bytes,
|
||||
u64 num_bytes, u64 ram_bytes,
|
||||
u64 locked_end,
|
||||
u8 compression, u8 encryption,
|
||||
u16 other_encoding, int extent_type)
|
||||
{
|
||||
|
@ -1455,7 +1455,8 @@ static int insert_reserved_file_extent(struct btrfs_trans_handle *trans,
|
|||
|
||||
path->leave_spinning = 1;
|
||||
ret = btrfs_drop_extents(trans, root, inode, file_pos,
|
||||
file_pos + num_bytes, file_pos, &hint);
|
||||
file_pos + num_bytes, locked_end,
|
||||
file_pos, &hint);
|
||||
BUG_ON(ret);
|
||||
|
||||
ins.objectid = inode->i_ino;
|
||||
|
@ -1590,6 +1591,8 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
|
|||
ordered_extent->disk_len,
|
||||
ordered_extent->len,
|
||||
ordered_extent->len,
|
||||
ordered_extent->file_offset +
|
||||
ordered_extent->len,
|
||||
compressed, 0, 0,
|
||||
BTRFS_FILE_EXTENT_REG);
|
||||
BUG_ON(ret);
|
||||
|
@ -1819,10 +1822,12 @@ good:
|
|||
return 0;
|
||||
|
||||
zeroit:
|
||||
printk(KERN_INFO "btrfs csum failed ino %lu off %llu csum %u "
|
||||
"private %llu\n", page->mapping->host->i_ino,
|
||||
(unsigned long long)start, csum,
|
||||
(unsigned long long)private);
|
||||
if (printk_ratelimit()) {
|
||||
printk(KERN_INFO "btrfs csum failed ino %lu off %llu csum %u "
|
||||
"private %llu\n", page->mapping->host->i_ino,
|
||||
(unsigned long long)start, csum,
|
||||
(unsigned long long)private);
|
||||
}
|
||||
memset(kaddr + offset, 1, end - start + 1);
|
||||
flush_dcache_page(page);
|
||||
kunmap_atomic(kaddr, KM_USER0);
|
||||
|
@ -2010,6 +2015,57 @@ void btrfs_orphan_cleanup(struct btrfs_root *root)
|
|||
btrfs_free_path(path);
|
||||
}
|
||||
|
||||
/*
|
||||
* very simple check to peek ahead in the leaf looking for xattrs. If we
|
||||
* don't find any xattrs, we know there can't be any acls.
|
||||
*
|
||||
* slot is the slot the inode is in, objectid is the objectid of the inode
|
||||
*/
|
||||
static noinline int acls_after_inode_item(struct extent_buffer *leaf,
|
||||
int slot, u64 objectid)
|
||||
{
|
||||
u32 nritems = btrfs_header_nritems(leaf);
|
||||
struct btrfs_key found_key;
|
||||
int scanned = 0;
|
||||
|
||||
slot++;
|
||||
while (slot < nritems) {
|
||||
btrfs_item_key_to_cpu(leaf, &found_key, slot);
|
||||
|
||||
/* we found a different objectid, there must not be acls */
|
||||
if (found_key.objectid != objectid)
|
||||
return 0;
|
||||
|
||||
/* we found an xattr, assume we've got an acl */
|
||||
if (found_key.type == BTRFS_XATTR_ITEM_KEY)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* we found a key greater than an xattr key, there can't
|
||||
* be any acls later on
|
||||
*/
|
||||
if (found_key.type > BTRFS_XATTR_ITEM_KEY)
|
||||
return 0;
|
||||
|
||||
slot++;
|
||||
scanned++;
|
||||
|
||||
/*
|
||||
* it goes inode, inode backrefs, xattrs, extents,
|
||||
* so if there are a ton of hard links to an inode there can
|
||||
* be a lot of backrefs. Don't waste time searching too hard,
|
||||
* this is just an optimization
|
||||
*/
|
||||
if (scanned >= 8)
|
||||
break;
|
||||
}
|
||||
/* we hit the end of the leaf before we found an xattr or
|
||||
* something larger than an xattr. We have to assume the inode
|
||||
* has acls
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* read an inode from the btree into the in-memory inode
|
||||
*/
|
||||
|
@ -2021,6 +2077,7 @@ void btrfs_read_locked_inode(struct inode *inode)
|
|||
struct btrfs_timespec *tspec;
|
||||
struct btrfs_root *root = BTRFS_I(inode)->root;
|
||||
struct btrfs_key location;
|
||||
int maybe_acls;
|
||||
u64 alloc_group_block;
|
||||
u32 rdev;
|
||||
int ret;
|
||||
|
@ -2067,6 +2124,16 @@ void btrfs_read_locked_inode(struct inode *inode)
|
|||
|
||||
alloc_group_block = btrfs_inode_block_group(leaf, inode_item);
|
||||
|
||||
/*
|
||||
* try to precache a NULL acl entry for files that don't have
|
||||
* any xattrs or acls
|
||||
*/
|
||||
maybe_acls = acls_after_inode_item(leaf, path->slots[0], inode->i_ino);
|
||||
if (!maybe_acls) {
|
||||
BTRFS_I(inode)->i_acl = NULL;
|
||||
BTRFS_I(inode)->i_default_acl = NULL;
|
||||
}
|
||||
|
||||
BTRFS_I(inode)->block_group = btrfs_find_block_group(root, 0,
|
||||
alloc_group_block, 0);
|
||||
btrfs_free_path(path);
|
||||
|
@ -2877,6 +2944,7 @@ int btrfs_cont_expand(struct inode *inode, loff_t size)
|
|||
err = btrfs_drop_extents(trans, root, inode,
|
||||
cur_offset,
|
||||
cur_offset + hole_size,
|
||||
block_end,
|
||||
cur_offset, &hint_byte);
|
||||
if (err)
|
||||
break;
|
||||
|
@ -3041,8 +3109,8 @@ static noinline void init_btrfs_i(struct inode *inode)
|
|||
{
|
||||
struct btrfs_inode *bi = BTRFS_I(inode);
|
||||
|
||||
bi->i_acl = NULL;
|
||||
bi->i_default_acl = NULL;
|
||||
bi->i_acl = BTRFS_ACL_NOT_CACHED;
|
||||
bi->i_default_acl = BTRFS_ACL_NOT_CACHED;
|
||||
|
||||
bi->generation = 0;
|
||||
bi->sequence = 0;
|
||||
|
@ -4634,47 +4702,36 @@ void btrfs_destroy_cachep(void)
|
|||
kmem_cache_destroy(btrfs_trans_handle_cachep);
|
||||
if (btrfs_transaction_cachep)
|
||||
kmem_cache_destroy(btrfs_transaction_cachep);
|
||||
if (btrfs_bit_radix_cachep)
|
||||
kmem_cache_destroy(btrfs_bit_radix_cachep);
|
||||
if (btrfs_path_cachep)
|
||||
kmem_cache_destroy(btrfs_path_cachep);
|
||||
}
|
||||
|
||||
struct kmem_cache *btrfs_cache_create(const char *name, size_t size,
|
||||
unsigned long extra_flags,
|
||||
void (*ctor)(void *))
|
||||
{
|
||||
return kmem_cache_create(name, size, 0, (SLAB_RECLAIM_ACCOUNT |
|
||||
SLAB_MEM_SPREAD | extra_flags), ctor);
|
||||
}
|
||||
|
||||
int btrfs_init_cachep(void)
|
||||
{
|
||||
btrfs_inode_cachep = btrfs_cache_create("btrfs_inode_cache",
|
||||
sizeof(struct btrfs_inode),
|
||||
0, init_once);
|
||||
btrfs_inode_cachep = kmem_cache_create("btrfs_inode_cache",
|
||||
sizeof(struct btrfs_inode), 0,
|
||||
SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, init_once);
|
||||
if (!btrfs_inode_cachep)
|
||||
goto fail;
|
||||
btrfs_trans_handle_cachep =
|
||||
btrfs_cache_create("btrfs_trans_handle_cache",
|
||||
sizeof(struct btrfs_trans_handle),
|
||||
0, NULL);
|
||||
|
||||
btrfs_trans_handle_cachep = kmem_cache_create("btrfs_trans_handle_cache",
|
||||
sizeof(struct btrfs_trans_handle), 0,
|
||||
SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
|
||||
if (!btrfs_trans_handle_cachep)
|
||||
goto fail;
|
||||
btrfs_transaction_cachep = btrfs_cache_create("btrfs_transaction_cache",
|
||||
sizeof(struct btrfs_transaction),
|
||||
0, NULL);
|
||||
|
||||
btrfs_transaction_cachep = kmem_cache_create("btrfs_transaction_cache",
|
||||
sizeof(struct btrfs_transaction), 0,
|
||||
SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
|
||||
if (!btrfs_transaction_cachep)
|
||||
goto fail;
|
||||
btrfs_path_cachep = btrfs_cache_create("btrfs_path_cache",
|
||||
sizeof(struct btrfs_path),
|
||||
0, NULL);
|
||||
|
||||
btrfs_path_cachep = kmem_cache_create("btrfs_path_cache",
|
||||
sizeof(struct btrfs_path), 0,
|
||||
SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
|
||||
if (!btrfs_path_cachep)
|
||||
goto fail;
|
||||
btrfs_bit_radix_cachep = btrfs_cache_create("btrfs_radix", 256,
|
||||
SLAB_DESTROY_BY_RCU, NULL);
|
||||
if (!btrfs_bit_radix_cachep)
|
||||
goto fail;
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
btrfs_destroy_cachep();
|
||||
|
@ -4972,7 +5029,7 @@ out_fail:
|
|||
|
||||
static int prealloc_file_range(struct btrfs_trans_handle *trans,
|
||||
struct inode *inode, u64 start, u64 end,
|
||||
u64 alloc_hint, int mode)
|
||||
u64 locked_end, u64 alloc_hint, int mode)
|
||||
{
|
||||
struct btrfs_root *root = BTRFS_I(inode)->root;
|
||||
struct btrfs_key ins;
|
||||
|
@ -4993,7 +5050,8 @@ static int prealloc_file_range(struct btrfs_trans_handle *trans,
|
|||
ret = insert_reserved_file_extent(trans, inode,
|
||||
cur_offset, ins.objectid,
|
||||
ins.offset, ins.offset,
|
||||
ins.offset, 0, 0, 0,
|
||||
ins.offset, locked_end,
|
||||
0, 0, 0,
|
||||
BTRFS_FILE_EXTENT_PREALLOC);
|
||||
BUG_ON(ret);
|
||||
num_bytes -= ins.offset;
|
||||
|
@ -5022,6 +5080,7 @@ static long btrfs_fallocate(struct inode *inode, int mode,
|
|||
u64 alloc_start;
|
||||
u64 alloc_end;
|
||||
u64 alloc_hint = 0;
|
||||
u64 locked_end;
|
||||
u64 mask = BTRFS_I(inode)->root->sectorsize - 1;
|
||||
struct extent_map *em;
|
||||
struct btrfs_trans_handle *trans;
|
||||
|
@ -5043,6 +5102,7 @@ static long btrfs_fallocate(struct inode *inode, int mode,
|
|||
goto out;
|
||||
}
|
||||
|
||||
locked_end = alloc_end - 1;
|
||||
while (1) {
|
||||
struct btrfs_ordered_extent *ordered;
|
||||
|
||||
|
@ -5055,8 +5115,8 @@ static long btrfs_fallocate(struct inode *inode, int mode,
|
|||
/* the extent lock is ordered inside the running
|
||||
* transaction
|
||||
*/
|
||||
lock_extent(&BTRFS_I(inode)->io_tree, alloc_start,
|
||||
alloc_end - 1, GFP_NOFS);
|
||||
lock_extent(&BTRFS_I(inode)->io_tree, alloc_start, locked_end,
|
||||
GFP_NOFS);
|
||||
ordered = btrfs_lookup_first_ordered_extent(inode,
|
||||
alloc_end - 1);
|
||||
if (ordered &&
|
||||
|
@ -5064,7 +5124,7 @@ static long btrfs_fallocate(struct inode *inode, int mode,
|
|||
ordered->file_offset < alloc_end) {
|
||||
btrfs_put_ordered_extent(ordered);
|
||||
unlock_extent(&BTRFS_I(inode)->io_tree,
|
||||
alloc_start, alloc_end - 1, GFP_NOFS);
|
||||
alloc_start, locked_end, GFP_NOFS);
|
||||
btrfs_end_transaction(trans, BTRFS_I(inode)->root);
|
||||
|
||||
/*
|
||||
|
@ -5089,7 +5149,8 @@ static long btrfs_fallocate(struct inode *inode, int mode,
|
|||
last_byte = (last_byte + mask) & ~mask;
|
||||
if (em->block_start == EXTENT_MAP_HOLE) {
|
||||
ret = prealloc_file_range(trans, inode, cur_offset,
|
||||
last_byte, alloc_hint, mode);
|
||||
last_byte, locked_end + 1,
|
||||
alloc_hint, mode);
|
||||
if (ret < 0) {
|
||||
free_extent_map(em);
|
||||
break;
|
||||
|
@ -5105,7 +5166,7 @@ static long btrfs_fallocate(struct inode *inode, int mode,
|
|||
break;
|
||||
}
|
||||
}
|
||||
unlock_extent(&BTRFS_I(inode)->io_tree, alloc_start, alloc_end - 1,
|
||||
unlock_extent(&BTRFS_I(inode)->io_tree, alloc_start, locked_end,
|
||||
GFP_NOFS);
|
||||
|
||||
btrfs_end_transaction(trans, BTRFS_I(inode)->root);
|
||||
|
|
|
@ -477,11 +477,13 @@ static int btrfs_ioctl_resize(struct btrfs_root *root, void __user *arg)
|
|||
*devstr = '\0';
|
||||
devstr = vol_args->name;
|
||||
devid = simple_strtoull(devstr, &end, 10);
|
||||
printk(KERN_INFO "resizing devid %llu\n", devid);
|
||||
printk(KERN_INFO "resizing devid %llu\n",
|
||||
(unsigned long long)devid);
|
||||
}
|
||||
device = btrfs_find_device(root, devid, NULL, NULL);
|
||||
if (!device) {
|
||||
printk(KERN_INFO "resizer unable to find device %llu\n", devid);
|
||||
printk(KERN_INFO "resizer unable to find device %llu\n",
|
||||
(unsigned long long)devid);
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
@ -805,7 +807,8 @@ static long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
|
|||
BUG_ON(!trans);
|
||||
|
||||
/* punch hole in destination first */
|
||||
btrfs_drop_extents(trans, root, inode, off, off+len, 0, &hint_byte);
|
||||
btrfs_drop_extents(trans, root, inode, off, off + len,
|
||||
off + len, 0, &hint_byte);
|
||||
|
||||
/* clone data */
|
||||
key.objectid = src->i_ino;
|
||||
|
|
|
@ -68,7 +68,7 @@ enum {
|
|||
Opt_degraded, Opt_subvol, Opt_device, Opt_nodatasum, Opt_nodatacow,
|
||||
Opt_max_extent, Opt_max_inline, Opt_alloc_start, Opt_nobarrier,
|
||||
Opt_ssd, Opt_thread_pool, Opt_noacl, Opt_compress, Opt_notreelog,
|
||||
Opt_flushoncommit, Opt_err,
|
||||
Opt_ratio, Opt_flushoncommit, Opt_err,
|
||||
};
|
||||
|
||||
static match_table_t tokens = {
|
||||
|
@ -87,6 +87,7 @@ static match_table_t tokens = {
|
|||
{Opt_noacl, "noacl"},
|
||||
{Opt_notreelog, "notreelog"},
|
||||
{Opt_flushoncommit, "flushoncommit"},
|
||||
{Opt_ratio, "metadata_ratio=%d"},
|
||||
{Opt_err, NULL},
|
||||
};
|
||||
|
||||
|
@ -195,7 +196,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
|
|||
info->max_extent = max_t(u64,
|
||||
info->max_extent, root->sectorsize);
|
||||
printk(KERN_INFO "btrfs: max_extent at %llu\n",
|
||||
info->max_extent);
|
||||
(unsigned long long)info->max_extent);
|
||||
}
|
||||
break;
|
||||
case Opt_max_inline:
|
||||
|
@ -210,7 +211,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
|
|||
root->sectorsize);
|
||||
}
|
||||
printk(KERN_INFO "btrfs: max_inline at %llu\n",
|
||||
info->max_inline);
|
||||
(unsigned long long)info->max_inline);
|
||||
}
|
||||
break;
|
||||
case Opt_alloc_start:
|
||||
|
@ -220,7 +221,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
|
|||
kfree(num);
|
||||
printk(KERN_INFO
|
||||
"btrfs: allocations start at %llu\n",
|
||||
info->alloc_start);
|
||||
(unsigned long long)info->alloc_start);
|
||||
}
|
||||
break;
|
||||
case Opt_noacl:
|
||||
|
@ -234,6 +235,15 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
|
|||
printk(KERN_INFO "btrfs: turning on flush-on-commit\n");
|
||||
btrfs_set_opt(info->mount_opt, FLUSHONCOMMIT);
|
||||
break;
|
||||
case Opt_ratio:
|
||||
intarg = 0;
|
||||
match_int(&args[0], &intarg);
|
||||
if (intarg) {
|
||||
info->metadata_ratio = intarg;
|
||||
printk(KERN_INFO "btrfs: metadata ratio %d\n",
|
||||
info->metadata_ratio);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -410,11 +420,14 @@ static int btrfs_show_options(struct seq_file *seq, struct vfsmount *vfs)
|
|||
if (btrfs_test_opt(root, NOBARRIER))
|
||||
seq_puts(seq, ",nobarrier");
|
||||
if (info->max_extent != (u64)-1)
|
||||
seq_printf(seq, ",max_extent=%llu", info->max_extent);
|
||||
seq_printf(seq, ",max_extent=%llu",
|
||||
(unsigned long long)info->max_extent);
|
||||
if (info->max_inline != 8192 * 1024)
|
||||
seq_printf(seq, ",max_inline=%llu", info->max_inline);
|
||||
seq_printf(seq, ",max_inline=%llu",
|
||||
(unsigned long long)info->max_inline);
|
||||
if (info->alloc_start != 0)
|
||||
seq_printf(seq, ",alloc_start=%llu", info->alloc_start);
|
||||
seq_printf(seq, ",alloc_start=%llu",
|
||||
(unsigned long long)info->alloc_start);
|
||||
if (info->thread_pool_size != min_t(unsigned long,
|
||||
num_online_cpus() + 2, 8))
|
||||
seq_printf(seq, ",thread_pool=%d", info->thread_pool_size);
|
||||
|
|
|
@ -687,7 +687,13 @@ static noinline int wait_transaction_pre_flush(struct btrfs_fs_info *info)
|
|||
prepare_to_wait(&info->transaction_wait, &wait,
|
||||
TASK_UNINTERRUPTIBLE);
|
||||
mutex_unlock(&info->trans_mutex);
|
||||
|
||||
atomic_dec(&info->throttles);
|
||||
wake_up(&info->transaction_throttle);
|
||||
|
||||
schedule();
|
||||
|
||||
atomic_inc(&info->throttles);
|
||||
mutex_lock(&info->trans_mutex);
|
||||
finish_wait(&info->transaction_wait, &wait);
|
||||
}
|
||||
|
|
|
@ -536,7 +536,7 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans,
|
|||
saved_nbytes = inode_get_bytes(inode);
|
||||
/* drop any overlapping extents */
|
||||
ret = btrfs_drop_extents(trans, root, inode,
|
||||
start, extent_end, start, &alloc_hint);
|
||||
start, extent_end, extent_end, start, &alloc_hint);
|
||||
BUG_ON(ret);
|
||||
|
||||
if (found_type == BTRFS_FILE_EXTENT_REG ||
|
||||
|
|
|
@ -1543,7 +1543,7 @@ static noinline int btrfs_update_device(struct btrfs_trans_handle *trans,
|
|||
btrfs_set_device_io_align(leaf, dev_item, device->io_align);
|
||||
btrfs_set_device_io_width(leaf, dev_item, device->io_width);
|
||||
btrfs_set_device_sector_size(leaf, dev_item, device->sector_size);
|
||||
btrfs_set_device_total_bytes(leaf, dev_item, device->total_bytes);
|
||||
btrfs_set_device_total_bytes(leaf, dev_item, device->disk_total_bytes);
|
||||
btrfs_set_device_bytes_used(leaf, dev_item, device->bytes_used);
|
||||
btrfs_mark_buffer_dirty(leaf);
|
||||
|
||||
|
@ -1940,14 +1940,6 @@ int btrfs_shrink_device(struct btrfs_device *device, u64 new_size)
|
|||
device->total_bytes = new_size;
|
||||
if (device->writeable)
|
||||
device->fs_devices->total_rw_bytes -= diff;
|
||||
ret = btrfs_update_device(trans, device);
|
||||
if (ret) {
|
||||
unlock_chunks(root);
|
||||
btrfs_end_transaction(trans, root);
|
||||
goto done;
|
||||
}
|
||||
WARN_ON(diff > old_total);
|
||||
btrfs_set_super_total_bytes(super_copy, old_total - diff);
|
||||
unlock_chunks(root);
|
||||
btrfs_end_transaction(trans, root);
|
||||
|
||||
|
@ -1979,7 +1971,7 @@ int btrfs_shrink_device(struct btrfs_device *device, u64 new_size)
|
|||
length = btrfs_dev_extent_length(l, dev_extent);
|
||||
|
||||
if (key.offset + length <= new_size)
|
||||
goto done;
|
||||
break;
|
||||
|
||||
chunk_tree = btrfs_dev_extent_chunk_tree(l, dev_extent);
|
||||
chunk_objectid = btrfs_dev_extent_chunk_objectid(l, dev_extent);
|
||||
|
@ -1992,6 +1984,26 @@ int btrfs_shrink_device(struct btrfs_device *device, u64 new_size)
|
|||
goto done;
|
||||
}
|
||||
|
||||
/* Shrinking succeeded, else we would be at "done". */
|
||||
trans = btrfs_start_transaction(root, 1);
|
||||
if (!trans) {
|
||||
ret = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
lock_chunks(root);
|
||||
|
||||
device->disk_total_bytes = new_size;
|
||||
/* Now btrfs_update_device() will change the on-disk size. */
|
||||
ret = btrfs_update_device(trans, device);
|
||||
if (ret) {
|
||||
unlock_chunks(root);
|
||||
btrfs_end_transaction(trans, root);
|
||||
goto done;
|
||||
}
|
||||
WARN_ON(diff > old_total);
|
||||
btrfs_set_super_total_bytes(super_copy, old_total - diff);
|
||||
unlock_chunks(root);
|
||||
btrfs_end_transaction(trans, root);
|
||||
done:
|
||||
btrfs_free_path(path);
|
||||
return ret;
|
||||
|
@ -3076,7 +3088,8 @@ static int fill_device_from_item(struct extent_buffer *leaf,
|
|||
unsigned long ptr;
|
||||
|
||||
device->devid = btrfs_device_id(leaf, dev_item);
|
||||
device->total_bytes = btrfs_device_total_bytes(leaf, dev_item);
|
||||
device->disk_total_bytes = btrfs_device_total_bytes(leaf, dev_item);
|
||||
device->total_bytes = device->disk_total_bytes;
|
||||
device->bytes_used = btrfs_device_bytes_used(leaf, dev_item);
|
||||
device->type = btrfs_device_type(leaf, dev_item);
|
||||
device->io_align = btrfs_device_io_align(leaf, dev_item);
|
||||
|
|
|
@ -61,6 +61,9 @@ struct btrfs_device {
|
|||
/* size of the device */
|
||||
u64 total_bytes;
|
||||
|
||||
/* size of the disk */
|
||||
u64 disk_total_bytes;
|
||||
|
||||
/* bytes used */
|
||||
u64 bytes_used;
|
||||
|
||||
|
|
Loading…
Reference in a new issue