162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * This file contains all the stubs needed when communicating with lockd.
462306a36Sopenharmony_ci * This level of indirection is necessary so we can run nfsd+lockd without
562306a36Sopenharmony_ci * requiring the nfs client to be compiled in/loaded, and vice versa.
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/file.h>
1162306a36Sopenharmony_ci#include <linux/lockd/bind.h>
1262306a36Sopenharmony_ci#include "nfsd.h"
1362306a36Sopenharmony_ci#include "vfs.h"
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#define NFSDDBG_FACILITY		NFSDDBG_LOCKD
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#ifdef CONFIG_LOCKD_V4
1862306a36Sopenharmony_ci#define nlm_stale_fh	nlm4_stale_fh
1962306a36Sopenharmony_ci#define nlm_failed	nlm4_failed
2062306a36Sopenharmony_ci#else
2162306a36Sopenharmony_ci#define nlm_stale_fh	nlm_lck_denied_nolocks
2262306a36Sopenharmony_ci#define nlm_failed	nlm_lck_denied_nolocks
2362306a36Sopenharmony_ci#endif
2462306a36Sopenharmony_ci/*
2562306a36Sopenharmony_ci * Note: we hold the dentry use count while the file is open.
2662306a36Sopenharmony_ci */
2762306a36Sopenharmony_cistatic __be32
2862306a36Sopenharmony_cinlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp,
2962306a36Sopenharmony_ci		int mode)
3062306a36Sopenharmony_ci{
3162306a36Sopenharmony_ci	__be32		nfserr;
3262306a36Sopenharmony_ci	int		access;
3362306a36Sopenharmony_ci	struct svc_fh	fh;
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	/* must initialize before using! but maxsize doesn't matter */
3662306a36Sopenharmony_ci	fh_init(&fh,0);
3762306a36Sopenharmony_ci	fh.fh_handle.fh_size = f->size;
3862306a36Sopenharmony_ci	memcpy(&fh.fh_handle.fh_raw, f->data, f->size);
3962306a36Sopenharmony_ci	fh.fh_export = NULL;
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	access = (mode == O_WRONLY) ? NFSD_MAY_WRITE : NFSD_MAY_READ;
4262306a36Sopenharmony_ci	access |= NFSD_MAY_LOCK;
4362306a36Sopenharmony_ci	nfserr = nfsd_open(rqstp, &fh, S_IFREG, access, filp);
4462306a36Sopenharmony_ci	fh_put(&fh);
4562306a36Sopenharmony_ci 	/* We return nlm error codes as nlm doesn't know
4662306a36Sopenharmony_ci	 * about nfsd, but nfsd does know about nlm..
4762306a36Sopenharmony_ci	 */
4862306a36Sopenharmony_ci	switch (nfserr) {
4962306a36Sopenharmony_ci	case nfs_ok:
5062306a36Sopenharmony_ci		return 0;
5162306a36Sopenharmony_ci	case nfserr_dropit:
5262306a36Sopenharmony_ci		return nlm_drop_reply;
5362306a36Sopenharmony_ci	case nfserr_stale:
5462306a36Sopenharmony_ci		return nlm_stale_fh;
5562306a36Sopenharmony_ci	default:
5662306a36Sopenharmony_ci		return nlm_failed;
5762306a36Sopenharmony_ci	}
5862306a36Sopenharmony_ci}
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_cistatic void
6162306a36Sopenharmony_cinlm_fclose(struct file *filp)
6262306a36Sopenharmony_ci{
6362306a36Sopenharmony_ci	fput(filp);
6462306a36Sopenharmony_ci}
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_cistatic const struct nlmsvc_binding nfsd_nlm_ops = {
6762306a36Sopenharmony_ci	.fopen		= nlm_fopen,		/* open file for locking */
6862306a36Sopenharmony_ci	.fclose		= nlm_fclose,		/* close file */
6962306a36Sopenharmony_ci};
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_civoid
7262306a36Sopenharmony_cinfsd_lockd_init(void)
7362306a36Sopenharmony_ci{
7462306a36Sopenharmony_ci	dprintk("nfsd: initializing lockd\n");
7562306a36Sopenharmony_ci	nlmsvc_ops = &nfsd_nlm_ops;
7662306a36Sopenharmony_ci}
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_civoid
7962306a36Sopenharmony_cinfsd_lockd_shutdown(void)
8062306a36Sopenharmony_ci{
8162306a36Sopenharmony_ci	nlmsvc_ops = NULL;
8262306a36Sopenharmony_ci}
83