Skip to content

Commit

Permalink
mm/balloon_compaction: remove balloon mapping and flag AS_BALLOON_MAP
Browse files Browse the repository at this point in the history
Now ballooned pages are detected using PageBalloon().  Fake mapping is no
longer required.  This patch links ballooned pages to balloon device using
field page->private instead of page->mapping.  Also this patch embeds
balloon_dev_info directly into struct virtio_balloon.

Signed-off-by: Konstantin Khlebnikov <[email protected]>
Cc: Rafael Aquini <[email protected]>
Cc: Andrey Ryabinin <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
Konstantin Khlebnikov authored and torvalds committed Oct 10, 2014
1 parent d6d86c0 commit 9d1ba80
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 206 deletions.
60 changes: 13 additions & 47 deletions drivers/virtio/virtio_balloon.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ struct virtio_balloon
* Each page on this list adds VIRTIO_BALLOON_PAGES_PER_PAGE
* to num_pages above.
*/
struct balloon_dev_info *vb_dev_info;
struct balloon_dev_info vb_dev_info;

/* Synchronize access/update to this struct virtio_balloon elements */
struct mutex balloon_lock;
Expand Down Expand Up @@ -127,7 +127,7 @@ static void set_page_pfns(u32 pfns[], struct page *page)

static void fill_balloon(struct virtio_balloon *vb, size_t num)
{
struct balloon_dev_info *vb_dev_info = vb->vb_dev_info;
struct balloon_dev_info *vb_dev_info = &vb->vb_dev_info;

/* We can only do one array worth at a time. */
num = min(num, ARRAY_SIZE(vb->pfns));
Expand Down Expand Up @@ -171,7 +171,7 @@ static void release_pages_by_pfn(const u32 pfns[], unsigned int num)
static void leak_balloon(struct virtio_balloon *vb, size_t num)
{
struct page *page;
struct balloon_dev_info *vb_dev_info = vb->vb_dev_info;
struct balloon_dev_info *vb_dev_info = &vb->vb_dev_info;

/* We can only do one array worth at a time. */
num = min(num, ARRAY_SIZE(vb->pfns));
Expand Down Expand Up @@ -353,12 +353,11 @@ static int init_vqs(struct virtio_balloon *vb)
return 0;
}

static const struct address_space_operations virtio_balloon_aops;
#ifdef CONFIG_BALLOON_COMPACTION
/*
* virtballoon_migratepage - perform the balloon page migration on behalf of
* a compation thread. (called under page lock)
* @mapping: the page->mapping which will be assigned to the new migrated page.
* @vb_dev_info: the balloon device
* @newpage: page that will replace the isolated page after migration finishes.
* @page : the isolated (old) page that is about to be migrated to newpage.
* @mode : compaction mode -- not used for balloon page migration.
Expand All @@ -373,17 +372,13 @@ static const struct address_space_operations virtio_balloon_aops;
* This function preforms the balloon page migration task.
* Called through balloon_mapping->a_ops->migratepage
*/
static int virtballoon_migratepage(struct address_space *mapping,
static int virtballoon_migratepage(struct balloon_dev_info *vb_dev_info,
struct page *newpage, struct page *page, enum migrate_mode mode)
{
struct balloon_dev_info *vb_dev_info = balloon_page_device(page);
struct virtio_balloon *vb;
struct virtio_balloon *vb = container_of(vb_dev_info,
struct virtio_balloon, vb_dev_info);
unsigned long flags;

BUG_ON(!vb_dev_info);

vb = vb_dev_info->balloon_device;

/*
* In order to avoid lock contention while migrating pages concurrently
* to leak_balloon() or fill_balloon() we just give up the balloon_lock
Expand All @@ -399,7 +394,7 @@ static int virtballoon_migratepage(struct address_space *mapping,

/* balloon's page migration 1st step -- inflate "newpage" */
spin_lock_irqsave(&vb_dev_info->pages_lock, flags);
balloon_page_insert(newpage, mapping, &vb_dev_info->pages);
balloon_page_insert(vb_dev_info, newpage);
vb_dev_info->isolated_pages--;
spin_unlock_irqrestore(&vb_dev_info->pages_lock, flags);
vb->num_pfns = VIRTIO_BALLOON_PAGES_PER_PAGE;
Expand All @@ -418,18 +413,11 @@ static int virtballoon_migratepage(struct address_space *mapping,

return MIGRATEPAGE_SUCCESS;
}

/* define the balloon_mapping->a_ops callback to allow balloon page migration */
static const struct address_space_operations virtio_balloon_aops = {
.migratepage = virtballoon_migratepage,
};
#endif /* CONFIG_BALLOON_COMPACTION */

static int virtballoon_probe(struct virtio_device *vdev)
{
struct virtio_balloon *vb;
struct address_space *vb_mapping;
struct balloon_dev_info *vb_devinfo;
int err;

vdev->priv = vb = kmalloc(sizeof(*vb), GFP_KERNEL);
Expand All @@ -445,30 +433,14 @@ static int virtballoon_probe(struct virtio_device *vdev)
vb->vdev = vdev;
vb->need_stats_update = 0;

vb_devinfo = balloon_devinfo_alloc(vb);
if (IS_ERR(vb_devinfo)) {
err = PTR_ERR(vb_devinfo);
goto out_free_vb;
}

vb_mapping = balloon_mapping_alloc(vb_devinfo,
(balloon_compaction_check()) ?
&virtio_balloon_aops : NULL);
if (IS_ERR(vb_mapping)) {
/*
* IS_ERR(vb_mapping) && PTR_ERR(vb_mapping) == -EOPNOTSUPP
* This means !CONFIG_BALLOON_COMPACTION, otherwise we get off.
*/
err = PTR_ERR(vb_mapping);
if (err != -EOPNOTSUPP)
goto out_free_vb_devinfo;
}

vb->vb_dev_info = vb_devinfo;
balloon_devinfo_init(&vb->vb_dev_info);
#ifdef CONFIG_BALLOON_COMPACTION
vb->vb_dev_info.migratepage = virtballoon_migratepage;
#endif

err = init_vqs(vb);
if (err)
goto out_free_vb_mapping;
goto out_free_vb;

vb->thread = kthread_run(balloon, vb, "vballoon");
if (IS_ERR(vb->thread)) {
Expand All @@ -480,10 +452,6 @@ static int virtballoon_probe(struct virtio_device *vdev)

out_del_vqs:
vdev->config->del_vqs(vdev);
out_free_vb_mapping:
balloon_mapping_free(vb_mapping);
out_free_vb_devinfo:
balloon_devinfo_free(vb_devinfo);
out_free_vb:
kfree(vb);
out:
Expand All @@ -509,8 +477,6 @@ static void virtballoon_remove(struct virtio_device *vdev)

kthread_stop(vb->thread);
remove_common(vb);
balloon_mapping_free(vb->vb_dev_info->mapping);
balloon_devinfo_free(vb->vb_dev_info);
kfree(vb);
}

Expand Down
72 changes: 19 additions & 53 deletions include/linux/balloon_compaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,36 +57,29 @@
* balloon driver as a page book-keeper for its registered balloon devices.
*/
struct balloon_dev_info {
void *balloon_device; /* balloon device descriptor */
struct address_space *mapping; /* balloon special page->mapping */
unsigned long isolated_pages; /* # of isolated pages for migration */
spinlock_t pages_lock; /* Protection to pages list */
struct list_head pages; /* Pages enqueued & handled to Host */
int (*migratepage)(struct balloon_dev_info *, struct page *newpage,
struct page *page, enum migrate_mode mode);
};

extern struct page *balloon_page_enqueue(struct balloon_dev_info *b_dev_info);
extern struct page *balloon_page_dequeue(struct balloon_dev_info *b_dev_info);
extern struct balloon_dev_info *balloon_devinfo_alloc(
void *balloon_dev_descriptor);

static inline void balloon_devinfo_free(struct balloon_dev_info *b_dev_info)
static inline void balloon_devinfo_init(struct balloon_dev_info *balloon)
{
kfree(b_dev_info);
balloon->isolated_pages = 0;
spin_lock_init(&balloon->pages_lock);
INIT_LIST_HEAD(&balloon->pages);
balloon->migratepage = NULL;
}

#ifdef CONFIG_BALLOON_COMPACTION
extern bool balloon_page_isolate(struct page *page);
extern void balloon_page_putback(struct page *page);
extern int balloon_page_migrate(struct page *newpage,
struct page *page, enum migrate_mode mode);
extern struct address_space
*balloon_mapping_alloc(struct balloon_dev_info *b_dev_info,
const struct address_space_operations *a_ops);

static inline void balloon_mapping_free(struct address_space *balloon_mapping)
{
kfree(balloon_mapping);
}

/*
* __is_movable_balloon_page - helper to perform @page PageBalloon tests
Expand Down Expand Up @@ -120,27 +113,25 @@ static inline bool isolated_balloon_page(struct page *page)

/*
* balloon_page_insert - insert a page into the balloon's page list and make
* the page->mapping assignment accordingly.
* the page->private assignment accordingly.
* @balloon : pointer to balloon device
* @page : page to be assigned as a 'balloon page'
* @mapping : allocated special 'balloon_mapping'
* @head : balloon's device page list head
*
* Caller must ensure the page is locked and the spin_lock protecting balloon
* pages list is held before inserting a page into the balloon device.
*/
static inline void balloon_page_insert(struct page *page,
struct address_space *mapping,
struct list_head *head)
static inline void balloon_page_insert(struct balloon_dev_info *balloon,
struct page *page)
{
__SetPageBalloon(page);
SetPagePrivate(page);
page->mapping = mapping;
list_add(&page->lru, head);
set_page_private(page, (unsigned long)balloon);
list_add(&page->lru, &balloon->pages);
}

/*
* balloon_page_delete - delete a page from balloon's page list and clear
* the page->mapping assignement accordingly.
* the page->private assignement accordingly.
* @page : page to be released from balloon's page list
*
* Caller must ensure the page is locked and the spin_lock protecting balloon
Expand All @@ -149,7 +140,7 @@ static inline void balloon_page_insert(struct page *page,
static inline void balloon_page_delete(struct page *page)
{
__ClearPageBalloon(page);
page->mapping = NULL;
set_page_private(page, 0);
if (PagePrivate(page)) {
ClearPagePrivate(page);
list_del(&page->lru);
Expand All @@ -162,41 +153,20 @@ static inline void balloon_page_delete(struct page *page)
*/
static inline struct balloon_dev_info *balloon_page_device(struct page *page)
{
struct address_space *mapping = page->mapping;
if (likely(mapping))
return mapping->private_data;

return NULL;
return (struct balloon_dev_info *)page_private(page);
}

static inline gfp_t balloon_mapping_gfp_mask(void)
{
return GFP_HIGHUSER_MOVABLE;
}

static inline bool balloon_compaction_check(void)
{
return true;
}

#else /* !CONFIG_BALLOON_COMPACTION */

static inline void *balloon_mapping_alloc(void *balloon_device,
const struct address_space_operations *a_ops)
static inline void balloon_page_insert(struct balloon_dev_info *balloon,
struct page *page)
{
return ERR_PTR(-EOPNOTSUPP);
}

static inline void balloon_mapping_free(struct address_space *balloon_mapping)
{
return;
}

static inline void balloon_page_insert(struct page *page,
struct address_space *mapping,
struct list_head *head)
{
list_add(&page->lru, head);
list_add(&page->lru, &balloon->pages);
}

static inline void balloon_page_delete(struct page *page)
Expand Down Expand Up @@ -240,9 +210,5 @@ static inline gfp_t balloon_mapping_gfp_mask(void)
return GFP_HIGHUSER;
}

static inline bool balloon_compaction_check(void)
{
return false;
}
#endif /* CONFIG_BALLOON_COMPACTION */
#endif /* _LINUX_BALLOON_COMPACTION_H */
18 changes: 1 addition & 17 deletions include/linux/pagemap.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ enum mapping_flags {
AS_ENOSPC = __GFP_BITS_SHIFT + 1, /* ENOSPC on async write */
AS_MM_ALL_LOCKS = __GFP_BITS_SHIFT + 2, /* under mm_take_all_locks() */
AS_UNEVICTABLE = __GFP_BITS_SHIFT + 3, /* e.g., ramdisk, SHM_LOCK */
AS_BALLOON_MAP = __GFP_BITS_SHIFT + 4, /* balloon page special map */
AS_EXITING = __GFP_BITS_SHIFT + 5, /* final truncate in progress */
AS_EXITING = __GFP_BITS_SHIFT + 4, /* final truncate in progress */
};

static inline void mapping_set_error(struct address_space *mapping, int error)
Expand Down Expand Up @@ -55,21 +54,6 @@ static inline int mapping_unevictable(struct address_space *mapping)
return !!mapping;
}

static inline void mapping_set_balloon(struct address_space *mapping)
{
set_bit(AS_BALLOON_MAP, &mapping->flags);
}

static inline void mapping_clear_balloon(struct address_space *mapping)
{
clear_bit(AS_BALLOON_MAP, &mapping->flags);
}

static inline int mapping_balloon(struct address_space *mapping)
{
return mapping && test_bit(AS_BALLOON_MAP, &mapping->flags);
}

static inline void mapping_set_exiting(struct address_space *mapping)
{
set_bit(AS_EXITING, &mapping->flags);
Expand Down
Loading

0 comments on commit 9d1ba80

Please sign in to comment.