Example #1
0
void test_io(rados_ioctx_t io, rbd_image_t image)
{
  char test_data[TEST_IO_SIZE + 1];
  int i;

  for (i = 0; i < TEST_IO_SIZE; ++i) {
    test_data[i] = (char) (rand() % (126 - 33) + 33);
  }
  test_data[TEST_IO_SIZE] = '\0';

  for (i = 0; i < 5; ++i)
    write_test_data(image, test_data, TEST_IO_SIZE * i, TEST_IO_SIZE);

  for (i = 5; i < 10; ++i)
    aio_write_test_data(image, test_data, TEST_IO_SIZE * i, TEST_IO_SIZE);

  for (i = 0; i < 5; ++i)
    read_test_data(image, test_data, TEST_IO_SIZE * i, TEST_IO_SIZE);

  for (i = 5; i < 10; ++i)
    aio_read_test_data(image, test_data, TEST_IO_SIZE * i, TEST_IO_SIZE);

  rbd_image_info_t info;
  rbd_completion_t comp;
  assert(rbd_stat(image, &info, sizeof(info)) == 0);
  assert(rbd_write(image, info.size, 1, test_data) == -EINVAL);
  assert(rbd_read(image, info.size, 1, test_data) == -EINVAL);
  rbd_aio_create_completion(NULL, (rbd_callback_t) simple_read_cb, &comp);
  assert(rbd_aio_write(image, info.size, 1, test_data, comp) == -EINVAL);
  assert(rbd_aio_read(image, info.size, 1, test_data, comp) == -EINVAL);
}
Example #2
0
static int rbdfs_read(const char *path, char *buf, size_t size,
                      off_t offset, struct fuse_file_info *fi)
{
    size_t numread;
    struct rbd_openimage *rbd;

    if (!gotrados)
        return -ENXIO;

    rbd = &opentbl[fi->fh];
    numread = 0;
    while (size > 0) {
        ssize_t ret;

        ret = rbd_read(rbd->image, offset, size, buf);

        if (ret <= 0)
            break;
        buf += ret;
        size -= ret;
        offset += ret;
        numread += ret;
    }

    return numread;
}
Example #3
0
File: fsx.c Project: CzBiX/ceph
ssize_t
librbd_read(struct rbd_ctx *ctx, uint64_t off, size_t len, void *buf)
{
	ssize_t n;

	n = rbd_read(ctx->image, off, len, buf);
	if (n < 0)
		prt("rbd_read(%llu, %zu) failed\n", off, len);

	return n;
}
Example #4
0
int main(int argc, char* argv[])
{
	int err;
	rados_t cluster;
	rados_ioctx_t io;
	rbd_image_t image;
	char *poolname = "pool100";
	char buf[IMAGE_BUF_SIZE] = {0};

	err = rados_create(&cluster, NULL);
	if (err < 0) {
		fprintf(stderr, "%s: cannot create a cluster handle: %s\n", argv[0], strerror(-err));
		exit(1);
	}

	err = rados_conf_read_file(cluster, "/etc/ceph/ceph.conf");
	if (err < 0) {
		fprintf(stderr, "%s: cannot read config file: %s\n", argv[0], strerror(-err));
		exit(1);
	}

	err = rados_connect(cluster);
	if (err < 0) {
		fprintf(stderr, "%s: cannot connect to cluster: %s\n", argv[0], strerror(-err));
		exit(1);
	}


	err = rados_ioctx_create(cluster, poolname, &io);
	if (err < 0) {
		fprintf(stderr, "%s: cannot open rados pool %s: %s\n", argv[0], poolname, strerror(-err));
		rados_shutdown(cluster);
		exit(1);
	}


	err = rbd_open(io, "user1_image2", &image, NULL);
	if (err < 0){
		fprintf(stderr, "open image failed: %s\n", strerror(-err));
		goto out;
	}
	

	err = rbd_read(image, IMAGE_BUF_SIZE*2, IMAGE_BUF_SIZE, buf);
	if (err < 0) {
		fprintf(stderr, "%s: cannot read image: %s\n",  poolname, strerror(-err));
	}else{
		fprintf(stderr, "read image return :%d\n", err);
	}
out:
	rados_ioctx_destroy(io);
	rados_shutdown(cluster);
	return 0;
}
Example #5
0
File: fsx.c Project: athanatos/ceph
void
check_clones()
{
	char filename[1024];
	char imagename[1024];
	int ret, fd;
	rbd_image_t cur_image;
	struct stat file_info;
	while (num_clones > 0) {
		prt("checking clone #%d\n", num_clones);
		--num_clones;

		clone_imagename(imagename, sizeof(imagename), num_clones);
		if ((ret = rbd_open(ioctx, imagename, &cur_image, NULL)) < 0) {
			simple_err("check_clones: rbd open", ret);
			exit(167);
		}

		clone_filename(filename, sizeof(filename), num_clones + 1);
		if ((fd = open(filename, O_RDONLY)) < 0) {
			simple_err("check_clones: open", -errno);
			exit(168);
		}

		prt("checking image %s against file %s\n", imagename, filename);
		if ((ret = fstat(fd, &file_info)) < 0) {
			simple_err("check_clones: fstat", -errno);
			exit(169);
		}

		if ((ret = pread(fd, good_buf, file_info.st_size, 0)) < 0) {
			simple_err("check_clones: pread", -errno);
			exit(170);
		}

		if ((ret = rbd_read(cur_image, 0, file_info.st_size, temp_buf)) < 0) {
			simple_err("check_clones: rbd_read", ret);
			exit(171);
		}
		close(fd);
		check_buffers(0, file_info.st_size);

		unlink(filename);
		/* remove the snapshot if it exists, ignore
		   the error from the last clone. */
		rbd_snap_unprotect(cur_image, "snap");
		rbd_snap_remove(cur_image, "snap");
		rbd_close(cur_image);
		rbd_remove(ioctx, imagename);
	}
}
Example #6
0
void read_test_data(rbd_image_t image, const char *expected, uint64_t off, size_t len)
{
  ssize_t read;
  char *result;
  assert((result = malloc(sizeof(result) * (len + 1))) != 0);

  read = rbd_read(image, off, len, result);
  printf("read: %d\n", (int) read);
  assert(read == (ssize_t)len);
  result[len] = '\0';
  printf("read: %s\nexpected: %s\n", result, expected);
  assert(memcmp(result, expected, len) == 0);
  free(result);
}
Example #7
0
void
doread(unsigned offset, unsigned size)
{
	int ret;

	offset -= offset % readbdy;
	if (o_direct)
		size -= size % readbdy;
	if (size == 0) {
		if (!quiet && testcalls > simulatedopcount && !o_direct)
			prt("skipping zero size read\n");
		log4(OP_SKIPPED, OP_READ, offset, size);
		return;
	}
	if (size + offset > file_size) {
		if (!quiet && testcalls > simulatedopcount)
			prt("skipping seek/read past end of file\n");
		log4(OP_SKIPPED, OP_READ, offset, size);
		return;
	}

	log4(OP_READ, offset, size, 0);

	if (testcalls <= simulatedopcount)
		return;

	if (!quiet &&
		((progressinterval && testcalls % progressinterval == 0)  ||
		(debug &&
		       (monitorstart == -1 ||
			(offset + size > monitorstart &&
			(monitorend == -1 || offset <= monitorend))))))
		prt("%lu read\t0x%x thru\t0x%x\t(0x%x bytes)\n", testcalls,
		    offset, offset + size - 1, size);
	ret = rbd_read(image, offset, size, temp_buf);
	if (ret != (int)size) {
		if (ret < 0)
			prterrcode("doread: read", ret);
		else
			prt("short read: 0x%x bytes instead of 0x%x\n",
			    ret, size);
		report_failure(141);
	}
	check_buffers(offset, size);
}
Example #8
0
File: bs_rbd.c Project: chitr/tgt
static void bs_rbd_request(struct scsi_cmd *cmd)
{
	int ret;
	uint32_t length;
	int result = SAM_STAT_GOOD;
	uint8_t key;
	uint16_t asc;
#if 0
	/*
	 * This should go in the sense data on error for COMPARE_AND_WRITE, but
	 * there doesn't seem to be any attempt to do so...
	 */

	uint32_t info = 0;
#endif
	char *tmpbuf;
	size_t blocksize;
	uint64_t offset = cmd->offset;
	uint32_t tl     = cmd->tl;
	int do_verify = 0;
	int i;
	char *ptr;
	const char *write_buf = NULL;
	ret = length = 0;
	key = asc = 0;
	struct active_rbd *rbd = RBDP(cmd->dev->fd);

	switch (cmd->scb[0]) {
	case ORWRITE_16:
		length = scsi_get_out_length(cmd);

		tmpbuf = malloc(length);
		if (!tmpbuf) {
			result = SAM_STAT_CHECK_CONDITION;
			key = HARDWARE_ERROR;
			asc = ASC_INTERNAL_TGT_FAILURE;
			break;
		}

		ret = rbd_read(rbd->rbd_image, offset, length, tmpbuf);

		if (ret != length) {
			set_medium_error(&result, &key, &asc);
			free(tmpbuf);
			break;
		}

		ptr = scsi_get_out_buffer(cmd);
		for (i = 0; i < length; i++)
			ptr[i] |= tmpbuf[i];

		free(tmpbuf);

		write_buf = scsi_get_out_buffer(cmd);
		goto write;
	case COMPARE_AND_WRITE:
		/* Blocks are transferred twice, first the set that
		 * we compare to the existing data, and second the set
		 * to write if the compare was successful.
		 */
		length = scsi_get_out_length(cmd) / 2;
		if (length != cmd->tl) {
			result = SAM_STAT_CHECK_CONDITION;
			key = ILLEGAL_REQUEST;
			asc = ASC_INVALID_FIELD_IN_CDB;
			break;
		}

		tmpbuf = malloc(length);
		if (!tmpbuf) {
			result = SAM_STAT_CHECK_CONDITION;
			key = HARDWARE_ERROR;
			asc = ASC_INTERNAL_TGT_FAILURE;
			break;
		}

		ret = rbd_read(rbd->rbd_image, offset, length, tmpbuf);

		if (ret != length) {
			set_medium_error(&result, &key, &asc);
			free(tmpbuf);
			break;
		}

		if (memcmp(scsi_get_out_buffer(cmd), tmpbuf, length)) {
			uint32_t pos = 0;
			char *spos = scsi_get_out_buffer(cmd);
			char *dpos = tmpbuf;

			/*
			 * Data differed, this is assumed to be 'rare'
			 * so use a much more expensive byte-by-byte
			 * comparasion to find out at which offset the
			 * data differs.
			 */
			for (pos = 0; pos < length && *spos++ == *dpos++;
			     pos++)
				;
#if 0
			/* See comment above at declaration */
			info = pos;
#endif
			result = SAM_STAT_CHECK_CONDITION;
			key = MISCOMPARE;
			asc = ASC_MISCOMPARE_DURING_VERIFY_OPERATION;
			free(tmpbuf);
			break;
		}

		/* no DPO bit (cache retention advice) support */
		free(tmpbuf);

		write_buf = scsi_get_out_buffer(cmd) + length;
		goto write;
	case SYNCHRONIZE_CACHE:
	case SYNCHRONIZE_CACHE_16:
		/* TODO */
		length = (cmd->scb[0] == SYNCHRONIZE_CACHE) ? 0 : 0;

		if (cmd->scb[1] & 0x2) {
			result = SAM_STAT_CHECK_CONDITION;
			key = ILLEGAL_REQUEST;
			asc = ASC_INVALID_FIELD_IN_CDB;
		} else
			bs_sync_sync_range(cmd, length, &result, &key, &asc);
		break;
	case WRITE_VERIFY:
	case WRITE_VERIFY_12:
	case WRITE_VERIFY_16:
		do_verify = 1;
	case WRITE_6:
	case WRITE_10:
	case WRITE_12:
	case WRITE_16:
		length = scsi_get_out_length(cmd);
		write_buf = scsi_get_out_buffer(cmd);
write:
		ret = rbd_write(rbd->rbd_image, offset, length, write_buf);
		if (ret == length) {
			struct mode_pg *pg;

			/*
			 * it would be better not to access to pg
			 * directy.
			 */
			pg = find_mode_page(cmd->dev, 0x08, 0);
			if (pg == NULL) {
				result = SAM_STAT_CHECK_CONDITION;
				key = ILLEGAL_REQUEST;
				asc = ASC_INVALID_FIELD_IN_CDB;
				break;
			}
			if (((cmd->scb[0] != WRITE_6) && (cmd->scb[1] & 0x8)) ||
			    !(pg->mode_data[0] & 0x04))
				bs_sync_sync_range(cmd, length, &result, &key,
						   &asc);
		} else
			set_medium_error(&result, &key, &asc);

		if (do_verify)
			goto verify;
		break;
	case WRITE_SAME:
	case WRITE_SAME_16:
		/* WRITE_SAME used to punch hole in file */
		if (cmd->scb[1] & 0x08) {
			ret = rbd_discard(rbd->rbd_image, offset, tl);
			if (ret != 0) {
				eprintf("Failed to punch hole for WRITE_SAME"
					" command\n");
				result = SAM_STAT_CHECK_CONDITION;
				key = HARDWARE_ERROR;
				asc = ASC_INTERNAL_TGT_FAILURE;
				break;
			}
			break;
		}
		while (tl > 0) {
			blocksize = 1 << cmd->dev->blk_shift;
			tmpbuf = scsi_get_out_buffer(cmd);

			switch (cmd->scb[1] & 0x06) {
			case 0x02: /* PBDATA==0 LBDATA==1 */
				put_unaligned_be32(offset, tmpbuf);
				break;
			case 0x04: /* PBDATA==1 LBDATA==0 */
				/* physical sector format */
				put_unaligned_be64(offset, tmpbuf);
				break;
			}

			ret = rbd_write(rbd->rbd_image, offset, blocksize,
					tmpbuf);
			if (ret != blocksize)
				set_medium_error(&result, &key, &asc);

			offset += blocksize;
			tl     -= blocksize;
		}
		break;
	case READ_6:
	case READ_10:
	case READ_12:
	case READ_16:
		length = scsi_get_in_length(cmd);
		ret = rbd_read(rbd->rbd_image, offset, length,
			       scsi_get_in_buffer(cmd));

		if (ret != length)
			set_medium_error(&result, &key, &asc);

		break;
	case PRE_FETCH_10:
	case PRE_FETCH_16:
		break;
	case VERIFY_10:
	case VERIFY_12:
	case VERIFY_16:
verify:
		length = scsi_get_out_length(cmd);

		tmpbuf = malloc(length);
		if (!tmpbuf) {
			result = SAM_STAT_CHECK_CONDITION;
			key = HARDWARE_ERROR;
			asc = ASC_INTERNAL_TGT_FAILURE;
			break;
		}

		ret = rbd_read(rbd->rbd_image, offset, length, tmpbuf);

		if (ret != length)
			set_medium_error(&result, &key, &asc);
		else if (memcmp(scsi_get_out_buffer(cmd), tmpbuf, length)) {
			result = SAM_STAT_CHECK_CONDITION;
			key = MISCOMPARE;
			asc = ASC_MISCOMPARE_DURING_VERIFY_OPERATION;
		}

		free(tmpbuf);
		break;
	case UNMAP:
		if (!cmd->dev->attrs.thinprovisioning) {
			result = SAM_STAT_CHECK_CONDITION;
			key = ILLEGAL_REQUEST;
			asc = ASC_INVALID_FIELD_IN_CDB;
			break;
		}

		length = scsi_get_out_length(cmd);
		tmpbuf = scsi_get_out_buffer(cmd);

		if (length < 8)
			break;

		length -= 8;
		tmpbuf += 8;

		while (length >= 16) {
			offset = get_unaligned_be64(&tmpbuf[0]);
			offset = offset << cmd->dev->blk_shift;

			tl = get_unaligned_be32(&tmpbuf[8]);
			tl = tl << cmd->dev->blk_shift;

			if (offset + tl > cmd->dev->size) {
				eprintf("UNMAP beyond EOF\n");
				result = SAM_STAT_CHECK_CONDITION;
				key = ILLEGAL_REQUEST;
				asc = ASC_LBA_OUT_OF_RANGE;
				break;
			}

			if (tl > 0) {
				if (rbd_discard(rbd->rbd_image, offset, tl)
				    != 0) {
					eprintf("Failed to punch hole for"
						" UNMAP at offset:%" PRIu64
						" length:%d\n",
						offset, tl);
					result = SAM_STAT_CHECK_CONDITION;
					key = HARDWARE_ERROR;
					asc = ASC_INTERNAL_TGT_FAILURE;
					break;
				}
			}

			length -= 16;
			tmpbuf += 16;
		}
		break;
	default:
		break;
	}

	dprintf("io done %p %x %d %u\n", cmd, cmd->scb[0], ret, length);

	scsi_set_result(cmd, result);

	if (result != SAM_STAT_GOOD) {
		eprintf("io error %p %x %d %d %" PRIu64 ", %m\n",
			cmd, cmd->scb[0], ret, length, offset);
		sense_data_build(cmd, key, asc);
	}
}
Example #9
0
void test_io_to_snapshot(rados_ioctx_t io_ctx, rbd_image_t image, size_t isize)
{
  int i, r;
  rbd_image_t image_at_snap;
  char orig_data[TEST_IO_TO_SNAP_SIZE + 1];
  char test_data[TEST_IO_TO_SNAP_SIZE + 1];

  for (i = 0; i < TEST_IO_TO_SNAP_SIZE - 1; ++i)
    test_data[i] = (char) (i + 48);
  test_data[TEST_IO_TO_SNAP_SIZE] = '\0';
  orig_data[TEST_IO_TO_SNAP_SIZE] = '\0';

  r = rbd_read(image, 0, TEST_IO_TO_SNAP_SIZE, orig_data);
  assert(r == TEST_IO_TO_SNAP_SIZE);

  test_ls_snaps(image, 0);
  test_create_snap(image, "orig");
  test_ls_snaps(image, 1, "orig", isize);
  read_test_data(image, orig_data, 0, TEST_IO_TO_SNAP_SIZE);

  printf("write test data!\n");
  write_test_data(image, test_data, 0, TEST_IO_TO_SNAP_SIZE);
  test_create_snap(image, "written");
  test_ls_snaps(image, 2, "orig", isize, "written", isize);

  read_test_data(image, test_data, 0, TEST_IO_TO_SNAP_SIZE);

  rbd_snap_set(image, "orig");
  read_test_data(image, orig_data, 0, TEST_IO_TO_SNAP_SIZE);

  rbd_snap_set(image, "written");
  read_test_data(image, test_data, 0, TEST_IO_TO_SNAP_SIZE);

  rbd_snap_set(image, "orig");

  r = rbd_write(image, 0, TEST_IO_TO_SNAP_SIZE, test_data);
  printf("write to snapshot returned %d\n", r);
  assert(r < 0);
  printf("%s\n", strerror(-r));

  read_test_data(image, orig_data, 0, TEST_IO_TO_SNAP_SIZE);
  rbd_snap_set(image, "written");
  read_test_data(image, test_data, 0, TEST_IO_TO_SNAP_SIZE);

  r = rbd_snap_rollback(image, "orig");
  printf("rbd_snap_rollback returned %d\n", r);
  assert(r >= 0);

  r = rbd_snap_set(image, NULL);
  assert(r == 0);
  write_test_data(image, test_data, 0, TEST_IO_TO_SNAP_SIZE);

  printf("opening testimg@orig\n");
  assert(rbd_open(io_ctx, TEST_IMAGE, &image_at_snap, "orig") >= 0);
  read_test_data(image_at_snap, orig_data, 0, TEST_IO_TO_SNAP_SIZE);
  r = rbd_write(image_at_snap, 0, TEST_IO_TO_SNAP_SIZE, test_data);
  printf("write to snapshot returned %d\n", r);
  assert(r < 0);
  printf("%s\n", strerror(-r));
  assert(rbd_close(image_at_snap) == 0);

  test_ls_snaps(image, 2, "orig", isize, "written", isize);
  test_delete_snap(image, "written");
  test_ls_snaps(image, 1, "orig", isize);
  test_delete_snap(image, "orig");
  test_ls_snaps(image, 0);
}