static int copy_one_inline(struct btrfs_root *root, int fd, struct btrfs_path *path, u64 pos) { struct extent_buffer *leaf = path->nodes[0]; struct btrfs_file_extent_item *fi; char buf[4096]; char *outbuf; u64 ram_size; ssize_t done; unsigned long ptr; int ret; int len; int inline_item_len; int compress; fi = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_file_extent_item); ptr = btrfs_file_extent_inline_start(fi); len = btrfs_file_extent_ram_bytes(leaf, fi); inline_item_len = btrfs_file_extent_inline_item_len(leaf, btrfs_item_nr(path->slots[0])); read_extent_buffer(leaf, buf, ptr, inline_item_len); compress = btrfs_file_extent_compression(leaf, fi); if (compress == BTRFS_COMPRESS_NONE) { done = pwrite(fd, buf, len, pos); if (done < len) { fprintf(stderr, "Short inline write, wanted %d, did " "%zd: %d\n", len, done, errno); return -1; } return 0; } ram_size = btrfs_file_extent_ram_bytes(leaf, fi); outbuf = calloc(1, ram_size); if (!outbuf) { error("not enough memory"); return -ENOMEM; } ret = decompress(root, buf, outbuf, inline_item_len, &ram_size, compress); if (ret) { free(outbuf); return ret; } done = pwrite(fd, outbuf, ram_size, pos); free(outbuf); if (done < ram_size) { fprintf(stderr, "Short compressed inline write, wanted %Lu, " "did %zd: %d\n", ram_size, done, errno); return -1; } return 0; }
int btrfs_insert_inline_extent(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 objectid, u64 offset, char *buffer, size_t size) { struct btrfs_key key; struct btrfs_path *path; struct extent_buffer *leaf; unsigned long ptr; struct btrfs_file_extent_item *ei; u32 datasize; int err = 0; int ret; path = btrfs_alloc_path(); if (!path) return -ENOMEM; key.objectid = objectid; key.offset = offset; btrfs_set_key_type(&key, BTRFS_EXTENT_DATA_KEY); datasize = btrfs_file_extent_calc_inline_size(size); ret = btrfs_insert_empty_item(trans, root, path, &key, datasize); if (ret) { err = ret; goto fail; } leaf = path->nodes[0]; ei = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_file_extent_item); btrfs_set_file_extent_generation(leaf, ei, trans->transid); btrfs_set_file_extent_type(leaf, ei, BTRFS_FILE_EXTENT_INLINE); btrfs_set_file_extent_ram_bytes(leaf, ei, size); btrfs_set_file_extent_compression(leaf, ei, 0); btrfs_set_file_extent_encryption(leaf, ei, 0); btrfs_set_file_extent_other_encoding(leaf, ei, 0); ptr = btrfs_file_extent_inline_start(ei) + offset - key.offset; write_extent_buffer(leaf, buffer, ptr, size); btrfs_mark_buffer_dirty(leaf); fail: btrfs_free_path(path); return err; }