patch-2.3.99-pre9 linux/mm/filemap.c
Next file: linux/mm/highmem.c
Previous file: linux/kernel/ksyms.c
Back to the patch index
Back to the overall index
- Lines: 123
- Date:
Mon May 22 09:50:55 2000
- Orig file:
v2.3.99-pre8/linux/mm/filemap.c
- Orig date:
Fri May 12 14:18:56 2000
diff -u --recursive --new-file v2.3.99-pre8/linux/mm/filemap.c linux/mm/filemap.c
@@ -244,14 +244,19 @@
spin_unlock(&pagecache_lock);
}
+/*
+ * nr_dirty represents the number of dirty pages that we will write async
+ * before doing sync writes. We can only do sync writes if we can
+ * wait for IO (__GFP_IO set).
+ */
int shrink_mmap(int priority, int gfp_mask)
{
- int ret = 0, count;
- LIST_HEAD(old);
- struct list_head * page_lru, * dispose;
+ int ret = 0, count, nr_dirty;
+ struct list_head * page_lru;
struct page * page = NULL;
count = nr_lru_pages / (priority + 1);
+ nr_dirty = priority;
/* we need pagemap_lru_lock for list_del() ... subtle code below */
spin_lock(&pagemap_lru_lock);
@@ -259,25 +264,10 @@
page = list_entry(page_lru, struct page, lru);
list_del(page_lru);
- dispose = &lru_cache;
if (PageTestandClearReferenced(page))
goto dispose_continue;
count--;
-
- /*
- * I'm ambivalent on this one.. Should we try to
- * maintain LRU on the LRU list, and put pages that
- * are old at the end of the queue, even if that
- * means that we'll re-scan then again soon and
- * often waste CPU time? Or should be just let any
- * pages we do not want to touch now for one reason
- * or another percolate to be "young"?
- *
- dispose = &old;
- *
- */
-
/*
* Avoid unscalable SMP locking for pages we can
* immediate tell are untouchable..
@@ -303,7 +293,8 @@
* of zone - it's old.
*/
if (page->buffers) {
- if (!try_to_free_buffers(page))
+ int wait = ((gfp_mask & __GFP_IO) && (nr_dirty-- < 0));
+ if (!try_to_free_buffers(page, wait))
goto unlock_continue;
/* page was locked, inode can't go away under us */
if (!page->mapping) {
@@ -362,7 +353,7 @@
UnlockPage(page);
page_cache_release(page);
dispose_continue:
- list_add(page_lru, dispose);
+ list_add(page_lru, &lru_cache);
}
goto out;
@@ -377,8 +368,6 @@
nr_lru_pages--;
out:
- list_splice(&old, lru_cache.prev);
-
spin_unlock(&pagemap_lru_lock);
return ret;
@@ -2319,7 +2308,8 @@
return error;
}
-struct page *read_cache_page(struct address_space *mapping,
+static inline
+struct page *__read_cache_page(struct address_space *mapping,
unsigned long index,
int (*filler)(void *,struct page*),
void *data)
@@ -2347,6 +2337,35 @@
}
if (cached_page)
page_cache_free(cached_page);
+ return page;
+}
+
+/*
+ * Read into the page cache. If a page already exists,
+ * and Page_Uptodate() is not set, try to fill the page.
+ */
+struct page *read_cache_page(struct address_space *mapping,
+ unsigned long index,
+ int (*filler)(void *,struct page*),
+ void *data)
+{
+ struct page *page = __read_cache_page(mapping, index, filler, data);
+ int err;
+
+ if (IS_ERR(page) || Page_Uptodate(page))
+ goto out;
+
+ lock_page(page);
+ if (Page_Uptodate(page)) {
+ UnlockPage(page);
+ goto out;
+ }
+ err = filler(data, page);
+ if (err < 0) {
+ page_cache_release(page);
+ page = ERR_PTR(err);
+ }
+ out:
return page;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)