Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

s390/dasd: enhance CUIR scope detection

This patch adds an enhanced detection for control unit initiated
reconfiguration request scope.
The first approach assumed the scope of the reconfiguration request
to be restricted to the path on which the message was received.
The enhanced approach determines the full scope of the reconfiguration
request by evaluating additional path and device selection information
contained in the reconfiguration message.

Reviewed-by: Peter Oberparleiter <oberpar@linux.vnet.ibm.com>
Reviewed-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: Stefan Haberland <stefan.haberland@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>

authored by

Stefan Haberland and committed by
Martin Schwidefsky
b179b037 1eb38023

+255 -79
+245 -78
drivers/s390/block/dasd_eckd.c
··· 1036 1036 { 1037 1037 void *conf_data; 1038 1038 int conf_len, conf_data_saved; 1039 - int rc, path_err; 1039 + int rc, path_err, pos; 1040 1040 __u8 lpm, opm; 1041 1041 struct dasd_eckd_private *private, path_private; 1042 1042 struct dasd_path *path_data; ··· 1068 1068 path_data->opm |= lpm; 1069 1069 continue; /* no error */ 1070 1070 } 1071 + /* translate path mask to position in mask */ 1072 + pos = 8 - ffs(lpm); 1073 + kfree(private->path_conf_data[pos]); 1074 + if ((__u8 *)private->path_conf_data[pos] == 1075 + private->conf_data) { 1076 + private->conf_data = NULL; 1077 + private->conf_len = 0; 1078 + conf_data_saved = 0; 1079 + } 1080 + private->path_conf_data[pos] = 1081 + (struct dasd_conf_data *) conf_data; 1071 1082 /* save first valid configuration data */ 1072 1083 if (!conf_data_saved) { 1073 1084 kfree(private->conf_data); ··· 1106 1095 kfree(conf_data); 1107 1096 continue; 1108 1097 } 1109 - 1110 1098 if (dasd_eckd_compare_path_uid( 1111 1099 device, &path_private)) { 1112 1100 uid = &path_private.uid; ··· 1167 1157 path_data->cablepm &= ~lpm; 1168 1158 path_data->hpfpm &= ~lpm; 1169 1159 path_data->cuirpm &= ~lpm; 1170 - 1171 - if (conf_data != private->conf_data) 1172 - kfree(conf_data); 1173 1160 } 1174 1161 1175 1162 return path_err; ··· 1821 1814 static void dasd_eckd_uncheck_device(struct dasd_device *device) 1822 1815 { 1823 1816 struct dasd_eckd_private *private; 1817 + int i; 1824 1818 1825 1819 private = (struct dasd_eckd_private *) device->private; 1826 1820 dasd_alias_disconnect_device_from_lcu(device); ··· 1830 1822 private->vdsneq = NULL; 1831 1823 private->gneq = NULL; 1832 1824 private->conf_len = 0; 1825 + for (i = 0; i < 8; i++) { 1826 + kfree(private->path_conf_data[i]); 1827 + if ((__u8 *)private->path_conf_data[i] == 1828 + private->conf_data) { 1829 + private->conf_data = NULL; 1830 + private->conf_len = 0; 1831 + } 1832 + private->path_conf_data[i] = NULL; 1833 + } 1833 1834 kfree(private->conf_data); 1834 1835 private->conf_data = NULL; 1835 1836 } ··· 4546 4529 cqr->startdev = device; 4547 4530 cqr->memdev = device; 4548 4531 cqr->block = NULL; 4549 - cqr->retries = 256; 4550 4532 cqr->expires = 10 * HZ; 4551 - 4552 - /* we need to check for messages on exactly this path */ 4553 4533 set_bit(DASD_CQR_VERIFY_PATH, &cqr->flags); 4554 - cqr->lpm = lpum; 4534 + /* dasd_sleep_on_immediatly does not do complex error 4535 + * recovery so clear erp flag and set retry counter to 4536 + * do basic erp */ 4537 + clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); 4538 + cqr->retries = 256; 4555 4539 4556 4540 /* Prepare for Read Subsystem Data */ 4557 4541 prssdp = (struct dasd_psf_prssd_data *) cqr->data; ··· 4627 4609 psf_cuir->message_id = message_id; 4628 4610 psf_cuir->cssid = sch_id.cssid; 4629 4611 psf_cuir->ssid = sch_id.ssid; 4630 - 4631 4612 ccw = cqr->cpaddr; 4632 4613 ccw->cmd_code = DASD_ECKD_CCW_PSF; 4633 4614 ccw->cda = (__u32)(addr_t)psf_cuir; 4615 + ccw->flags = CCW_FLAG_SLI; 4634 4616 ccw->count = sizeof(struct dasd_psf_cuir_response); 4635 4617 4636 4618 cqr->startdev = device; ··· 4640 4622 cqr->expires = 10*HZ; 4641 4623 cqr->buildclk = get_tod_clock(); 4642 4624 cqr->status = DASD_CQR_FILLED; 4625 + set_bit(DASD_CQR_VERIFY_PATH, &cqr->flags); 4643 4626 4644 4627 rc = dasd_sleep_on(cqr); 4645 4628 ··· 4648 4629 return rc; 4649 4630 } 4650 4631 4651 - static int dasd_eckd_cuir_change_state(struct dasd_device *device, __u8 lpum) 4632 + /* 4633 + * return configuration data that is referenced by record selector 4634 + * if a record selector is specified or per default return the 4635 + * conf_data pointer for the path specified by lpum 4636 + */ 4637 + static struct dasd_conf_data *dasd_eckd_get_ref_conf(struct dasd_device *device, 4638 + __u8 lpum, 4639 + struct dasd_cuir_message *cuir) 4652 4640 { 4653 - unsigned long flags; 4654 - __u8 tbcpm; 4641 + struct dasd_eckd_private *private; 4642 + struct dasd_conf_data *conf_data; 4643 + int path, pos; 4655 4644 4656 - spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); 4657 - tbcpm = device->path_data.opm & ~lpum; 4658 - if (tbcpm) { 4659 - device->path_data.opm = tbcpm; 4660 - device->path_data.cuirpm |= lpum; 4645 + private = (struct dasd_eckd_private *) device->private; 4646 + if (cuir->record_selector == 0) 4647 + goto out; 4648 + for (path = 0x80, pos = 0; path; path >>= 1, pos++) { 4649 + conf_data = private->path_conf_data[pos]; 4650 + if (conf_data->gneq.record_selector == 4651 + cuir->record_selector) 4652 + return conf_data; 4661 4653 } 4662 - spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); 4663 - return tbcpm ? 0 : PSF_CUIR_LAST_PATH; 4654 + out: 4655 + return private->path_conf_data[8 - ffs(lpum)]; 4664 4656 } 4665 4657 4666 4658 /* 4667 - * walk through all devices and quiesce them 4668 - * if it is the last path return error 4659 + * This function determines the scope of a reconfiguration request by 4660 + * analysing the path and device selection data provided in the CUIR request. 4661 + * Returns a path mask containing CUIR affected paths for the give device. 4662 + * 4663 + * If the CUIR request does not contain the required information return the 4664 + * path mask of the path the attention message for the CUIR request was reveived 4665 + * on. 4666 + */ 4667 + static int dasd_eckd_cuir_scope(struct dasd_device *device, __u8 lpum, 4668 + struct dasd_cuir_message *cuir) 4669 + { 4670 + struct dasd_conf_data *ref_conf_data; 4671 + unsigned long bitmask = 0, mask = 0; 4672 + struct dasd_eckd_private *private; 4673 + struct dasd_conf_data *conf_data; 4674 + unsigned int pos, path; 4675 + char *ref_gneq, *gneq; 4676 + char *ref_ned, *ned; 4677 + int tbcpm = 0; 4678 + 4679 + /* if CUIR request does not specify the scope use the path 4680 + the attention message was presented on */ 4681 + if (!cuir->ned_map || 4682 + !(cuir->neq_map[0] | cuir->neq_map[1] | cuir->neq_map[2])) 4683 + return lpum; 4684 + 4685 + private = (struct dasd_eckd_private *) device->private; 4686 + /* get reference conf data */ 4687 + ref_conf_data = dasd_eckd_get_ref_conf(device, lpum, cuir); 4688 + /* reference ned is determined by ned_map field */ 4689 + pos = 8 - ffs(cuir->ned_map); 4690 + ref_ned = (char *)&ref_conf_data->neds[pos]; 4691 + ref_gneq = (char *)&ref_conf_data->gneq; 4692 + /* transfer 24 bit neq_map to mask */ 4693 + mask = cuir->neq_map[2]; 4694 + mask |= cuir->neq_map[1] << 8; 4695 + mask |= cuir->neq_map[0] << 16; 4696 + 4697 + for (path = 0x80; path; path >>= 1) { 4698 + /* initialise data per path */ 4699 + bitmask = mask; 4700 + pos = 8 - ffs(path); 4701 + conf_data = private->path_conf_data[pos]; 4702 + pos = 8 - ffs(cuir->ned_map); 4703 + ned = (char *) &conf_data->neds[pos]; 4704 + /* compare reference ned and per path ned */ 4705 + if (memcmp(ref_ned, ned, sizeof(*ned)) != 0) 4706 + continue; 4707 + gneq = (char *)&conf_data->gneq; 4708 + /* compare reference gneq and per_path gneq under 4709 + 24 bit mask where mask bit 0 equals byte 7 of 4710 + the gneq and mask bit 24 equals byte 31 */ 4711 + while (bitmask) { 4712 + pos = ffs(bitmask) - 1; 4713 + if (memcmp(&ref_gneq[31 - pos], &gneq[31 - pos], 1) 4714 + != 0) 4715 + break; 4716 + clear_bit(pos, &bitmask); 4717 + } 4718 + if (bitmask) 4719 + continue; 4720 + /* device and path match the reference values 4721 + add path to CUIR scope */ 4722 + tbcpm |= path; 4723 + } 4724 + return tbcpm; 4725 + } 4726 + 4727 + static void dasd_eckd_cuir_notify_user(struct dasd_device *device, 4728 + unsigned long paths, 4729 + struct subchannel_id sch_id, int action) 4730 + { 4731 + struct channel_path_desc *desc; 4732 + int pos; 4733 + 4734 + while (paths) { 4735 + /* get position of bit in mask */ 4736 + pos = ffs(paths) - 1; 4737 + /* get channel path descriptor from this position */ 4738 + desc = ccw_device_get_chp_desc(device->cdev, 7 - pos); 4739 + if (action == CUIR_QUIESCE) 4740 + pr_warn("Service on the storage server caused path " 4741 + "%x.%02x to go offline", sch_id.cssid, 4742 + desc ? desc->chpid : 0); 4743 + else if (action == CUIR_RESUME) 4744 + pr_info("Path %x.%02x is back online after service " 4745 + "on the storage server", sch_id.cssid, 4746 + desc ? desc->chpid : 0); 4747 + kfree(desc); 4748 + clear_bit(pos, &paths); 4749 + } 4750 + } 4751 + 4752 + static int dasd_eckd_cuir_remove_path(struct dasd_device *device, __u8 lpum, 4753 + struct dasd_cuir_message *cuir) 4754 + { 4755 + unsigned long tbcpm; 4756 + 4757 + tbcpm = dasd_eckd_cuir_scope(device, lpum, cuir); 4758 + /* nothing to do if path is not in use */ 4759 + if (!(device->path_data.opm & tbcpm)) 4760 + return 0; 4761 + if (!(device->path_data.opm & ~tbcpm)) { 4762 + /* no path would be left if the CUIR action is taken 4763 + return error */ 4764 + return -EINVAL; 4765 + } 4766 + /* remove device from operational path mask */ 4767 + device->path_data.opm &= ~tbcpm; 4768 + device->path_data.cuirpm |= tbcpm; 4769 + return tbcpm; 4770 + } 4771 + 4772 + /* 4773 + * walk through all devices and build a path mask to quiesce them 4774 + * return an error if the last path to a device would be removed 4669 4775 * 4670 4776 * if only part of the devices are quiesced and an error 4671 4777 * occurs no onlining necessary, the storage server will 4672 4778 * notify the already set offline devices again 4673 4779 */ 4674 4780 static int dasd_eckd_cuir_quiesce(struct dasd_device *device, __u8 lpum, 4675 - struct channel_path_desc *desc, 4676 - struct subchannel_id sch_id) 4781 + struct subchannel_id sch_id, 4782 + struct dasd_cuir_message *cuir) 4677 4783 { 4678 4784 struct alias_pav_group *pavgroup, *tempgroup; 4679 4785 struct dasd_eckd_private *private; 4680 4786 struct dasd_device *dev, *n; 4681 - int rc; 4787 + unsigned long paths = 0; 4788 + unsigned long flags; 4789 + int tbcpm; 4682 4790 4683 4791 private = (struct dasd_eckd_private *) device->private; 4684 - rc = 0; 4685 - 4686 4792 /* active devices */ 4687 - list_for_each_entry_safe(dev, n, 4688 - &private->lcu->active_devices, 4793 + list_for_each_entry_safe(dev, n, &private->lcu->active_devices, 4689 4794 alias_list) { 4690 - rc = dasd_eckd_cuir_change_state(dev, lpum); 4691 - if (rc) 4692 - goto out; 4795 + spin_lock_irqsave(get_ccwdev_lock(dev->cdev), flags); 4796 + tbcpm = dasd_eckd_cuir_remove_path(dev, lpum, cuir); 4797 + spin_unlock_irqrestore(get_ccwdev_lock(dev->cdev), flags); 4798 + if (tbcpm < 0) 4799 + goto out_err; 4800 + paths |= tbcpm; 4693 4801 } 4694 - 4695 4802 /* inactive devices */ 4696 - list_for_each_entry_safe(dev, n, 4697 - &private->lcu->inactive_devices, 4803 + list_for_each_entry_safe(dev, n, &private->lcu->inactive_devices, 4698 4804 alias_list) { 4699 - rc = dasd_eckd_cuir_change_state(dev, lpum); 4700 - if (rc) 4701 - goto out; 4805 + spin_lock_irqsave(get_ccwdev_lock(dev->cdev), flags); 4806 + tbcpm = dasd_eckd_cuir_remove_path(dev, lpum, cuir); 4807 + spin_unlock_irqrestore(get_ccwdev_lock(dev->cdev), flags); 4808 + if (tbcpm < 0) 4809 + goto out_err; 4810 + paths |= tbcpm; 4702 4811 } 4703 - 4704 4812 /* devices in PAV groups */ 4705 4813 list_for_each_entry_safe(pavgroup, tempgroup, 4706 4814 &private->lcu->grouplist, group) { 4707 4815 list_for_each_entry_safe(dev, n, &pavgroup->baselist, 4708 4816 alias_list) { 4709 - rc = dasd_eckd_cuir_change_state(dev, lpum); 4710 - if (rc) 4711 - goto out; 4817 + spin_lock_irqsave(get_ccwdev_lock(dev->cdev), flags); 4818 + tbcpm = dasd_eckd_cuir_remove_path(dev, lpum, cuir); 4819 + spin_unlock_irqrestore( 4820 + get_ccwdev_lock(dev->cdev), flags); 4821 + if (tbcpm < 0) 4822 + goto out_err; 4823 + paths |= tbcpm; 4712 4824 } 4713 4825 list_for_each_entry_safe(dev, n, &pavgroup->aliaslist, 4714 4826 alias_list) { 4715 - rc = dasd_eckd_cuir_change_state(dev, lpum); 4716 - if (rc) 4717 - goto out; 4827 + spin_lock_irqsave(get_ccwdev_lock(dev->cdev), flags); 4828 + tbcpm = dasd_eckd_cuir_remove_path(dev, lpum, cuir); 4829 + spin_unlock_irqrestore( 4830 + get_ccwdev_lock(dev->cdev), flags); 4831 + if (tbcpm < 0) 4832 + goto out_err; 4833 + paths |= tbcpm; 4718 4834 } 4719 4835 } 4720 - 4721 - pr_warn("Service on the storage server caused path %x.%02x to go offline", 4722 - sch_id.cssid, desc ? desc->chpid : 0); 4723 - rc = PSF_CUIR_COMPLETED; 4724 - out: 4725 - return rc; 4836 + /* notify user about all paths affected by CUIR action */ 4837 + dasd_eckd_cuir_notify_user(device, paths, sch_id, CUIR_QUIESCE); 4838 + return 0; 4839 + out_err: 4840 + return tbcpm; 4726 4841 } 4727 4842 4728 4843 static int dasd_eckd_cuir_resume(struct dasd_device *device, __u8 lpum, 4729 - struct channel_path_desc *desc, 4730 - struct subchannel_id sch_id) 4844 + struct subchannel_id sch_id, 4845 + struct dasd_cuir_message *cuir) 4731 4846 { 4732 4847 struct alias_pav_group *pavgroup, *tempgroup; 4733 4848 struct dasd_eckd_private *private; 4734 4849 struct dasd_device *dev, *n; 4850 + unsigned long paths = 0; 4851 + int tbcpm; 4735 4852 4736 - pr_info("Path %x.%02x is back online after service on the storage server", 4737 - sch_id.cssid, desc ? desc->chpid : 0); 4738 4853 private = (struct dasd_eckd_private *) device->private; 4739 - 4740 4854 /* 4741 4855 * the path may have been added through a generic path event before 4742 4856 * only trigger path verification if the path is not already in use 4743 4857 */ 4744 - 4745 4858 list_for_each_entry_safe(dev, n, 4746 4859 &private->lcu->active_devices, 4747 4860 alias_list) { 4748 - if (!(dev->path_data.opm & lpum)) { 4749 - dev->path_data.tbvpm |= lpum; 4861 + tbcpm = dasd_eckd_cuir_scope(dev, lpum, cuir); 4862 + paths |= tbcpm; 4863 + if (!(dev->path_data.opm & tbcpm)) { 4864 + dev->path_data.tbvpm |= tbcpm; 4750 4865 dasd_schedule_device_bh(dev); 4751 4866 } 4752 4867 } 4753 - 4754 4868 list_for_each_entry_safe(dev, n, 4755 4869 &private->lcu->inactive_devices, 4756 4870 alias_list) { 4757 - if (!(dev->path_data.opm & lpum)) { 4758 - dev->path_data.tbvpm |= lpum; 4871 + tbcpm = dasd_eckd_cuir_scope(dev, lpum, cuir); 4872 + paths |= tbcpm; 4873 + if (!(dev->path_data.opm & tbcpm)) { 4874 + dev->path_data.tbvpm |= tbcpm; 4759 4875 dasd_schedule_device_bh(dev); 4760 4876 } 4761 4877 } 4762 - 4763 4878 /* devices in PAV groups */ 4764 4879 list_for_each_entry_safe(pavgroup, tempgroup, 4765 4880 &private->lcu->grouplist, ··· 4901 4748 list_for_each_entry_safe(dev, n, 4902 4749 &pavgroup->baselist, 4903 4750 alias_list) { 4904 - if (!(dev->path_data.opm & lpum)) { 4905 - dev->path_data.tbvpm |= lpum; 4751 + tbcpm = dasd_eckd_cuir_scope(dev, lpum, cuir); 4752 + paths |= tbcpm; 4753 + if (!(dev->path_data.opm & tbcpm)) { 4754 + dev->path_data.tbvpm |= tbcpm; 4906 4755 dasd_schedule_device_bh(dev); 4907 4756 } 4908 4757 } 4909 4758 list_for_each_entry_safe(dev, n, 4910 4759 &pavgroup->aliaslist, 4911 4760 alias_list) { 4912 - if (!(dev->path_data.opm & lpum)) { 4913 - dev->path_data.tbvpm |= lpum; 4761 + tbcpm = dasd_eckd_cuir_scope(dev, lpum, cuir); 4762 + paths |= tbcpm; 4763 + if (!(dev->path_data.opm & tbcpm)) { 4764 + dev->path_data.tbvpm |= tbcpm; 4914 4765 dasd_schedule_device_bh(dev); 4915 4766 } 4916 4767 } 4917 4768 } 4918 - return PSF_CUIR_COMPLETED; 4769 + /* notify user about all paths affected by CUIR action */ 4770 + dasd_eckd_cuir_notify_user(device, paths, sch_id, CUIR_RESUME); 4771 + return 0; 4919 4772 } 4920 4773 4921 4774 static void dasd_eckd_handle_cuir(struct dasd_device *device, void *messages, ··· 4931 4772 struct channel_path_desc *desc; 4932 4773 struct subchannel_id sch_id; 4933 4774 int pos, response; 4934 - ccw_device_get_schid(device->cdev, &sch_id); 4935 4775 4776 + DBF_DEV_EVENT(DBF_WARNING, device, 4777 + "CUIR request: %016llx %016llx %016llx %08x", 4778 + ((u64 *)cuir)[0], ((u64 *)cuir)[1], ((u64 *)cuir)[2], 4779 + ((u32 *)cuir)[3]); 4780 + ccw_device_get_schid(device->cdev, &sch_id); 4936 4781 /* get position of path in mask */ 4937 4782 pos = 8 - ffs(lpum); 4938 4783 /* get channel path descriptor from this position */ ··· 4944 4781 4945 4782 if (cuir->code == CUIR_QUIESCE) { 4946 4783 /* quiesce */ 4947 - response = dasd_eckd_cuir_quiesce(device, lpum, desc, sch_id); 4784 + if (dasd_eckd_cuir_quiesce(device, lpum, sch_id, cuir)) 4785 + response = PSF_CUIR_LAST_PATH; 4786 + else 4787 + response = PSF_CUIR_COMPLETED; 4948 4788 } else if (cuir->code == CUIR_RESUME) { 4949 4789 /* resume */ 4950 - response = dasd_eckd_cuir_resume(device, lpum, desc, sch_id); 4790 + dasd_eckd_cuir_resume(device, lpum, sch_id, cuir); 4791 + response = PSF_CUIR_COMPLETED; 4951 4792 } else 4952 4793 response = PSF_CUIR_NOT_SUPPORTED; 4953 4794 4954 - dasd_eckd_psf_cuir_response(device, response, cuir->message_id, 4955 - desc, sch_id); 4956 - 4795 + dasd_eckd_psf_cuir_response(device, response, 4796 + cuir->message_id, desc, sch_id); 4797 + DBF_DEV_EVENT(DBF_WARNING, device, 4798 + "CUIR response: %d on message ID %08x", response, 4799 + cuir->message_id); 4957 4800 /* free descriptor copy */ 4958 4801 kfree(desc); 4802 + /* to make sure there is no attention left schedule work again */ 4803 + device->discipline->check_attention(device, lpum); 4959 4804 } 4960 4805 4961 4806 static void dasd_eckd_check_attention_work(struct work_struct *work) ··· 4975 4804 4976 4805 data = container_of(work, struct check_attention_work_data, worker); 4977 4806 device = data->device; 4978 - 4979 4807 messages = kzalloc(sizeof(*messages), GFP_KERNEL); 4980 4808 if (!messages) { 4981 4809 DBF_DEV_EVENT(DBF_WARNING, device, "%s", 4982 4810 "Could not allocate attention message buffer"); 4983 4811 goto out; 4984 4812 } 4985 - 4986 4813 rc = dasd_eckd_read_message_buffer(device, messages, data->lpum); 4987 4814 if (rc) 4988 4815 goto out; 4989 - 4990 4816 if (messages->length == ATTENTION_LENGTH_CUIR && 4991 4817 messages->format == ATTENTION_FORMAT_CUIR) 4992 4818 dasd_eckd_handle_cuir(device, messages, data->lpum); 4993 - 4994 4819 out: 4995 4820 dasd_put_device(device); 4996 4821 kfree(messages);
+10 -1
drivers/s390/block/dasd_eckd.h
··· 355 355 __u8 identifier:2; 356 356 __u8 reserved:6; 357 357 } __attribute__ ((packed)) flags; 358 - __u8 reserved[5]; 358 + __u8 record_selector; 359 + __u8 reserved[4]; 359 360 struct { 360 361 __u8 value:2; 361 362 __u8 number:6; ··· 493 492 struct dasd_device *next; 494 493 }; 495 494 495 + struct dasd_conf_data { 496 + struct dasd_ned neds[5]; 497 + u8 reserved[64]; 498 + struct dasd_gneq gneq; 499 + } __packed; 500 + 496 501 struct dasd_eckd_private { 497 502 struct dasd_eckd_characteristics rdc_data; 498 503 u8 *conf_data; 499 504 int conf_len; 505 + /* per path configuration data */ 506 + struct dasd_conf_data *path_conf_data[8]; 500 507 /* pointers to specific parts in the conf_data */ 501 508 struct dasd_ned *ned; 502 509 struct dasd_sneq *sneq;