forked from Minki/linux
UBIFS: fix bug where page is marked uptodate when out of space
UBIFS fast path in write_begin may mark a page up to date and then discover that there may not be enough space to do the write, and so fall back to a slow path. The slow path tries harder, but may still find no space - leaving the page marked up to date, when it is not. This patch ensures that the page is marked not up to date in that case. The bug that this patch fixes becomes evident when the write is into a hole (sparse file) or is at the end of the file and a subsequent read is off the end of the file. In both cases, the file system should return zeros but was instead returning the page that had not been written because the file system was out of space. Signed-off-by: Adrian Hunter <ext-adrian.hunter@nokia.com> Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
This commit is contained in:
parent
cb4f952db3
commit
f55aa59106
@ -430,6 +430,7 @@ static int ubifs_write_begin(struct file *file, struct address_space *mapping,
|
||||
struct ubifs_inode *ui = ubifs_inode(inode);
|
||||
pgoff_t index = pos >> PAGE_CACHE_SHIFT;
|
||||
int uninitialized_var(err), appending = !!(pos + len > inode->i_size);
|
||||
int skipped_read = 0;
|
||||
struct page *page;
|
||||
|
||||
ubifs_assert(ubifs_inode(inode)->ui_size == inode->i_size);
|
||||
@ -444,7 +445,7 @@ static int ubifs_write_begin(struct file *file, struct address_space *mapping,
|
||||
|
||||
if (!PageUptodate(page)) {
|
||||
/* The page is not loaded from the flash */
|
||||
if (!(pos & ~PAGE_CACHE_MASK) && len == PAGE_CACHE_SIZE)
|
||||
if (!(pos & ~PAGE_CACHE_MASK) && len == PAGE_CACHE_SIZE) {
|
||||
/*
|
||||
* We change whole page so no need to load it. But we
|
||||
* have to set the @PG_checked flag to make the further
|
||||
@ -453,7 +454,8 @@ static int ubifs_write_begin(struct file *file, struct address_space *mapping,
|
||||
* the media.
|
||||
*/
|
||||
SetPageChecked(page);
|
||||
else {
|
||||
skipped_read = 1;
|
||||
} else {
|
||||
err = do_readpage(page);
|
||||
if (err) {
|
||||
unlock_page(page);
|
||||
@ -469,6 +471,14 @@ static int ubifs_write_begin(struct file *file, struct address_space *mapping,
|
||||
err = allocate_budget(c, page, ui, appending);
|
||||
if (unlikely(err)) {
|
||||
ubifs_assert(err == -ENOSPC);
|
||||
/*
|
||||
* If we skipped reading the page because we were going to
|
||||
* write all of it, then it is not up to date.
|
||||
*/
|
||||
if (skipped_read) {
|
||||
ClearPageChecked(page);
|
||||
ClearPageUptodate(page);
|
||||
}
|
||||
/*
|
||||
* Budgeting failed which means it would have to force
|
||||
* write-back but didn't, because we set the @fast flag in the
|
||||
|
Loading…
Reference in New Issue
Block a user