From: Christoph Rohland <cr@sap.com>
To: Rik van Riel <riel@conectiva.com.br>
Cc: "Stephen C. Tweedie" <sct@redhat.com>, linux-mm@kvack.org
Subject: [PATCH,incomplete] shm integration into shrink_mmap
Date: 08 Jun 2000 17:04:24 +0200 [thread overview]
Message-ID: <qwwg0qob4ef.fsf_-_@sap.com> (raw)
In-Reply-To: "Stephen C. Tweedie"'s message of "Wed, 7 Jun 2000 15:43:50 +0100"
[-- Attachment #1: Type: text/plain, Size: 718 bytes --]
Hi Rik,
Here is my first proposal for changing shm to be integrated into
shrink_mmap.
It gives you a function 'int shm_write_swap (struct page *page)' to
write out a page to swap and replace the pte in the shm structures. I
tested the stuff with no swapping and it seems stable so far. But
shm_write_swap is completely untested.
It probably needs to add the pages in shm_nopage_core to your lru
queues and of course it needs the calls from shrink_mmap.
I think it would be nicer to only have a notify function instead of
shm_write_swap, which gets the page and the swap_entry and can simply
put the swap_entry into the shm structures without handling the
swapping at all.
What do you think?
Christoph
[-- Attachment #2: patch-shm_shrink_mmap --]
[-- Type: text/plain, Size: 8385 bytes --]
diff -uNr 4-1-ac10/include/linux/mm.h c/include/linux/mm.h
--- 4-1-ac10/include/linux/mm.h Wed Jun 7 11:47:52 2000
+++ c/include/linux/mm.h Thu Jun 8 10:20:52 2000
@@ -176,6 +176,7 @@
#define PG_skip 10
#define PG_unused_03 11
#define PG_highmem 12
+#define PG_shm 13
/* bits 21-30 unused */
#define PG_reserved 31
@@ -220,6 +221,9 @@
#define PageClearSwapCache(page) clear_bit(PG_swap_cache, &(page)->flags)
#define PageTestandClearSwapCache(page) test_and_clear_bit(PG_swap_cache, &(page)->flags)
+
+#define PageSHM(page) test_bit(PG_shm, &(page)->flags)
+#define SetPageSHM(page) set_bit(PG_shm, &(page)->flags)
#ifdef CONFIG_HIGHMEM
#define PageHighMem(page) test_bit(PG_highmem, &(page)->flags)
diff -uNr 4-1-ac10/ipc/shm.c c/ipc/shm.c
--- 4-1-ac10/ipc/shm.c Wed Jun 7 11:43:52 2000
+++ c/ipc/shm.c Thu Jun 8 15:12:00 2000
@@ -81,6 +81,7 @@
unsigned long shm_npages; /* size of segment (pages) */
pte_t **shm_dir; /* ptr to arr of ptrs to frames */
int id;
+ struct address_space mapping;
union permap {
struct shmem {
time_t atime;
@@ -130,7 +131,6 @@
static int sysvipc_shm_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data);
#endif
-static void zshm_swap (int prio, int gfp_mask);
static void zmap_unuse(swp_entry_t entry, struct page *page);
static void shmzero_open(struct vm_area_struct *shmd);
static void shmzero_close(struct vm_area_struct *shmd);
@@ -628,7 +628,9 @@
if (pte_none(pte))
continue;
if (pte_present(pte)) {
- __free_page (pte_page(pte));
+ struct page *page = pte_page(pte);
+ page->mapping = NULL; /* make __free_pages_ok happy */
+ __free_page (page);
rss++;
} else {
swap_free(pte_to_swp_entry(pte));
@@ -744,6 +746,12 @@
shp->shm_npages = numpages;
shp->shm_nattch = 0;
shp->shm_namelen = namelen;
+ INIT_LIST_HEAD (&shp->mapping.pages);
+ shp->mapping.nrpages = 0;
+ shp->mapping.a_ops = NULL;
+ shp->mapping.host = (void *) shp;
+ shp->mapping.i_mmap = NULL;
+ spin_lock_init(&shp->mapping.i_shared_lock);
return(shp);
}
@@ -1441,6 +1449,9 @@
(*swp)--;
}
(*rss)++;
+ SetPageSHM(page);
+ page->mapping = &shp->mapping;
+ page->index = idx;
pte = pte_mkdirty(mk_pte(page, PAGE_SHARED));
SHM_ENTRY(shp, idx) = pte;
}
@@ -1473,124 +1484,55 @@
return(page);
}
-#define OKAY 0
-#define RETRY 1
-#define FAILED 2
-
-static int shm_swap_core(struct shmid_kernel *shp, unsigned long idx, swp_entry_t swap_entry, int *counter, struct page **outpage)
-{
- pte_t page;
- struct page *page_map;
-
- page = SHM_ENTRY(shp, idx);
- if (!pte_present(page))
- return RETRY;
- page_map = pte_page(page);
- if (page_map->zone->free_pages > page_map->zone->pages_high)
- return RETRY;
- if (shp->id != zero_id) swap_attempts++;
-
- if (--counter < 0) /* failed */
- return FAILED;
- if (page_count(page_map) != 1)
- return RETRY;
-
- lock_page(page_map);
- if (!(page_map = prepare_highmem_swapout(page_map)))
- return FAILED;
- SHM_ENTRY (shp, idx) = swp_entry_to_pte(swap_entry);
-
- /* add the locked page to the swap cache before allowing
- the swapin path to run lookup_swap_cache(). This avoids
- reading a not yet uptodate block from disk.
- NOTE: we just accounted the swap space reference for this
- swap cache page at __get_swap_page() time. */
- add_to_swap_cache(*outpage = page_map, swap_entry);
- return OKAY;
-}
-
-static void shm_swap_postop(struct page *page)
+int shm_write_swap (struct page *page)
{
- lock_kernel();
- rw_swap_page(WRITE, page, 0);
- unlock_kernel();
- page_cache_release(page);
-}
+ struct shmid_kernel *shp;
+ swp_entry_t swap_entry;
+ unsigned long idx;
+
+ if (!PageSHM (page))
+ BUG();
-static int shm_swap_preop(swp_entry_t *swap_entry)
-{
lock_kernel();
/* subtle: preload the swap count for the swap cache. We can't
increase the count inside the critical section as we can't release
the shm_lock there. And we can't acquire the big lock with the
shm_lock held (otherwise we would deadlock too easily). */
- *swap_entry = __get_swap_page(2);
- if (!(*swap_entry).val) {
+ swap_entry = __get_swap_page(2);
+ if (!swap_entry.val) {
unlock_kernel();
- return 1;
+ return 0;
}
unlock_kernel();
- return 0;
-}
-
-/*
- * Goes through counter = (shm_rss / (prio + 1)) present shm pages.
- */
-static unsigned long swap_id; /* currently being swapped */
-static unsigned long swap_idx; /* next to swap */
-int shm_swap (int prio, int gfp_mask)
-{
- struct shmid_kernel *shp;
- swp_entry_t swap_entry;
- unsigned long id, idx;
- int loop = 0;
- int counter;
- struct page * page_map;
-
- zshm_swap(prio, gfp_mask);
- counter = shm_rss / (prio + 1);
- if (!counter)
- return 0;
- if (shm_swap_preop(&swap_entry))
- return 0;
+ shp = (struct shmid_kernel *) page->mapping->host;
+ idx = page->index;
+ if (shp->id != zero_id) swap_attempts++;
+ lock_page(page);
+ if (!(page = prepare_highmem_swapout(page)))
+ goto err;
shm_lockall();
-check_id:
- shp = shm_get(swap_id);
- if(shp==NULL || shp->shm_flags & PRV_LOCKED) {
-next_id:
- swap_idx = 0;
- if (++swap_id > shm_ids.max_id) {
- swap_id = 0;
- if (loop) {
-failed:
- shm_unlockall();
- __swap_free(swap_entry, 2);
- return 0;
- }
- loop = 1;
- }
- goto check_id;
- }
- id = swap_id;
-
-check_table:
- idx = swap_idx++;
- if (idx >= shp->shm_npages)
- goto next_id;
-
- switch (shm_swap_core(shp, idx, swap_entry, &counter, &page_map)) {
- case RETRY: goto check_table;
- case FAILED: goto failed;
- }
+ SHM_ENTRY (shp, idx) = swp_entry_to_pte(swap_entry);
swap_successes++;
shm_swp++;
shm_rss--;
shm_unlockall();
- shm_swap_postop(page_map);
+ /* add the locked page to the swap cache before allowing
+ the swapin path to run lookup_swap_cache(). This avoids
+ reading a not yet uptodate block from disk.
+ NOTE: we just accounted the swap space reference for this
+ swap cache page at __get_swap_page() time. */
+ add_to_swap_cache(page, swap_entry);
+ lock_kernel();
+ rw_swap_page(WRITE, page, 0);
+ unlock_kernel();
+ page_cache_release(page);
return 1;
+err:
+ __swap_free(swap_entry, 2);
+ return 0;
}
/*
@@ -1718,7 +1660,6 @@
#define VMA_TO_SHP(vma) ((vma)->vm_file->private_data)
static spinlock_t zmap_list_lock = SPIN_LOCK_UNLOCKED;
-static unsigned long zswap_idx; /* next to swap */
static struct shmid_kernel *zswap_shp = &zshmid_kernel;
static int zshm_rss;
@@ -1864,63 +1805,5 @@
}
shm_unlock(zero_id);
spin_unlock(&zmap_list_lock);
-}
-
-static void zshm_swap (int prio, int gfp_mask)
-{
- struct shmid_kernel *shp;
- swp_entry_t swap_entry;
- unsigned long idx;
- int loop = 0;
- int counter;
- struct page * page_map;
-
- counter = zshm_rss / (prio + 1);
- if (!counter)
- return;
-next:
- if (shm_swap_preop(&swap_entry))
- return;
-
- spin_lock(&zmap_list_lock);
- shm_lock(zero_id);
- if (zshmid_kernel.zero_list.next == 0)
- goto failed;
-next_id:
- if (zswap_shp == &zshmid_kernel) {
- if (loop) {
-failed:
- shm_unlock(zero_id);
- spin_unlock(&zmap_list_lock);
- __swap_free(swap_entry, 2);
- return;
- }
- zswap_shp = list_entry(zshmid_kernel.zero_list.next,
- struct shmid_kernel, zero_list);
- zswap_idx = 0;
- loop = 1;
- }
- shp = zswap_shp;
-
-check_table:
- idx = zswap_idx++;
- if (idx >= shp->shm_npages) {
- zswap_shp = list_entry(zswap_shp->zero_list.next,
- struct shmid_kernel, zero_list);
- zswap_idx = 0;
- goto next_id;
- }
-
- switch (shm_swap_core(shp, idx, swap_entry, &counter, &page_map)) {
- case RETRY: goto check_table;
- case FAILED: goto failed;
- }
- shm_unlock(zero_id);
- spin_unlock(&zmap_list_lock);
-
- shm_swap_postop(page_map);
- if (counter)
- goto next;
- return;
}
diff -uNr 4-1-ac10/ipc/util.c c/ipc/util.c
--- 4-1-ac10/ipc/util.c Mon Jun 5 11:12:29 2000
+++ c/ipc/util.c Thu Jun 8 13:27:27 2000
@@ -243,11 +243,6 @@
return;
}
-int shm_swap (int prio, int gfp_mask)
-{
- return 0;
-}
-
asmlinkage long sys_semget (key_t key, int nsems, int semflg)
{
return -ENOSYS;
diff -uNr 4-1-ac10/mm/vmscan.c c/mm/vmscan.c
--- 4-1-ac10/mm/vmscan.c Mon Jun 5 11:12:29 2000
+++ c/mm/vmscan.c Thu Jun 8 13:28:17 2000
@@ -471,11 +471,6 @@
ret = 1;
goto done;
}
- while (shm_swap(priority, gfp_mask)) {
- ret = 1;
- if (!--count)
- goto done;
- }
}
/*
next prev parent reply other threads:[~2000-06-08 15:04 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2000-06-01 22:31 [PATCH] VM kswapd autotuning vs. -ac7 Rik van Riel
2000-06-02 15:54 ` Christoph Rohland
2000-06-02 16:01 ` Rik van Riel
2000-06-03 9:02 ` Christoph Rohland
2000-06-03 20:47 ` Rik van Riel
2000-06-04 11:12 ` Christoph Rohland
2000-06-05 8:58 ` Christoph Rohland
2000-06-05 10:16 ` Rik van Riel
2000-06-07 10:23 ` Christoph Rohland
2000-06-07 12:43 ` Rik van Riel
2000-06-07 13:04 ` Christoph Rohland
2000-06-07 13:39 ` Rik van Riel
2000-06-07 14:29 ` Christoph Rohland
2000-06-07 14:43 ` Stephen C. Tweedie
2000-06-08 15:04 ` Christoph Rohland [this message]
2000-06-08 15:21 ` [PATCH,incomplete] shm integration into shrink_mmap Juan J. Quintela
2000-06-08 15:35 ` Rik van Riel
2000-06-07 13:32 ` [PATCH] VM kswapd autotuning vs. -ac7 Stephen C. Tweedie
2000-06-07 14:09 ` Jamie Lokier
2000-06-07 14:11 ` Christoph Rohland
2000-06-07 14:17 ` Stephen C. Tweedie
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=qwwg0qob4ef.fsf_-_@sap.com \
--to=cr@sap.com \
--cc=linux-mm@kvack.org \
--cc=riel@conectiva.com.br \
--cc=sct@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.