/*
 * calculate the mapping of a file extent onto an object, and fill out the
 * request accordingly.  shorten extent as necessary if it crosses an
 * object boundary.
 *
 * fill osd op in request message.
 */
static void calc_layout(struct ceph_osd_client *osdc,
			struct ceph_vino vino, struct ceph_file_layout *layout,
			u64 off, u64 *plen,
			struct ceph_osd_request *req)
{
	struct ceph_osd_request_head *reqhead = req->r_request->front.iov_base;
	struct ceph_osd_op *op = (void *)(reqhead + 1);
	u64 orig_len = *plen;
	u64 objoff, objlen;    /* extent in object */
	u64 bno;

	reqhead->snapid = cpu_to_le64(vino.snap);

	/* object extent? */
	ceph_calc_file_object_mapping(layout, off, plen, &bno,
				      &objoff, &objlen);
	if (*plen < orig_len)
		dout(" skipping last %llu, final file extent %llu~%llu\n",
		     orig_len - *plen, off, *plen);

	sprintf(req->r_oid, "%llx.%08llx", vino.ino, bno);
	req->r_oid_len = strlen(req->r_oid);

	op->extent.offset = cpu_to_le64(objoff);
	op->extent.length = cpu_to_le64(objlen);
	req->r_num_pages = calc_pages_for(off, *plen);

	dout("calc_layout %s (%d) %llu~%llu (%d pages)\n",
	     req->r_oid, req->r_oid_len, objoff, objlen, req->r_num_pages);
}
Esempio n. 2
0
void ceph_calc_raw_layout(struct ceph_osd_client *osdc,
			struct ceph_file_layout *layout,
			u64 snapid,
			u64 off, u64 *plen, u64 *bno,
			struct ceph_osd_request *req,
			struct ceph_osd_req_op *op)
{
	struct ceph_osd_request_head *reqhead = req->r_request->front.iov_base;
	u64 orig_len = *plen;
	u64 objoff, objlen;    /* extent in object */

	reqhead->snapid = cpu_to_le64(snapid);

	/* object extent? */
	ceph_calc_file_object_mapping(layout, off, plen, bno,
				      &objoff, &objlen);
	if (*plen < orig_len)
		dout(" skipping last %llu, final file extent %llu~%llu\n",
		     orig_len - *plen, off, *plen);

	if (op_has_extent(op->op)) {
		op->extent.offset = objoff;
		op->extent.length = objlen;
	}
	req->r_num_pages = calc_pages_for(off, *plen);
	req->r_page_alignment = off & ~PAGE_MASK;
	if (op->op == CEPH_OSD_OP_WRITE)
		op->payload_len = *plen;

	dout("calc_layout bno=%llx %llu~%llu (%d pages)\n",
	     *bno, objoff, objlen, req->r_num_pages);

}
Esempio n. 3
0
/*
 * Return object name, size/offset information, and location (OSD
 * number, network address) for a given file offset.
 */
static long ceph_ioctl_get_dataloc(struct file *file, void __user *arg)
{
	struct ceph_ioctl_dataloc dl;
	struct inode *inode = file_inode(file);
	struct ceph_inode_info *ci = ceph_inode(inode);
	struct ceph_osd_client *osdc =
		&ceph_sb_to_client(inode->i_sb)->client->osdc;
	u64 len = 1, olen;
	u64 tmp;
	struct ceph_object_layout ol;
	struct ceph_pg pgid;
	int r;

	/* copy and validate */
	if (copy_from_user(&dl, arg, sizeof(dl)))
		return -EFAULT;

	down_read(&osdc->map_sem);
	r = ceph_calc_file_object_mapping(&ci->i_layout, dl.file_offset, &len,
					  &dl.object_no, &dl.object_offset,
					  &olen);
	if (r < 0)
		return -EIO;
	dl.file_offset -= dl.object_offset;
	dl.object_size = ceph_file_layout_object_size(ci->i_layout);
	dl.block_size = ceph_file_layout_su(ci->i_layout);

	/* block_offset = object_offset % block_size */
	tmp = dl.object_offset;
	dl.block_offset = do_div(tmp, dl.block_size);

	snprintf(dl.object_name, sizeof(dl.object_name), "%llx.%08llx",
		 ceph_ino(inode), dl.object_no);
	ceph_calc_object_layout(&ol, dl.object_name, &ci->i_layout,
				osdc->osdmap);

	pgid = ol.ol_pgid;
	dl.osd = ceph_calc_pg_primary(osdc->osdmap, pgid);
	if (dl.osd >= 0) {
		struct ceph_entity_addr *a =
			ceph_osd_addr(osdc->osdmap, dl.osd);
		if (a)
			memcpy(&dl.osd_addr, &a->in_addr, sizeof(dl.osd_addr));
	} else {
		memset(&dl.osd_addr, 0, sizeof(dl.osd_addr));
	}
	up_read(&osdc->map_sem);

	/* send result back to user */
	if (copy_to_user(arg, &dl, sizeof(dl)))
		return -EFAULT;

	return 0;
}