patch-2.4.0-test8 linux/mm/filemap.c
Next file: linux/mm/memory.c
Previous file: linux/mm/bootmem.c
Back to the patch index
Back to the overall index
- Lines: 148
- Date:
Fri Sep 8 12:37:34 2000
- Orig file:
v2.4.0-test7/linux/mm/filemap.c
- Orig date:
Wed Aug 23 18:36:39 2000
diff -u --recursive --new-file v2.4.0-test7/linux/mm/filemap.c linux/mm/filemap.c
@@ -146,9 +146,40 @@
spin_unlock(&pagecache_lock);
}
-/*
+static inline void truncate_partial_page(struct page *page, unsigned partial)
+{
+ memclear_highpage_flush(page, partial, PAGE_CACHE_SIZE-partial);
+
+ if (page->buffers)
+ block_flushpage(page, partial);
+
+}
+
+static inline void truncate_complete_page(struct page *page)
+{
+ if (!page->buffers || block_flushpage(page, 0))
+ lru_cache_del(page);
+
+ /*
+ * We remove the page from the page cache _after_ we have
+ * destroyed all buffer-cache references to it. Otherwise some
+ * other process might think this inode page is not in the
+ * page cache and creates a buffer-cache alias to it causing
+ * all sorts of fun problems ...
+ */
+ ClearPageDirty(page);
+ remove_inode_page(page);
+ page_cache_release(page);
+}
+
+/**
+ * truncate_inode_pages - truncate *all* the pages from an offset
+ * @mapping: mapping to truncate
+ * @lstart: offset from with to truncate
+ *
* Truncate the page cache at a set offset, removing the pages
* that are beyond that offset (and zeroing out partial pages).
+ * If any page is locked we wait for it to become unlocked.
*/
void truncate_inode_pages(struct address_space * mapping, loff_t lstart)
{
@@ -168,11 +199,10 @@
page = list_entry(curr, struct page, list);
curr = curr->next;
-
offset = page->index;
- /* page wholly truncated - free it */
- if (offset >= start) {
+ /* Is one of the pages to truncate? */
+ if ((offset >= start) || (partial && (offset + 1) == start)) {
if (TryLockPage(page)) {
page_cache_get(page);
spin_unlock(&pagecache_lock);
@@ -183,23 +213,14 @@
page_cache_get(page);
spin_unlock(&pagecache_lock);
- if (!page->buffers || block_flushpage(page, 0))
- lru_cache_del(page);
-
- /*
- * We remove the page from the page cache
- * _after_ we have destroyed all buffer-cache
- * references to it. Otherwise some other process
- * might think this inode page is not in the
- * page cache and creates a buffer-cache alias
- * to it causing all sorts of fun problems ...
- */
- remove_inode_page(page);
- ClearPageDirty(page);
+ if (partial && (offset + 1) == start) {
+ truncate_partial_page(page, partial);
+ partial = 0;
+ } else
+ truncate_complete_page(page);
UnlockPage(page);
page_cache_release(page);
- page_cache_release(page);
/*
* We have done things without the pagecache lock,
@@ -210,37 +231,6 @@
*/
goto repeat;
}
- /*
- * there is only one partial page possible.
- */
- if (!partial)
- continue;
-
- /* and it's the one preceeding the first wholly truncated page */
- if ((offset + 1) != start)
- continue;
-
- /* partial truncate, clear end of page */
- if (TryLockPage(page)) {
- spin_unlock(&pagecache_lock);
- goto repeat;
- }
- page_cache_get(page);
- spin_unlock(&pagecache_lock);
-
- memclear_highpage_flush(page, partial, PAGE_CACHE_SIZE-partial);
- if (page->buffers)
- block_flushpage(page, partial);
-
- partial = 0;
-
- /*
- * we have dropped the spinlock so we have to
- * restart.
- */
- UnlockPage(page);
- page_cache_release(page);
- goto repeat;
}
spin_unlock(&pagecache_lock);
}
@@ -895,7 +885,7 @@
* page only.
*/
if (PageLocked(page)) {
- if (!filp->f_ralen || index >= raend || index + filp->f_ralen < raend) {
+ if (!filp->f_ralen || index >= raend || index + filp->f_rawin < raend) {
raend = index;
if (raend < end_index)
max_ahead = filp->f_ramax;
@@ -1072,7 +1062,15 @@
if (!Page_Uptodate(page))
goto page_not_up_to_date;
+ generic_file_readahead(reada_ok, filp, inode, page);
page_ok:
+ /* If users can be writing to this page using arbitrary
+ * virtual addresses, take care about potential aliasing
+ * before reading the page on the kernel side.
+ */
+ if (page->mapping->i_mmap_shared != NULL)
+ flush_dcache_page(page);
+
/*
* Ok, we have the page, and it's up-to-date, so
* now we can copy it to user space...
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)