예제 #1
0
static void calc_total_layout(LAYOUT *base)
{
    calc_layout(base->next);
    calc_fills(base->next, 0, 0);
    calc_aligns(base->next);
    calc_offsets(base->next, 0, 0);
    
}
예제 #2
0
struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc,
					       struct ceph_file_layout *layout,
					       struct ceph_vino vino,
					       u64 off, u64 *plen,
					       int opcode, int flags,
					       struct ceph_snap_context *snapc,
					       int do_sync,
					       u32 truncate_seq,
					       u64 truncate_size,
					       struct timespec *mtime,
					       bool use_mempool, int num_reply,
					       int page_align)
{
	struct ceph_osd_req_op ops[3];
	struct ceph_osd_request *req;
	int r;

	ops[0].op = opcode;
	ops[0].extent.truncate_seq = truncate_seq;
	ops[0].extent.truncate_size = truncate_size;
	ops[0].payload_len = 0;

	if (do_sync) {
		ops[1].op = CEPH_OSD_OP_STARTSYNC;
		ops[1].payload_len = 0;
		ops[2].op = 0;
	} else
		ops[1].op = 0;

	req = ceph_osdc_alloc_request(osdc, flags,
					 snapc, ops,
					 use_mempool,
					 GFP_NOFS, NULL, NULL);
	if (!req)
		return NULL;

	
	r = calc_layout(osdc, vino, layout, off, plen, req, ops);
	if (r < 0)
		return ERR_PTR(r);
	req->r_file_layout = *layout;  

	req->r_num_pages = calc_pages_for(page_align, *plen);
	req->r_page_alignment = page_align;

	ceph_osdc_build_request(req, off, plen, ops,
				snapc,
				mtime,
				req->r_oid, req->r_oid_len);

	return req;
}
예제 #3
0
/*
 * build new request AND message, calculate layout, and adjust file
 * extent as needed.
 *
 * if the file was recently truncated, we include information about its
 * old and new size so that the object can be updated appropriately.  (we
 * avoid synchronously deleting truncated objects because it's slow.)
 *
 * if @do_sync, include a 'startsync' command so that the osd will flush
 * data quickly.
 */
struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc,
					       struct ceph_file_layout *layout,
					       struct ceph_vino vino,
					       u64 off, u64 *plen,
					       int opcode, int flags,
					       struct ceph_snap_context *snapc,
					       int do_sync,
					       u32 truncate_seq,
					       u64 truncate_size,
					       struct timespec *mtime,
					       bool use_mempool, int num_reply,
					       int page_align)
{
	struct ceph_osd_req_op ops[3];
	struct ceph_osd_request *req;

	ops[0].op = opcode;
	ops[0].extent.truncate_seq = truncate_seq;
	ops[0].extent.truncate_size = truncate_size;
	ops[0].payload_len = 0;

	if (do_sync) {
		ops[1].op = CEPH_OSD_OP_STARTSYNC;
		ops[1].payload_len = 0;
		ops[2].op = 0;
	} else
		ops[1].op = 0;

	req = ceph_osdc_alloc_request(osdc, flags,
					 snapc, ops,
					 use_mempool,
					 GFP_NOFS, NULL, NULL);
	if (!req)
		return NULL;

	/* calculate max write size */
	calc_layout(osdc, vino, layout, off, plen, req, ops);
	req->r_file_layout = *layout;  /* keep a copy */

	/* in case it differs from natural (file) alignment that
	   calc_layout filled in for us */
	req->r_num_pages = calc_pages_for(page_align, *plen);
	req->r_page_alignment = page_align;

	ceph_osdc_build_request(req, off, plen, ops,
				snapc,
				mtime,
				req->r_oid, req->r_oid_len);

	return req;
}
/*
 * build new request AND message, calculate layout, and adjust file
 * extent as needed.
 *
 * if the file was recently truncated, we include information about its
 * old and new size so that the object can be updated appropriately.  (we
 * avoid synchronously deleting truncated objects because it's slow.)
 *
 * if @do_sync, include a 'startsync' command so that the osd will flush
 * data quickly.
 */
struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc,
					       struct ceph_file_layout *layout,
					       struct ceph_vino vino,
					       u64 off, u64 *plen,
					       int opcode, int flags,
					       struct ceph_snap_context *snapc,
					       int do_sync,
					       u32 truncate_seq,
					       u64 truncate_size,
					       struct timespec *mtime,
					       bool use_mempool, int num_reply)
{
	struct ceph_osd_request *req;
	struct ceph_msg *msg;
	struct ceph_osd_request_head *head;
	struct ceph_osd_op *op;
	void *p;
	int num_op = 1 + do_sync;
	size_t msg_size = sizeof(*head) + num_op*sizeof(*op);
	int i;

	if (use_mempool) {
		req = mempool_alloc(osdc->req_mempool, GFP_NOFS);
		memset(req, 0, sizeof(*req));
	} else {
		req = kzalloc(sizeof(*req), GFP_NOFS);
	}
	if (req == NULL)
		return NULL;

	req->r_osdc = osdc;
	req->r_mempool = use_mempool;
	kref_init(&req->r_kref);
	init_completion(&req->r_completion);
	init_completion(&req->r_safe_completion);
	INIT_LIST_HEAD(&req->r_unsafe_item);
	req->r_flags = flags;

	WARN_ON((flags & (CEPH_OSD_FLAG_READ|CEPH_OSD_FLAG_WRITE)) == 0);

	/* create reply message */
	if (use_mempool)
		msg = ceph_msgpool_get(&osdc->msgpool_op_reply, 0);
	else
		msg = ceph_msg_new(CEPH_MSG_OSD_OPREPLY,
				   OSD_OPREPLY_FRONT_LEN, GFP_NOFS);
	if (!msg) {
		ceph_osdc_put_request(req);
		return NULL;
	}
	req->r_reply = msg;

	/* create request message; allow space for oid */
	msg_size += 40;
	if (snapc)
		msg_size += sizeof(u64) * snapc->num_snaps;
	if (use_mempool)
		msg = ceph_msgpool_get(&osdc->msgpool_op, 0);
	else
		msg = ceph_msg_new(CEPH_MSG_OSD_OP, msg_size, GFP_NOFS);
	if (!msg) {
		ceph_osdc_put_request(req);
		return NULL;
	}
	msg->hdr.type = cpu_to_le16(CEPH_MSG_OSD_OP);
	memset(msg->front.iov_base, 0, msg->front.iov_len);
	head = msg->front.iov_base;
	op = (void *)(head + 1);
	p = (void *)(op + num_op);

	req->r_request = msg;
	req->r_snapc = ceph_get_snap_context(snapc);

	head->client_inc = cpu_to_le32(1); /* always, for now. */
	head->flags = cpu_to_le32(flags);
	if (flags & CEPH_OSD_FLAG_WRITE)
		ceph_encode_timespec(&head->mtime, mtime);
	head->num_ops = cpu_to_le16(num_op);
	op->op = cpu_to_le16(opcode);

	/* calculate max write size */
	calc_layout(osdc, vino, layout, off, plen, req);
	req->r_file_layout = *layout;  /* keep a copy */

	if (flags & CEPH_OSD_FLAG_WRITE) {
		req->r_request->hdr.data_off = cpu_to_le16(off);
		req->r_request->hdr.data_len = cpu_to_le32(*plen);
		op->payload_len = cpu_to_le32(*plen);
	}
	op->extent.truncate_size = cpu_to_le64(truncate_size);
	op->extent.truncate_seq = cpu_to_le32(truncate_seq);

	/* fill in oid */
	head->object_len = cpu_to_le32(req->r_oid_len);
	memcpy(p, req->r_oid, req->r_oid_len);
	p += req->r_oid_len;

	if (do_sync) {
		op++;
		op->op = cpu_to_le16(CEPH_OSD_OP_STARTSYNC);
	}
	if (snapc) {
		head->snap_seq = cpu_to_le64(snapc->seq);
		head->num_snaps = cpu_to_le32(snapc->num_snaps);
		for (i = 0; i < snapc->num_snaps; i++) {
			put_unaligned_le64(snapc->snaps[i], p);
			p += sizeof(u64);
		}
	}

	BUG_ON(p > msg->front.iov_base + msg->front.iov_len);
	msg_size = p - msg->front.iov_base;
	msg->front.iov_len = msg_size;
	msg->hdr.front_len = cpu_to_le32(msg_size);
	return req;
}
예제 #5
0
/*
 * Calc the layout of all siblings
 * If they have children, do those first
 */
static void calc_layout(LAYOUT *layout)
{
    int width, height;
    int width_common, height_common;
    int direction;
    LAYOUT *tmp;

    direction = layout->direction;
    layout->x = layout->borderx;
    layout->y = layout->border_top;
    tmp = layout;
  
    if (layout->child)
        calc_layout(layout->child);
    width_common  = layout->width;
    height_common = layout->height;
    while (layout->next) {
        if (layout->next->child)
            calc_layout(layout->next->child);
        if (direction == PACK_HORIZONTAL) {
            layout->next->x = layout->x + layout->width + layout->marginx;
            layout->next->y = layout->y;
        }
        else {
            layout->next->x = layout->x;
            layout->next->y = layout->y + layout->height + layout->marginy;
        }
        width_common    = max(width_common, layout->next->width);
        height_common   = max(height_common, layout->next->height);
        layout = layout->next;
    }

    if (direction == PACK_HORIZONTAL) {
        LAYOUT *tmp2 = tmp;
        if (tmp->flag & GRID_X) {
            int old_x;

            old_x = tmp->x;
            tmp->width = width_common;
            while (tmp->next) {
                tmp = tmp->next;
                tmp->width = width_common;
                tmp->x = old_x + width_common + layout->marginx;
                old_x = tmp->x;
            } 
        }
        tmp = tmp2;
        if (tmp->flag & GRID_Y) {
            tmp->height = height_common;
            while (tmp->next) {
                tmp = tmp->next;
                tmp->height = height_common;
            } 
        }
        width  = layout->x + layout->width + layout->borderx;
        height = height_common + layout->border_top + layout->border_bottom;
    }
    else {
        LAYOUT *tmp2 = tmp;
        if (tmp->flag & GRID_Y) {
            int old_y;

            old_y = tmp->y;
            tmp->height = height_common;
            while (tmp->next) {
                tmp = tmp->next;
                tmp->height = height_common;
                tmp->y = old_y + height_common + layout->marginy;
                old_y = tmp->y;
            } 
        }
        tmp = tmp2;
        if (tmp->flag & GRID_X) {
            tmp->width = width_common;
            while (tmp->next) {
                tmp = tmp->next;
                tmp->width = width_common;
            } 
        }
        width = width_common + 2 * layout->borderx;
        height = layout->y + layout->height + layout->border_bottom;
    }

    /*
     * Update parents, and grand parents
     */
    while (layout->parent) {
        layout->parent->width  = max(layout->parent->width, width);
        layout->parent->height = max(layout->parent->height, height);
        layout = layout->parent;
        if (layout->direction == PACK_HORIZONTAL) {
            height +=  layout->border_top + layout->border_bottom;
        }
        else {
            width += 2 * layout->borderx;
        }
    }
}