Commit f55aa59106b66cd547c8f296e0b3430ad76554c5

Authored by Adrian Hunter
Committed by Artem Bityutskiy
1 parent cb4f952db3

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>

Showing 1 changed file with 12 additions and 2 deletions Side-by-side Diff

... ... @@ -430,6 +430,7 @@
430 430 struct ubifs_inode *ui = ubifs_inode(inode);
431 431 pgoff_t index = pos >> PAGE_CACHE_SHIFT;
432 432 int uninitialized_var(err), appending = !!(pos + len > inode->i_size);
  433 + int skipped_read = 0;
433 434 struct page *page;
434 435  
435 436 ubifs_assert(ubifs_inode(inode)->ui_size == inode->i_size);
... ... @@ -444,7 +445,7 @@
444 445  
445 446 if (!PageUptodate(page)) {
446 447 /* The page is not loaded from the flash */
447   - if (!(pos & ~PAGE_CACHE_MASK) && len == PAGE_CACHE_SIZE)
  448 + if (!(pos & ~PAGE_CACHE_MASK) && len == PAGE_CACHE_SIZE) {
448 449 /*
449 450 * We change whole page so no need to load it. But we
450 451 * have to set the @PG_checked flag to make the further
... ... @@ -453,7 +454,8 @@
453 454 * the media.
454 455 */
455 456 SetPageChecked(page);
456   - else {
  457 + skipped_read = 1;
  458 + } else {
457 459 err = do_readpage(page);
458 460 if (err) {
459 461 unlock_page(page);
... ... @@ -469,6 +471,14 @@
469 471 err = allocate_budget(c, page, ui, appending);
470 472 if (unlikely(err)) {
471 473 ubifs_assert(err == -ENOSPC);
  474 + /*
  475 + * If we skipped reading the page because we were going to
  476 + * write all of it, then it is not up to date.
  477 + */
  478 + if (skipped_read) {
  479 + ClearPageChecked(page);
  480 + ClearPageUptodate(page);
  481 + }
472 482 /*
473 483 * Budgeting failed which means it would have to force
474 484 * write-back but didn't, because we set the @fast flag in the