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); }
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; }
/* * 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; }
/* * 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; } } }