Skip to content

Commit

Permalink
eCryptfs: Propagate vfs_read and vfs_write return codes
Browse files Browse the repository at this point in the history
Errors returned from vfs_read() and vfs_write() calls to the lower
filesystem were being masked as -EINVAL.  This caused some confusion to
users who saw EINVAL instead of ENOSPC when the disk was full, for
instance.

Also, the actual bytes read or written were not accessible by callers to
ecryptfs_read_lower() and ecryptfs_write_lower(), which may be useful in
some cases.  This patch updates the error handling logic where those
functions are called in order to accept positive return codes indicating
success.

Cc: Eric Sandeen <esandeen@redhat.com>
Acked-by: Serge Hallyn <serue@us.ibm.com>
Cc: ecryptfs-devel@lists.launchpad.net
Signed-off-by: Tyler Hicks <tyhicks@linux.vnet.ibm.com>
  • Loading branch information
Tyler Hicks committed Sep 23, 2009
1 parent 3891959 commit 96a7b9c
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 29 deletions.
19 changes: 11 additions & 8 deletions fs/ecryptfs/crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -509,13 +509,14 @@ int ecryptfs_encrypt_page(struct page *page)
+ extent_offset), crypt_stat);
rc = ecryptfs_write_lower(ecryptfs_inode, enc_extent_virt,
offset, crypt_stat->extent_size);
if (rc) {
if (rc < 0) {
ecryptfs_printk(KERN_ERR, "Error attempting "
"to write lower page; rc = [%d]"
"\n", rc);
goto out;
}
}
rc = 0;
out:
if (enc_extent_page) {
kunmap(enc_extent_page);
Expand Down Expand Up @@ -631,7 +632,7 @@ int ecryptfs_decrypt_page(struct page *page)
rc = ecryptfs_read_lower(enc_extent_virt, offset,
crypt_stat->extent_size,
ecryptfs_inode);
if (rc) {
if (rc < 0) {
ecryptfs_printk(KERN_ERR, "Error attempting "
"to read lower page; rc = [%d]"
"\n", rc);
Expand Down Expand Up @@ -1213,14 +1214,15 @@ int ecryptfs_read_and_validate_header_region(char *data,
crypt_stat->extent_size = ECRYPTFS_DEFAULT_EXTENT_SIZE;
rc = ecryptfs_read_lower(data, 0, crypt_stat->extent_size,
ecryptfs_inode);
if (rc) {
if (rc < 0) {
printk(KERN_ERR "%s: Error reading header region; rc = [%d]\n",
__func__, rc);
goto out;
}
if (!contains_ecryptfs_marker(data + ECRYPTFS_FILE_SIZE_BYTES)) {
rc = -EINVAL;
}
} else
rc = 0;
out:
return rc;
}
Expand Down Expand Up @@ -1315,10 +1317,11 @@ ecryptfs_write_metadata_to_contents(struct dentry *ecryptfs_dentry,

rc = ecryptfs_write_lower(ecryptfs_dentry->d_inode, virt,
0, virt_len);
if (rc)
if (rc < 0)
printk(KERN_ERR "%s: Error attempting to write header "
"information to lower file; rc = [%d]\n", __func__,
rc);
"information to lower file; rc = [%d]\n", __func__, rc);
else
rc = 0;
return rc;
}

Expand Down Expand Up @@ -1598,7 +1601,7 @@ int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry)
}
rc = ecryptfs_read_lower(page_virt, 0, crypt_stat->extent_size,
ecryptfs_inode);
if (!rc)
if (rc >= 0)
rc = ecryptfs_read_headers_virt(page_virt, crypt_stat,
ecryptfs_dentry,
ECRYPTFS_VALIDATE_HEADER_SIZE);
Expand Down
4 changes: 3 additions & 1 deletion fs/ecryptfs/mmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -396,9 +396,11 @@ static int ecryptfs_write_inode_size_to_header(struct inode *ecryptfs_inode)
rc = ecryptfs_write_lower(ecryptfs_inode, file_size_virt, 0,
sizeof(u64));
kfree(file_size_virt);
if (rc)
if (rc < 0)
printk(KERN_ERR "%s: Error writing file size to header; "
"rc = [%d]\n", __func__, rc);
else
rc = 0;
out:
return rc;
}
Expand Down
32 changes: 12 additions & 20 deletions fs/ecryptfs/read_write.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,30 +34,24 @@
*
* Write data to the lower file.
*
* Returns zero on success; non-zero on error
* Returns bytes written on success; less than zero on error
*/
int ecryptfs_write_lower(struct inode *ecryptfs_inode, char *data,
loff_t offset, size_t size)
{
struct ecryptfs_inode_info *inode_info;
ssize_t octets_written;
mm_segment_t fs_save;
int rc = 0;
ssize_t rc;

inode_info = ecryptfs_inode_to_private(ecryptfs_inode);
mutex_lock(&inode_info->lower_file_mutex);
BUG_ON(!inode_info->lower_file);
inode_info->lower_file->f_pos = offset;
fs_save = get_fs();
set_fs(get_ds());
octets_written = vfs_write(inode_info->lower_file, data, size,
&inode_info->lower_file->f_pos);
rc = vfs_write(inode_info->lower_file, data, size,
&inode_info->lower_file->f_pos);
set_fs(fs_save);
if (octets_written < 0) {
printk(KERN_ERR "%s: octets_written = [%td]; "
"expected [%td]\n", __func__, octets_written, size);
rc = -EINVAL;
}
mutex_unlock(&inode_info->lower_file_mutex);
mark_inode_dirty_sync(ecryptfs_inode);
return rc;
Expand Down Expand Up @@ -91,6 +85,8 @@ int ecryptfs_write_lower_page_segment(struct inode *ecryptfs_inode,
+ offset_in_page);
virt = kmap(page_for_lower);
rc = ecryptfs_write_lower(ecryptfs_inode, virt, offset, size);
if (rc > 0)
rc = 0;
kunmap(page_for_lower);
return rc;
}
Expand Down Expand Up @@ -229,30 +225,24 @@ int ecryptfs_write(struct file *ecryptfs_file, char *data, loff_t offset,
* Read @size bytes of data at byte offset @offset from the lower
* inode into memory location @data.
*
* Returns zero on success; non-zero on error
* Returns bytes read on success; 0 on EOF; less than zero on error
*/
int ecryptfs_read_lower(char *data, loff_t offset, size_t size,
struct inode *ecryptfs_inode)
{
struct ecryptfs_inode_info *inode_info =
ecryptfs_inode_to_private(ecryptfs_inode);
ssize_t octets_read;
mm_segment_t fs_save;
int rc = 0;
ssize_t rc;

mutex_lock(&inode_info->lower_file_mutex);
BUG_ON(!inode_info->lower_file);
inode_info->lower_file->f_pos = offset;
fs_save = get_fs();
set_fs(get_ds());
octets_read = vfs_read(inode_info->lower_file, data, size,
&inode_info->lower_file->f_pos);
rc = vfs_read(inode_info->lower_file, data, size,
&inode_info->lower_file->f_pos);
set_fs(fs_save);
if (octets_read < 0) {
printk(KERN_ERR "%s: octets_read = [%td]; "
"expected [%td]\n", __func__, octets_read, size);
rc = -EINVAL;
}
mutex_unlock(&inode_info->lower_file_mutex);
return rc;
}
Expand Down Expand Up @@ -284,6 +274,8 @@ int ecryptfs_read_lower_page_segment(struct page *page_for_ecryptfs,
offset = ((((loff_t)page_index) << PAGE_CACHE_SHIFT) + offset_in_page);
virt = kmap(page_for_ecryptfs);
rc = ecryptfs_read_lower(virt, offset, size, ecryptfs_inode);
if (rc > 0)
rc = 0;
kunmap(page_for_ecryptfs);
flush_dcache_page(page_for_ecryptfs);
return rc;
Expand Down

0 comments on commit 96a7b9c

Please sign in to comment.