diff options
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r-- | fs/btrfs/ctree.c | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index e2fc6f0d0243..6b76fd967153 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -1249,6 +1249,60 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1249 | return ret; | 1249 | return ret; |
1250 | } | 1250 | } |
1251 | 1251 | ||
1252 | int btrfs_extend_item(struct btrfs_trans_handle *trans, struct btrfs_root | ||
1253 | *root, struct btrfs_path *path, u32 data_size) | ||
1254 | { | ||
1255 | int ret = 0; | ||
1256 | int slot; | ||
1257 | int slot_orig; | ||
1258 | struct btrfs_leaf *leaf; | ||
1259 | struct buffer_head *leaf_buf; | ||
1260 | u32 nritems; | ||
1261 | unsigned int data_end; | ||
1262 | unsigned int old_data; | ||
1263 | unsigned int old_size; | ||
1264 | int i; | ||
1265 | |||
1266 | slot_orig = path->slots[0]; | ||
1267 | leaf_buf = path->nodes[0]; | ||
1268 | leaf = btrfs_buffer_leaf(leaf_buf); | ||
1269 | |||
1270 | nritems = btrfs_header_nritems(&leaf->header); | ||
1271 | data_end = leaf_data_end(root, leaf); | ||
1272 | |||
1273 | if (btrfs_leaf_free_space(root, leaf) < data_size) | ||
1274 | BUG(); | ||
1275 | slot = path->slots[0]; | ||
1276 | old_data = btrfs_item_end(leaf->items + slot); | ||
1277 | |||
1278 | BUG_ON(slot < 0); | ||
1279 | BUG_ON(slot >= nritems); | ||
1280 | |||
1281 | /* | ||
1282 | * item0..itemN ... dataN.offset..dataN.size .. data0.size | ||
1283 | */ | ||
1284 | /* first correct the data pointers */ | ||
1285 | for (i = slot; i < nritems; i++) { | ||
1286 | u32 ioff = btrfs_item_offset(leaf->items + i); | ||
1287 | btrfs_set_item_offset(leaf->items + i, | ||
1288 | ioff - data_size); | ||
1289 | } | ||
1290 | /* shift the data */ | ||
1291 | btrfs_memmove(root, leaf, btrfs_leaf_data(leaf) + | ||
1292 | data_end - data_size, btrfs_leaf_data(leaf) + | ||
1293 | data_end, old_data - data_end); | ||
1294 | data_end = old_data; | ||
1295 | old_size = btrfs_item_size(leaf->items + slot); | ||
1296 | btrfs_set_item_size(leaf->items + slot, old_size + data_size); | ||
1297 | btrfs_mark_buffer_dirty(leaf_buf); | ||
1298 | |||
1299 | ret = 0; | ||
1300 | if (btrfs_leaf_free_space(root, leaf) < 0) | ||
1301 | BUG(); | ||
1302 | check_leaf(root, path, 0); | ||
1303 | return ret; | ||
1304 | } | ||
1305 | |||
1252 | /* | 1306 | /* |
1253 | * Given a key and some data, insert an item into the tree. | 1307 | * Given a key and some data, insert an item into the tree. |
1254 | * This does all the path init required, making room in the tree if needed. | 1308 | * This does all the path init required, making room in the tree if needed. |