diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-12-18 16:25:45 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:03:58 -0400 |
commit | 4aec2b52327b3a3a20faa3f1af3102c0d97c7c92 (patch) | |
tree | f17d84355d64dd42c17462069b00f271f920e4a0 /fs/btrfs/ctree.c | |
parent | 6da6abae027e2dbc59bca5f4168b0760f25068c7 (diff) |
kmalloc a few large stack objects in the btrfs_ioctl path
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r-- | fs/btrfs/ctree.c | 20 |
1 files changed, 14 insertions, 6 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 585f279d1112..7f764455f26e 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -80,10 +80,14 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans, | |||
80 | int ret = 0; | 80 | int ret = 0; |
81 | int level; | 81 | int level; |
82 | struct btrfs_key first_key; | 82 | struct btrfs_key first_key; |
83 | struct btrfs_root new_root; | 83 | struct btrfs_root *new_root; |
84 | 84 | ||
85 | memcpy(&new_root, root, sizeof(new_root)); | 85 | new_root = kmalloc(sizeof(*new_root), GFP_NOFS); |
86 | new_root.root_key.objectid = new_root_objectid; | 86 | if (!new_root) |
87 | return -ENOMEM; | ||
88 | |||
89 | memcpy(new_root, root, sizeof(*new_root)); | ||
90 | new_root->root_key.objectid = new_root_objectid; | ||
87 | 91 | ||
88 | WARN_ON(root->ref_cows && trans->transid != | 92 | WARN_ON(root->ref_cows && trans->transid != |
89 | root->fs_info->running_transaction->transid); | 93 | root->fs_info->running_transaction->transid); |
@@ -99,12 +103,14 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans, | |||
99 | } else { | 103 | } else { |
100 | first_key.objectid = 0; | 104 | first_key.objectid = 0; |
101 | } | 105 | } |
102 | cow = __btrfs_alloc_free_block(trans, &new_root, buf->len, | 106 | cow = __btrfs_alloc_free_block(trans, new_root, buf->len, |
103 | new_root_objectid, | 107 | new_root_objectid, |
104 | trans->transid, first_key.objectid, | 108 | trans->transid, first_key.objectid, |
105 | level, buf->start, 0); | 109 | level, buf->start, 0); |
106 | if (IS_ERR(cow)) | 110 | if (IS_ERR(cow)) { |
111 | kfree(new_root); | ||
107 | return PTR_ERR(cow); | 112 | return PTR_ERR(cow); |
113 | } | ||
108 | 114 | ||
109 | copy_extent_buffer(cow, buf, 0, 0, cow->len); | 115 | copy_extent_buffer(cow, buf, 0, 0, cow->len); |
110 | btrfs_set_header_bytenr(cow, cow->start); | 116 | btrfs_set_header_bytenr(cow, cow->start); |
@@ -112,7 +118,9 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans, | |||
112 | btrfs_set_header_owner(cow, new_root_objectid); | 118 | btrfs_set_header_owner(cow, new_root_objectid); |
113 | 119 | ||
114 | WARN_ON(btrfs_header_generation(buf) > trans->transid); | 120 | WARN_ON(btrfs_header_generation(buf) > trans->transid); |
115 | ret = btrfs_inc_ref(trans, &new_root, buf); | 121 | ret = btrfs_inc_ref(trans, new_root, buf); |
122 | kfree(new_root); | ||
123 | |||
116 | if (ret) | 124 | if (ret) |
117 | return ret; | 125 | return ret; |
118 | 126 | ||