diff options
author | Stefan Haberland <stefan.haberland@de.ibm.com> | 2016-03-18 04:42:13 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2016-04-15 12:16:37 -0400 |
commit | 5a3b7b112884f80ff19b18028fabeb4f9c035518 (patch) | |
tree | b1b743c481c829d26fdb97043f446f9f0d682b4f /drivers/s390 | |
parent | 2fd92273646abad21766ddfbfa00b6f927362308 (diff) |
s390/dasd: add query host access to volume support
With this feature, applications can query if a DASD volume is online
to another operating system instances by checking the online status of
all attached hosts from the storage server.
Reviewed-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
Reviewed-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Stefan Haberland <stefan.haberland@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/block/dasd.c | 56 | ||||
-rw-r--r-- | drivers/s390/block/dasd_devmap.c | 27 | ||||
-rw-r--r-- | drivers/s390/block/dasd_eckd.c | 164 | ||||
-rw-r--r-- | drivers/s390/block/dasd_eckd.h | 33 | ||||
-rw-r--r-- | drivers/s390/block/dasd_int.h | 3 |
5 files changed, 282 insertions, 1 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index c78db05e75b1..4adb6d14d562 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
@@ -75,6 +75,8 @@ static void dasd_block_timeout(unsigned long); | |||
75 | static void __dasd_process_erp(struct dasd_device *, struct dasd_ccw_req *); | 75 | static void __dasd_process_erp(struct dasd_device *, struct dasd_ccw_req *); |
76 | static void dasd_profile_init(struct dasd_profile *, struct dentry *); | 76 | static void dasd_profile_init(struct dasd_profile *, struct dentry *); |
77 | static void dasd_profile_exit(struct dasd_profile *); | 77 | static void dasd_profile_exit(struct dasd_profile *); |
78 | static void dasd_hosts_init(struct dentry *, struct dasd_device *); | ||
79 | static void dasd_hosts_exit(struct dasd_device *); | ||
78 | 80 | ||
79 | /* | 81 | /* |
80 | * SECTION: Operations on the device structure. | 82 | * SECTION: Operations on the device structure. |
@@ -267,6 +269,7 @@ static int dasd_state_known_to_basic(struct dasd_device *device) | |||
267 | dasd_debugfs_setup(dev_name(&device->cdev->dev), | 269 | dasd_debugfs_setup(dev_name(&device->cdev->dev), |
268 | dasd_debugfs_root_entry); | 270 | dasd_debugfs_root_entry); |
269 | dasd_profile_init(&device->profile, device->debugfs_dentry); | 271 | dasd_profile_init(&device->profile, device->debugfs_dentry); |
272 | dasd_hosts_init(device->debugfs_dentry, device); | ||
270 | 273 | ||
271 | /* register 'device' debug area, used for all DBF_DEV_XXX calls */ | 274 | /* register 'device' debug area, used for all DBF_DEV_XXX calls */ |
272 | device->debug_area = debug_register(dev_name(&device->cdev->dev), 4, 1, | 275 | device->debug_area = debug_register(dev_name(&device->cdev->dev), 4, 1, |
@@ -304,6 +307,7 @@ static int dasd_state_basic_to_known(struct dasd_device *device) | |||
304 | return rc; | 307 | return rc; |
305 | dasd_device_clear_timer(device); | 308 | dasd_device_clear_timer(device); |
306 | dasd_profile_exit(&device->profile); | 309 | dasd_profile_exit(&device->profile); |
310 | dasd_hosts_exit(device); | ||
307 | debugfs_remove(device->debugfs_dentry); | 311 | debugfs_remove(device->debugfs_dentry); |
308 | DBF_DEV_EVENT(DBF_EMERG, device, "%p debug area deleted", device); | 312 | DBF_DEV_EVENT(DBF_EMERG, device, "%p debug area deleted", device); |
309 | if (device->debug_area != NULL) { | 313 | if (device->debug_area != NULL) { |
@@ -1150,6 +1154,58 @@ int dasd_profile_on(struct dasd_profile *profile) | |||
1150 | 1154 | ||
1151 | #endif /* CONFIG_DASD_PROFILE */ | 1155 | #endif /* CONFIG_DASD_PROFILE */ |
1152 | 1156 | ||
1157 | static int dasd_hosts_show(struct seq_file *m, void *v) | ||
1158 | { | ||
1159 | struct dasd_device *device; | ||
1160 | int rc = -EOPNOTSUPP; | ||
1161 | |||
1162 | device = m->private; | ||
1163 | dasd_get_device(device); | ||
1164 | |||
1165 | if (device->discipline->hosts_print) | ||
1166 | rc = device->discipline->hosts_print(device, m); | ||
1167 | |||
1168 | dasd_put_device(device); | ||
1169 | return rc; | ||
1170 | } | ||
1171 | |||
1172 | static int dasd_hosts_open(struct inode *inode, struct file *file) | ||
1173 | { | ||
1174 | struct dasd_device *device = inode->i_private; | ||
1175 | |||
1176 | return single_open(file, dasd_hosts_show, device); | ||
1177 | } | ||
1178 | |||
1179 | static const struct file_operations dasd_hosts_fops = { | ||
1180 | .owner = THIS_MODULE, | ||
1181 | .open = dasd_hosts_open, | ||
1182 | .read = seq_read, | ||
1183 | .llseek = seq_lseek, | ||
1184 | .release = single_release, | ||
1185 | }; | ||
1186 | |||
1187 | static void dasd_hosts_exit(struct dasd_device *device) | ||
1188 | { | ||
1189 | debugfs_remove(device->hosts_dentry); | ||
1190 | device->hosts_dentry = NULL; | ||
1191 | } | ||
1192 | |||
1193 | static void dasd_hosts_init(struct dentry *base_dentry, | ||
1194 | struct dasd_device *device) | ||
1195 | { | ||
1196 | struct dentry *pde; | ||
1197 | umode_t mode; | ||
1198 | |||
1199 | if (!base_dentry) | ||
1200 | return; | ||
1201 | |||
1202 | mode = S_IRUSR | S_IFREG; | ||
1203 | pde = debugfs_create_file("host_access_list", mode, base_dentry, | ||
1204 | device, &dasd_hosts_fops); | ||
1205 | if (pde && !IS_ERR(pde)) | ||
1206 | device->hosts_dentry = pde; | ||
1207 | } | ||
1208 | |||
1153 | /* | 1209 | /* |
1154 | * Allocate memory for a channel program with 'cplength' channel | 1210 | * Allocate memory for a channel program with 'cplength' channel |
1155 | * command words and 'datasize' additional space. There are two | 1211 | * command words and 'datasize' additional space. There are two |
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index 2f18f61092b5..3cdbce45e464 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c | |||
@@ -982,6 +982,32 @@ out: | |||
982 | static DEVICE_ATTR(safe_offline, 0200, NULL, dasd_safe_offline_store); | 982 | static DEVICE_ATTR(safe_offline, 0200, NULL, dasd_safe_offline_store); |
983 | 983 | ||
984 | static ssize_t | 984 | static ssize_t |
985 | dasd_access_show(struct device *dev, struct device_attribute *attr, | ||
986 | char *buf) | ||
987 | { | ||
988 | struct ccw_device *cdev = to_ccwdev(dev); | ||
989 | struct dasd_device *device; | ||
990 | int count; | ||
991 | |||
992 | device = dasd_device_from_cdev(cdev); | ||
993 | if (IS_ERR(device)) | ||
994 | return PTR_ERR(device); | ||
995 | |||
996 | if (device->discipline->host_access_count) | ||
997 | count = device->discipline->host_access_count(device); | ||
998 | else | ||
999 | count = -EOPNOTSUPP; | ||
1000 | |||
1001 | dasd_put_device(device); | ||
1002 | if (count < 0) | ||
1003 | return count; | ||
1004 | |||
1005 | return sprintf(buf, "%d\n", count); | ||
1006 | } | ||
1007 | |||
1008 | static DEVICE_ATTR(host_access_count, 0444, dasd_access_show, NULL); | ||
1009 | |||
1010 | static ssize_t | ||
985 | dasd_discipline_show(struct device *dev, struct device_attribute *attr, | 1011 | dasd_discipline_show(struct device *dev, struct device_attribute *attr, |
986 | char *buf) | 1012 | char *buf) |
987 | { | 1013 | { |
@@ -1471,6 +1497,7 @@ static struct attribute * dasd_attrs[] = { | |||
1471 | &dev_attr_reservation_policy.attr, | 1497 | &dev_attr_reservation_policy.attr, |
1472 | &dev_attr_last_known_reservation_state.attr, | 1498 | &dev_attr_last_known_reservation_state.attr, |
1473 | &dev_attr_safe_offline.attr, | 1499 | &dev_attr_safe_offline.attr, |
1500 | &dev_attr_host_access_count.attr, | ||
1474 | &dev_attr_path_masks.attr, | 1501 | &dev_attr_path_masks.attr, |
1475 | NULL, | 1502 | NULL, |
1476 | }; | 1503 | }; |
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index c1b4ae55e129..3b70d378d1c1 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/compat.h> | 20 | #include <linux/compat.h> |
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | #include <linux/seq_file.h> | ||
22 | 23 | ||
23 | #include <asm/css_chars.h> | 24 | #include <asm/css_chars.h> |
24 | #include <asm/debug.h> | 25 | #include <asm/debug.h> |
@@ -4627,6 +4628,167 @@ static int dasd_eckd_read_message_buffer(struct dasd_device *device, | |||
4627 | return rc; | 4628 | return rc; |
4628 | } | 4629 | } |
4629 | 4630 | ||
4631 | static int dasd_eckd_query_host_access(struct dasd_device *device, | ||
4632 | struct dasd_psf_query_host_access *data) | ||
4633 | { | ||
4634 | struct dasd_eckd_private *private = device->private; | ||
4635 | struct dasd_psf_query_host_access *host_access; | ||
4636 | struct dasd_psf_prssd_data *prssdp; | ||
4637 | struct dasd_ccw_req *cqr; | ||
4638 | struct ccw1 *ccw; | ||
4639 | int rc; | ||
4640 | |||
4641 | /* not available for HYPER PAV alias devices */ | ||
4642 | if (!device->block && private->lcu->pav == HYPER_PAV) | ||
4643 | return -EOPNOTSUPP; | ||
4644 | |||
4645 | cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1 /* PSF */ + 1 /* RSSD */, | ||
4646 | sizeof(struct dasd_psf_prssd_data) + 1, | ||
4647 | device); | ||
4648 | if (IS_ERR(cqr)) { | ||
4649 | DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s", | ||
4650 | "Could not allocate read message buffer request"); | ||
4651 | return PTR_ERR(cqr); | ||
4652 | } | ||
4653 | host_access = kzalloc(sizeof(*host_access), GFP_KERNEL | GFP_DMA); | ||
4654 | if (!host_access) { | ||
4655 | dasd_sfree_request(cqr, device); | ||
4656 | DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s", | ||
4657 | "Could not allocate host_access buffer"); | ||
4658 | return -ENOMEM; | ||
4659 | } | ||
4660 | cqr->startdev = device; | ||
4661 | cqr->memdev = device; | ||
4662 | cqr->block = NULL; | ||
4663 | cqr->retries = 256; | ||
4664 | cqr->expires = 10 * HZ; | ||
4665 | |||
4666 | /* Prepare for Read Subsystem Data */ | ||
4667 | prssdp = (struct dasd_psf_prssd_data *) cqr->data; | ||
4668 | memset(prssdp, 0, sizeof(struct dasd_psf_prssd_data)); | ||
4669 | prssdp->order = PSF_ORDER_PRSSD; | ||
4670 | prssdp->suborder = PSF_SUBORDER_QHA; /* query host access */ | ||
4671 | /* LSS and Volume that will be queried */ | ||
4672 | prssdp->lss = private->ned->ID; | ||
4673 | prssdp->volume = private->ned->unit_addr; | ||
4674 | /* all other bytes of prssdp must be zero */ | ||
4675 | |||
4676 | ccw = cqr->cpaddr; | ||
4677 | ccw->cmd_code = DASD_ECKD_CCW_PSF; | ||
4678 | ccw->count = sizeof(struct dasd_psf_prssd_data); | ||
4679 | ccw->flags |= CCW_FLAG_CC; | ||
4680 | ccw->flags |= CCW_FLAG_SLI; | ||
4681 | ccw->cda = (__u32)(addr_t) prssdp; | ||
4682 | |||
4683 | /* Read Subsystem Data - query host access */ | ||
4684 | ccw++; | ||
4685 | ccw->cmd_code = DASD_ECKD_CCW_RSSD; | ||
4686 | ccw->count = sizeof(struct dasd_psf_query_host_access); | ||
4687 | ccw->flags |= CCW_FLAG_SLI; | ||
4688 | ccw->cda = (__u32)(addr_t) host_access; | ||
4689 | |||
4690 | cqr->buildclk = get_tod_clock(); | ||
4691 | cqr->status = DASD_CQR_FILLED; | ||
4692 | rc = dasd_sleep_on(cqr); | ||
4693 | if (rc == 0) { | ||
4694 | *data = *host_access; | ||
4695 | } else { | ||
4696 | DBF_EVENT_DEVID(DBF_WARNING, device->cdev, | ||
4697 | "Reading host access data failed with rc=%d\n", | ||
4698 | rc); | ||
4699 | rc = -EOPNOTSUPP; | ||
4700 | } | ||
4701 | |||
4702 | dasd_sfree_request(cqr, cqr->memdev); | ||
4703 | kfree(host_access); | ||
4704 | return rc; | ||
4705 | } | ||
4706 | /* | ||
4707 | * return number of grouped devices | ||
4708 | */ | ||
4709 | static int dasd_eckd_host_access_count(struct dasd_device *device) | ||
4710 | { | ||
4711 | struct dasd_psf_query_host_access *access; | ||
4712 | struct dasd_ckd_path_group_entry *entry; | ||
4713 | struct dasd_ckd_host_information *info; | ||
4714 | int count = 0; | ||
4715 | int rc, i; | ||
4716 | |||
4717 | access = kzalloc(sizeof(*access), GFP_NOIO); | ||
4718 | if (!access) { | ||
4719 | DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s", | ||
4720 | "Could not allocate access buffer"); | ||
4721 | return -ENOMEM; | ||
4722 | } | ||
4723 | rc = dasd_eckd_query_host_access(device, access); | ||
4724 | if (rc) { | ||
4725 | kfree(access); | ||
4726 | return rc; | ||
4727 | } | ||
4728 | |||
4729 | info = (struct dasd_ckd_host_information *) | ||
4730 | access->host_access_information; | ||
4731 | for (i = 0; i < info->entry_count; i++) { | ||
4732 | entry = (struct dasd_ckd_path_group_entry *) | ||
4733 | (info->entry + i * info->entry_size); | ||
4734 | if (entry->status_flags & DASD_ECKD_PG_GROUPED) | ||
4735 | count++; | ||
4736 | } | ||
4737 | |||
4738 | kfree(access); | ||
4739 | return count; | ||
4740 | } | ||
4741 | |||
4742 | /* | ||
4743 | * write host access information to a sequential file | ||
4744 | */ | ||
4745 | static int dasd_hosts_print(struct dasd_device *device, struct seq_file *m) | ||
4746 | { | ||
4747 | struct dasd_psf_query_host_access *access; | ||
4748 | struct dasd_ckd_path_group_entry *entry; | ||
4749 | struct dasd_ckd_host_information *info; | ||
4750 | char sysplex[9] = ""; | ||
4751 | int rc, i, j; | ||
4752 | |||
4753 | access = kzalloc(sizeof(*access), GFP_NOIO); | ||
4754 | if (!access) { | ||
4755 | DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s", | ||
4756 | "Could not allocate access buffer"); | ||
4757 | return -ENOMEM; | ||
4758 | } | ||
4759 | rc = dasd_eckd_query_host_access(device, access); | ||
4760 | if (rc) { | ||
4761 | kfree(access); | ||
4762 | return rc; | ||
4763 | } | ||
4764 | |||
4765 | info = (struct dasd_ckd_host_information *) | ||
4766 | access->host_access_information; | ||
4767 | for (i = 0; i < info->entry_count; i++) { | ||
4768 | entry = (struct dasd_ckd_path_group_entry *) | ||
4769 | (info->entry + i * info->entry_size); | ||
4770 | /* PGID */ | ||
4771 | seq_puts(m, "pgid "); | ||
4772 | for (j = 0; j < 11; j++) | ||
4773 | seq_printf(m, "%02x", entry->pgid[j]); | ||
4774 | seq_putc(m, '\n'); | ||
4775 | /* FLAGS */ | ||
4776 | seq_printf(m, "status_flags %02x\n", entry->status_flags); | ||
4777 | /* SYSPLEX NAME */ | ||
4778 | memcpy(&sysplex, &entry->sysplex_name, sizeof(sysplex) - 1); | ||
4779 | EBCASC(sysplex, sizeof(sysplex)); | ||
4780 | seq_printf(m, "sysplex_name %8s\n", sysplex); | ||
4781 | /* SUPPORTED CYLINDER */ | ||
4782 | seq_printf(m, "supported_cylinder %d\n", entry->cylinder); | ||
4783 | /* TIMESTAMP */ | ||
4784 | seq_printf(m, "timestamp %lu\n", (unsigned long) | ||
4785 | entry->timestamp); | ||
4786 | } | ||
4787 | kfree(access); | ||
4788 | |||
4789 | return 0; | ||
4790 | } | ||
4791 | |||
4630 | /* | 4792 | /* |
4631 | * Perform Subsystem Function - CUIR response | 4793 | * Perform Subsystem Function - CUIR response |
4632 | */ | 4794 | */ |
@@ -5099,6 +5261,8 @@ static struct dasd_discipline dasd_eckd_discipline = { | |||
5099 | .get_uid = dasd_eckd_get_uid, | 5261 | .get_uid = dasd_eckd_get_uid, |
5100 | .kick_validate = dasd_eckd_kick_validate_server, | 5262 | .kick_validate = dasd_eckd_kick_validate_server, |
5101 | .check_attention = dasd_eckd_check_attention, | 5263 | .check_attention = dasd_eckd_check_attention, |
5264 | .host_access_count = dasd_eckd_host_access_count, | ||
5265 | .hosts_print = dasd_hosts_print, | ||
5102 | }; | 5266 | }; |
5103 | 5267 | ||
5104 | static int __init | 5268 | static int __init |
diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h index 6d9a6d3517cd..862ee4291abd 100644 --- a/drivers/s390/block/dasd_eckd.h +++ b/drivers/s390/block/dasd_eckd.h | |||
@@ -53,6 +53,7 @@ | |||
53 | */ | 53 | */ |
54 | #define PSF_ORDER_PRSSD 0x18 | 54 | #define PSF_ORDER_PRSSD 0x18 |
55 | #define PSF_ORDER_CUIR_RESPONSE 0x1A | 55 | #define PSF_ORDER_CUIR_RESPONSE 0x1A |
56 | #define PSF_SUBORDER_QHA 0x1C | ||
56 | #define PSF_ORDER_SSC 0x1D | 57 | #define PSF_ORDER_SSC 0x1D |
57 | 58 | ||
58 | /* | 59 | /* |
@@ -81,6 +82,8 @@ | |||
81 | #define ATTENTION_LENGTH_CUIR 0x0e | 82 | #define ATTENTION_LENGTH_CUIR 0x0e |
82 | #define ATTENTION_FORMAT_CUIR 0x01 | 83 | #define ATTENTION_FORMAT_CUIR 0x01 |
83 | 84 | ||
85 | #define DASD_ECKD_PG_GROUPED 0x10 | ||
86 | |||
84 | /* | 87 | /* |
85 | * Size that is reportet for large volumes in the old 16-bit no_cyl field | 88 | * Size that is reportet for large volumes in the old 16-bit no_cyl field |
86 | */ | 89 | */ |
@@ -403,13 +406,41 @@ struct dasd_psf_cuir_response { | |||
403 | __u8 ssid; | 406 | __u8 ssid; |
404 | } __packed; | 407 | } __packed; |
405 | 408 | ||
409 | struct dasd_ckd_path_group_entry { | ||
410 | __u8 status_flags; | ||
411 | __u8 pgid[11]; | ||
412 | __u8 sysplex_name[8]; | ||
413 | __u32 timestamp; | ||
414 | __u32 cylinder; | ||
415 | __u8 reserved[4]; | ||
416 | } __packed; | ||
417 | |||
418 | struct dasd_ckd_host_information { | ||
419 | __u8 access_flags; | ||
420 | __u8 entry_size; | ||
421 | __u16 entry_count; | ||
422 | __u8 entry[16390]; | ||
423 | } __packed; | ||
424 | |||
425 | struct dasd_psf_query_host_access { | ||
426 | __u8 access_flag; | ||
427 | __u8 version; | ||
428 | __u16 CKD_length; | ||
429 | __u16 SCSI_length; | ||
430 | __u8 unused[10]; | ||
431 | __u8 host_access_information[16394]; | ||
432 | } __packed; | ||
433 | |||
406 | /* | 434 | /* |
407 | * Perform Subsystem Function - Prepare for Read Subsystem Data | 435 | * Perform Subsystem Function - Prepare for Read Subsystem Data |
408 | */ | 436 | */ |
409 | struct dasd_psf_prssd_data { | 437 | struct dasd_psf_prssd_data { |
410 | unsigned char order; | 438 | unsigned char order; |
411 | unsigned char flags; | 439 | unsigned char flags; |
412 | unsigned char reserved[4]; | 440 | unsigned char reserved1; |
441 | unsigned char reserved2; | ||
442 | unsigned char lss; | ||
443 | unsigned char volume; | ||
413 | unsigned char suborder; | 444 | unsigned char suborder; |
414 | unsigned char varies[5]; | 445 | unsigned char varies[5]; |
415 | } __attribute__ ((packed)); | 446 | } __attribute__ ((packed)); |
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 0f0add932e7a..6132733bcd95 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h | |||
@@ -365,6 +365,8 @@ struct dasd_discipline { | |||
365 | int (*get_uid) (struct dasd_device *, struct dasd_uid *); | 365 | int (*get_uid) (struct dasd_device *, struct dasd_uid *); |
366 | void (*kick_validate) (struct dasd_device *); | 366 | void (*kick_validate) (struct dasd_device *); |
367 | int (*check_attention)(struct dasd_device *, __u8); | 367 | int (*check_attention)(struct dasd_device *, __u8); |
368 | int (*host_access_count)(struct dasd_device *); | ||
369 | int (*hosts_print)(struct dasd_device *, struct seq_file *); | ||
368 | }; | 370 | }; |
369 | 371 | ||
370 | extern struct dasd_discipline *dasd_diag_discipline_pointer; | 372 | extern struct dasd_discipline *dasd_diag_discipline_pointer; |
@@ -487,6 +489,7 @@ struct dasd_device { | |||
487 | unsigned long blk_timeout; | 489 | unsigned long blk_timeout; |
488 | 490 | ||
489 | struct dentry *debugfs_dentry; | 491 | struct dentry *debugfs_dentry; |
492 | struct dentry *hosts_dentry; | ||
490 | struct dasd_profile profile; | 493 | struct dasd_profile profile; |
491 | }; | 494 | }; |
492 | 495 | ||