patch-1.3.56 linux/mm/filemap.c
Next file: linux/mm/memory.c
Previous file: linux/include/linux/pagemap.h
Back to the patch index
Back to the overall index
- Lines: 172
- Date:
Mon Jan 8 08:14:54 1996
- Orig file:
v1.3.55/linux/mm/filemap.c
- Orig date:
Sat Jan 6 19:10:42 1996
diff -u --recursive --new-file v1.3.55/linux/mm/filemap.c linux/mm/filemap.c
@@ -88,7 +88,7 @@
if (page->count != 1)
age |= PAGE_AGE_VALUE << 1;
page->age = age >> 1;
- if (age <= PAGE_AGE_VALUE/2) {
+ if (age < PAGE_AGE_VALUE) {
remove_page_from_hash_queue(page);
remove_page_from_inode_queue(page);
free_page(page_address(page));
@@ -147,51 +147,47 @@
}
/*
- * Find a cached page and wait for it to become up-to-date, return
- * the page address.
- *
- * If no cached page can be found, create one using the supplied
- * new page instead (and return zero to indicate that we used the
- * supplied page in doing so).
+ * Try to read ahead in the file. "page_cache" is a potentially free page
+ * that we could use for the cache (if it is 0 we can try to create one,
+ * this is all overlapped with the IO on the previous page finishing anyway)
*/
-static unsigned long fill_page(struct inode * inode, unsigned long offset, unsigned long newpage)
+static unsigned long try_to_read_ahead(struct inode * inode, unsigned long offset, unsigned long page_cache)
{
struct page * page;
+ if (!page_cache) {
+ page_cache = __get_free_page(GFP_KERNEL);
+ if (!page_cache)
+ return 0;
+ }
+#ifdef readahead_makes_sense_due_to_asynchronous_reads
+ offset = (offset + PAGE_SIZE) & PAGE_MASK;
page = find_page(inode, offset);
if (page) {
- if (!page->uptodate)
- sleep_on(&page->wait);
- return page_address(page);
+ page->count--;
+ return page_cache;
}
- page = mem_map + MAP_NR(newpage);
+ /*
+ * Ok, add the new page to the hash-queues...
+ */
+ page = mem_map + MAP_NR(page_cache);
page->count++;
page->uptodate = 0;
page->error = 0;
page->offset = offset;
add_page_to_inode_queue(inode, page);
add_page_to_hash_queue(inode, page);
- inode->i_op->readpage(inode, page);
- page->uptodate = 1;
- wake_up(&page->wait);
- return 0;
-}
-/*
- * Try to read ahead in the file. "page_cache" is a potentially free page
- * that we could use for the cache (if it is 0 we can try to create one,
- * this is all overlapped with the IO on the previous page finishing anyway)
- */
-static unsigned long try_to_read_ahead(struct inode * inode, unsigned long offset, unsigned long page_cache)
-{
- if (!page_cache)
- page_cache = __get_free_page(GFP_KERNEL);
- offset = (offset + PAGE_SIZE) & PAGE_MASK;
- /*
- * read-ahead is not implemented yet, but this is
- * where we should start..
+ /*
+ * And start IO on it..
+ * (this should be asynchronous, but currently isn't)
*/
+ inode->i_op->readpage(inode, page);
+ free_page(page_cache);
+ return 0;
+#else
return page_cache;
+#endif
}
/*
@@ -294,41 +290,63 @@
}
/*
+ * Find a cached page and wait for it to become up-to-date, return
+ * the page address.
+ */
+static inline unsigned long fill_page(struct inode * inode, unsigned long offset)
+{
+ struct page * page;
+ unsigned long new_page;
+
+ page = find_page(inode, offset);
+ if (page)
+ goto found_page;
+ new_page = __get_free_page(GFP_KERNEL);
+ page = find_page(inode, offset);
+ if (page) {
+ if (new_page)
+ free_page(new_page);
+ goto found_page;
+ }
+ if (!new_page)
+ return 0;
+ page = mem_map + MAP_NR(new_page);
+ new_page = 0;
+ page->count++;
+ page->uptodate = 0;
+ page->error = 0;
+ page->offset = offset;
+ add_page_to_inode_queue(inode, page);
+ add_page_to_hash_queue(inode, page);
+ inode->i_op->readpage(inode, page);
+found_page:
+ if (!page->uptodate)
+ sleep_on(&page->wait);
+ return page_address(page);
+}
+
+/*
* Semantics for shared and private memory areas are different past the end
* of the file. A shared mapping past the last page of the file is an error
* and results in a SIBGUS, while a private mapping just maps in a zero page.
*/
-static unsigned long filemap_nopage(struct vm_area_struct * area, unsigned long address,
- unsigned long page, int no_share)
+static unsigned long filemap_nopage(struct vm_area_struct * area, unsigned long address, int no_share)
{
unsigned long offset;
struct inode * inode = area->vm_inode;
- unsigned long new_page;
+ unsigned long page;
offset = (address & PAGE_MASK) - area->vm_start + area->vm_offset;
if (offset >= inode->i_size && (area->vm_flags & VM_SHARED) && area->vm_mm == current->mm)
- send_sig(SIGBUS, current, 1);
+ return 0;
- new_page = fill_page(inode, offset, page);
- if (new_page) {
- if (no_share) {
- memcpy((void *) page, (void *) new_page, PAGE_SIZE);
- free_page(new_page);
- return page;
- }
+ page = fill_page(inode, offset);
+ if (page && no_share) {
+ unsigned long new_page = __get_free_page(GFP_KERNEL);
+ if (new_page)
+ memcpy((void *) new_page, (void *) page, PAGE_SIZE);
free_page(page);
return new_page;
- }
-
- if (no_share) {
- new_page = __get_free_page(GFP_USER);
- if (!new_page) {
- oom(current);
- new_page = pte_page(BAD_PAGE);
- }
- memcpy((void *) new_page, (void *) page, PAGE_SIZE);
- free_page(page);
- page = new_page;
}
return page;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this