diff options
Diffstat (limited to 'fs/ecryptfs/read_write.c')
-rw-r--r-- | fs/ecryptfs/read_write.c | 100 |
1 files changed, 18 insertions, 82 deletions
diff --git a/fs/ecryptfs/read_write.c b/fs/ecryptfs/read_write.c index 3745f7c2b9c2..b2a34a192f4f 100644 --- a/fs/ecryptfs/read_write.c +++ b/fs/ecryptfs/read_write.c | |||
@@ -130,13 +130,18 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset, | |||
130 | pgoff_t ecryptfs_page_idx = (pos >> PAGE_CACHE_SHIFT); | 130 | pgoff_t ecryptfs_page_idx = (pos >> PAGE_CACHE_SHIFT); |
131 | size_t start_offset_in_page = (pos & ~PAGE_CACHE_MASK); | 131 | size_t start_offset_in_page = (pos & ~PAGE_CACHE_MASK); |
132 | size_t num_bytes = (PAGE_CACHE_SIZE - start_offset_in_page); | 132 | size_t num_bytes = (PAGE_CACHE_SIZE - start_offset_in_page); |
133 | size_t total_remaining_bytes = ((offset + size) - pos); | 133 | loff_t total_remaining_bytes = ((offset + size) - pos); |
134 | |||
135 | if (fatal_signal_pending(current)) { | ||
136 | rc = -EINTR; | ||
137 | break; | ||
138 | } | ||
134 | 139 | ||
135 | if (num_bytes > total_remaining_bytes) | 140 | if (num_bytes > total_remaining_bytes) |
136 | num_bytes = total_remaining_bytes; | 141 | num_bytes = total_remaining_bytes; |
137 | if (pos < offset) { | 142 | if (pos < offset) { |
138 | /* remaining zeros to write, up to destination offset */ | 143 | /* remaining zeros to write, up to destination offset */ |
139 | size_t total_remaining_zeros = (offset - pos); | 144 | loff_t total_remaining_zeros = (offset - pos); |
140 | 145 | ||
141 | if (num_bytes > total_remaining_zeros) | 146 | if (num_bytes > total_remaining_zeros) |
142 | num_bytes = total_remaining_zeros; | 147 | num_bytes = total_remaining_zeros; |
@@ -151,7 +156,7 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset, | |||
151 | ecryptfs_page_idx, rc); | 156 | ecryptfs_page_idx, rc); |
152 | goto out; | 157 | goto out; |
153 | } | 158 | } |
154 | ecryptfs_page_virt = kmap_atomic(ecryptfs_page, KM_USER0); | 159 | ecryptfs_page_virt = kmap_atomic(ecryptfs_page); |
155 | 160 | ||
156 | /* | 161 | /* |
157 | * pos: where we're now writing, offset: where the request was | 162 | * pos: where we're now writing, offset: where the request was |
@@ -174,7 +179,7 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset, | |||
174 | (data + data_offset), num_bytes); | 179 | (data + data_offset), num_bytes); |
175 | data_offset += num_bytes; | 180 | data_offset += num_bytes; |
176 | } | 181 | } |
177 | kunmap_atomic(ecryptfs_page_virt, KM_USER0); | 182 | kunmap_atomic(ecryptfs_page_virt); |
178 | flush_dcache_page(ecryptfs_page); | 183 | flush_dcache_page(ecryptfs_page); |
179 | SetPageUptodate(ecryptfs_page); | 184 | SetPageUptodate(ecryptfs_page); |
180 | unlock_page(ecryptfs_page); | 185 | unlock_page(ecryptfs_page); |
@@ -193,15 +198,19 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset, | |||
193 | } | 198 | } |
194 | pos += num_bytes; | 199 | pos += num_bytes; |
195 | } | 200 | } |
196 | if ((offset + size) > ecryptfs_file_size) { | 201 | if (pos > ecryptfs_file_size) { |
197 | i_size_write(ecryptfs_inode, (offset + size)); | 202 | i_size_write(ecryptfs_inode, pos); |
198 | if (crypt_stat->flags & ECRYPTFS_ENCRYPTED) { | 203 | if (crypt_stat->flags & ECRYPTFS_ENCRYPTED) { |
199 | rc = ecryptfs_write_inode_size_to_metadata( | 204 | int rc2; |
205 | |||
206 | rc2 = ecryptfs_write_inode_size_to_metadata( | ||
200 | ecryptfs_inode); | 207 | ecryptfs_inode); |
201 | if (rc) { | 208 | if (rc2) { |
202 | printk(KERN_ERR "Problem with " | 209 | printk(KERN_ERR "Problem with " |
203 | "ecryptfs_write_inode_size_to_metadata; " | 210 | "ecryptfs_write_inode_size_to_metadata; " |
204 | "rc = [%d]\n", rc); | 211 | "rc = [%d]\n", rc2); |
212 | if (!rc) | ||
213 | rc = rc2; | ||
205 | goto out; | 214 | goto out; |
206 | } | 215 | } |
207 | } | 216 | } |
@@ -273,76 +282,3 @@ int ecryptfs_read_lower_page_segment(struct page *page_for_ecryptfs, | |||
273 | flush_dcache_page(page_for_ecryptfs); | 282 | flush_dcache_page(page_for_ecryptfs); |
274 | return rc; | 283 | return rc; |
275 | } | 284 | } |
276 | |||
277 | #if 0 | ||
278 | /** | ||
279 | * ecryptfs_read | ||
280 | * @data: The virtual address into which to write the data read (and | ||
281 | * possibly decrypted) from the lower file | ||
282 | * @offset: The offset in the decrypted view of the file from which to | ||
283 | * read into @data | ||
284 | * @size: The number of bytes to read into @data | ||
285 | * @ecryptfs_file: The eCryptfs file from which to read | ||
286 | * | ||
287 | * Read an arbitrary amount of data from an arbitrary location in the | ||
288 | * eCryptfs page cache. This is done on an extent-by-extent basis; | ||
289 | * individual extents are decrypted and read from the lower page | ||
290 | * cache (via VFS reads). This function takes care of all the | ||
291 | * address translation to locations in the lower filesystem. | ||
292 | * | ||
293 | * Returns zero on success; non-zero otherwise | ||
294 | */ | ||
295 | int ecryptfs_read(char *data, loff_t offset, size_t size, | ||
296 | struct file *ecryptfs_file) | ||
297 | { | ||
298 | struct inode *ecryptfs_inode = ecryptfs_file->f_dentry->d_inode; | ||
299 | struct page *ecryptfs_page; | ||
300 | char *ecryptfs_page_virt; | ||
301 | loff_t ecryptfs_file_size = i_size_read(ecryptfs_inode); | ||
302 | loff_t data_offset = 0; | ||
303 | loff_t pos; | ||
304 | int rc = 0; | ||
305 | |||
306 | if ((offset + size) > ecryptfs_file_size) { | ||
307 | rc = -EINVAL; | ||
308 | printk(KERN_ERR "%s: Attempt to read data past the end of the " | ||
309 | "file; offset = [%lld]; size = [%td]; " | ||
310 | "ecryptfs_file_size = [%lld]\n", | ||
311 | __func__, offset, size, ecryptfs_file_size); | ||
312 | goto out; | ||
313 | } | ||
314 | pos = offset; | ||
315 | while (pos < (offset + size)) { | ||
316 | pgoff_t ecryptfs_page_idx = (pos >> PAGE_CACHE_SHIFT); | ||
317 | size_t start_offset_in_page = (pos & ~PAGE_CACHE_MASK); | ||
318 | size_t num_bytes = (PAGE_CACHE_SIZE - start_offset_in_page); | ||
319 | size_t total_remaining_bytes = ((offset + size) - pos); | ||
320 | |||
321 | if (num_bytes > total_remaining_bytes) | ||
322 | num_bytes = total_remaining_bytes; | ||
323 | ecryptfs_page = ecryptfs_get_locked_page(ecryptfs_inode, | ||
324 | ecryptfs_page_idx); | ||
325 | if (IS_ERR(ecryptfs_page)) { | ||
326 | rc = PTR_ERR(ecryptfs_page); | ||
327 | printk(KERN_ERR "%s: Error getting page at " | ||
328 | "index [%ld] from eCryptfs inode " | ||
329 | "mapping; rc = [%d]\n", __func__, | ||
330 | ecryptfs_page_idx, rc); | ||
331 | goto out; | ||
332 | } | ||
333 | ecryptfs_page_virt = kmap_atomic(ecryptfs_page, KM_USER0); | ||
334 | memcpy((data + data_offset), | ||
335 | ((char *)ecryptfs_page_virt + start_offset_in_page), | ||
336 | num_bytes); | ||
337 | kunmap_atomic(ecryptfs_page_virt, KM_USER0); | ||
338 | flush_dcache_page(ecryptfs_page); | ||
339 | SetPageUptodate(ecryptfs_page); | ||
340 | unlock_page(ecryptfs_page); | ||
341 | page_cache_release(ecryptfs_page); | ||
342 | pos += num_bytes; | ||
343 | data_offset += num_bytes; | ||
344 | } | ||
345 | out: | ||
346 | return rc; | ||
347 | } | ||
348 | #endif /* 0 */ | ||