Re: Way to quickly "revert back" to a snapshot?

2009-10-29 Thread TARUISI Hiroaki
I'm trying to make this snapshots/subvolumes listing feature,
I wonder how the interface should be.

I tried to make this feature using ioctl interface, but I don't
know how to notify all subvolume informations because number
of subvolumes are not known before search.
(It may work, that we call number-notify ioctl before subvol-
 listing ioctl itself, or we call subvol-listing ioctl repeatedly
 to last subvolume. But both seem to be not good to me.)

Is there any other idea?

Chris Mason wrote:
> On Sat, Oct 17, 2009 at 01:20:28PM -0400, John Dong wrote:
>> Suppose I want to do test something insane (like a massive OS
>> update) to my system, and create a snapshot before doing so.
>> Afterwards, if I decide my system is hosed and I'd like to revert
>> back to the snapshot and forget any of this actually happened,
>> what's the quickest way of doing it. It seems like by btrfs's design
>> there should be a way to just "set the head" of the filesystem back
>> to the snapshot, like git-reset, right?
> 
> This is near the top of the list of features I want to add for 2.6.33.
> Basically all we need is a way to swap the default subvolume (which is
> just a directory entry) pointer with another subvolume.
> 
> We also want a way to find an snapshot all the subvolumes and snapshots
> underneath a given root.  That way the user won't have to do it
> manually (snapshotting isn't recursive by default).
> 
> If anyone is interested in a coding project, both are fairly easy, just
> let me know.
> 
> -chris
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


-- 
taruisi

--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] Btrfs: reserve space specifically for the extent root

2009-10-29 Thread Yan, Zheng
On Fri, Oct 30, 2009 at 11:24 AM, Josef Bacik  wrote:
> On Fri, Oct 30, 2009 at 09:48:55AM +0800, Yan, Zheng  wrote:
>> On Fri, Oct 30, 2009 at 4:35 AM, Josef Bacik  wrote:
>> > If there are alot of snapshots we could conceivably end up using much more
>> > metadata space than what the worst case calculation would come up with, so
>> > instead of trying to figure out how many extents will be modified by 
>> > changing
>> > items, just calculate it per tree, and then reserve space specifically for 
>> > the
>> > extent root.  This patch does a max(size of extent root tree, 20% of free
>> > metadata space) reservation for the extent root, and then tracks how much
>> > space is used per transaction for the extent root.  Then if we get close to
>> > this amount in our transaction we will force the commit of the transaction 
>> > to
>> > free up space.  This will help us better deal with the massive space
>> > requirements that will come when users have alot of snapshots.  This was
>> > tested with my normal enospc tests.  Thanks,
>> >
>> > Signed-off-by: Josef Bacik 
>> > ---
>> >  fs/btrfs/ctree.h       |    2 +
>> >  fs/btrfs/extent-tree.c |  115 
>> > +---
>> >  fs/btrfs/transaction.c |   19 +++-
>> >  fs/btrfs/transaction.h |    1 +
>> >  4 files changed, 119 insertions(+), 18 deletions(-)
>> >
>> > diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
>> > index e5dd628..3e00df1 100644
>> > --- a/fs/btrfs/ctree.h
>> > +++ b/fs/btrfs/ctree.h
>> > @@ -2049,6 +2049,8 @@ void btrfs_delalloc_reserve_space(struct btrfs_root 
>> > *root, struct inode *inode,
>> >                                 u64 bytes);
>> >  void btrfs_delalloc_free_space(struct btrfs_root *root, struct inode 
>> > *inode,
>> >                              u64 bytes);
>> > +int btrfs_check_reserved_extent_space(struct btrfs_trans_handle *trans,
>> > +                                     struct btrfs_root *root);
>> >  /* ctree.c */
>> >  int btrfs_bin_search(struct extent_buffer *eb, struct btrfs_key *key,
>> >                     int level, int *slot);
>> > diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
>> > index c56f916..7a1f1a4 100644
>> > --- a/fs/btrfs/extent-tree.c
>> > +++ b/fs/btrfs/extent-tree.c
>> > @@ -2768,6 +2768,12 @@ static u64 calculate_bytes_needed(struct btrfs_root 
>> > *root, int num_items)
>> >        u64 num_bytes;
>> >        int level;
>> >
>> > +       /*
>> > +        * The level is the number of node level's we could possibly cow.  
>> > So
>> > +        * since we track root item reservations seperately we don't need 
>> > that,
>> > +        * and we don't need to count the leaf level, so the max number of
>> > +        * levels that could have nodes is MAX_LEVEL - 2.
>> > +        */
>> >        level = BTRFS_MAX_LEVEL - 2;
>> >        /*
>> >         * NOTE: these calculations are absolutely the worst possible case.
>> > @@ -2776,17 +2782,11 @@ static u64 calculate_bytes_needed(struct 
>> > btrfs_root *root, int num_items)
>> >         */
>> >
>> >        /*
>> > -        * for every item we insert we could insert both an extent item 
>> > and a
>> > -        * extent ref item.  Then for ever item we insert, we will need to 
>> > cow
>> > -        * both the original leaf, plus the leaf to the left and right of 
>> > it.
>> > -        *
>> > -        * Unless we are talking about the extent root, then we just want 
>> > the
>> > -        * number of items * 2, since we just need the extent item plus 
>> > its ref.
>> > +        * For each item we need we'll assume that we're going to add a 
>> > leaf for
>> > +        * it, and then we may cow the leaves on either side to make room 
>> > for
>> > +        * the items we're inserting, so multiply by 3.
>> >         */
>> > -       if (root == root->fs_info->extent_root)
>> > -               num_bytes = num_items * 2;
>> > -       else
>> > -               num_bytes = (num_items + (2 * num_items)) * 3;
>> > +       num_bytes = num_items * 3;
>> >
>> >        /*
>> >         * num_bytes is total number of leaves we could need times the leaf
>> > @@ -3031,6 +3031,64 @@ out:
>> >  }
>> >
>> >  /*
>> > + * This checks how many bytes we've allocated for the extent tree vs. how 
>> > much
>> > + * we reserved, and if we need to go ahead and force the transaction to 
>> > commit.
>> > + */
>> > +int btrfs_check_reserved_extent_space(struct btrfs_trans_handle *trans,
>> > +                                     struct btrfs_root *root)
>> > +{
>> > +       struct btrfs_fs_info *info = root->fs_info;
>> > +       struct btrfs_space_info *meta_sinfo;
>> > +       u64 used;
>> > +       u64 alloc_target;
>> > +
>> > +       /* don't force a commit if this is an embedded transaction */
>> > +       if (current->journal_info != trans)
>> > +               return 0;
>> > +
>> > +       /* get the space info for where the metadata will live */
>> > +       alloc_target = btrfs_get_alloc_profile(root, 0);
>> > +       meta_

Hard link across subvolumes

2009-10-29 Thread TARUISI Hiroaki
Hi,

In Btrfs, a hard link across subvolumes should be prohibited,
but not prohibited yet. (It may be convenient if possible,
I think.) If we make a hard link like this, filesystem may
abort or after umount/mount, contents of file may be swapped to
contents of other file(with same i-node number in same tree as
'from' file).

About this, I found Christian Parpart's patch posted last year,
and this patch seems to work well.
  http://www.spinics.net/lists/linux-btrfs/msg00749.html

But this patch is not merged yet.
Some work(to check more, to change error code or to simply test)
shuould be done for this?

-- 
taruisi

--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] Prevent btrfsck to run on mounted filesystems

2009-10-29 Thread Christoph Hellwig
On Thu, Oct 29, 2009 at 09:52:15PM +0100, Andi Drebes wrote:
> As recently discussed on the list, btrfsck should only be run on unmounted 
> filesystems. This patch adds a short check for the mount status at the 
> beginning of btrfsck. If the FS is mounted, the program aborts showing an 
> error message.

Just open the nodes with O_EXCL and you'll get all the checking for
free.  Also make sure that for a pure, read-only checks instead of a
repair to allow running on at least a read-only mounted filesystem.

--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] Btrfs: reserve space specifically for the extent root

2009-10-29 Thread Josef Bacik
On Fri, Oct 30, 2009 at 09:48:55AM +0800, Yan, Zheng  wrote:
> On Fri, Oct 30, 2009 at 4:35 AM, Josef Bacik  wrote:
> > If there are alot of snapshots we could conceivably end up using much more
> > metadata space than what the worst case calculation would come up with, so
> > instead of trying to figure out how many extents will be modified by 
> > changing
> > items, just calculate it per tree, and then reserve space specifically for 
> > the
> > extent root.  This patch does a max(size of extent root tree, 20% of free
> > metadata space) reservation for the extent root, and then tracks how much
> > space is used per transaction for the extent root.  Then if we get close to
> > this amount in our transaction we will force the commit of the transaction 
> > to
> > free up space.  This will help us better deal with the massive space
> > requirements that will come when users have alot of snapshots.  This was
> > tested with my normal enospc tests.  Thanks,
> >
> > Signed-off-by: Josef Bacik 
> > ---
> >  fs/btrfs/ctree.h       |    2 +
> >  fs/btrfs/extent-tree.c |  115 
> > +---
> >  fs/btrfs/transaction.c |   19 +++-
> >  fs/btrfs/transaction.h |    1 +
> >  4 files changed, 119 insertions(+), 18 deletions(-)
> >
> > diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
> > index e5dd628..3e00df1 100644
> > --- a/fs/btrfs/ctree.h
> > +++ b/fs/btrfs/ctree.h
> > @@ -2049,6 +2049,8 @@ void btrfs_delalloc_reserve_space(struct btrfs_root 
> > *root, struct inode *inode,
> >                                 u64 bytes);
> >  void btrfs_delalloc_free_space(struct btrfs_root *root, struct inode 
> > *inode,
> >                              u64 bytes);
> > +int btrfs_check_reserved_extent_space(struct btrfs_trans_handle *trans,
> > +                                     struct btrfs_root *root);
> >  /* ctree.c */
> >  int btrfs_bin_search(struct extent_buffer *eb, struct btrfs_key *key,
> >                     int level, int *slot);
> > diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
> > index c56f916..7a1f1a4 100644
> > --- a/fs/btrfs/extent-tree.c
> > +++ b/fs/btrfs/extent-tree.c
> > @@ -2768,6 +2768,12 @@ static u64 calculate_bytes_needed(struct btrfs_root 
> > *root, int num_items)
> >        u64 num_bytes;
> >        int level;
> >
> > +       /*
> > +        * The level is the number of node level's we could possibly cow.  
> > So
> > +        * since we track root item reservations seperately we don't need 
> > that,
> > +        * and we don't need to count the leaf level, so the max number of
> > +        * levels that could have nodes is MAX_LEVEL - 2.
> > +        */
> >        level = BTRFS_MAX_LEVEL - 2;
> >        /*
> >         * NOTE: these calculations are absolutely the worst possible case.
> > @@ -2776,17 +2782,11 @@ static u64 calculate_bytes_needed(struct btrfs_root 
> > *root, int num_items)
> >         */
> >
> >        /*
> > -        * for every item we insert we could insert both an extent item and 
> > a
> > -        * extent ref item.  Then for ever item we insert, we will need to 
> > cow
> > -        * both the original leaf, plus the leaf to the left and right of 
> > it.
> > -        *
> > -        * Unless we are talking about the extent root, then we just want 
> > the
> > -        * number of items * 2, since we just need the extent item plus its 
> > ref.
> > +        * For each item we need we'll assume that we're going to add a 
> > leaf for
> > +        * it, and then we may cow the leaves on either side to make room 
> > for
> > +        * the items we're inserting, so multiply by 3.
> >         */
> > -       if (root == root->fs_info->extent_root)
> > -               num_bytes = num_items * 2;
> > -       else
> > -               num_bytes = (num_items + (2 * num_items)) * 3;
> > +       num_bytes = num_items * 3;
> >
> >        /*
> >         * num_bytes is total number of leaves we could need times the leaf
> > @@ -3031,6 +3031,64 @@ out:
> >  }
> >
> >  /*
> > + * This checks how many bytes we've allocated for the extent tree vs. how 
> > much
> > + * we reserved, and if we need to go ahead and force the transaction to 
> > commit.
> > + */
> > +int btrfs_check_reserved_extent_space(struct btrfs_trans_handle *trans,
> > +                                     struct btrfs_root *root)
> > +{
> > +       struct btrfs_fs_info *info = root->fs_info;
> > +       struct btrfs_space_info *meta_sinfo;
> > +       u64 used;
> > +       u64 alloc_target;
> > +
> > +       /* don't force a commit if this is an embedded transaction */
> > +       if (current->journal_info != trans)
> > +               return 0;
> > +
> > +       /* get the space info for where the metadata will live */
> > +       alloc_target = btrfs_get_alloc_profile(root, 0);
> > +       meta_sinfo = __find_space_info(info, alloc_target);
> > +
> > +       spin_lock(&meta_sinfo->lock);
> > +
> > +       if (unlikely(!meta_sinfo->bytes_root)) {
> > +           

Re: [PATCH] Btrfs: reserve space specifically for the extent root

2009-10-29 Thread Yan, Zheng
On Fri, Oct 30, 2009 at 4:35 AM, Josef Bacik  wrote:
> If there are alot of snapshots we could conceivably end up using much more
> metadata space than what the worst case calculation would come up with, so
> instead of trying to figure out how many extents will be modified by changing
> items, just calculate it per tree, and then reserve space specifically for the
> extent root.  This patch does a max(size of extent root tree, 20% of free
> metadata space) reservation for the extent root, and then tracks how much
> space is used per transaction for the extent root.  Then if we get close to
> this amount in our transaction we will force the commit of the transaction to
> free up space.  This will help us better deal with the massive space
> requirements that will come when users have alot of snapshots.  This was
> tested with my normal enospc tests.  Thanks,
>
> Signed-off-by: Josef Bacik 
> ---
>  fs/btrfs/ctree.h       |    2 +
>  fs/btrfs/extent-tree.c |  115 
> +---
>  fs/btrfs/transaction.c |   19 +++-
>  fs/btrfs/transaction.h |    1 +
>  4 files changed, 119 insertions(+), 18 deletions(-)
>
> diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
> index e5dd628..3e00df1 100644
> --- a/fs/btrfs/ctree.h
> +++ b/fs/btrfs/ctree.h
> @@ -2049,6 +2049,8 @@ void btrfs_delalloc_reserve_space(struct btrfs_root 
> *root, struct inode *inode,
>                                 u64 bytes);
>  void btrfs_delalloc_free_space(struct btrfs_root *root, struct inode *inode,
>                              u64 bytes);
> +int btrfs_check_reserved_extent_space(struct btrfs_trans_handle *trans,
> +                                     struct btrfs_root *root);
>  /* ctree.c */
>  int btrfs_bin_search(struct extent_buffer *eb, struct btrfs_key *key,
>                     int level, int *slot);
> diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
> index c56f916..7a1f1a4 100644
> --- a/fs/btrfs/extent-tree.c
> +++ b/fs/btrfs/extent-tree.c
> @@ -2768,6 +2768,12 @@ static u64 calculate_bytes_needed(struct btrfs_root 
> *root, int num_items)
>        u64 num_bytes;
>        int level;
>
> +       /*
> +        * The level is the number of node level's we could possibly cow.  So
> +        * since we track root item reservations seperately we don't need 
> that,
> +        * and we don't need to count the leaf level, so the max number of
> +        * levels that could have nodes is MAX_LEVEL - 2.
> +        */
>        level = BTRFS_MAX_LEVEL - 2;
>        /*
>         * NOTE: these calculations are absolutely the worst possible case.
> @@ -2776,17 +2782,11 @@ static u64 calculate_bytes_needed(struct btrfs_root 
> *root, int num_items)
>         */
>
>        /*
> -        * for every item we insert we could insert both an extent item and a
> -        * extent ref item.  Then for ever item we insert, we will need to cow
> -        * both the original leaf, plus the leaf to the left and right of it.
> -        *
> -        * Unless we are talking about the extent root, then we just want the
> -        * number of items * 2, since we just need the extent item plus its 
> ref.
> +        * For each item we need we'll assume that we're going to add a leaf 
> for
> +        * it, and then we may cow the leaves on either side to make room for
> +        * the items we're inserting, so multiply by 3.
>         */
> -       if (root == root->fs_info->extent_root)
> -               num_bytes = num_items * 2;
> -       else
> -               num_bytes = (num_items + (2 * num_items)) * 3;
> +       num_bytes = num_items * 3;
>
>        /*
>         * num_bytes is total number of leaves we could need times the leaf
> @@ -3031,6 +3031,64 @@ out:
>  }
>
>  /*
> + * This checks how many bytes we've allocated for the extent tree vs. how 
> much
> + * we reserved, and if we need to go ahead and force the transaction to 
> commit.
> + */
> +int btrfs_check_reserved_extent_space(struct btrfs_trans_handle *trans,
> +                                     struct btrfs_root *root)
> +{
> +       struct btrfs_fs_info *info = root->fs_info;
> +       struct btrfs_space_info *meta_sinfo;
> +       u64 used;
> +       u64 alloc_target;
> +
> +       /* don't force a commit if this is an embedded transaction */
> +       if (current->journal_info != trans)
> +               return 0;
> +
> +       /* get the space info for where the metadata will live */
> +       alloc_target = btrfs_get_alloc_profile(root, 0);
> +       meta_sinfo = __find_space_info(info, alloc_target);
> +
> +       spin_lock(&meta_sinfo->lock);
> +
> +       if (unlikely(!meta_sinfo->bytes_root)) {
> +               u64 bytes;
> +
> +               /*
> +                * somebody should have already reserved space before starting
> +                * the transaction, so WARN_ON so we can fix that person.
> +                */
> +               WARN_ON(1);
> +
> +               used = meta_sinfo->bytes_used + meta_sinfo->bytes_reserved

Re: [patch 1/2] grub-0.97: btrfs support for a singe device configuration

2009-10-29 Thread Johannes Hirte
Am Donnerstag 29 Oktober 2009 00:02:08 schrieb Edward Shishkin:
> Johannes Hirte wrote:
> [...]
> > This compiles and works, but only with stage2. When using stage1_5, grub 
> > hangs
> > on boot with
> >
> > GRUB loading stage1.5 
> >
> > and blinking cursor. Is the multidevice patch also necessary for single 
> > devices?
> 
> Yes, please use both patches!
> I have split the stuff because the mailing list refuse attachments >100K.
> 
> Thanks,
> Edward.

With both patches applied it works now with stage1_5. Thank you. The patch for
gentoo is available on http://bugs.gentoo.org/show_bug.cgi?id=283637, if
somebody is interested.

Johannes
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] Prevent btrfsck to run on mounted filesystems

2009-10-29 Thread Andi Drebes
As recently discussed on the list, btrfsck should only be run on unmounted 
filesystems. This patch adds a short check for the mount status at the 
beginning of btrfsck. If the FS is mounted, the program aborts showing an error 
message.

Signed-off-by: Andi Drebes 
---
diff --git a/btrfsck.c b/btrfsck.c
index 73f1836..87ae776 100644
--- a/btrfsck.c
+++ b/btrfsck.c
@@ -28,6 +28,7 @@
 #include "transaction.h"
 #include "list.h"
 #include "version.h"
+#include "utils.h"
 
 static u64 bytes_used = 0;
 static u64 total_csum_bytes = 0;
@@ -2819,6 +2820,16 @@ int main(int ac, char **av)
if (ac < 2)
print_usage();
 
+   ret = check_mounted(av[1]);
+   if (ret < 0) {
+   fprintf(stderr, "error checking %s mount status\n", av[1]);
+   return 1;
+   }
+   if (ret == 1) {
+   fprintf(stderr, "%s is mounted. btrfsck can only be run on an 
unmounted filesystem.\n", av[1]);
+   return 1;
+   }
+
radix_tree_init();
cache_tree_init(&root_cache);
root = open_ctree(av[1], 0, 0);
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] Btrfs: reserve space specifically for the extent root

2009-10-29 Thread Josef Bacik
If there are alot of snapshots we could conceivably end up using much more
metadata space than what the worst case calculation would come up with, so
instead of trying to figure out how many extents will be modified by changing
items, just calculate it per tree, and then reserve space specifically for the
extent root.  This patch does a max(size of extent root tree, 20% of free
metadata space) reservation for the extent root, and then tracks how much
space is used per transaction for the extent root.  Then if we get close to
this amount in our transaction we will force the commit of the transaction to
free up space.  This will help us better deal with the massive space
requirements that will come when users have alot of snapshots.  This was
tested with my normal enospc tests.  Thanks,

Signed-off-by: Josef Bacik 
---
 fs/btrfs/ctree.h   |2 +
 fs/btrfs/extent-tree.c |  115 +---
 fs/btrfs/transaction.c |   19 +++-
 fs/btrfs/transaction.h |1 +
 4 files changed, 119 insertions(+), 18 deletions(-)

diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index e5dd628..3e00df1 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -2049,6 +2049,8 @@ void btrfs_delalloc_reserve_space(struct btrfs_root 
*root, struct inode *inode,
 u64 bytes);
 void btrfs_delalloc_free_space(struct btrfs_root *root, struct inode *inode,
  u64 bytes);
+int btrfs_check_reserved_extent_space(struct btrfs_trans_handle *trans,
+ struct btrfs_root *root);
 /* ctree.c */
 int btrfs_bin_search(struct extent_buffer *eb, struct btrfs_key *key,
 int level, int *slot);
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index c56f916..7a1f1a4 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -2768,6 +2768,12 @@ static u64 calculate_bytes_needed(struct btrfs_root 
*root, int num_items)
u64 num_bytes;
int level;
 
+   /*
+* The level is the number of node level's we could possibly cow.  So
+* since we track root item reservations seperately we don't need that,
+* and we don't need to count the leaf level, so the max number of
+* levels that could have nodes is MAX_LEVEL - 2.
+*/
level = BTRFS_MAX_LEVEL - 2;
/*
 * NOTE: these calculations are absolutely the worst possible case.
@@ -2776,17 +2782,11 @@ static u64 calculate_bytes_needed(struct btrfs_root 
*root, int num_items)
 */
 
/*
-* for every item we insert we could insert both an extent item and a
-* extent ref item.  Then for ever item we insert, we will need to cow
-* both the original leaf, plus the leaf to the left and right of it.
-*
-* Unless we are talking about the extent root, then we just want the
-* number of items * 2, since we just need the extent item plus its ref.
+* For each item we need we'll assume that we're going to add a leaf for
+* it, and then we may cow the leaves on either side to make room for
+* the items we're inserting, so multiply by 3.
 */
-   if (root == root->fs_info->extent_root)
-   num_bytes = num_items * 2;
-   else
-   num_bytes = (num_items + (2 * num_items)) * 3;
+   num_bytes = num_items * 3;
 
/*
 * num_bytes is total number of leaves we could need times the leaf
@@ -3031,6 +3031,64 @@ out:
 }
 
 /*
+ * This checks how many bytes we've allocated for the extent tree vs. how much
+ * we reserved, and if we need to go ahead and force the transaction to commit.
+ */
+int btrfs_check_reserved_extent_space(struct btrfs_trans_handle *trans,
+ struct btrfs_root *root)
+{
+   struct btrfs_fs_info *info = root->fs_info;
+   struct btrfs_space_info *meta_sinfo;
+   u64 used;
+   u64 alloc_target;
+
+   /* don't force a commit if this is an embedded transaction */
+   if (current->journal_info != trans)
+   return 0;
+
+   /* get the space info for where the metadata will live */
+   alloc_target = btrfs_get_alloc_profile(root, 0);
+   meta_sinfo = __find_space_info(info, alloc_target);
+
+   spin_lock(&meta_sinfo->lock);
+
+   if (unlikely(!meta_sinfo->bytes_root)) {
+   u64 bytes;
+
+   /*
+* somebody should have already reserved space before starting
+* the transaction, so WARN_ON so we can fix that person.
+*/
+   WARN_ON(1);
+
+   used = meta_sinfo->bytes_used + meta_sinfo->bytes_reserved +
+   meta_sinfo->bytes_pinned + meta_sinfo->bytes_readonly +
+   meta_sinfo->bytes_super + meta_sinfo->bytes_root +
+   meta_sinfo->bytes_may_use + meta_sinfo->bytes_delalloc;
+
+   bytes = meta