Exemplo n.º 1
0
/**
 * Set a device info.
 */
static int
zbc_fake_set_info(struct zbc_device *dev)
{
    unsigned long long size64;
    struct stat st;
    int size32;
    int ret;

    /* Get device stats */
    if ( fstat(dev->zbd_fd, &st) < 0 ) {
        ret = -errno;
        zbc_error("%s: stat failed %d (%s)\n",
                  dev->zbd_filename,
                  errno,
                  strerror(errno));
        return ret;
    }

    if ( S_ISBLK(st.st_mode) ) {

        /* Get logical block size */
        ret = ioctl(dev->zbd_fd, BLKSSZGET, &size32);
        if ( ret != 0 ) {
            ret = -errno;
            zbc_error("%s: ioctl BLKSSZGET failed %d (%s)\n",
                      dev->zbd_filename,
                      errno,
                      strerror(errno));
            return ret;
        }

        dev->zbd_info.zbd_logical_block_size = size32;

        /* Get physical block size */
        ret = ioctl(dev->zbd_fd, BLKPBSZGET, &size32);
        if ( ret != 0 ) {
            ret = -errno;
            zbc_error("%s: ioctl BLKPBSZGET failed %d (%s)\n",
                      dev->zbd_filename,
                      errno,
                      strerror(errno));
            return ret;
        }
        dev->zbd_info.zbd_physical_block_size = size32;

        /* Get capacity (B) */
        ret = ioctl(dev->zbd_fd, BLKGETSIZE64, &size64);
        if ( ret != 0 ) {
            ret = -errno;
            zbc_error("%s: ioctl BLKGETSIZE64 failed %d (%s)\n",
                      dev->zbd_filename,
                      errno,
                      strerror(errno));
            return ret;
        }

        if ( dev->zbd_info.zbd_logical_block_size <= 0 ) {
            zbc_error("%s: invalid logical sector size %d\n",
                      dev->zbd_filename,
                      size32);
            return -EINVAL;
        }
        dev->zbd_info.zbd_logical_blocks = size64 / dev->zbd_info.zbd_logical_block_size;

        if ( dev->zbd_info.zbd_physical_block_size <= 0 ) {
            zbc_error("%s: invalid physical sector size %d\n",
                      dev->zbd_filename,
                      size32);
            return -EINVAL;
        }
        dev->zbd_info.zbd_physical_blocks = size64 / dev->zbd_info.zbd_physical_block_size;

    } else if ( S_ISREG(st.st_mode) ) {

        /* Default value for files */
        dev->zbd_info.zbd_logical_block_size = ZBC_FAKE_FILE_SECTOR_SIZE;
        dev->zbd_info.zbd_logical_blocks = st.st_size / ZBC_FAKE_FILE_SECTOR_SIZE;
        dev->zbd_info.zbd_physical_block_size = dev->zbd_info.zbd_logical_block_size;
        dev->zbd_info.zbd_physical_blocks = dev->zbd_info.zbd_logical_blocks;

    } else {

        return -ENXIO;

    }

    /* Check */
    if ( ! dev->zbd_info.zbd_logical_blocks ) {
        zbc_error("%s: invalid capacity (logical blocks)\n",
                  dev->zbd_filename);
        return -EINVAL;
    }

    if ( ! dev->zbd_info.zbd_physical_blocks ) {
        zbc_error("%s: invalid capacity (physical blocks)\n",
                  dev->zbd_filename);
        return -EINVAL;
    }

    /* Finish setting */
    dev->zbd_info.zbd_type = ZBC_DT_FAKE;
    dev->zbd_info.zbd_model = ZBC_DM_HOST_MANAGED;
    strncpy(dev->zbd_info.zbd_vendor_id, "FAKE HGST HM libzbc", ZBC_DEVICE_INFO_LENGTH - 1);

    dev->zbd_info.zbd_opt_nr_open_seq_pref = 0;
    dev->zbd_info.zbd_opt_nr_non_seq_write_seq_pref = 0;
    dev->zbd_info.zbd_max_nr_open_seq_req = ZBC_FAKE_MAX_OPEN_NR_ZONES;

    /* Get maximum command size */
    zbc_sg_get_max_cmd_blocks(dev);

    return 0;

}
Exemplo n.º 2
0
/**
 * Get a device capacity information (total sectors & sector sizes).
 */
int
zbc_sg_get_capacity(zbc_device_t *dev,
		    int (*report_zones)(struct zbc_device *,
					uint64_t,
					enum zbc_reporting_options,
					uint64_t *,
					zbc_zone_t *,
					unsigned int *))
{
    zbc_sg_cmd_t cmd;
    zbc_zone_t *zones = NULL;
    int logical_per_physical;
    unsigned int nr_zones = 0;
    uint64_t max_lba;
    int ret;

    /* READ CAPACITY 16 */
    ret = zbc_sg_cmd_init(&cmd, ZBC_SG_READ_CAPACITY, NULL, ZBC_SG_READ_CAPACITY_REPLY_LEN);
    if ( ret != 0 ) {
        zbc_error("zbc_sg_cmd_init failed\n");
        return( ret );
    }

    /* Fill command CDB */
    cmd.cdb[0] = ZBC_SG_READ_CAPACITY_CDB_OPCODE;
    cmd.cdb[1] = ZBC_SG_READ_CAPACITY_CDB_SA;
    zbc_sg_cmd_set_int32(&cmd.cdb[10], ZBC_SG_READ_CAPACITY_REPLY_LEN);

    /* Send the SG_IO command */
    ret = zbc_sg_cmd_exec(dev, &cmd);
    if ( ret != 0 ) {
        goto out;
    }

    /* Logical block size */
    dev->zbd_info.zbd_logical_block_size = zbc_sg_cmd_get_int32(&cmd.out_buf[8]);
    if ( dev->zbd_info.zbd_logical_block_size <= 0 ) {
        zbc_error("%s: invalid logical sector size\n",
                  dev->zbd_filename);
        ret = -EINVAL;
        goto out;
    }

    logical_per_physical = 1 << cmd.out_buf[13] & 0x0f;

    /* Get maximum command size */
    zbc_sg_get_max_cmd_blocks(dev);

    /* Check RC_BASIS field */
    switch( (cmd.out_buf[12] & 0x30) >> 4 ) {

    case 0x00:

        /* The logical block address indicates the last LBA of the */
        /* conventional zones at the beginning of the disk. To get */
        /* the entire disk capacity, we need to get last LBA of    */
        /* the last zone of the disk.                              */
        ret = report_zones(dev, 0, ZBC_RO_ALL, &max_lba, NULL, &nr_zones);
        if ( ret != 0 ) {
	    goto out;
	}

	/* Set the drive capacity to the reported max LBA */
	dev->zbd_info.zbd_logical_blocks = max_lba + 1;

        break;

    case 0x01:

        /* The disk last LBA was reported */
        dev->zbd_info.zbd_logical_blocks = zbc_sg_cmd_get_int64(&cmd.out_buf[0]) + 1;

        break;

    default:

        zbc_error("%s: invalid RC_BASIS field encountered in READ CAPACITY result\n",
                  dev->zbd_filename);
        ret = -EIO;

        goto out;

    }

    if ( ! dev->zbd_info.zbd_logical_blocks ) {
        zbc_error("%s: invalid capacity (logical blocks)\n",
                  dev->zbd_filename);
        ret = -EINVAL;
        goto out;
    }

    dev->zbd_info.zbd_physical_block_size = dev->zbd_info.zbd_logical_block_size * logical_per_physical;
    dev->zbd_info.zbd_physical_blocks = dev->zbd_info.zbd_logical_blocks / logical_per_physical;

out:

    zbc_sg_cmd_destroy(&cmd);

    if ( zones ) {
        free(zones);
    }

    return( ret );

}