Merge tag 'docs-5.15-2' of git://git.lwn.net/linux
[linux-2.6-microblaze.git] / fs / ext4 / inode.c
index c26f946..d18852d 100644 (file)
@@ -3957,20 +3957,19 @@ int ext4_update_disksize_before_punch(struct inode *inode, loff_t offset,
        return ret;
 }
 
-static void ext4_wait_dax_page(struct ext4_inode_info *ei)
+static void ext4_wait_dax_page(struct inode *inode)
 {
-       up_write(&ei->i_mmap_sem);
+       filemap_invalidate_unlock(inode->i_mapping);
        schedule();
-       down_write(&ei->i_mmap_sem);
+       filemap_invalidate_lock(inode->i_mapping);
 }
 
 int ext4_break_layouts(struct inode *inode)
 {
-       struct ext4_inode_info *ei = EXT4_I(inode);
        struct page *page;
        int error;
 
-       if (WARN_ON_ONCE(!rwsem_is_locked(&ei->i_mmap_sem)))
+       if (WARN_ON_ONCE(!rwsem_is_locked(&inode->i_mapping->invalidate_lock)))
                return -EINVAL;
 
        do {
@@ -3981,7 +3980,7 @@ int ext4_break_layouts(struct inode *inode)
                error = ___wait_var_event(&page->_refcount,
                                atomic_read(&page->_refcount) == 1,
                                TASK_INTERRUPTIBLE, 0, 0,
-                               ext4_wait_dax_page(ei));
+                               ext4_wait_dax_page(inode));
        } while (error == 0);
 
        return error;
@@ -4012,9 +4011,9 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
 
        ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);
        if (ext4_has_inline_data(inode)) {
-               down_write(&EXT4_I(inode)->i_mmap_sem);
+               filemap_invalidate_lock(mapping);
                ret = ext4_convert_inline_data(inode);
-               up_write(&EXT4_I(inode)->i_mmap_sem);
+               filemap_invalidate_unlock(mapping);
                if (ret)
                        return ret;
        }
@@ -4065,7 +4064,7 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
         * Prevent page faults from reinstantiating pages we have released from
         * page cache.
         */
-       down_write(&EXT4_I(inode)->i_mmap_sem);
+       filemap_invalidate_lock(mapping);
 
        ret = ext4_break_layouts(inode);
        if (ret)
@@ -4138,7 +4137,7 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
 out_stop:
        ext4_journal_stop(handle);
 out_dio:
-       up_write(&EXT4_I(inode)->i_mmap_sem);
+       filemap_invalidate_unlock(mapping);
 out_mutex:
        inode_unlock(inode);
        return ret;
@@ -4932,8 +4931,14 @@ static int ext4_inode_blocks_set(handle_t *handle,
                ext4_clear_inode_flag(inode, EXT4_INODE_HUGE_FILE);
                return 0;
        }
+
+       /*
+        * This should never happen since sb->s_maxbytes should not have
+        * allowed this, sb->s_maxbytes was set according to the huge_file
+        * feature in ext4_fill_super().
+        */
        if (!ext4_has_feature_huge_file(sb))
-               return -EFBIG;
+               return -EFSCORRUPTED;
 
        if (i_blocks <= 0xffffffffffffULL) {
                /*
@@ -5036,16 +5041,14 @@ static int ext4_do_update_inode(handle_t *handle,
 
        spin_lock(&ei->i_raw_lock);
 
-       /* For fields not tracked in the in-memory inode,
-        * initialise them to zero for new inodes. */
+       /*
+        * For fields not tracked in the in-memory inode, initialise them
+        * to zero for new inodes.
+        */
        if (ext4_test_inode_state(inode, EXT4_STATE_NEW))
                memset(raw_inode, 0, EXT4_SB(inode->i_sb)->s_inode_size);
 
        err = ext4_inode_blocks_set(handle, raw_inode, ei);
-       if (err) {
-               spin_unlock(&ei->i_raw_lock);
-               goto out_brelse;
-       }
 
        raw_inode->i_mode = cpu_to_le16(inode->i_mode);
        i_uid = i_uid_read(inode);
@@ -5054,10 +5057,11 @@ static int ext4_do_update_inode(handle_t *handle,
        if (!(test_opt(inode->i_sb, NO_UID32))) {
                raw_inode->i_uid_low = cpu_to_le16(low_16_bits(i_uid));
                raw_inode->i_gid_low = cpu_to_le16(low_16_bits(i_gid));
-/*
- * Fix up interoperability with old kernels. Otherwise, old inodes get
- * re-used with the upper 16 bits of the uid/gid intact
- */
+               /*
+                * Fix up interoperability with old kernels. Otherwise,
+                * old inodes get re-used with the upper 16 bits of the
+                * uid/gid intact.
+                */
                if (ei->i_dtime && list_empty(&ei->i_orphan)) {
                        raw_inode->i_uid_high = 0;
                        raw_inode->i_gid_high = 0;
@@ -5126,8 +5130,9 @@ static int ext4_do_update_inode(handle_t *handle,
                }
        }
 
-       BUG_ON(!ext4_has_feature_project(inode->i_sb) &&
-              i_projid != EXT4_DEF_PROJID);
+       if (i_projid != EXT4_DEF_PROJID &&
+           !ext4_has_feature_project(inode->i_sb))
+               err = err ?: -EFSCORRUPTED;
 
        if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE &&
            EXT4_FITS_IN_INODE(raw_inode, ei, i_projid))
@@ -5135,6 +5140,11 @@ static int ext4_do_update_inode(handle_t *handle,
 
        ext4_inode_csum_set(inode, raw_inode, ei);
        spin_unlock(&ei->i_raw_lock);
+       if (err) {
+               EXT4_ERROR_INODE(inode, "corrupted inode contents");
+               goto out_brelse;
+       }
+
        if (inode->i_sb->s_flags & SB_LAZYTIME)
                ext4_update_other_inodes_time(inode->i_sb, inode->i_ino,
                                              bh->b_data);
@@ -5142,7 +5152,7 @@ static int ext4_do_update_inode(handle_t *handle,
        BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
        err = ext4_handle_dirty_metadata(handle, NULL, bh);
        if (err)
-               goto out_brelse;
+               goto out_error;
        ext4_clear_inode_state(inode, EXT4_STATE_NEW);
        if (set_large_file) {
                BUFFER_TRACE(EXT4_SB(sb)->s_sbh, "get write access");
@@ -5150,7 +5160,7 @@ static int ext4_do_update_inode(handle_t *handle,
                                                    EXT4_SB(sb)->s_sbh,
                                                    EXT4_JTR_NONE);
                if (err)
-                       goto out_brelse;
+                       goto out_error;
                lock_buffer(EXT4_SB(sb)->s_sbh);
                ext4_set_feature_large_file(sb);
                ext4_superblock_csum_set(sb);
@@ -5160,9 +5170,10 @@ static int ext4_do_update_inode(handle_t *handle,
                                                 EXT4_SB(sb)->s_sbh);
        }
        ext4_update_inode_fsync_trans(handle, inode, need_datasync);
+out_error:
+       ext4_std_error(inode->i_sb, err);
 out_brelse:
        brelse(bh);
-       ext4_std_error(inode->i_sb, err);
        return err;
 }
 
@@ -5432,11 +5443,11 @@ int ext4_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
                        inode_dio_wait(inode);
                }
 
-               down_write(&EXT4_I(inode)->i_mmap_sem);
+               filemap_invalidate_lock(inode->i_mapping);
 
                rc = ext4_break_layouts(inode);
                if (rc) {
-                       up_write(&EXT4_I(inode)->i_mmap_sem);
+                       filemap_invalidate_unlock(inode->i_mapping);
                        goto err_out;
                }
 
@@ -5512,7 +5523,7 @@ int ext4_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
                                error = rc;
                }
 out_mmap_sem:
-               up_write(&EXT4_I(inode)->i_mmap_sem);
+               filemap_invalidate_unlock(inode->i_mapping);
        }
 
        if (!error) {
@@ -5991,10 +6002,10 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val)
         * data (and journalled aops don't know how to handle these cases).
         */
        if (val) {
-               down_write(&EXT4_I(inode)->i_mmap_sem);
+               filemap_invalidate_lock(inode->i_mapping);
                err = filemap_write_and_wait(inode->i_mapping);
                if (err < 0) {
-                       up_write(&EXT4_I(inode)->i_mmap_sem);
+                       filemap_invalidate_unlock(inode->i_mapping);
                        return err;
                }
        }
@@ -6027,7 +6038,7 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val)
        percpu_up_write(&sbi->s_writepages_rwsem);
 
        if (val)
-               up_write(&EXT4_I(inode)->i_mmap_sem);
+               filemap_invalidate_unlock(inode->i_mapping);
 
        /* Finally we can mark the inode as dirty. */
 
@@ -6072,7 +6083,7 @@ vm_fault_t ext4_page_mkwrite(struct vm_fault *vmf)
        sb_start_pagefault(inode->i_sb);
        file_update_time(vma->vm_file);
 
-       down_read(&EXT4_I(inode)->i_mmap_sem);
+       filemap_invalidate_lock_shared(mapping);
 
        err = ext4_convert_inline_data(inode);
        if (err)
@@ -6187,7 +6198,7 @@ retry_alloc:
 out_ret:
        ret = block_page_mkwrite_return(err);
 out:
-       up_read(&EXT4_I(inode)->i_mmap_sem);
+       filemap_invalidate_unlock_shared(mapping);
        sb_end_pagefault(inode->i_sb);
        return ret;
 out_error:
@@ -6195,15 +6206,3 @@ out_error:
        ext4_journal_stop(handle);
        goto out;
 }
-
-vm_fault_t ext4_filemap_fault(struct vm_fault *vmf)
-{
-       struct inode *inode = file_inode(vmf->vma->vm_file);
-       vm_fault_t ret;
-
-       down_read(&EXT4_I(inode)->i_mmap_sem);
-       ret = filemap_fault(vmf);
-       up_read(&EXT4_I(inode)->i_mmap_sem);
-
-       return ret;
-}