static inline void mon_read_debug(struct mon_msg *monmsg, struct mon_private *monpriv) { #ifdef MON_DEBUG u8 msg_type[2], mca_type; unsigned long records_len; records_len = mon_rec_end(monmsg) - mon_rec_start(monmsg) + 1; memcpy(msg_type, &monmsg->msg.class, 2); EBCASC(msg_type, 2); mca_type = mon_mca_type(monmsg, 0); EBCASC(&mca_type, 1); P_DEBUG("read, mon_read_index = %i, mon_write_index = %i\n", monpriv->read_index, monpriv->write_index); P_DEBUG("read, pathid = 0x%04X, msgid = 0x%08X, trgcls = 0x%08X\n", monpriv->path->pathid, monmsg->msg.id, monmsg->msg.class); P_DEBUG("read, msg_type = '%c%c', mca_type = '%c' / 0x%X / 0x%X\n", msg_type[0], msg_type[1], mca_type ? mca_type : 'X', mon_mca_type(monmsg, 1), mon_mca_type(monmsg, 2)); P_DEBUG("read, MCA: start = 0x%lX, end = 0x%lX\n", mon_mca_start(monmsg), mon_mca_end(monmsg)); P_DEBUG("read, REC: start = 0x%X, end = 0x%X, len = %lu\n\n", mon_rec_start(monmsg), mon_rec_end(monmsg), records_len); if (mon_mca_size(monmsg) > 12) P_DEBUG("READ, MORE THAN ONE MCA\n\n"); #endif }
static int mon_check_mca(struct mon_msg *monmsg) { if ((mon_rec_end(monmsg) <= mon_rec_start(monmsg)) || (mon_rec_start(monmsg) < mon_dcss_start) || (mon_rec_end(monmsg) > mon_dcss_end) || (mon_mca_type(monmsg, 0) == 0) || (mon_mca_size(monmsg) % 12 != 0) || (mon_mca_end(monmsg) <= mon_mca_start(monmsg)) || (mon_mca_end(monmsg) > mon_dcss_end) || (mon_mca_start(monmsg) < mon_dcss_start) || ((mon_mca_type(monmsg, 1) == 0) && (mon_mca_type(monmsg, 2) == 0))) return -EINVAL; return 0; }
static int mon_check_mca(struct mon_msg *monmsg) { if ((mon_rec_end(monmsg) <= mon_rec_start(monmsg)) || (mon_rec_start(monmsg) < mon_dcss_start) || (mon_rec_end(monmsg) > mon_dcss_end) || (mon_mca_type(monmsg, 0) == 0) || (mon_mca_size(monmsg) % 12 != 0) || (mon_mca_end(monmsg) <= mon_mca_start(monmsg)) || (mon_mca_end(monmsg) > mon_dcss_end) || (mon_mca_start(monmsg) < mon_dcss_start) || ((mon_mca_type(monmsg, 1) == 0) && (mon_mca_type(monmsg, 2) == 0))) { P_DEBUG("READ, IGNORED INVALID MCA\n\n"); return -EINVAL; } return 0; }
static ssize_t mon_read(struct file *filp, char __user *data, size_t count, loff_t *ppos) { struct mon_private *monpriv = filp->private_data; struct mon_msg *monmsg; int ret; u32 mce_start; monmsg = mon_next_message(monpriv); if (IS_ERR(monmsg)) return PTR_ERR(monmsg); if (!monmsg) { if (filp->f_flags & O_NONBLOCK) return -EAGAIN; ret = wait_event_interruptible(mon_read_wait_queue, atomic_read(&monpriv->read_ready) || atomic_read(&monpriv->iucv_severed)); if (ret) return ret; if (unlikely(atomic_read(&monpriv->iucv_severed))) return -EIO; monmsg = monpriv->msg_array[monpriv->read_index]; } if (!monmsg->pos) monmsg->pos = mon_mca_start(monmsg) + monmsg->mca_offset; if (mon_check_mca(monmsg)) goto reply; /* read monitor control element (12 bytes) first */ mce_start = mon_mca_start(monmsg) + monmsg->mca_offset; if ((monmsg->pos >= mce_start) && (monmsg->pos < mce_start + 12)) { count = min(count, (size_t) mce_start + 12 - monmsg->pos); ret = copy_to_user(data, (void *) (unsigned long) monmsg->pos, count); if (ret) return -EFAULT; monmsg->pos += count; if (monmsg->pos == mce_start + 12) monmsg->pos = mon_rec_start(monmsg); goto out_copy; } /* read records */ if (monmsg->pos <= mon_rec_end(monmsg)) { count = min(count, (size_t) mon_rec_end(monmsg) - monmsg->pos + 1); ret = copy_to_user(data, (void *) (unsigned long) monmsg->pos, count); if (ret) return -EFAULT; monmsg->pos += count; if (monmsg->pos > mon_rec_end(monmsg)) mon_next_mca(monmsg); goto out_copy; } reply: ret = mon_send_reply(monmsg, monpriv); return ret; out_copy: *ppos += count; return count; }