Merge tag 'ubifs-for-linus-6.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-block.git] / fs / ubifs / file.c
index 8cb5d76b301ccde611be04b7662acdcbdb1ead82..979ab1d9d0c39ddf56ea9d9f8e1f5c2e4c30a3d3 100644 (file)
@@ -1032,7 +1032,7 @@ static int ubifs_writepage(struct page *page, struct writeback_control *wbc)
                if (page->index >= synced_i_size >> PAGE_SHIFT) {
                        err = inode->i_sb->s_op->write_inode(inode, NULL);
                        if (err)
-                               goto out_unlock;
+                               goto out_redirty;
                        /*
                         * The inode has been written, but the write-buffer has
                         * not been synchronized, so in case of an unclean
@@ -1060,11 +1060,17 @@ static int ubifs_writepage(struct page *page, struct writeback_control *wbc)
        if (i_size > synced_i_size) {
                err = inode->i_sb->s_op->write_inode(inode, NULL);
                if (err)
-                       goto out_unlock;
+                       goto out_redirty;
        }
 
        return do_writepage(page, len);
-
+out_redirty:
+       /*
+        * redirty_page_for_writepage() won't call ubifs_dirty_inode() because
+        * it passes I_DIRTY_PAGES flag while calling __mark_inode_dirty(), so
+        * there is no need to do space budget for dirty inode.
+        */
+       redirty_page_for_writepage(wbc, page);
 out_unlock:
        unlock_page(page);
        return err;
@@ -1466,14 +1472,23 @@ static bool ubifs_release_folio(struct folio *folio, gfp_t unused_gfp_flags)
        struct inode *inode = folio->mapping->host;
        struct ubifs_info *c = inode->i_sb->s_fs_info;
 
-       /*
-        * An attempt to release a dirty page without budgeting for it - should
-        * not happen.
-        */
        if (folio_test_writeback(folio))
                return false;
+
+       /*
+        * Page is private but not dirty, weird? There is one condition
+        * making it happened. ubifs_writepage skipped the page because
+        * page index beyonds isize (for example. truncated by other
+        * process named A), then the page is invalidated by fadvise64
+        * syscall before being truncated by process A.
+        */
        ubifs_assert(c, folio_test_private(folio));
-       ubifs_assert(c, 0);
+       if (folio_test_checked(folio))
+               release_new_page_budget(c);
+       else
+               release_existing_page_budget(c);
+
+       atomic_long_dec(&c->dirty_pg_cnt);
        folio_detach_private(folio);
        folio_clear_checked(folio);
        return true;