Re: eCryptfs ablkcipher patch

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Tyler,

The patch below adds the workqueue for write operations.
This patch depends on the ecryptfs ablkcipher support patch rebased to 3.7.

Regards,
Ze'ev

---

>From 606ea815140caa30ff93bdcd998f43d7f95edf61 Mon Sep 17 00:00:00 2001
From: Zeev Zilberman <zeev@xxxxxxxxxxxxxxxxx>
Date: Mon, 17 Dec 2012 17:59:22 +0200
Subject: [PATCH] ecryptfs ablkcipher support - add workqueue

ablkcipher callback may called from tasklet, so it can't sleep.
Using work queue for write operations allows using sleeping functions.

Signed-off-by: Zeev Zilberman <zeev@xxxxxxxxxxxxxxxxx>
---
fs/ecryptfs/crypto.c          |   93
+++++++++++++++++++++++++++++-----------
fs/ecryptfs/ecryptfs_kernel.h |    1 +
2 files changed, 68 insertions(+), 26 deletions(-)

diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index 7f5ff05..27b1702 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -34,6 +34,7 @@
#include <linux/file.h>
#include <linux/scatterlist.h>
#include <linux/slab.h>
+#include <linux/workqueue.h>
#include <asm/unaligned.h>
#include "ecryptfs_kernel.h"
@@ -562,6 +563,53 @@ out:
	}
}
+static struct workqueue_struct *crypto_cmp_write_queue;
+
+/**
+ * ecryptfs_encrypt_extent_write
+ * @work: The extent work structure
+ *
+ * This function is called performs the io operations after
+ * the encryption is completed. It is queued in a workqueue by
+ * ecryptfs_encrypt_extent_done, so it can sleep.
+ */
+static void ecryptfs_encrypt_extent_write(struct work_struct *work)
+{
+	struct ecryptfs_extent_crypt_req *extent_crypt_req = container_of(
+			work, struct ecryptfs_extent_crypt_req, work);
+	struct ecryptfs_page_crypt_req *page_crypt_req =
+				extent_crypt_req->page_crypt_req;
+	char *enc_extent_virt = NULL;
+	struct page *page = page_crypt_req->page;
+	struct page *enc_extent_page = extent_crypt_req->enc_extent_page;
+	loff_t offset;
+	int rc = 0;
+
+	enc_extent_virt = kmap(enc_extent_page);
+	ecryptfs_lower_offset_for_extent(
+		&offset,
+		((((loff_t)page->index)
+		  * (PAGE_CACHE_SIZE
+		     / extent_crypt_req->crypt_stat->extent_size))
+		    + extent_crypt_req->extent_offset),
+		extent_crypt_req->crypt_stat);
+	rc = ecryptfs_write_lower(extent_crypt_req->inode, enc_extent_virt,
+				  offset,
+				  extent_crypt_req->crypt_stat->extent_size);
+	if (rc < 0) {
+		atomic_set(&page_crypt_req->rc, rc);
+		ecryptfs_printk(KERN_ERR, "Error attempting "
+				"to write lower page; rc = [%d]"
+				"\n", rc);
+		goto out;
+	}
+out:
+	if (enc_extent_virt)
+		kunmap(enc_extent_page);
+	__free_page(enc_extent_page);
+	ecryptfs_free_extent_crypt_req(extent_crypt_req);
+}
+
/**
  * ecryptfs_encrypt_extent_done
  * @req: The original extent encrypt request
@@ -576,14 +624,11 @@ static void ecryptfs_encrypt_extent_done(
	struct ecryptfs_extent_crypt_req *extent_crypt_req = req->data;
	struct ecryptfs_page_crypt_req *page_crypt_req =
				extent_crypt_req->page_crypt_req;
-	char *enc_extent_virt = NULL;
	struct page *page = page_crypt_req->page;
	struct page *enc_extent_page = extent_crypt_req->enc_extent_page;
	struct ecryptfs_crypt_stat *crypt_stat = extent_crypt_req->crypt_stat;
	loff_t extent_base;
	unsigned long extent_offset = extent_crypt_req->extent_offset;
-	loff_t offset;
-	int rc = 0;
	if (!err && unlikely(ecryptfs_verbosity > 0)) {
		extent_base = (((loff_t)page->index)
@@ -600,32 +645,14 @@ static void ecryptfs_encrypt_extent_done(
		atomic_set(&page_crypt_req->rc, err);
		printk(KERN_ERR "%s: Error encrypting extent; "
		       "rc = [%d]\n", __func__, err);
+		__free_page(enc_extent_page);
+		ecryptfs_free_extent_crypt_req(extent_crypt_req);
		goto out;
	}
-
-	enc_extent_virt = kmap(enc_extent_page);
-	ecryptfs_lower_offset_for_extent(
-		&offset,
-		((((loff_t)page->index)
-		  * (PAGE_CACHE_SIZE
-		     / extent_crypt_req->crypt_stat->extent_size))
-		    + extent_crypt_req->extent_offset),
-		extent_crypt_req->crypt_stat);
-	rc = ecryptfs_write_lower(extent_crypt_req->inode, enc_extent_virt,
-				  offset,
-				  extent_crypt_req->crypt_stat->extent_size);
-	if (rc < 0) {
-		atomic_set(&page_crypt_req->rc, rc);
-		ecryptfs_printk(KERN_ERR, "Error attempting "
-				"to write lower page; rc = [%d]"
-				"\n", rc);
-		goto out;
-	}
+	INIT_WORK(&extent_crypt_req->work, ecryptfs_encrypt_extent_write);
+	queue_work(crypto_cmp_write_queue, &extent_crypt_req->work);
out:
-	if (enc_extent_virt)
-		kunmap(enc_extent_page);
-	__free_page(enc_extent_page);
-	ecryptfs_free_extent_crypt_req(extent_crypt_req);
+	return;
}
/**
@@ -2124,6 +2151,17 @@ int __init ecryptfs_init_crypto(void)
{
	mutex_init(&key_tfm_list_mutex);
	INIT_LIST_HEAD(&key_tfm_list);
+
+	crypto_cmp_write_queue = alloc_workqueue("ecryptfs_cmp_write",
+				       WQ_NON_REENTRANT|
+				       WQ_MEM_RECLAIM,
+				       1);
+	if (!crypto_cmp_write_queue) {
+		printk(KERN_ERR "%s: failed to alloc crypto write workqueue\n",
+				__func__);
+		return -ENOMEM;
+	}
+
	return 0;
}
@@ -2136,6 +2174,9 @@ int ecryptfs_destroy_crypto(void)
{
	struct ecryptfs_key_tfm *key_tfm, *key_tfm_tmp;
+	if (crypto_cmp_write_queue)
+		destroy_workqueue(crypto_cmp_write_queue);
+
	mutex_lock(&key_tfm_list_mutex);
	list_for_each_entry_safe(key_tfm, key_tfm_tmp, &key_tfm_list,
				 key_tfm_list) {
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index 5af953f..7d4dafd 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -571,6 +571,7 @@ struct ecryptfs_extent_crypt_req {
	unsigned long extent_offset;
	struct scatterlist src_sg;
	struct scatterlist dst_sg;
+	struct work_struct work;
};
struct inode *ecryptfs_get_inode(struct inode *lower_inode,
--
1.7.0.4



--
To unsubscribe from this list: send the line "unsubscribe ecryptfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Crypto]     [Device Mapper Crypto]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux