diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h index 6ba982ef..8c923be9 100644 --- a/kernel-shared/ctree.h +++ b/kernel-shared/ctree.h @@ -831,6 +831,16 @@ static inline u64 btrfs_dev_stats_value(const struct extent_buffer *eb, return val; } +static inline void btrfs_set_dev_stats_value(struct extent_buffer *eb, + struct btrfs_dev_stats_item *ptr, + int index, u64 val) +{ + write_extent_buffer(eb, &val, + offsetof(struct btrfs_dev_stats_item, values) + + ((unsigned long)ptr) + (index * sizeof(u64)), + sizeof(val)); +} + /* struct btrfs_ioctl_search_header */ static inline u64 btrfs_search_header_transid(struct btrfs_ioctl_search_header *sh) { diff --git a/kernel-shared/volumes.c b/kernel-shared/volumes.c index b21231ef..a0842d58 100644 --- a/kernel-shared/volumes.c +++ b/kernel-shared/volumes.c @@ -1135,6 +1135,7 @@ int btrfs_add_device(struct btrfs_trans_handle *trans, int ret; struct btrfs_path *path; struct btrfs_dev_item *dev_item; + struct btrfs_dev_stats_item *dev_stats; struct extent_buffer *leaf; struct btrfs_key key; struct btrfs_root *root = fs_info->chunk_root; @@ -1149,6 +1150,7 @@ int btrfs_add_device(struct btrfs_trans_handle *trans, if (ret) goto out; + /* Add DEV_ITEM. */ key.objectid = BTRFS_DEV_ITEMS_OBJECTID; key.type = BTRFS_DEV_ITEM_KEY; key.offset = free_devid; @@ -1182,6 +1184,27 @@ int btrfs_add_device(struct btrfs_trans_handle *trans, BTRFS_UUID_SIZE); btrfs_mark_buffer_dirty(leaf); fs_info->fs_devices->total_rw_bytes += device->total_bytes; + + btrfs_release_path(path); + + /* Add DEV STATS item. */ + key.objectid = BTRFS_DEV_STATS_OBJECTID; + key.type = BTRFS_PERSISTENT_ITEM_KEY; + key.offset = free_devid; + + ret = btrfs_insert_empty_item(trans, fs_info->dev_root, path, &key, + sizeof(*dev_stats)); + if (ret) + goto out; + + leaf = path->nodes[0]; + dev_stats = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_dev_stats_item); + + for (int i = 0; i < BTRFS_DEV_STAT_VALUES_MAX; i++) + btrfs_set_dev_stats_value(leaf, dev_stats, i, 0); + + btrfs_mark_buffer_dirty(leaf); + ret = 0; out: diff --git a/mkfs/common.c b/mkfs/common.c index 249e6f3d..bb5a2ad4 100644 --- a/mkfs/common.c +++ b/mkfs/common.c @@ -369,6 +369,7 @@ int make_btrfs(int fd, struct btrfs_mkfs_config *cfg) struct btrfs_chunk *chunk; struct btrfs_dev_item *dev_item; struct btrfs_dev_extent *dev_extent; + struct btrfs_dev_stats_item *dev_stats; enum btrfs_mkfs_block blocks[MKFS_BLOCK_COUNT]; u8 chunk_tree_uuid[BTRFS_UUID_SIZE]; u8 *ptr; @@ -673,8 +674,25 @@ int make_btrfs(int fd, struct btrfs_mkfs_config *cfg) memset(buf->data + sizeof(struct btrfs_header), 0, cfg->nodesize - sizeof(struct btrfs_header)); nritems = 0; - itemoff = cfg->leaf_data_size - sizeof(struct btrfs_dev_extent); + itemoff = cfg->leaf_data_size; + /* Add a DEV_STATS item for device 1. */ + itemoff -= sizeof(struct btrfs_dev_stats_item); + btrfs_set_disk_key_objectid(&disk_key, BTRFS_DEV_STATS_OBJECTID); + btrfs_set_disk_key_type(&disk_key, BTRFS_PERSISTENT_ITEM_KEY); + btrfs_set_disk_key_offset(&disk_key, 1); + btrfs_set_item_key(buf, &disk_key, nritems); + btrfs_set_item_offset(buf, nritems, itemoff); + btrfs_set_item_size(buf, nritems, sizeof(struct btrfs_dev_stats_item)); + dev_stats = btrfs_item_ptr(buf, nritems, struct btrfs_dev_stats_item); + + for (i = 0; i < BTRFS_DEV_STAT_VALUES_MAX; i++) + btrfs_set_dev_stats_value(buf, dev_stats, i, 0); + + nritems++; + + /* Add the DEV_EXTENT item for the system chunk. */ + itemoff -= sizeof(struct btrfs_dev_extent); btrfs_set_disk_key_objectid(&disk_key, 1); btrfs_set_disk_key_offset(&disk_key, system_group_offset); btrfs_set_disk_key_type(&disk_key, BTRFS_DEV_EXTENT_KEY);