struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc, int flags, struct ceph_snap_context *snapc, struct ceph_osd_req_op *ops, bool use_mempool, gfp_t gfp_flags, struct page **pages, struct bio *bio) { struct ceph_osd_request *req; struct ceph_msg *msg; int needs_trail; int num_op = get_num_ops(ops, &needs_trail); size_t msg_size = sizeof(struct ceph_osd_request_head); msg_size += num_op*sizeof(struct ceph_osd_op); if (use_mempool) { req = mempool_alloc(osdc->req_mempool, gfp_flags); memset(req, 0, sizeof(*req)); } else { req = kzalloc(sizeof(*req), gfp_flags); } 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); rb_init_node(&req->r_node); INIT_LIST_HEAD(&req->r_unsafe_item); INIT_LIST_HEAD(&req->r_linger_item); INIT_LIST_HEAD(&req->r_linger_osd); INIT_LIST_HEAD(&req->r_req_lru_item); INIT_LIST_HEAD(&req->r_osd_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_flags, true); if (!msg) { ceph_osdc_put_request(req); return NULL; } req->r_reply = msg; /* allocate space for the trailing data */ if (needs_trail) { req->r_trail = kmalloc(sizeof(struct ceph_pagelist), gfp_flags); if (!req->r_trail) { ceph_osdc_put_request(req); return NULL; } ceph_pagelist_init(req->r_trail); } /* create request message; allow space for oid */ msg_size += MAX_OBJ_NAME_SIZE; 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_flags, true); if (!msg) { ceph_osdc_put_request(req); return NULL; } memset(msg->front.iov_base, 0, msg->front.iov_len); req->r_request = msg; req->r_pages = pages; #ifdef CONFIG_BLOCK if (bio) { req->r_bio = bio; bio_get(req->r_bio); } #endif return req; }
int ceph_pre_init_acls(struct inode *dir, umode_t *mode, struct ceph_acls_info *info) { struct posix_acl *acl, *default_acl; size_t val_size1 = 0, val_size2 = 0; struct ceph_pagelist *pagelist = NULL; void *tmp_buf = NULL; int err; err = posix_acl_create(dir, mode, &default_acl, &acl); if (err) return err; if (acl) { int ret = posix_acl_equiv_mode(acl, mode); if (ret < 0) goto out_err; if (ret == 0) { posix_acl_release(acl); acl = NULL; } } if (!default_acl && !acl) return 0; if (acl) val_size1 = posix_acl_xattr_size(acl->a_count); if (default_acl) val_size2 = posix_acl_xattr_size(default_acl->a_count); err = -ENOMEM; tmp_buf = kmalloc(max(val_size1, val_size2), GFP_KERNEL); if (!tmp_buf) goto out_err; pagelist = kmalloc(sizeof(struct ceph_pagelist), GFP_KERNEL); if (!pagelist) goto out_err; ceph_pagelist_init(pagelist); err = ceph_pagelist_reserve(pagelist, PAGE_SIZE); if (err) goto out_err; ceph_pagelist_encode_32(pagelist, acl && default_acl ? 2 : 1); if (acl) { size_t len = strlen(XATTR_NAME_POSIX_ACL_ACCESS); err = ceph_pagelist_reserve(pagelist, len + val_size1 + 8); if (err) goto out_err; ceph_pagelist_encode_string(pagelist, XATTR_NAME_POSIX_ACL_ACCESS, len); err = posix_acl_to_xattr(&init_user_ns, acl, tmp_buf, val_size1); if (err < 0) goto out_err; ceph_pagelist_encode_32(pagelist, val_size1); ceph_pagelist_append(pagelist, tmp_buf, val_size1); } if (default_acl) { size_t len = strlen(XATTR_NAME_POSIX_ACL_DEFAULT); err = ceph_pagelist_reserve(pagelist, len + val_size2 + 8); if (err) goto out_err; err = ceph_pagelist_encode_string(pagelist, XATTR_NAME_POSIX_ACL_DEFAULT, len); err = posix_acl_to_xattr(&init_user_ns, default_acl, tmp_buf, val_size2); if (err < 0) goto out_err; ceph_pagelist_encode_32(pagelist, val_size2); ceph_pagelist_append(pagelist, tmp_buf, val_size2); } kfree(tmp_buf); info->acl = acl; info->default_acl = default_acl; info->pagelist = pagelist; return 0; out_err: posix_acl_release(acl); posix_acl_release(default_acl); kfree(tmp_buf); if (pagelist) ceph_pagelist_release(pagelist); return err; }