[Devel] [PATCH] vziolimit: add bc cgroup control

Konstantin Khorenko khorenko at odin.com
Mon Apr 27 08:13:04 PDT 2015


Volodya, please review it from the interface's point of view.

--
Best regards,

Konstantin Khorenko,
Virtuozzo Linux Kernel Team

On 04/27/2015 05:50 PM, Dmitry Monakhov wrote:
> Example: Equivalent if: vzctl set $VE --iopslimit 10 --save
> 
> echo 15000 > /sys/fs/cgroup/beancounter/$VE/beancounter.iopslimit.burst
> echo 1000  > /sys/fs/cgroup/beancounter/$VE/beancounter.iopslimit.latency
> echo 10    > /sys/fs/cgroup/beancounter/$VE/beancounter.iopslimit.speed
> 
> Signed-off-by: Dmitry Monakhov <dmonakhov at openvz.org>
> ---
>  include/bc/beancounter.h |    7 ++
>  kernel/bc/beancounter.c  |    7 +--
>  kernel/ve/vziolimit.c    |  152 +++++++++++++++++++++++++++++++++++++++++++++-
>  3 files changed, 159 insertions(+), 7 deletions(-)
> 
> diff --git a/include/bc/beancounter.h b/include/bc/beancounter.h
> index 3ee6389..faf0197 100644
> --- a/include/bc/beancounter.h
> +++ b/include/bc/beancounter.h
> @@ -178,6 +178,13 @@ enum ub_severity { UB_HARD, UB_SOFT, UB_FORCE };
>  #define UB_TEST	0x100
>  #define UB_SEV_FLAGS	UB_TEST
>  
> +extern struct cgroup_subsys ub_subsys;
> +static inline struct user_beancounter *cgroup_ub(struct cgroup *cg)
> +{
> +	return container_of(cgroup_subsys_state(cg, ub_subsys_id),
> +			    struct user_beancounter, css);
> +}
> +
>  static inline int ub_barrier_hit(struct user_beancounter *ub, int resource)
>  {
>  	return ub->ub_parms[resource].held > ub->ub_parms[resource].barrier;
> diff --git a/kernel/bc/beancounter.c b/kernel/bc/beancounter.c
> index c9b17de..76936e0 100644
> --- a/kernel/bc/beancounter.c
> +++ b/kernel/bc/beancounter.c
> @@ -319,12 +319,6 @@ LIST_HEAD(ub_list_head); /* protected by ub_list_lock */
>  EXPORT_SYMBOL(ub_list_head);
>  int ub_count;
>  
> -static inline struct user_beancounter *cgroup_ub(struct cgroup *cg)
> -{
> -	return container_of(cgroup_subsys_state(cg, ub_subsys_id),
> -			    struct user_beancounter, css);
> -}
> -
>  /*
>   *	Per user resource beancounting. Resources are tied to their luid.
>   *	The resource structure itself is tagged both to the process and
> @@ -713,6 +707,7 @@ struct cgroup_subsys ub_subsys = {
>  	.attach = ub_cgroup_attach,
>  	.use_id = true,
>  };
> +EXPORT_SYMBOL(ub_subsys);
>  
>  /*
>   *	Generic resource charging stuff
> diff --git a/kernel/ve/vziolimit.c b/kernel/ve/vziolimit.c
> index 9e2b014..d78bf27 100644
> --- a/kernel/ve/vziolimit.c
> +++ b/kernel/ve/vziolimit.c
> @@ -25,6 +25,16 @@ struct throttle {
>         long long state;		/* current state in units */
>  };
>  
> +enum {
> +	UB_CGROUP_IOLIMIT_SPEED 	= 0,
> +	UB_CGROUP_IOLIMIT_BURST 	= 1,
> +	UB_CGROUP_IOLIMIT_LATENCY 	= 2,
> +	UB_CGROUP_IOPSLIMIT_SPEED 	= 3,
> +	UB_CGROUP_IOPSLIMIT_BURST 	= 4,
> +	UB_CGROUP_IOPSLIMIT_LATENCY 	= 5,
> +
> +};
> +
>  /**
>   * set throttler initial state, externally serialized
>   * @speed	maximum speed (1/sec)
> @@ -350,16 +360,156 @@ static struct vzioctlinfo iolimit_vzioctl = {
>  	.owner		= THIS_MODULE,
>  };
>  
> +static ssize_t iolimit_cgroup_read(struct cgroup *cg, struct cftype *cft,
> +			      struct file *file, char __user *buf,
> +			      size_t nbytes, loff_t *ppos)
> +{
> +	struct user_beancounter *ub = cgroup_ub(cg);
> +	struct iolimit *iolimit = ub->private_data2;
> +	unsigned long val = 0;
> +	int len;
> +	char str[32];
> +
> +	if (!iolimit)
> +		goto out;
> +
> +	spin_lock_irq(&ub->ub_lock);
> +	switch (cft->private) {
> +	case UB_CGROUP_IOLIMIT_SPEED:
> +		val = iolimit->throttle.speed;
> +		break;
> +	case UB_CGROUP_IOLIMIT_BURST:
> +		val = iolimit->throttle.burst;
> +		break;
> +	case UB_CGROUP_IOLIMIT_LATENCY:
> +		val = iolimit->throttle.latency;
> +		break;
> +
> +	case UB_CGROUP_IOPSLIMIT_SPEED:
> +		val = iolimit->iops.speed;
> +		break;
> +	case UB_CGROUP_IOPSLIMIT_BURST:
> +		val = iolimit->iops.burst;
> +		break;
> +	case UB_CGROUP_IOPSLIMIT_LATENCY:
> +		val = iolimit->iops.latency;
> +		break;
> +	default:
> +		BUG();
> +	}
> +	spin_unlock_irq(&ub->ub_lock);
> +out:
> +	len = scnprintf(str, sizeof(str), "%lu\n", val);
> +	return simple_read_from_buffer(buf, nbytes, ppos, str, len);
> +}
> +
> +static int iolimit_cgroup_write_u64(struct cgroup *cg, struct cftype *cft, u64 val)
> +{
> +	struct user_beancounter *ub = cgroup_ub(cg);
> +	struct iolimit *iolimit;
> +
> +	iolimit = iolimit_get(ub);
> +	if (!iolimit)
> +		return -ENOMEM;
> +
> +	spin_lock_irq(&ub->ub_lock);
> +	iolimit->throttle.time = iolimit->iops.time = jiffies;
> +
> +	switch (cft->private) {
> +	case UB_CGROUP_IOLIMIT_SPEED:
> +		wmb();
> +		iolimit->throttle.speed = val;
> +		break;
> +	case UB_CGROUP_IOPSLIMIT_SPEED:
> +		wmb();
> +		iolimit->iops.speed = val;
> +		break;
> +	case UB_CGROUP_IOLIMIT_BURST:
> +		iolimit->throttle.burst = val;
> +		break;
> +	case UB_CGROUP_IOLIMIT_LATENCY:
> +		iolimit->throttle.latency = val;
> +		break;
> +	case UB_CGROUP_IOPSLIMIT_BURST:
> +		iolimit->iops.burst = val;
> +		break;
> +	case UB_CGROUP_IOPSLIMIT_LATENCY:
> +		iolimit->iops.latency = val;
> +		break;
> +	default:
> +		BUG();
> +	}
> +	wake_up_all(&iolimit->wq);
> +	spin_unlock_irq(&ub->ub_lock);
> +	return 0;
> +}
> +
> +static struct cftype vziolimit_cftypes[] = {
> +	{
> +		.name = "iolimit.speed",
> +		.flags = CFTYPE_NOT_ON_ROOT,
> +		.private = UB_CGROUP_IOLIMIT_SPEED,
> +		.read = iolimit_cgroup_read,
> +		.write_u64 = iolimit_cgroup_write_u64,
> +	},
> +	{
> +		.name = "iolimit.burst",
> +		.flags = CFTYPE_NOT_ON_ROOT,
> +		.private = UB_CGROUP_IOLIMIT_BURST,
> +		.read = iolimit_cgroup_read,
> +		.write_u64 = iolimit_cgroup_write_u64,
> +	},
> +	{
> +		.name = "iolimit.latency",
> +		.flags = CFTYPE_NOT_ON_ROOT,
> +		.private = UB_CGROUP_IOLIMIT_LATENCY,
> +		.read = iolimit_cgroup_read,
> +		.write_u64 = iolimit_cgroup_write_u64,
> +	},
> +
> +	{
> +		.name = "iopslimit.speed",
> +		.flags = CFTYPE_NOT_ON_ROOT,
> +		.private = UB_CGROUP_IOPSLIMIT_SPEED,
> +		.read = iolimit_cgroup_read,
> +		.write_u64 = iolimit_cgroup_write_u64,
> +	},
> +	{
> +		.name = "iopslimit.burst",
> +		.flags = CFTYPE_NOT_ON_ROOT,
> +		.private = UB_CGROUP_IOPSLIMIT_BURST,
> +		.read = iolimit_cgroup_read,
> +		.write_u64 = iolimit_cgroup_write_u64,
> +	},
> +	{
> +		.name = "iopslimit.latency",
> +		.flags = CFTYPE_NOT_ON_ROOT,
> +		.private = UB_CGROUP_IOPSLIMIT_LATENCY,
> +		.read = iolimit_cgroup_read,
> +		.write_u64 = iolimit_cgroup_write_u64,
> +	},
> +	{ }
> +};
> +
>  static int __init iolimit_init(void)
>  {
> +	int err;
>  	virtinfo_notifier_register(VITYPE_IO, &iolimit_virtinfo_nb);
>  	vzioctl_register(&iolimit_vzioctl);
> -
> +	err = cgroup_add_cftypes(&ub_subsys, vziolimit_cftypes);
> +	if (err)
> +		goto err_cgroup;
>  	return 0;
> +
> +err_cgroup:
> +	vzioctl_unregister(&iolimit_vzioctl);
> +	virtinfo_notifier_unregister(VITYPE_IO, &iolimit_virtinfo_nb);
> +	return err;
>  }
>  
>  static void __exit iolimit_exit(void)
>  {
> +	cgroup_rm_cftypes(&ub_subsys, vziolimit_cftypes);
>  	vzioctl_unregister(&iolimit_vzioctl);
>  	virtinfo_notifier_unregister(VITYPE_IO, &iolimit_virtinfo_nb);
>  }
> 



More information about the Devel mailing list