Merge tag 'folio-5.19' of git://git.infradead.org/users/willy/pagecache
[linux-2.6-microblaze.git] / fs / ext4 / inline.c
index 9c07626..cff52ff 100644 (file)
@@ -527,13 +527,13 @@ int ext4_readpage_inline(struct inode *inode, struct page *page)
 }
 
 static int ext4_convert_inline_data_to_extent(struct address_space *mapping,
-                                             struct inode *inode,
-                                             unsigned flags)
+                                             struct inode *inode)
 {
        int ret, needed_blocks, no_expand;
        handle_t *handle = NULL;
        int retries = 0, sem_held = 0;
        struct page *page = NULL;
+       unsigned int flags;
        unsigned from, to;
        struct ext4_iloc iloc;
 
@@ -562,9 +562,9 @@ retry:
 
        /* We cannot recurse into the filesystem as the transaction is already
         * started */
-       flags |= AOP_FLAG_NOFS;
-
-       page = grab_cache_page_write_begin(mapping, 0, flags);
+       flags = memalloc_nofs_save();
+       page = grab_cache_page_write_begin(mapping, 0);
+       memalloc_nofs_restore(flags);
        if (!page) {
                ret = -ENOMEM;
                goto out;
@@ -649,11 +649,11 @@ out:
 int ext4_try_to_write_inline_data(struct address_space *mapping,
                                  struct inode *inode,
                                  loff_t pos, unsigned len,
-                                 unsigned flags,
                                  struct page **pagep)
 {
        int ret;
        handle_t *handle;
+       unsigned int flags;
        struct page *page;
        struct ext4_iloc iloc;
 
@@ -691,9 +691,9 @@ int ext4_try_to_write_inline_data(struct address_space *mapping,
        if (ret)
                goto out;
 
-       flags |= AOP_FLAG_NOFS;
-
-       page = grab_cache_page_write_begin(mapping, 0, flags);
+       flags = memalloc_nofs_save();
+       page = grab_cache_page_write_begin(mapping, 0);
+       memalloc_nofs_restore(flags);
        if (!page) {
                ret = -ENOMEM;
                goto out;
@@ -727,8 +727,7 @@ out:
        brelse(iloc.bh);
        return ret;
 convert:
-       return ext4_convert_inline_data_to_extent(mapping,
-                                                 inode, flags);
+       return ext4_convert_inline_data_to_extent(mapping, inode);
 }
 
 int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned len,
@@ -848,13 +847,12 @@ ext4_journalled_write_inline_data(struct inode *inode,
  */
 static int ext4_da_convert_inline_data_to_extent(struct address_space *mapping,
                                                 struct inode *inode,
-                                                unsigned flags,
                                                 void **fsdata)
 {
        int ret = 0, inline_size;
        struct page *page;
 
-       page = grab_cache_page_write_begin(mapping, 0, flags);
+       page = grab_cache_page_write_begin(mapping, 0);
        if (!page)
                return -ENOMEM;
 
@@ -907,7 +905,6 @@ out:
 int ext4_da_write_inline_data_begin(struct address_space *mapping,
                                    struct inode *inode,
                                    loff_t pos, unsigned len,
-                                   unsigned flags,
                                    struct page **pagep,
                                    void **fsdata)
 {
@@ -916,6 +913,7 @@ int ext4_da_write_inline_data_begin(struct address_space *mapping,
        struct page *page;
        struct ext4_iloc iloc;
        int retries = 0;
+       unsigned int flags;
 
        ret = ext4_get_inode_loc(inode, &iloc);
        if (ret)
@@ -932,17 +930,10 @@ retry_journal:
        if (ret && ret != -ENOSPC)
                goto out_journal;
 
-       /*
-        * We cannot recurse into the filesystem as the transaction
-        * is already started.
-        */
-       flags |= AOP_FLAG_NOFS;
-
        if (ret == -ENOSPC) {
                ext4_journal_stop(handle);
                ret = ext4_da_convert_inline_data_to_extent(mapping,
                                                            inode,
-                                                           flags,
                                                            fsdata);
                if (ret == -ENOSPC &&
                    ext4_should_retry_alloc(inode->i_sb, &retries))
@@ -950,7 +941,13 @@ retry_journal:
                goto out;
        }
 
-       page = grab_cache_page_write_begin(mapping, 0, flags);
+       /*
+        * 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_journal;
@@ -1083,14 +1080,14 @@ static void ext4_update_final_de(void *de_buf, int old_size, int new_size)
        void *limit;
        int de_len;
 
-       de = (struct ext4_dir_entry_2 *)de_buf;
+       de = de_buf;
        if (old_size) {
                limit = de_buf + old_size;
                do {
                        prev_de = de;
                        de_len = ext4_rec_len_from_disk(de->rec_len, old_size);
                        de_buf += de_len;
-                       de = (struct ext4_dir_entry_2 *)de_buf;
+                       de = de_buf;
                } while (de_buf < limit);
 
                prev_de->rec_len = ext4_rec_len_to_disk(de_len + new_size -
@@ -1155,7 +1152,7 @@ static int ext4_finish_convert_inline_dir(handle_t *handle,
         * First create "." and ".." and then copy the dir information
         * back to the block.
         */
-       de = (struct ext4_dir_entry_2 *)target;
+       de = target;
        de = ext4_init_dot_dotdot(inode, de,
                inode->i_sb->s_blocksize, csum_size,
                le32_to_cpu(((struct ext4_dir_entry_2 *)buf)->inode), 1);
@@ -2005,6 +2002,18 @@ int ext4_convert_inline_data(struct inode *inode)
        if (!ext4_has_inline_data(inode)) {
                ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);
                return 0;
+       } else if (!ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) {
+               /*
+                * Inode has inline data but EXT4_STATE_MAY_INLINE_DATA is
+                * cleared. This means we are in the middle of moving of
+                * inline data to delay allocated block. Just force writeout
+                * here to finish conversion.
+                */
+               error = filemap_flush(inode->i_mapping);
+               if (error)
+                       return error;
+               if (!ext4_has_inline_data(inode))
+                       return 0;
        }
 
        needed_blocks = ext4_writepage_trans_blocks(inode);