summaryrefslogtreecommitdiff
path: root/fs/f2fs/gc.c
diff options
context:
space:
mode:
authorJaegeuk Kim <jaegeuk@kernel.org>2015-04-23 12:04:33 -0700
committerJaegeuk Kim <jaegeuk@kernel.org>2015-05-28 15:41:52 -0700
commit4375a33664de17af9032b5f491a49bd256670927 (patch)
tree7c083fd9fafecaac1e6b49d5c60abe1ecbe68ece /fs/f2fs/gc.c
parentfcc85a4d86b5018f08717160c89c0eb50afd1dca (diff)
f2fs crypto: add encryption support in read/write paths
This patch adds encryption support in read and write paths. Note that, in f2fs, we need to consider cleaning operation. In cleaning procedure, we must avoid encrypting and decrypting written blocks. So, this patch implements move_encrypted_block(). Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Diffstat (limited to 'fs/f2fs/gc.c')
-rw-r--r--fs/f2fs/gc.c79
1 files changed, 78 insertions, 1 deletions
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 2e2afebd9d0f..43354cb3ce94 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -518,6 +518,72 @@ static int check_dnode(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
return 1;
}
+static void move_encrypted_block(struct inode *inode, block_t bidx)
+{
+ struct f2fs_io_info fio = {
+ .sbi = F2FS_I_SB(inode),
+ .type = DATA,
+ .rw = READ_SYNC,
+ .encrypted_page = NULL,
+ };
+ struct dnode_of_data dn;
+ struct f2fs_summary sum;
+ struct node_info ni;
+ struct page *page;
+ int err;
+
+ /* do not read out */
+ page = grab_cache_page(inode->i_mapping, bidx);
+ if (!page)
+ return;
+
+ set_new_dnode(&dn, inode, NULL, NULL, 0);
+ err = get_dnode_of_data(&dn, bidx, LOOKUP_NODE);
+ if (err)
+ goto out;
+
+ if (unlikely(dn.data_blkaddr == NULL_ADDR))
+ goto put_out;
+
+ get_node_info(fio.sbi, dn.nid, &ni);
+ set_summary(&sum, dn.nid, dn.ofs_in_node, ni.version);
+
+ /* read page */
+ fio.page = page;
+ fio.blk_addr = dn.data_blkaddr;
+
+ fio.encrypted_page = grab_cache_page(META_MAPPING(fio.sbi), fio.blk_addr);
+ if (!fio.encrypted_page)
+ goto put_out;
+
+ f2fs_submit_page_bio(&fio);
+
+ /* allocate block address */
+ f2fs_wait_on_page_writeback(dn.node_page, NODE);
+
+ allocate_data_block(fio.sbi, NULL, fio.blk_addr,
+ &fio.blk_addr, &sum, CURSEG_COLD_DATA);
+ dn.data_blkaddr = fio.blk_addr;
+
+ /* write page */
+ lock_page(fio.encrypted_page);
+ set_page_writeback(fio.encrypted_page);
+ fio.rw = WRITE_SYNC;
+ f2fs_submit_page_mbio(&fio);
+
+ set_data_blkaddr(&dn);
+ f2fs_update_extent_cache(&dn);
+ set_inode_flag(F2FS_I(inode), FI_APPEND_WRITE);
+ if (page->index == 0)
+ set_inode_flag(F2FS_I(inode), FI_FIRST_BLOCK_WRITTEN);
+
+ f2fs_put_page(fio.encrypted_page, 1);
+put_out:
+ f2fs_put_dnode(&dn);
+out:
+ f2fs_put_page(page, 1);
+}
+
static void move_data_page(struct inode *inode, block_t bidx, int gc_type)
{
struct page *page;
@@ -537,6 +603,7 @@ static void move_data_page(struct inode *inode, block_t bidx, int gc_type)
.type = DATA,
.rw = WRITE_SYNC,
.page = page,
+ .encrypted_page = NULL,
};
f2fs_wait_on_page_writeback(page, DATA);
@@ -606,6 +673,13 @@ next_step:
if (IS_ERR(inode) || is_bad_inode(inode))
continue;
+ /* if encrypted inode, let's go phase 3 */
+ if (f2fs_encrypted_inode(inode) &&
+ S_ISREG(inode->i_mode)) {
+ add_gc_inode(gc_list, inode);
+ continue;
+ }
+
start_bidx = start_bidx_of_node(nofs, F2FS_I(inode));
data_page = get_read_data_page(inode,
start_bidx + ofs_in_node, READA);
@@ -624,7 +698,10 @@ next_step:
if (inode) {
start_bidx = start_bidx_of_node(nofs, F2FS_I(inode))
+ ofs_in_node;
- move_data_page(inode, start_bidx, gc_type);
+ if (f2fs_encrypted_inode(inode) && S_ISREG(inode->i_mode))
+ move_encrypted_block(inode, start_bidx);
+ else
+ move_data_page(inode, start_bidx, gc_type);
stat_inc_data_blk_count(sbi, 1, gc_type);
}
}