Merge tag 'fscrypt_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso...
[linux-2.6-block.git] / fs / f2fs / namei.c
index c4c94c7e9f4fb332a6684d4d46b1efb232d27742..b68e7b03959f5b7cc67d2b6f9b94715d517fac14 100644 (file)
@@ -486,27 +486,16 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry,
        struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
        struct inode *inode;
        size_t len = strlen(symname);
-       struct fscrypt_str disk_link = FSTR_INIT((char *)symname, len + 1);
-       struct fscrypt_symlink_data *sd = NULL;
+       struct fscrypt_str disk_link;
        int err;
 
        if (unlikely(f2fs_cp_error(sbi)))
                return -EIO;
 
-       if (f2fs_encrypted_inode(dir)) {
-               err = fscrypt_get_encryption_info(dir);
-               if (err)
-                       return err;
-
-               if (!fscrypt_has_encryption_key(dir))
-                       return -ENOKEY;
-
-               disk_link.len = (fscrypt_fname_encrypted_size(dir, len) +
-                               sizeof(struct fscrypt_symlink_data));
-       }
-
-       if (disk_link.len > dir->i_sb->s_blocksize)
-               return -ENAMETOOLONG;
+       err = fscrypt_prepare_symlink(dir, symname, len, dir->i_sb->s_blocksize,
+                                     &disk_link);
+       if (err)
+               return err;
 
        err = dquot_initialize(dir);
        if (err)
@@ -516,7 +505,7 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry,
        if (IS_ERR(inode))
                return PTR_ERR(inode);
 
-       if (f2fs_encrypted_inode(inode))
+       if (IS_ENCRYPTED(inode))
                inode->i_op = &f2fs_encrypted_symlink_inode_operations;
        else
                inode->i_op = &f2fs_symlink_inode_operations;
@@ -526,38 +515,13 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry,
        f2fs_lock_op(sbi);
        err = f2fs_add_link(dentry, inode);
        if (err)
-               goto out;
+               goto out_handle_failed_inode;
        f2fs_unlock_op(sbi);
        alloc_nid_done(sbi, inode->i_ino);
 
-       if (f2fs_encrypted_inode(inode)) {
-               struct qstr istr = QSTR_INIT(symname, len);
-               struct fscrypt_str ostr;
-
-               sd = f2fs_kzalloc(sbi, disk_link.len, GFP_NOFS);
-               if (!sd) {
-                       err = -ENOMEM;
-                       goto err_out;
-               }
-
-               err = fscrypt_get_encryption_info(inode);
-               if (err)
-                       goto err_out;
-
-               if (!fscrypt_has_encryption_key(inode)) {
-                       err = -ENOKEY;
-                       goto err_out;
-               }
-
-               ostr.name = sd->encrypted_path;
-               ostr.len = disk_link.len;
-               err = fscrypt_fname_usr_to_disk(inode, &istr, &ostr);
-               if (err)
-                       goto err_out;
-
-               sd->len = cpu_to_le16(ostr.len);
-               disk_link.name = (char *)sd;
-       }
+       err = fscrypt_encrypt_symlink(inode, symname, len, &disk_link);
+       if (err)
+               goto err_out;
 
        err = page_symlink(inode, disk_link.name, disk_link.len);
 
@@ -584,12 +548,14 @@ err_out:
                f2fs_unlink(dir, dentry);
        }
 
-       kfree(sd);
-
        f2fs_balance_fs(sbi, true);
-       return err;
-out:
+       goto out_free_encrypted_link;
+
+out_handle_failed_inode:
        handle_failed_inode(inode);
+out_free_encrypted_link:
+       if (disk_link.name != (unsigned char *)symname)
+               kfree(disk_link.name);
        return err;
 }
 
@@ -1148,68 +1114,20 @@ static const char *f2fs_encrypted_get_link(struct dentry *dentry,
                                           struct inode *inode,
                                           struct delayed_call *done)
 {
-       struct page *cpage = NULL;
-       char *caddr, *paddr = NULL;
-       struct fscrypt_str cstr = FSTR_INIT(NULL, 0);
-       struct fscrypt_str pstr = FSTR_INIT(NULL, 0);
-       struct fscrypt_symlink_data *sd;
-       u32 max_size = inode->i_sb->s_blocksize;
-       int res;
+       struct page *page;
+       const char *target;
 
        if (!dentry)
                return ERR_PTR(-ECHILD);
 
-       res = fscrypt_get_encryption_info(inode);
-       if (res)
-               return ERR_PTR(res);
-
-       cpage = read_mapping_page(inode->i_mapping, 0, NULL);
-       if (IS_ERR(cpage))
-               return ERR_CAST(cpage);
-       caddr = page_address(cpage);
-
-       /* Symlink is encrypted */
-       sd = (struct fscrypt_symlink_data *)caddr;
-       cstr.name = sd->encrypted_path;
-       cstr.len = le16_to_cpu(sd->len);
-
-       /* this is broken symlink case */
-       if (unlikely(cstr.len == 0)) {
-               res = -ENOENT;
-               goto errout;
-       }
-
-       if ((cstr.len + sizeof(struct fscrypt_symlink_data) - 1) > max_size) {
-               /* Symlink data on the disk is corrupted */
-               res = -EIO;
-               goto errout;
-       }
-       res = fscrypt_fname_alloc_buffer(inode, cstr.len, &pstr);
-       if (res)
-               goto errout;
-
-       res = fscrypt_fname_disk_to_usr(inode, 0, 0, &cstr, &pstr);
-       if (res)
-               goto errout;
-
-       /* this is broken symlink case */
-       if (unlikely(pstr.name[0] == 0)) {
-               res = -ENOENT;
-               goto errout;
-       }
-
-       paddr = pstr.name;
-
-       /* Null-terminate the name */
-       paddr[pstr.len] = '\0';
+       page = read_mapping_page(inode->i_mapping, 0, NULL);
+       if (IS_ERR(page))
+               return ERR_CAST(page);
 
-       put_page(cpage);
-       set_delayed_call(done, kfree_link, paddr);
-       return paddr;
-errout:
-       fscrypt_fname_free_buffer(&pstr);
-       put_page(cpage);
-       return ERR_PTR(res);
+       target = fscrypt_get_symlink(inode, page_address(page),
+                                    inode->i_sb->s_blocksize, done);
+       put_page(page);
+       return target;
 }
 
 const struct inode_operations f2fs_encrypted_symlink_inode_operations = {