Merge tag 'mm-stable-2023-04-27-15-30' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-block.git] / fs / ext4 / inline.c
index 1602d74b5eeb35f0090afb0ec566ed5f00c21ecc..859bc4e2c9b0af3a98e0b33dd4a0eac94e0a9585 100644 (file)
@@ -467,16 +467,16 @@ out:
        return error;
 }
 
-static int ext4_read_inline_page(struct inode *inode, struct page *page)
+static int ext4_read_inline_folio(struct inode *inode, struct folio *folio)
 {
        void *kaddr;
        int ret = 0;
        size_t len;
        struct ext4_iloc iloc;
 
-       BUG_ON(!PageLocked(page));
+       BUG_ON(!folio_test_locked(folio));
        BUG_ON(!ext4_has_inline_data(inode));
-       BUG_ON(page->index);
+       BUG_ON(folio->index);
 
        if (!EXT4_I(inode)->i_inline_off) {
                ext4_warning(inode->i_sb, "inode %lu doesn't have inline data.",
@@ -489,19 +489,20 @@ static int ext4_read_inline_page(struct inode *inode, struct page *page)
                goto out;
 
        len = min_t(size_t, ext4_get_inline_size(inode), i_size_read(inode));
-       kaddr = kmap_atomic(page);
+       BUG_ON(len > PAGE_SIZE);
+       kaddr = kmap_local_folio(folio, 0);
        ret = ext4_read_inline_data(inode, kaddr, len, &iloc);
-       flush_dcache_page(page);
-       kunmap_atomic(kaddr);
-       zero_user_segment(page, len, PAGE_SIZE);
-       SetPageUptodate(page);
+       flush_dcache_folio(folio);
+       kunmap_local(kaddr);
+       folio_zero_segment(folio, len, folio_size(folio));
+       folio_mark_uptodate(folio);
        brelse(iloc.bh);
 
 out:
        return ret;
 }
 
-int ext4_readpage_inline(struct inode *inode, struct page *page)
+int ext4_readpage_inline(struct inode *inode, struct folio *folio)
 {
        int ret = 0;
 
@@ -515,16 +516,16 @@ int ext4_readpage_inline(struct inode *inode, struct page *page)
         * Current inline data can only exist in the 1st page,
         * So for all the other pages, just set them uptodate.
         */
-       if (!page->index)
-               ret = ext4_read_inline_page(inode, page);
-       else if (!PageUptodate(page)) {
-               zero_user_segment(page, 0, PAGE_SIZE);
-               SetPageUptodate(page);
+       if (!folio->index)
+               ret = ext4_read_inline_folio(inode, folio);
+       else if (!folio_test_uptodate(folio)) {
+               folio_zero_segment(folio, 0, folio_size(folio));
+               folio_mark_uptodate(folio);
        }
 
        up_read(&EXT4_I(inode)->xattr_sem);
 
-       unlock_page(page);
+       folio_unlock(folio);
        return ret >= 0 ? 0 : ret;
 }
 
@@ -534,8 +535,7 @@ static int ext4_convert_inline_data_to_extent(struct address_space *mapping,
        int ret, needed_blocks, no_expand;
        handle_t *handle = NULL;
        int retries = 0, sem_held = 0;
-       struct page *page = NULL;
-       unsigned int flags;
+       struct folio *folio = NULL;
        unsigned from, to;
        struct ext4_iloc iloc;
 
@@ -564,12 +564,11 @@ retry:
 
        /* We cannot recurse into the filesystem as the transaction is already
         * started */
-       flags = memalloc_nofs_save();
-       page = grab_cache_page_write_begin(mapping, 0);
-       memalloc_nofs_restore(flags);
-       if (!page) {
-               ret = -ENOMEM;
-               goto out;
+       folio = __filemap_get_folio(mapping, 0, FGP_WRITEBEGIN | FGP_NOFS,
+                       mapping_gfp_mask(mapping));
+       if (IS_ERR(folio)) {
+               ret = PTR_ERR(folio);
+               goto out_nofolio;
        }
 
        ext4_write_lock_xattr(inode, &no_expand);
@@ -582,8 +581,8 @@ retry:
 
        from = 0;
        to = ext4_get_inline_size(inode);
-       if (!PageUptodate(page)) {
-               ret = ext4_read_inline_page(inode, page);
+       if (!folio_test_uptodate(folio)) {
+               ret = ext4_read_inline_folio(inode, folio);
                if (ret < 0)
                        goto out;
        }
@@ -593,21 +592,21 @@ retry:
                goto out;
 
        if (ext4_should_dioread_nolock(inode)) {
-               ret = __block_write_begin(page, from, to,
+               ret = __block_write_begin(&folio->page, from, to,
                                          ext4_get_block_unwritten);
        } else
-               ret = __block_write_begin(page, from, to, ext4_get_block);
+               ret = __block_write_begin(&folio->page, from, to, ext4_get_block);
 
        if (!ret && ext4_should_journal_data(inode)) {
-               ret = ext4_walk_page_buffers(handle, inode, page_buffers(page),
-                                            from, to, NULL,
-                                            do_journal_get_write_access);
+               ret = ext4_walk_page_buffers(handle, inode,
+                                            folio_buffers(folio), from, to,
+                                            NULL, do_journal_get_write_access);
        }
 
        if (ret) {
-               unlock_page(page);
-               put_page(page);
-               page = NULL;
+               folio_unlock(folio);
+               folio_put(folio);
+               folio = NULL;
                ext4_orphan_add(handle, inode);
                ext4_write_unlock_xattr(inode, &no_expand);
                sem_held = 0;
@@ -627,13 +626,14 @@ retry:
        if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
                goto retry;
 
-       if (page)
-               block_commit_write(page, from, to);
+       if (folio)
+               block_commit_write(&folio->page, from, to);
 out:
-       if (page) {
-               unlock_page(page);
-               put_page(page);
+       if (folio) {
+               folio_unlock(folio);
+               folio_put(folio);
        }
+out_nofolio:
        if (sem_held)
                ext4_write_unlock_xattr(inode, &no_expand);
        if (handle)
@@ -655,8 +655,7 @@ int ext4_try_to_write_inline_data(struct address_space *mapping,
 {
        int ret;
        handle_t *handle;
-       unsigned int flags;
-       struct page *page;
+       struct folio *folio;
        struct ext4_iloc iloc;
 
        if (pos + len > ext4_get_max_inline_size(inode))
@@ -693,28 +692,27 @@ int ext4_try_to_write_inline_data(struct address_space *mapping,
        if (ret)
                goto out;
 
-       flags = memalloc_nofs_save();
-       page = grab_cache_page_write_begin(mapping, 0);
-       memalloc_nofs_restore(flags);
-       if (!page) {
-               ret = -ENOMEM;
+       folio = __filemap_get_folio(mapping, 0, FGP_WRITEBEGIN | FGP_NOFS,
+                                       mapping_gfp_mask(mapping));
+       if (IS_ERR(folio)) {
+               ret = PTR_ERR(folio);
                goto out;
        }
 
-       *pagep = page;
+       *pagep = &folio->page;
        down_read(&EXT4_I(inode)->xattr_sem);
        if (!ext4_has_inline_data(inode)) {
                ret = 0;
-               unlock_page(page);
-               put_page(page);
+               folio_unlock(folio);
+               folio_put(folio);
                goto out_up_read;
        }
 
-       if (!PageUptodate(page)) {
-               ret = ext4_read_inline_page(inode, page);
+       if (!folio_test_uptodate(folio)) {
+               ret = ext4_read_inline_folio(inode, folio);
                if (ret < 0) {
-                       unlock_page(page);
-                       put_page(page);
+                       folio_unlock(folio);
+                       folio_put(folio);
                        goto out_up_read;
                }
        }
@@ -735,20 +733,21 @@ convert:
 int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned len,
                               unsigned copied, struct page *page)
 {
+       struct folio *folio = page_folio(page);
        handle_t *handle = ext4_journal_current_handle();
        int no_expand;
        void *kaddr;
        struct ext4_iloc iloc;
        int ret = 0, ret2;
 
-       if (unlikely(copied < len) && !PageUptodate(page))
+       if (unlikely(copied < len) && !folio_test_uptodate(folio))
                copied = 0;
 
        if (likely(copied)) {
                ret = ext4_get_inode_loc(inode, &iloc);
                if (ret) {
-                       unlock_page(page);
-                       put_page(page);
+                       folio_unlock(folio);
+                       folio_put(folio);
                        ext4_std_error(inode->i_sb, ret);
                        goto out;
                }
@@ -762,30 +761,30 @@ int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned len,
                 */
                (void) ext4_find_inline_data_nolock(inode);
 
-               kaddr = kmap_atomic(page);
+               kaddr = kmap_local_folio(folio, 0);
                ext4_write_inline_data(inode, &iloc, kaddr, pos, copied);
-               kunmap_atomic(kaddr);
-               SetPageUptodate(page);
-               /* clear page dirty so that writepages wouldn't work for us. */
-               ClearPageDirty(page);
+               kunmap_local(kaddr);
+               folio_mark_uptodate(folio);
+               /* clear dirty flag so that writepages wouldn't work for us. */
+               folio_clear_dirty(folio);
 
                ext4_write_unlock_xattr(inode, &no_expand);
                brelse(iloc.bh);
 
                /*
-                * It's important to update i_size while still holding page
+                * It's important to update i_size while still holding folio
                 * lock: page writeout could otherwise come in and zero
                 * beyond i_size.
                 */
                ext4_update_inode_size(inode, pos + copied);
        }
-       unlock_page(page);
-       put_page(page);
+       folio_unlock(folio);
+       folio_put(folio);
 
        /*
-        * Don't mark the inode dirty under page lock. First, it unnecessarily
-        * makes the holding time of page lock longer. Second, it forces lock
-        * ordering of page lock and transaction start for journaling
+        * Don't mark the inode dirty under folio lock. First, it unnecessarily
+        * makes the holding time of folio lock longer. Second, it forces lock
+        * ordering of folio lock and transaction start for journaling
         * filesystems.
         */
        if (likely(copied))
@@ -852,11 +851,12 @@ static int ext4_da_convert_inline_data_to_extent(struct address_space *mapping,
                                                 void **fsdata)
 {
        int ret = 0, inline_size;
-       struct page *page;
+       struct folio *folio;
 
-       page = grab_cache_page_write_begin(mapping, 0);
-       if (!page)
-               return -ENOMEM;
+       folio = __filemap_get_folio(mapping, 0, FGP_WRITEBEGIN,
+                                       mapping_gfp_mask(mapping));
+       if (IS_ERR(folio))
+               return PTR_ERR(folio);
 
        down_read(&EXT4_I(inode)->xattr_sem);
        if (!ext4_has_inline_data(inode)) {
@@ -866,32 +866,32 @@ static int ext4_da_convert_inline_data_to_extent(struct address_space *mapping,
 
        inline_size = ext4_get_inline_size(inode);
 
-       if (!PageUptodate(page)) {
-               ret = ext4_read_inline_page(inode, page);
+       if (!folio_test_uptodate(folio)) {
+               ret = ext4_read_inline_folio(inode, folio);
                if (ret < 0)
                        goto out;
        }
 
-       ret = __block_write_begin(page, 0, inline_size,
+       ret = __block_write_begin(&folio->page, 0, inline_size,
                                  ext4_da_get_block_prep);
        if (ret) {
                up_read(&EXT4_I(inode)->xattr_sem);
-               unlock_page(page);
-               put_page(page);
+               folio_unlock(folio);
+               folio_put(folio);
                ext4_truncate_failed_write(inode);
                return ret;
        }
 
-       SetPageDirty(page);
-       SetPageUptodate(page);
+       folio_mark_dirty(folio);
+       folio_mark_uptodate(folio);
        ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);
        *fsdata = (void *)CONVERT_INLINE_DATA;
 
 out:
        up_read(&EXT4_I(inode)->xattr_sem);
-       if (page) {
-               unlock_page(page);
-               put_page(page);
+       if (folio) {
+               folio_unlock(folio);
+               folio_put(folio);
        }
        return ret;
 }
@@ -912,10 +912,9 @@ int ext4_da_write_inline_data_begin(struct address_space *mapping,
 {
        int ret;
        handle_t *handle;
-       struct page *page;
+       struct folio *folio;
        struct ext4_iloc iloc;
        int retries = 0;
-       unsigned int flags;
 
        ret = ext4_get_inode_loc(inode, &iloc);
        if (ret)
@@ -947,11 +946,10 @@ retry_journal:
         * We cannot recurse into the filesystem as the transaction
         * is already started.
         */
-       flags = memalloc_nofs_save();
-       page = grab_cache_page_write_begin(mapping, 0);
-       memalloc_nofs_restore(flags);
-       if (!page) {
-               ret = -ENOMEM;
+       folio = __filemap_get_folio(mapping, 0, FGP_WRITEBEGIN | FGP_NOFS,
+                                       mapping_gfp_mask(mapping));
+       if (IS_ERR(folio)) {
+               ret = PTR_ERR(folio);
                goto out_journal;
        }
 
@@ -961,8 +959,8 @@ retry_journal:
                goto out_release_page;
        }
 
-       if (!PageUptodate(page)) {
-               ret = ext4_read_inline_page(inode, page);
+       if (!folio_test_uptodate(folio)) {
+               ret = ext4_read_inline_folio(inode, folio);
                if (ret < 0)
                        goto out_release_page;
        }
@@ -972,13 +970,13 @@ retry_journal:
                goto out_release_page;
 
        up_read(&EXT4_I(inode)->xattr_sem);
-       *pagep = page;
+       *pagep = &folio->page;
        brelse(iloc.bh);
        return 1;
 out_release_page:
        up_read(&EXT4_I(inode)->xattr_sem);
-       unlock_page(page);
-       put_page(page);
+       folio_unlock(folio);
+       folio_put(folio);
 out_journal:
        ext4_journal_stop(handle);
 out: