f2fs crypto: add encryption support in read/write paths
[deliverable/linux.git] / fs / f2fs / inline.c
index 1484c00133cd8e9fe2492c0ee955b7c587c19f97..b0b7805028365485a941c0113bdb4b28caa59b8a 100644 (file)
@@ -13,7 +13,7 @@
 
 #include "f2fs.h"
 
-bool f2fs_may_inline(struct inode *inode)
+bool f2fs_may_inline_data(struct inode *inode)
 {
        if (!test_opt(F2FS_I_SB(inode), INLINE_DATA))
                return false;
@@ -21,12 +21,26 @@ bool f2fs_may_inline(struct inode *inode)
        if (f2fs_is_atomic_file(inode))
                return false;
 
-       if (!S_ISREG(inode->i_mode))
+       if (!S_ISREG(inode->i_mode) && !S_ISLNK(inode->i_mode))
                return false;
 
        if (i_size_read(inode) > MAX_INLINE_DATA)
                return false;
 
+       if (f2fs_encrypted_inode(inode) && S_ISREG(inode->i_mode))
+               return false;
+
+       return true;
+}
+
+bool f2fs_may_inline_dentry(struct inode *inode)
+{
+       if (!test_opt(F2FS_I_SB(inode), INLINE_DENTRY))
+               return false;
+
+       if (!S_ISDIR(inode->i_mode))
+               return false;
+
        return true;
 }
 
@@ -50,10 +64,19 @@ void read_inline_data(struct page *page, struct page *ipage)
        SetPageUptodate(page);
 }
 
-static void truncate_inline_data(struct page *ipage)
+bool truncate_inline_inode(struct page *ipage, u64 from)
 {
+       void *addr;
+
+       if (from >= MAX_INLINE_DATA)
+               return false;
+
+       addr = inline_data_addr(ipage);
+
        f2fs_wait_on_page_writeback(ipage, NODE);
-       memset(inline_data_addr(ipage), 0, MAX_INLINE_DATA);
+       memset(addr + from, 0, MAX_INLINE_DATA - from);
+
+       return true;
 }
 
 int f2fs_read_inline_data(struct inode *inode, struct page *page)
@@ -86,8 +109,11 @@ int f2fs_convert_inline_page(struct dnode_of_data *dn, struct page *page)
 {
        void *src_addr, *dst_addr;
        struct f2fs_io_info fio = {
+               .sbi = F2FS_I_SB(dn->inode),
                .type = DATA,
                .rw = WRITE_SYNC | REQ_PRIO,
+               .page = page,
+               .encrypted_page = NULL,
        };
        int dirty, err;
 
@@ -121,8 +147,9 @@ no_update:
        /* write data page to try to make data consistent */
        set_page_writeback(page);
        fio.blk_addr = dn->data_blkaddr;
-       write_data_page(page, dn, &fio);
-       update_extent_cache(dn);
+       write_data_page(dn, &fio);
+       set_data_blkaddr(dn);
+       f2fs_update_extent_cache(dn);
        f2fs_wait_on_page_writeback(page, DATA);
        if (dirty)
                inode_dec_dirty_pages(dn->inode);
@@ -131,7 +158,7 @@ no_update:
        set_inode_flag(F2FS_I(dn->inode), FI_APPEND_WRITE);
 
        /* clear inline data and flag after data writeback */
-       truncate_inline_data(dn->inode_page);
+       truncate_inline_inode(dn->inode_page, 0);
 clear_out:
        stat_dec_inline_inode(dn->inode);
        f2fs_clear_inline_inode(dn->inode);
@@ -245,7 +272,7 @@ process_inline:
        if (f2fs_has_inline_data(inode)) {
                ipage = get_node_page(sbi, inode->i_ino);
                f2fs_bug_on(sbi, IS_ERR(ipage));
-               truncate_inline_data(ipage);
+               truncate_inline_inode(ipage, 0);
                f2fs_clear_inline_inode(inode);
                update_inode(inode, ipage);
                f2fs_put_page(ipage, 1);
@@ -363,7 +390,7 @@ static int f2fs_convert_inline_dir(struct inode *dir, struct page *ipage,
        set_page_dirty(page);
 
        /* clear inline dir and flag after data writeback */
-       truncate_inline_data(ipage);
+       truncate_inline_inode(ipage, 0);
 
        stat_dec_inline_dir(dir);
        clear_inode_flag(F2FS_I(dir), FI_INLINE_DENTRY);
@@ -380,21 +407,18 @@ out:
 }
 
 int f2fs_add_inline_entry(struct inode *dir, const struct qstr *name,
-                                               struct inode *inode)
+                       struct inode *inode, nid_t ino, umode_t mode)
 {
        struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
        struct page *ipage;
        unsigned int bit_pos;
        f2fs_hash_t name_hash;
-       struct f2fs_dir_entry *de;
        size_t namelen = name->len;
        struct f2fs_inline_dentry *dentry_blk = NULL;
+       struct f2fs_dentry_ptr d;
        int slots = GET_DENTRY_SLOTS(namelen);
-       struct page *page;
+       struct page *page = NULL;
        int err = 0;
-       int i;
-
-       name_hash = f2fs_dentry_hash(name);
 
        ipage = get_node_page(sbi, dir->i_ino);
        if (IS_ERR(ipage))
@@ -410,32 +434,34 @@ int f2fs_add_inline_entry(struct inode *dir, const struct qstr *name,
                goto out;
        }
 
-       down_write(&F2FS_I(inode)->i_sem);
-       page = init_inode_metadata(inode, dir, name, ipage);
-       if (IS_ERR(page)) {
-               err = PTR_ERR(page);
-               goto fail;
+       if (inode) {
+               down_write(&F2FS_I(inode)->i_sem);
+               page = init_inode_metadata(inode, dir, name, ipage);
+               if (IS_ERR(page)) {
+                       err = PTR_ERR(page);
+                       goto fail;
+               }
        }
 
        f2fs_wait_on_page_writeback(ipage, NODE);
-       de = &dentry_blk->dentry[bit_pos];
-       de->hash_code = name_hash;
-       de->name_len = cpu_to_le16(namelen);
-       memcpy(dentry_blk->filename[bit_pos], name->name, name->len);
-       de->ino = cpu_to_le32(inode->i_ino);
-       set_de_type(de, inode);
-       for (i = 0; i < slots; i++)
-               test_and_set_bit_le(bit_pos + i, &dentry_blk->dentry_bitmap);
+
+       name_hash = f2fs_dentry_hash(name);
+       make_dentry_ptr(&d, (void *)dentry_blk, 2);
+       f2fs_update_dentry(ino, mode, &d, name, name_hash, bit_pos);
+
        set_page_dirty(ipage);
 
        /* we don't need to mark_inode_dirty now */
-       F2FS_I(inode)->i_pino = dir->i_ino;
-       update_inode(inode, page);
-       f2fs_put_page(page, 1);
+       if (inode) {
+               F2FS_I(inode)->i_pino = dir->i_ino;
+               update_inode(inode, page);
+               f2fs_put_page(page, 1);
+       }
 
        update_parent_metadata(dir, inode, 0);
 fail:
-       up_write(&F2FS_I(inode)->i_sem);
+       if (inode)
+               up_write(&F2FS_I(inode)->i_sem);
 
        if (is_inode_flag_set(F2FS_I(dir), FI_UPDATE_DIR)) {
                update_inode(dir, ipage);
This page took 0.042211 seconds and 5 git commands to generate.