Merge 4.14.86 into android-4.14-p
[GitHub/moto-9609/android_kernel_motorola_exynos9610.git] / fs / f2fs / file.c
index 1d6a862bd25f1d61709c50558539adf21866a00f..9de30472643aaba7de433b62f000c9c934f94254 100644 (file)
@@ -110,8 +110,8 @@ mapped:
        /* fill the page */
        f2fs_wait_on_page_writeback(page, DATA, false);
 
-       /* wait for GCed encrypted page writeback */
-       if (f2fs_encrypted_file(inode))
+       /* wait for GCed page writeback via META_MAPPING */
+       if (f2fs_post_read_required(inode))
                f2fs_wait_on_block_writeback(sbi, dn.data_blkaddr);
 
 out_sem:
@@ -163,9 +163,10 @@ static inline enum cp_reason_type need_do_checkpoint(struct inode *inode)
                cp_reason = CP_NODE_NEED_CP;
        else if (test_opt(sbi, FASTBOOT))
                cp_reason = CP_FASTBOOT_MODE;
-       else if (sbi->active_logs == 2)
+       else if (F2FS_OPTION(sbi).active_logs == 2)
                cp_reason = CP_SPEC_LOG_NUM;
-       else if (need_dentry_mark(sbi, inode->i_ino) &&
+       else if (F2FS_OPTION(sbi).fsync_mode == FSYNC_MODE_STRICT &&
+               need_dentry_mark(sbi, inode->i_ino) &&
                exist_written_data(sbi, F2FS_I(inode)->i_pino, TRANS_DIR_INO))
                cp_reason = CP_RECOVER_DIR;
 
@@ -305,7 +306,7 @@ sync_nodes:
        remove_ino_entry(sbi, ino, APPEND_INO);
        clear_inode_flag(inode, FI_APPEND_WRITE);
 flush_out:
-       if (!atomic)
+       if (!atomic && F2FS_OPTION(sbi).fsync_mode != FSYNC_MODE_NOBARRIER)
                ret = f2fs_issue_flush(sbi, inode->i_ino);
        if (!ret) {
                remove_ino_entry(sbi, ino, UPDATE_INO);
@@ -344,13 +345,13 @@ static pgoff_t __get_first_dirty_index(struct address_space *mapping,
        return pgofs;
 }
 
-static bool __found_offset(block_t blkaddr, pgoff_t dirty, pgoff_t pgofs,
-                                                       int whence)
+static bool __found_offset(struct f2fs_sb_info *sbi, block_t blkaddr,
+                               pgoff_t dirty, pgoff_t pgofs, int whence)
 {
        switch (whence) {
        case SEEK_DATA:
                if ((blkaddr == NEW_ADDR && dirty == pgofs) ||
-                       (blkaddr != NEW_ADDR && blkaddr != NULL_ADDR))
+                       is_valid_data_blkaddr(sbi, blkaddr))
                        return true;
                break;
        case SEEK_HOLE:
@@ -413,7 +414,15 @@ static loff_t f2fs_seek_block(struct file *file, loff_t offset, int whence)
                        blkaddr = datablock_addr(dn.inode,
                                        dn.node_page, dn.ofs_in_node);
 
-                       if (__found_offset(blkaddr, dirty, pgofs, whence)) {
+                       if (__is_valid_data_blkaddr(blkaddr) &&
+                               !f2fs_is_valid_blkaddr(F2FS_I_SB(inode),
+                                               blkaddr, DATA_GENERIC)) {
+                               f2fs_put_dnode(&dn);
+                               goto fail;
+                       }
+
+                       if (__found_offset(F2FS_I_SB(inode), blkaddr, dirty,
+                                                       pgofs, whence)) {
                                f2fs_put_dnode(&dn);
                                goto found;
                        }
@@ -478,6 +487,9 @@ static int f2fs_file_open(struct inode *inode, struct file *filp)
 
        if (err)
                return err;
+
+       filp->f_mode |= FMODE_NOWAIT;
+
        return dquot_file_open(inode, filp);
 }
 
@@ -502,6 +514,11 @@ void truncate_data_blocks_range(struct dnode_of_data *dn, int count)
 
                dn->data_blkaddr = NULL_ADDR;
                set_data_blkaddr(dn);
+
+               if (__is_valid_data_blkaddr(blkaddr) &&
+                       !f2fs_is_valid_blkaddr(sbi, blkaddr, DATA_GENERIC))
+                       continue;
+
                invalidate_blocks(sbi, blkaddr);
                if (dn->ofs_in_node == 0 && IS_INODE(dn->node_page))
                        clear_inode_flag(dn->inode, FI_FIRST_BLOCK_WRITTEN);
@@ -568,7 +585,6 @@ truncate_out:
 int truncate_blocks(struct inode *inode, u64 from, bool lock)
 {
        struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
-       unsigned int blocksize = inode->i_sb->s_blocksize;
        struct dnode_of_data dn;
        pgoff_t free_from;
        int count = 0, err = 0;
@@ -577,7 +593,7 @@ int truncate_blocks(struct inode *inode, u64 from, bool lock)
 
        trace_f2fs_truncate_blocks_enter(inode, from);
 
-       free_from = (pgoff_t)F2FS_BYTES_TO_BLK(from + blocksize - 1);
+       free_from = (pgoff_t)F2FS_BLK_ALIGN(from);
 
        if (free_from >= sbi->max_file_blocks)
                goto free_partial;
@@ -1347,8 +1363,12 @@ static int f2fs_zero_range(struct inode *inode, loff_t offset, loff_t len,
        }
 
 out:
-       if (!(mode & FALLOC_FL_KEEP_SIZE) && i_size_read(inode) < new_size)
-               f2fs_i_size_write(inode, new_size);
+       if (new_size > i_size_read(inode)) {
+               if (mode & FALLOC_FL_KEEP_SIZE)
+                       file_set_keep_isize(inode);
+               else
+                       f2fs_i_size_write(inode, new_size);
+       }
 out_sem:
        up_write(&F2FS_I(inode)->i_mmap_sem);
 
@@ -1662,6 +1682,8 @@ static int f2fs_ioc_start_atomic_write(struct file *filp)
 
        inode_lock(inode);
 
+       down_write(&F2FS_I(inode)->dio_rwsem[WRITE]);
+
        if (f2fs_is_atomic_file(inode))
                goto out;
 
@@ -1691,6 +1713,7 @@ inc_stat:
        stat_inc_atomic_write(inode);
        stat_update_max_atomic_write(inode);
 out:
+       up_write(&F2FS_I(inode)->dio_rwsem[WRITE]);
        inode_unlock(inode);
        mnt_drop_write_file(filp);
        return ret;
@@ -1710,6 +1733,8 @@ static int f2fs_ioc_commit_atomic_write(struct file *filp)
 
        inode_lock(inode);
 
+       down_write(&F2FS_I(inode)->dio_rwsem[WRITE]);
+
        if (f2fs_is_volatile_file(inode))
                goto err_out;
 
@@ -1728,6 +1753,7 @@ static int f2fs_ioc_commit_atomic_write(struct file *filp)
                ret = f2fs_do_sync_file(filp, 0, LLONG_MAX, 1, false);
        }
 err_out:
+       up_write(&F2FS_I(inode)->dio_rwsem[WRITE]);
        inode_unlock(inode);
        mnt_drop_write_file(filp);
        return ret;
@@ -1832,7 +1858,7 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg)
        struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
        struct super_block *sb = sbi->sb;
        __u32 in;
-       int ret;
+       int ret = 0;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
@@ -1840,9 +1866,11 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg)
        if (get_user(in, (__u32 __user *)arg))
                return -EFAULT;
 
-       ret = mnt_want_write_file(filp);
-       if (ret)
-               return ret;
+       if (in != F2FS_GOING_DOWN_FULLSYNC) {
+               ret = mnt_want_write_file(filp);
+               if (ret)
+                       return ret;
+       }
 
        switch (in) {
        case F2FS_GOING_DOWN_FULLSYNC:
@@ -1883,7 +1911,8 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg)
 
        f2fs_update_time(sbi, REQ_TIME);
 out:
-       mnt_drop_write_file(filp);
+       if (in != F2FS_GOING_DOWN_FULLSYNC)
+               mnt_drop_write_file(filp);
        return ret;
 }
 
@@ -1937,7 +1966,7 @@ static int f2fs_ioc_set_encryption_policy(struct file *filp, unsigned long arg)
 {
        struct inode *inode = file_inode(filp);
 
-       if (!f2fs_sb_has_crypto(inode->i_sb))
+       if (!f2fs_sb_has_encrypt(inode->i_sb))
                return -EOPNOTSUPP;
 
        f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
@@ -1947,7 +1976,7 @@ static int f2fs_ioc_set_encryption_policy(struct file *filp, unsigned long arg)
 
 static int f2fs_ioc_get_encryption_policy(struct file *filp, unsigned long arg)
 {
-       if (!f2fs_sb_has_crypto(file_inode(filp)->i_sb))
+       if (!f2fs_sb_has_encrypt(file_inode(filp)->i_sb))
                return -EOPNOTSUPP;
        return fscrypt_ioctl_get_policy(filp, (void __user *)arg);
 }
@@ -1958,16 +1987,18 @@ static int f2fs_ioc_get_encryption_pwsalt(struct file *filp, unsigned long arg)
        struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
        int err;
 
-       if (!f2fs_sb_has_crypto(inode->i_sb))
+       if (!f2fs_sb_has_encrypt(inode->i_sb))
                return -EOPNOTSUPP;
 
-       if (uuid_is_nonzero(sbi->raw_super->encrypt_pw_salt))
-               goto got_it;
-
        err = mnt_want_write_file(filp);
        if (err)
                return err;
 
+       down_write(&sbi->sb_lock);
+
+       if (uuid_is_nonzero(sbi->raw_super->encrypt_pw_salt))
+               goto got_it;
+
        /* update superblock with uuid */
        generate_random_uuid(sbi->raw_super->encrypt_pw_salt);
 
@@ -1975,15 +2006,16 @@ static int f2fs_ioc_get_encryption_pwsalt(struct file *filp, unsigned long arg)
        if (err) {
                /* undo new data */
                memset(sbi->raw_super->encrypt_pw_salt, 0, 16);
-               mnt_drop_write_file(filp);
-               return err;
+               goto out_err;
        }
-       mnt_drop_write_file(filp);
 got_it:
        if (copy_to_user((__u8 __user *)arg, sbi->raw_super->encrypt_pw_salt,
                                                                        16))
-               return -EFAULT;
-       return 0;
+               err = -EFAULT;
+out_err:
+       up_write(&sbi->sb_lock);
+       mnt_drop_write_file(filp);
+       return err;
 }
 
 static int f2fs_ioc_gc(struct file *filp, unsigned long arg)
@@ -2044,8 +2076,10 @@ static int f2fs_ioc_gc_range(struct file *filp, unsigned long arg)
                return ret;
 
        end = range.start + range.len;
-       if (range.start < MAIN_BLKADDR(sbi) || end >= MAX_BLKADDR(sbi))
-               return -EINVAL;
+       if (range.start < MAIN_BLKADDR(sbi) || end >= MAX_BLKADDR(sbi)) {
+               ret = -EINVAL;
+               goto out;
+       }
 do_more:
        if (!range.sync) {
                if (!mutex_trylock(&sbi->gc_mutex)) {
@@ -2552,7 +2586,9 @@ static int f2fs_ioc_setproject(struct file *filp, __u32 projid)
        }
        f2fs_put_page(ipage, 1);
 
-       dquot_initialize(inode);
+       err = dquot_initialize(inode);
+       if (err)
+               goto out_unlock;
 
        transfer_to[PRJQUOTA] = dqget(sb, make_kqid_projid(kprojid));
        if (!IS_ERR(transfer_to[PRJQUOTA])) {
@@ -2884,25 +2920,54 @@ static ssize_t f2fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
        if (unlikely(f2fs_cp_error(F2FS_I_SB(inode))))
                return -EIO;
 
-       inode_lock(inode);
+       if ((iocb->ki_flags & IOCB_NOWAIT) && !(iocb->ki_flags & IOCB_DIRECT))
+               return -EINVAL;
+
+       if (!inode_trylock(inode)) {
+               if (iocb->ki_flags & IOCB_NOWAIT)
+                       return -EAGAIN;
+               inode_lock(inode);
+       }
+
        ret = generic_write_checks(iocb, from);
        if (ret > 0) {
+               bool preallocated = false;
+               size_t target_size = 0;
                int err;
 
                if (iov_iter_fault_in_readable(from, iov_iter_count(from)))
                        set_inode_flag(inode, FI_NO_PREALLOC);
 
-               err = f2fs_preallocate_blocks(iocb, from);
-               if (err) {
-                       clear_inode_flag(inode, FI_NO_PREALLOC);
-                       inode_unlock(inode);
-                       return err;
+               if ((iocb->ki_flags & IOCB_NOWAIT) &&
+                       (iocb->ki_flags & IOCB_DIRECT)) {
+                               if (!f2fs_overwrite_io(inode, iocb->ki_pos,
+                                               iov_iter_count(from)) ||
+                                       f2fs_has_inline_data(inode) ||
+                                       f2fs_force_buffered_io(inode, WRITE)) {
+                                               inode_unlock(inode);
+                                               return -EAGAIN;
+                               }
+
+               } else {
+                       preallocated = true;
+                       target_size = iocb->ki_pos + iov_iter_count(from);
+
+                       err = f2fs_preallocate_blocks(iocb, from);
+                       if (err) {
+                               clear_inode_flag(inode, FI_NO_PREALLOC);
+                               inode_unlock(inode);
+                               return err;
+                       }
                }
                blk_start_plug(&plug);
                ret = __generic_file_write_iter(iocb, from);
                blk_finish_plug(&plug);
                clear_inode_flag(inode, FI_NO_PREALLOC);
 
+               /* if we couldn't write data, we should deallocate blocks. */
+               if (preallocated && i_size_read(inode) < target_size)
+                       f2fs_truncate(inode);
+
                if (ret > 0)
                        f2fs_update_iostat(F2FS_I_SB(inode), APP_WRITE_IO, ret);
        }