ufs_get_locked_page(): make sure we have buffer_heads
authorAl Viro <viro@zeniv.linux.org.uk>
Thu, 15 Jun 2017 03:32:19 +0000 (23:32 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Thu, 15 Jun 2017 03:32:19 +0000 (23:32 -0400)
callers rely upon that, but find_lock_page() racing with attempt of
page eviction by memory pressure might have left us with
* try_to_free_buffers() successfully done
* __remove_mapping() failed, leaving the page in our mapping
* find_lock_page() returning an uptodate page with no
buffer_heads attached.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/ufs/util.c

index f41ad0a6106f28a2165c94068f6c7c3d71a67b3e..02497a492eb25085fc7fcefc446ad0e9cd0f967a 100644 (file)
@@ -243,9 +243,8 @@ ufs_set_inode_dev(struct super_block *sb, struct ufs_inode_info *ufsi, dev_t dev
 struct page *ufs_get_locked_page(struct address_space *mapping,
                                 pgoff_t index)
 {
-       struct page *page;
-
-       page = find_lock_page(mapping, index);
+       struct inode *inode = mapping->host;
+       struct page *page = find_lock_page(mapping, index);
        if (!page) {
                page = read_mapping_page(mapping, index, NULL);
 
@@ -253,7 +252,7 @@ struct page *ufs_get_locked_page(struct address_space *mapping,
                        printk(KERN_ERR "ufs_change_blocknr: "
                               "read_mapping_page error: ino %lu, index: %lu\n",
                               mapping->host->i_ino, index);
-                       goto out;
+                       return page;
                }
 
                lock_page(page);
@@ -262,8 +261,7 @@ struct page *ufs_get_locked_page(struct address_space *mapping,
                        /* Truncate got there first */
                        unlock_page(page);
                        put_page(page);
-                       page = NULL;
-                       goto out;
+                       return NULL;
                }
 
                if (!PageUptodate(page) || PageError(page)) {
@@ -272,11 +270,12 @@ struct page *ufs_get_locked_page(struct address_space *mapping,
 
                        printk(KERN_ERR "ufs_change_blocknr: "
                               "can not read page: ino %lu, index: %lu\n",
-                              mapping->host->i_ino, index);
+                              inode->i_ino, index);
 
-                       page = ERR_PTR(-EIO);
+                       return ERR_PTR(-EIO);
                }
        }
-out:
+       if (!page_has_buffers(page))
+               create_empty_buffers(page, 1 << inode->i_blkbits, 0);
        return page;
 }