1249592Sken/*-
2249592Sken * Copyright (c) 2008 Isilon Inc http://www.isilon.com/
3249592Sken * Copyright (c) 2013 Spectra Logic Corporation
4249592Sken *
5249592Sken * Redistribution and use in source and binary forms, with or without
6249592Sken * modification, are permitted provided that the following conditions
7249592Sken * are met:
8249592Sken * 1. Redistributions of source code must retain the above copyright
9249592Sken *    notice, this list of conditions and the following disclaimer.
10249592Sken * 2. Redistributions in binary form must reproduce the above copyright
11249592Sken *    notice, this list of conditions and the following disclaimer in the
12249592Sken *    documentation and/or other materials provided with the distribution.
13249592Sken *
14249592Sken * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15249592Sken * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16249592Sken * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17249592Sken * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18249592Sken * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19249592Sken * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20249592Sken * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21249592Sken * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22249592Sken * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23249592Sken * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24249592Sken * SUCH DAMAGE.
25249592Sken */
26249592Sken
27249592Sken#include <sys/cdefs.h>
28249592Sken__FBSDID("$FreeBSD$");
29249592Sken
30249592Sken#include <sys/param.h>
31249592Sken#include <sys/systm.h>
32249592Sken#include <sys/sysproto.h>
33249592Sken#include <sys/kernel.h>
34249592Sken#include <sys/vnode.h>
35249592Sken#include <sys/malloc.h>
36249592Sken#include <sys/mount.h>
37249592Sken#include <sys/mbuf.h>
38249592Sken#include <sys/sysctl.h>
39249592Sken
40249592Sken#include <rpc/rpc.h>
41249592Sken#include <nfs/xdr_subs.h>
42249592Sken#include <nfs/nfsproto.h>
43251641Sken#include <nfs/nfs_fha.h>
44249592Sken#include <nfsserver/nfs.h>
45249592Sken#include <nfsserver/nfsm_subs.h>
46249592Sken#include <nfsserver/nfs_fha_old.h>
47249592Sken
48249592Skenstatic void fhaold_init(void *foo);
49249592Skenstatic void fhaold_uninit(void *foo);
50249592Skenrpcproc_t fhaold_get_procnum(rpcproc_t procnum);
51249592Skenint fhaold_realign(struct mbuf **mb, int malloc_flags);
52261061Smavint fhaold_get_fh(uint64_t *fh, int v3, struct mbuf **md, caddr_t *dpos);
53249592Skenint fhaold_is_read(rpcproc_t procnum);
54249592Skenint fhaold_is_write(rpcproc_t procnum);
55249592Skenint fhaold_get_offset(struct mbuf **md, caddr_t *dpos, int v3,
56249592Sken		      struct fha_info *info);
57249592Skenint fhaold_no_offset(rpcproc_t procnum);
58249592Skenvoid fhaold_set_locktype(rpcproc_t procnum, struct fha_info *info);
59249592Skenstatic int fheold_stats_sysctl(SYSCTL_HANDLER_ARGS);
60249592Sken
61249592Skenstatic struct fha_params fhaold_softc;
62249592Sken
63249592SkenSYSCTL_DECL(_vfs_nfsrv);
64249592Sken
65249592Skenextern SVCPOOL *nfsrv_pool;
66249592Sken
67249592SkenSYSINIT(nfs_fhaold, SI_SUB_ROOT_CONF, SI_ORDER_ANY, fhaold_init, NULL);
68249592SkenSYSUNINIT(nfs_fhaold, SI_SUB_ROOT_CONF, SI_ORDER_ANY, fhaold_uninit, NULL);
69249592Sken
70249592Skenstatic void
71249592Skenfhaold_init(void *foo)
72249592Sken{
73249592Sken	struct fha_params *softc;
74249592Sken
75249592Sken	softc = &fhaold_softc;
76249592Sken
77249592Sken	bzero(softc, sizeof(*softc));
78249592Sken
79249592Sken	/*
80249592Sken	 * Setup the callbacks for this FHA personality.
81249592Sken	 */
82249592Sken	softc->callbacks.get_procnum = fhaold_get_procnum;
83249592Sken	softc->callbacks.realign = fhaold_realign;
84249592Sken	softc->callbacks.get_fh = fhaold_get_fh;
85249592Sken	softc->callbacks.is_read = fhaold_is_read;
86249592Sken	softc->callbacks.is_write = fhaold_is_write;
87249592Sken	softc->callbacks.get_offset = fhaold_get_offset;
88249592Sken	softc->callbacks.no_offset = fhaold_no_offset;
89249592Sken	softc->callbacks.set_locktype = fhaold_set_locktype;
90249592Sken	softc->callbacks.fhe_stats_sysctl = fheold_stats_sysctl;
91249592Sken
92249592Sken	snprintf(softc->server_name, sizeof(softc->server_name),
93249592Sken	    FHAOLD_SERVER_NAME);
94249592Sken
95249592Sken	softc->pool = &nfsrv_pool;
96249592Sken
97249592Sken	/*
98249592Sken	 * Initialize the sysctl context list for the fha module.
99249592Sken	 */
100249592Sken	sysctl_ctx_init(&softc->sysctl_ctx);
101249592Sken	softc->sysctl_tree = SYSCTL_ADD_NODE(&softc->sysctl_ctx,
102249592Sken	    SYSCTL_STATIC_CHILDREN(_vfs_nfsrv), OID_AUTO, "fha", CTLFLAG_RD,
103249592Sken	    0, "fha node");
104249592Sken	if (softc->sysctl_tree == NULL) {
105249592Sken		printf("%s: unable to allocate sysctl tree\n", __func__);
106249592Sken		return;
107249592Sken	}
108249592Sken	fha_init(softc);
109249592Sken}
110249592Sken
111249592Skenstatic void
112249592Skenfhaold_uninit(void *foo)
113249592Sken{
114249592Sken	struct fha_params *softc;
115249592Sken
116249592Sken	softc = &fhaold_softc;
117249592Sken
118249592Sken	fha_uninit(softc);
119249592Sken}
120249592Sken
121249592Sken
122249592Skenrpcproc_t
123249592Skenfhaold_get_procnum(rpcproc_t procnum)
124249592Sken{
125249592Sken	if (procnum > NFSV2PROC_STATFS)
126249592Sken		return (-1);
127249592Sken
128249592Sken	return (nfsrv_nfsv3_procid[procnum]);
129249592Sken}
130249592Sken
131249592Skenint
132249592Skenfhaold_realign(struct mbuf **mb, int malloc_flags)
133249592Sken{
134249592Sken	return (nfs_realign(mb, malloc_flags));
135249592Sken}
136249592Sken
137249592Skenint
138261061Smavfhaold_get_fh(uint64_t *fh, int v3, struct mbuf **md, caddr_t *dpos)
139249592Sken{
140261061Smav	u_int32_t *tl;
141261061Smav	uint8_t *buf;
142261061Smav	uint64_t t;
143261061Smav	int fhlen, i;
144261061Smav
145261061Smav	if (v3) {
146261061Smav		tl = nfsm_dissect_xx_nonblock(NFSX_UNSIGNED, md, dpos);
147261061Smav		if (tl == NULL)
148261061Smav			return EBADRPC;
149261061Smav		fhlen = fxdr_unsigned(int, *tl);
150261061Smav		if (fhlen != 0 && fhlen != NFSX_V3FH)
151261061Smav			return EBADRPC;
152261061Smav	} else {
153261061Smav		fhlen = NFSX_V2FH;
154261061Smav	}
155261061Smav	t = 0;
156261061Smav	if (fhlen != 0) {
157261061Smav		buf = nfsm_dissect_xx_nonblock(fhlen, md, dpos);
158261061Smav		if (buf == NULL)
159261061Smav			return EBADRPC;
160261061Smav		for (i = 0; i < fhlen; i++)
161261061Smav			t ^= ((uint64_t)buf[i] << (i & 7) * 8);
162261061Smav	}
163261061Smav	*fh = t;
164261061Smav	return 0;
165249592Sken}
166249592Sken
167249592Skenint
168249592Skenfhaold_is_read(rpcproc_t procnum)
169249592Sken{
170249592Sken	if (procnum == NFSPROC_READ)
171249592Sken		return (1);
172249592Sken	else
173249592Sken		return (0);
174249592Sken}
175249592Sken
176249592Skenint
177249592Skenfhaold_is_write(rpcproc_t procnum)
178249592Sken{
179249592Sken	if (procnum == NFSPROC_WRITE)
180249592Sken		return (1);
181249592Sken	else
182249592Sken		return (0);
183249592Sken}
184249592Sken
185249592Skenint
186249592Skenfhaold_get_offset(struct mbuf **md, caddr_t *dpos, int v3,
187249592Sken		  struct fha_info *info)
188249592Sken{
189249592Sken	uint32_t *tl;
190249592Sken
191249592Sken	if (v3) {
192249592Sken		tl = nfsm_dissect_xx_nonblock(2 * NFSX_UNSIGNED, md, dpos);
193249592Sken		if (tl == NULL)
194249592Sken			goto out;
195249592Sken		info->offset = fxdr_hyper(tl);
196249592Sken	} else {
197249592Sken		tl = nfsm_dissect_xx_nonblock(NFSX_UNSIGNED, md, dpos);
198249592Sken		if (tl == NULL)
199249592Sken			goto out;
200249592Sken		info->offset = fxdr_unsigned(uint32_t, *tl);
201249592Sken	}
202249592Sken
203249592Sken	return (0);
204249592Skenout:
205249592Sken	return (-1);
206249592Sken}
207249592Sken
208249592Skenint
209249592Skenfhaold_no_offset(rpcproc_t procnum)
210249592Sken{
211249592Sken	if (procnum == NFSPROC_FSSTAT ||
212249592Sken	    procnum == NFSPROC_FSINFO ||
213249592Sken	    procnum == NFSPROC_PATHCONF ||
214249592Sken	    procnum == NFSPROC_NOOP ||
215249592Sken	    procnum == NFSPROC_NULL)
216249592Sken		return (1);
217249592Sken	else
218249592Sken		return (0);
219249592Sken}
220249592Sken
221249592Skenvoid
222249592Skenfhaold_set_locktype(rpcproc_t procnum, struct fha_info *info)
223249592Sken{
224249592Sken	switch (procnum) {
225249592Sken	case NFSPROC_NULL:
226249592Sken	case NFSPROC_GETATTR:
227249592Sken	case NFSPROC_LOOKUP:
228249592Sken	case NFSPROC_ACCESS:
229249592Sken	case NFSPROC_READLINK:
230249592Sken	case NFSPROC_READ:
231249592Sken	case NFSPROC_READDIR:
232249592Sken	case NFSPROC_READDIRPLUS:
233249592Sken	case NFSPROC_WRITE:
234249592Sken		info->locktype = LK_SHARED;
235249592Sken		break;
236249592Sken	case NFSPROC_SETATTR:
237249592Sken	case NFSPROC_CREATE:
238249592Sken	case NFSPROC_MKDIR:
239249592Sken	case NFSPROC_SYMLINK:
240249592Sken	case NFSPROC_MKNOD:
241249592Sken	case NFSPROC_REMOVE:
242249592Sken	case NFSPROC_RMDIR:
243249592Sken	case NFSPROC_RENAME:
244249592Sken	case NFSPROC_LINK:
245249592Sken	case NFSPROC_FSSTAT:
246249592Sken	case NFSPROC_FSINFO:
247249592Sken	case NFSPROC_PATHCONF:
248249592Sken	case NFSPROC_COMMIT:
249249592Sken	case NFSPROC_NOOP:
250249592Sken		info->locktype = LK_EXCLUSIVE;
251249592Sken		break;
252249592Sken	}
253249592Sken}
254249592Sken
255249592Skenstatic int
256249592Skenfheold_stats_sysctl(SYSCTL_HANDLER_ARGS)
257249592Sken{
258249592Sken	return (fhe_stats_sysctl(oidp, arg1, arg2, req, &fhaold_softc));
259249592Sken}
260249592Sken
261249592SkenSVCTHREAD *
262249592Skenfhaold_assign(SVCTHREAD *this_thread, struct svc_req *req)
263249592Sken{
264249592Sken	return (fha_assign(this_thread, req, &fhaold_softc));
265249592Sken}
266