swap: Add swap slot free callback to block_device_operations
authorNitin Gupta <ngupta@vflare.org>
Mon, 17 May 2010 05:32:43 +0000 (11:02 +0530)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 18 May 2010 22:07:52 +0000 (15:07 -0700)
This callback is required when RAM based devices are used as swap disks.
One such device is ramzswap which is used as compressed in-memory swap
disk.  For such devices, we need a callback as soon as a swap slot is no
longer used to allow freeing memory allocated for this slot.  Without this
callback, stale data can quickly accumulate in memory defeating the whole
purpose of such devices.

Signed-off-by: Nitin Gupta <ngupta@vflare.org>
Acked-by: Linus Torvalds <torvalds@linux-foundation.org>
Acked-by: Nigel Cunningham <nigel@tuxonice.net>
Acked-by: Pekka Enberg <penberg@cs.helsinki.fi>
Reviewed-by: Minchan Kim <minchan.kim@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
include/linux/blkdev.h
mm/swapfile.c

index 6690e8bae7bb5946396577fcc12a9c85836cb7b5..413284a51ccc4adb23c53b3a13d8ed610ce84a70 100644 (file)
@@ -1287,6 +1287,8 @@ struct block_device_operations {
                                                unsigned long long);
        int (*revalidate_disk) (struct gendisk *);
        int (*getgeo)(struct block_device *, struct hd_geometry *);
+       /* this callback is with swap_lock and sometimes page table lock held */
+       void (*swap_slot_free_notify) (struct block_device *, unsigned long);
        struct module *owner;
 };
 
index ecb069e213d097faf58edf951e84adf26968bea7..f5ccc476aa51368c96ba9918e6e011067fad94ad 100644 (file)
@@ -574,6 +574,7 @@ static unsigned char swap_entry_free(struct swap_info_struct *p,
 
        /* free if no reference */
        if (!usage) {
+               struct gendisk *disk = p->bdev->bd_disk;
                if (offset < p->lowest_bit)
                        p->lowest_bit = offset;
                if (offset > p->highest_bit)
@@ -583,6 +584,9 @@ static unsigned char swap_entry_free(struct swap_info_struct *p,
                        swap_list.next = p->type;
                nr_swap_pages++;
                p->inuse_pages--;
+               if ((p->flags & SWP_BLKDEV) &&
+                               disk->fops->swap_slot_free_notify)
+                       disk->fops->swap_slot_free_notify(p->bdev, offset);
        }
 
        return usage;