diff options
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r-- | fs/btrfs/ctree.c | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 6b76fd967153..43d4779abdd1 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -1249,6 +1249,63 @@ 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_truncate_item(struct btrfs_trans_handle *trans, | ||
1253 | struct btrfs_root *root, | ||
1254 | struct btrfs_path *path, | ||
1255 | u32 new_size) | ||
1256 | { | ||
1257 | int ret = 0; | ||
1258 | int slot; | ||
1259 | int slot_orig; | ||
1260 | struct btrfs_leaf *leaf; | ||
1261 | struct buffer_head *leaf_buf; | ||
1262 | u32 nritems; | ||
1263 | unsigned int data_end; | ||
1264 | unsigned int old_data_start; | ||
1265 | unsigned int old_size; | ||
1266 | unsigned int size_diff; | ||
1267 | int i; | ||
1268 | |||
1269 | slot_orig = path->slots[0]; | ||
1270 | leaf_buf = path->nodes[0]; | ||
1271 | leaf = btrfs_buffer_leaf(leaf_buf); | ||
1272 | |||
1273 | nritems = btrfs_header_nritems(&leaf->header); | ||
1274 | data_end = leaf_data_end(root, leaf); | ||
1275 | |||
1276 | slot = path->slots[0]; | ||
1277 | old_data_start = btrfs_item_offset(leaf->items + slot); | ||
1278 | old_size = btrfs_item_size(leaf->items + slot); | ||
1279 | BUG_ON(old_size <= new_size); | ||
1280 | size_diff = old_size - new_size; | ||
1281 | |||
1282 | BUG_ON(slot < 0); | ||
1283 | BUG_ON(slot >= nritems); | ||
1284 | |||
1285 | /* | ||
1286 | * item0..itemN ... dataN.offset..dataN.size .. data0.size | ||
1287 | */ | ||
1288 | /* first correct the data pointers */ | ||
1289 | for (i = slot; i < nritems; i++) { | ||
1290 | u32 ioff = btrfs_item_offset(leaf->items + i); | ||
1291 | btrfs_set_item_offset(leaf->items + i, | ||
1292 | ioff + size_diff); | ||
1293 | } | ||
1294 | /* shift the data */ | ||
1295 | printk("truncate item, new_size %u old_size %u, diff %u, bufp %p, dst, %p, num %u, old_data_start %u, data_end %u\n", new_size, old_size, size_diff, leaf, btrfs_leaf_data(leaf) + data_end + size_diff, old_data_start-data_end, old_data_start, data_end); | ||
1296 | btrfs_memmove(root, leaf, btrfs_leaf_data(leaf) + | ||
1297 | data_end + size_diff, btrfs_leaf_data(leaf) + | ||
1298 | data_end, old_data_start + new_size - data_end); | ||
1299 | btrfs_set_item_size(leaf->items + slot, new_size); | ||
1300 | btrfs_mark_buffer_dirty(leaf_buf); | ||
1301 | |||
1302 | ret = 0; | ||
1303 | if (btrfs_leaf_free_space(root, leaf) < 0) | ||
1304 | BUG(); | ||
1305 | check_leaf(root, path, 0); | ||
1306 | return ret; | ||
1307 | } | ||
1308 | |||
1252 | int btrfs_extend_item(struct btrfs_trans_handle *trans, struct btrfs_root | 1309 | int btrfs_extend_item(struct btrfs_trans_handle *trans, struct btrfs_root |
1253 | *root, struct btrfs_path *path, u32 data_size) | 1310 | *root, struct btrfs_path *path, u32 data_size) |
1254 | { | 1311 | { |