--- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -1299,6 +1299,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; }; --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -574,6 +574,7 @@ static unsigned char swap_entry_free(str /* 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,8 @@ static unsigned char swap_entry_free(str swap_list.next = p->type; nr_swap_pages++; p->inuse_pages--; + if (disk->fops->swap_slot_free_notify) + disk->fops->swap_slot_free_notify(p->bdev, offset); } return usage;