Merge tag 'idmapped-mounts-v5.12' of git://git.kernel.org/pub/scm/linux/kernel/git...
[platform/kernel/linux-rpi.git] / fs / f2fs / file.c
index 8f1e97e..d26ff2a 100644 (file)
@@ -29,7 +29,6 @@
 #include "xattr.h"
 #include "acl.h"
 #include "gc.h"
-#include "trace.h"
 #include <trace/events/f2fs.h>
 #include <uapi/linux/f2fs.h>
 
@@ -60,6 +59,9 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault *vmf)
        bool need_alloc = true;
        int err = 0;
 
+       if (unlikely(IS_IMMUTABLE(inode)))
+               return VM_FAULT_SIGBUS;
+
        if (unlikely(f2fs_cp_error(sbi))) {
                err = -EIO;
                goto err;
@@ -70,6 +72,10 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault *vmf)
                goto err;
        }
 
+       err = f2fs_convert_inline_inode(inode);
+       if (err)
+               goto err;
+
 #ifdef CONFIG_F2FS_FS_COMPRESSION
        if (f2fs_compressed_file(inode)) {
                int ret = f2fs_is_compressed_cluster(inode, page->index);
@@ -366,7 +372,6 @@ flush_out:
        f2fs_update_time(sbi, REQ_TIME);
 out:
        trace_f2fs_sync_file_exit(inode, cp_reason, datasync, ret);
-       f2fs_trace_ios(NULL, 1);
        return ret;
 }
 
@@ -483,6 +488,9 @@ static loff_t f2fs_llseek(struct file *file, loff_t offset, int whence)
        struct inode *inode = file->f_mapping->host;
        loff_t maxbytes = inode->i_sb->s_maxbytes;
 
+       if (f2fs_compressed_file(inode))
+               maxbytes = max_file_blocks(inode) << F2FS_BLKSIZE_BITS;
+
        switch (whence) {
        case SEEK_SET:
        case SEEK_CUR:
@@ -502,7 +510,6 @@ static loff_t f2fs_llseek(struct file *file, loff_t offset, int whence)
 static int f2fs_file_mmap(struct file *file, struct vm_area_struct *vma)
 {
        struct inode *inode = file_inode(file);
-       int err;
 
        if (unlikely(f2fs_cp_error(F2FS_I_SB(inode))))
                return -EIO;
@@ -510,11 +517,6 @@ static int f2fs_file_mmap(struct file *file, struct vm_area_struct *vma)
        if (!f2fs_is_compress_backend_ready(inode))
                return -EOPNOTSUPP;
 
-       /* we don't need to use inline_data strictly */
-       err = f2fs_convert_inline_inode(inode);
-       if (err)
-               return err;
-
        file_accessed(file);
        vma->vm_ops = &f2fs_file_vm_ops;
        set_inode_flag(inode, FI_MMAP_FILE);
@@ -667,7 +669,7 @@ int f2fs_do_truncate_blocks(struct inode *inode, u64 from, bool lock)
 
        free_from = (pgoff_t)F2FS_BLK_ALIGN(from);
 
-       if (free_from >= sbi->max_file_blocks)
+       if (free_from >= max_file_blocks(inode))
                goto free_partial;
 
        if (lock)
@@ -767,6 +769,10 @@ int f2fs_truncate(struct inode *inode)
                return -EIO;
        }
 
+       err = dquot_initialize(inode);
+       if (err)
+               return err;
+
        /* we should check inline_data size */
        if (!f2fs_may_inline_data(inode)) {
                err = f2fs_convert_inline_inode(inode);
@@ -850,7 +856,7 @@ static void __setattr_copy(struct user_namespace *mnt_userns,
                umode_t mode = attr->ia_mode;
                kgid_t kgid = i_gid_into_mnt(mnt_userns, inode);
 
-               if (!in_group_p(kgid) && !capable(CAP_FSETID))
+               if (!in_group_p(kgid) && !capable_wrt_inode_uidgid(mnt_userns, inode, CAP_FSETID))
                        mode &= ~S_ISGID;
                set_acl_inode(inode, mode);
        }
@@ -868,6 +874,14 @@ int f2fs_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
        if (unlikely(f2fs_cp_error(F2FS_I_SB(inode))))
                return -EIO;
 
+       if (unlikely(IS_IMMUTABLE(inode)))
+               return -EPERM;
+
+       if (unlikely(IS_APPEND(inode) &&
+                       (attr->ia_valid & (ATTR_MODE | ATTR_UID |
+                                 ATTR_GID | ATTR_TIMES_SET))))
+               return -EPERM;
+
        if ((attr->ia_valid & ATTR_SIZE) &&
                !f2fs_is_compress_backend_ready(inode))
                return -EOPNOTSUPP;
@@ -951,10 +965,11 @@ int f2fs_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
        __setattr_copy(&init_user_ns, inode, attr);
 
        if (attr->ia_valid & ATTR_MODE) {
-               err = posix_acl_chmod(&init_user_ns, inode,
-                                     f2fs_get_inode_mode(inode));
-               if (err || is_inode_flag_set(inode, FI_ACL_MODE)) {
-                       inode->i_mode = F2FS_I(inode)->i_acl_mode;
+               err = posix_acl_chmod(&init_user_ns, inode, f2fs_get_inode_mode(inode));
+
+               if (is_inode_flag_set(inode, FI_ACL_MODE)) {
+                       if (!err)
+                               inode->i_mode = F2FS_I(inode)->i_acl_mode;
                        clear_inode_flag(inode, FI_ACL_MODE);
                }
        }
@@ -2734,7 +2749,7 @@ static int f2fs_ioc_defragment(struct file *filp, unsigned long arg)
                return -EINVAL;
 
        if (unlikely((range.start + range.len) >> PAGE_SHIFT >
-                                       sbi->max_file_blocks))
+                                       max_file_blocks(inode)))
                return -EINVAL;
 
        err = mnt_want_write_file(filp);
@@ -3297,7 +3312,7 @@ int f2fs_precache_extents(struct inode *inode)
        map.m_next_extent = &m_next_extent;
        map.m_seg_type = NO_CHECK_TYPE;
        map.m_may_create = false;
-       end = F2FS_I_SB(inode)->max_file_blocks;
+       end = max_file_blocks(inode);
 
        while (map.m_lblk < end) {
                map.m_len = end - map.m_lblk;
@@ -3361,6 +3376,14 @@ static int f2fs_ioc_measure_verity(struct file *filp, unsigned long arg)
        return fsverity_ioctl_measure(filp, (void __user *)arg);
 }
 
+static int f2fs_ioc_read_verity_metadata(struct file *filp, unsigned long arg)
+{
+       if (!f2fs_sb_has_verity(F2FS_I_SB(file_inode(filp))))
+               return -EOPNOTSUPP;
+
+       return fsverity_ioctl_read_metadata(filp, (const void __user *)arg);
+}
+
 static int f2fs_ioc_getfslabel(struct file *filp, unsigned long arg)
 {
        struct inode *inode = file_inode(filp);
@@ -4047,8 +4070,10 @@ static int redirty_blocks(struct inode *inode, pgoff_t page_idx, int len)
 
        for (i = 0; i < page_len; i++, redirty_idx++) {
                page = find_lock_page(mapping, redirty_idx);
-               if (!page)
-                       ret = -ENOENT;
+               if (!page) {
+                       ret = -ENOMEM;
+                       break;
+               }
                set_page_dirty(page);
                f2fs_put_page(page, 1);
                f2fs_put_page(page, 0);
@@ -4276,6 +4301,8 @@ static long __f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                return f2fs_ioc_enable_verity(filp, arg);
        case FS_IOC_MEASURE_VERITY:
                return f2fs_ioc_measure_verity(filp, arg);
+       case FS_IOC_READ_VERITY_METADATA:
+               return f2fs_ioc_read_verity_metadata(filp, arg);
        case FS_IOC_GETFSLABEL:
                return f2fs_ioc_getfslabel(filp, arg);
        case FS_IOC_SETFSLABEL:
@@ -4353,6 +4380,11 @@ static ssize_t f2fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
                inode_lock(inode);
        }
 
+       if (unlikely(IS_IMMUTABLE(inode))) {
+               ret = -EPERM;
+               goto unlock;
+       }
+
        ret = generic_write_checks(iocb, from);
        if (ret > 0) {
                bool preallocated = false;
@@ -4417,6 +4449,7 @@ write:
                if (ret > 0)
                        f2fs_update_iostat(F2FS_I_SB(inode), APP_WRITE_IO, ret);
        }
+unlock:
        inode_unlock(inode);
 out:
        trace_f2fs_file_write_iter(inode, iocb->ki_pos,
@@ -4527,6 +4560,7 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        case F2FS_IOC_RESIZE_FS:
        case FS_IOC_ENABLE_VERITY:
        case FS_IOC_MEASURE_VERITY:
+       case FS_IOC_READ_VERITY_METADATA:
        case FS_IOC_GETFSLABEL:
        case FS_IOC_SETFSLABEL:
        case F2FS_IOC_GET_COMPRESS_BLOCKS: