[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#550898: DASD DIAG driver doesn't work for read-only minidisks (s390, s390x only)



I have come up with a patch that seems to solve my problem.

The mdsk_init_io internal subroutine of drivers/s390/block/dasd_diag.c
currently looks like this:

----------

/* Initialize block I/O to DIAG device using the specified blocksize and
 * block offset. On success, return zero and set end_block to contain the
 * number of blocks on the device minus the specified offset. Return non-zero
 * otherwise. */
static inline int
mdsk_init_io(struct dasd_device *device, unsigned int blocksize,
             blocknum_t offset, blocknum_t *end_block)
{
        struct dasd_diag_private *private;
        struct dasd_diag_init_io *iib;
        int rc;

        private = (struct dasd_diag_private *) device->private;
        iib = &private->iib;
        memset(iib, 0, sizeof (struct dasd_diag_init_io));

        iib->dev_nr = private->dev_id.devno;
        iib->block_size = blocksize;
        iib->offset = offset;
        iib->flaga = DASD_DIAG_FLAGA_DEFAULT;

        rc = dia250(iib, INIT_BIO);

        if ((rc & 3) == 0 && end_block)
                *end_block = iib->end_block;

        return rc;
}

----------

After the "rc = dia250(iib, INIT_BIO);" statement I add a
statement that sets rc to zero if it is 4.  The resulting code
looks like this:

----------

/* Initialize block I/O to DIAG device using the specified blocksize and
 * block offset. On success, return zero and set end_block to contain the
 * number of blocks on the device minus the specified offset. Return non-zero
 * otherwise. */
static inline int
mdsk_init_io(struct dasd_device *device, unsigned int blocksize,
             blocknum_t offset, blocknum_t *end_block)
{
        struct dasd_diag_private *private;
        struct dasd_diag_init_io *iib;
        int rc;

        private = (struct dasd_diag_private *) device->private;
        iib = &private->iib;
        memset(iib, 0, sizeof (struct dasd_diag_init_io));

        iib->dev_nr = private->dev_id.devno;
        iib->block_size = blocksize;
        iib->offset = offset;
        iib->flaga = DASD_DIAG_FLAGA_DEFAULT;

        rc = dia250(iib, INIT_BIO);

        /* Fix for read-only minidisk */
        if (rc == 4) rc = 0;
        /* End fix for read-only minidisk */

        if ((rc & 3) == 0 && end_block)
                *end_block = iib->end_block;

        return rc;
}

----------

This fix solves the problem.  I can now get read-only minidisks to come online.

However ...

This fix also creates (or more likely exposes) another problem.  When this fix
is on, devices which are manually taken offline immediately come online again!
I had this problem once before in an earlier kernel, but the problem eventually
went away with maintenance.  But with this fix on, the original problem of
getting disks offline is back.  The only way I can get around it is to
immediately detach the disk with CP.  For example:

# echo 0 > /sys/bus/ccw/devices/0.0.0404/online;vmcp DETACH VIRTUAL 0404

If the device isn't there, it can't be brought online!  But I shouldn't have
to resort to something like this.  Someone really needs to take a closer
look at this.


Reply to: