Skip to content

Commit

Permalink
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/gi…
Browse files Browse the repository at this point in the history
…t/mason/btrfs-unstable

* 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable:
  Btrfs: always pin metadata in discard mode
  Btrfs: enable discard support
  Btrfs: add -o discard option
  Btrfs: properly wait log writers during log sync
  Btrfs: fix possible ENOSPC problems with truncate
  Btrfs: fix btrfs acl #ifdef checks
  Btrfs: streamline tree-log btree block writeout
  Btrfs: avoid tree log commit when there are no changes
  Btrfs: only write one super copy during fsync
  • Loading branch information
Linus Torvalds committed Oct 15, 2009
2 parents 2b650df + 444528b commit dcbeb0b
Show file tree
Hide file tree
Showing 13 changed files with 179 additions and 42 deletions.
6 changes: 3 additions & 3 deletions fs/btrfs/acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
#include "btrfs_inode.h"
#include "xattr.h"

#ifdef CONFIG_BTRFS_POSIX_ACL
#ifdef CONFIG_BTRFS_FS_POSIX_ACL

static struct posix_acl *btrfs_get_acl(struct inode *inode, int type)
{
Expand Down Expand Up @@ -313,7 +313,7 @@ struct xattr_handler btrfs_xattr_acl_access_handler = {
.set = btrfs_xattr_acl_access_set,
};

#else /* CONFIG_BTRFS_POSIX_ACL */
#else /* CONFIG_BTRFS_FS_POSIX_ACL */

int btrfs_acl_chmod(struct inode *inode)
{
Expand All @@ -325,4 +325,4 @@ int btrfs_init_acl(struct inode *inode, struct inode *dir)
return 0;
}

#endif /* CONFIG_BTRFS_POSIX_ACL */
#endif /* CONFIG_BTRFS_FS_POSIX_ACL */
6 changes: 6 additions & 0 deletions fs/btrfs/btrfs_inode.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,12 @@ struct btrfs_inode {
* transid of the trans_handle that last modified this inode
*/
u64 last_trans;

/*
* log transid when this inode was last modified
*/
u64 last_sub_trans;

/*
* transid that last logged this inode
*/
Expand Down
4 changes: 3 additions & 1 deletion fs/btrfs/ctree.h
Original file line number Diff line number Diff line change
Expand Up @@ -1009,6 +1009,7 @@ struct btrfs_root {
atomic_t log_writers;
atomic_t log_commit[2];
unsigned long log_transid;
unsigned long last_log_commit;
unsigned long log_batch;
pid_t log_start_pid;
bool log_multiple_pids;
Expand Down Expand Up @@ -1152,6 +1153,7 @@ struct btrfs_root {
#define BTRFS_MOUNT_FLUSHONCOMMIT (1 << 7)
#define BTRFS_MOUNT_SSD_SPREAD (1 << 8)
#define BTRFS_MOUNT_NOSSD (1 << 9)
#define BTRFS_MOUNT_DISCARD (1 << 10)

#define btrfs_clear_opt(o, opt) ((o) &= ~BTRFS_MOUNT_##opt)
#define btrfs_set_opt(o, opt) ((o) |= BTRFS_MOUNT_##opt)
Expand Down Expand Up @@ -2373,7 +2375,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options);
int btrfs_sync_fs(struct super_block *sb, int wait);

/* acl.c */
#ifdef CONFIG_BTRFS_POSIX_ACL
#ifdef CONFIG_BTRFS_FS_POSIX_ACL
int btrfs_check_acl(struct inode *inode, int mask);
#else
#define btrfs_check_acl NULL
Expand Down
2 changes: 2 additions & 0 deletions fs/btrfs/disk-io.c
Original file line number Diff line number Diff line change
Expand Up @@ -917,6 +917,7 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
atomic_set(&root->log_writers, 0);
root->log_batch = 0;
root->log_transid = 0;
root->last_log_commit = 0;
extent_io_tree_init(&root->dirty_log_pages,
fs_info->btree_inode->i_mapping, GFP_NOFS);

Expand Down Expand Up @@ -1087,6 +1088,7 @@ int btrfs_add_log_tree(struct btrfs_trans_handle *trans,
WARN_ON(root->log_root);
root->log_root = log_root;
root->log_transid = 0;
root->last_log_commit = 0;
return 0;
}

Expand Down
17 changes: 11 additions & 6 deletions fs/btrfs/extent-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -1568,23 +1568,23 @@ static int remove_extent_backref(struct btrfs_trans_handle *trans,
return ret;
}

#ifdef BIO_RW_DISCARD
static void btrfs_issue_discard(struct block_device *bdev,
u64 start, u64 len)
{
blkdev_issue_discard(bdev, start >> 9, len >> 9, GFP_KERNEL,
DISCARD_FL_BARRIER);
}
#endif

static int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr,
u64 num_bytes)
{
#ifdef BIO_RW_DISCARD
int ret;
u64 map_length = num_bytes;
struct btrfs_multi_bio *multi = NULL;

if (!btrfs_test_opt(root, DISCARD))
return 0;

/* Tell the block device(s) that the sectors can be discarded */
ret = btrfs_map_block(&root->fs_info->mapping_tree, READ,
bytenr, &map_length, &multi, 0);
Expand All @@ -1604,9 +1604,6 @@ static int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr,
}

return ret;
#else
return 0;
#endif
}

int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
Expand Down Expand Up @@ -3690,6 +3687,14 @@ static int pin_down_bytes(struct btrfs_trans_handle *trans,
if (is_data)
goto pinit;

/*
* discard is sloooow, and so triggering discards on
* individual btree blocks isn't a good plan. Just
* pin everything in discard mode.
*/
if (btrfs_test_opt(root, DISCARD))
goto pinit;

buf = btrfs_find_tree_block(root, bytenr, num_bytes);
if (!buf)
goto pinit;
Expand Down
41 changes: 26 additions & 15 deletions fs/btrfs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -1086,8 +1086,10 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
btrfs_end_transaction(trans, root);
else
btrfs_commit_transaction(trans, root);
} else {
} else if (ret != BTRFS_NO_LOG_SYNC) {
btrfs_commit_transaction(trans, root);
} else {
btrfs_end_transaction(trans, root);
}
}
if (file->f_flags & O_DIRECT) {
Expand Down Expand Up @@ -1137,13 +1139,25 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync)
int ret = 0;
struct btrfs_trans_handle *trans;


/* we wait first, since the writeback may change the inode */
root->log_batch++;
/* the VFS called filemap_fdatawrite for us */
btrfs_wait_ordered_range(inode, 0, (u64)-1);
root->log_batch++;

/*
* check the transaction that last modified this inode
* and see if its already been committed
*/
if (!BTRFS_I(inode)->last_trans)
goto out;

/*
* if the last transaction that changed this file was before
* the current transaction, we can bail out now without any
* syncing
*/
mutex_lock(&root->fs_info->trans_mutex);
if (BTRFS_I(inode)->last_trans <=
root->fs_info->last_trans_committed) {
Expand All @@ -1153,13 +1167,6 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync)
}
mutex_unlock(&root->fs_info->trans_mutex);

root->log_batch++;
filemap_fdatawrite(inode->i_mapping);
btrfs_wait_ordered_range(inode, 0, (u64)-1);
root->log_batch++;

if (datasync && !(inode->i_state & I_DIRTY_PAGES))
goto out;
/*
* ok we haven't committed the transaction yet, lets do a commit
*/
Expand Down Expand Up @@ -1188,14 +1195,18 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync)
*/
mutex_unlock(&dentry->d_inode->i_mutex);

if (ret > 0) {
ret = btrfs_commit_transaction(trans, root);
} else {
ret = btrfs_sync_log(trans, root);
if (ret == 0)
ret = btrfs_end_transaction(trans, root);
else
if (ret != BTRFS_NO_LOG_SYNC) {
if (ret > 0) {
ret = btrfs_commit_transaction(trans, root);
} else {
ret = btrfs_sync_log(trans, root);
if (ret == 0)
ret = btrfs_end_transaction(trans, root);
else
ret = btrfs_commit_transaction(trans, root);
}
} else {
ret = btrfs_end_transaction(trans, root);
}
mutex_lock(&dentry->d_inode->i_mutex);
out:
Expand Down
33 changes: 29 additions & 4 deletions fs/btrfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -3032,12 +3032,22 @@ static int btrfs_truncate_page(struct address_space *mapping, loff_t from)

if ((offset & (blocksize - 1)) == 0)
goto out;
ret = btrfs_check_data_free_space(root, inode, PAGE_CACHE_SIZE);
if (ret)
goto out;

ret = btrfs_reserve_metadata_for_delalloc(root, inode, 1);
if (ret)
goto out;

ret = -ENOMEM;
again:
page = grab_cache_page(mapping, index);
if (!page)
if (!page) {
btrfs_free_reserved_data_space(root, inode, PAGE_CACHE_SIZE);
btrfs_unreserve_metadata_for_delalloc(root, inode, 1);
goto out;
}

page_start = page_offset(page);
page_end = page_start + PAGE_CACHE_SIZE - 1;
Expand Down Expand Up @@ -3070,6 +3080,10 @@ static int btrfs_truncate_page(struct address_space *mapping, loff_t from)
goto again;
}

clear_extent_bits(&BTRFS_I(inode)->io_tree, page_start, page_end,
EXTENT_DIRTY | EXTENT_DELALLOC | EXTENT_DO_ACCOUNTING,
GFP_NOFS);

ret = btrfs_set_extent_delalloc(inode, page_start, page_end);
if (ret) {
unlock_extent(io_tree, page_start, page_end, GFP_NOFS);
Expand All @@ -3088,6 +3102,9 @@ static int btrfs_truncate_page(struct address_space *mapping, loff_t from)
unlock_extent(io_tree, page_start, page_end, GFP_NOFS);

out_unlock:
if (ret)
btrfs_free_reserved_data_space(root, inode, PAGE_CACHE_SIZE);
btrfs_unreserve_metadata_for_delalloc(root, inode, 1);
unlock_page(page);
page_cache_release(page);
out:
Expand All @@ -3111,7 +3128,9 @@ int btrfs_cont_expand(struct inode *inode, loff_t size)
if (size <= hole_start)
return 0;

btrfs_truncate_page(inode->i_mapping, inode->i_size);
err = btrfs_truncate_page(inode->i_mapping, inode->i_size);
if (err)
return err;

while (1) {
struct btrfs_ordered_extent *ordered;
Expand Down Expand Up @@ -3480,6 +3499,7 @@ static noinline void init_btrfs_i(struct inode *inode)
bi->generation = 0;
bi->sequence = 0;
bi->last_trans = 0;
bi->last_sub_trans = 0;
bi->logged_trans = 0;
bi->delalloc_bytes = 0;
bi->reserved_bytes = 0;
Expand Down Expand Up @@ -4980,7 +5000,9 @@ int btrfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
set_page_dirty(page);
SetPageUptodate(page);

BTRFS_I(inode)->last_trans = root->fs_info->generation + 1;
BTRFS_I(inode)->last_trans = root->fs_info->generation;
BTRFS_I(inode)->last_sub_trans = BTRFS_I(inode)->root->log_transid;

unlock_extent(io_tree, page_start, page_end, GFP_NOFS);

out_unlock:
Expand All @@ -5005,7 +5027,9 @@ static void btrfs_truncate(struct inode *inode)
if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
return;

btrfs_truncate_page(inode->i_mapping, inode->i_size);
ret = btrfs_truncate_page(inode->i_mapping, inode->i_size);
if (ret)
return;
btrfs_wait_ordered_range(inode, inode->i_size & (~mask), (u64)-1);

trans = btrfs_start_transaction(root, 1);
Expand Down Expand Up @@ -5100,6 +5124,7 @@ struct inode *btrfs_alloc_inode(struct super_block *sb)
if (!ei)
return NULL;
ei->last_trans = 0;
ei->last_sub_trans = 0;
ei->logged_trans = 0;
ei->outstanding_extents = 0;
ei->reserved_extents = 0;
Expand Down
9 changes: 7 additions & 2 deletions fs/btrfs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ 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_nossd, Opt_ssd_spread, Opt_thread_pool, Opt_noacl,
Opt_compress, Opt_notreelog, Opt_ratio, Opt_flushoncommit, Opt_err,
Opt_compress, Opt_notreelog, Opt_ratio, Opt_flushoncommit,
Opt_discard, Opt_err,
};

static match_table_t tokens = {
Expand All @@ -88,6 +89,7 @@ static match_table_t tokens = {
{Opt_notreelog, "notreelog"},
{Opt_flushoncommit, "flushoncommit"},
{Opt_ratio, "metadata_ratio=%d"},
{Opt_discard, "discard"},
{Opt_err, NULL},
};

Expand Down Expand Up @@ -257,6 +259,9 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
info->metadata_ratio);
}
break;
case Opt_discard:
btrfs_set_opt(info->mount_opt, DISCARD);
break;
default:
break;
}
Expand Down Expand Up @@ -344,7 +349,7 @@ static int btrfs_fill_super(struct super_block *sb,
sb->s_export_op = &btrfs_export_ops;
sb->s_xattr = btrfs_xattr_handlers;
sb->s_time_gran = 1;
#ifdef CONFIG_BTRFS_POSIX_ACL
#ifdef CONFIG_BTRFS_FS_POSIX_ACL
sb->s_flags |= MS_POSIXACL;
#endif

Expand Down
Loading

0 comments on commit dcbeb0b

Please sign in to comment.