xref: /freebsd-src/sys/fs/p9fs/p9fs_subr.c (revision e97ad33a89a78f55280b0485b3249ee9b907a718)
1*e97ad33aSDoug Rabson /*-
2*e97ad33aSDoug Rabson  * Copyright (c) 2017 Juniper Networks, Inc.
3*e97ad33aSDoug Rabson  * All rights reserved.
4*e97ad33aSDoug Rabson  *
5*e97ad33aSDoug Rabson  * Redistribution and use in source and binary forms, with or without
6*e97ad33aSDoug Rabson  * modification, are permitted provided that the following conditions
7*e97ad33aSDoug Rabson  * are met:
8*e97ad33aSDoug Rabson  * 1. Redistributions of source code must retain the above copyright
9*e97ad33aSDoug Rabson  *    notice, this list of conditions and the following disclaimer.
10*e97ad33aSDoug Rabson  * 2. Redistributions in binary form must reproduce the above copyright
11*e97ad33aSDoug Rabson  *    notice, this list of conditions and the following disclaimer in the
12*e97ad33aSDoug Rabson  *    documentation and/or other materials provided with the distribution.
13*e97ad33aSDoug Rabson  *
14*e97ad33aSDoug Rabson  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15*e97ad33aSDoug Rabson  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16*e97ad33aSDoug Rabson  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17*e97ad33aSDoug Rabson  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18*e97ad33aSDoug Rabson  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19*e97ad33aSDoug Rabson  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20*e97ad33aSDoug Rabson  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21*e97ad33aSDoug Rabson  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22*e97ad33aSDoug Rabson  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23*e97ad33aSDoug Rabson  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24*e97ad33aSDoug Rabson  *
25*e97ad33aSDoug Rabson  */
26*e97ad33aSDoug Rabson /*-
27*e97ad33aSDoug Rabson  * 9P filesystem subroutines. This file consists of all the Non VFS subroutines.
28*e97ad33aSDoug Rabson  * It contains all of the functions related to the driver submission which form
29*e97ad33aSDoug Rabson  * the upper layer i.e, p9fs driver. This will interact with the client to make
30*e97ad33aSDoug Rabson  * sure we have correct API calls in the header.
31*e97ad33aSDoug Rabson  */
32*e97ad33aSDoug Rabson 
33*e97ad33aSDoug Rabson #include <sys/cdefs.h>
34*e97ad33aSDoug Rabson #include <sys/systm.h>
35*e97ad33aSDoug Rabson #include <sys/limits.h>
36*e97ad33aSDoug Rabson #include <sys/mount.h>
37*e97ad33aSDoug Rabson #include <sys/sysctl.h>
38*e97ad33aSDoug Rabson #include <sys/vnode.h>
39*e97ad33aSDoug Rabson 
40*e97ad33aSDoug Rabson #include "p9fs_proto.h"
41*e97ad33aSDoug Rabson 
42*e97ad33aSDoug Rabson #include <fs/p9fs/p9_client.h>
43*e97ad33aSDoug Rabson #include <fs/p9fs/p9_debug.h>
44*e97ad33aSDoug Rabson #include <fs/p9fs/p9_protocol.h>
45*e97ad33aSDoug Rabson #include <fs/p9fs/p9fs.h>
46*e97ad33aSDoug Rabson 
47*e97ad33aSDoug Rabson int
p9fs_proto_dotl(struct p9fs_session * vses)48*e97ad33aSDoug Rabson p9fs_proto_dotl(struct p9fs_session *vses)
49*e97ad33aSDoug Rabson {
50*e97ad33aSDoug Rabson 
51*e97ad33aSDoug Rabson 	return (vses->flags & P9FS_PROTO_2000L);
52*e97ad33aSDoug Rabson }
53*e97ad33aSDoug Rabson 
54*e97ad33aSDoug Rabson /* Initialize a p9fs session */
55*e97ad33aSDoug Rabson struct p9_fid *
p9fs_init_session(struct mount * mp,int * error)56*e97ad33aSDoug Rabson p9fs_init_session(struct mount *mp, int *error)
57*e97ad33aSDoug Rabson {
58*e97ad33aSDoug Rabson 	struct p9fs_session *vses;
59*e97ad33aSDoug Rabson 	struct p9fs_mount *virtmp;
60*e97ad33aSDoug Rabson 	struct p9_fid *fid;
61*e97ad33aSDoug Rabson 	char *access;
62*e97ad33aSDoug Rabson 
63*e97ad33aSDoug Rabson 	virtmp = VFSTOP9(mp);
64*e97ad33aSDoug Rabson 	vses = &virtmp->p9fs_session;
65*e97ad33aSDoug Rabson 	vses->uid = P9_NONUNAME;
66*e97ad33aSDoug Rabson 	vses->uname = P9_DEFUNAME;
67*e97ad33aSDoug Rabson 	vses->aname = P9_DEFANAME;
68*e97ad33aSDoug Rabson 
69*e97ad33aSDoug Rabson 	/*
70*e97ad33aSDoug Rabson 	 * Create the client structure. Call into the driver to create
71*e97ad33aSDoug Rabson 	 * driver structures for the actual IO transfer.
72*e97ad33aSDoug Rabson 	 */
73*e97ad33aSDoug Rabson 	vses->clnt = p9_client_create(mp, error, virtmp->mount_tag);
74*e97ad33aSDoug Rabson 
75*e97ad33aSDoug Rabson 	if (vses->clnt == NULL) {
76*e97ad33aSDoug Rabson 		P9_DEBUG(ERROR, "%s: p9_client_create failed\n", __func__);
77*e97ad33aSDoug Rabson 		return (NULL);
78*e97ad33aSDoug Rabson 	}
79*e97ad33aSDoug Rabson 	/*
80*e97ad33aSDoug Rabson 	 * Find the client version and cache the copy. We will use this copy
81*e97ad33aSDoug Rabson 	 * throughout FS layer.
82*e97ad33aSDoug Rabson 	 */
83*e97ad33aSDoug Rabson 	if (p9_is_proto_dotl(vses->clnt))
84*e97ad33aSDoug Rabson 		vses->flags |= P9FS_PROTO_2000L;
85*e97ad33aSDoug Rabson 	else if (p9_is_proto_dotu(vses->clnt))
86*e97ad33aSDoug Rabson 		vses->flags |= P9FS_PROTO_2000U;
87*e97ad33aSDoug Rabson 
88*e97ad33aSDoug Rabson 	/* Set the access mode */
89*e97ad33aSDoug Rabson 	access = vfs_getopts(mp->mnt_optnew, "access", error);
90*e97ad33aSDoug Rabson 	if (access == NULL)
91*e97ad33aSDoug Rabson 		vses->flags |= P9_ACCESS_USER;
92*e97ad33aSDoug Rabson 	else if (!strcmp(access, "any"))
93*e97ad33aSDoug Rabson 		vses->flags |= P9_ACCESS_ANY;
94*e97ad33aSDoug Rabson 	else if (!strcmp(access, "single"))
95*e97ad33aSDoug Rabson 		vses->flags |= P9_ACCESS_SINGLE;
96*e97ad33aSDoug Rabson 	else if (!strcmp(access, "user"))
97*e97ad33aSDoug Rabson 		vses->flags |= P9_ACCESS_USER;
98*e97ad33aSDoug Rabson 	else {
99*e97ad33aSDoug Rabson 		P9_DEBUG(ERROR, "%s: unknown access mode\n", __func__);
100*e97ad33aSDoug Rabson 		*error = EINVAL;
101*e97ad33aSDoug Rabson 		goto out;
102*e97ad33aSDoug Rabson 	}
103*e97ad33aSDoug Rabson 
104*e97ad33aSDoug Rabson 	*error = 0;
105*e97ad33aSDoug Rabson 	/* Attach with the backend host*/
106*e97ad33aSDoug Rabson 	fid = p9_client_attach(vses->clnt, NULL, vses->uname, P9_NONUNAME,
107*e97ad33aSDoug Rabson 	    vses->aname, error);
108*e97ad33aSDoug Rabson 	vses->mnt_fid = fid;
109*e97ad33aSDoug Rabson 
110*e97ad33aSDoug Rabson 	if (*error != 0) {
111*e97ad33aSDoug Rabson 		P9_DEBUG(ERROR, "%s: attach failed: %d\n", __func__, *error);
112*e97ad33aSDoug Rabson 		goto out;
113*e97ad33aSDoug Rabson 	}
114*e97ad33aSDoug Rabson 	P9_DEBUG(SUBR, "%s: attach successful fid :%p\n", __func__, fid);
115*e97ad33aSDoug Rabson 	fid->uid = vses->uid;
116*e97ad33aSDoug Rabson 
117*e97ad33aSDoug Rabson 	/* initialize the node list for the session */
118*e97ad33aSDoug Rabson 	STAILQ_INIT(&vses->virt_node_list);
119*e97ad33aSDoug Rabson 	P9FS_LOCK_INIT(vses);
120*e97ad33aSDoug Rabson 
121*e97ad33aSDoug Rabson 	P9_DEBUG(SUBR, "%s: INIT session successful\n", __func__);
122*e97ad33aSDoug Rabson 
123*e97ad33aSDoug Rabson 	return (fid);
124*e97ad33aSDoug Rabson out:
125*e97ad33aSDoug Rabson 	p9_client_destroy(vses->clnt);
126*e97ad33aSDoug Rabson 	return (NULL);
127*e97ad33aSDoug Rabson }
128*e97ad33aSDoug Rabson 
129*e97ad33aSDoug Rabson /* Begin to terminate a session */
130*e97ad33aSDoug Rabson void
p9fs_prepare_to_close(struct mount * mp)131*e97ad33aSDoug Rabson p9fs_prepare_to_close(struct mount *mp)
132*e97ad33aSDoug Rabson {
133*e97ad33aSDoug Rabson 	struct p9fs_session *vses;
134*e97ad33aSDoug Rabson 	struct p9fs_mount *vmp;
135*e97ad33aSDoug Rabson 	struct p9fs_node *np, *pnp, *tmp;
136*e97ad33aSDoug Rabson 
137*e97ad33aSDoug Rabson 	vmp = VFSTOP9(mp);
138*e97ad33aSDoug Rabson 	vses = &vmp->p9fs_session;
139*e97ad33aSDoug Rabson 
140*e97ad33aSDoug Rabson 	/* break the node->parent references */
141*e97ad33aSDoug Rabson 	STAILQ_FOREACH_SAFE(np, &vses->virt_node_list, p9fs_node_next, tmp) {
142*e97ad33aSDoug Rabson 		if (np->parent && np->parent != np) {
143*e97ad33aSDoug Rabson 			pnp = np->parent;
144*e97ad33aSDoug Rabson 			np->parent = NULL;
145*e97ad33aSDoug Rabson 			vrele(P9FS_NTOV(pnp));
146*e97ad33aSDoug Rabson 		}
147*e97ad33aSDoug Rabson 	}
148*e97ad33aSDoug Rabson 
149*e97ad33aSDoug Rabson 	/* We are about to teardown, we dont allow anything other than clunk after this.*/
150*e97ad33aSDoug Rabson 	p9_client_begin_disconnect(vses->clnt);
151*e97ad33aSDoug Rabson }
152*e97ad33aSDoug Rabson 
153*e97ad33aSDoug Rabson /* Shutdown a session */
154*e97ad33aSDoug Rabson void
p9fs_complete_close(struct mount * mp)155*e97ad33aSDoug Rabson p9fs_complete_close(struct mount *mp)
156*e97ad33aSDoug Rabson {
157*e97ad33aSDoug Rabson 	struct p9fs_session *vses;
158*e97ad33aSDoug Rabson 	struct p9fs_mount *vmp;
159*e97ad33aSDoug Rabson 
160*e97ad33aSDoug Rabson 	vmp = VFSTOP9(mp);
161*e97ad33aSDoug Rabson 	vses = &vmp->p9fs_session;
162*e97ad33aSDoug Rabson 
163*e97ad33aSDoug Rabson 	/* Finish the close*/
164*e97ad33aSDoug Rabson 	p9_client_disconnect(vses->clnt);
165*e97ad33aSDoug Rabson }
166*e97ad33aSDoug Rabson 
167*e97ad33aSDoug Rabson 
168*e97ad33aSDoug Rabson /* Call from unmount. Close the session. */
169*e97ad33aSDoug Rabson void
p9fs_close_session(struct mount * mp)170*e97ad33aSDoug Rabson p9fs_close_session(struct mount *mp)
171*e97ad33aSDoug Rabson {
172*e97ad33aSDoug Rabson 	struct p9fs_session *vses;
173*e97ad33aSDoug Rabson 	struct p9fs_mount *vmp;
174*e97ad33aSDoug Rabson 
175*e97ad33aSDoug Rabson 	vmp = VFSTOP9(mp);
176*e97ad33aSDoug Rabson 	vses = &vmp->p9fs_session;
177*e97ad33aSDoug Rabson 
178*e97ad33aSDoug Rabson 	p9fs_complete_close(mp);
179*e97ad33aSDoug Rabson 	/* Clean up the clnt structure. */
180*e97ad33aSDoug Rabson 	p9_client_destroy(vses->clnt);
181*e97ad33aSDoug Rabson 	P9FS_LOCK_DESTROY(vses);
182*e97ad33aSDoug Rabson 	P9_DEBUG(SUBR, "%s: Clean close session .\n", __func__);
183*e97ad33aSDoug Rabson }
184*e97ad33aSDoug Rabson 
185*e97ad33aSDoug Rabson /*
186*e97ad33aSDoug Rabson  * Remove all the fids of a particular type from a p9fs node
187*e97ad33aSDoug Rabson  * as well as destroy/clunk them.
188*e97ad33aSDoug Rabson  */
189*e97ad33aSDoug Rabson void
p9fs_fid_remove_all(struct p9fs_node * np,int leave_ofids)190*e97ad33aSDoug Rabson p9fs_fid_remove_all(struct p9fs_node *np, int leave_ofids)
191*e97ad33aSDoug Rabson {
192*e97ad33aSDoug Rabson 	struct p9_fid *fid, *tfid;
193*e97ad33aSDoug Rabson 
194*e97ad33aSDoug Rabson 	STAILQ_FOREACH_SAFE(fid, &np->vfid_list, fid_next, tfid) {
195*e97ad33aSDoug Rabson 		STAILQ_REMOVE(&np->vfid_list, fid, p9_fid, fid_next);
196*e97ad33aSDoug Rabson 		p9_client_clunk(fid);
197*e97ad33aSDoug Rabson 	}
198*e97ad33aSDoug Rabson 
199*e97ad33aSDoug Rabson 	if (!leave_ofids) {
200*e97ad33aSDoug Rabson 		STAILQ_FOREACH_SAFE(fid, &np->vofid_list, fid_next, tfid) {
201*e97ad33aSDoug Rabson 			STAILQ_REMOVE(&np->vofid_list, fid, p9_fid, fid_next);
202*e97ad33aSDoug Rabson 			p9_client_clunk(fid);
203*e97ad33aSDoug Rabson 		}
204*e97ad33aSDoug Rabson 	}
205*e97ad33aSDoug Rabson }
206*e97ad33aSDoug Rabson 
207*e97ad33aSDoug Rabson 
208*e97ad33aSDoug Rabson /* Remove a fid from its corresponding fid list */
209*e97ad33aSDoug Rabson void
p9fs_fid_remove(struct p9fs_node * np,struct p9_fid * fid,int fid_type)210*e97ad33aSDoug Rabson p9fs_fid_remove(struct p9fs_node *np, struct p9_fid *fid, int fid_type)
211*e97ad33aSDoug Rabson {
212*e97ad33aSDoug Rabson 
213*e97ad33aSDoug Rabson 	switch (fid_type) {
214*e97ad33aSDoug Rabson 	case VFID:
215*e97ad33aSDoug Rabson 		P9FS_VFID_LOCK(np);
216*e97ad33aSDoug Rabson 		STAILQ_REMOVE(&np->vfid_list, fid, p9_fid, fid_next);
217*e97ad33aSDoug Rabson 		P9FS_VFID_UNLOCK(np);
218*e97ad33aSDoug Rabson 		break;
219*e97ad33aSDoug Rabson 	case VOFID:
220*e97ad33aSDoug Rabson 		P9FS_VOFID_LOCK(np);
221*e97ad33aSDoug Rabson 		STAILQ_REMOVE(&np->vofid_list, fid, p9_fid, fid_next);
222*e97ad33aSDoug Rabson 		P9FS_VOFID_UNLOCK(np);
223*e97ad33aSDoug Rabson 		break;
224*e97ad33aSDoug Rabson 	}
225*e97ad33aSDoug Rabson }
226*e97ad33aSDoug Rabson 
227*e97ad33aSDoug Rabson /* Add a fid to the corresponding fid list */
228*e97ad33aSDoug Rabson void
p9fs_fid_add(struct p9fs_node * np,struct p9_fid * fid,int fid_type)229*e97ad33aSDoug Rabson p9fs_fid_add(struct p9fs_node *np, struct p9_fid *fid, int fid_type)
230*e97ad33aSDoug Rabson {
231*e97ad33aSDoug Rabson 
232*e97ad33aSDoug Rabson 	switch (fid_type) {
233*e97ad33aSDoug Rabson 	case VFID:
234*e97ad33aSDoug Rabson 		P9FS_VFID_LOCK(np);
235*e97ad33aSDoug Rabson 		STAILQ_INSERT_TAIL(&np->vfid_list, fid, fid_next);
236*e97ad33aSDoug Rabson 		P9FS_VFID_UNLOCK(np);
237*e97ad33aSDoug Rabson 		break;
238*e97ad33aSDoug Rabson 	case VOFID:
239*e97ad33aSDoug Rabson 		P9FS_VOFID_LOCK(np);
240*e97ad33aSDoug Rabson 		STAILQ_INSERT_TAIL(&np->vofid_list, fid, fid_next);
241*e97ad33aSDoug Rabson 		P9FS_VOFID_UNLOCK(np);
242*e97ad33aSDoug Rabson 		break;
243*e97ad33aSDoug Rabson 	}
244*e97ad33aSDoug Rabson }
245*e97ad33aSDoug Rabson 
246*e97ad33aSDoug Rabson /* Build the path from root to current directory */
247*e97ad33aSDoug Rabson static int
p9fs_get_full_path(struct p9fs_node * np,char *** names)248*e97ad33aSDoug Rabson p9fs_get_full_path(struct p9fs_node *np, char ***names)
249*e97ad33aSDoug Rabson {
250*e97ad33aSDoug Rabson 	int i, n;
251*e97ad33aSDoug Rabson 	struct p9fs_node *node;
252*e97ad33aSDoug Rabson 	char **wnames;
253*e97ad33aSDoug Rabson 
254*e97ad33aSDoug Rabson 	n = 0;
255*e97ad33aSDoug Rabson 	for (node = np ; (node != NULL) && !IS_ROOT(node) ; node = node->parent)
256*e97ad33aSDoug Rabson 		n++;
257*e97ad33aSDoug Rabson 
258*e97ad33aSDoug Rabson 	if (node == NULL)
259*e97ad33aSDoug Rabson 		return (0);
260*e97ad33aSDoug Rabson 
261*e97ad33aSDoug Rabson 	wnames = malloc(n * sizeof(char *), M_TEMP, M_ZERO|M_WAITOK);
262*e97ad33aSDoug Rabson 
263*e97ad33aSDoug Rabson 	for (i = n-1, node = np; i >= 0 ; i--, node = node->parent)
264*e97ad33aSDoug Rabson 		wnames[i] = node->inode.i_name;
265*e97ad33aSDoug Rabson 
266*e97ad33aSDoug Rabson 	*names = wnames;
267*e97ad33aSDoug Rabson 	return (n);
268*e97ad33aSDoug Rabson }
269*e97ad33aSDoug Rabson 
270*e97ad33aSDoug Rabson /*
271*e97ad33aSDoug Rabson  * Return TRUE if this fid can be used for the requested mode.
272*e97ad33aSDoug Rabson  */
273*e97ad33aSDoug Rabson static int
p9fs_compatible_mode(struct p9_fid * fid,int mode)274*e97ad33aSDoug Rabson p9fs_compatible_mode(struct p9_fid *fid, int mode)
275*e97ad33aSDoug Rabson {
276*e97ad33aSDoug Rabson 	/*
277*e97ad33aSDoug Rabson 	 * Return TRUE for an exact match. For OREAD and OWRITE, allow
278*e97ad33aSDoug Rabson 	 * existing ORDWR fids to match. Only check the low two bits
279*e97ad33aSDoug Rabson 	 * of mode.
280*e97ad33aSDoug Rabson 	 *
281*e97ad33aSDoug Rabson 	 * TODO: figure out if this is correct for O_APPEND
282*e97ad33aSDoug Rabson 	 */
283*e97ad33aSDoug Rabson 	int fid_mode = fid->mode & 3;
284*e97ad33aSDoug Rabson 	if (fid_mode == mode)
285*e97ad33aSDoug Rabson 		return (TRUE);
286*e97ad33aSDoug Rabson 	if (fid_mode == P9PROTO_ORDWR)
287*e97ad33aSDoug Rabson 		return (mode == P9PROTO_OREAD || mode == P9PROTO_OWRITE);
288*e97ad33aSDoug Rabson 	return (FALSE);
289*e97ad33aSDoug Rabson }
290*e97ad33aSDoug Rabson 
291*e97ad33aSDoug Rabson /*
292*e97ad33aSDoug Rabson  * Retrieve fid structure corresponding to a particular
293*e97ad33aSDoug Rabson  * uid and fid type for a p9fs node
294*e97ad33aSDoug Rabson  */
295*e97ad33aSDoug Rabson static struct p9_fid *
p9fs_get_fid_from_uid(struct p9fs_node * np,uid_t uid,int fid_type,int mode)296*e97ad33aSDoug Rabson p9fs_get_fid_from_uid(struct p9fs_node *np, uid_t uid, int fid_type, int mode)
297*e97ad33aSDoug Rabson {
298*e97ad33aSDoug Rabson 	struct p9_fid *fid;
299*e97ad33aSDoug Rabson 
300*e97ad33aSDoug Rabson 	switch (fid_type) {
301*e97ad33aSDoug Rabson 	case VFID:
302*e97ad33aSDoug Rabson 		P9FS_VFID_LOCK(np);
303*e97ad33aSDoug Rabson 		STAILQ_FOREACH(fid, &np->vfid_list, fid_next) {
304*e97ad33aSDoug Rabson 			if (fid->uid == uid) {
305*e97ad33aSDoug Rabson 				P9FS_VFID_UNLOCK(np);
306*e97ad33aSDoug Rabson 				return (fid);
307*e97ad33aSDoug Rabson 			}
308*e97ad33aSDoug Rabson 		}
309*e97ad33aSDoug Rabson 		P9FS_VFID_UNLOCK(np);
310*e97ad33aSDoug Rabson 		break;
311*e97ad33aSDoug Rabson 	case VOFID:
312*e97ad33aSDoug Rabson 		P9FS_VOFID_LOCK(np);
313*e97ad33aSDoug Rabson 		STAILQ_FOREACH(fid, &np->vofid_list, fid_next) {
314*e97ad33aSDoug Rabson 			if (fid->uid == uid && p9fs_compatible_mode(fid, mode)) {
315*e97ad33aSDoug Rabson 				P9FS_VOFID_UNLOCK(np);
316*e97ad33aSDoug Rabson 				return (fid);
317*e97ad33aSDoug Rabson 			}
318*e97ad33aSDoug Rabson 		}
319*e97ad33aSDoug Rabson 		P9FS_VOFID_UNLOCK(np);
320*e97ad33aSDoug Rabson 		break;
321*e97ad33aSDoug Rabson 	}
322*e97ad33aSDoug Rabson 
323*e97ad33aSDoug Rabson 	return (NULL);
324*e97ad33aSDoug Rabson }
325*e97ad33aSDoug Rabson 
326*e97ad33aSDoug Rabson /*
327*e97ad33aSDoug Rabson  * Function returns the fid sturcture for a file corresponding to current user id.
328*e97ad33aSDoug Rabson  * First it searches in the fid list of the corresponding p9fs node.
329*e97ad33aSDoug Rabson  * New fid will be created if not already present and added in the corresponding
330*e97ad33aSDoug Rabson  * fid list in the p9fs node.
331*e97ad33aSDoug Rabson  * If the user is not already attached then this will attach the user first
332*e97ad33aSDoug Rabson  * and then create a new fid for this particular file by doing dir walk.
333*e97ad33aSDoug Rabson  */
334*e97ad33aSDoug Rabson struct p9_fid *
p9fs_get_fid(struct p9_client * clnt,struct p9fs_node * np,struct ucred * cred,int fid_type,int mode,int * error)335*e97ad33aSDoug Rabson p9fs_get_fid(struct p9_client *clnt, struct p9fs_node *np, struct ucred *cred,
336*e97ad33aSDoug Rabson     int fid_type, int mode, int *error)
337*e97ad33aSDoug Rabson {
338*e97ad33aSDoug Rabson 	uid_t uid;
339*e97ad33aSDoug Rabson 	struct p9_fid *fid, *oldfid;
340*e97ad33aSDoug Rabson 	struct p9fs_node *root;
341*e97ad33aSDoug Rabson 	struct p9fs_session *vses;
342*e97ad33aSDoug Rabson 	int i, l, clone;
343*e97ad33aSDoug Rabson 	char **wnames = NULL;
344*e97ad33aSDoug Rabson 	uint16_t nwnames;
345*e97ad33aSDoug Rabson 
346*e97ad33aSDoug Rabson 	oldfid = NULL;
347*e97ad33aSDoug Rabson 	vses = np->p9fs_ses;
348*e97ad33aSDoug Rabson 
349*e97ad33aSDoug Rabson 	if (vses->flags & P9_ACCESS_ANY)
350*e97ad33aSDoug Rabson 		uid = vses->uid;
351*e97ad33aSDoug Rabson 	else if (cred)
352*e97ad33aSDoug Rabson 		uid = cred->cr_uid;
353*e97ad33aSDoug Rabson 	else
354*e97ad33aSDoug Rabson 		uid = 0;
355*e97ad33aSDoug Rabson 
356*e97ad33aSDoug Rabson 	/*
357*e97ad33aSDoug Rabson 	 * Search for the fid in corresponding fid list.
358*e97ad33aSDoug Rabson 	 * We should return NULL for VOFID if it is not present in the list.
359*e97ad33aSDoug Rabson 	 * Because VOFID should have been created during the file open.
360*e97ad33aSDoug Rabson 	 * If VFID is not present in the list then we should create one.
361*e97ad33aSDoug Rabson 	 */
362*e97ad33aSDoug Rabson 	fid = p9fs_get_fid_from_uid(np, uid, fid_type, mode);
363*e97ad33aSDoug Rabson 	if (fid != NULL || fid_type == VOFID)
364*e97ad33aSDoug Rabson 		return (fid);
365*e97ad33aSDoug Rabson 
366*e97ad33aSDoug Rabson 	/* Check root if the user is attached */
367*e97ad33aSDoug Rabson 	root = &np->p9fs_ses->rnp;
368*e97ad33aSDoug Rabson 	fid = p9fs_get_fid_from_uid(root, uid, fid_type, mode);
369*e97ad33aSDoug Rabson 	if(fid == NULL) {
370*e97ad33aSDoug Rabson 		/* Attach the user */
371*e97ad33aSDoug Rabson 		fid = p9_client_attach(clnt, NULL, NULL, uid,
372*e97ad33aSDoug Rabson 		    vses->aname, error);
373*e97ad33aSDoug Rabson 		if (*error != 0)
374*e97ad33aSDoug Rabson 			return (NULL);
375*e97ad33aSDoug Rabson 		p9fs_fid_add(root, fid, fid_type);
376*e97ad33aSDoug Rabson 	}
377*e97ad33aSDoug Rabson 
378*e97ad33aSDoug Rabson 	/* If we are looking for root then return it */
379*e97ad33aSDoug Rabson 	if (IS_ROOT(np))
380*e97ad33aSDoug Rabson 		return (fid);
381*e97ad33aSDoug Rabson 
382*e97ad33aSDoug Rabson 	/* Get full path from root to p9fs node */
383*e97ad33aSDoug Rabson 	nwnames = p9fs_get_full_path(np, &wnames);
384*e97ad33aSDoug Rabson 
385*e97ad33aSDoug Rabson 	/*
386*e97ad33aSDoug Rabson 	 * Could not get full path.
387*e97ad33aSDoug Rabson 	 * If p9fs node is not deleted, parent should exist.
388*e97ad33aSDoug Rabson 	 */
389*e97ad33aSDoug Rabson 	KASSERT(nwnames != 0, ("%s: Directory of %s doesn't exist", __func__, np->inode.i_name));
390*e97ad33aSDoug Rabson 
391*e97ad33aSDoug Rabson 	clone = 1;
392*e97ad33aSDoug Rabson 	i = 0;
393*e97ad33aSDoug Rabson 	while (i < nwnames) {
394*e97ad33aSDoug Rabson 		l = MIN(nwnames - i, P9_MAXWELEM);
395*e97ad33aSDoug Rabson 
396*e97ad33aSDoug Rabson 		fid = p9_client_walk(fid, l, wnames, clone, error);
397*e97ad33aSDoug Rabson 		if (*error != 0) {
398*e97ad33aSDoug Rabson 			if (oldfid)
399*e97ad33aSDoug Rabson 				p9_client_clunk(oldfid);
400*e97ad33aSDoug Rabson 			fid = NULL;
401*e97ad33aSDoug Rabson 			goto bail_out;
402*e97ad33aSDoug Rabson 		}
403*e97ad33aSDoug Rabson 		oldfid = fid;
404*e97ad33aSDoug Rabson 		clone = 0;
405*e97ad33aSDoug Rabson 		i += l ;
406*e97ad33aSDoug Rabson 	}
407*e97ad33aSDoug Rabson 	p9fs_fid_add(np, fid, fid_type);
408*e97ad33aSDoug Rabson bail_out:
409*e97ad33aSDoug Rabson 	free(wnames, M_TEMP);
410*e97ad33aSDoug Rabson 	return (fid);
411*e97ad33aSDoug Rabson }
412