From: Jan Schmidt <list.btrfs@jan-o-sch.net>
To: Tsutomu Itoh <t-itoh@jp.fujitsu.com>, linux-btrfs@vger.kernel.org
Subject: Re: [PATCH 07/24] Btrfs: add tree modification log functions
Date: Mon, 21 May 2012 08:06:44 +0200 [thread overview]
Message-ID: <4FB9DB74.9000200@jan-o-sch.net> (raw)
In-Reply-To: <4FB981D2.9040209@jp.fujitsu.com>
Hi Tsutomu,
On Mon, May 21, 2012 at 01:44 (+0200), Tsutomu Itoh wrote:
>> +static noinline int
>> +__tree_mod_log_insert(struct btrfs_fs_info *fs_info, struct tree_mod_elem *tm)
>> +{
>> + struct rb_root *tm_root;
>> + struct rb_node **new;
>> + struct rb_node *parent = NULL;
>> + struct tree_mod_elem *cur;
>> +
>> + BUG_ON(!tm || !tm->elem.seq);
>> +
>> + write_lock(&fs_info->tree_mod_log_lock);
>> + tm_root =&fs_info->tree_mod_log;
>> + new =&tm_root->rb_node;
>> + while (*new) {
>> + cur = container_of(*new, struct tree_mod_elem, node);
>> + parent = *new;
>> + if (cur->index< tm->index)
>> + new =&((*new)->rb_left);
>> + else if (cur->index> tm->index)
>> + new =&((*new)->rb_right);
>> + else if (cur->elem.seq< tm->elem.seq)
>> + new =&((*new)->rb_left);
>> + else if (cur->elem.seq> tm->elem.seq)
>> + new =&((*new)->rb_right);
>> + else {
>> + kfree(tm);
>> + return -EEXIST;
>
> I think that write_unlock() is necessary for here.
I thought about calling write_unlock() here and decided against, because
we cannot handle EEXIST anyway. If it ever occurs, there's a bug in the
code and we hit a BUG_ON immediately after.
To make that more explicit, I'll change it to either call BUG() here
directly or do the write_unlock nevertheless.
>> + }
>> + }
>> +
>> + rb_link_node(&tm->node, parent, new);
>> + rb_insert_color(&tm->node, tm_root);
>> + write_unlock(&fs_info->tree_mod_log_lock);
>> +
>> + return 0;
>> +}
>> +
>> +int tree_mod_alloc(struct btrfs_fs_info *fs_info, gfp_t flags,
>> + struct tree_mod_elem **tm_ret)
>> +{
>> + struct tree_mod_elem *tm;
>> + u64 seq = 0;
>> +
>> + /*
>> + * we want to avoid a malloc/free cycle if there's no blocker in the
>> + * list.
>> + * we also want to avoid atomic malloc. so we must drop the spinlock
>> + * before calling kzalloc and recheck afterwards.
>> + */
>> + spin_lock(&fs_info->tree_mod_seq_lock);
>> + if (list_empty(&fs_info->tree_mod_seq_list))
>> + goto out;
>> +
>> + spin_unlock(&fs_info->tree_mod_seq_lock);
>> + tm = *tm_ret = kzalloc(sizeof(*tm), flags);
>> + if (!tm)
>> + return -ENOMEM;
>> +
>> + spin_lock(&fs_info->tree_mod_seq_lock);
>> + if (list_empty(&fs_info->tree_mod_seq_list)) {
>> + kfree(tm);
>> + goto out;
>> + }
>> +
>> + __get_tree_mod_seq(fs_info,&tm->elem);
>> + seq = tm->elem.seq;
>> + tm->elem.flags = 0;
>> +
>> +out:
>> + spin_unlock(&fs_info->tree_mod_seq_lock);
>> + return seq;
>> +}
>> +
>> +static noinline int
>> +tree_mod_log_insert_key_mask(struct btrfs_fs_info *fs_info,
>> + struct extent_buffer *eb, int slot,
>> + enum mod_log_op op, gfp_t flags)
>> +{
>> + struct tree_mod_elem *tm;
>> + int ret;
>> +
>> + ret = tree_mod_alloc(fs_info, flags,&tm);
>> + if (ret<= 0)
>> + return ret;
>> +
>> + tm->index = eb->start>> PAGE_CACHE_SHIFT;
>> + if (op != MOD_LOG_KEY_ADD) {
>> + btrfs_node_key(eb,&tm->key, slot);
>> + tm->blockptr = btrfs_node_blockptr(eb, slot);
>> + }
>> + tm->op = op;
>> + tm->slot = slot;
>> + tm->generation = btrfs_node_ptr_generation(eb, slot);
>> +
>> + return __tree_mod_log_insert(fs_info, tm);
>> +}
>> +
>> +static noinline int
>> +tree_mod_log_insert_key(struct btrfs_fs_info *fs_info, struct extent_buffer *eb,
>> + int slot, enum mod_log_op op)
>> +{
>> + return tree_mod_log_insert_key_mask(fs_info, eb, slot, op, GFP_NOFS);
>> +}
>> +
>> +static noinline int
>> +tree_mod_log_insert_move(struct btrfs_fs_info *fs_info,
>> + struct extent_buffer *eb, int dst_slot, int src_slot,
>> + int nr_items, gfp_t flags)
>> +{
>> + struct tree_mod_elem *tm;
>> + int ret;
>> +
>> + ret = tree_mod_alloc(fs_info, flags,&tm);
>> + if (ret<= 0)
>> + return ret;
>> +
>> + tm->index = eb->start>> PAGE_CACHE_SHIFT;
>> + tm->slot = src_slot;
>> + tm->move.dst_slot = dst_slot;
>> + tm->move.nr_items = nr_items;
>> + tm->op = MOD_LOG_MOVE_KEYS;
>> +
>> + return __tree_mod_log_insert(fs_info, tm);
>> +}
>> +
>> +static noinline int
>> +tree_mod_log_insert_root(struct btrfs_fs_info *fs_info,
>> + struct extent_buffer *old_root,
>> + struct extent_buffer *new_root, gfp_t flags)
>> +{
>> + struct tree_mod_elem *tm;
>> + int ret;
>> +
>> + ret = tree_mod_alloc(fs_info, flags,&tm);
>> + if (ret<= 0)
>> + return ret;
>> +
>> + tm->index = new_root->start>> PAGE_CACHE_SHIFT;
>> + tm->old_root.logical = old_root->start;
>> + tm->old_root.level = btrfs_header_level(old_root);
>> + tm->generation = btrfs_header_generation(old_root);
>> + tm->op = MOD_LOG_ROOT_REPLACE;
>> +
>> + return __tree_mod_log_insert(fs_info, tm);
>> +}
>> +
>> +static struct tree_mod_elem *
>> +__tree_mod_log_search(struct btrfs_fs_info *fs_info, u64 start, u64 min_seq,
>> + int smallest)
>> +{
>> + struct rb_root *tm_root;
>> + struct rb_node *node;
>> + struct tree_mod_elem *cur = NULL;
>> + struct tree_mod_elem *found = NULL;
>> + u64 index = start>> PAGE_CACHE_SHIFT;
>> +
>> + read_lock(&fs_info->tree_mod_log_lock);
>> + tm_root =&fs_info->tree_mod_log;
>> + node = tm_root->rb_node;
>> + while (node) {
>> + cur = container_of(node, struct tree_mod_elem, node);
>> + if (cur->index< index) {
>> + node = node->rb_left;
>> + } else if (cur->index> index) {
>> + node = node->rb_right;
>> + } else if (cur->elem.seq< min_seq) {
>> + node = node->rb_left;
>> + } else if (!smallest) {
>> + /* we want the node with the highest seq */
>> + if (found)
>> + BUG_ON(found->elem.seq> cur->elem.seq);
>> + found = cur;
>> + node = node->rb_left;
>> + } else if (cur->elem.seq> min_seq) {
>> + /* we want the node with the smallest seq */
>> + if (found)
>> + BUG_ON(found->elem.seq< cur->elem.seq);
>> + found = cur;
>> + node = node->rb_right;
>> + } else {
>
> I think read_unlock() is necessary for here.
Right, I'll add that. Strange lockdep didn't catch this one.
Thanks for looking!
-Jan
next prev parent reply other threads:[~2012-05-21 6:06 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-05-20 16:06 [PATCH 00/24] Btrfs: tree modification log and qgroup patch set Jan Schmidt
2012-05-20 16:06 ` [PATCH 01/24] Btrfs: bugfix: ignore the wrong key for indirect tree block backrefs Jan Schmidt
2012-05-20 16:06 ` [PATCH 02/24] Btrfs: look into the extent during find_all_leafs Jan Schmidt
2012-05-20 16:06 ` [PATCH 03/24] Btrfs: don't set for_cow parameter for tree block functions Jan Schmidt
2012-05-20 16:06 ` [PATCH 04/24] Btrfs: move struct seq_list to ctree.h Jan Schmidt
2012-05-20 16:06 ` [PATCH 05/24] Btrfs: dummy extent buffers for tree mod log Jan Schmidt
2012-05-20 16:06 ` [PATCH 06/24] Btrfs: add tree mod log to fs_info Jan Schmidt
2012-05-20 16:06 ` [PATCH 07/24] Btrfs: add tree modification log functions Jan Schmidt
2012-05-20 23:44 ` Tsutomu Itoh
2012-05-21 6:06 ` Jan Schmidt [this message]
2012-05-20 16:06 ` [PATCH 08/24] Btrfs: put all modifications into the tree mod log Jan Schmidt
2012-05-20 16:06 ` [PATCH 09/24] Btrfs: add btrfs_search_old_slot Jan Schmidt
2012-05-20 16:06 ` [PATCH 10/24] Btrfs: use the tree modification log for backref resolving Jan Schmidt
2012-05-20 16:06 ` [PATCH 11/24] Btrfs: fs_info variable for join_transaction Jan Schmidt
2012-05-20 16:06 ` [PATCH 12/24] Btrfs: tree mod log sanity checks in join_transaction Jan Schmidt
2012-05-20 16:06 ` [PATCH 13/24] Btrfs: qgroup on-disk format Jan Schmidt
2012-05-20 16:06 ` [PATCH 14/24] Btrfs: add helper for tree enumeration Jan Schmidt
2012-05-20 16:06 ` [PATCH 15/24] Btrfs: check the root passed to btrfs_end_transaction Jan Schmidt
2012-05-20 16:06 ` [PATCH 16/24] Btrfs: added helper to create new trees Jan Schmidt
2012-05-20 16:06 ` [PATCH 17/24] Btrfs: qgroup state and initialization Jan Schmidt
2012-05-20 16:06 ` [PATCH 18/24] Btrfs: Test code to change the order of delayed-ref processing Jan Schmidt
2012-05-20 16:06 ` [PATCH 19/24] Btrfs: qgroup implementation and prototypes Jan Schmidt
2012-05-21 0:42 ` Tsutomu Itoh
2012-05-20 16:06 ` [PATCH 20/24] Btrfs: quota tree support and startup Jan Schmidt
2012-05-20 16:06 ` [PATCH 21/24] Btrfs: hooks for qgroup to record delayed refs Jan Schmidt
2012-05-20 16:06 ` [PATCH 22/24] Btrfs: hooks to reserve qgroup space Jan Schmidt
2012-05-20 16:06 ` [PATCH 23/24] Btrfs: add qgroup ioctls Jan Schmidt
[not found] ` <1337533249.9054.1.camel@ierdnac-hp>
2012-05-21 6:32 ` Jan Schmidt
2012-05-20 16:06 ` [PATCH 24/24] Btrfs: add qgroup inheritance Jan Schmidt
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4FB9DB74.9000200@jan-o-sch.net \
--to=list.btrfs@jan-o-sch.net \
--cc=linux-btrfs@vger.kernel.org \
--cc=t-itoh@jp.fujitsu.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.