net/9p/client.c

Source file repositories/reference/linux-study-clean/net/9p/client.c

File Facts

System
Linux kernel
Corpus path
net/9p/client.c
Extension
.c
Size
53560 bytes
Lines
2213
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

if (!fc->sdata && c->trans_mod->supports_vmalloc) {
			fc->sdata = kvmalloc(alloc_msize, GFP_NOFS);
			fc->cache = NULL;
		}
	} else {
		if (c->trans_mod->supports_vmalloc)
			fc->sdata = kvmalloc(alloc_msize, GFP_NOFS);
		else
			fc->sdata = kmalloc(alloc_msize, GFP_NOFS);
		fc->cache = NULL;
	}
	if (!fc->sdata)
		return -ENOMEM;
	fc->capacity = alloc_msize;
	fc->id = 0;
	fc->tag = P9_NOTAG;
	return 0;
}

void p9_fcall_fini(struct p9_fcall *fc)
{
	/* sdata can be NULL for interrupted requests in trans_rdma,
	 * and kmem_cache_free does not do NULL-check for us
	 */
	if (unlikely(!fc->sdata))
		return;

	if (fc->cache)
		kmem_cache_free(fc->cache, fc->sdata);
	else
		kvfree(fc->sdata);
}
EXPORT_SYMBOL(p9_fcall_fini);

static struct kmem_cache *p9_req_cache;

/**
 * p9_tag_alloc - Allocate a new request.
 * @c: Client session.
 * @type: Transaction type.
 * @t_size: Buffer size for holding this request
 * (automatic calculation by format template if 0).
 * @r_size: Buffer size for holding server's reply on this request
 * (automatic calculation by format template if 0).
 * @fmt: Format template for assembling 9p request message
 * (see p9pdu_vwritef).
 * @ap: Variable arguments to be fed to passed format template
 * (see p9pdu_vwritef).
 *
 * Context: Process context.
 * Return: Pointer to new request.
 */
static struct p9_req_t *
p9_tag_alloc(struct p9_client *c, int8_t type, uint t_size, uint r_size,
	      const char *fmt, va_list ap)
{
	struct p9_req_t *req = kmem_cache_alloc(p9_req_cache, GFP_NOFS);
	int alloc_tsize;
	int alloc_rsize;
	int tag;
	va_list apc;

	va_copy(apc, ap);
	alloc_tsize = min_t(size_t, c->msize,
			    t_size ?: p9_msg_buf_size(c, type, fmt, apc));
	va_end(apc);

	alloc_rsize = min_t(size_t, c->msize,
			    r_size ?: p9_msg_buf_size(c, type + 1, fmt, ap));

	if (!req)
		return ERR_PTR(-ENOMEM);

	if (p9_fcall_init(c, &req->tc, alloc_tsize))
		goto free_req;
	if (p9_fcall_init(c, &req->rc, alloc_rsize))
		goto free;

	p9pdu_reset(&req->tc);
	p9pdu_reset(&req->rc);
	req->t_err = 0;
	req->status = REQ_STATUS_ALLOC;
	/* refcount needs to be set to 0 before inserting into the idr
	 * so p9_tag_lookup does not accept a request that is not fully
	 * initialized. refcount_set to 2 below will mark request ready.
	 */
	refcount_set(&req->refcount, 0);
	init_waitqueue_head(&req->wq);
	INIT_LIST_HEAD(&req->req_list);

Annotation

Implementation Notes