⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vmlogrdr.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
			 * We need to return the total length of the record                         * + size of FENCE in the first 4 bytes of the buffer.		         */			iucv_data_count =				priv->local_interrupt_buffer.ln1msg2.ipbfln1f;			user_data_count = sizeof(int);			temp = (int*)priv->buffer;			*temp= iucv_data_count + sizeof(FENCE);			buffer = priv->buffer + sizeof(int);		}		/*		 * If the record is bigger then our buffer, we receive only		 * a part of it. We can get the rest later.		 */		if (iucv_data_count > NET_BUFFER_SIZE)			iucv_data_count = NET_BUFFER_SIZE;		rc = iucv_receive(priv->pathid,				  priv->local_interrupt_buffer.ipmsgid,				  priv->local_interrupt_buffer.iptrgcls,				  buffer,				  iucv_data_count,				  NULL,				  NULL,				  &priv->residual_length);		spin_unlock_bh(&priv->priv_lock);		/* An rc of 5 indicates that the record was bigger then		 * the buffer, which is OK for us. A 9 indicates that the		 * record was purged befor we could receive it.		 */		if (rc == 5)			rc = 0;		if (rc == 9)			atomic_set(&priv->receive_ready, 0);	} else {		rc = 1;	}	if (!rc) {		priv->buffer_free = 0; 		user_data_count += iucv_data_count;		priv->current_position = priv->buffer;		if (priv->residual_length == 0){			/* the whole record has been captured,			 * now add the fence */			atomic_dec(&priv->receive_ready);			buffer = priv->buffer + user_data_count;			memcpy(buffer, FENCE, sizeof(FENCE));			user_data_count += sizeof(FENCE);		}		priv->remaining = user_data_count;	}	return rc;}static ssize_tvmlogrdr_read (struct file *filp, char *data, size_t count, loff_t * ppos){	int rc;	struct vmlogrdr_priv_t * priv = filp->private_data;	while (priv->buffer_free) {		rc = vmlogrdr_receive_data(priv);		if (rc) {			rc = wait_event_interruptible(read_wait_queue,					atomic_read(&priv->receive_ready));			if (rc)				return rc;		}	}	/* copy only up to end of record */	if (count > priv->remaining)		count = priv->remaining;	if (copy_to_user(data, priv->current_position, count))		return -EFAULT;	*ppos += count;	priv->current_position += count;	priv->remaining -= count;	/* if all data has been transferred, set buffer free */	if (priv->remaining == 0)		priv->buffer_free = 1;	return count;}static ssize_tvmlogrdr_autopurge_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t count) {	struct vmlogrdr_priv_t *priv = dev->driver_data;	ssize_t ret = count;	switch (buf[0]) {	case '0':		priv->autopurge=0;		break;	case '1':		priv->autopurge=1;		break;	default:		ret = -EINVAL;	}	return ret;}static ssize_tvmlogrdr_autopurge_show(struct device *dev, struct device_attribute *attr, char *buf) {	struct vmlogrdr_priv_t *priv = dev->driver_data;	return sprintf(buf, "%u\n", priv->autopurge);}static DEVICE_ATTR(autopurge, 0644, vmlogrdr_autopurge_show,		   vmlogrdr_autopurge_store);static ssize_tvmlogrdr_purge_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t count) {	char cp_command[80];	char cp_response[80];	struct vmlogrdr_priv_t *priv = dev->driver_data;	if (buf[0] != '1')		return -EINVAL;	memset(cp_command, 0x00, sizeof(cp_command));	memset(cp_response, 0x00, sizeof(cp_response));        /*	 * The recording command needs to be called with option QID	 * for guests that have previlege classes A or B.	 * Other guests will not recognize the command and we have to	 * issue the same command without the QID parameter.	 */	if (recording_class_AB)		snprintf(cp_command, sizeof(cp_command),			 "RECORDING %s PURGE QID * ",			 priv->recording_name);	else		snprintf(cp_command, sizeof(cp_command),			 "RECORDING %s PURGE ",			 priv->recording_name);	printk (KERN_DEBUG "vmlogrdr: recording command: %s\n", cp_command);	cpcmd(cp_command, cp_response, sizeof(cp_response), NULL);	printk (KERN_DEBUG "vmlogrdr: recording response: %s",		cp_response);	return count;}static DEVICE_ATTR(purge, 0200, NULL, vmlogrdr_purge_store);static ssize_tvmlogrdr_autorecording_store(struct device *dev, struct device_attribute *attr, const char *buf,			     size_t count) {	struct vmlogrdr_priv_t *priv = dev->driver_data;	ssize_t ret = count;	switch (buf[0]) {	case '0':		priv->autorecording=0;		break;	case '1':		priv->autorecording=1;		break;	default:		ret = -EINVAL;	}	return ret;}static ssize_tvmlogrdr_autorecording_show(struct device *dev, struct device_attribute *attr, char *buf) {	struct vmlogrdr_priv_t *priv = dev->driver_data;	return sprintf(buf, "%u\n", priv->autorecording);}static DEVICE_ATTR(autorecording, 0644, vmlogrdr_autorecording_show,		   vmlogrdr_autorecording_store);static ssize_tvmlogrdr_recording_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t count) {	struct vmlogrdr_priv_t *priv = dev->driver_data;	ssize_t ret;	switch (buf[0]) {	case '0':		ret = vmlogrdr_recording(priv,0,0);		break;	case '1':		ret = vmlogrdr_recording(priv,1,0);		break;	default:		ret = -EINVAL;	}	if (ret)		return ret;	else		return count;}static DEVICE_ATTR(recording, 0200, NULL, vmlogrdr_recording_store);static ssize_tvmlogrdr_recording_status_show(struct device_driver *driver, char *buf) {	char cp_command[] = "QUERY RECORDING ";	int len;	cpcmd(cp_command, buf, 4096, NULL);	len = strlen(buf);	return len;}static DRIVER_ATTR(recording_status, 0444, vmlogrdr_recording_status_show,		   NULL);static struct attribute *vmlogrdr_attrs[] = {	&dev_attr_autopurge.attr,	&dev_attr_purge.attr,	&dev_attr_autorecording.attr,	&dev_attr_recording.attr,	NULL,};static struct attribute_group vmlogrdr_attr_group = {	.attrs = vmlogrdr_attrs,};static struct class *vmlogrdr_class;static struct device_driver vmlogrdr_driver = {	.name = "vmlogrdr",	.bus  = &iucv_bus,};static intvmlogrdr_register_driver(void) {	int ret;	ret = driver_register(&vmlogrdr_driver);	if (ret) {		printk(KERN_ERR "vmlogrdr: failed to register driver.\n");		return ret;	}	ret = driver_create_file(&vmlogrdr_driver,				 &driver_attr_recording_status);	if (ret) {		printk(KERN_ERR "vmlogrdr: failed to add driver attribute.\n");		goto unregdriver;	}	vmlogrdr_class = class_create(THIS_MODULE, "vmlogrdr");	if (IS_ERR(vmlogrdr_class)) {		printk(KERN_ERR "vmlogrdr: failed to create class.\n");		ret=PTR_ERR(vmlogrdr_class);		vmlogrdr_class=NULL;		goto unregattr;	}	return 0;unregattr:	driver_remove_file(&vmlogrdr_driver, &driver_attr_recording_status);unregdriver:	driver_unregister(&vmlogrdr_driver);	return ret;}static voidvmlogrdr_unregister_driver(void) {	class_destroy(vmlogrdr_class);	vmlogrdr_class = NULL;	driver_remove_file(&vmlogrdr_driver, &driver_attr_recording_status);	driver_unregister(&vmlogrdr_driver);	return;}static intvmlogrdr_register_device(struct vmlogrdr_priv_t *priv) {	struct device *dev;	int ret;	dev = kmalloc(sizeof(struct device), GFP_KERNEL);	if (dev) {		memset(dev, 0, sizeof(struct device));		snprintf(dev->bus_id, BUS_ID_SIZE, "%s",			 priv->internal_name);		dev->bus = &iucv_bus;		dev->parent = iucv_root;		dev->driver = &vmlogrdr_driver;		/*		 * The release function could be called after the		 * module has been unloaded. It's _only_ task is to		 * free the struct. Therefore, we specify kfree()		 * directly here. (Probably a little bit obfuscating		 * but legitime ...).		 */		dev->release = (void (*)(struct device *))kfree;	} else		return -ENOMEM;	ret = device_register(dev);	if (ret)		return ret;	ret = sysfs_create_group(&dev->kobj, &vmlogrdr_attr_group);	if (ret) {		device_unregister(dev);		return ret;	}	priv->class_device = class_device_create(				vmlogrdr_class,				NULL,				MKDEV(vmlogrdr_major, priv->minor_num),				dev,				"%s", dev->bus_id );	if (IS_ERR(priv->class_device)) {		ret = PTR_ERR(priv->class_device);		priv->class_device=NULL;		sysfs_remove_group(&dev->kobj, &vmlogrdr_attr_group);		device_unregister(dev);		return ret;	}	dev->driver_data = priv;	priv->device = dev;	return 0;}static intvmlogrdr_unregister_device(struct vmlogrdr_priv_t *priv ) {	class_device_destroy(vmlogrdr_class, MKDEV(vmlogrdr_major, priv->minor_num));	if (priv->device != NULL) {		sysfs_remove_group(&priv->device->kobj, &vmlogrdr_attr_group);		device_unregister(priv->device);		priv->device=NULL;	}	return 0;}static intvmlogrdr_register_cdev(dev_t dev) {	int rc = 0;	vmlogrdr_cdev = cdev_alloc();	if (!vmlogrdr_cdev) {		return -ENOMEM;	}	vmlogrdr_cdev->owner = THIS_MODULE;	vmlogrdr_cdev->ops = &vmlogrdr_fops;	vmlogrdr_cdev->dev = dev;	rc = cdev_add(vmlogrdr_cdev, vmlogrdr_cdev->dev, MAXMINOR);	if (!rc)		return 0;	// cleanup: cdev is not fully registered, no cdev_del here!	kobject_put(&vmlogrdr_cdev->kobj);	vmlogrdr_cdev=NULL;	return rc;}static voidvmlogrdr_cleanup(void) {        int i;	if (vmlogrdr_cdev) {		cdev_del(vmlogrdr_cdev);		vmlogrdr_cdev=NULL;	}	for (i=0; i < MAXMINOR; ++i ) {		vmlogrdr_unregister_device(&sys_ser[i]);		free_page((unsigned long)sys_ser[i].buffer);	}	vmlogrdr_unregister_driver();	if (vmlogrdr_major) {		unregister_chrdev_region(MKDEV(vmlogrdr_major, 0), MAXMINOR);		vmlogrdr_major=0;	}}static intvmlogrdr_init(void){	int rc;	int i;	dev_t dev;	if (! MACHINE_IS_VM) {		printk (KERN_ERR "vmlogrdr: not running under VM, "				"driver not loaded.\n");		return -ENODEV;	}        recording_class_AB = vmlogrdr_get_recording_class_AB();	rc = alloc_chrdev_region(&dev, 0, MAXMINOR, "vmlogrdr");	if (rc)		return rc;	vmlogrdr_major = MAJOR(dev);	rc=vmlogrdr_register_driver();	if (rc)		goto cleanup;	for (i=0; i < MAXMINOR; ++i ) {		sys_ser[i].buffer = (char *) get_zeroed_page(GFP_KERNEL);		if (!sys_ser[i].buffer) {			rc = ENOMEM;			break;		}		sys_ser[i].current_position = sys_ser[i].buffer;		rc=vmlogrdr_register_device(&sys_ser[i]);		if (rc)			break;	}	if (rc)		goto cleanup;	rc = vmlogrdr_register_cdev(dev);	if (rc)		goto cleanup;	printk (KERN_INFO "vmlogrdr: driver loaded\n");	return 0;cleanup:	vmlogrdr_cleanup();	printk (KERN_ERR "vmlogrdr: driver not loaded.\n");	return rc;}static voidvmlogrdr_exit(void){	vmlogrdr_cleanup();	printk (KERN_INFO "vmlogrdr: driver unloaded\n");	return;}module_init(vmlogrdr_init);module_exit(vmlogrdr_exit);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -