Hello,

This patch adds two hooks to 'extent_map_ops'. 'set_extent_bit' and
'set_extent_bit' call the hook functions before they modify
'extent_state->state'. The last parameter of the hook functions
indicates bits that will be inverted.  By using these hooks, do delay
allocation accounting is easy.

Regards
YZ
---
diff -r dc03d8df4762 ctree.h
--- a/ctree.h   Wed Nov 07 21:08:16 2007 -0500
+++ b/ctree.h   Mon Nov 12 11:03:16 2007 +0800
@@ -323,6 +323,9 @@ struct btrfs_fs_info {
        struct completion kobj_unregister;
        int do_barriers;
        int closing;
+
+       u64 total_delalloc;
+       spinlock_t stat_lock;
 };

 /*
diff -r dc03d8df4762 disk-io.c
--- a/disk-io.c Wed Nov 07 21:08:16 2007 -0500
+++ b/disk-io.c Mon Nov 12 11:03:16 2007 +0800
@@ -570,6 +570,9 @@ struct btrfs_root *open_ctree(struct sup
        fs_info->do_barriers = 1;
        fs_info->closing = 0;

+       fs_info->total_delalloc = 0;
+       spin_lock_init(&fs_info->stat_lock);
+
        INIT_DELAYED_WORK(&fs_info->trans_work, btrfs_transaction_cleaner);
        BTRFS_I(fs_info->btree_inode)->root = tree_root;
        memset(&BTRFS_I(fs_info->btree_inode)->location, 0,
diff -r dc03d8df4762 extent_map.c
--- a/extent_map.c      Wed Nov 07 21:08:16 2007 -0500
+++ b/extent_map.c      Mon Nov 12 11:03:16 2007 +0800
@@ -502,7 +502,15 @@ int clear_extent_bit(struct extent_map_t
        unsigned long flags;
        int err;
        int set = 0;
-
+       int clear = bits;
+       void (*hook)(struct extent_map_tree *, struct extent_state *, int);
+
+       if (delete)
+               clear = -1;
+       if (tree->ops)
+               hook = tree->ops->clear_extent_bits_hook;
+       else
+               hook = NULL;
 again:
        if (!prealloc && (mask & __GFP_WAIT)) {
                prealloc = alloc_extent_state(mask);
@@ -546,6 +554,8 @@ again:
                if (err)
                        goto out;
                if (state->end <= end) {
+                       if (hook)
+                               hook(tree, state, clear & state->state);
                        start = state->end + 1;
                        set |= clear_state_bit(tree, state, bits,
                                        wake, delete);
@@ -566,12 +576,16 @@ again:

                if (wake)
                        wake_up(&state->wq);
+               if (hook)
+                       hook(tree, prealloc, clear & prealloc->state);
                set |= clear_state_bit(tree, prealloc, bits,
                                       wake, delete);
                prealloc = NULL;
                goto out;
        }

+       if (hook)
+               hook(tree, state, clear & state->state);
        start = state->end + 1;
        set |= clear_state_bit(tree, state, bits, wake, delete);
        goto search_again;
@@ -677,6 +691,12 @@ int set_extent_bit(struct extent_map_tre
        int set;
        u64 last_start;
        u64 last_end;
+       void (*hook)(struct extent_map_tree *, struct extent_state *, int);
+
+       if (tree->ops)
+               hook = tree->ops->set_extent_bits_hook;
+       else
+               hook = NULL;
 again:
        if (!prealloc && (mask & __GFP_WAIT)) {
                prealloc = alloc_extent_state(mask);
@@ -691,6 +711,11 @@ again:
         */
        node = tree_search(&tree->state, start);
        if (!node) {
+               if (hook) {
+                       prealloc->start = start;
+                       prealloc->end = end;
+                       hook(tree, prealloc, bits);
+               }
                err = insert_state(tree, prealloc, start, end, bits);
                prealloc = NULL;
                BUG_ON(err == -EEXIST);
@@ -714,6 +739,8 @@ again:
                        err = -EEXIST;
                        goto out;
                }
+               if (hook)
+                       hook(tree, state, bits ^ set);
                state->state |= bits;
                start = state->end + 1;
                merge_state(tree, state);
@@ -749,6 +776,8 @@ again:
                if (err)
                        goto out;
                if (state->end <= end) {
+                       if (hook)
+                               hook(tree, state, bits ^ set);
                        state->state |= bits;
                        start = state->end + 1;
                        merge_state(tree, state);
@@ -770,6 +799,11 @@ again:
                        this_end = end;
                else
                        this_end = last_start -1;
+               if (hook) {
+                       prealloc->start = start;
+                       prealloc->end = this_end;
+                       hook(tree, prealloc, bits);
+               }
                err = insert_state(tree, prealloc, start, this_end,
                                   bits);
                prealloc = NULL;
@@ -794,7 +828,8 @@ again:
                }
                err = split_state(tree, state, prealloc, end + 1);
                BUG_ON(err == -EEXIST);
-
+               if (hook)
+                       hook(tree, prealloc, bits ^ set);
                prealloc->state |= bits;
                merge_state(tree, prealloc);
                prealloc = NULL;
diff -r dc03d8df4762 extent_map.h
--- a/extent_map.h      Wed Nov 07 21:08:16 2007 -0500
+++ b/extent_map.h      Mon Nov 12 11:03:16 2007 +0800
@@ -27,6 +27,9 @@
 #define EXTENT_PAGE_PRIVATE 1
 #define EXTENT_PAGE_PRIVATE_FIRST_PAGE 3

+struct extent_map;
+struct extent_state;
+struct extent_map_tree;

 struct extent_map_ops {
        int (*fill_delalloc)(struct inode *inode, u64 start, u64 end);
@@ -34,6 +37,10 @@ struct extent_map_ops {
        int (*readpage_io_hook)(struct page *page, u64 start, u64 end);
        int (*readpage_end_io_hook)(struct page *page, u64 start, u64 end);
        void (*writepage_end_io_hook)(struct page *page, u64 start, u64 end);
+       void (*set_extent_bits_hook)(struct extent_map_tree *tree,
+                               struct extent_state *state, int diff);
+       void (*clear_extent_bits_hook)(struct extent_map_tree *tree,
+                               struct extent_state *state, int diff);
 };

 struct extent_map_tree {
diff -r dc03d8df4762 inode.c
--- a/inode.c   Wed Nov 07 21:08:16 2007 -0500
+++ b/inode.c   Mon Nov 12 11:03:16 2007 +0800
@@ -196,6 +196,36 @@ zeroit:
        kunmap_atomic(kaddr, KM_IRQ0);
        local_irq_restore(flags);
        return 0;
+}
+
+void btrfs_set_extent_bits_hook(struct extent_map_tree *tree,
+                               struct extent_state *state, int diff)
+{
+       struct inode *inode = tree->mapping->host;
+       struct btrfs_fs_info *info = BTRFS_I(inode)->root->fs_info;
+
+       /* local irq has already been disabled */
+       if (diff & EXTENT_DELALLOC) {
+               spin_lock(&info->stat_lock);
+               info->total_delalloc += state->end + 1 - state->start;
+               spin_unlock(&info->stat_lock);
+       }
+       return;
+}
+
+void btrfs_clear_extent_bits_hook(struct extent_map_tree *tree,
+                                 struct extent_state *state, int diff)
+{
+       struct inode *inode = tree->mapping->host;
+       struct btrfs_fs_info *info = BTRFS_I(inode)->root->fs_info;
+       
+       /* local irq has already been disabled */
+       if (diff & EXTENT_DELALLOC) {
+               spin_lock(&info->stat_lock);
+               info->total_delalloc -= state->end + 1 - state->start;
+               spin_unlock(&info->stat_lock);
+       }
+       return;
 }

 void btrfs_read_locked_inode(struct inode *inode)
@@ -2531,6 +2561,8 @@ static struct extent_map_ops btrfs_exten
        .writepage_io_hook = btrfs_writepage_io_hook,
        .readpage_io_hook = btrfs_readpage_io_hook,
        .readpage_end_io_hook = btrfs_readpage_end_io_hook,
+       .set_extent_bits_hook = btrfs_set_extent_bits_hook,
+       .clear_extent_bits_hook = btrfs_clear_extent_bits_hook,
 };

 static struct address_space_operations btrfs_aops = {

_______________________________________________
Btrfs-devel mailing list
[email protected]
http://oss.oracle.com/mailman/listinfo/btrfs-devel

Reply via email to