#include <linux/spinlock.h>
#include <linux/kthread.h>
#include <linux/list.h>
#include <linux/delay.h>
#include <linux/freezer.h>
#include <linux/bitmap.h>
#include <xen/events.h>
#include <xen/page.h>
#include <xen/xen.h>
#include <asm/xen/hypervisor.h>
#include <asm/xen/hypercall.h>
#include <xen/balloon.h>
#include "common.h"
/*
* Maximum number of unused free pages to keep in the internal buffer.
* Setting this to a value too low will reduce memory used in each backend,
* but can have a performance penalty.
*
* A sane value is xen_blkif_reqs * BLKIF_MAX_SEGMENTS_PER_REQUEST, but can
* be set to a lower value that might degrade performance on some intensive
* IO workloads.
*/
static int xen_blkif_max_buffer_pages = 1024;
module_param_named(max_buffer_pages, xen_blkif_max_buffer_pages, int, 0644);
MODULE_PARM_DESC(max_buffer_pages,
"Maximum number of free pages to keep in each block backend buffer");
/*
* Maximum number of grants to map persistently in blkback. For maximum
* performance this should be the total numbers of grants that can be used
* to fill the ring, but since this might become too high, specially with
* the use of indirect descriptors, we set it to a value that provides good
* performance without using too much memory.
*
* When the list of persistent grants is full we clean it up using a LRU
* algorithm.
*/
static int xen_blkif_max_pgrants = 1056;
module_param_named(max_persistent_grants, xen_blkif_max_pgrants, int, 0644);
MODULE_PARM_DESC(max_persistent_grants,
"Maximum number of grants to map persistently");
/*
* The LRU mechanism to clean the lists of persistent grants needs to
* be executed periodically. The time interval between consecutive executions
* of the purge mechanism is set in ms.
*/
#define LRU_INTERVAL 100
/*
* When the persistent grants list is full we will remove unused grants
* from the list. The percent number of grants to be removed at each LRU
* execution.
*/
#define LRU_PERCENT_CLEAN 5
/* Run-time switchable: /sys/module/blkback/parameters/ */
static unsigned int log_stats;
module_param(log_stats, int, 0644);
#define BLKBACK_INVALID_HANDLE (~0)
/* Number of free pages to remove on each call to free_xenballooned_pages */
#define NUM_BATCH_FREE_PAGES 10
static inline int get_free_page(struct xen_blkif *blkif, struct page **page)
{
unsigned long flags;
spin_lock_irqsave(&blkif->free_pages_lock, flags);
if (list_empty(&blkif->free_pages)) {
BUG_ON(blkif->free_pages_num != 0);
spin_unlock_irqrestore(&blkif->free_pages_lock, flags);
return alloc_xenballooned_pages(1, page, false);
}
BUG_ON(blkif->free_pages_num == 0);
page[0] = list_first_entry(&blkif->free_pages, struct page, lru);
list_del(&page[0]->lru);
blkif->free_pages_num--;
spin_unlock_irqrestore(&blkif->free_pages_lock, flags);
return 0;
}
static inline void put_free_pages(struct xen_blkif *blkif, struct page **page,
int num)
{
unsigned long flags;
int i;
spin_lock_irqsave(&blkif->free_pages_lock, flags);
for (i = 0; i < num; i++)
list_add(&page[i]->lru, &blkif->free_pages);
blkif->free_pages_num += num;
spin_unlock_irqrestore(&blkif->free_pages_lock, flags);
}
static inline void shrink_free_pagepool(struct xen_blkif *blkif, int num)
{
/* Remove requested pages in batches of NUM_BATCH_FREE_PAGES */
struct page *page[NUM_BATCH_FREE_PAGES];
unsigned int num_pages = 0;
unsigned long flags;
spin_lock_irqsave(&blkif->free_pages_lock, flags);
while (blkif->free_pages_num > num) {
BUG_ON(list_empty(&blkif->free_pages));
page[num_pages] = list_first_entry(&blkif->free_pages,
struct page, lru);
list_del(&page[num_pages]->lru);
blkif->free_pages_num--;
if (++num_pages == NUM_BATCH_FREE_PAGES) {
spin_unlock_irqrestore(&blkif->free_pages_lock, flags);
free_xenballooned_pages(num_pages, page);
spin_lock_irqsave(&blkif->free_pages_lock, flags);
num_pages = 0;
}
}
spin_unlock_irqrestore(&blkif->free_pages_lock, flags);
if (num_pages != 0)
free_xenballooned_pages(num_pages, page);
}
#define vaddr(page) ((unsigned long)pfn_to_kaddr(page_to_pfn(page)))
static int do_block_io_op(struct xen_blkif *blkif);
static int dispatch_rw_block_io(struct xen_blkif *blkif,
struct blkif_request *req,
struct pending_req *pending_req);
static void make_response(struct xen_blkif *blkif, u64 id,
unsigned short op, int st);
#define foreach_grant_safe(pos, n, rbtree, node) \
for ((pos) = container_of(rb_first((rbtree)), typeof(*(pos)), node), \
(n) = (&(pos)->node != NULL) ? rb_next(&(pos)->node) : NULL; \
&(pos)->node != NULL; \
(pos) = container_of(n, typeof(*(pos)), node), \
(n) = (&(pos)->node != NULL) ? rb_next(&(pos)->node) : NULL)
/*
* We don't need locking around the persistent grant helpers
* because blkback uses a single-thread for each backed, so we
* can be sure that this functions will never be called recursively.
*
* The only exception to that is put_persistent_grant, that can be called
* from interrupt context (by xen_blkbk_unmap), so we have to use atomic
* bit operations to modify the flags of a persistent grant and to count
* the number of used grants.
*/
static int add_persistent_gnt(struct xen_blkif *blkif,
struct persistent_gnt *persistent_gnt)
{
struct rb_node **new = NULL, *parent = NULL;
struct persistent_gnt *this;
if (blkif->persistent_gnt_c >= xen_blkif_max_pgrants) {
if (!blkif->vbd.overflow_max_grants)
blkif->vbd.overflow_max_grants = 1;
return -EBUSY;
}
/* Figure out where to put new node */
new = &blkif->persistent_gnts.rb_node;
while (*new) {
this = container_of(*new, struct persistent_gnt, node);
parent = *new;
if (persistent_gnt->gnt < this->gnt)
new = &((*new)->rb_left);
else if (persistent_gnt->gnt > this->gnt)
new = &((*new)->rb_right);
else {
pr_alert_ratelimited(DRV_PFX " trying to add a gref that's already in the tree\n");
return -EINVAL;
}
}
bitmap_zero(persistent_gnt->flags, PERSISTENT_GNT_FLAGS_SIZE);
set_bit(PERSISTENT_GNT_ACTIVE, persistent_gnt->flags);
/* Add new node and rebalance tree. */
rb_link_node(&(persistent_gnt->node), parent, new);
rb_insert_color(&(persistent_gnt->node), &blkif->persistent_gnts);
blkif->persistent_gnt_c++;
atomic_inc(&blkif->persistent_gnt_in_use);
return 0;
}
static struct persistent_gnt *get_persistent_gnt(struct xen_blkif *blkif,
grant_ref_t gref)
{
struct persistent_gnt *data;
struct rb_node *node = NULL;
node = blkif->persistent_gnts.rb_node;
while (node) {
data = container_of(node, struct persistent_gnt, node);
if (gref < data->gnt)
node = node->rb_left;
else if (gref > data->gnt)
node = node->rb_right;
else {
if(test_bit(PERSISTENT_GNT_ACTIVE, data->flags)) {
pr_alert_ratelimited(DRV_PFX " requesting a grant already in use\n");
return NULL;
}
set_bit(PERSISTENT_GNT_ACTIVE, data->flags);
atomic_inc(&blkif->persistent_gnt_in_use);
return data;
}
}
return NULL;
}
static void put_persistent_gnt(struct xen_blkif *blkif,
struct persistent_gnt *persistent_gnt)
{
if(!test_bit(PERSISTENT_GNT_ACTIVE, persistent_gnt->flags))
pr_alert_ratelimited(DRV_PFX " freeing a grant already unused");
set_bit(PERSISTENT_GNT_WAS_ACTIVE, persistent_gnt->flags);
clear_bit(PERSISTENT_GNT_ACTIVE, persistent_gnt->flags);
atomic_dec(&blkif->persistent_gnt_in_use);
}
static void free_persistent_gnts(struct xen_blkif *blkif, struct rb_root *root,
unsigned int num)
{
struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST];
struct page *pages[BLKIF_MAX_SEGMENTS_PER_REQUEST];
struct persistent_gnt *persistent_gnt;
struct rb_node *n;
int ret = 0;
int segs_to_unmap = 0;
foreach_grant_safe(persistent_gnt, n, root, node) {
BUG_ON(persistent_gnt->handle ==
BLKBACK_INVALID_HANDLE);
gnttab_set_unmap
钱亚锋
- 粉丝: 107
- 资源: 1万+
最新资源
- 基于springboot+vue的实践性教学系统源码(java毕业设计完整源码+LW).zip
- 基于SpringBoot的食物营养分析与推荐网站的设计与实现源码(java毕业设计完整源码+LW).zip
- AvalonDock-master WPF
- 基于BS架构社区快递上门服务系统设计与实现源码(java毕业设计完整源码).zip
- (177631206)大麦抢票+源代码+辅助工具+详细文档教程
- 基于javaweb宿舍管理系统源码(java毕业设计完整源码).zip
- 英飞凌79AMOSFET
- 基于javaweb的在线购物平台源码(java毕业设计完整源码).zip
- ETOPO2022一秒钟冰面高程数据集.zip
- 基于全阶滑模观测器的IPMSM无位置传感器控制策略研究
- 基于JavaWeb的宠物救助及领养平台的设计与实现源码(java毕业设计完整源码+LW).zip
- 设计模式 DesignPatterns C#源码
- 基于Java技术的救灾物资调动系统源码(java毕业设计完整源码).zip
- 机械设计无纺布检测机(sw可编辑+工程图+bom)全套设计资料100%好用.zip
- MATLAB用yalmip+cplex解决电动汽车有序充放电问题,目标函数为总负荷峰谷差最小,代码可运行且有注释
- 基于java的城市公交查询系统源码(java毕业设计完整源码+LW).zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
评论0