patch-2.3.11 linux/ipc/shm.c
Next file: linux/kernel/exit.c
Previous file: linux/init/main.c
Back to the patch index
Back to the overall index
- Lines: 121
- Date:
Tue Jul 13 09:25:59 1999
- Orig file:
v2.3.10/linux/ipc/shm.c
- Orig date:
Thu Jul 8 15:42:21 1999
diff -u --recursive --new-file v2.3.10/linux/ipc/shm.c linux/ipc/shm.c
@@ -15,6 +15,7 @@
#include <linux/smp_lock.h>
#include <linux/init.h>
#include <linux/vmalloc.h>
+#include <linux/pagemap.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
@@ -626,6 +627,8 @@
pte_t pte;
struct shmid_kernel *shp;
unsigned int id, idx;
+ unsigned long page;
+ struct page * page_map;
id = SWP_OFFSET(shmd->vm_pte) & SHM_ID_MASK;
idx = (address - shmd->vm_start + shmd->vm_offset) >> PAGE_SHIFT;
@@ -649,26 +652,32 @@
}
#endif
+ lock_kernel();
+ again:
pte = __pte(shp->shm_pages[idx]);
if (!pte_present(pte)) {
- unsigned long page = get_free_page(GFP_USER);
- if (!page) {
- oom(current);
- return 0;
- }
- pte = __pte(shp->shm_pages[idx]);
- if (pte_present(pte)) {
- free_page (page); /* doesn't sleep */
- goto done;
- }
- if (!pte_none(pte)) {
- rw_swap_page_nocache(READ, pte_val(pte), (char *)page);
- pte = __pte(shp->shm_pages[idx]);
- if (pte_present(pte)) {
- free_page (page); /* doesn't sleep */
- goto done;
+ if (pte_none(pte)) {
+ page = get_free_page(GFP_USER);
+ if (!page)
+ goto oom;
+ if (pte_val(pte) != shp->shm_pages[idx])
+ goto changed;
+ } else {
+ unsigned long entry = pte_val(pte);
+
+ page_map = lookup_swap_cache(entry);
+ if (!page_map) {
+ swapin_readahead(entry);
+ page_map = read_swap_cache(entry);
}
- swap_free(pte_val(pte));
+ pte = __pte(shp->shm_pages[idx]);
+ page = page_address(page_map);
+ if (pte_present(pte))
+ goto present;
+ if (!page_map)
+ goto oom;
+ delete_from_swap_cache(page_map);
+ swap_free(entry);
shm_swp--;
}
shm_rss++;
@@ -678,9 +687,21 @@
--current->maj_flt; /* was incremented in do_no_page */
done: /* pte_val(pte) == shp->shm_pages[idx] */
+ unlock_kernel();
current->min_flt++;
get_page(mem_map + MAP_NR(pte_page(pte)));
return pte_page(pte);
+
+changed:
+ free_page(page);
+ goto again;
+present:
+ if (page_map)
+ free_page_and_swap_cache(page);
+ goto done;
+oom:
+ unlock_kernel();
+ return -1;
}
/*
@@ -697,6 +718,7 @@
unsigned long id, idx;
int loop = 0;
int counter;
+ struct page * page_map;
counter = shm_rss >> prio;
if (!counter || !(swap_nr = get_swap_page()))
@@ -725,7 +747,8 @@
page = __pte(shp->shm_pages[idx]);
if (!pte_present(page))
goto check_table;
- if ((gfp_mask & __GFP_DMA) && !PageDMA(&mem_map[MAP_NR(pte_page(page))]))
+ page_map = &mem_map[MAP_NR(pte_page(page))];
+ if ((gfp_mask & __GFP_DMA) && !PageDMA(page_map))
goto check_table;
swap_attempts++;
@@ -737,8 +760,11 @@
if (page_count(mem_map + MAP_NR(pte_page(page))) != 1)
goto check_table;
shp->shm_pages[idx] = swap_nr;
- rw_swap_page_nocache (WRITE, swap_nr, (char *) pte_page(page));
- free_page(pte_page(page));
+ swap_duplicate(swap_nr);
+ add_to_swap_cache(page_map, swap_nr);
+ rw_swap_page(WRITE, page_map, 0);
+
+ __free_page(page_map);
swap_successes++;
shm_swp++;
shm_rss--;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)