Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  *  character device driver for reading z/VM system service records
0004  *
0005  *
0006  *  Copyright IBM Corp. 2004, 2009
0007  *  character device driver for reading z/VM system service records,
0008  *  Version 1.0
0009  *  Author(s): Xenia Tkatschow <xenia@us.ibm.com>
0010  *         Stefan Weinhuber <wein@de.ibm.com>
0011  *
0012  */
0013 
0014 #define KMSG_COMPONENT "vmlogrdr"
0015 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
0016 
0017 #include <linux/module.h>
0018 #include <linux/init.h>
0019 #include <linux/slab.h>
0020 #include <linux/errno.h>
0021 #include <linux/types.h>
0022 #include <linux/interrupt.h>
0023 #include <linux/spinlock.h>
0024 #include <linux/atomic.h>
0025 #include <linux/uaccess.h>
0026 #include <asm/cpcmd.h>
0027 #include <asm/debug.h>
0028 #include <asm/ebcdic.h>
0029 #include <net/iucv/iucv.h>
0030 #include <linux/kmod.h>
0031 #include <linux/cdev.h>
0032 #include <linux/device.h>
0033 #include <linux/string.h>
0034 
0035 MODULE_AUTHOR
0036     ("(C) 2004 IBM Corporation by Xenia Tkatschow (xenia@us.ibm.com)\n"
0037      "                            Stefan Weinhuber (wein@de.ibm.com)");
0038 MODULE_DESCRIPTION ("Character device driver for reading z/VM "
0039             "system service records.");
0040 MODULE_LICENSE("GPL");
0041 
0042 
0043 /*
0044  * The size of the buffer for iucv data transfer is one page,
0045  * but in addition to the data we read from iucv we also
0046  * place an integer and some characters into that buffer,
0047  * so the maximum size for record data is a little less then
0048  * one page.
0049  */
0050 #define NET_BUFFER_SIZE (PAGE_SIZE - sizeof(int) - sizeof(FENCE))
0051 
0052 /*
0053  * The elements that are concurrently accessed by bottom halves are
0054  * connection_established, iucv_path_severed, local_interrupt_buffer
0055  * and receive_ready. The first three can be protected by
0056  * priv_lock.  receive_ready is atomic, so it can be incremented and
0057  * decremented without holding a lock.
0058  * The variable dev_in_use needs to be protected by the lock, since
0059  * it's a flag used by open to make sure that the device is opened only
0060  * by one user at the same time.
0061  */
0062 struct vmlogrdr_priv_t {
0063     char system_service[8];
0064     char internal_name[8];
0065     char recording_name[8];
0066     struct iucv_path *path;
0067     int connection_established;
0068     int iucv_path_severed;
0069     struct iucv_message local_interrupt_buffer;
0070     atomic_t receive_ready;
0071     int minor_num;
0072     char * buffer;
0073     char * current_position;
0074     int remaining;
0075     ulong residual_length;
0076     int buffer_free;
0077     int dev_in_use; /* 1: already opened, 0: not opened*/
0078     spinlock_t priv_lock;
0079     struct device  *device;
0080     struct device  *class_device;
0081     int autorecording;
0082     int autopurge;
0083 };
0084 
0085 
0086 /*
0087  * File operation structure for vmlogrdr devices
0088  */
0089 static int vmlogrdr_open(struct inode *, struct file *);
0090 static int vmlogrdr_release(struct inode *, struct file *);
0091 static ssize_t vmlogrdr_read (struct file *filp, char __user *data,
0092                   size_t count, loff_t * ppos);
0093 
0094 static const struct file_operations vmlogrdr_fops = {
0095     .owner   = THIS_MODULE,
0096     .open    = vmlogrdr_open,
0097     .release = vmlogrdr_release,
0098     .read    = vmlogrdr_read,
0099     .llseek  = no_llseek,
0100 };
0101 
0102 
0103 static void vmlogrdr_iucv_path_complete(struct iucv_path *, u8 *ipuser);
0104 static void vmlogrdr_iucv_path_severed(struct iucv_path *, u8 *ipuser);
0105 static void vmlogrdr_iucv_message_pending(struct iucv_path *,
0106                       struct iucv_message *);
0107 
0108 
0109 static struct iucv_handler vmlogrdr_iucv_handler = {
0110     .path_complete   = vmlogrdr_iucv_path_complete,
0111     .path_severed    = vmlogrdr_iucv_path_severed,
0112     .message_pending = vmlogrdr_iucv_message_pending,
0113 };
0114 
0115 
0116 static DECLARE_WAIT_QUEUE_HEAD(conn_wait_queue);
0117 static DECLARE_WAIT_QUEUE_HEAD(read_wait_queue);
0118 
0119 /*
0120  * pointer to system service private structure
0121  * minor number 0 --> logrec
0122  * minor number 1 --> account
0123  * minor number 2 --> symptom
0124  */
0125 
0126 static struct vmlogrdr_priv_t sys_ser[] = {
0127     { .system_service = "*LOGREC ",
0128       .internal_name  = "logrec",
0129       .recording_name = "EREP",
0130       .minor_num      = 0,
0131       .buffer_free    = 1,
0132       .priv_lock      = __SPIN_LOCK_UNLOCKED(sys_ser[0].priv_lock),
0133       .autorecording  = 1,
0134       .autopurge      = 1,
0135     },
0136     { .system_service = "*ACCOUNT",
0137       .internal_name  = "account",
0138       .recording_name = "ACCOUNT",
0139       .minor_num      = 1,
0140       .buffer_free    = 1,
0141       .priv_lock      = __SPIN_LOCK_UNLOCKED(sys_ser[1].priv_lock),
0142       .autorecording  = 1,
0143       .autopurge      = 1,
0144     },
0145     { .system_service = "*SYMPTOM",
0146       .internal_name  = "symptom",
0147       .recording_name = "SYMPTOM",
0148       .minor_num      = 2,
0149       .buffer_free    = 1,
0150       .priv_lock      = __SPIN_LOCK_UNLOCKED(sys_ser[2].priv_lock),
0151       .autorecording  = 1,
0152       .autopurge      = 1,
0153     }
0154 };
0155 
0156 #define MAXMINOR  ARRAY_SIZE(sys_ser)
0157 
0158 static char FENCE[] = {"EOR"};
0159 static int vmlogrdr_major = 0;
0160 static struct cdev  *vmlogrdr_cdev = NULL;
0161 static int recording_class_AB;
0162 
0163 
0164 static void vmlogrdr_iucv_path_complete(struct iucv_path *path, u8 *ipuser)
0165 {
0166     struct vmlogrdr_priv_t * logptr = path->private;
0167 
0168     spin_lock(&logptr->priv_lock);
0169     logptr->connection_established = 1;
0170     spin_unlock(&logptr->priv_lock);
0171     wake_up(&conn_wait_queue);
0172 }
0173 
0174 
0175 static void vmlogrdr_iucv_path_severed(struct iucv_path *path, u8 *ipuser)
0176 {
0177     struct vmlogrdr_priv_t * logptr = path->private;
0178     u8 reason = (u8) ipuser[8];
0179 
0180     pr_err("vmlogrdr: connection severed with reason %i\n", reason);
0181 
0182     iucv_path_sever(path, NULL);
0183     kfree(path);
0184     logptr->path = NULL;
0185 
0186     spin_lock(&logptr->priv_lock);
0187     logptr->connection_established = 0;
0188     logptr->iucv_path_severed = 1;
0189     spin_unlock(&logptr->priv_lock);
0190 
0191     wake_up(&conn_wait_queue);
0192     /* just in case we're sleeping waiting for a record */
0193     wake_up_interruptible(&read_wait_queue);
0194 }
0195 
0196 
0197 static void vmlogrdr_iucv_message_pending(struct iucv_path *path,
0198                       struct iucv_message *msg)
0199 {
0200     struct vmlogrdr_priv_t * logptr = path->private;
0201 
0202     /*
0203      * This function is the bottom half so it should be quick.
0204      * Copy the external interrupt data into our local eib and increment
0205      * the usage count
0206      */
0207     spin_lock(&logptr->priv_lock);
0208     memcpy(&logptr->local_interrupt_buffer, msg, sizeof(*msg));
0209     atomic_inc(&logptr->receive_ready);
0210     spin_unlock(&logptr->priv_lock);
0211     wake_up_interruptible(&read_wait_queue);
0212 }
0213 
0214 
0215 static int vmlogrdr_get_recording_class_AB(void)
0216 {
0217     static const char cp_command[] = "QUERY COMMAND RECORDING ";
0218     char cp_response[80];
0219     char *tail;
0220     int len,i;
0221 
0222     cpcmd(cp_command, cp_response, sizeof(cp_response), NULL);
0223     len = strnlen(cp_response,sizeof(cp_response));
0224     // now the parsing
0225     tail=strnchr(cp_response,len,'=');
0226     if (!tail)
0227         return 0;
0228     tail++;
0229     if (!strncmp("ANY",tail,3))
0230         return 1;
0231     if (!strncmp("NONE",tail,4))
0232         return 0;
0233     /*
0234      * expect comma separated list of classes here, if one of them
0235      * is A or B return 1 otherwise 0
0236      */
0237         for (i=tail-cp_response; i<len; i++)
0238         if ( cp_response[i]=='A' || cp_response[i]=='B' )
0239             return 1;
0240     return 0;
0241 }
0242 
0243 
0244 static int vmlogrdr_recording(struct vmlogrdr_priv_t * logptr,
0245                   int action, int purge)
0246 {
0247 
0248     char cp_command[80];
0249     char cp_response[160];
0250     char *onoff, *qid_string;
0251     int rc;
0252 
0253     onoff = ((action == 1) ? "ON" : "OFF");
0254     qid_string = ((recording_class_AB == 1) ? " QID * " : "");
0255 
0256     /*
0257      * The recording commands needs to be called with option QID
0258      * for guests that have previlege classes A or B.
0259      * Purging has to be done as separate step, because recording
0260      * can't be switched on as long as records are on the queue.
0261      * Doing both at the same time doesn't work.
0262      */
0263     if (purge && (action == 1)) {
0264         memset(cp_command, 0x00, sizeof(cp_command));
0265         memset(cp_response, 0x00, sizeof(cp_response));
0266         snprintf(cp_command, sizeof(cp_command),
0267              "RECORDING %s PURGE %s",
0268              logptr->recording_name,
0269              qid_string);
0270         cpcmd(cp_command, cp_response, sizeof(cp_response), NULL);
0271     }
0272 
0273     memset(cp_command, 0x00, sizeof(cp_command));
0274     memset(cp_response, 0x00, sizeof(cp_response));
0275     snprintf(cp_command, sizeof(cp_command), "RECORDING %s %s %s",
0276         logptr->recording_name,
0277         onoff,
0278         qid_string);
0279     cpcmd(cp_command, cp_response, sizeof(cp_response), NULL);
0280     /* The recording command will usually answer with 'Command complete'
0281      * on success, but when the specific service was never connected
0282      * before then there might be an additional informational message
0283      * 'HCPCRC8072I Recording entry not found' before the
0284      * 'Command complete'. So I use strstr rather then the strncmp.
0285      */
0286     if (strstr(cp_response,"Command complete"))
0287         rc = 0;
0288     else
0289         rc = -EIO;
0290     /*
0291      * If we turn recording off, we have to purge any remaining records
0292      * afterwards, as a large number of queued records may impact z/VM
0293      * performance.
0294      */
0295     if (purge && (action == 0)) {
0296         memset(cp_command, 0x00, sizeof(cp_command));
0297         memset(cp_response, 0x00, sizeof(cp_response));
0298         snprintf(cp_command, sizeof(cp_command),
0299              "RECORDING %s PURGE %s",
0300              logptr->recording_name,
0301              qid_string);
0302         cpcmd(cp_command, cp_response, sizeof(cp_response), NULL);
0303     }
0304 
0305     return rc;
0306 }
0307 
0308 
0309 static int vmlogrdr_open (struct inode *inode, struct file *filp)
0310 {
0311     int dev_num = 0;
0312     struct vmlogrdr_priv_t * logptr = NULL;
0313     int connect_rc = 0;
0314     int ret;
0315 
0316     dev_num = iminor(inode);
0317     if (dev_num >= MAXMINOR)
0318         return -ENODEV;
0319     logptr = &sys_ser[dev_num];
0320 
0321     /*
0322      * only allow for blocking reads to be open
0323      */
0324     if (filp->f_flags & O_NONBLOCK)
0325         return -EOPNOTSUPP;
0326 
0327     /* Besure this device hasn't already been opened */
0328     spin_lock_bh(&logptr->priv_lock);
0329     if (logptr->dev_in_use) {
0330         spin_unlock_bh(&logptr->priv_lock);
0331         return -EBUSY;
0332     }
0333     logptr->dev_in_use = 1;
0334     logptr->connection_established = 0;
0335     logptr->iucv_path_severed = 0;
0336     atomic_set(&logptr->receive_ready, 0);
0337     logptr->buffer_free = 1;
0338     spin_unlock_bh(&logptr->priv_lock);
0339 
0340     /* set the file options */
0341     filp->private_data = logptr;
0342 
0343     /* start recording for this service*/
0344     if (logptr->autorecording) {
0345         ret = vmlogrdr_recording(logptr,1,logptr->autopurge);
0346         if (ret)
0347             pr_warn("vmlogrdr: failed to start recording automatically\n");
0348     }
0349 
0350     /* create connection to the system service */
0351     logptr->path = iucv_path_alloc(10, 0, GFP_KERNEL);
0352     if (!logptr->path)
0353         goto out_dev;
0354     connect_rc = iucv_path_connect(logptr->path, &vmlogrdr_iucv_handler,
0355                        logptr->system_service, NULL, NULL,
0356                        logptr);
0357     if (connect_rc) {
0358         pr_err("vmlogrdr: iucv connection to %s "
0359                "failed with rc %i \n",
0360                logptr->system_service, connect_rc);
0361         goto out_path;
0362     }
0363 
0364     /* We've issued the connect and now we must wait for a
0365      * ConnectionComplete or ConnectinSevered Interrupt
0366      * before we can continue to process.
0367      */
0368     wait_event(conn_wait_queue, (logptr->connection_established)
0369            || (logptr->iucv_path_severed));
0370     if (logptr->iucv_path_severed)
0371         goto out_record;
0372     nonseekable_open(inode, filp);
0373     return 0;
0374 
0375 out_record:
0376     if (logptr->autorecording)
0377         vmlogrdr_recording(logptr,0,logptr->autopurge);
0378 out_path:
0379     kfree(logptr->path);    /* kfree(NULL) is ok. */
0380     logptr->path = NULL;
0381 out_dev:
0382     logptr->dev_in_use = 0;
0383     return -EIO;
0384 }
0385 
0386 
0387 static int vmlogrdr_release (struct inode *inode, struct file *filp)
0388 {
0389     int ret;
0390 
0391     struct vmlogrdr_priv_t * logptr = filp->private_data;
0392 
0393     iucv_path_sever(logptr->path, NULL);
0394     kfree(logptr->path);
0395     logptr->path = NULL;
0396     if (logptr->autorecording) {
0397         ret = vmlogrdr_recording(logptr,0,logptr->autopurge);
0398         if (ret)
0399             pr_warn("vmlogrdr: failed to stop recording automatically\n");
0400     }
0401     logptr->dev_in_use = 0;
0402 
0403     return 0;
0404 }
0405 
0406 
0407 static int vmlogrdr_receive_data(struct vmlogrdr_priv_t *priv)
0408 {
0409     int rc, *temp;
0410     /* we need to keep track of two data sizes here:
0411      * The number of bytes we need to receive from iucv and
0412      * the total number of bytes we actually write into the buffer.
0413      */
0414     int user_data_count, iucv_data_count;
0415     char * buffer;
0416 
0417     if (atomic_read(&priv->receive_ready)) {
0418         spin_lock_bh(&priv->priv_lock);
0419         if (priv->residual_length){
0420             /* receive second half of a record */
0421             iucv_data_count = priv->residual_length;
0422             user_data_count = 0;
0423             buffer = priv->buffer;
0424         } else {
0425             /* receive a new record:
0426              * We need to return the total length of the record
0427                          * + size of FENCE in the first 4 bytes of the buffer.
0428                  */
0429             iucv_data_count = priv->local_interrupt_buffer.length;
0430             user_data_count = sizeof(int);
0431             temp = (int*)priv->buffer;
0432             *temp= iucv_data_count + sizeof(FENCE);
0433             buffer = priv->buffer + sizeof(int);
0434         }
0435         /*
0436          * If the record is bigger than our buffer, we receive only
0437          * a part of it. We can get the rest later.
0438          */
0439         if (iucv_data_count > NET_BUFFER_SIZE)
0440             iucv_data_count = NET_BUFFER_SIZE;
0441         rc = iucv_message_receive(priv->path,
0442                       &priv->local_interrupt_buffer,
0443                       0, buffer, iucv_data_count,
0444                       &priv->residual_length);
0445         spin_unlock_bh(&priv->priv_lock);
0446         /* An rc of 5 indicates that the record was bigger than
0447          * the buffer, which is OK for us. A 9 indicates that the
0448          * record was purged befor we could receive it.
0449          */
0450         if (rc == 5)
0451             rc = 0;
0452         if (rc == 9)
0453             atomic_set(&priv->receive_ready, 0);
0454     } else {
0455         rc = 1;
0456     }
0457     if (!rc) {
0458         priv->buffer_free = 0;
0459         user_data_count += iucv_data_count;
0460         priv->current_position = priv->buffer;
0461         if (priv->residual_length == 0){
0462             /* the whole record has been captured,
0463              * now add the fence */
0464             atomic_dec(&priv->receive_ready);
0465             buffer = priv->buffer + user_data_count;
0466             memcpy(buffer, FENCE, sizeof(FENCE));
0467             user_data_count += sizeof(FENCE);
0468         }
0469         priv->remaining = user_data_count;
0470     }
0471 
0472     return rc;
0473 }
0474 
0475 
0476 static ssize_t vmlogrdr_read(struct file *filp, char __user *data,
0477                  size_t count, loff_t * ppos)
0478 {
0479     int rc;
0480     struct vmlogrdr_priv_t * priv = filp->private_data;
0481 
0482     while (priv->buffer_free) {
0483         rc = vmlogrdr_receive_data(priv);
0484         if (rc) {
0485             rc = wait_event_interruptible(read_wait_queue,
0486                     atomic_read(&priv->receive_ready));
0487             if (rc)
0488                 return rc;
0489         }
0490     }
0491     /* copy only up to end of record */
0492     if (count > priv->remaining)
0493         count = priv->remaining;
0494 
0495     if (copy_to_user(data, priv->current_position, count))
0496         return -EFAULT;
0497 
0498     *ppos += count;
0499     priv->current_position += count;
0500     priv->remaining -= count;
0501 
0502     /* if all data has been transferred, set buffer free */
0503     if (priv->remaining == 0)
0504         priv->buffer_free = 1;
0505 
0506     return count;
0507 }
0508 
0509 static ssize_t vmlogrdr_autopurge_store(struct device * dev,
0510                     struct device_attribute *attr,
0511                     const char * buf, size_t count)
0512 {
0513     struct vmlogrdr_priv_t *priv = dev_get_drvdata(dev);
0514     ssize_t ret = count;
0515 
0516     switch (buf[0]) {
0517     case '0':
0518         priv->autopurge=0;
0519         break;
0520     case '1':
0521         priv->autopurge=1;
0522         break;
0523     default:
0524         ret = -EINVAL;
0525     }
0526     return ret;
0527 }
0528 
0529 
0530 static ssize_t vmlogrdr_autopurge_show(struct device *dev,
0531                        struct device_attribute *attr,
0532                        char *buf)
0533 {
0534     struct vmlogrdr_priv_t *priv = dev_get_drvdata(dev);
0535     return sprintf(buf, "%u\n", priv->autopurge);
0536 }
0537 
0538 
0539 static DEVICE_ATTR(autopurge, 0644, vmlogrdr_autopurge_show,
0540            vmlogrdr_autopurge_store);
0541 
0542 
0543 static ssize_t vmlogrdr_purge_store(struct device * dev,
0544                     struct device_attribute *attr,
0545                     const char * buf, size_t count)
0546 {
0547 
0548     char cp_command[80];
0549     char cp_response[80];
0550     struct vmlogrdr_priv_t *priv = dev_get_drvdata(dev);
0551 
0552     if (buf[0] != '1')
0553         return -EINVAL;
0554 
0555     memset(cp_command, 0x00, sizeof(cp_command));
0556     memset(cp_response, 0x00, sizeof(cp_response));
0557 
0558         /*
0559      * The recording command needs to be called with option QID
0560      * for guests that have previlege classes A or B.
0561      * Other guests will not recognize the command and we have to
0562      * issue the same command without the QID parameter.
0563      */
0564 
0565     if (recording_class_AB)
0566         snprintf(cp_command, sizeof(cp_command),
0567              "RECORDING %s PURGE QID * ",
0568              priv->recording_name);
0569     else
0570         snprintf(cp_command, sizeof(cp_command),
0571              "RECORDING %s PURGE ",
0572              priv->recording_name);
0573 
0574     cpcmd(cp_command, cp_response, sizeof(cp_response), NULL);
0575 
0576     return count;
0577 }
0578 
0579 
0580 static DEVICE_ATTR(purge, 0200, NULL, vmlogrdr_purge_store);
0581 
0582 
0583 static ssize_t vmlogrdr_autorecording_store(struct device *dev,
0584                         struct device_attribute *attr,
0585                         const char *buf, size_t count)
0586 {
0587     struct vmlogrdr_priv_t *priv = dev_get_drvdata(dev);
0588     ssize_t ret = count;
0589 
0590     switch (buf[0]) {
0591     case '0':
0592         priv->autorecording=0;
0593         break;
0594     case '1':
0595         priv->autorecording=1;
0596         break;
0597     default:
0598         ret = -EINVAL;
0599     }
0600     return ret;
0601 }
0602 
0603 
0604 static ssize_t vmlogrdr_autorecording_show(struct device *dev,
0605                        struct device_attribute *attr,
0606                        char *buf)
0607 {
0608     struct vmlogrdr_priv_t *priv = dev_get_drvdata(dev);
0609     return sprintf(buf, "%u\n", priv->autorecording);
0610 }
0611 
0612 
0613 static DEVICE_ATTR(autorecording, 0644, vmlogrdr_autorecording_show,
0614            vmlogrdr_autorecording_store);
0615 
0616 
0617 static ssize_t vmlogrdr_recording_store(struct device * dev,
0618                     struct device_attribute *attr,
0619                     const char * buf, size_t count)
0620 {
0621     struct vmlogrdr_priv_t *priv = dev_get_drvdata(dev);
0622     ssize_t ret;
0623 
0624     switch (buf[0]) {
0625     case '0':
0626         ret = vmlogrdr_recording(priv,0,0);
0627         break;
0628     case '1':
0629         ret = vmlogrdr_recording(priv,1,0);
0630         break;
0631     default:
0632         ret = -EINVAL;
0633     }
0634     if (ret)
0635         return ret;
0636     else
0637         return count;
0638 
0639 }
0640 
0641 
0642 static DEVICE_ATTR(recording, 0200, NULL, vmlogrdr_recording_store);
0643 
0644 
0645 static ssize_t recording_status_show(struct device_driver *driver, char *buf)
0646 {
0647     static const char cp_command[] = "QUERY RECORDING ";
0648     int len;
0649 
0650     cpcmd(cp_command, buf, 4096, NULL);
0651     len = strlen(buf);
0652     return len;
0653 }
0654 static DRIVER_ATTR_RO(recording_status);
0655 static struct attribute *vmlogrdr_drv_attrs[] = {
0656     &driver_attr_recording_status.attr,
0657     NULL,
0658 };
0659 static struct attribute_group vmlogrdr_drv_attr_group = {
0660     .attrs = vmlogrdr_drv_attrs,
0661 };
0662 static const struct attribute_group *vmlogrdr_drv_attr_groups[] = {
0663     &vmlogrdr_drv_attr_group,
0664     NULL,
0665 };
0666 
0667 static struct attribute *vmlogrdr_attrs[] = {
0668     &dev_attr_autopurge.attr,
0669     &dev_attr_purge.attr,
0670     &dev_attr_autorecording.attr,
0671     &dev_attr_recording.attr,
0672     NULL,
0673 };
0674 static struct attribute_group vmlogrdr_attr_group = {
0675     .attrs = vmlogrdr_attrs,
0676 };
0677 static const struct attribute_group *vmlogrdr_attr_groups[] = {
0678     &vmlogrdr_attr_group,
0679     NULL,
0680 };
0681 
0682 static struct class *vmlogrdr_class;
0683 static struct device_driver vmlogrdr_driver = {
0684     .name = "vmlogrdr",
0685     .bus  = &iucv_bus,
0686     .groups = vmlogrdr_drv_attr_groups,
0687 };
0688 
0689 static int vmlogrdr_register_driver(void)
0690 {
0691     int ret;
0692 
0693     /* Register with iucv driver */
0694     ret = iucv_register(&vmlogrdr_iucv_handler, 1);
0695     if (ret)
0696         goto out;
0697 
0698     ret = driver_register(&vmlogrdr_driver);
0699     if (ret)
0700         goto out_iucv;
0701 
0702     vmlogrdr_class = class_create(THIS_MODULE, "vmlogrdr");
0703     if (IS_ERR(vmlogrdr_class)) {
0704         ret = PTR_ERR(vmlogrdr_class);
0705         vmlogrdr_class = NULL;
0706         goto out_driver;
0707     }
0708     return 0;
0709 
0710 out_driver:
0711     driver_unregister(&vmlogrdr_driver);
0712 out_iucv:
0713     iucv_unregister(&vmlogrdr_iucv_handler, 1);
0714 out:
0715     return ret;
0716 }
0717 
0718 
0719 static void vmlogrdr_unregister_driver(void)
0720 {
0721     class_destroy(vmlogrdr_class);
0722     vmlogrdr_class = NULL;
0723     driver_unregister(&vmlogrdr_driver);
0724     iucv_unregister(&vmlogrdr_iucv_handler, 1);
0725 }
0726 
0727 
0728 static int vmlogrdr_register_device(struct vmlogrdr_priv_t *priv)
0729 {
0730     struct device *dev;
0731     int ret;
0732 
0733     dev = kzalloc(sizeof(struct device), GFP_KERNEL);
0734     if (dev) {
0735         dev_set_name(dev, "%s", priv->internal_name);
0736         dev->bus = &iucv_bus;
0737         dev->parent = iucv_root;
0738         dev->driver = &vmlogrdr_driver;
0739         dev->groups = vmlogrdr_attr_groups;
0740         dev_set_drvdata(dev, priv);
0741         /*
0742          * The release function could be called after the
0743          * module has been unloaded. It's _only_ task is to
0744          * free the struct. Therefore, we specify kfree()
0745          * directly here. (Probably a little bit obfuscating
0746          * but legitime ...).
0747          */
0748         dev->release = (void (*)(struct device *))kfree;
0749     } else
0750         return -ENOMEM;
0751     ret = device_register(dev);
0752     if (ret) {
0753         put_device(dev);
0754         return ret;
0755     }
0756 
0757     priv->class_device = device_create(vmlogrdr_class, dev,
0758                        MKDEV(vmlogrdr_major,
0759                          priv->minor_num),
0760                        priv, "%s", dev_name(dev));
0761     if (IS_ERR(priv->class_device)) {
0762         ret = PTR_ERR(priv->class_device);
0763         priv->class_device=NULL;
0764         device_unregister(dev);
0765         return ret;
0766     }
0767     priv->device = dev;
0768     return 0;
0769 }
0770 
0771 
0772 static int vmlogrdr_unregister_device(struct vmlogrdr_priv_t *priv)
0773 {
0774     device_destroy(vmlogrdr_class, MKDEV(vmlogrdr_major, priv->minor_num));
0775     if (priv->device != NULL) {
0776         device_unregister(priv->device);
0777         priv->device=NULL;
0778     }
0779     return 0;
0780 }
0781 
0782 
0783 static int vmlogrdr_register_cdev(dev_t dev)
0784 {
0785     int rc = 0;
0786     vmlogrdr_cdev = cdev_alloc();
0787     if (!vmlogrdr_cdev) {
0788         return -ENOMEM;
0789     }
0790     vmlogrdr_cdev->owner = THIS_MODULE;
0791     vmlogrdr_cdev->ops = &vmlogrdr_fops;
0792     rc = cdev_add(vmlogrdr_cdev, dev, MAXMINOR);
0793     if (!rc)
0794         return 0;
0795 
0796     // cleanup: cdev is not fully registered, no cdev_del here!
0797     kobject_put(&vmlogrdr_cdev->kobj);
0798     vmlogrdr_cdev=NULL;
0799     return rc;
0800 }
0801 
0802 
0803 static void vmlogrdr_cleanup(void)
0804 {
0805         int i;
0806 
0807     if (vmlogrdr_cdev) {
0808         cdev_del(vmlogrdr_cdev);
0809         vmlogrdr_cdev=NULL;
0810     }
0811     for (i=0; i < MAXMINOR; ++i ) {
0812         vmlogrdr_unregister_device(&sys_ser[i]);
0813         free_page((unsigned long)sys_ser[i].buffer);
0814     }
0815     vmlogrdr_unregister_driver();
0816     if (vmlogrdr_major) {
0817         unregister_chrdev_region(MKDEV(vmlogrdr_major, 0), MAXMINOR);
0818         vmlogrdr_major=0;
0819     }
0820 }
0821 
0822 
0823 static int __init vmlogrdr_init(void)
0824 {
0825     int rc;
0826     int i;
0827     dev_t dev;
0828 
0829     if (! MACHINE_IS_VM) {
0830         pr_err("not running under VM, driver not loaded.\n");
0831         return -ENODEV;
0832     }
0833 
0834         recording_class_AB = vmlogrdr_get_recording_class_AB();
0835 
0836     rc = alloc_chrdev_region(&dev, 0, MAXMINOR, "vmlogrdr");
0837     if (rc)
0838         return rc;
0839     vmlogrdr_major = MAJOR(dev);
0840 
0841     rc=vmlogrdr_register_driver();
0842     if (rc)
0843         goto cleanup;
0844 
0845     for (i=0; i < MAXMINOR; ++i ) {
0846         sys_ser[i].buffer = (char *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
0847         if (!sys_ser[i].buffer) {
0848             rc = -ENOMEM;
0849             break;
0850         }
0851         sys_ser[i].current_position = sys_ser[i].buffer;
0852         rc=vmlogrdr_register_device(&sys_ser[i]);
0853         if (rc)
0854             break;
0855     }
0856     if (rc)
0857         goto cleanup;
0858 
0859     rc = vmlogrdr_register_cdev(dev);
0860     if (rc)
0861         goto cleanup;
0862     return 0;
0863 
0864 cleanup:
0865     vmlogrdr_cleanup();
0866     return rc;
0867 }
0868 
0869 
0870 static void __exit vmlogrdr_exit(void)
0871 {
0872     vmlogrdr_cleanup();
0873     return;
0874 }
0875 
0876 
0877 module_init(vmlogrdr_init);
0878 module_exit(vmlogrdr_exit);