Merge tag 'fs_for_v6.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack...
[platform/kernel/linux-starfive.git] / fs / buffer.c
index 00cad26..bd09132 100644 (file)
@@ -111,7 +111,6 @@ void buffer_check_dirty_writeback(struct folio *folio,
                bh = bh->b_this_page;
        } while (bh != head);
 }
-EXPORT_SYMBOL(buffer_check_dirty_writeback);
 
 /*
  * Block until a buffer comes unlocked.  This doesn't stop it
@@ -195,19 +194,19 @@ __find_get_block_slow(struct block_device *bdev, sector_t block)
        pgoff_t index;
        struct buffer_head *bh;
        struct buffer_head *head;
-       struct page *page;
+       struct folio *folio;
        int all_mapped = 1;
        static DEFINE_RATELIMIT_STATE(last_warned, HZ, 1);
 
        index = block >> (PAGE_SHIFT - bd_inode->i_blkbits);
-       page = find_get_page_flags(bd_mapping, index, FGP_ACCESSED);
-       if (!page)
+       folio = __filemap_get_folio(bd_mapping, index, FGP_ACCESSED, 0);
+       if (IS_ERR(folio))
                goto out;
 
        spin_lock(&bd_mapping->private_lock);
-       if (!page_has_buffers(page))
+       head = folio_buffers(folio);
+       if (!head)
                goto out_unlock;
-       head = page_buffers(page);
        bh = head;
        do {
                if (!buffer_mapped(bh))
@@ -237,7 +236,7 @@ __find_get_block_slow(struct block_device *bdev, sector_t block)
        }
 out_unlock:
        spin_unlock(&bd_mapping->private_lock);
-       put_page(page);
+       folio_put(folio);
 out:
        return ret;
 }
@@ -977,8 +976,8 @@ struct buffer_head *alloc_page_buffers(struct page *page, unsigned long size,
 }
 EXPORT_SYMBOL_GPL(alloc_page_buffers);
 
-static inline void
-link_dev_buffers(struct page *page, struct buffer_head *head)
+static inline void link_dev_buffers(struct folio *folio,
+               struct buffer_head *head)
 {
        struct buffer_head *bh, *tail;
 
@@ -988,7 +987,7 @@ link_dev_buffers(struct page *page, struct buffer_head *head)
                bh = bh->b_this_page;
        } while (bh);
        tail->b_this_page = head;
-       attach_page_private(page, head);
+       folio_attach_private(folio, head);
 }
 
 static sector_t blkdev_max_block(struct block_device *bdev, unsigned int size)
@@ -1004,15 +1003,14 @@ static sector_t blkdev_max_block(struct block_device *bdev, unsigned int size)
 }
 
 /*
- * Initialise the state of a blockdev page's buffers.
+ * Initialise the state of a blockdev folio's buffers.
  */ 
-static sector_t
-init_page_buffers(struct page *page, struct block_device *bdev,
-                       sector_t block, int size)
+static sector_t folio_init_buffers(struct folio *folio,
+               struct block_device *bdev, sector_t block, int size)
 {
-       struct buffer_head *head = page_buffers(page);
+       struct buffer_head *head = folio_buffers(folio);
        struct buffer_head *bh = head;
-       int uptodate = PageUptodate(page);
+       bool uptodate = folio_test_uptodate(folio);
        sector_t end_block = blkdev_max_block(bdev, size);
 
        do {
@@ -1046,7 +1044,7 @@ grow_dev_page(struct block_device *bdev, sector_t block,
              pgoff_t index, int size, int sizebits, gfp_t gfp)
 {
        struct inode *inode = bdev->bd_inode;
-       struct page *page;
+       struct folio *folio;
        struct buffer_head *bh;
        sector_t end_block;
        int ret = 0;
@@ -1062,42 +1060,37 @@ grow_dev_page(struct block_device *bdev, sector_t block,
         */
        gfp_mask |= __GFP_NOFAIL;
 
-       page = find_or_create_page(inode->i_mapping, index, gfp_mask);
-
-       BUG_ON(!PageLocked(page));
+       folio = __filemap_get_folio(inode->i_mapping, index,
+                       FGP_LOCK | FGP_ACCESSED | FGP_CREAT, gfp_mask);
 
-       if (page_has_buffers(page)) {
-               bh = page_buffers(page);
+       bh = folio_buffers(folio);
+       if (bh) {
                if (bh->b_size == size) {
-                       end_block = init_page_buffers(page, bdev,
-                                               (sector_t)index << sizebits,
-                                               size);
+                       end_block = folio_init_buffers(folio, bdev,
+                                       (sector_t)index << sizebits, size);
                        goto done;
                }
-               if (!try_to_free_buffers(page_folio(page)))
+               if (!try_to_free_buffers(folio))
                        goto failed;
        }
 
-       /*
-        * Allocate some buffers for this page
-        */
-       bh = alloc_page_buffers(page, size, true);
+       bh = folio_alloc_buffers(folio, size, true);
 
        /*
-        * Link the page to the buffers and initialise them.  Take the
+        * Link the folio to the buffers and initialise them.  Take the
         * lock to be atomic wrt __find_get_block(), which does not
-        * run under the page lock.
+        * run under the folio lock.
         */
        spin_lock(&inode->i_mapping->private_lock);
-       link_dev_buffers(page, bh);
-       end_block = init_page_buffers(page, bdev, (sector_t)index << sizebits,
-                       size);
+       link_dev_buffers(folio, bh);
+       end_block = folio_init_buffers(folio, bdev,
+                       (sector_t)index << sizebits, size);
        spin_unlock(&inode->i_mapping->private_lock);
 done:
        ret = (block < end_block) ? 1 : -ENXIO;
 failed:
-       unlock_page(page);
-       put_page(page);
+       folio_unlock(folio);
+       folio_put(folio);
        return ret;
 }
 
@@ -1834,7 +1827,7 @@ static struct buffer_head *folio_create_buffers(struct folio *folio,
  * WB_SYNC_ALL, the writes are posted using REQ_SYNC; this
  * causes the writes to be flagged as synchronous writes.
  */
-int __block_write_full_page(struct inode *inode, struct page *page,
+int __block_write_full_folio(struct inode *inode, struct folio *folio,
                        get_block_t *get_block, struct writeback_control *wbc,
                        bh_end_io_t *handler)
 {
@@ -1846,14 +1839,14 @@ int __block_write_full_page(struct inode *inode, struct page *page,
        int nr_underway = 0;
        blk_opf_t write_flags = wbc_to_write_flags(wbc);
 
-       head = folio_create_buffers(page_folio(page), inode,
+       head = folio_create_buffers(folio, inode,
                                    (1 << BH_Dirty) | (1 << BH_Uptodate));
 
        /*
         * Be very careful.  We have no exclusion from block_dirty_folio
         * here, and the (potentially unmapped) buffers may become dirty at
         * any time.  If a buffer becomes dirty here after we've inspected it
-        * then we just miss that fact, and the page stays dirty.
+        * then we just miss that fact, and the folio stays dirty.
         *
         * Buffers outside i_size may be dirtied by block_dirty_folio;
         * handle that here by just cleaning them.
@@ -1863,7 +1856,7 @@ int __block_write_full_page(struct inode *inode, struct page *page,
        blocksize = bh->b_size;
        bbits = block_size_bits(blocksize);
 
-       block = (sector_t)page->index << (PAGE_SHIFT - bbits);
+       block = (sector_t)folio->index << (PAGE_SHIFT - bbits);
        last_block = (i_size_read(inode) - 1) >> bbits;
 
        /*
@@ -1874,7 +1867,7 @@ int __block_write_full_page(struct inode *inode, struct page *page,
                if (block > last_block) {
                        /*
                         * mapped buffers outside i_size will occur, because
-                        * this page can be outside i_size when there is a
+                        * this folio can be outside i_size when there is a
                         * truncate in progress.
                         */
                        /*
@@ -1904,7 +1897,7 @@ int __block_write_full_page(struct inode *inode, struct page *page,
                        continue;
                /*
                 * If it's a fully non-blocking write attempt and we cannot
-                * lock the buffer then redirty the page.  Note that this can
+                * lock the buffer then redirty the folio.  Note that this can
                 * potentially cause a busy-wait loop from writeback threads
                 * and kswapd activity, but those code paths have their own
                 * higher-level throttling.
@@ -1912,7 +1905,7 @@ int __block_write_full_page(struct inode *inode, struct page *page,
                if (wbc->sync_mode != WB_SYNC_NONE) {
                        lock_buffer(bh);
                } else if (!trylock_buffer(bh)) {
-                       redirty_page_for_writepage(wbc, page);
+                       folio_redirty_for_writepage(wbc, folio);
                        continue;
                }
                if (test_clear_buffer_dirty(bh)) {
@@ -1923,11 +1916,11 @@ int __block_write_full_page(struct inode *inode, struct page *page,
        } while ((bh = bh->b_this_page) != head);
 
        /*
-        * The page and its buffers are protected by PageWriteback(), so we can
-        * drop the bh refcounts early.
+        * The folio and its buffers are protected by the writeback flag,
+        * so we can drop the bh refcounts early.
         */
-       BUG_ON(PageWriteback(page));
-       set_page_writeback(page);
+       BUG_ON(folio_test_writeback(folio));
+       folio_start_writeback(folio);
 
        do {
                struct buffer_head *next = bh->b_this_page;
@@ -1937,20 +1930,20 @@ int __block_write_full_page(struct inode *inode, struct page *page,
                }
                bh = next;
        } while (bh != head);
-       unlock_page(page);
+       folio_unlock(folio);
 
        err = 0;
 done:
        if (nr_underway == 0) {
                /*
-                * The page was marked dirty, but the buffers were
+                * The folio was marked dirty, but the buffers were
                 * clean.  Someone wrote them back by hand with
                 * write_dirty_buffer/submit_bh.  A rare case.
                 */
-               end_page_writeback(page);
+               folio_end_writeback(folio);
 
                /*
-                * The page and buffer_heads can be released at any time from
+                * The folio and buffer_heads can be released at any time from
                 * here on.
                 */
        }
@@ -1961,7 +1954,7 @@ recover:
         * ENOSPC, or some other error.  We may already have added some
         * blocks to the file, so we need to write these out to avoid
         * exposing stale data.
-        * The page is currently locked and not marked for writeback
+        * The folio is currently locked and not marked for writeback
         */
        bh = head;
        /* Recovery: lock and submit the mapped buffers */
@@ -1973,15 +1966,15 @@ recover:
                } else {
                        /*
                         * The buffer may have been set dirty during
-                        * attachment to a dirty page.
+                        * attachment to a dirty folio.
                         */
                        clear_buffer_dirty(bh);
                }
        } while ((bh = bh->b_this_page) != head);
-       SetPageError(page);
-       BUG_ON(PageWriteback(page));
-       mapping_set_error(page->mapping, err);
-       set_page_writeback(page);
+       folio_set_error(folio);
+       BUG_ON(folio_test_writeback(folio));
+       mapping_set_error(folio->mapping, err);
+       folio_start_writeback(folio);
        do {
                struct buffer_head *next = bh->b_this_page;
                if (buffer_async_write(bh)) {
@@ -1991,39 +1984,40 @@ recover:
                }
                bh = next;
        } while (bh != head);
-       unlock_page(page);
+       folio_unlock(folio);
        goto done;
 }
-EXPORT_SYMBOL(__block_write_full_page);
+EXPORT_SYMBOL(__block_write_full_folio);
 
 /*
- * If a page has any new buffers, zero them out here, and mark them uptodate
+ * If a folio has any new buffers, zero them out here, and mark them uptodate
  * and dirty so they'll be written out (in order to prevent uninitialised
  * block data from leaking). And clear the new bit.
  */
-void page_zero_new_buffers(struct page *page, unsigned from, unsigned to)
+void folio_zero_new_buffers(struct folio *folio, size_t from, size_t to)
 {
-       unsigned int block_start, block_end;
+       size_t block_start, block_end;
        struct buffer_head *head, *bh;
 
-       BUG_ON(!PageLocked(page));
-       if (!page_has_buffers(page))
+       BUG_ON(!folio_test_locked(folio));
+       head = folio_buffers(folio);
+       if (!head)
                return;
 
-       bh = head = page_buffers(page);
+       bh = head;
        block_start = 0;
        do {
                block_end = block_start + bh->b_size;
 
                if (buffer_new(bh)) {
                        if (block_end > from && block_start < to) {
-                               if (!PageUptodate(page)) {
-                                       unsigned start, size;
+                               if (!folio_test_uptodate(folio)) {
+                                       size_t start, xend;
 
                                        start = max(from, block_start);
-                                       size = min(to, block_end) - start;
+                                       xend = min(to, block_end);
 
-                                       zero_user(page, start, size);
+                                       folio_zero_segment(folio, start, xend);
                                        set_buffer_uptodate(bh);
                                }
 
@@ -2036,7 +2030,7 @@ void page_zero_new_buffers(struct page *page, unsigned from, unsigned to)
                bh = bh->b_this_page;
        } while (bh != head);
 }
-EXPORT_SYMBOL(page_zero_new_buffers);
+EXPORT_SYMBOL(folio_zero_new_buffers);
 
 static void
 iomap_to_bh(struct inode *inode, sector_t block, struct buffer_head *bh,
@@ -2174,7 +2168,7 @@ int __block_write_begin_int(struct folio *folio, loff_t pos, unsigned len,
                        err = -EIO;
        }
        if (unlikely(err))
-               page_zero_new_buffers(&folio->page, from, to);
+               folio_zero_new_buffers(folio, from, to);
        return err;
 }
 
@@ -2186,15 +2180,15 @@ int __block_write_begin(struct page *page, loff_t pos, unsigned len,
 }
 EXPORT_SYMBOL(__block_write_begin);
 
-static int __block_commit_write(struct inode *inode, struct page *page,
-               unsigned from, unsigned to)
+static int __block_commit_write(struct inode *inode, struct folio *folio,
+               size_t from, size_t to)
 {
-       unsigned block_start, block_end;
-       int partial = 0;
+       size_t block_start, block_end;
+       bool partial = false;
        unsigned blocksize;
        struct buffer_head *bh, *head;
 
-       bh = head = page_buffers(page);
+       bh = head = folio_buffers(folio);
        blocksize = bh->b_size;
 
        block_start = 0;
@@ -2202,7 +2196,7 @@ static int __block_commit_write(struct inode *inode, struct page *page,
                block_end = block_start + blocksize;
                if (block_end <= from || block_start >= to) {
                        if (!buffer_uptodate(bh))
-                               partial = 1;
+                               partial = true;
                } else {
                        set_buffer_uptodate(bh);
                        mark_buffer_dirty(bh);
@@ -2217,11 +2211,11 @@ static int __block_commit_write(struct inode *inode, struct page *page,
        /*
         * If this is a partial write which happened to make all buffers
         * uptodate then we can optimize away a bogus read_folio() for
-        * the next read(). Here we 'discover' whether the page went
+        * the next read(). Here we 'discover' whether the folio went
         * uptodate as a result of this (potentially partial) write.
         */
        if (!partial)
-               SetPageUptodate(page);
+               folio_mark_uptodate(folio);
        return 0;
 }
 
@@ -2258,10 +2252,9 @@ int block_write_end(struct file *file, struct address_space *mapping,
                        loff_t pos, unsigned len, unsigned copied,
                        struct page *page, void *fsdata)
 {
+       struct folio *folio = page_folio(page);
        struct inode *inode = mapping->host;
-       unsigned start;
-
-       start = pos & (PAGE_SIZE - 1);
+       size_t start = pos - folio_pos(folio);
 
        if (unlikely(copied < len)) {
                /*
@@ -2273,18 +2266,18 @@ int block_write_end(struct file *file, struct address_space *mapping,
                 * read_folio might come in and destroy our partial write.
                 *
                 * Do the simplest thing, and just treat any short write to a
-                * non uptodate page as a zero-length write, and force the
+                * non uptodate folio as a zero-length write, and force the
                 * caller to redo the whole thing.
                 */
-               if (!PageUptodate(page))
+               if (!folio_test_uptodate(folio))
                        copied = 0;
 
-               page_zero_new_buffers(page, start+copied, start+len);
+               folio_zero_new_buffers(folio, start+copied, start+len);
        }
-       flush_dcache_page(page);
+       flush_dcache_folio(folio);
 
        /* This could be a short (even 0-length) commit */
-       __block_commit_write(inode, page, start, start+copied);
+       __block_commit_write(inode, folio, start, start + copied);
 
        return copied;
 }
@@ -2607,8 +2600,9 @@ EXPORT_SYMBOL(cont_write_begin);
 
 int block_commit_write(struct page *page, unsigned from, unsigned to)
 {
-       struct inode *inode = page->mapping->host;
-       __block_commit_write(inode,page,from,to);
+       struct folio *folio = page_folio(page);
+       struct inode *inode = folio->mapping->host;
+       __block_commit_write(inode, folio, from, to);
        return 0;
 }
 EXPORT_SYMBOL(block_commit_write);
@@ -2634,38 +2628,37 @@ EXPORT_SYMBOL(block_commit_write);
 int block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf,
                         get_block_t get_block)
 {
-       struct page *page = vmf->page;
+       struct folio *folio = page_folio(vmf->page);
        struct inode *inode = file_inode(vma->vm_file);
        unsigned long end;
        loff_t size;
        int ret;
 
-       lock_page(page);
+       folio_lock(folio);
        size = i_size_read(inode);
-       if ((page->mapping != inode->i_mapping) ||
-           (page_offset(page) > size)) {
+       if ((folio->mapping != inode->i_mapping) ||
+           (folio_pos(folio) >= size)) {
                /* We overload EFAULT to mean page got truncated */
                ret = -EFAULT;
                goto out_unlock;
        }
 
-       /* page is wholly or partially inside EOF */
-       if (((page->index + 1) << PAGE_SHIFT) > size)
-               end = size & ~PAGE_MASK;
-       else
-               end = PAGE_SIZE;
+       end = folio_size(folio);
+       /* folio is wholly or partially inside EOF */
+       if (folio_pos(folio) + end > size)
+               end = size - folio_pos(folio);
 
-       ret = __block_write_begin(page, 0, end, get_block);
+       ret = __block_write_begin_int(folio, 0, end, get_block, NULL);
        if (!ret)
-               ret = block_commit_write(page, 0, end);
+               ret = __block_commit_write(inode, folio, 0, end);
 
        if (unlikely(ret < 0))
                goto out_unlock;
-       set_page_dirty(page);
-       wait_for_stable_page(page);
+       folio_mark_dirty(folio);
+       folio_wait_stable(folio);
        return 0;
 out_unlock:
-       unlock_page(page);
+       folio_unlock(folio);
        return ret;
 }
 EXPORT_SYMBOL(block_page_mkwrite);
@@ -2674,17 +2667,16 @@ int block_truncate_page(struct address_space *mapping,
                        loff_t from, get_block_t *get_block)
 {
        pgoff_t index = from >> PAGE_SHIFT;
-       unsigned offset = from & (PAGE_SIZE-1);
        unsigned blocksize;
        sector_t iblock;
-       unsigned length, pos;
+       size_t offset, length, pos;
        struct inode *inode = mapping->host;
-       struct page *page;
+       struct folio *folio;
        struct buffer_head *bh;
        int err = 0;
 
        blocksize = i_blocksize(inode);
-       length = offset & (blocksize - 1);
+       length = from & (blocksize - 1);
 
        /* Block boundary? Nothing to do */
        if (!length)
@@ -2693,15 +2685,18 @@ int block_truncate_page(struct address_space *mapping,
        length = blocksize - length;
        iblock = (sector_t)index << (PAGE_SHIFT - inode->i_blkbits);
        
-       page = grab_cache_page(mapping, index);
-       if (!page)
-               return -ENOMEM;
+       folio = filemap_grab_folio(mapping, index);
+       if (IS_ERR(folio))
+               return PTR_ERR(folio);
 
-       if (!page_has_buffers(page))
-               create_empty_buffers(page, blocksize, 0);
+       bh = folio_buffers(folio);
+       if (!bh) {
+               folio_create_empty_buffers(folio, blocksize, 0);
+               bh = folio_buffers(folio);
+       }
 
        /* Find the buffer that contains "offset" */
-       bh = page_buffers(page);
+       offset = offset_in_folio(folio, from);
        pos = blocksize;
        while (offset >= pos) {
                bh = bh->b_this_page;
@@ -2720,7 +2715,7 @@ int block_truncate_page(struct address_space *mapping,
        }
 
        /* Ok, it's mapped. Make sure it's up-to-date */
-       if (PageUptodate(page))
+       if (folio_test_uptodate(folio))
                set_buffer_uptodate(bh);
 
        if (!buffer_uptodate(bh) && !buffer_delay(bh) && !buffer_unwritten(bh)) {
@@ -2730,12 +2725,12 @@ int block_truncate_page(struct address_space *mapping,
                        goto unlock;
        }
 
-       zero_user(page, offset, length);
+       folio_zero_range(folio, offset, length);
        mark_buffer_dirty(bh);
 
 unlock:
-       unlock_page(page);
-       put_page(page);
+       folio_unlock(folio);
+       folio_put(folio);
 
        return err;
 }
@@ -2747,33 +2742,32 @@ EXPORT_SYMBOL(block_truncate_page);
 int block_write_full_page(struct page *page, get_block_t *get_block,
                        struct writeback_control *wbc)
 {
-       struct inode * const inode = page->mapping->host;
+       struct folio *folio = page_folio(page);
+       struct inode * const inode = folio->mapping->host;
        loff_t i_size = i_size_read(inode);
-       const pgoff_t end_index = i_size >> PAGE_SHIFT;
-       unsigned offset;
 
-       /* Is the page fully inside i_size? */
-       if (page->index < end_index)
-               return __block_write_full_page(inode, page, get_block, wbc,
+       /* Is the folio fully inside i_size? */
+       if (folio_pos(folio) + folio_size(folio) <= i_size)
+               return __block_write_full_folio(inode, folio, get_block, wbc,
                                               end_buffer_async_write);
 
-       /* Is the page fully outside i_size? (truncate in progress) */
-       offset = i_size & (PAGE_SIZE-1);
-       if (page->index >= end_index+1 || !offset) {
-               unlock_page(page);
+       /* Is the folio fully outside i_size? (truncate in progress) */
+       if (folio_pos(folio) >= i_size) {
+               folio_unlock(folio);
                return 0; /* don't care */
        }
 
        /*
-        * The page straddles i_size.  It must be zeroed out on each and every
+        * The folio straddles i_size.  It must be zeroed out on each and every
         * writepage invocation because it may be mmapped.  "A file is mapped
         * in multiples of the page size.  For a file that is not a multiple of
-        * the  page size, the remaining memory is zeroed when mapped, and
+        * the page size, the remaining memory is zeroed when mapped, and
         * writes to that region are not written out to the file."
         */
-       zero_user_segment(page, offset, PAGE_SIZE);
-       return __block_write_full_page(inode, page, get_block, wbc,
-                                                       end_buffer_async_write);
+       folio_zero_segment(folio, offset_in_folio(folio, i_size),
+                       folio_size(folio));
+       return __block_write_full_folio(inode, folio, get_block, wbc,
+                       end_buffer_async_write);
 }
 EXPORT_SYMBOL(block_write_full_page);
 
@@ -2830,8 +2824,7 @@ static void submit_bh_wbc(blk_opf_t opf, struct buffer_head *bh,
 
        bio->bi_iter.bi_sector = bh->b_blocknr * (bh->b_size >> 9);
 
-       bio_add_page(bio, bh->b_page, bh->b_size, bh_offset(bh));
-       BUG_ON(bio->bi_iter.bi_size != bh->b_size);
+       __bio_add_page(bio, bh->b_page, bh->b_size, bh_offset(bh));
 
        bio->bi_end_io = end_bio_bh_io_sync;
        bio->bi_private = bh;