Merge tag 'for-f2fs-4.2' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 25 Jun 2015 03:38:29 +0000 (20:38 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 25 Jun 2015 03:38:29 +0000 (20:38 -0700)
Pull f2fs updates from Jaegeuk Kim:
 "New features:
   - per-file encryption (e.g., ext4)
   - FALLOC_FL_ZERO_RANGE
   - FALLOC_FL_COLLAPSE_RANGE
   - RENAME_WHITEOUT

  Major enhancement/fixes:
   - recovery broken superblocks
   - enhance f2fs_trim_fs with a discard_map
   - fix a race condition on dentry block allocation
   - fix a deadlock during summary operation
   - fix a missing fiemap result

  .. and many minor bug fixes and clean-ups were done"

* tag 'for-f2fs-4.2' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs: (83 commits)
  f2fs: do not trim preallocated blocks when truncating after i_size
  f2fs crypto: add alloc_bounce_page
  f2fs crypto: fix to handle errors likewise ext4
  f2fs: drop the volatile_write flag only
  f2fs: skip committing valid superblock
  f2fs: setting discard option in parse_options()
  f2fs: fix to return exact trimmed size
  f2fs: support FALLOC_FL_INSERT_RANGE
  f2fs: hide common code in f2fs_replace_block
  f2fs: disable the discard option when device doesn't support
  f2fs crypto: remove alloc_page for bounce_page
  f2fs: fix a deadlock for summary page lock vs. sentry_lock
  f2fs crypto: clean up error handling in f2fs_fname_setup_filename
  f2fs crypto: avoid f2fs_inherit_context for symlink
  f2fs crypto: do not set encryption policy for non-directory by ioctl
  f2fs crypto: allow setting encryption policy once
  f2fs crypto: check context consistent for rename2
  f2fs: avoid duplicated code by reusing f2fs_read_end_io
  f2fs crypto: use per-inode tfm structure
  f2fs: recovering broken superblock during mount
  ...

1  2 
fs/f2fs/namei.c

diff --cc fs/f2fs/namei.c
index 71765d062914a515fc7603843cabd2b456d5a189,83e21a17497745aad4df0cbad71437756da57799..fdbae21ee8fb2ca991c2e37e35b9fdc505eb291a
@@@ -730,53 -916,87 +912,85 @@@ static int f2fs_rename2(struct inode *o
         * VFS has already handled the new dentry existence case,
         * here, we just deal with "RENAME_NOREPLACE" as regular rename.
         */
-       return f2fs_rename(old_dir, old_dentry, new_dir, new_dentry);
+       return f2fs_rename(old_dir, old_dentry, new_dir, new_dentry, flags);
  }
  
- static int f2fs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
+ #ifdef CONFIG_F2FS_FS_ENCRYPTION
 -static void *f2fs_encrypted_follow_link(struct dentry *dentry,
 -                                              struct nameidata *nd)
++static const char *f2fs_encrypted_follow_link(struct dentry *dentry, void **cookie)
  {
-       struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
-       struct inode *inode;
-       int err;
-       inode = f2fs_new_inode(dir, mode);
-       if (IS_ERR(inode))
-               return PTR_ERR(inode);
-       inode->i_op = &f2fs_file_inode_operations;
-       inode->i_fop = &f2fs_file_operations;
-       inode->i_mapping->a_ops = &f2fs_dblock_aops;
-       f2fs_lock_op(sbi);
-       err = acquire_orphan_inode(sbi);
-       if (err)
-               goto out;
-       err = f2fs_do_tmpfile(inode, dir);
-       if (err)
-               goto release_out;
-       /*
-        * add this non-linked tmpfile to orphan list, in this way we could
-        * remove all unused data of tmpfile after abnormal power-off.
-        */
-       add_orphan_inode(sbi, inode->i_ino);
-       f2fs_unlock_op(sbi);
-       alloc_nid_done(sbi, inode->i_ino);
-       stat_inc_inline_inode(inode);
-       d_tmpfile(dentry, inode);
-       unlock_new_inode(inode);
-       return 0;
+       struct page *cpage = NULL;
+       char *caddr, *paddr = NULL;
+       struct f2fs_str cstr;
+       struct f2fs_str pstr = FSTR_INIT(NULL, 0);
+       struct inode *inode = d_inode(dentry);
+       struct f2fs_encrypted_symlink_data *sd;
+       loff_t size = min_t(loff_t, i_size_read(inode), PAGE_SIZE - 1);
+       u32 max_size = inode->i_sb->s_blocksize;
+       int res;
+       res = f2fs_get_encryption_info(inode);
+       if (res)
+               return ERR_PTR(res);
+       cpage = read_mapping_page(inode->i_mapping, 0, NULL);
+       if (IS_ERR(cpage))
 -              return cpage;
++              return ERR_CAST(cpage);
+       caddr = kmap(cpage);
+       caddr[size] = 0;
+       /* Symlink is encrypted */
+       sd = (struct f2fs_encrypted_symlink_data *)caddr;
+       cstr.name = sd->encrypted_path;
+       cstr.len = le16_to_cpu(sd->len);
+       /* this is broken symlink case */
+       if (cstr.name[0] == 0 && cstr.len == 0) {
+               res = -ENOENT;
+               goto errout;
+       }
  
- release_out:
-       release_orphan_inode(sbi);
- out:
-       handle_failed_inode(inode);
-       return err;
+       if ((cstr.len + sizeof(struct f2fs_encrypted_symlink_data) - 1) >
+                                                               max_size) {
+               /* Symlink data on the disk is corrupted */
+               res = -EIO;
+               goto errout;
+       }
+       res = f2fs_fname_crypto_alloc_buffer(inode, cstr.len, &pstr);
+       if (res)
+               goto errout;
+       res = f2fs_fname_disk_to_usr(inode, NULL, &cstr, &pstr);
+       if (res < 0)
+               goto errout;
+       paddr = pstr.name;
+       /* Null-terminate the name */
+       paddr[res] = '\0';
 -      nd_set_link(nd, paddr);
+       kunmap(cpage);
+       page_cache_release(cpage);
 -      return NULL;
++      return *cookie = paddr;
+ errout:
+       f2fs_fname_crypto_free_buffer(&pstr);
+       kunmap(cpage);
+       page_cache_release(cpage);
+       return ERR_PTR(res);
  }
  
+ const struct inode_operations f2fs_encrypted_symlink_inode_operations = {
+       .readlink       = generic_readlink,
+       .follow_link    = f2fs_encrypted_follow_link,
+       .put_link       = kfree_put_link,
+       .getattr        = f2fs_getattr,
+       .setattr        = f2fs_setattr,
+       .setxattr       = generic_setxattr,
+       .getxattr       = generic_getxattr,
+       .listxattr      = f2fs_listxattr,
+       .removexattr    = generic_removexattr,
+ };
+ #endif
  const struct inode_operations f2fs_dir_inode_operations = {
        .create         = f2fs_create,
        .lookup         = f2fs_lookup,