linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC][PATCH] swap: send callback when swap slot is freed
@ 2009-08-10 14:37 Nitin Gupta
  0 siblings, 0 replies; 4+ messages in thread
From: Nitin Gupta @ 2009-08-10 14:37 UTC (permalink / raw)
  To: linux-kernel

Currently, we have "swap discard" mechanism which sends a discard bio 
request
when we find a free cluster during scan_swap_map(). This callback can come a
long time after swap slots are actually freed.

This delay in callback is a great problem when (compressed) RAM [1] is used
as a swap device. So, this change adds a callback which is called as
soon as a swap slot becomes free. For above mentioned case of swapping
over compressed RAM device, this is very useful since we can immediately
free memory allocated for this swap page.

This callback does not replace swap discard support. It is called with
swap_lock held, so it is meant to trigger action that finishes quickly.
However, swap discard is an I/O request and can be used for taking longer
actions.

This patch is simply a quick hack but it works (tested on x86 and x64).
Can anyone please suggest a cleaner and proper way to do this? This is
really essential for compcache[1] project. Any feedback would be really
helpful. Thanks.


Links:
[1] http://code.google.com/p/compcache/

Signed-off-by: Nitin Gupta <ngupta@vflare.org>
---

  include/linux/swap.h |   14 ++++++++++++++
  init/Kconfig         |    9 +++++++++
  mm/swapfile.c        |   20 ++++++++++++++++++++
  3 files changed, 43 insertions(+), 0 deletions(-)

diff --git a/include/linux/swap.h b/include/linux/swap.h
index 7c15334..483d0b9 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -8,6 +8,7 @@
  #include <linux/memcontrol.h>
  #include <linux/sched.h>
  #include <linux/node.h>
+#include <linux/blkdev.h>

  #include <asm/atomic.h>
  #include <asm/page.h>
@@ -20,6 +21,8 @@ struct bio;
  #define SWAP_FLAG_PRIO_MASK    0x7fff
  #define SWAP_FLAG_PRIO_SHIFT    0

+typedef void (swap_free_notify_fn) (struct block_device *, unsigned long);
+
  static inline int current_is_kswapd(void)
  {
      return current->flags & PF_KSWAPD;
@@ -155,6 +158,9 @@ struct swap_info_struct {
      unsigned int max;
      unsigned int inuse_pages;
      unsigned int old_block_size;
+#ifdef CONFIG_SWAP_FREE_NOTIFY
+    swap_free_notify_fn *swap_free_notify_fn;
+#endif
  };

  struct swap_list_t {
@@ -297,6 +303,14 @@ extern int reuse_swap_page(struct page *);
  extern int try_to_free_swap(struct page *);
  struct backing_dev_info;

+#ifdef CONFIG_SWAP_FREE_NOTIFY
+extern void set_swap_free_notify(unsigned, swap_free_notify_fn *);
+#else
+void set_swap_free_notify(unsigned, swap_free_notify_fn *)
+{
+}
+#endif
+
  /* linux/mm/thrash.c */
  extern struct mm_struct *swap_token_mm;
  extern void grab_swap_token(struct mm_struct *);
diff --git a/init/Kconfig b/init/Kconfig
index 3f7e609..b0112c6 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -176,6 +176,15 @@ config SWAP
        used to provide more virtual memory than the actual RAM present
        in your computer.  If unsure say Y.

+config SWAP_FREE_NOTIFY
+    bool "Enable swap free notification"
+    depends on SWAP
+    default y
+    help
+      This causes swap subsystem to send a callback to swap device when
+      a swap block becomes free. This is useful in cases such as when
+      compressed RAM device is used as swap disk.
+
  config SYSVIPC
      bool "System V IPC"
      ---help---
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 8ffdc0d..25bacfd 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -552,6 +552,22 @@ out:
      return NULL;
  }

+#ifdef CONFIG_SWAP_FREE_NOTIFY
+/*
+ * Sets callback for event when swap_map[offset] == 0
+ * i.e. page at this swap offset is not longer used.
+ */
+void set_swap_free_notify(unsigned type, swap_free_notify_fn *notify_fn)
+{
+    struct swap_info_struct *sis;
+    sis = get_swap_info_struct(type);
+    BUG_ON(!sis);
+    sis->swap_free_notify_fn = notify_fn;
+    return;
+}
+EXPORT_SYMBOL(set_swap_free_notify);
+#endif
+
  static int swap_entry_free(struct swap_info_struct *p,
                 swp_entry_t ent, int cache)
  {
@@ -583,6 +599,10 @@ static int swap_entry_free(struct swap_info_struct *p,
              swap_list.next = p - swap_info;
          nr_swap_pages++;
          p->inuse_pages--;
+#ifdef CONFIG_SWAP_FREE_NOTIFY
+        if (p->swap_free_notify_fn)
+            p->swap_free_notify_fn(p->bdev, offset);
+#endif
      }
      if (!swap_count(count))
          mem_cgroup_uncharge_swap(ent);


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [RFC][PATCH] swap: send callback when swap slot is freed
  2009-08-12 12:56 ` Ingo Molnar
@ 2009-08-12 13:29   ` Nitin Gupta
  0 siblings, 0 replies; 4+ messages in thread
From: Nitin Gupta @ 2009-08-12 13:29 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: linux-kernel

On 08/12/2009 06:26 PM, Ingo Molnar wrote:
> * Nitin Gupta<ngupta@vflare.org>  wrote:
>
>> (Re-sending since I didn't get any reply last time)
>>
>> Currently, we have "swap discard" mechanism which sends a discard
>> bio request when we find a free cluster during scan_swap_map().
>> This callback can come a long time after swap slots are actually
>> freed.
>>
>> This delay in callback is a great problem when (compressed) RAM
>> [1] is used as a swap device. So, this change adds a callback
>> which is called as soon as a swap slot becomes free. For above
>> mentioned case of swapping over compressed RAM device, this is
>> very useful since we can immediately free memory allocated for
>> this swap page.
>>
>> This callback does not replace swap discard support. It is called
>> with swap_lock held, so it is meant to trigger action that
>> finishes quickly. However, swap discard is an I/O request and can
>> be used for taking longer actions.

<snip>

>
> Shouldnt this be all be unconditional? Sounds like a reasonable VM
> callback. The patch would become a lot smaller as well.
>


I also think this can be made unconditional as it makes the patch
much cleaner. I made it conditional just to be on path of least
resistance :)

Thanks for looking into this. I will resend the patch removing
all the #ifdef'ery.

Nitin

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [RFC][PATCH] swap: send callback when swap slot is freed
  2009-08-12 12:47 Nitin Gupta
@ 2009-08-12 12:56 ` Ingo Molnar
  2009-08-12 13:29   ` Nitin Gupta
  0 siblings, 1 reply; 4+ messages in thread
From: Ingo Molnar @ 2009-08-12 12:56 UTC (permalink / raw)
  To: Nitin Gupta; +Cc: linux-kernel, linux-mm


* Nitin Gupta <ngupta@vflare.org> wrote:

> (Re-sending since I didn't get any reply last time)
> 
> Currently, we have "swap discard" mechanism which sends a discard 
> bio request when we find a free cluster during scan_swap_map(). 
> This callback can come a long time after swap slots are actually 
> freed.
> 
> This delay in callback is a great problem when (compressed) RAM 
> [1] is used as a swap device. So, this change adds a callback 
> which is called as soon as a swap slot becomes free. For above 
> mentioned case of swapping over compressed RAM device, this is 
> very useful since we can immediately free memory allocated for 
> this swap page.
> 
> This callback does not replace swap discard support. It is called 
> with swap_lock held, so it is meant to trigger action that 
> finishes quickly. However, swap discard is an I/O request and can 
> be used for taking longer actions.
> 
> This patch is simply a quick hack but it works (tested on x86 and 
> x64). Can anyone please suggest a cleaner and proper way to do 
> this? Any feedback would be really helpful. Thanks.
> 
> 
> Links:
> [1] http://code.google.com/p/compcache/
> 
> Signed-off-by: Nitin Gupta <ngupta@vflare.org>
> ---
> 
>  include/linux/swap.h |   14 ++++++++++++++
>  init/Kconfig         |    9 +++++++++
>  mm/swapfile.c        |   20 ++++++++++++++++++++
>  3 files changed, 43 insertions(+), 0 deletions(-)
> 
> diff --git a/include/linux/swap.h b/include/linux/swap.h
> index 7c15334..483d0b9 100644
> --- a/include/linux/swap.h
> +++ b/include/linux/swap.h
> @@ -8,6 +8,7 @@
>  #include <linux/memcontrol.h>
>  #include <linux/sched.h>
>  #include <linux/node.h>
> +#include <linux/blkdev.h>
>  
>  #include <asm/atomic.h>
>  #include <asm/page.h>
> @@ -20,6 +21,8 @@ struct bio;
>  #define SWAP_FLAG_PRIO_MASK	0x7fff
>  #define SWAP_FLAG_PRIO_SHIFT	0
>  
> +typedef void (swap_free_notify_fn) (struct block_device *, unsigned long);
> +
>  static inline int current_is_kswapd(void)
>  {
>  	return current->flags & PF_KSWAPD;
> @@ -155,6 +158,9 @@ struct swap_info_struct {
>  	unsigned int max;
>  	unsigned int inuse_pages;
>  	unsigned int old_block_size;
> +#ifdef CONFIG_SWAP_FREE_NOTIFY
> +	swap_free_notify_fn *swap_free_notify_fn;
> +#endif
>  };
>  
>  struct swap_list_t {
> @@ -297,6 +303,14 @@ extern int reuse_swap_page(struct page *);
>  extern int try_to_free_swap(struct page *);
>  struct backing_dev_info;
>  
> +#ifdef CONFIG_SWAP_FREE_NOTIFY
> +extern void set_swap_free_notify(unsigned, swap_free_notify_fn *);
> +#else
> +void set_swap_free_notify(unsigned, swap_free_notify_fn *)
> +{
> +}
> +#endif
> +
>  /* linux/mm/thrash.c */
>  extern struct mm_struct *swap_token_mm;
>  extern void grab_swap_token(struct mm_struct *);
> diff --git a/init/Kconfig b/init/Kconfig
> index 3f7e609..b0112c6 100644
> --- a/init/Kconfig
> +++ b/init/Kconfig
> @@ -176,6 +176,15 @@ config SWAP
>  	  used to provide more virtual memory than the actual RAM present
>  	  in your computer.  If unsure say Y.
>  
> +config SWAP_FREE_NOTIFY
> +	bool "Enable swap free notification"
> +	depends on SWAP
> +	default y
> +	help
> +	  This causes swap subsystem to send a callback to swap device when
> +	  a swap block becomes free. This is useful in cases such as when
> +	  compressed RAM device is used as swap disk.
> +
>  config SYSVIPC
>  	bool "System V IPC"
>  	---help---
> diff --git a/mm/swapfile.c b/mm/swapfile.c
> index 8ffdc0d..25bacfd 100644
> --- a/mm/swapfile.c
> +++ b/mm/swapfile.c
> @@ -552,6 +552,22 @@ out:
>  	return NULL;
>  }
>  
> +#ifdef CONFIG_SWAP_FREE_NOTIFY
> +/*
> + * Sets callback for event when swap_map[offset] == 0
> + * i.e. page at this swap offset is not longer used.
> + */
> +void set_swap_free_notify(unsigned type, swap_free_notify_fn *notify_fn)
> +{
> +	struct swap_info_struct *sis;
> +	sis = get_swap_info_struct(type);
> +	BUG_ON(!sis);
> +	sis->swap_free_notify_fn = notify_fn;
> +	return;
> +}
> +EXPORT_SYMBOL(set_swap_free_notify);
> +#endif
> +
>  static int swap_entry_free(struct swap_info_struct *p,
>  			   swp_entry_t ent, int cache)
>  {
> @@ -583,6 +599,10 @@ static int swap_entry_free(struct swap_info_struct *p,
>  			swap_list.next = p - swap_info;
>  		nr_swap_pages++;
>  		p->inuse_pages--;
> +#ifdef CONFIG_SWAP_FREE_NOTIFY
> +		if (p->swap_free_notify_fn)
> +			p->swap_free_notify_fn(p->bdev, offset);
> +#endif
>  	}
>  	if (!swap_count(count))
>  		mem_cgroup_uncharge_swap(ent);

Shouldnt this be all be unconditional? Sounds like a reasonable VM 
callback. The patch would become a lot smaller as well.

	Ingo

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [RFC][PATCH] swap: send callback when swap slot is freed
@ 2009-08-12 12:47 Nitin Gupta
  2009-08-12 12:56 ` Ingo Molnar
  0 siblings, 1 reply; 4+ messages in thread
From: Nitin Gupta @ 2009-08-12 12:47 UTC (permalink / raw)
  To: linux-kernel, linux-mm

(Re-sending since I didn't get any reply last time)

Currently, we have "swap discard" mechanism which sends a discard bio request
when we find a free cluster during scan_swap_map(). This callback can come a
long time after swap slots are actually freed.

This delay in callback is a great problem when (compressed) RAM [1] is used
as a swap device. So, this change adds a callback which is called as
soon as a swap slot becomes free. For above mentioned case of swapping
over compressed RAM device, this is very useful since we can immediately
free memory allocated for this swap page.

This callback does not replace swap discard support. It is called with
swap_lock held, so it is meant to trigger action that finishes quickly.
However, swap discard is an I/O request and can be used for taking longer
actions.

This patch is simply a quick hack but it works (tested on x86 and x64).
Can anyone please suggest a cleaner and proper way to do this? Any
feedback would be really helpful. Thanks.


Links:
[1] http://code.google.com/p/compcache/

Signed-off-by: Nitin Gupta <ngupta@vflare.org>
---

 include/linux/swap.h |   14 ++++++++++++++
 init/Kconfig         |    9 +++++++++
 mm/swapfile.c        |   20 ++++++++++++++++++++
 3 files changed, 43 insertions(+), 0 deletions(-)

diff --git a/include/linux/swap.h b/include/linux/swap.h
index 7c15334..483d0b9 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -8,6 +8,7 @@
 #include <linux/memcontrol.h>
 #include <linux/sched.h>
 #include <linux/node.h>
+#include <linux/blkdev.h>
 
 #include <asm/atomic.h>
 #include <asm/page.h>
@@ -20,6 +21,8 @@ struct bio;
 #define SWAP_FLAG_PRIO_MASK	0x7fff
 #define SWAP_FLAG_PRIO_SHIFT	0
 
+typedef void (swap_free_notify_fn) (struct block_device *, unsigned long);
+
 static inline int current_is_kswapd(void)
 {
 	return current->flags & PF_KSWAPD;
@@ -155,6 +158,9 @@ struct swap_info_struct {
 	unsigned int max;
 	unsigned int inuse_pages;
 	unsigned int old_block_size;
+#ifdef CONFIG_SWAP_FREE_NOTIFY
+	swap_free_notify_fn *swap_free_notify_fn;
+#endif
 };
 
 struct swap_list_t {
@@ -297,6 +303,14 @@ extern int reuse_swap_page(struct page *);
 extern int try_to_free_swap(struct page *);
 struct backing_dev_info;
 
+#ifdef CONFIG_SWAP_FREE_NOTIFY
+extern void set_swap_free_notify(unsigned, swap_free_notify_fn *);
+#else
+void set_swap_free_notify(unsigned, swap_free_notify_fn *)
+{
+}
+#endif
+
 /* linux/mm/thrash.c */
 extern struct mm_struct *swap_token_mm;
 extern void grab_swap_token(struct mm_struct *);
diff --git a/init/Kconfig b/init/Kconfig
index 3f7e609..b0112c6 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -176,6 +176,15 @@ config SWAP
 	  used to provide more virtual memory than the actual RAM present
 	  in your computer.  If unsure say Y.
 
+config SWAP_FREE_NOTIFY
+	bool "Enable swap free notification"
+	depends on SWAP
+	default y
+	help
+	  This causes swap subsystem to send a callback to swap device when
+	  a swap block becomes free. This is useful in cases such as when
+	  compressed RAM device is used as swap disk.
+
 config SYSVIPC
 	bool "System V IPC"
 	---help---
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 8ffdc0d..25bacfd 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -552,6 +552,22 @@ out:
 	return NULL;
 }
 
+#ifdef CONFIG_SWAP_FREE_NOTIFY
+/*
+ * Sets callback for event when swap_map[offset] == 0
+ * i.e. page at this swap offset is not longer used.
+ */
+void set_swap_free_notify(unsigned type, swap_free_notify_fn *notify_fn)
+{
+	struct swap_info_struct *sis;
+	sis = get_swap_info_struct(type);
+	BUG_ON(!sis);
+	sis->swap_free_notify_fn = notify_fn;
+	return;
+}
+EXPORT_SYMBOL(set_swap_free_notify);
+#endif
+
 static int swap_entry_free(struct swap_info_struct *p,
 			   swp_entry_t ent, int cache)
 {
@@ -583,6 +599,10 @@ static int swap_entry_free(struct swap_info_struct *p,
 			swap_list.next = p - swap_info;
 		nr_swap_pages++;
 		p->inuse_pages--;
+#ifdef CONFIG_SWAP_FREE_NOTIFY
+		if (p->swap_free_notify_fn)
+			p->swap_free_notify_fn(p->bdev, offset);
+#endif
 	}
 	if (!swap_count(count))
 		mem_cgroup_uncharge_swap(ent);


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2009-08-12 13:29 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-08-10 14:37 [RFC][PATCH] swap: send callback when swap slot is freed Nitin Gupta
2009-08-12 12:47 Nitin Gupta
2009-08-12 12:56 ` Ingo Molnar
2009-08-12 13:29   ` Nitin Gupta

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).