diff options
| author | Al Viro <viro@zeniv.linux.org.uk> | 2017-06-14 23:32:19 -0400 |
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2017-06-14 23:32:19 -0400 |
| commit | 267309f394bf3cd8db001992890b1fa52b97974e (patch) | |
| tree | 1d9917f5ac2b5a6c68607074aaab6bcd1c78452e | |
| parent | c596961d1b4ccc6f15754fe5a49c37ac6da57145 (diff) | |
ufs_get_locked_page(): make sure we have buffer_heads
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>
| -rw-r--r-- | fs/ufs/util.c | 17 |
1 files changed, 8 insertions, 9 deletions
diff --git a/fs/ufs/util.c b/fs/ufs/util.c index f41ad0a6106f..02497a492eb2 100644 --- a/fs/ufs/util.c +++ b/fs/ufs/util.c | |||
| @@ -243,9 +243,8 @@ ufs_set_inode_dev(struct super_block *sb, struct ufs_inode_info *ufsi, dev_t dev | |||
| 243 | struct page *ufs_get_locked_page(struct address_space *mapping, | 243 | struct page *ufs_get_locked_page(struct address_space *mapping, |
| 244 | pgoff_t index) | 244 | pgoff_t index) |
| 245 | { | 245 | { |
| 246 | struct page *page; | 246 | struct inode *inode = mapping->host; |
| 247 | 247 | struct page *page = find_lock_page(mapping, index); | |
| 248 | page = find_lock_page(mapping, index); | ||
| 249 | if (!page) { | 248 | if (!page) { |
| 250 | page = read_mapping_page(mapping, index, NULL); | 249 | page = read_mapping_page(mapping, index, NULL); |
| 251 | 250 | ||
| @@ -253,7 +252,7 @@ struct page *ufs_get_locked_page(struct address_space *mapping, | |||
| 253 | printk(KERN_ERR "ufs_change_blocknr: " | 252 | printk(KERN_ERR "ufs_change_blocknr: " |
| 254 | "read_mapping_page error: ino %lu, index: %lu\n", | 253 | "read_mapping_page error: ino %lu, index: %lu\n", |
| 255 | mapping->host->i_ino, index); | 254 | mapping->host->i_ino, index); |
| 256 | goto out; | 255 | return page; |
| 257 | } | 256 | } |
| 258 | 257 | ||
| 259 | lock_page(page); | 258 | lock_page(page); |
| @@ -262,8 +261,7 @@ struct page *ufs_get_locked_page(struct address_space *mapping, | |||
| 262 | /* Truncate got there first */ | 261 | /* Truncate got there first */ |
| 263 | unlock_page(page); | 262 | unlock_page(page); |
| 264 | put_page(page); | 263 | put_page(page); |
| 265 | page = NULL; | 264 | return NULL; |
| 266 | goto out; | ||
| 267 | } | 265 | } |
| 268 | 266 | ||
| 269 | if (!PageUptodate(page) || PageError(page)) { | 267 | if (!PageUptodate(page) || PageError(page)) { |
| @@ -272,11 +270,12 @@ struct page *ufs_get_locked_page(struct address_space *mapping, | |||
| 272 | 270 | ||
| 273 | printk(KERN_ERR "ufs_change_blocknr: " | 271 | printk(KERN_ERR "ufs_change_blocknr: " |
| 274 | "can not read page: ino %lu, index: %lu\n", | 272 | "can not read page: ino %lu, index: %lu\n", |
| 275 | mapping->host->i_ino, index); | 273 | inode->i_ino, index); |
| 276 | 274 | ||
| 277 | page = ERR_PTR(-EIO); | 275 | return ERR_PTR(-EIO); |
| 278 | } | 276 | } |
| 279 | } | 277 | } |
| 280 | out: | 278 | if (!page_has_buffers(page)) |
| 279 | create_empty_buffers(page, 1 << inode->i_blkbits, 0); | ||
| 281 | return page; | 280 | return page; |
| 282 | } | 281 | } |
