Skip to content

Commit

Permalink
[S390] dasd: Add support for raw ECKD access.
Browse files Browse the repository at this point in the history
Normal I/O operations through the DASD device driver give only access
to the data fields of an ECKD device even for track based I/O.
This patch extends the DASD device driver to give access to whole
ECKD tracks including count, key and data fields.

Signed-off-by: Stefan Haberland <stefan.haberland@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
  • Loading branch information
Stefan Haberland authored and Martin Schwidefsky committed Jan 5, 2011
1 parent 6f272b9 commit e4dbb0f
Show file tree
Hide file tree
Showing 5 changed files with 268 additions and 8 deletions.
2 changes: 2 additions & 0 deletions arch/s390/include/asm/dasd.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ typedef struct dasd_information2_t {
* 0x02: use diag discipline (diag)
* 0x04: set the device initially online (internal use only)
* 0x08: enable ERP related logging
* 0x20: give access to raw eckd data
*/
#define DASD_FEATURE_DEFAULT 0x00
#define DASD_FEATURE_READONLY 0x01
Expand All @@ -81,6 +82,7 @@ typedef struct dasd_information2_t {
#define DASD_FEATURE_ERPLOG 0x08
#define DASD_FEATURE_FAILFAST 0x10
#define DASD_FEATURE_FAILONSLCK 0x20
#define DASD_FEATURE_USERAW 0x40

#define DASD_PARTN_BITS 2

Expand Down
23 changes: 20 additions & 3 deletions drivers/s390/block/dasd.c
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,11 @@ dasd_state_ready_to_online(struct dasd_device * device)
device->state = DASD_STATE_ONLINE;
if (device->block) {
dasd_schedule_block_bh(device->block);
if ((device->features & DASD_FEATURE_USERAW)) {
disk = device->block->gdp;
kobject_uevent(&disk_to_dev(disk)->kobj, KOBJ_CHANGE);
return 0;
}
disk = device->block->bdev->bd_disk;
disk_part_iter_init(&piter, disk, DISK_PITER_INCL_PART0);
while ((part = disk_part_iter_next(&piter)))
Expand All @@ -394,7 +399,7 @@ static int dasd_state_online_to_ready(struct dasd_device *device)
return rc;
}
device->state = DASD_STATE_READY;
if (device->block) {
if (device->block && !(device->features & DASD_FEATURE_USERAW)) {
disk = device->block->bdev->bd_disk;
disk_part_iter_init(&piter, disk, DISK_PITER_INCL_PART0);
while ((part = disk_part_iter_next(&piter)))
Expand Down Expand Up @@ -2258,8 +2263,20 @@ static void dasd_setup_queue(struct dasd_block *block)
{
int max;

blk_queue_logical_block_size(block->request_queue, block->bp_block);
max = block->base->discipline->max_blocks << block->s2b_shift;
if (block->base->features & DASD_FEATURE_USERAW) {
/*
* the max_blocks value for raw_track access is 256
* it is higher than the native ECKD value because we
* only need one ccw per track
* so the max_hw_sectors are
* 2048 x 512B = 1024kB = 16 tracks
*/
max = 2048;
} else {
max = block->base->discipline->max_blocks << block->s2b_shift;
}
blk_queue_logical_block_size(block->request_queue,
block->bp_block);
blk_queue_max_hw_sectors(block->request_queue, max);
blk_queue_max_segments(block->request_queue, -1L);
/* with page sized segments we can translate each segement into
Expand Down
55 changes: 54 additions & 1 deletion drivers/s390/block/dasd_devmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,8 @@ dasd_feature_list(char *str, char **endp)
features |= DASD_FEATURE_READONLY;
else if (len == 4 && !strncmp(str, "diag", 4))
features |= DASD_FEATURE_USEDIAG;
else if (len == 3 && !strncmp(str, "raw", 3))
features |= DASD_FEATURE_USERAW;
else if (len == 6 && !strncmp(str, "erplog", 6))
features |= DASD_FEATURE_ERPLOG;
else if (len == 8 && !strncmp(str, "failfast", 8))
Expand Down Expand Up @@ -857,7 +859,7 @@ dasd_use_diag_store(struct device *dev, struct device_attribute *attr,
spin_lock(&dasd_devmap_lock);
/* Changing diag discipline flag is only allowed in offline state. */
rc = count;
if (!devmap->device) {
if (!devmap->device && !(devmap->features & DASD_FEATURE_USERAW)) {
if (val)
devmap->features |= DASD_FEATURE_USEDIAG;
else
Expand All @@ -870,6 +872,56 @@ dasd_use_diag_store(struct device *dev, struct device_attribute *attr,

static DEVICE_ATTR(use_diag, 0644, dasd_use_diag_show, dasd_use_diag_store);

/*
* use_raw controls whether the driver should give access to raw eckd data or
* operate in standard mode
*/
static ssize_t
dasd_use_raw_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct dasd_devmap *devmap;
int use_raw;

devmap = dasd_find_busid(dev_name(dev));
if (!IS_ERR(devmap))
use_raw = (devmap->features & DASD_FEATURE_USERAW) != 0;
else
use_raw = (DASD_FEATURE_DEFAULT & DASD_FEATURE_USERAW) != 0;
return sprintf(buf, use_raw ? "1\n" : "0\n");
}

static ssize_t
dasd_use_raw_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct dasd_devmap *devmap;
ssize_t rc;
unsigned long val;

devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
if (IS_ERR(devmap))
return PTR_ERR(devmap);

if ((strict_strtoul(buf, 10, &val) != 0) || val > 1)
return -EINVAL;

spin_lock(&dasd_devmap_lock);
/* Changing diag discipline flag is only allowed in offline state. */
rc = count;
if (!devmap->device && !(devmap->features & DASD_FEATURE_USEDIAG)) {
if (val)
devmap->features |= DASD_FEATURE_USERAW;
else
devmap->features &= ~DASD_FEATURE_USERAW;
} else
rc = -EPERM;
spin_unlock(&dasd_devmap_lock);
return rc;
}

static DEVICE_ATTR(raw_track_access, 0644, dasd_use_raw_show,
dasd_use_raw_store);

static ssize_t
dasd_discipline_show(struct device *dev, struct device_attribute *attr,
char *buf)
Expand Down Expand Up @@ -1232,6 +1284,7 @@ static struct attribute * dasd_attrs[] = {
&dev_attr_vendor.attr,
&dev_attr_uid.attr,
&dev_attr_use_diag.attr,
&dev_attr_raw_track_access.attr,
&dev_attr_eer_enabled.attr,
&dev_attr_erplog.attr,
&dev_attr_failfast.attr,
Expand Down
Loading

0 comments on commit e4dbb0f

Please sign in to comment.