<commit_before>#include <linux/ceph/ceph_debug.h>

#include <linux/module.h>
#include <linux/err.h>
#include <linux/highmem.h>
#include <linux/mm.h>
#include <linux/pagemap.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#ifdef CONFIG_BLOCK
#include <linux/bio.h>
#endif

#include <linux/ceph/libceph.h>
#include <linux/ceph/osd_client.h>
#include <linux/ceph/messenger.h>
#include <linux/ceph/decode.h>
#include <linux/ceph/auth.h>
#include <linux/ceph/pagelist.h>

#define OSD_OP_FRONT_LEN	4096
#define OSD_OPREPLY_FRONT_LEN	512

static const struct ceph_connection_operations osd_con_ops;

static void send_queued(struct ceph_osd_client *osdc);
static int __reset_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd);
static void __register_request(struct ceph_osd_client *osdc,
			       struct ceph_osd_request *req);
static void __unregister_linger_request(struct ceph_osd_client *osdc,
					struct ceph_osd_request *req);
static void __send_request(struct ceph_osd_client *osdc,
			   struct ceph_osd_request *req);

static int op_needs_trail(int op)
{
	switch (op) {
	case CEPH_OSD_OP_GETXATTR:
	case CEPH_OSD_OP_SETXATTR:
	case CEPH_OSD_OP_CMPXATTR:
	case CEPH_OSD_OP_CALL:
	case CEPH_OSD_OP_NOTIFY:
		return 1;
	default:
		return 0;
	}
}

static int op_has_extent(int op)
{
	return (op == CEPH_OSD_OP_READ ||
		op == CEPH_OSD_OP_WRITE);
}

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);

}
EXPORT_SYMBOL(ceph_calc_raw_layout);

/*
 * Implement client access to distributed object storage cluster.
 *
 * All data objects are stored within a cluster/cloud of OSDs, or
 * "object storage devices."  (Note that Ceph OSDs have _nothing_ to
 * do with the T10 OSD extensions to SCSI.)  Ceph OSDs are simply
 * remote daemons serving up and coordinating consistent and safe
 * access to storage.
 *
 * Cluster membership and the mapping of data objects onto storage devices
 * are described by the osd map.
 *
 * We keep track of pending OSD requests (read, write), resubmit
 * requests to different OSDs when the cluster topology/data layout
 * change, or retry the affected requests when the communications
 * channel with an OSD is reset.
 */

/*
 * 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_req_op *op)
{
	u64 bno;

	ceph_calc_raw_layout(osdc, layout, vino.snap, off,
			     plen, &bno, req, op);

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

/*
 * requests
 */
void ceph_osdc_release_request(struct kref *kref)
{
	struct ceph_osd_request *req = container_of(kref,
						    struct ceph_osd_request,
						    r_kref);

	if (req->r_request)
		ceph_msg_put(req->r_request);
	if (req->r_reply)
		ceph_msg_put(req->r_reply);
	if (req->r_con_filling_msg) {
		dout("release_request revoking pages %p from con %p\n",
		     req->r_pages, req->r_con_filling_msg);
		ceph_con_revoke_message(req->r_con_filling_msg,
				      req->r_reply);
		ceph_con_put(req->r_con_filling_msg);
	}
	if (req->r_own_pages)
		ceph_release_page_vector(req->r_pages,
					 req->r_num_pages);
#ifdef CONFIG_BLOCK
	if (req->r_bio)
		bio_put(req->r_bio);
#endif
	ceph_put_snap_context(req->r_snapc);
	if (req->r_trail) {
		ceph_pagelist_release(req->r_trail);
		kfree(req->r_trail);
	}
	if (req->r_mempool)
		mempool_free(req, req->r_osdc->req_mempool);
	else
		kfree(req);
}
EXPORT_SYMBOL(ceph_osdc_release_request);

static int get_num_ops(struct ceph_osd_req_op *ops, int *needs_trail)
{
	int i = 0;

	if (needs_trail)<commit_msg>libceph: osd_client: don't drop reply reference too early<commit_after>#include <linux/ceph/ceph_debug.h>

#include <linux/module.h>
#include <linux/err.h>
#include <linux/highmem.h>
#include <linux/mm.h>
#include <linux/pagemap.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#ifdef CONFIG_BLOCK
#include <linux/bio.h>
#endif

#include <linux/ceph/libceph.h>
#include <linux/ceph/osd_client.h>
#include <linux/ceph/messenger.h>
#include <linux/ceph/decode.h>
#include <linux/ceph/auth.h>
#include <linux/ceph/pagelist.h>

#define OSD_OP_FRONT_LEN	4096
#define OSD_OPREPLY_FRONT_LEN	512

static const struct ceph_connection_operations osd_con_ops;

static void send_queued(struct ceph_osd_client *osdc);
static int __reset_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd);
static void __register_request(struct ceph_osd_client *osdc,
			       struct ceph_osd_request *req);
static void __unregister_linger_request(struct ceph_osd_client *osdc,
					struct ceph_osd_request *req);
static void __send_request(struct ceph_osd_client *osdc,
			   struct ceph_osd_request *req);

static int op_needs_trail(int op)
{
	switch (op) {
	case CEPH_OSD_OP_GETXATTR:
	case CEPH_OSD_OP_SETXATTR:
	case CEPH_OSD_OP_CMPXATTR:
	case CEPH_OSD_OP_CALL:
	case CEPH_OSD_OP_NOTIFY:
		return 1;
	default:
		return 0;
	}
}

static int op_has_extent(int op)
{
	return (op == CEPH_OSD_OP_READ ||
		op == CEPH_OSD_OP_WRITE);
}

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);

}
EXPORT_SYMBOL(ceph_calc_raw_layout);

/*
 * Implement client access to distributed object storage cluster.
 *
 * All data objects are stored within a cluster/cloud of OSDs, or
 * "object storage devices."  (Note that Ceph OSDs have _nothing_ to
 * do with the T10 OSD extensions to SCSI.)  Ceph OSDs are simply
 * remote daemons serving up and coordinating consistent and safe
 * access to storage.
 *
 * Cluster membership and the mapping of data objects onto storage devices
 * are described by the osd map.
 *
 * We keep track of pending OSD requests (read, write), resubmit
 * requests to different OSDs when the cluster topology/data layout
 * change, or retry the affected requests when the communications
 * channel with an OSD is reset.
 */

/*
 * 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_req_op *op)
{
	u64 bno;

	ceph_calc_raw_layout(osdc, layout, vino.snap, off,
			     plen, &bno, req, op);

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

/*
 * requests
 */
void ceph_osdc_release_request(struct kref *kref)
{
	struct ceph_osd_request *req = container_of(kref,
						    struct ceph_osd_request,
						    r_kref);

	if (req->r_request)
		ceph_msg_put(req->r_request);
	if (req->r_con_filling_msg) {
		dout("release_request revoking pages %p from con %p\n",
		     req->r_pages, req->r_con_filling_msg);
		ceph_con_revoke_message(req->r_con_filling_msg,
				      req->r_reply);
		ceph_con_put(req->r_con_filling_msg);
	}
	if (req->r_reply)
		ceph_msg_put(req->r_reply);
	if (req->r_own_pages)
		ceph_release_page_vector(req->r_pages,
					 req->r_num_pages);
#ifdef CONFIG_BLOCK
	if (req->r_bio)
		bio_put(req->r_bio);
#endif
	ceph_put_snap_context(req->r_snapc);
	if (req->r_trail) {
		ceph_pagelist_release(req->r_trail);
		kfree(req->r_trail);
	}
	if (req->r_mempool)
		mempool_free(req, req->r_osdc->req_mempool);
	else
		kfree(req);
}
EXPORT_SYMBOL(ceph_osdc_release_request);

static int get_num_ops(struct ceph_osd_req_op *ops, int *needs_trail)
{
	int i = 0;

	if (needs_trail)
{'fraction_non_alphanumeric': 0.11219155165202845, 'fraction_numerical': 0.007109995817649519, 'mean_word_length': 4.528901734104046, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 107, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '881186', 'n_tokens_mistral': 4025, 'n_tokens_neox': 3776, 'n_words': 880}