2007-01-18 21:26:31

by Michael Halcrow

[permalink] [raw]
Subject: [PATCH 1/5] eCryptfs: convert f_op->write() to vfs_write()

Andrew Morton wrote:
> On Tue, 9 Jan 2007 16:22:55 -0600
> Michael Halcrow <[email protected]> wrote:
>
> > + lower_file->f_op->write(lower_file, (char __user *)page_virt,
> > + PAGE_CACHE_SIZE, &lower_file->f_pos);
>
> hm. sys_write() takes a local copy of f_pos and writes that back
> into the struct file.It does this so that two concurrent write()
> callers don't make a mess of f_pos, and of the file contents.
>
> Perhaps ecryptfs should be calling vfs_write()?
>
> That way we'd also get the fsnotify notifications, which ecryptfs
> presently appears to have subverted.

Convert direct calls to f_op->write() into calls to vfs_write().

Signed-off-by: Michael Halcrow <[email protected]>

---

fs/ecryptfs/crypto.c | 27 ++++++++++++++++++++++-----
fs/ecryptfs/inode.c | 2 +-
2 files changed, 23 insertions(+), 6 deletions(-)

b91d05b02335e38e18ffb87de6127b80bfe66dd7
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index 8fbc38c..fbb62c8 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -1346,24 +1346,41 @@ int ecryptfs_write_metadata_to_contents(
mm_segment_t oldfs;
int current_header_page;
int header_pages;
+ ssize_t size;
+ int rc = 0;

lower_file->f_pos = 0;
oldfs = get_fs();
set_fs(get_ds());
- lower_file->f_op->write(lower_file, (char __user *)page_virt,
- PAGE_CACHE_SIZE, &lower_file->f_pos);
+ size = vfs_write(lower_file, (char __user *)page_virt, PAGE_CACHE_SIZE,
+ &lower_file->f_pos);
+ if (size < 0) {
+ rc = (int)size;
+ printk(KERN_ERR "Error attempting to write lower page; "
+ "rc = [%d]\n", rc);
+ set_fs(oldfs);
+ goto out;
+ }
header_pages = ((crypt_stat->header_extent_size
* crypt_stat->num_header_extents_at_front)
/ PAGE_CACHE_SIZE);
memset(page_virt, 0, PAGE_CACHE_SIZE);
current_header_page = 1;
while (current_header_page < header_pages) {
- lower_file->f_op->write(lower_file, (char __user *)page_virt,
- PAGE_CACHE_SIZE, &lower_file->f_pos);
+ size = vfs_write(lower_file, (char __user *)page_virt,
+ PAGE_CACHE_SIZE, &lower_file->f_pos);
+ if (size < 0) {
+ rc = (int)size;
+ printk(KERN_ERR "Error attempting to write lower page; "
+ "rc = [%d]\n", rc);
+ set_fs(oldfs);
+ goto out;
+ }
current_header_page++;
}
set_fs(oldfs);
- return 0;
+out:
+ return rc;
}

int ecryptfs_write_metadata_to_xattr(struct dentry *ecryptfs_dentry,
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index bbc1b4f..7d33917 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -201,7 +201,7 @@ static int ecryptfs_initialize_file(stru
lower_dentry->d_name.name);
inode = ecryptfs_dentry->d_inode;
crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
- lower_flags = ((O_CREAT | O_WRONLY | O_TRUNC) & O_ACCMODE) | O_RDWR;
+ lower_flags = ((O_CREAT | O_TRUNC) & O_ACCMODE) | O_RDWR;
#if BITS_PER_LONG != 32
lower_flags |= O_LARGEFILE;
#endif
--
1.3.3


2007-01-18 21:27:29

by Michael Halcrow

[permalink] [raw]
Subject: [PATCH 2/5] eCryptfs: convert kmap() to kmap_atomic()

On Tue, Jan 09, 2007 at 02:42:03PM -0800, Andrew Morton wrote:
> On Tue, 9 Jan 2007 16:23:37 -0600
> Michael Halcrow <[email protected]> wrote:
>
> > + page_virt = (char *)kmap(page);
>
> Do we _have_ to use kmap here? It's slow and theoretically
> deadlocky. kmap_atomic() is much preferred.
>
> Can the other kmap() calls in ecryptfs be converted?

Replace kmap() with kmap_atomic(). Reduce the number of kmaps and the
amount of time that kmaps are held.

Signed-off-by: Michael Halcrow <[email protected]>
Signed-off-by: Trevor Highland <[email protected]>

---

fs/ecryptfs/crypto.c | 8 +--
fs/ecryptfs/ecryptfs_kernel.h | 4 -
fs/ecryptfs/mmap.c | 121 ++++++++++++-----------------------------
3 files changed, 39 insertions(+), 94 deletions(-)

fd04da707b2164272acc05a56ff4b71786aad011
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index fbb62c8..ac4ea8d 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -429,10 +429,10 @@ static int ecryptfs_read_in_page(struct
goto out;
}
} else {
- rc = ecryptfs_grab_and_map_lower_page(lower_page, NULL,
- lower_inode,
- lower_page_idx);
- if (rc) {
+ *lower_page = grab_cache_page(lower_inode->i_mapping,
+ lower_page_idx);
+ if (!(*lower_page)) {
+ rc = -EINVAL;
ecryptfs_printk(
KERN_ERR, "Error attempting to grab and map "
"lower page with index [0x%.16x]; rc = [%d]\n",
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index 859d31b..0e38d0d 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -527,10 +527,6 @@ int ecryptfs_copy_page_to_lower(struct p
struct file *lower_file);
int ecryptfs_do_readpage(struct file *file, struct page *page,
pgoff_t lower_page_index);
-int ecryptfs_grab_and_map_lower_page(struct page **lower_page,
- char **lower_virt,
- struct inode *lower_inode,
- unsigned long lower_page_index);
int ecryptfs_writepage_and_release_lower_page(struct page *lower_page,
struct inode *lower_inode,
struct writeback_control *wbc);
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index 94bcabf..6f167f1 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -234,22 +234,11 @@ int ecryptfs_do_readpage(struct file *fi
goto out;
}
wait_on_page_locked(lower_page);
- page_data = (char *)kmap(page);
- if (!page_data) {
- rc = -ENOMEM;
- ecryptfs_printk(KERN_ERR, "Error mapping page\n");
- goto out;
- }
- lower_page_data = (char *)kmap(lower_page);
- if (!lower_page_data) {
- rc = -ENOMEM;
- ecryptfs_printk(KERN_ERR, "Error mapping page\n");
- kunmap(page);
- goto out;
- }
+ page_data = (char *)kmap_atomic(page, KM_USER0);
+ lower_page_data = (char *)kmap_atomic(lower_page, KM_USER1);
memcpy(page_data, lower_page_data, PAGE_CACHE_SIZE);
- kunmap(lower_page);
- kunmap(page);
+ kunmap_atomic(lower_page_data, KM_USER1);
+ kunmap_atomic(page_data, KM_USER0);
rc = 0;
out:
if (likely(lower_page))
@@ -325,19 +314,14 @@ static int ecryptfs_readpage(struct file
if (page->index < num_pages_in_header_region) {
char *page_virt;

- page_virt = (char *)kmap(page);
- if (!page_virt) {
- rc = -ENOMEM;
- printk(KERN_ERR "Error mapping page\n");
- goto out;
- }
+ page_virt = (char *)kmap_atomic(page, KM_USER0);
memset(page_virt, 0, PAGE_CACHE_SIZE);
if (page->index == 0) {
rc = ecryptfs_read_xattr_region(
page_virt, file->f_path.dentry);
set_header_info(page_virt, crypt_stat);
}
- kunmap(page);
+ kunmap_atomic(page_virt, KM_USER0);
if (rc) {
printk(KERN_ERR "Error reading xattr "
"region\n");
@@ -387,26 +371,19 @@ static int fill_zeros_to_end_of_page(str
{
struct inode *inode = page->mapping->host;
int end_byte_in_page;
- int rc = 0;
char *page_virt;

- if ((i_size_read(inode) / PAGE_CACHE_SIZE) == page->index) {
- end_byte_in_page = i_size_read(inode) % PAGE_CACHE_SIZE;
- if (to > end_byte_in_page)
- end_byte_in_page = to;
- page_virt = kmap(page);
- if (!page_virt) {
- rc = -ENOMEM;
- ecryptfs_printk(KERN_WARNING,
- "Could not map page\n");
- goto out;
- }
- memset((page_virt + end_byte_in_page), 0,
- (PAGE_CACHE_SIZE - end_byte_in_page));
- kunmap(page);
- }
+ if ((i_size_read(inode) / PAGE_CACHE_SIZE) != page->index)
+ goto out;
+ end_byte_in_page = i_size_read(inode) % PAGE_CACHE_SIZE;
+ if (to > end_byte_in_page)
+ end_byte_in_page = to;
+ page_virt = kmap_atomic(page, KM_USER0);
+ memset((page_virt + end_byte_in_page), 0,
+ (PAGE_CACHE_SIZE - end_byte_in_page));
+ kunmap_atomic(page_virt, KM_USER0);
out:
- return rc;
+ return 0;
}

static int ecryptfs_prepare_write(struct file *file, struct page *page,
@@ -414,7 +391,6 @@ static int ecryptfs_prepare_write(struct
{
int rc = 0;

- kmap(page);
if (from == 0 && to == PAGE_CACHE_SIZE)
goto out; /* If we are writing a full page, it will be
up to date. */
@@ -424,30 +400,6 @@ out:
return rc;
}

-int ecryptfs_grab_and_map_lower_page(struct page **lower_page,
- char **lower_virt,
- struct inode *lower_inode,
- unsigned long lower_page_index)
-{
- int rc = 0;
-
- (*lower_page) = grab_cache_page(lower_inode->i_mapping,
- lower_page_index);
- if (!(*lower_page)) {
- ecryptfs_printk(KERN_ERR, "grab_cache_page for "
- "lower_page_index = [0x%.16x] failed\n",
- lower_page_index);
- rc = -EINVAL;
- goto out;
- }
- if (lower_virt)
- (*lower_virt) = kmap((*lower_page));
- else
- kmap((*lower_page));
-out:
- return rc;
-}
-
int ecryptfs_writepage_and_release_lower_page(struct page *lower_page,
struct inode *lower_inode,
struct writeback_control *wbc)
@@ -466,11 +418,8 @@ out:
return rc;
}

-static void ecryptfs_unmap_and_release_lower_page(struct page *lower_page)
+static void ecryptfs_release_lower_page(struct page *lower_page)
{
- kunmap(lower_page);
- ecryptfs_printk(KERN_DEBUG, "Unlocking lower page with index = "
- "[0x%.16x]\n", lower_page->index);
unlock_page(lower_page);
page_cache_release(lower_page);
}
@@ -492,11 +441,11 @@ static int ecryptfs_write_inode_size_to_
const struct address_space_operations *lower_a_ops;
u64 file_size;

- rc = ecryptfs_grab_and_map_lower_page(&header_page, &header_virt,
- lower_inode, 0);
- if (rc) {
- ecryptfs_printk(KERN_ERR, "grab_cache_page for header page "
- "failed\n");
+ header_page = grab_cache_page(lower_inode->i_mapping, 0);
+ if (!header_page) {
+ ecryptfs_printk(KERN_ERR, "grab_cache_page for "
+ "lower_page_index 0 failed\n");
+ rc = -EINVAL;
goto out;
}
lower_a_ops = lower_inode->i_mapping->a_ops;
@@ -504,12 +453,14 @@ static int ecryptfs_write_inode_size_to_
file_size = (u64)i_size_read(inode);
ecryptfs_printk(KERN_DEBUG, "Writing size: [0x%.16x]\n", file_size);
file_size = cpu_to_be64(file_size);
+ header_virt = kmap_atomic(header_page, KM_USER0);
memcpy(header_virt, &file_size, sizeof(u64));
+ kunmap_atomic(header_virt, KM_USER0);
rc = lower_a_ops->commit_write(lower_file, header_page, 0, 8);
if (rc < 0)
ecryptfs_printk(KERN_ERR, "Error commiting header page "
"write\n");
- ecryptfs_unmap_and_release_lower_page(header_page);
+ ecryptfs_release_lower_page(header_page);
lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME;
mark_inode_dirty_sync(inode);
out:
@@ -597,10 +548,10 @@ int ecryptfs_get_lower_page(struct page
{
int rc = 0;

- rc = ecryptfs_grab_and_map_lower_page(lower_page, NULL, lower_inode,
- lower_page_index);
- if (rc) {
- ecryptfs_printk(KERN_ERR, "Error attempting to grab and map "
+ *lower_page = grab_cache_page(lower_inode->i_mapping, lower_page_index);
+ if (!(*lower_page)) {
+ rc = -EINVAL;
+ ecryptfs_printk(KERN_ERR, "Error attempting to grab "
"lower page with index [0x%.16x]\n",
lower_page_index);
goto out;
@@ -616,7 +567,7 @@ int ecryptfs_get_lower_page(struct page
}
out:
if (rc && (*lower_page)) {
- ecryptfs_unmap_and_release_lower_page(*lower_page);
+ ecryptfs_release_lower_page(*lower_page);
(*lower_page) = NULL;
}
return rc;
@@ -641,7 +592,7 @@ ecryptfs_commit_lower_page(struct page *
"Error committing write; rc = [%d]\n", rc);
} else
rc = 0;
- ecryptfs_unmap_and_release_lower_page(lower_page);
+ ecryptfs_release_lower_page(lower_page);
return rc;
}

@@ -747,7 +698,6 @@ static int ecryptfs_commit_write(struct
lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME;
mark_inode_dirty_sync(inode);
out:
- kunmap(page); /* mapped in prior call (prepare_write) */
if (rc < 0)
ClearPageUptodate(page);
else
@@ -772,6 +722,7 @@ int write_zeros(struct file *file, pgoff
{
int rc = 0;
struct page *tmp_page;
+ char *tmp_page_virt;

tmp_page = ecryptfs_get1page(file, index);
if (IS_ERR(tmp_page)) {
@@ -780,28 +731,26 @@ int write_zeros(struct file *file, pgoff
rc = PTR_ERR(tmp_page);
goto out;
}
- kmap(tmp_page);
rc = ecryptfs_prepare_write(file, tmp_page, start, start + num_zeros);
if (rc) {
ecryptfs_printk(KERN_ERR, "Error preparing to write zero's "
"to remainder of page at index [0x%.16x]\n",
index);
- kunmap(tmp_page);
page_cache_release(tmp_page);
goto out;
}
- memset(((char *)page_address(tmp_page) + start), 0, num_zeros);
+ tmp_page_virt = kmap_atomic(tmp_page, KM_USER0);
+ memset(((char *)tmp_page_virt + start), 0, num_zeros);
+ kunmap_atomic(tmp_page_virt, KM_USER0);
rc = ecryptfs_commit_write(file, tmp_page, start, start + num_zeros);
if (rc < 0) {
ecryptfs_printk(KERN_ERR, "Error attempting to write zero's "
"to remainder of page at index [0x%.16x]\n",
index);
- kunmap(tmp_page);
page_cache_release(tmp_page);
goto out;
}
rc = 0;
- kunmap(tmp_page);
page_cache_release(tmp_page);
out:
return rc;
--
1.3.3

2007-01-18 21:28:10

by Michael Halcrow

[permalink] [raw]
Subject: [PATCH 3/5] eCryptfs: open-code flag checking and manipulation

Open-code flag checking and manipulation.

Signed-off-by: Michael Halcrow <[email protected]>
Signed-off-by: Trevor Highland <[email protected]>

---

fs/ecryptfs/crypto.c | 37 +++++++++++++++----------------------
fs/ecryptfs/debug.c | 6 +++---
fs/ecryptfs/ecryptfs_kernel.h | 3 ---
fs/ecryptfs/file.c | 17 +++++++----------
fs/ecryptfs/inode.c | 14 ++++++--------
fs/ecryptfs/keystore.c | 32 ++++++++++++++------------------
fs/ecryptfs/mmap.c | 8 ++++----
7 files changed, 49 insertions(+), 68 deletions(-)

3cb9652018a1be5ae400bb9bb105bb5685fbc302
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index ac4ea8d..e03113c 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -207,7 +207,7 @@ ecryptfs_init_crypt_stat(struct ecryptfs
mutex_init(&crypt_stat->cs_mutex);
mutex_init(&crypt_stat->cs_tfm_mutex);
mutex_init(&crypt_stat->cs_hash_tfm_mutex);
- ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_STRUCT_INITIALIZED);
+ crypt_stat->flags |= ECRYPTFS_STRUCT_INITIALIZED;
}

/**
@@ -305,8 +305,7 @@ static int encrypt_scatterlist(struct ec
int rc = 0;

BUG_ON(!crypt_stat || !crypt_stat->tfm
- || !ECRYPTFS_CHECK_FLAG(crypt_stat->flags,
- ECRYPTFS_STRUCT_INITIALIZED));
+ || !(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED));
if (unlikely(ecryptfs_verbosity > 0)) {
ecryptfs_printk(KERN_DEBUG, "Key size [%d]; key:\n",
crypt_stat->key_size);
@@ -485,7 +484,7 @@ #define ECRYPTFS_PAGE_STATE_WRITTEN 3
lower_inode = ecryptfs_inode_to_lower(ctx->page->mapping->host);
inode_info = ecryptfs_inode_to_private(ctx->page->mapping->host);
crypt_stat = &inode_info->crypt_stat;
- if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED)) {
+ if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
rc = ecryptfs_copy_page_to_lower(ctx->page, lower_inode,
ctx->param.lower_file);
if (rc)
@@ -617,7 +616,7 @@ int ecryptfs_decrypt_page(struct file *f
crypt_stat = &(ecryptfs_inode_to_private(
page->mapping->host)->crypt_stat);
lower_inode = ecryptfs_inode_to_lower(page->mapping->host);
- if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED)) {
+ if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
rc = ecryptfs_do_readpage(file, page, page->index);
if (rc)
ecryptfs_printk(KERN_ERR, "Error attempting to copy "
@@ -884,7 +883,7 @@ int ecryptfs_compute_root_iv(struct ecry

BUG_ON(crypt_stat->iv_bytes > MD5_DIGEST_SIZE);
BUG_ON(crypt_stat->iv_bytes <= 0);
- if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_KEY_VALID)) {
+ if (!(crypt_stat->flags & ECRYPTFS_KEY_VALID)) {
rc = -EINVAL;
ecryptfs_printk(KERN_WARNING, "Session key not valid; "
"cannot generate root IV\n");
@@ -901,8 +900,7 @@ int ecryptfs_compute_root_iv(struct ecry
out:
if (rc) {
memset(crypt_stat->root_iv, 0, crypt_stat->iv_bytes);
- ECRYPTFS_SET_FLAG(crypt_stat->flags,
- ECRYPTFS_SECURITY_WARNING);
+ crypt_stat->flags |= ECRYPTFS_SECURITY_WARNING;
}
return rc;
}
@@ -910,7 +908,7 @@ out:
static void ecryptfs_generate_new_key(struct ecryptfs_crypt_stat *crypt_stat)
{
get_random_bytes(crypt_stat->key, crypt_stat->key_size);
- ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_KEY_VALID);
+ crypt_stat->flags |= ECRYPTFS_KEY_VALID;
ecryptfs_compute_root_iv(crypt_stat);
if (unlikely(ecryptfs_verbosity > 0)) {
ecryptfs_printk(KERN_DEBUG, "Generated new session key:\n");
@@ -950,7 +948,7 @@ static void ecryptfs_set_default_crypt_s
ecryptfs_set_default_sizes(crypt_stat);
strcpy(crypt_stat->cipher, ECRYPTFS_DEFAULT_CIPHER);
crypt_stat->key_size = ECRYPTFS_DEFAULT_KEY_BYTES;
- ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, ECRYPTFS_KEY_VALID);
+ crypt_stat->flags &= ~(ECRYPTFS_KEY_VALID);
crypt_stat->file_version = ECRYPTFS_FILE_VERSION;
crypt_stat->mount_crypt_stat = mount_crypt_stat;
}
@@ -990,8 +988,8 @@ int ecryptfs_new_file_context(struct den
if (mount_crypt_stat->global_auth_tok) {
ecryptfs_printk(KERN_DEBUG, "Initializing context for new "
"file using mount_crypt_stat\n");
- ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED);
- ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_KEY_VALID);
+ crypt_stat->flags |= ECRYPTFS_ENCRYPTED;
+ crypt_stat->flags |= ECRYPTFS_KEY_VALID;
ecryptfs_copy_mount_wide_flags_to_inode_flags(crypt_stat,
mount_crypt_stat);
memcpy(crypt_stat->keysigs[crypt_stat->num_keysigs++],
@@ -1076,11 +1074,9 @@ static int ecryptfs_process_flags(struct
for (i = 0; i < ((sizeof(ecryptfs_flag_map)
/ sizeof(struct ecryptfs_flag_map_elem))); i++)
if (flags & ecryptfs_flag_map[i].file_flag) {
- ECRYPTFS_SET_FLAG(crypt_stat->flags,
- ecryptfs_flag_map[i].local_flag);
+ crypt_stat->flags |= ecryptfs_flag_map[i].local_flag;
} else
- ECRYPTFS_CLEAR_FLAG(crypt_stat->flags,
- ecryptfs_flag_map[i].local_flag);
+ crypt_stat->flags &= ~(ecryptfs_flag_map[i].local_flag);
/* Version is in top 8 bits of the 32-bit flag vector */
crypt_stat->file_version = ((flags >> 24) & 0xFF);
(*bytes_read) = 4;
@@ -1117,8 +1113,7 @@ write_ecryptfs_flags(char *page_virt, st

for (i = 0; i < ((sizeof(ecryptfs_flag_map)
/ sizeof(struct ecryptfs_flag_map_elem))); i++)
- if (ECRYPTFS_CHECK_FLAG(crypt_stat->flags,
- ecryptfs_flag_map[i].local_flag))
+ if (crypt_stat->flags & ecryptfs_flag_map[i].local_flag)
flags |= ecryptfs_flag_map[i].file_flag;
/* Version is in top 8 bits of the 32-bit flag vector */
flags |= ((((u8)crypt_stat->file_version) << 24) & 0xFF000000);
@@ -1416,10 +1411,8 @@ int ecryptfs_write_metadata(struct dentr

crypt_stat = &ecryptfs_inode_to_private(
ecryptfs_dentry->d_inode)->crypt_stat;
- if (likely(ECRYPTFS_CHECK_FLAG(crypt_stat->flags,
- ECRYPTFS_ENCRYPTED))) {
- if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags,
- ECRYPTFS_KEY_VALID)) {
+ if (likely(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
+ if (!(crypt_stat->flags & ECRYPTFS_KEY_VALID)) {
ecryptfs_printk(KERN_DEBUG, "Key is "
"invalid; bailing out\n");
rc = -EINVAL;
diff --git a/fs/ecryptfs/debug.c b/fs/ecryptfs/debug.c
index 61f8e89..434c7ef 100644
--- a/fs/ecryptfs/debug.c
+++ b/fs/ecryptfs/debug.c
@@ -36,7 +36,7 @@ void ecryptfs_dump_auth_tok(struct ecryp

ecryptfs_printk(KERN_DEBUG, "Auth tok at mem loc [%p]:\n",
auth_tok);
- if (ECRYPTFS_CHECK_FLAG(auth_tok->flags, ECRYPTFS_PRIVATE_KEY)) {
+ if (auth_tok->flags & ECRYPTFS_PRIVATE_KEY) {
ecryptfs_printk(KERN_DEBUG, " * private key type\n");
ecryptfs_printk(KERN_DEBUG, " * (NO PRIVATE KEY SUPPORT "
"IN ECRYPTFS VERSION 0.1)\n");
@@ -46,8 +46,8 @@ void ecryptfs_dump_auth_tok(struct ecryp
ECRYPTFS_SALT_SIZE);
salt[ECRYPTFS_SALT_SIZE * 2] = '\0';
ecryptfs_printk(KERN_DEBUG, " * salt = [%s]\n", salt);
- if (ECRYPTFS_CHECK_FLAG(auth_tok->token.password.flags,
- ECRYPTFS_PERSISTENT_PASSWORD)) {
+ if (auth_tok->token.password.flags &
+ ECRYPTFS_PERSISTENT_PASSWORD) {
ecryptfs_printk(KERN_DEBUG, " * persistent\n");
}
memcpy(sig, auth_tok->token.password.signature,
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index 0e38d0d..046f0c3 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -94,9 +94,6 @@ #define RFC2440_CIPHER_AES_256 0x09
#define RFC2440_CIPHER_TWOFISH 0x0a
#define RFC2440_CIPHER_CAST_6 0x0b

-#define ECRYPTFS_SET_FLAG(flag_bit_vector, flag) (flag_bit_vector |= (flag))
-#define ECRYPTFS_CLEAR_FLAG(flag_bit_vector, flag) (flag_bit_vector &= ~(flag))
-#define ECRYPTFS_CHECK_FLAG(flag_bit_vector, flag) (flag_bit_vector & (flag))
#define RFC2440_CIPHER_RSA 0x01

/**
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index 652ed77..bd969ad 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -273,11 +273,11 @@ static int ecryptfs_open(struct inode *i
lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
mutex_lock(&crypt_stat->cs_mutex);
- if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_POLICY_APPLIED)) {
+ if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED)) {
ecryptfs_printk(KERN_DEBUG, "Setting flags for stat...\n");
/* Policy code enabled in future release */
- ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_POLICY_APPLIED);
- ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED);
+ crypt_stat->flags |= ECRYPTFS_POLICY_APPLIED;
+ crypt_stat->flags |= ECRYPTFS_ENCRYPTED;
}
mutex_unlock(&crypt_stat->cs_mutex);
lower_flags = file->f_flags;
@@ -297,15 +297,13 @@ static int ecryptfs_open(struct inode *i
lower_inode = lower_dentry->d_inode;
if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) {
ecryptfs_printk(KERN_DEBUG, "This is a directory\n");
- ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED);
+ crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
rc = 0;
goto out;
}
mutex_lock(&crypt_stat->cs_mutex);
- if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags,
- ECRYPTFS_POLICY_APPLIED)
- || !ECRYPTFS_CHECK_FLAG(crypt_stat->flags,
- ECRYPTFS_KEY_VALID)) {
+ if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED)
+ || !(crypt_stat->flags & ECRYPTFS_KEY_VALID)) {
rc = ecryptfs_read_metadata(ecryptfs_dentry, lower_file);
if (rc) {
ecryptfs_printk(KERN_DEBUG,
@@ -320,9 +318,8 @@ static int ecryptfs_open(struct inode *i
mutex_unlock(&crypt_stat->cs_mutex);
goto out_puts;
}
- ECRYPTFS_CLEAR_FLAG(crypt_stat->flags,
- ECRYPTFS_ENCRYPTED);
rc = 0;
+ crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
mutex_unlock(&crypt_stat->cs_mutex);
goto out;
}
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 7d33917..9135718 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -161,9 +161,8 @@ static int grow_file(struct dentry *ecry
ecryptfs_set_file_lower(&fake_file, lower_file);
rc = ecryptfs_fill_zeros(&fake_file, 1);
if (rc) {
- ECRYPTFS_SET_FLAG(
- ecryptfs_inode_to_private(inode)->crypt_stat.flags,
- ECRYPTFS_SECURITY_WARNING);
+ ecryptfs_inode_to_private(inode)->crypt_stat.flags |=
+ ECRYPTFS_SECURITY_WARNING;
ecryptfs_printk(KERN_WARNING, "Error attempting to fill zeros "
"in file; rc = [%d]\n", rc);
goto out;
@@ -172,8 +171,7 @@ static int grow_file(struct dentry *ecry
ecryptfs_write_inode_size_to_metadata(lower_file, lower_inode, inode,
ecryptfs_dentry,
ECRYPTFS_LOWER_I_MUTEX_NOT_HELD);
- ECRYPTFS_SET_FLAG(ecryptfs_inode_to_private(inode)->crypt_stat.flags,
- ECRYPTFS_NEW_FILE);
+ ecryptfs_inode_to_private(inode)->crypt_stat.flags |= ECRYPTFS_NEW_FILE;
out:
return rc;
}
@@ -216,10 +214,10 @@ #endif
lower_inode = lower_dentry->d_inode;
if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) {
ecryptfs_printk(KERN_DEBUG, "This is a directory\n");
- ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED);
+ crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
goto out_fput;
}
- ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_NEW_FILE);
+ crypt_stat->flags |= ECRYPTFS_NEW_FILE;
ecryptfs_printk(KERN_DEBUG, "Initializing crypto context\n");
rc = ecryptfs_new_file_context(ecryptfs_dentry);
if (rc) {
@@ -373,7 +371,7 @@ static struct dentry *ecryptfs_lookup(st
goto out_dput;
}
crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat;
- if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_POLICY_APPLIED))
+ if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED))
ecryptfs_set_default_sizes(crypt_stat);
rc = ecryptfs_read_and_validate_header_region(page_virt, lower_dentry,
nd->mnt);
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c
index cd9c091..81156e9 100644
--- a/fs/ecryptfs/keystore.c
+++ b/fs/ecryptfs/keystore.c
@@ -606,13 +606,13 @@ parse_tag_1_packet(struct ecryptfs_crypt
(*new_auth_tok)->session_key.flags |=
ECRYPTFS_CONTAINS_ENCRYPTED_KEY;
(*new_auth_tok)->token_type = ECRYPTFS_PRIVATE_KEY;
- ECRYPTFS_SET_FLAG((*new_auth_tok)->flags, ECRYPTFS_PRIVATE_KEY);
+ (*new_auth_tok)->flags |= ECRYPTFS_PRIVATE_KEY;
/* TODO: Why are we setting this flag here? Don't we want the
* userspace to decrypt the session key? */
- ECRYPTFS_CLEAR_FLAG((*new_auth_tok)->session_key.flags,
- ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT);
- ECRYPTFS_CLEAR_FLAG((*new_auth_tok)->session_key.flags,
- ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT);
+ (*new_auth_tok)->session_key.flags &=
+ ~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT);
+ (*new_auth_tok)->session_key.flags &=
+ ~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT);
list_add(&auth_tok_list_item->list, auth_tok_list);
goto out;
out_free:
@@ -792,10 +792,10 @@ parse_tag_3_packet(struct ecryptfs_crypt
(*new_auth_tok)->token_type = ECRYPTFS_PASSWORD;
/* TODO: Parametarize; we might actually want userspace to
* decrypt the session key. */
- ECRYPTFS_CLEAR_FLAG((*new_auth_tok)->session_key.flags,
- ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT);
- ECRYPTFS_CLEAR_FLAG((*new_auth_tok)->session_key.flags,
- ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT);
+ (*new_auth_tok)->session_key.flags &=
+ ~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT);
+ (*new_auth_tok)->session_key.flags &=
+ ~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT);
list_add(&auth_tok_list_item->list, auth_tok_list);
goto out;
out_free:
@@ -940,8 +940,7 @@ static int decrypt_session_key(struct ec
int rc = 0;

password_s_ptr = &auth_tok->token.password;
- if (ECRYPTFS_CHECK_FLAG(password_s_ptr->flags,
- ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET))
+ if (password_s_ptr->flags & ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET)
ecryptfs_printk(KERN_DEBUG, "Session key encryption key "
"set; skipping key generation\n");
ecryptfs_printk(KERN_DEBUG, "Session key encryption key (size [%d])"
@@ -1023,7 +1022,7 @@ static int decrypt_session_key(struct ec
auth_tok->session_key.flags |= ECRYPTFS_CONTAINS_DECRYPTED_KEY;
memcpy(crypt_stat->key, auth_tok->session_key.decrypted_key,
auth_tok->session_key.decrypted_key_size);
- ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_KEY_VALID);
+ crypt_stat->flags |= ECRYPTFS_KEY_VALID;
ecryptfs_printk(KERN_DEBUG, "Decrypted session key:\n");
if (ecryptfs_verbosity > 0)
ecryptfs_dump_hex(crypt_stat->key,
@@ -1126,8 +1125,7 @@ int ecryptfs_parse_packet_set(struct ecr
sig_tmp_space, tag_11_contents_size);
new_auth_tok->token.password.signature[
ECRYPTFS_PASSWORD_SIG_SIZE] = '\0';
- ECRYPTFS_SET_FLAG(crypt_stat->flags,
- ECRYPTFS_ENCRYPTED);
+ crypt_stat->flags |= ECRYPTFS_ENCRYPTED;
break;
case ECRYPTFS_TAG_1_PACKET_TYPE:
rc = parse_tag_1_packet(crypt_stat,
@@ -1141,8 +1139,7 @@ int ecryptfs_parse_packet_set(struct ecr
goto out_wipe_list;
}
i += packet_size;
- ECRYPTFS_SET_FLAG(crypt_stat->flags,
- ECRYPTFS_ENCRYPTED);
+ crypt_stat->flags |= ECRYPTFS_ENCRYPTED;
break;
case ECRYPTFS_TAG_11_PACKET_TYPE:
ecryptfs_printk(KERN_WARNING, "Invalid packet set "
@@ -1208,8 +1205,7 @@ int ecryptfs_parse_packet_set(struct ecr
}
leave_list:
rc = -ENOTSUPP;
- if ((ECRYPTFS_CHECK_FLAG(candidate_auth_tok->flags,
- ECRYPTFS_PRIVATE_KEY))) {
+ if (candidate_auth_tok->token_type == ECRYPTFS_PRIVATE_KEY) {
memcpy(&(candidate_auth_tok->token.private_key),
&(chosen_auth_tok->token.private_key),
sizeof(struct ecryptfs_private_key));
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index 6f167f1..2a7ba51 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -295,8 +295,8 @@ static int ecryptfs_readpage(struct file
crypt_stat = &ecryptfs_inode_to_private(file->f_path.dentry->d_inode)
->crypt_stat;
if (!crypt_stat
- || !ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED)
- || ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_NEW_FILE)) {
+ || !(crypt_stat->flags & ECRYPTFS_ENCRYPTED)
+ || (crypt_stat->flags & ECRYPTFS_NEW_FILE)) {
ecryptfs_printk(KERN_DEBUG,
"Passing through unencrypted page\n");
rc = ecryptfs_do_readpage(file, page, page->index);
@@ -657,10 +657,10 @@ static int ecryptfs_commit_write(struct
mutex_lock(&lower_inode->i_mutex);
crypt_stat = &ecryptfs_inode_to_private(file->f_path.dentry->d_inode)
->crypt_stat;
- if (ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_NEW_FILE)) {
+ if (crypt_stat->flags & ECRYPTFS_NEW_FILE) {
ecryptfs_printk(KERN_DEBUG, "ECRYPTFS_NEW_FILE flag set in "
"crypt_stat at memory location [%p]\n", crypt_stat);
- ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, ECRYPTFS_NEW_FILE);
+ crypt_stat->flags &= ~(ECRYPTFS_NEW_FILE);
} else
ecryptfs_printk(KERN_DEBUG, "Not a new file\n");
ecryptfs_printk(KERN_DEBUG, "Calling fill_zeros_to_end_of_page"
--
1.3.3

2007-01-18 21:29:00

by Michael Halcrow

[permalink] [raw]
Subject: [PATCH 4/5] eCryptfs: add flush_dcache_page() calls

On Tue, Jan 09, 2007 at 02:42:03PM -0800, Andrew Morton wrote:
> On Tue, 9 Jan 2007 16:23:37 -0600
> Michael Halcrow <[email protected]> wrote:
> > + set_header_info(page_virt, crypt_stat);
> > + }
>
> The kernel must always run flush_dcache_page() after modifying a pagecache
> page by hand. Please review all of ecryptfs for this.

Call flush_dcache_page() after modifying a pagecache by hand.

Signed-off-by: Michael Halcrow <[email protected]>

---

fs/ecryptfs/mmap.c | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)

b77b1e2cbda1dfa6cc0925bca790701261771c43
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index 2a7ba51..59ec097 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -238,7 +238,9 @@ int ecryptfs_do_readpage(struct file *fi
lower_page_data = (char *)kmap_atomic(lower_page, KM_USER1);
memcpy(page_data, lower_page_data, PAGE_CACHE_SIZE);
kunmap_atomic(lower_page_data, KM_USER1);
+ flush_dcache_page(lower_page);
kunmap_atomic(page_data, KM_USER0);
+ flush_dcache_page(page);
rc = 0;
out:
if (likely(lower_page))
@@ -322,6 +324,7 @@ static int ecryptfs_readpage(struct file
set_header_info(page_virt, crypt_stat);
}
kunmap_atomic(page_virt, KM_USER0);
+ flush_dcache_page(page);
if (rc) {
printk(KERN_ERR "Error reading xattr "
"region\n");
@@ -382,6 +385,7 @@ static int fill_zeros_to_end_of_page(str
memset((page_virt + end_byte_in_page), 0,
(PAGE_CACHE_SIZE - end_byte_in_page));
kunmap_atomic(page_virt, KM_USER0);
+ flush_dcache_page(page);
out:
return 0;
}
@@ -456,6 +460,7 @@ static int ecryptfs_write_inode_size_to_
header_virt = kmap_atomic(header_page, KM_USER0);
memcpy(header_virt, &file_size, sizeof(u64));
kunmap_atomic(header_virt, KM_USER0);
+ flush_dcache_page(header_page);
rc = lower_a_ops->commit_write(lower_file, header_page, 0, 8);
if (rc < 0)
ecryptfs_printk(KERN_ERR, "Error commiting header page "
@@ -742,6 +747,7 @@ int write_zeros(struct file *file, pgoff
tmp_page_virt = kmap_atomic(tmp_page, KM_USER0);
memset(((char *)tmp_page_virt + start), 0, num_zeros);
kunmap_atomic(tmp_page_virt, KM_USER0);
+ flush_dcache_page(tmp_page);
rc = ecryptfs_commit_write(file, tmp_page, start, start + num_zeros);
if (rc < 0) {
ecryptfs_printk(KERN_ERR, "Error attempting to write zero's "
--
1.3.3

2007-01-18 21:29:37

by Michael Halcrow

[permalink] [raw]
Subject: [PATCH 5/5] eCryptfs: convert lookup_one_len() to lookup_one_len_nd()

Call the new lookup_one_len_nd() rather than lookup_one_len(). This
fixes an oops when stacked on NFS.

Note that there are still some issues with eCryptfs on NFS having to
do with directory deletion (I'm not getting an oops, just an -EBUSY).

Signed-off-by: Michael Halcrow <[email protected]>

---
fs/ecryptfs/inode.c | 10 ++++++++--
1 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 9135718..cf02a66 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -283,7 +283,9 @@ static struct dentry *ecryptfs_lookup(st
int rc = 0;
struct dentry *lower_dir_dentry;
struct dentry *lower_dentry;
+ struct dentry *dentry_save;
struct vfsmount *lower_mnt;
+ struct vfsmount *mnt_save;
char *encoded_name;
unsigned int encoded_namelen;
struct ecryptfs_crypt_stat *crypt_stat = NULL;
@@ -311,9 +313,13 @@ static struct dentry *ecryptfs_lookup(st
}
ecryptfs_printk(KERN_DEBUG, "encoded_name = [%s]; encoded_namelen "
"= [%d]\n", encoded_name, encoded_namelen);
- lower_dentry = lookup_one_len(encoded_name, lower_dir_dentry,
- encoded_namelen - 1);
+ dentry_save = nd->dentry;
+ mnt_save = nd->mnt;
+ lower_dentry = lookup_one_len_nd(encoded_name, lower_dir_dentry,
+ (encoded_namelen - 1), nd);
kfree(encoded_name);
+ nd->mnt = mnt_save;
+ nd->dentry = dentry_save;
if (IS_ERR(lower_dentry)) {
ecryptfs_printk(KERN_ERR, "ERR from lower_dentry\n");
rc = PTR_ERR(lower_dentry);
--
1.4.2.4

2007-01-19 12:04:49

by Pekka Enberg

[permalink] [raw]
Subject: Re: [PATCH 2/5] eCryptfs: convert kmap() to kmap_atomic()

On 1/18/07, Michael Halcrow <[email protected]> wrote:
> + page_data = (char *)kmap_atomic(page, KM_USER0);
> + lower_page_data = (char *)kmap_atomic(lower_page, KM_USER1);

Drop 'em redundant casts, please.

2007-01-19 20:35:11

by Michael Halcrow

[permalink] [raw]
Subject: Re: [PATCH 2/5 (try 2)] eCryptfs: convert kmap() to kmap_atomic()

On Fri, Jan 19, 2007 at 02:04:47PM +0200, Pekka Enberg wrote:
> On 1/18/07, Michael Halcrow <[email protected]> wrote:
> >+ page_data = (char *)kmap_atomic(page, KM_USER0);
> >+ lower_page_data = (char *)kmap_atomic(lower_page, KM_USER1);
>
> Drop 'em redundant casts, please.

Replace kmap() with kmap_atomic(). Reduce the amount of time that
mappings are held.

Signed-off-by: Michael Halcrow <[email protected]>
Signed-off-by: Trevor Highland <[email protected]>

---

fs/ecryptfs/crypto.c | 8 +--
fs/ecryptfs/ecryptfs_kernel.h | 4 -
fs/ecryptfs/mmap.c | 121 ++++++++++++-----------------------------
3 files changed, 39 insertions(+), 94 deletions(-)

ff2dcd23fe6bd000049987b2bf98ada70755f114
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index fbb62c8..ac4ea8d 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -429,10 +429,10 @@ static int ecryptfs_read_in_page(struct
goto out;
}
} else {
- rc = ecryptfs_grab_and_map_lower_page(lower_page, NULL,
- lower_inode,
- lower_page_idx);
- if (rc) {
+ *lower_page = grab_cache_page(lower_inode->i_mapping,
+ lower_page_idx);
+ if (!(*lower_page)) {
+ rc = -EINVAL;
ecryptfs_printk(
KERN_ERR, "Error attempting to grab and map "
"lower page with index [0x%.16x]; rc = [%d]\n",
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index 859d31b..0e38d0d 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -527,10 +527,6 @@ int ecryptfs_copy_page_to_lower(struct p
struct file *lower_file);
int ecryptfs_do_readpage(struct file *file, struct page *page,
pgoff_t lower_page_index);
-int ecryptfs_grab_and_map_lower_page(struct page **lower_page,
- char **lower_virt,
- struct inode *lower_inode,
- unsigned long lower_page_index);
int ecryptfs_writepage_and_release_lower_page(struct page *lower_page,
struct inode *lower_inode,
struct writeback_control *wbc);
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index 94bcabf..3dec846 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -234,22 +234,11 @@ int ecryptfs_do_readpage(struct file *fi
goto out;
}
wait_on_page_locked(lower_page);
- page_data = (char *)kmap(page);
- if (!page_data) {
- rc = -ENOMEM;
- ecryptfs_printk(KERN_ERR, "Error mapping page\n");
- goto out;
- }
- lower_page_data = (char *)kmap(lower_page);
- if (!lower_page_data) {
- rc = -ENOMEM;
- ecryptfs_printk(KERN_ERR, "Error mapping page\n");
- kunmap(page);
- goto out;
- }
+ page_data = kmap_atomic(page, KM_USER0);
+ lower_page_data = kmap_atomic(lower_page, KM_USER1);
memcpy(page_data, lower_page_data, PAGE_CACHE_SIZE);
- kunmap(lower_page);
- kunmap(page);
+ kunmap_atomic(lower_page_data, KM_USER1);
+ kunmap_atomic(page_data, KM_USER0);
rc = 0;
out:
if (likely(lower_page))
@@ -325,19 +314,14 @@ static int ecryptfs_readpage(struct file
if (page->index < num_pages_in_header_region) {
char *page_virt;

- page_virt = (char *)kmap(page);
- if (!page_virt) {
- rc = -ENOMEM;
- printk(KERN_ERR "Error mapping page\n");
- goto out;
- }
+ page_virt = kmap_atomic(page, KM_USER0);
memset(page_virt, 0, PAGE_CACHE_SIZE);
if (page->index == 0) {
rc = ecryptfs_read_xattr_region(
page_virt, file->f_path.dentry);
set_header_info(page_virt, crypt_stat);
}
- kunmap(page);
+ kunmap_atomic(page_virt, KM_USER0);
if (rc) {
printk(KERN_ERR "Error reading xattr "
"region\n");
@@ -387,26 +371,19 @@ static int fill_zeros_to_end_of_page(str
{
struct inode *inode = page->mapping->host;
int end_byte_in_page;
- int rc = 0;
char *page_virt;

- if ((i_size_read(inode) / PAGE_CACHE_SIZE) == page->index) {
- end_byte_in_page = i_size_read(inode) % PAGE_CACHE_SIZE;
- if (to > end_byte_in_page)
- end_byte_in_page = to;
- page_virt = kmap(page);
- if (!page_virt) {
- rc = -ENOMEM;
- ecryptfs_printk(KERN_WARNING,
- "Could not map page\n");
- goto out;
- }
- memset((page_virt + end_byte_in_page), 0,
- (PAGE_CACHE_SIZE - end_byte_in_page));
- kunmap(page);
- }
+ if ((i_size_read(inode) / PAGE_CACHE_SIZE) != page->index)
+ goto out;
+ end_byte_in_page = i_size_read(inode) % PAGE_CACHE_SIZE;
+ if (to > end_byte_in_page)
+ end_byte_in_page = to;
+ page_virt = kmap_atomic(page, KM_USER0);
+ memset((page_virt + end_byte_in_page), 0,
+ (PAGE_CACHE_SIZE - end_byte_in_page));
+ kunmap_atomic(page_virt, KM_USER0);
out:
- return rc;
+ return 0;
}

static int ecryptfs_prepare_write(struct file *file, struct page *page,
@@ -414,7 +391,6 @@ static int ecryptfs_prepare_write(struct
{
int rc = 0;

- kmap(page);
if (from == 0 && to == PAGE_CACHE_SIZE)
goto out; /* If we are writing a full page, it will be
up to date. */
@@ -424,30 +400,6 @@ out:
return rc;
}

-int ecryptfs_grab_and_map_lower_page(struct page **lower_page,
- char **lower_virt,
- struct inode *lower_inode,
- unsigned long lower_page_index)
-{
- int rc = 0;
-
- (*lower_page) = grab_cache_page(lower_inode->i_mapping,
- lower_page_index);
- if (!(*lower_page)) {
- ecryptfs_printk(KERN_ERR, "grab_cache_page for "
- "lower_page_index = [0x%.16x] failed\n",
- lower_page_index);
- rc = -EINVAL;
- goto out;
- }
- if (lower_virt)
- (*lower_virt) = kmap((*lower_page));
- else
- kmap((*lower_page));
-out:
- return rc;
-}
-
int ecryptfs_writepage_and_release_lower_page(struct page *lower_page,
struct inode *lower_inode,
struct writeback_control *wbc)
@@ -466,11 +418,8 @@ out:
return rc;
}

-static void ecryptfs_unmap_and_release_lower_page(struct page *lower_page)
+static void ecryptfs_release_lower_page(struct page *lower_page)
{
- kunmap(lower_page);
- ecryptfs_printk(KERN_DEBUG, "Unlocking lower page with index = "
- "[0x%.16x]\n", lower_page->index);
unlock_page(lower_page);
page_cache_release(lower_page);
}
@@ -492,11 +441,11 @@ static int ecryptfs_write_inode_size_to_
const struct address_space_operations *lower_a_ops;
u64 file_size;

- rc = ecryptfs_grab_and_map_lower_page(&header_page, &header_virt,
- lower_inode, 0);
- if (rc) {
- ecryptfs_printk(KERN_ERR, "grab_cache_page for header page "
- "failed\n");
+ header_page = grab_cache_page(lower_inode->i_mapping, 0);
+ if (!header_page) {
+ ecryptfs_printk(KERN_ERR, "grab_cache_page for "
+ "lower_page_index 0 failed\n");
+ rc = -EINVAL;
goto out;
}
lower_a_ops = lower_inode->i_mapping->a_ops;
@@ -504,12 +453,14 @@ static int ecryptfs_write_inode_size_to_
file_size = (u64)i_size_read(inode);
ecryptfs_printk(KERN_DEBUG, "Writing size: [0x%.16x]\n", file_size);
file_size = cpu_to_be64(file_size);
+ header_virt = kmap_atomic(header_page, KM_USER0);
memcpy(header_virt, &file_size, sizeof(u64));
+ kunmap_atomic(header_virt, KM_USER0);
rc = lower_a_ops->commit_write(lower_file, header_page, 0, 8);
if (rc < 0)
ecryptfs_printk(KERN_ERR, "Error commiting header page "
"write\n");
- ecryptfs_unmap_and_release_lower_page(header_page);
+ ecryptfs_release_lower_page(header_page);
lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME;
mark_inode_dirty_sync(inode);
out:
@@ -597,10 +548,10 @@ int ecryptfs_get_lower_page(struct page
{
int rc = 0;

- rc = ecryptfs_grab_and_map_lower_page(lower_page, NULL, lower_inode,
- lower_page_index);
- if (rc) {
- ecryptfs_printk(KERN_ERR, "Error attempting to grab and map "
+ *lower_page = grab_cache_page(lower_inode->i_mapping, lower_page_index);
+ if (!(*lower_page)) {
+ rc = -EINVAL;
+ ecryptfs_printk(KERN_ERR, "Error attempting to grab "
"lower page with index [0x%.16x]\n",
lower_page_index);
goto out;
@@ -616,7 +567,7 @@ int ecryptfs_get_lower_page(struct page
}
out:
if (rc && (*lower_page)) {
- ecryptfs_unmap_and_release_lower_page(*lower_page);
+ ecryptfs_release_lower_page(*lower_page);
(*lower_page) = NULL;
}
return rc;
@@ -641,7 +592,7 @@ ecryptfs_commit_lower_page(struct page *
"Error committing write; rc = [%d]\n", rc);
} else
rc = 0;
- ecryptfs_unmap_and_release_lower_page(lower_page);
+ ecryptfs_release_lower_page(lower_page);
return rc;
}

@@ -747,7 +698,6 @@ static int ecryptfs_commit_write(struct
lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME;
mark_inode_dirty_sync(inode);
out:
- kunmap(page); /* mapped in prior call (prepare_write) */
if (rc < 0)
ClearPageUptodate(page);
else
@@ -772,6 +722,7 @@ int write_zeros(struct file *file, pgoff
{
int rc = 0;
struct page *tmp_page;
+ char *tmp_page_virt;

tmp_page = ecryptfs_get1page(file, index);
if (IS_ERR(tmp_page)) {
@@ -780,28 +731,26 @@ int write_zeros(struct file *file, pgoff
rc = PTR_ERR(tmp_page);
goto out;
}
- kmap(tmp_page);
rc = ecryptfs_prepare_write(file, tmp_page, start, start + num_zeros);
if (rc) {
ecryptfs_printk(KERN_ERR, "Error preparing to write zero's "
"to remainder of page at index [0x%.16x]\n",
index);
- kunmap(tmp_page);
page_cache_release(tmp_page);
goto out;
}
- memset(((char *)page_address(tmp_page) + start), 0, num_zeros);
+ tmp_page_virt = kmap_atomic(tmp_page, KM_USER0);
+ memset(((char *)tmp_page_virt + start), 0, num_zeros);
+ kunmap_atomic(tmp_page_virt, KM_USER0);
rc = ecryptfs_commit_write(file, tmp_page, start, start + num_zeros);
if (rc < 0) {
ecryptfs_printk(KERN_ERR, "Error attempting to write zero's "
"to remainder of page at index [0x%.16x]\n",
index);
- kunmap(tmp_page);
page_cache_release(tmp_page);
goto out;
}
rc = 0;
- kunmap(tmp_page);
page_cache_release(tmp_page);
out:
return rc;
--
1.3.3