]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
f2fs: introduce FI_COMPRESS_RELEASED instead of using IMMUTABLE bit
authorJaegeuk Kim <jaegeuk@kernel.org>
Tue, 25 May 2021 18:39:35 +0000 (11:39 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 16 Jun 2024 11:32:17 +0000 (13:32 +0200)
[ Upstream commit c61404153eb683da9c35aad133131554861ed561 ]

Once we release compressed blocks, we used to set IMMUTABLE bit. But it turned
out it disallows every fs operations which we don't need for compression.

Let's just prevent writing data only.

Reviewed-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Stable-dep-of: 7c5dffb3d90c ("f2fs: compress: fix to relocate check condition in f2fs_{release,reserve}_compress_blocks()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/f2fs/compress.c
fs/f2fs/f2fs.h
fs/f2fs/file.c
include/linux/f2fs_fs.h

index 388ed7052d9b6627795efcd2a17f35fe8b3a95df..be6f2988ac7fc7eb30d232970c6fed8b3d164cda 100644 (file)
@@ -902,7 +902,8 @@ static int __f2fs_cluster_blocks(struct inode *inode,
                }
 
                f2fs_bug_on(F2FS_I_SB(inode),
-                       !compr && ret != cluster_size && !IS_IMMUTABLE(inode));
+                       !compr && ret != cluster_size &&
+                       !is_inode_flag_set(inode, FI_COMPRESS_RELEASED));
        }
 fail:
        f2fs_put_dnode(&dn);
index 6a9f4dcea06d65afd21ecbfd3ea7ef3ddd6a7fe2..4380df9b2d70abec57f0c21353b0833d6b1b8444 100644 (file)
@@ -683,6 +683,7 @@ enum {
        FI_COMPRESS_CORRUPT,    /* indicate compressed cluster is corrupted */
        FI_MMAP_FILE,           /* indicate file was mmapped */
        FI_ENABLE_COMPRESS,     /* enable compression in "user" compression mode */
+       FI_COMPRESS_RELEASED,   /* compressed blocks were released */
        FI_MAX,                 /* max flag, never be used */
 };
 
@@ -2650,6 +2651,7 @@ static inline void __mark_inode_dirty_flag(struct inode *inode,
        case FI_DATA_EXIST:
        case FI_INLINE_DOTS:
        case FI_PIN_FILE:
+       case FI_COMPRESS_RELEASED:
                f2fs_mark_inode_dirty_sync(inode, true);
        }
 }
@@ -2771,6 +2773,8 @@ static inline void get_inline_info(struct inode *inode, struct f2fs_inode *ri)
                set_bit(FI_EXTRA_ATTR, fi->flags);
        if (ri->i_inline & F2FS_PIN_FILE)
                set_bit(FI_PIN_FILE, fi->flags);
+       if (ri->i_inline & F2FS_COMPRESS_RELEASED)
+               set_bit(FI_COMPRESS_RELEASED, fi->flags);
 }
 
 static inline void set_raw_inline(struct inode *inode, struct f2fs_inode *ri)
@@ -2791,6 +2795,8 @@ static inline void set_raw_inline(struct inode *inode, struct f2fs_inode *ri)
                ri->i_inline |= F2FS_EXTRA_ATTR;
        if (is_inode_flag_set(inode, FI_PIN_FILE))
                ri->i_inline |= F2FS_PIN_FILE;
+       if (is_inode_flag_set(inode, FI_COMPRESS_RELEASED))
+               ri->i_inline |= F2FS_COMPRESS_RELEASED;
 }
 
 static inline int f2fs_has_extra_attr(struct inode *inode)
index 8b136f2dc2d2248b1d69574b051e3a1da65ade4b..cdd2630f4860f2e08f1d6fd8bc4752d56b2725bb 100644 (file)
@@ -63,6 +63,9 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault *vmf)
        if (unlikely(IS_IMMUTABLE(inode)))
                return VM_FAULT_SIGBUS;
 
+       if (is_inode_flag_set(inode, FI_COMPRESS_RELEASED))
+               return VM_FAULT_SIGBUS;
+
        if (unlikely(f2fs_cp_error(sbi))) {
                err = -EIO;
                goto err;
@@ -3551,7 +3554,7 @@ static int f2fs_release_compress_blocks(struct file *filp, unsigned long arg)
                goto out;
        }
 
-       if (IS_IMMUTABLE(inode)) {
+       if (is_inode_flag_set(inode, FI_COMPRESS_RELEASED)) {
                ret = -EINVAL;
                goto out;
        }
@@ -3560,8 +3563,7 @@ static int f2fs_release_compress_blocks(struct file *filp, unsigned long arg)
        if (ret)
                goto out;
 
-       F2FS_I(inode)->i_flags |= F2FS_IMMUTABLE_FL;
-       f2fs_set_inode_flags(inode);
+       set_inode_flag(inode, FI_COMPRESS_RELEASED);
        inode->i_ctime = current_time(inode);
        f2fs_mark_inode_dirty_sync(inode, true);
 
@@ -3727,7 +3729,7 @@ static int f2fs_reserve_compress_blocks(struct file *filp, unsigned long arg)
 
        inode_lock(inode);
 
-       if (!IS_IMMUTABLE(inode)) {
+       if (!is_inode_flag_set(inode, FI_COMPRESS_RELEASED)) {
                ret = -EINVAL;
                goto unlock_inode;
        }
@@ -3772,8 +3774,7 @@ static int f2fs_reserve_compress_blocks(struct file *filp, unsigned long arg)
        up_write(&F2FS_I(inode)->i_mmap_sem);
 
        if (ret >= 0) {
-               F2FS_I(inode)->i_flags &= ~F2FS_IMMUTABLE_FL;
-               f2fs_set_inode_flags(inode);
+               clear_inode_flag(inode, FI_COMPRESS_RELEASED);
                inode->i_ctime = current_time(inode);
                f2fs_mark_inode_dirty_sync(inode, true);
        }
@@ -4130,6 +4131,11 @@ static ssize_t f2fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
                goto unlock;
        }
 
+       if (is_inode_flag_set(inode, FI_COMPRESS_RELEASED)) {
+               ret = -EPERM;
+               goto unlock;
+       }
+
        ret = generic_write_checks(iocb, from);
        if (ret > 0) {
                bool preallocated = false;
index 7dc2a06cf19a119e11bc8abdf119eec9b54ccb82..9a6082c5721999350cafea8179b0d23037b7a81d 100644 (file)
@@ -229,6 +229,7 @@ struct f2fs_extent {
 #define F2FS_INLINE_DOTS       0x10    /* file having implicit dot dentries */
 #define F2FS_EXTRA_ATTR                0x20    /* file having extra attribute */
 #define F2FS_PIN_FILE          0x40    /* file should not be gced */
+#define F2FS_COMPRESS_RELEASED 0x80    /* file released compressed blocks */
 
 struct f2fs_inode {
        __le16 i_mode;                  /* file mode */