Messages in this thread Patch in this message | | | Date | Tue, 24 Aug 2010 03:50:34 -0700 (PDT) | From | David Rientjes <> | Subject | [patch 4/5] btrfs: add nofail variant of set_extent_dirty |
| |
Add set_extent_dirty_nofail(). This function is equivalent to set_extent_dirty(), except that it will never fail because of allocation failure and instead loop forever trying to allocate memory.
If the first allocation attempt fails, a warning will be emitted, including a call trace. Subsequent failures will suppress this warning.
This was added as a helper function for documentation and auditability. No future callers should be added.
Signed-off-by: David Rientjes <rientjes@google.com> --- fs/btrfs/extent-tree.c | 8 ++++---- fs/btrfs/extent_io.c | 19 +++++++++++++++++++ fs/btrfs/extent_io.h | 2 ++ 3 files changed, 25 insertions(+), 4 deletions(-)
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -3831,9 +3831,9 @@ static int update_block_group(struct btrfs_trans_handle *trans, spin_unlock(&cache->lock); spin_unlock(&cache->space_info->lock); - set_extent_dirty(info->pinned_extents, + set_extent_dirty_nofail(info->pinned_extents, bytenr, bytenr + num_bytes - 1, - GFP_NOFS | __GFP_NOFAIL); + GFP_NOFS); } btrfs_put_block_group(cache); total -= num_bytes; @@ -3872,8 +3872,8 @@ static int pin_down_extent(struct btrfs_root *root, spin_unlock(&cache->lock); spin_unlock(&cache->space_info->lock); - set_extent_dirty(root->fs_info->pinned_extents, bytenr, - bytenr + num_bytes - 1, GFP_NOFS | __GFP_NOFAIL); + set_extent_dirty_nofail(root->fs_info->pinned_extents, bytenr, + bytenr + num_bytes - 1, GFP_NOFS); return 0; } diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -940,6 +940,25 @@ int set_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end, NULL, mask); } +/* + * NOTE: no new callers of this function should be implemented! + * All memory allocations should be failable whenever possible. + */ +int set_extent_dirty_nofail(struct extent_io_tree *tree, u64 start, u64 end, + gfp_t mask) +{ + int ret; + + for (;;) { + ret = set_extent_dirty(tree, start, end, mask); + if (ret != -ENOMEM) + return ret; + WARN_ONCE(1, "Out of memory, no fallback implemented " + "(flags=0x%x)\n", + mask); + } +} + int set_extent_bits(struct extent_io_tree *tree, u64 start, u64 end, int bits, gfp_t mask) { diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h @@ -197,6 +197,8 @@ int set_extent_new(struct extent_io_tree *tree, u64 start, u64 end, gfp_t mask); int set_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end, gfp_t mask); +int set_extent_dirty_nofail(struct extent_io_tree *tree, u64 start, u64 end, + gfp_t mask); int clear_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end, gfp_t mask); int clear_extent_ordered(struct extent_io_tree *tree, u64 start, u64 end,
| |