[RFC PATCH 07/19] btrfs: add new keys to key root when flushed
From: Mark Harmstone
Date: Tue Jan 08 2019 - 20:29:12 EST
Signed-off-by: Mark Harmstone <mark@xxxxxxxxxxxxx>
---
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