Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
[deliverable/linux.git] / fs / f2fs / file.c
index ea272be62677004d29c8018691ea442c2c992bb1..b41c3579ea9e859bd692127e30c1b998e4346fb9 100644 (file)
@@ -86,7 +86,7 @@ static int f2fs_vm_page_mkwrite(struct vm_area_struct *vma,
        trace_f2fs_vm_page_mkwrite(page, DATA);
 mapped:
        /* fill the page */
-       f2fs_wait_on_page_writeback(page, DATA);
+       f2fs_wait_on_page_writeback(page, DATA, false);
 
        /* wait for GCed encrypted page writeback */
        if (f2fs_encrypted_inode(inode) && S_ISREG(inode->i_mode))
@@ -301,7 +301,7 @@ static pgoff_t __get_first_dirty_index(struct address_space *mapping,
        pagevec_init(&pvec, 0);
        nr_pages = pagevec_lookup_tag(&pvec, mapping, &pgofs,
                                        PAGECACHE_TAG_DIRTY, 1);
-       pgofs = nr_pages ? pvec.pages[0]->index : LONG_MAX;
+       pgofs = nr_pages ? pvec.pages[0]->index : ULONG_MAX;
        pagevec_release(&pvec);
        return pgofs;
 }
@@ -358,15 +358,14 @@ static loff_t f2fs_seek_block(struct file *file, loff_t offset, int whence)
                } else if (err == -ENOENT) {
                        /* direct node does not exists */
                        if (whence == SEEK_DATA) {
-                               pgofs = PGOFS_OF_NEXT_DNODE(pgofs,
-                                                       F2FS_I(inode));
+                               pgofs = get_next_page_offset(&dn, pgofs);
                                continue;
                        } else {
                                goto found;
                        }
                }
 
-               end_offset = ADDRS_PER_PAGE(dn.node_page, F2FS_I(inode));
+               end_offset = ADDRS_PER_PAGE(dn.node_page, inode);
 
                /* find data/hole in dnode block */
                for (; dn.ofs_in_node < end_offset;
@@ -422,9 +421,11 @@ static int f2fs_file_mmap(struct file *file, struct vm_area_struct *vma)
        int err;
 
        if (f2fs_encrypted_inode(inode)) {
-               err = f2fs_get_encryption_info(inode);
+               err = fscrypt_get_encryption_info(inode);
                if (err)
                        return 0;
+               if (!f2fs_encrypted_inode(inode))
+                       return -ENOKEY;
        }
 
        /* we don't need to use inline_data strictly */
@@ -440,12 +441,18 @@ static int f2fs_file_mmap(struct file *file, struct vm_area_struct *vma)
 static int f2fs_file_open(struct inode *inode, struct file *filp)
 {
        int ret = generic_file_open(inode, filp);
+       struct inode *dir = filp->f_path.dentry->d_parent->d_inode;
 
        if (!ret && f2fs_encrypted_inode(inode)) {
-               ret = f2fs_get_encryption_info(inode);
+               ret = fscrypt_get_encryption_info(inode);
                if (ret)
-                       ret = -EACCES;
+                       return -EACCES;
+               if (!fscrypt_has_encryption_key(inode))
+                       return -ENOKEY;
        }
+       if (f2fs_encrypted_inode(dir) &&
+                       !fscrypt_has_permitted_context(dir, inode))
+               return -EPERM;
        return ret;
 }
 
@@ -480,7 +487,7 @@ int truncate_data_blocks_range(struct dnode_of_data *dn, int count)
                 * we will invalidate all blkaddr in the whole range.
                 */
                fofs = start_bidx_of_node(ofs_of_node(dn->node_page),
-                                               F2FS_I(dn->inode)) + ofs;
+                                                       dn->inode) + ofs;
                f2fs_update_extent_cache_range(dn, fofs, 0, len);
                dec_valid_block_count(sbi, dn->inode, nr_free);
                sync_inode_page(dn);
@@ -521,9 +528,10 @@ static int truncate_partial_data_page(struct inode *inode, u64 from,
        if (IS_ERR(page))
                return 0;
 truncate_out:
-       f2fs_wait_on_page_writeback(page, DATA);
+       f2fs_wait_on_page_writeback(page, DATA, true);
        zero_user(page, offset, PAGE_CACHE_SIZE - offset);
-       if (!cache_only || !f2fs_encrypted_inode(inode) || !S_ISREG(inode->i_mode))
+       if (!cache_only || !f2fs_encrypted_inode(inode) ||
+                                       !S_ISREG(inode->i_mode))
                set_page_dirty(page);
        f2fs_put_page(page, 1);
        return 0;
@@ -568,7 +576,7 @@ int truncate_blocks(struct inode *inode, u64 from, bool lock)
                goto out;
        }
 
-       count = ADDRS_PER_PAGE(dn.node_page, F2FS_I(inode));
+       count = ADDRS_PER_PAGE(dn.node_page, inode);
 
        count -= dn.ofs_in_node;
        f2fs_bug_on(sbi, count < 0);
@@ -671,7 +679,7 @@ int f2fs_setattr(struct dentry *dentry, struct iattr *attr)
 
        if (attr->ia_valid & ATTR_SIZE) {
                if (f2fs_encrypted_inode(inode) &&
-                               f2fs_get_encryption_info(inode))
+                               fscrypt_get_encryption_info(inode))
                        return -EACCES;
 
                if (attr->ia_size <= i_size_read(inode)) {
@@ -743,7 +751,7 @@ static int fill_zero(struct inode *inode, pgoff_t index,
        if (IS_ERR(page))
                return PTR_ERR(page);
 
-       f2fs_wait_on_page_writeback(page, DATA);
+       f2fs_wait_on_page_writeback(page, DATA, true);
        zero_user(page, start, len);
        set_page_dirty(page);
        f2fs_put_page(page, 1);
@@ -768,7 +776,7 @@ int truncate_hole(struct inode *inode, pgoff_t pg_start, pgoff_t pg_end)
                        return err;
                }
 
-               end_offset = ADDRS_PER_PAGE(dn.node_page, F2FS_I(inode));
+               end_offset = ADDRS_PER_PAGE(dn.node_page, inode);
                count = min(end_offset - dn.ofs_in_node, pg_end - pg_start);
 
                f2fs_bug_on(F2FS_I_SB(inode), count == 0 || count > end_offset);
@@ -854,10 +862,8 @@ static int __exchange_data_block(struct inode *inode, pgoff_t src,
        } else {
                new_addr = dn.data_blkaddr;
                if (!is_checkpointed_data(sbi, new_addr)) {
-                       dn.data_blkaddr = NULL_ADDR;
                        /* do not invalidate this block address */
-                       set_data_blkaddr(&dn);
-                       f2fs_update_extent_cache(&dn);
+                       f2fs_update_data_blkaddr(&dn, NULL_ADDR);
                        do_replace = true;
                }
                f2fs_put_dnode(&dn);
@@ -884,7 +890,7 @@ static int __exchange_data_block(struct inode *inode, pgoff_t src,
 
                get_node_info(sbi, dn.nid, &ni);
                f2fs_replace_block(sbi, &dn, dn.data_blkaddr, new_addr,
-                               ni.version, true);
+                               ni.version, true, false);
                f2fs_put_dnode(&dn);
        } else {
                struct page *psrc, *pdst;
@@ -892,7 +898,7 @@ static int __exchange_data_block(struct inode *inode, pgoff_t src,
                psrc = get_lock_data_page(inode, src, true);
                if (IS_ERR(psrc))
                        return PTR_ERR(psrc);
-               pdst = get_new_data_page(inode, NULL, dst, false);
+               pdst = get_new_data_page(inode, NULL, dst, true);
                if (IS_ERR(pdst)) {
                        f2fs_put_page(psrc, 1);
                        return PTR_ERR(pdst);
@@ -908,9 +914,7 @@ static int __exchange_data_block(struct inode *inode, pgoff_t src,
 
 err_out:
        if (!get_dnode_of_data(&dn, src, LOOKUP_NODE)) {
-               dn.data_blkaddr = new_addr;
-               set_data_blkaddr(&dn);
-               f2fs_update_extent_cache(&dn);
+               f2fs_update_data_blkaddr(&dn, new_addr);
                f2fs_put_dnode(&dn);
        }
        return ret;
@@ -1050,12 +1054,7 @@ static int f2fs_zero_range(struct inode *inode, loff_t offset, loff_t len,
 
                        if (dn.data_blkaddr != NEW_ADDR) {
                                invalidate_blocks(sbi, dn.data_blkaddr);
-
-                               dn.data_blkaddr = NEW_ADDR;
-                               set_data_blkaddr(&dn);
-
-                               dn.data_blkaddr = NULL_ADDR;
-                               f2fs_update_extent_cache(&dn);
+                               f2fs_update_data_blkaddr(&dn, NEW_ADDR);
                        }
                        f2fs_put_dnode(&dn);
                        f2fs_unlock_op(sbi);
@@ -1253,7 +1252,7 @@ static int f2fs_release_file(struct inode *inode, struct file *filp)
 {
        /* some remained atomic pages should discarded */
        if (f2fs_is_atomic_file(inode))
-               commit_inmem_pages(inode, true);
+               drop_inmem_pages(inode);
        if (f2fs_is_volatile_file(inode)) {
                set_inode_flag(F2FS_I(inode), FI_DROP_CACHE);
                filemap_fdatawrite(inode->i_mapping);
@@ -1377,7 +1376,7 @@ static int f2fs_ioc_commit_atomic_write(struct file *filp)
 
        if (f2fs_is_atomic_file(inode)) {
                clear_inode_flag(F2FS_I(inode), FI_ATOMIC_FILE);
-               ret = commit_inmem_pages(inode, false);
+               ret = commit_inmem_pages(inode);
                if (ret) {
                        set_inode_flag(F2FS_I(inode), FI_ATOMIC_FILE);
                        goto err_out;
@@ -1440,7 +1439,7 @@ static int f2fs_ioc_abort_volatile_write(struct file *filp)
 
        if (f2fs_is_atomic_file(inode)) {
                clear_inode_flag(F2FS_I(inode), FI_ATOMIC_FILE);
-               commit_inmem_pages(inode, true);
+               drop_inmem_pages(inode);
        }
        if (f2fs_is_volatile_file(inode)) {
                clear_inode_flag(F2FS_I(inode), FI_VOLATILE_FILE);
@@ -1535,39 +1534,30 @@ static bool uuid_is_nonzero(__u8 u[16])
 
 static int f2fs_ioc_set_encryption_policy(struct file *filp, unsigned long arg)
 {
-#ifdef CONFIG_F2FS_FS_ENCRYPTION
-       struct f2fs_encryption_policy policy;
+       struct fscrypt_policy policy;
        struct inode *inode = file_inode(filp);
 
-       if (copy_from_user(&policy, (struct f2fs_encryption_policy __user *)arg,
-                               sizeof(policy)))
+       if (copy_from_user(&policy, (struct fscrypt_policy __user *)arg,
+                                                       sizeof(policy)))
                return -EFAULT;
 
        f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
-       return f2fs_process_policy(&policy, inode);
-#else
-       return -EOPNOTSUPP;
-#endif
+       return fscrypt_process_policy(inode, &policy);
 }
 
 static int f2fs_ioc_get_encryption_policy(struct file *filp, unsigned long arg)
 {
-#ifdef CONFIG_F2FS_FS_ENCRYPTION
-       struct f2fs_encryption_policy policy;
+       struct fscrypt_policy policy;
        struct inode *inode = file_inode(filp);
        int err;
 
-       err = f2fs_get_policy(inode, &policy);
+       err = fscrypt_get_policy(inode, &policy);
        if (err)
                return err;
 
-       if (copy_to_user((struct f2fs_encryption_policy __user *)arg, &policy,
-                                                       sizeof(policy)))
+       if (copy_to_user((struct fscrypt_policy __user *)arg, &policy, sizeof(policy)))
                return -EFAULT;
        return 0;
-#else
-       return -EOPNOTSUPP;
-#endif
 }
 
 static int f2fs_ioc_get_encryption_pwsalt(struct file *filp, unsigned long arg)
@@ -1648,7 +1638,7 @@ static int f2fs_defragment_range(struct f2fs_sb_info *sbi,
                                        struct f2fs_defragment *range)
 {
        struct inode *inode = file_inode(filp);
-       struct f2fs_map_blocks map;
+       struct f2fs_map_blocks map = { .m_next_pgofs = NULL };
        struct extent_info ei;
        pgoff_t pg_start, pg_end;
        unsigned int blk_per_seg = sbi->blocks_per_seg;
@@ -1874,14 +1864,32 @@ long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 
 static ssize_t f2fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
 {
-       struct inode *inode = file_inode(iocb->ki_filp);
+       struct file *file = iocb->ki_filp;
+       struct inode *inode = file_inode(file);
+       ssize_t ret;
 
        if (f2fs_encrypted_inode(inode) &&
-                               !f2fs_has_encryption_key(inode) &&
-                               f2fs_get_encryption_info(inode))
+                               !fscrypt_has_encryption_key(inode) &&
+                               fscrypt_get_encryption_info(inode))
                return -EACCES;
 
-       return generic_file_write_iter(iocb, from);
+       inode_lock(inode);
+       ret = generic_write_checks(iocb, from);
+       if (ret > 0) {
+               ret = f2fs_preallocate_blocks(iocb, from);
+               if (!ret)
+                       ret = __generic_file_write_iter(iocb, from);
+       }
+       inode_unlock(inode);
+
+       if (ret > 0) {
+               ssize_t err;
+
+               err = generic_write_sync(file, iocb->ki_pos - ret, ret);
+               if (err < 0)
+                       ret = err;
+       }
+       return ret;
 }
 
 #ifdef CONFIG_COMPAT
This page took 0.029918 seconds and 5 git commands to generate.