static int get_whole_cluster(BlockDriverState *bs, VmdkExtent *extent, uint64_t cluster_offset, uint64_t offset, bool allocate) { /* 128 sectors * 512 bytes each = grain size 64KB */ uint8_t whole_grain[extent->cluster_sectors * 512]; /* we will be here if it's first write on non-exist grain(cluster). * try to read from parent image, if exist */ if (bs->backing_hd) { int ret; if (!vmdk_is_cid_valid(bs)) { return -1; } /* floor offset to cluster */ offset -= offset % (extent->cluster_sectors * 512); ret = bdrv_read(bs->backing_hd, offset >> 9, whole_grain, extent->cluster_sectors); if (ret < 0) { return -1; } /* Write grain only into the active image */ ret = bdrv_write(extent->file, cluster_offset, whole_grain, extent->cluster_sectors); if (ret < 0) { return -1; } }
static int coroutine_fn commit_populate(BlockDriverState *bs, BlockDriverState *base, int64_t sector_num, int nb_sectors, void *buf) { int ret = 0; ret = bdrv_read(bs, sector_num, buf, nb_sectors); if (ret) { return ret; } ret = bdrv_write(base, sector_num, buf, nb_sectors); if (ret) { return ret; } return 0; }
static int goldfish_mmc_bdrv_write(struct goldfish_mmc_state *s, int64_t sector_number, target_phys_addr_t dst_address, int num_sectors) { int ret; while (num_sectors > 0) { cpu_physical_memory_read(dst_address, s->buf, 512); ret = bdrv_write(s->bs, sector_number, s->buf, 1); if (ret < 0) return ret; dst_address += 512; num_sectors -= 1; sector_number += 1; } return 0; }
static int goldfish_mmc_bdrv_write(struct goldfish_mmc_state *s, int64_t sector_number, hwaddr dst_address, int num_sectors) { int ret; int printData = matchMeInPidTid(cpu_single_env); while (num_sectors > 0) { cpu_physical_memory_read(dst_address, s->buf, 512, printData, "goldfish_mmc_bdrv_write"); ret = bdrv_write(s->bs, sector_number, s->buf, 1); if (ret < 0) return ret; dst_address += 512; num_sectors -= 1; sector_number += 1; } return 0; }
static int vpc_write(BlockDriverState *bs, int64_t sector_num, const uint8_t *buf, int nb_sectors) { BDRVVPCState *s = bs->opaque; int64_t offset; int64_t sectors, sectors_per_block; int ret; VHDFooter *footer = (VHDFooter *) s->footer_buf; if (be32_to_cpu(footer->type) == VHD_FIXED) { return bdrv_write(bs->file->bs, sector_num, buf, nb_sectors); } while (nb_sectors > 0) { offset = get_sector_offset(bs, sector_num, 1); sectors_per_block = s->block_size >> BDRV_SECTOR_BITS; sectors = sectors_per_block - (sector_num % sectors_per_block); if (sectors > nb_sectors) { sectors = nb_sectors; } if (offset == -1) { offset = alloc_block(bs, sector_num); if (offset < 0) return -1; } ret = bdrv_pwrite(bs->file->bs, offset, buf, sectors * BDRV_SECTOR_SIZE); if (ret != sectors * BDRV_SECTOR_SIZE) { return -1; } nb_sectors -= sectors; sector_num += sectors; buf += sectors * BDRV_SECTOR_SIZE; } return 0; }
static int disk_img_write(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { int err; int nb_sectors = size >> SHIFT_SECTOR; int start_sec = offset >> SHIFT_SECTOR; FDBG("path %s" , path ); if(strcasecmp(path, disk_img_data.raw_filename) != 0) return -ENOENT; FDBG("path %s" , path ); FDBG("buffer %s" , buf ); FDBG("size: %d offset %lld fh %lld" , size , offset , fi->fh ); err = bdrv_write(disk_img_data.img_bs, start_sec, (uint8_t*) buf, nb_sectors); //FDBG("DATA : %s", buf); FDBG("Exit code : %d", err); return size; }
static int ioreq_runio_qemu_sync(struct ioreq *ioreq) { struct XenBlkDev *blkdev = ioreq->blkdev; int i, rc, len = 0; off_t pos; if (ioreq->req.nr_segments && ioreq_map(ioreq) == -1) goto err; if (ioreq->presync) bdrv_flush(blkdev->bs); switch (ioreq->req.operation) { case BLKIF_OP_READ: pos = ioreq->start; for (i = 0; i < ioreq->v.niov; i++) { rc = bdrv_read(blkdev->bs, pos / BLOCK_SIZE, ioreq->v.iov[i].iov_base, ioreq->v.iov[i].iov_len / BLOCK_SIZE); if (rc != 0) { xen_be_printf(&blkdev->xendev, 0, "rd I/O error (%p, len %zd)\n", ioreq->v.iov[i].iov_base, ioreq->v.iov[i].iov_len); goto err; } len += ioreq->v.iov[i].iov_len; pos += ioreq->v.iov[i].iov_len; } break; case BLKIF_OP_WRITE: case BLKIF_OP_WRITE_BARRIER: if (!ioreq->req.nr_segments) break; pos = ioreq->start; for (i = 0; i < ioreq->v.niov; i++) { rc = bdrv_write(blkdev->bs, pos / BLOCK_SIZE, ioreq->v.iov[i].iov_base, ioreq->v.iov[i].iov_len / BLOCK_SIZE); if (rc != 0) { xen_be_printf(&blkdev->xendev, 0, "wr I/O error (%p, len %zd)\n", ioreq->v.iov[i].iov_base, ioreq->v.iov[i].iov_len); goto err; } len += ioreq->v.iov[i].iov_len; pos += ioreq->v.iov[i].iov_len; } break; default: /* unknown operation (shouldn't happen -- parse catches this) */ goto err; } if (ioreq->postsync) bdrv_flush(blkdev->bs); ioreq->status = BLKIF_RSP_OKAY; ioreq_unmap(ioreq); ioreq_finish(ioreq); return 0; err: ioreq->status = BLKIF_RSP_ERROR; return -1; }
int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset, off_t *offset, bool readonly, uint8_t *data, int data_size) { struct nbd_request request; struct nbd_reply reply; TRACE("Reading request."); if (nbd_receive_request(csock, &request) == -1) return -1; if (request.len > data_size) { LOG("len (%u) is larger than max len (%u)", request.len, data_size); errno = EINVAL; return -1; } if ((request.from + request.len) < request.from) { LOG("integer overflow detected! " "you're probably being attacked"); errno = EINVAL; return -1; } if ((request.from + request.len) > size) { LOG("From: %" PRIu64 ", Len: %u, Size: %" PRIu64 ", Offset: %" PRIu64 "\n", request.from, request.len, (uint64_t)size, dev_offset); LOG("requested operation past EOF--bad client?"); errno = EINVAL; return -1; } TRACE("Decoding type"); reply.handle = request.handle; reply.error = 0; switch (request.type) { case NBD_CMD_READ: TRACE("Request type is READ"); if (bdrv_read(bs, (request.from + dev_offset) / 512, data, request.len / 512) == -1) { LOG("reading from file failed"); errno = EINVAL; return -1; } *offset += request.len; TRACE("Read %u byte(s)", request.len); if (nbd_send_reply(csock, &reply) == -1) return -1; TRACE("Sending data to client"); if (write_sync(csock, data, request.len) != request.len) { LOG("writing to socket failed"); errno = EINVAL; return -1; } break; case NBD_CMD_WRITE: TRACE("Request type is WRITE"); TRACE("Reading %u byte(s)", request.len); if (read_sync(csock, data, request.len) != request.len) { LOG("reading from socket failed"); errno = EINVAL; return -1; } if (readonly) { TRACE("Server is read-only, return error"); reply.error = 1; } else { TRACE("Writing to device"); if (bdrv_write(bs, (request.from + dev_offset) / 512, data, request.len / 512) == -1) { LOG("writing to file failed"); errno = EINVAL; return -1; } *offset += request.len; } if (nbd_send_reply(csock, &reply) == -1) return -1; break; case NBD_CMD_DISC: TRACE("Request type is DISCONNECT"); errno = 0; return 1; default: LOG("invalid request type (%u) received", request.type); errno = EINVAL; return -1; } TRACE("Request/Reply complete"); return 0; }
static int raw_write(BlockDriverState *bs, int64_t sector_num, const uint8_t *buf, int nb_sectors) { return bdrv_write(bs->file, sector_num, buf, nb_sectors); }
static void nbd_trip(void *opaque) { NBDClient *client = opaque; NBDRequest *req = nbd_request_get(client); NBDExport *exp = client->exp; struct nbd_request request; struct nbd_reply reply; ssize_t ret; TRACE("Reading request."); ret = nbd_co_receive_request(req, &request); if (ret == -EAGAIN) { goto done; } if (ret == -EIO) { goto out; } reply.handle = request.handle; reply.error = 0; if (ret < 0) { reply.error = -ret; goto error_reply; } if ((request.from + request.len) > exp->size) { LOG("From: %" PRIu64 ", Len: %u, Size: %" PRIu64 ", Offset: %" PRIu64 "\n", request.from, request.len, (uint64_t)exp->size, (uint64_t)exp->dev_offset); LOG("requested operation past EOF--bad client?"); goto invalid_request; } switch (request.type & NBD_CMD_MASK_COMMAND) { case NBD_CMD_READ: TRACE("Request type is READ"); if (request.type & NBD_CMD_FLAG_FUA) { ret = bdrv_co_flush(exp->bs); if (ret < 0) { LOG("flush failed"); reply.error = -ret; goto error_reply; } } ret = bdrv_read(exp->bs, (request.from + exp->dev_offset) / 512, req->data, request.len / 512); if (ret < 0) { LOG("reading from file failed"); reply.error = -ret; goto error_reply; } TRACE("Read %u byte(s)", request.len); if (nbd_co_send_reply(req, &reply, request.len) < 0) goto out; break; case NBD_CMD_WRITE: TRACE("Request type is WRITE"); if (exp->nbdflags & NBD_FLAG_READ_ONLY) { TRACE("Server is read-only, return error"); reply.error = EROFS; goto error_reply; } TRACE("Writing to device"); ret = bdrv_write(exp->bs, (request.from + exp->dev_offset) / 512, req->data, request.len / 512); if (ret < 0) { LOG("writing to file failed"); reply.error = -ret; goto error_reply; } if (request.type & NBD_CMD_FLAG_FUA) { ret = bdrv_co_flush(exp->bs); if (ret < 0) { LOG("flush failed"); reply.error = -ret; goto error_reply; } } if (nbd_co_send_reply(req, &reply, 0) < 0) { goto out; } break; case NBD_CMD_DISC: TRACE("Request type is DISCONNECT"); errno = 0; goto out; case NBD_CMD_FLUSH: TRACE("Request type is FLUSH"); ret = bdrv_co_flush(exp->bs); if (ret < 0) { LOG("flush failed"); reply.error = -ret; } if (nbd_co_send_reply(req, &reply, 0) < 0) { goto out; } break; case NBD_CMD_TRIM: TRACE("Request type is TRIM"); ret = bdrv_co_discard(exp->bs, (request.from + exp->dev_offset) / 512, request.len / 512); if (ret < 0) { LOG("discard failed"); reply.error = -ret; } if (nbd_co_send_reply(req, &reply, 0) < 0) { goto out; } break; default: LOG("invalid request type (%u) received", request.type); invalid_request: reply.error = -EINVAL; error_reply: if (nbd_co_send_reply(req, &reply, 0) < 0) { goto out; } break; } TRACE("Request/Reply complete"); done: nbd_request_put(req); return; out: nbd_request_put(req); nbd_client_close(client); }