Messages in this thread Patch in this message | | | From | Mark Harmstone <> | Subject | [RFC PATCH 07/19] btrfs: add new keys to key root when flushed | Date | Wed, 9 Jan 2019 01:26:49 +0000 |
| |
Signed-off-by: Mark Harmstone <mark@harmstone.com> --- fs/btrfs/transaction.c | 79 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-)
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index d1eeef9ec5da..a6c8d49b6962 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -19,6 +19,7 @@ #include "volumes.h" #include "dev-replace.h" #include "qgroup.h" +#include "encryption.h" #define BTRFS_ROOT_TRANS_TAG 0 @@ -520,7 +521,7 @@ start_transaction(struct btrfs_root *root, unsigned int num_items, * and then we deadlock with somebody doing a freeze. * * If we are ATTACH, it means we just want to catch the current - * transaction and commit it, so we needn't do sb_start_intwrite(). + * transaction and commit it, so we needn't do sb_start_intwrite(). */ if (type & __TRANS_FREEZABLE) sb_start_intwrite(fs_info->sb); @@ -1918,12 +1919,74 @@ btrfs_wait_pending_ordered(struct btrfs_transaction *cur_trans) atomic_read(&cur_trans->pending_ordered) == 0); } +static int flush_key(struct btrfs_trans_handle *trans, + struct btrfs_enc_key *k) +{ + struct btrfs_fs_info *fs_info = trans->fs_info; + struct btrfs_path *path; + struct btrfs_key key; + struct extent_buffer *leaf; + struct btrfs_encryption_key_item *item; + int ret; + + path = btrfs_alloc_path(); + if (!path) + return -ENOMEM; + + path->leave_spinning = 1; + + if (!fs_info->key_root) { + struct btrfs_root *root; + + root = btrfs_create_tree(trans, fs_info, + BTRFS_KEY_TREE_OBJECTID); + + if (IS_ERR(root)) { + btrfs_free_path(path); + return PTR_ERR(root); + } + + fs_info->key_root = root; + + btrfs_set_fs_incompat(fs_info, ENCRYPTION); + } + + key.objectid = k->key_number; + key.type = BTRFS_ENCRYPTION_KEY; + key.offset = 0; + + ret = btrfs_insert_empty_item(trans, fs_info->key_root, path, &key, + sizeof(struct btrfs_encryption_key_item)); + + if (ret) { + btrfs_free_path(path); + return ret; + } + + leaf = path->nodes[0]; + + btrfs_mark_buffer_dirty(leaf); + + item = btrfs_item_ptr(leaf, path->slots[0], + struct btrfs_encryption_key_item); + + write_eb_member(leaf, item, struct btrfs_encryption_key_item, + key_id, k->key_id); + + btrfs_free_path(path); + + k->added = false; + + return ret; +} + int btrfs_commit_transaction(struct btrfs_trans_handle *trans) { struct btrfs_fs_info *fs_info = trans->fs_info; struct btrfs_transaction *cur_trans = trans->transaction; struct btrfs_transaction *prev_trans = NULL; int ret; + struct btrfs_enc_key *key; /* Stop the commit early if ->aborted is set */ if (unlikely(READ_ONCE(cur_trans->aborted))) { @@ -2071,6 +2134,20 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans) ret = cur_trans->aborted; goto scrub_continue; } + + down_read(&fs_info->key_sem); + + list_for_each_entry(key, &fs_info->key_list, key_list) { + if (key->added && key->used) { + ret = flush_key(trans, key); + + if (ret) + goto scrub_continue; + } + } + + up_read(&fs_info->key_sem); + /* * the reloc mutex makes sure that we stop * the balancing code from coming in and moving -- 2.19.2
| |