From: Suparna Bhattacharya The attached patch helped fix some short writes I was seeing with O_SYNC and AIO. Most likely this happened in the situation when pagevec_lookup() didn't find all the pages being looked up in the page cache. In that situation accounting of how much of the range was written back wasn't being taken care of correctly. 25-akpm/mm/page-writeback.c | 19 ++++++++++--------- 1 files changed, 10 insertions(+), 9 deletions(-) diff -puN mm/page-writeback.c~aio-O_SYNC-short-write-fix mm/page-writeback.c --- 25/mm/page-writeback.c~aio-O_SYNC-short-write-fix Thu Oct 9 02:05:30 2003 +++ 25-akpm/mm/page-writeback.c Thu Oct 9 02:05:30 2003 @@ -585,19 +585,19 @@ static ssize_t operate_on_page_range(str pgoff_t next = first, curr = first; struct pagevec pvec; ssize_t ret = 0, bytes = 0; - int i; + int i, nr; if (count == 0) return 0; pagevec_init(&pvec, 0); - while (pagevec_lookup(&pvec, mapping, &next, - min((pgoff_t)PAGEVEC_SIZE, last - next + 1))) { + while ((nr = pagevec_lookup(&pvec, mapping, &next, + min((pgoff_t)PAGEVEC_SIZE, last - next + 1)))) { for (i = 0; i < pagevec_count(&pvec); i++) { struct page *page = pvec.pages[i]; curr = page->index; - if ((curr > next) || !page->mapping) /* truncated ?*/ { + if (page->mapping != mapping) /* truncated ?*/ { curr = next; break; } else { @@ -607,16 +607,17 @@ static ssize_t operate_on_page_range(str if (PageError(page)) { if (!ret) ret = -EIO; - } + } else + curr++; } - curr++; - if (next > last) - break; } pagevec_release(&pvec); - if ((next > last) || (ret == -EIOCBRETRY)) + if ((ret == -EIOCBRETRY) || (next > last)) break; } + if (!nr) + curr = last + 1; + bytes = (curr << PAGE_CACHE_SHIFT) - pos; if (bytes > count) bytes = count; _