}
 
                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);
 
        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 */
 };
 
        case FI_DATA_EXIST:
        case FI_INLINE_DOTS:
        case FI_PIN_FILE:
+       case FI_COMPRESS_RELEASED:
                f2fs_mark_inode_dirty_sync(inode, true);
        }
 }
                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)
                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)
 
        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;
                goto out;
        }
 
-       if (IS_IMMUTABLE(inode)) {
+       if (is_inode_flag_set(inode, FI_COMPRESS_RELEASED)) {
                ret = -EINVAL;
                goto out;
        }
        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);
 
 
        inode_lock(inode);
 
-       if (!IS_IMMUTABLE(inode)) {
+       if (!is_inode_flag_set(inode, FI_COMPRESS_RELEASED)) {
                ret = -EINVAL;
                goto unlock_inode;
        }
        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);
        }
                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;
 
 #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 */