Merge tag 'kvm-ppc-fixes-5.7-1' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-block.git] / fs / f2fs / file.c
index 351762f7784054fea55496b376c3e96f2948b8c9..6ab8f621a3c5a25caa268c55f021488180efb3f2 100644 (file)
@@ -106,13 +106,20 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault *vmf)
                err = f2fs_get_block(&dn, page->index);
                f2fs_put_dnode(&dn);
                __do_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO, false);
-               if (err) {
-                       unlock_page(page);
-                       goto out_sem;
-               }
        }
 
-       /* fill the page */
+#ifdef CONFIG_F2FS_FS_COMPRESSION
+       if (!need_alloc) {
+               set_new_dnode(&dn, inode, NULL, NULL, 0);
+               err = f2fs_get_dnode_of_data(&dn, page->index, LOOKUP_NODE);
+               f2fs_put_dnode(&dn);
+       }
+#endif
+       if (err) {
+               unlock_page(page);
+               goto out_sem;
+       }
+
        f2fs_wait_on_page_writeback(page, DATA, false, true);
 
        /* wait for GCed page writeback via META_MAPPING */
@@ -448,8 +455,7 @@ static loff_t f2fs_seek_block(struct file *file, loff_t offset, int whence)
                                data_ofs = (loff_t)pgofs << PAGE_SHIFT) {
                        block_t blkaddr;
 
-                       blkaddr = datablock_addr(dn.inode,
-                                       dn.node_page, dn.ofs_in_node);
+                       blkaddr = f2fs_data_blkaddr(&dn);
 
                        if (__is_valid_data_blkaddr(blkaddr) &&
                                !f2fs_is_valid_blkaddr(F2FS_I_SB(inode),
@@ -793,6 +799,8 @@ int f2fs_getattr(const struct path *path, struct kstat *stat,
        }
 
        flags = fi->i_flags;
+       if (flags & F2FS_COMPR_FL)
+               stat->attributes |= STATX_ATTR_COMPRESSED;
        if (flags & F2FS_APPEND_FL)
                stat->attributes |= STATX_ATTR_APPEND;
        if (IS_ENCRYPTED(inode))
@@ -804,7 +812,8 @@ int f2fs_getattr(const struct path *path, struct kstat *stat,
        if (IS_VERITY(inode))
                stat->attributes |= STATX_ATTR_VERITY;
 
-       stat->attributes_mask |= (STATX_ATTR_APPEND |
+       stat->attributes_mask |= (STATX_ATTR_COMPRESSED |
+                                 STATX_ATTR_APPEND |
                                  STATX_ATTR_ENCRYPTED |
                                  STATX_ATTR_IMMUTABLE |
                                  STATX_ATTR_NODUMP |
@@ -929,10 +938,10 @@ int f2fs_setattr(struct dentry *dentry, struct iattr *attr)
                if (err)
                        return err;
 
-               down_write(&F2FS_I(inode)->i_sem);
+               spin_lock(&F2FS_I(inode)->i_size_lock);
                inode->i_mtime = inode->i_ctime = current_time(inode);
                F2FS_I(inode)->last_disk_size = i_size_read(inode);
-               up_write(&F2FS_I(inode)->i_sem);
+               spin_unlock(&F2FS_I(inode)->i_size_lock);
        }
 
        __setattr_copy(inode, attr);
@@ -1109,8 +1118,7 @@ next_dnode:
        done = min((pgoff_t)ADDRS_PER_PAGE(dn.node_page, inode) -
                                                        dn.ofs_in_node, len);
        for (i = 0; i < done; i++, blkaddr++, do_replace++, dn.ofs_in_node++) {
-               *blkaddr = datablock_addr(dn.inode,
-                                       dn.node_page, dn.ofs_in_node);
+               *blkaddr = f2fs_data_blkaddr(&dn);
 
                if (__is_valid_data_blkaddr(*blkaddr) &&
                        !f2fs_is_valid_blkaddr(sbi, *blkaddr,
@@ -1121,7 +1129,7 @@ next_dnode:
 
                if (!f2fs_is_checkpointed_data(sbi, *blkaddr)) {
 
-                       if (test_opt(sbi, LFS)) {
+                       if (f2fs_lfs_mode(sbi)) {
                                f2fs_put_dnode(&dn);
                                return -EOPNOTSUPP;
                        }
@@ -1199,8 +1207,7 @@ static int __clone_blkaddrs(struct inode *src_inode, struct inode *dst_inode,
                                ADDRS_PER_PAGE(dn.node_page, dst_inode) -
                                                dn.ofs_in_node, len - i);
                        do {
-                               dn.data_blkaddr = datablock_addr(dn.inode,
-                                               dn.node_page, dn.ofs_in_node);
+                               dn.data_blkaddr = f2fs_data_blkaddr(&dn);
                                f2fs_truncate_data_blocks_range(&dn, 1);
 
                                if (do_replace[i]) {
@@ -1376,8 +1383,7 @@ static int f2fs_do_zero_range(struct dnode_of_data *dn, pgoff_t start,
        int ret;
 
        for (; index < end; index++, dn->ofs_in_node++) {
-               if (datablock_addr(dn->inode, dn->node_page,
-                                       dn->ofs_in_node) == NULL_ADDR)
+               if (f2fs_data_blkaddr(dn) == NULL_ADDR)
                        count++;
        }
 
@@ -1388,8 +1394,7 @@ static int f2fs_do_zero_range(struct dnode_of_data *dn, pgoff_t start,
 
        dn->ofs_in_node = ofs_in_node;
        for (index = start; index < end; index++, dn->ofs_in_node++) {
-               dn->data_blkaddr = datablock_addr(dn->inode,
-                                       dn->node_page, dn->ofs_in_node);
+               dn->data_blkaddr = f2fs_data_blkaddr(dn);
                /*
                 * f2fs_reserve_new_blocks will not guarantee entire block
                 * allocation.
@@ -1787,12 +1792,15 @@ static int f2fs_file_flush(struct file *file, fl_owner_t id)
 static int f2fs_setflags_common(struct inode *inode, u32 iflags, u32 mask)
 {
        struct f2fs_inode_info *fi = F2FS_I(inode);
+       u32 masked_flags = fi->i_flags & mask;
+
+       f2fs_bug_on(F2FS_I_SB(inode), (iflags & ~mask));
 
        /* Is it quota file? Do not allow user to mess with it */
        if (IS_NOQUOTA(inode))
                return -EPERM;
 
-       if ((iflags ^ fi->i_flags) & F2FS_CASEFOLD_FL) {
+       if ((iflags ^ masked_flags) & F2FS_CASEFOLD_FL) {
                if (!f2fs_sb_has_casefold(F2FS_I_SB(inode)))
                        return -EOPNOTSUPP;
                if (!f2fs_empty_dir(inode))
@@ -1806,27 +1814,22 @@ static int f2fs_setflags_common(struct inode *inode, u32 iflags, u32 mask)
                        return -EINVAL;
        }
 
-       if ((iflags ^ fi->i_flags) & F2FS_COMPR_FL) {
-               if (S_ISREG(inode->i_mode) &&
-                       (fi->i_flags & F2FS_COMPR_FL || i_size_read(inode) ||
-                                               F2FS_HAS_BLOCKS(inode)))
-                       return -EINVAL;
+       if ((iflags ^ masked_flags) & F2FS_COMPR_FL) {
+               if (masked_flags & F2FS_COMPR_FL) {
+                       if (f2fs_disable_compressed_file(inode))
+                               return -EINVAL;
+               }
                if (iflags & F2FS_NOCOMP_FL)
                        return -EINVAL;
                if (iflags & F2FS_COMPR_FL) {
-                       int err = f2fs_convert_inline_inode(inode);
-
-                       if (err)
-                               return err;
-
                        if (!f2fs_may_compress(inode))
                                return -EINVAL;
 
                        set_compress_context(inode);
                }
        }
-       if ((iflags ^ fi->i_flags) & F2FS_NOCOMP_FL) {
-               if (fi->i_flags & F2FS_COMPR_FL)
+       if ((iflags ^ masked_flags) & F2FS_NOCOMP_FL) {
+               if (masked_flags & F2FS_COMPR_FL)
                        return -EINVAL;
        }
 
@@ -3401,6 +3404,21 @@ out:
        return err;
 }
 
+static int f2fs_get_compress_blocks(struct file *filp, unsigned long arg)
+{
+       struct inode *inode = file_inode(filp);
+       __u64 blocks;
+
+       if (!f2fs_sb_has_compression(F2FS_I_SB(inode)))
+               return -EOPNOTSUPP;
+
+       if (!f2fs_compressed_file(inode))
+               return -EINVAL;
+
+       blocks = F2FS_I(inode)->i_compr_blocks;
+       return put_user(blocks, (u64 __user *)arg);
+}
+
 long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
        if (unlikely(f2fs_cp_error(F2FS_I_SB(file_inode(filp)))))
@@ -3481,6 +3499,8 @@ long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                return f2fs_get_volume_name(filp, arg);
        case F2FS_IOC_SET_VOLUME_NAME:
                return f2fs_set_volume_name(filp, arg);
+       case F2FS_IOC_GET_COMPRESS_BLOCKS:
+               return f2fs_get_compress_blocks(filp, arg);
        default:
                return -ENOTTY;
        }
@@ -3508,8 +3528,10 @@ static ssize_t f2fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
                goto out;
        }
 
-       if (!f2fs_is_compress_backend_ready(inode))
-               return -EOPNOTSUPP;
+       if (!f2fs_is_compress_backend_ready(inode)) {
+               ret = -EOPNOTSUPP;
+               goto out;
+       }
 
        if (iocb->ki_flags & IOCB_NOWAIT) {
                if (!inode_trylock(inode)) {
@@ -3639,6 +3661,7 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        case FS_IOC_MEASURE_VERITY:
        case F2FS_IOC_GET_VOLUME_NAME:
        case F2FS_IOC_SET_VOLUME_NAME:
+       case F2FS_IOC_GET_COMPRESS_BLOCKS:
                break;
        default:
                return -ENOIOCTLCMD;