Currently mapping for balloon_dev_info is allocated separately. That saves some memory in case CONFIG_BALLOON_COMPACTION is disabled but it creates a need to point from struct address_space to balloon_dev_info. Just embed struct address_space into struct balloon_dev_info so that we don't have to use mapping->private_data which is going away. Signed-off-by: Jan Kara <jack@xxxxxxx> --- drivers/virtio/virtio_balloon.c | 22 +---------- include/linux/balloon_compaction.h | 39 ++------------------ mm/balloon_compaction.c | 75 +++++++++++--------------------------- 3 files changed, 28 insertions(+), 108 deletions(-) diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 34bdabaecbd6..3620df32b71e 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -425,7 +425,6 @@ static const struct address_space_operations virtio_balloon_aops = { 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; @@ -442,30 +441,16 @@ static int virtballoon_probe(struct virtio_device *vdev) vb->vdev = vdev; vb->need_stats_update = 0; - vb_devinfo = balloon_devinfo_alloc(vb); + vb_devinfo = balloon_devinfo_alloc(vb, &virtio_balloon_aops); 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; err = init_vqs(vb); if (err) - goto out_free_vb_mapping; + goto out_free_vb_devinfo; vb->thread = kthread_run(balloon, vb, "vballoon"); if (IS_ERR(vb->thread)) { @@ -477,8 +462,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: @@ -506,7 +489,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); } diff --git a/include/linux/balloon_compaction.h b/include/linux/balloon_compaction.h index 089743ade734..a11eb723561b 100644 --- a/include/linux/balloon_compaction.h +++ b/include/linux/balloon_compaction.h @@ -54,8 +54,8 @@ * balloon driver as a page book-keeper for its registered balloon devices. */ struct balloon_dev_info { + struct address_space mapping; /* balloon special page->mapping */ 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 */ @@ -64,7 +64,8 @@ struct balloon_dev_info { 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); + void *balloon_dev_descriptor, + const struct address_space_operations *a_ops); static inline void balloon_devinfo_free(struct balloon_dev_info *b_dev_info) { @@ -98,14 +99,6 @@ 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); -} /* * page_flags_cleared - helper to perform balloon @page ->flags tests. @@ -216,11 +209,7 @@ 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 container_of(page->mapping, struct balloon_dev_info, mapping); } static inline gfp_t balloon_mapping_gfp_mask(void) @@ -228,24 +217,8 @@ 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) -{ - 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) @@ -289,9 +262,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 */ diff --git a/mm/balloon_compaction.c b/mm/balloon_compaction.c index 6e45a5074bf0..e5ddd28a6915 100644 --- a/mm/balloon_compaction.c +++ b/mm/balloon_compaction.c @@ -19,15 +19,30 @@ * struct balloon_dev_info which will be used to reference a balloon device * as well as to keep track of the balloon device page list. */ -struct balloon_dev_info *balloon_devinfo_alloc(void *balloon_dev_descriptor) +struct balloon_dev_info *balloon_devinfo_alloc(void *balloon_dev_descriptor, + const struct address_space_operations *a_ops) { struct balloon_dev_info *b_dev_info; b_dev_info = kmalloc(sizeof(*b_dev_info), GFP_KERNEL); if (!b_dev_info) return ERR_PTR(-ENOMEM); + /* + * Give a clean 'zeroed' status to all elements of this special + * balloon page->mapping struct address_space instance. + */ + address_space_init_once(&b_dev_info->mapping); + + /* + * Set mapping->flags appropriately, to allow balloon pages + * ->mapping identification. + */ + mapping_set_balloon(&b_dev_info->mapping); + mapping_set_gfp_mask(&b_dev_info->mapping, balloon_mapping_gfp_mask()); + + /* balloon's page->mapping->a_ops callback descriptor */ + b_dev_info->mapping.a_ops = a_ops; b_dev_info->balloon_device = balloon_dev_descriptor; - b_dev_info->mapping = NULL; b_dev_info->isolated_pages = 0; spin_lock_init(&b_dev_info->pages_lock); INIT_LIST_HEAD(&b_dev_info->pages); @@ -61,7 +76,7 @@ struct page *balloon_page_enqueue(struct balloon_dev_info *b_dev_info) */ BUG_ON(!trylock_page(page)); spin_lock_irqsave(&b_dev_info->pages_lock, flags); - balloon_page_insert(page, b_dev_info->mapping, &b_dev_info->pages); + balloon_page_insert(page, &b_dev_info->mapping, &b_dev_info->pages); spin_unlock_irqrestore(&b_dev_info->pages_lock, flags); unlock_page(page); return page; @@ -132,60 +147,14 @@ struct page *balloon_page_dequeue(struct balloon_dev_info *b_dev_info) EXPORT_SYMBOL_GPL(balloon_page_dequeue); #ifdef CONFIG_BALLOON_COMPACTION -/* - * balloon_mapping_alloc - allocates a special ->mapping for ballooned pages. - * @b_dev_info: holds the balloon device information descriptor. - * @a_ops: balloon_mapping address_space_operations descriptor. - * - * Driver must call it to properly allocate and initialize an instance of - * struct address_space which will be used as the special page->mapping for - * balloon device enlisted page instances. - */ -struct address_space *balloon_mapping_alloc(struct balloon_dev_info *b_dev_info, - const struct address_space_operations *a_ops) +static inline struct balloon_dev_info *page_balloon_dev(struct page *page) { - struct address_space *mapping; - - mapping = kmalloc(sizeof(*mapping), GFP_KERNEL); - if (!mapping) - return ERR_PTR(-ENOMEM); - - /* - * Give a clean 'zeroed' status to all elements of this special - * balloon page->mapping struct address_space instance. - */ - address_space_init_once(mapping); - - /* - * Set mapping->flags appropriately, to allow balloon pages - * ->mapping identification. - */ - mapping_set_balloon(mapping); - mapping_set_gfp_mask(mapping, balloon_mapping_gfp_mask()); - - /* balloon's page->mapping->a_ops callback descriptor */ - mapping->a_ops = a_ops; - - /* - * Establish a pointer reference back to the balloon device descriptor - * this particular page->mapping will be servicing. - * This is used by compaction / migration procedures to identify and - * access the balloon device pageset while isolating / migrating pages. - * - * As some balloon drivers can register multiple balloon devices - * for a single guest, this also helps compaction / migration to - * properly deal with multiple balloon pagesets, when required. - */ - mapping->private_data = b_dev_info; - b_dev_info->mapping = mapping; - - return mapping; + return container_of(page->mapping, struct balloon_dev_info, mapping); } -EXPORT_SYMBOL_GPL(balloon_mapping_alloc); static inline void __isolate_balloon_page(struct page *page) { - struct balloon_dev_info *b_dev_info = page->mapping->private_data; + struct balloon_dev_info *b_dev_info = page_balloon_device(page); unsigned long flags; spin_lock_irqsave(&b_dev_info->pages_lock, flags); list_del(&page->lru); @@ -195,7 +164,7 @@ static inline void __isolate_balloon_page(struct page *page) static inline void __putback_balloon_page(struct page *page) { - struct balloon_dev_info *b_dev_info = page->mapping->private_data; + struct balloon_dev_info *b_dev_info = page_balloon_device(page); unsigned long flags; spin_lock_irqsave(&b_dev_info->pages_lock, flags); list_add(&page->lru, &b_dev_info->pages); -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html