aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJanosch Frank <frankja@linux.vnet.ibm.com>2016-05-18 07:26:23 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2016-05-25 10:12:05 -0400
commit536a6f88c49dd739961ffd53774775afed852c83 (patch)
treeda2c0c7f8f0c55258c0beee21d4551004edb3749
parent6d0a1a61e7b2eb21415aea7e3c5df7c6e456f33a (diff)
KVM: Create debugfs dir and stat files for each VM
This patch adds a kvm debugfs subdirectory for each VM, which is named after its pid and file descriptor. The directories contain the same kind of files that are already in the kvm debugfs directory, but the data exported through them is now VM specific. This makes the debugfs kvm data a convenient alternative to the tracepoints which already have per VM data. The debugfs data is easy to read and low overhead. CC: Dan Carpenter <dan.carpenter@oracle.com> [includes fixes by Dan Carpenter] Signed-off-by: Janosch Frank <frankja@linux.vnet.ibm.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--include/linux/kvm_host.h7
-rw-r--r--virt/kvm/kvm_main.c187
2 files changed, 184 insertions, 10 deletions
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index b1fa8f11c95b..1c9c973a7dd9 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -412,6 +412,8 @@ struct kvm {
412#endif 412#endif
413 long tlbs_dirty; 413 long tlbs_dirty;
414 struct list_head devices; 414 struct list_head devices;
415 struct dentry *debugfs_dentry;
416 struct kvm_stat_data **debugfs_stat_data;
415}; 417};
416 418
417#define kvm_err(fmt, ...) \ 419#define kvm_err(fmt, ...) \
@@ -991,6 +993,11 @@ enum kvm_stat_kind {
991 KVM_STAT_VCPU, 993 KVM_STAT_VCPU,
992}; 994};
993 995
996struct kvm_stat_data {
997 int offset;
998 struct kvm *kvm;
999};
1000
994struct kvm_stats_debugfs_item { 1001struct kvm_stats_debugfs_item {
995 const char *name; 1002 const char *name;
996 int offset; 1003 int offset;
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index dd4ac9d9e8f5..37af23052470 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -63,6 +63,9 @@
63#define CREATE_TRACE_POINTS 63#define CREATE_TRACE_POINTS
64#include <trace/events/kvm.h> 64#include <trace/events/kvm.h>
65 65
66/* Worst case buffer size needed for holding an integer. */
67#define ITOA_MAX_LEN 12
68
66MODULE_AUTHOR("Qumranet"); 69MODULE_AUTHOR("Qumranet");
67MODULE_LICENSE("GPL"); 70MODULE_LICENSE("GPL");
68 71
@@ -100,6 +103,9 @@ static __read_mostly struct preempt_ops kvm_preempt_ops;
100struct dentry *kvm_debugfs_dir; 103struct dentry *kvm_debugfs_dir;
101EXPORT_SYMBOL_GPL(kvm_debugfs_dir); 104EXPORT_SYMBOL_GPL(kvm_debugfs_dir);
102 105
106static int kvm_debugfs_num_entries;
107static const struct file_operations *stat_fops_per_vm[];
108
103static long kvm_vcpu_ioctl(struct file *file, unsigned int ioctl, 109static long kvm_vcpu_ioctl(struct file *file, unsigned int ioctl,
104 unsigned long arg); 110 unsigned long arg);
105#ifdef CONFIG_KVM_COMPAT 111#ifdef CONFIG_KVM_COMPAT
@@ -542,6 +548,58 @@ static void kvm_free_memslots(struct kvm *kvm, struct kvm_memslots *slots)
542 kvfree(slots); 548 kvfree(slots);
543} 549}
544 550
551static void kvm_destroy_vm_debugfs(struct kvm *kvm)
552{
553 int i;
554
555 if (!kvm->debugfs_dentry)
556 return;
557
558 debugfs_remove_recursive(kvm->debugfs_dentry);
559
560 for (i = 0; i < kvm_debugfs_num_entries; i++)
561 kfree(kvm->debugfs_stat_data[i]);
562 kfree(kvm->debugfs_stat_data);
563}
564
565static int kvm_create_vm_debugfs(struct kvm *kvm, int fd)
566{
567 char dir_name[ITOA_MAX_LEN * 2];
568 struct kvm_stat_data *stat_data;
569 struct kvm_stats_debugfs_item *p;
570
571 if (!debugfs_initialized())
572 return 0;
573
574 snprintf(dir_name, sizeof(dir_name), "%d-%d", task_pid_nr(current), fd);
575 kvm->debugfs_dentry = debugfs_create_dir(dir_name,
576 kvm_debugfs_dir);
577 if (!kvm->debugfs_dentry)
578 return -ENOMEM;
579
580 kvm->debugfs_stat_data = kcalloc(kvm_debugfs_num_entries,
581 sizeof(*kvm->debugfs_stat_data),
582 GFP_KERNEL);
583 if (!kvm->debugfs_stat_data)
584 return -ENOMEM;
585
586 for (p = debugfs_entries; p->name; p++) {
587 stat_data = kzalloc(sizeof(*stat_data), GFP_KERNEL);
588 if (!stat_data)
589 return -ENOMEM;
590
591 stat_data->kvm = kvm;
592 stat_data->offset = p->offset;
593 kvm->debugfs_stat_data[p - debugfs_entries] = stat_data;
594 if (!debugfs_create_file(p->name, 0444,
595 kvm->debugfs_dentry,
596 stat_data,
597 stat_fops_per_vm[p->kind]))
598 return -ENOMEM;
599 }
600 return 0;
601}
602
545static struct kvm *kvm_create_vm(unsigned long type) 603static struct kvm *kvm_create_vm(unsigned long type)
546{ 604{
547 int r, i; 605 int r, i;
@@ -647,6 +705,7 @@ static void kvm_destroy_vm(struct kvm *kvm)
647 int i; 705 int i;
648 struct mm_struct *mm = kvm->mm; 706 struct mm_struct *mm = kvm->mm;
649 707
708 kvm_destroy_vm_debugfs(kvm);
650 kvm_arch_sync_events(kvm); 709 kvm_arch_sync_events(kvm);
651 spin_lock(&kvm_lock); 710 spin_lock(&kvm_lock);
652 list_del(&kvm->vm_list); 711 list_del(&kvm->vm_list);
@@ -2999,8 +3058,15 @@ static int kvm_dev_ioctl_create_vm(unsigned long type)
2999 } 3058 }
3000#endif 3059#endif
3001 r = anon_inode_getfd("kvm-vm", &kvm_vm_fops, kvm, O_RDWR | O_CLOEXEC); 3060 r = anon_inode_getfd("kvm-vm", &kvm_vm_fops, kvm, O_RDWR | O_CLOEXEC);
3002 if (r < 0) 3061 if (r < 0) {
3003 kvm_put_kvm(kvm); 3062 kvm_put_kvm(kvm);
3063 return r;
3064 }
3065
3066 if (kvm_create_vm_debugfs(kvm, r) < 0) {
3067 kvm_put_kvm(kvm);
3068 return -ENOMEM;
3069 }
3004 3070
3005 return r; 3071 return r;
3006} 3072}
@@ -3425,15 +3491,114 @@ static struct notifier_block kvm_cpu_notifier = {
3425 .notifier_call = kvm_cpu_hotplug, 3491 .notifier_call = kvm_cpu_hotplug,
3426}; 3492};
3427 3493
3494static int kvm_debugfs_open(struct inode *inode, struct file *file,
3495 int (*get)(void *, u64 *), int (*set)(void *, u64),
3496 const char *fmt)
3497{
3498 struct kvm_stat_data *stat_data = (struct kvm_stat_data *)
3499 inode->i_private;
3500
3501 /* The debugfs files are a reference to the kvm struct which
3502 * is still valid when kvm_destroy_vm is called.
3503 * To avoid the race between open and the removal of the debugfs
3504 * directory we test against the users count.
3505 */
3506 if (!atomic_add_unless(&stat_data->kvm->users_count, 1, 0))
3507 return -ENOENT;
3508
3509 if (simple_attr_open(inode, file, get, set, fmt)) {
3510 kvm_put_kvm(stat_data->kvm);
3511 return -ENOMEM;
3512 }
3513
3514 return 0;
3515}
3516
3517static int kvm_debugfs_release(struct inode *inode, struct file *file)
3518{
3519 struct kvm_stat_data *stat_data = (struct kvm_stat_data *)
3520 inode->i_private;
3521
3522 simple_attr_release(inode, file);
3523 kvm_put_kvm(stat_data->kvm);
3524
3525 return 0;
3526}
3527
3528static int vm_stat_get_per_vm(void *data, u64 *val)
3529{
3530 struct kvm_stat_data *stat_data = (struct kvm_stat_data *)data;
3531
3532 *val = *(u32 *)((void *)stat_data->kvm + stat_data->offset);
3533
3534 return 0;
3535}
3536
3537static int vm_stat_get_per_vm_open(struct inode *inode, struct file *file)
3538{
3539 __simple_attr_check_format("%llu\n", 0ull);
3540 return kvm_debugfs_open(inode, file, vm_stat_get_per_vm,
3541 NULL, "%llu\n");
3542}
3543
3544static const struct file_operations vm_stat_get_per_vm_fops = {
3545 .owner = THIS_MODULE,
3546 .open = vm_stat_get_per_vm_open,
3547 .release = kvm_debugfs_release,
3548 .read = simple_attr_read,
3549 .write = simple_attr_write,
3550 .llseek = generic_file_llseek,
3551};
3552
3553static int vcpu_stat_get_per_vm(void *data, u64 *val)
3554{
3555 int i;
3556 struct kvm_stat_data *stat_data = (struct kvm_stat_data *)data;
3557 struct kvm_vcpu *vcpu;
3558
3559 *val = 0;
3560
3561 kvm_for_each_vcpu(i, vcpu, stat_data->kvm)
3562 *val += *(u32 *)((void *)vcpu + stat_data->offset);
3563
3564 return 0;
3565}
3566
3567static int vcpu_stat_get_per_vm_open(struct inode *inode, struct file *file)
3568{
3569 __simple_attr_check_format("%llu\n", 0ull);
3570 return kvm_debugfs_open(inode, file, vcpu_stat_get_per_vm,
3571 NULL, "%llu\n");
3572}
3573
3574static const struct file_operations vcpu_stat_get_per_vm_fops = {
3575 .owner = THIS_MODULE,
3576 .open = vcpu_stat_get_per_vm_open,
3577 .release = kvm_debugfs_release,
3578 .read = simple_attr_read,
3579 .write = simple_attr_write,
3580 .llseek = generic_file_llseek,
3581};
3582
3583static const struct file_operations *stat_fops_per_vm[] = {
3584 [KVM_STAT_VCPU] = &vcpu_stat_get_per_vm_fops,
3585 [KVM_STAT_VM] = &vm_stat_get_per_vm_fops,
3586};
3587
3428static int vm_stat_get(void *_offset, u64 *val) 3588static int vm_stat_get(void *_offset, u64 *val)
3429{ 3589{
3430 unsigned offset = (long)_offset; 3590 unsigned offset = (long)_offset;
3431 struct kvm *kvm; 3591 struct kvm *kvm;
3592 struct kvm_stat_data stat_tmp = {.offset = offset};
3593 u64 tmp_val;
3432 3594
3433 *val = 0; 3595 *val = 0;
3434 spin_lock(&kvm_lock); 3596 spin_lock(&kvm_lock);
3435 list_for_each_entry(kvm, &vm_list, vm_list) 3597 list_for_each_entry(kvm, &vm_list, vm_list) {
3436 *val += *(u32 *)((void *)kvm + offset); 3598 stat_tmp.kvm = kvm;
3599 vm_stat_get_per_vm((void *)&stat_tmp, &tmp_val);
3600 *val += tmp_val;
3601 }
3437 spin_unlock(&kvm_lock); 3602 spin_unlock(&kvm_lock);
3438 return 0; 3603 return 0;
3439} 3604}
@@ -3444,15 +3609,16 @@ static int vcpu_stat_get(void *_offset, u64 *val)
3444{ 3609{
3445 unsigned offset = (long)_offset; 3610 unsigned offset = (long)_offset;
3446 struct kvm *kvm; 3611 struct kvm *kvm;
3447 struct kvm_vcpu *vcpu; 3612 struct kvm_stat_data stat_tmp = {.offset = offset};
3448 int i; 3613 u64 tmp_val;
3449 3614
3450 *val = 0; 3615 *val = 0;
3451 spin_lock(&kvm_lock); 3616 spin_lock(&kvm_lock);
3452 list_for_each_entry(kvm, &vm_list, vm_list) 3617 list_for_each_entry(kvm, &vm_list, vm_list) {
3453 kvm_for_each_vcpu(i, vcpu, kvm) 3618 stat_tmp.kvm = kvm;
3454 *val += *(u32 *)((void *)vcpu + offset); 3619 vcpu_stat_get_per_vm((void *)&stat_tmp, &tmp_val);
3455 3620 *val += tmp_val;
3621 }
3456 spin_unlock(&kvm_lock); 3622 spin_unlock(&kvm_lock);
3457 return 0; 3623 return 0;
3458} 3624}
@@ -3473,7 +3639,8 @@ static int kvm_init_debug(void)
3473 if (kvm_debugfs_dir == NULL) 3639 if (kvm_debugfs_dir == NULL)
3474 goto out; 3640 goto out;
3475 3641
3476 for (p = debugfs_entries; p->name; ++p) { 3642 kvm_debugfs_num_entries = 0;
3643 for (p = debugfs_entries; p->name; ++p, kvm_debugfs_num_entries++) {
3477 if (!debugfs_create_file(p->name, 0444, kvm_debugfs_dir, 3644 if (!debugfs_create_file(p->name, 0444, kvm_debugfs_dir,
3478 (void *)(long)p->offset, 3645 (void *)(long)p->offset,
3479 stat_fops[p->kind])) 3646 stat_fops[p->kind]))