Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

eCryptfs: Propagate vfs_read and vfs_write return codes

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>

+26 -29
+11 -8
fs/ecryptfs/crypto.c
··· 509 509 + extent_offset), crypt_stat); 510 510 rc = ecryptfs_write_lower(ecryptfs_inode, enc_extent_virt, 511 511 offset, crypt_stat->extent_size); 512 - if (rc) { 512 + if (rc < 0) { 513 513 ecryptfs_printk(KERN_ERR, "Error attempting " 514 514 "to write lower page; rc = [%d]" 515 515 "\n", rc); 516 516 goto out; 517 517 } 518 518 } 519 + rc = 0; 519 520 out: 520 521 if (enc_extent_page) { 521 522 kunmap(enc_extent_page); ··· 632 631 rc = ecryptfs_read_lower(enc_extent_virt, offset, 633 632 crypt_stat->extent_size, 634 633 ecryptfs_inode); 635 - if (rc) { 634 + if (rc < 0) { 636 635 ecryptfs_printk(KERN_ERR, "Error attempting " 637 636 "to read lower page; rc = [%d]" 638 637 "\n", rc); ··· 1214 1213 crypt_stat->extent_size = ECRYPTFS_DEFAULT_EXTENT_SIZE; 1215 1214 rc = ecryptfs_read_lower(data, 0, crypt_stat->extent_size, 1216 1215 ecryptfs_inode); 1217 - if (rc) { 1216 + if (rc < 0) { 1218 1217 printk(KERN_ERR "%s: Error reading header region; rc = [%d]\n", 1219 1218 __func__, rc); 1220 1219 goto out; 1221 1220 } 1222 1221 if (!contains_ecryptfs_marker(data + ECRYPTFS_FILE_SIZE_BYTES)) { 1223 1222 rc = -EINVAL; 1224 - } 1223 + } else 1224 + rc = 0; 1225 1225 out: 1226 1226 return rc; 1227 1227 } ··· 1317 1315 1318 1316 rc = ecryptfs_write_lower(ecryptfs_dentry->d_inode, virt, 1319 1317 0, virt_len); 1320 - if (rc) 1318 + if (rc < 0) 1321 1319 printk(KERN_ERR "%s: Error attempting to write header " 1322 - "information to lower file; rc = [%d]\n", __func__, 1323 - rc); 1320 + "information to lower file; rc = [%d]\n", __func__, rc); 1321 + else 1322 + rc = 0; 1324 1323 return rc; 1325 1324 } 1326 1325 ··· 1601 1598 } 1602 1599 rc = ecryptfs_read_lower(page_virt, 0, crypt_stat->extent_size, 1603 1600 ecryptfs_inode); 1604 - if (!rc) 1601 + if (rc >= 0) 1605 1602 rc = ecryptfs_read_headers_virt(page_virt, crypt_stat, 1606 1603 ecryptfs_dentry, 1607 1604 ECRYPTFS_VALIDATE_HEADER_SIZE);
+3 -1
fs/ecryptfs/mmap.c
··· 396 396 rc = ecryptfs_write_lower(ecryptfs_inode, file_size_virt, 0, 397 397 sizeof(u64)); 398 398 kfree(file_size_virt); 399 - if (rc) 399 + if (rc < 0) 400 400 printk(KERN_ERR "%s: Error writing file size to header; " 401 401 "rc = [%d]\n", __func__, rc); 402 + else 403 + rc = 0; 402 404 out: 403 405 return rc; 404 406 }
+12 -20
fs/ecryptfs/read_write.c
··· 34 34 * 35 35 * Write data to the lower file. 36 36 * 37 - * Returns zero on success; non-zero on error 37 + * Returns bytes written on success; less than zero on error 38 38 */ 39 39 int ecryptfs_write_lower(struct inode *ecryptfs_inode, char *data, 40 40 loff_t offset, size_t size) 41 41 { 42 42 struct ecryptfs_inode_info *inode_info; 43 - ssize_t octets_written; 44 43 mm_segment_t fs_save; 45 - int rc = 0; 44 + ssize_t rc; 46 45 47 46 inode_info = ecryptfs_inode_to_private(ecryptfs_inode); 48 47 mutex_lock(&inode_info->lower_file_mutex); ··· 49 50 inode_info->lower_file->f_pos = offset; 50 51 fs_save = get_fs(); 51 52 set_fs(get_ds()); 52 - octets_written = vfs_write(inode_info->lower_file, data, size, 53 - &inode_info->lower_file->f_pos); 53 + rc = vfs_write(inode_info->lower_file, data, size, 54 + &inode_info->lower_file->f_pos); 54 55 set_fs(fs_save); 55 - if (octets_written < 0) { 56 - printk(KERN_ERR "%s: octets_written = [%td]; " 57 - "expected [%td]\n", __func__, octets_written, size); 58 - rc = -EINVAL; 59 - } 60 56 mutex_unlock(&inode_info->lower_file_mutex); 61 57 mark_inode_dirty_sync(ecryptfs_inode); 62 58 return rc; ··· 85 91 + offset_in_page); 86 92 virt = kmap(page_for_lower); 87 93 rc = ecryptfs_write_lower(ecryptfs_inode, virt, offset, size); 94 + if (rc > 0) 95 + rc = 0; 88 96 kunmap(page_for_lower); 89 97 return rc; 90 98 } ··· 225 229 * Read @size bytes of data at byte offset @offset from the lower 226 230 * inode into memory location @data. 227 231 * 228 - * Returns zero on success; non-zero on error 232 + * Returns bytes read on success; 0 on EOF; less than zero on error 229 233 */ 230 234 int ecryptfs_read_lower(char *data, loff_t offset, size_t size, 231 235 struct inode *ecryptfs_inode) 232 236 { 233 237 struct ecryptfs_inode_info *inode_info = 234 238 ecryptfs_inode_to_private(ecryptfs_inode); 235 - ssize_t octets_read; 236 239 mm_segment_t fs_save; 237 - int rc = 0; 240 + ssize_t rc; 238 241 239 242 mutex_lock(&inode_info->lower_file_mutex); 240 243 BUG_ON(!inode_info->lower_file); 241 244 inode_info->lower_file->f_pos = offset; 242 245 fs_save = get_fs(); 243 246 set_fs(get_ds()); 244 - octets_read = vfs_read(inode_info->lower_file, data, size, 245 - &inode_info->lower_file->f_pos); 247 + rc = vfs_read(inode_info->lower_file, data, size, 248 + &inode_info->lower_file->f_pos); 246 249 set_fs(fs_save); 247 - if (octets_read < 0) { 248 - printk(KERN_ERR "%s: octets_read = [%td]; " 249 - "expected [%td]\n", __func__, octets_read, size); 250 - rc = -EINVAL; 251 - } 252 250 mutex_unlock(&inode_info->lower_file_mutex); 253 251 return rc; 254 252 } ··· 274 284 offset = ((((loff_t)page_index) << PAGE_CACHE_SHIFT) + offset_in_page); 275 285 virt = kmap(page_for_ecryptfs); 276 286 rc = ecryptfs_read_lower(virt, offset, size, ecryptfs_inode); 287 + if (rc > 0) 288 + rc = 0; 277 289 kunmap(page_for_ecryptfs); 278 290 flush_dcache_page(page_for_ecryptfs); 279 291 return rc;