fs/nfs/callback.c

Source file repositories/reference/linux-study-clean/fs/nfs/callback.c

File Facts

System
Linux kernel
Corpus path
fs/nfs/callback.c
Extension
.c
Size
8679 bytes
Lines
354
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

struct nfs_callback_data {
	unsigned int users;
	struct svc_serv *serv;
};

static struct nfs_callback_data nfs_callback_info[NFS4_MAX_MINOR_VERSION + 1];
static DEFINE_MUTEX(nfs_callback_mutex);
static struct svc_program nfs4_callback_program;

static int nfs4_callback_up_net(struct svc_serv *serv, struct net *net)
{
	const struct cred *cred = current_cred();
	int ret;
	struct nfs_net *nn = net_generic(net, nfs_net_id);

	ret = svc_xprt_create(serv, "tcp", net, PF_INET,
			      nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS,
			      cred);
	if (ret <= 0)
		goto out_err;
	nn->nfs_callback_tcpport = ret;
	dprintk("NFS: Callback listener port = %u (af %u, net %x)\n",
		nn->nfs_callback_tcpport, PF_INET, net->ns.inum);

	ret = svc_xprt_create(serv, "tcp", net, PF_INET6,
			      nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS,
			      cred);
	if (ret > 0) {
		nn->nfs_callback_tcpport6 = ret;
		dprintk("NFS: Callback listener port = %u (af %u, net %x)\n",
			nn->nfs_callback_tcpport6, PF_INET6, net->ns.inum);
	} else if (ret != -EAFNOSUPPORT)
		goto out_err;
	return 0;

out_err:
	return (ret) ? ret : -ENOMEM;
}

/*
 * This is the NFSv4 callback kernel thread.
 */
static int
nfs4_callback_svc(void *vrqstp)
{
	struct svc_rqst *rqstp = vrqstp;

	svc_thread_init_status(rqstp, 0);

	set_freezable();

	while (!svc_thread_should_stop(rqstp))
		svc_recv(rqstp, 0);

	svc_exit_thread(rqstp);
	return 0;
}

static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt,
		struct svc_serv *serv)
{
	if (minorversion)
		/*
		 * Save the svc_serv in the transport so that it can
		 * be referenced when the session backchannel is initialized
		 */
		xprt->bc_serv = serv;
}

static int nfs_callback_start_svc(int minorversion, struct rpc_xprt *xprt,
				  struct svc_serv *serv)
{
	int nrservs = nfs_callback_nr_threads;
	int ret;

	nfs_callback_bc_serv(minorversion, xprt, serv);

	if (nrservs < NFS4_MIN_NR_CALLBACK_THREADS)
		nrservs = NFS4_MIN_NR_CALLBACK_THREADS;

	if (serv->sv_nrthreads == nrservs)
		return 0;

	ret = svc_set_num_threads(serv, 0, nrservs);
	if (ret) {
		svc_set_num_threads(serv, 0, 0);
		return ret;
	}
	dprintk("nfs_callback_up: service started\n");
	return 0;

Annotation

Implementation Notes