1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #include <sys/param.h>
27 #include <sys/types.h>
28 #include <sys/pathname.h>
29 #include <sys/errno.h>
30 #include <sys/cmn_err.h>
31 #include <sys/debug.h>
32 #include <sys/systm.h>
33 #include <sys/unistd.h>
34 #include <sys/door.h>
35 #include <sys/socket.h>
36 #include <nfs/export.h>
37 #include <nfs/nfs_cmd.h>
38 #include <sys/kmem.h>
39 #include <sys/sunddi.h>
40
41 #define NFSCMD_DR_TRYCNT 8
42
43 #ifdef nextdp
44 #undef nextdp
45 #endif
46 #define nextdp(dp) ((struct dirent64 *)((char *)(dp) + (dp)->d_reclen))
47
48 kmutex_t nfscmd_lock;
49 door_handle_t nfscmd_dh;
50
51 static struct charset_cache *nfscmd_charmap(exportinfo_t *exi,
52 struct sockaddr *sp);
53
54
55 void
56 nfscmd_args(uint_t did)
57 {
58 mutex_enter(&nfscmd_lock);
59 if (nfscmd_dh)
60 door_ki_rele(nfscmd_dh);
61 nfscmd_dh = door_ki_lookup(did);
62 mutex_exit(&nfscmd_lock);
63 }
64
65 void
66 nfscmd_init(void)
67 {
68 mutex_init(&nfscmd_lock, NULL, MUTEX_DEFAULT, NULL);
69 }
70
71 void
72 nfscmd_fini(void)
73 {
74 }
75
76 /*
77 * nfscmd_send(arg, result)
78 *
79 * Send a command to the daemon listening on the door. The result is
80 * returned in the result pointer if the function return value is
81 * NFSCMD_ERR_SUCCESS. Otherwise it is the error value.
82 */
83 int
84 nfscmd_send(nfscmd_arg_t *arg, nfscmd_res_t *res)
85 {
86 door_handle_t dh;
87 door_arg_t da;
88 door_info_t di;
89 int ntries = 0;
90 int last = 0;
91
92 retry:
93 mutex_enter(&nfscmd_lock);
94 dh = nfscmd_dh;
95 if (dh != NULL)
96 door_ki_hold(dh);
97 mutex_exit(&nfscmd_lock);
98
99 if (dh == NULL) {
100 /*
101 * The rendezvous point has not been established yet !
102 * This could mean that either mountd(1m) has not yet
103 * been started or that _this_ routine nuked the door
104 * handle after receiving an EINTR for a REVOKED door.
105 *
106 * Returning NFSAUTH_DROP will cause the NFS client
107 * to retransmit the request, so let's try to be more
108 * rescillient and attempt for ntries before we bail.
109 */
110 if (++ntries % NFSCMD_DR_TRYCNT) {
111 delay(hz);
112 goto retry;
113 }
114 return (NFSCMD_ERR_DROP);
115 }
116
117 da.data_ptr = (char *)arg;
124 switch (door_ki_upcall(dh, &da)) {
125 case 0:
126 /* Success */
127 break;
128 case EAGAIN:
129 /* Need to retry a couple of times */
130 door_ki_rele(dh);
131 delay(hz);
132 goto retry;
133 /* NOTREACHED */
134 case EINTR:
135 if (!door_ki_info(dh, &di)) {
136 if (di.di_attributes & DOOR_REVOKED) {
137 /*
138 * The server barfed and revoked
139 * the (existing) door on us; we
140 * want to wait to give smf(5) a
141 * chance to restart mountd(1m)
142 * and establish a new door handle.
143 */
144 mutex_enter(&nfscmd_lock);
145 if (dh == nfscmd_dh)
146 nfscmd_dh = NULL;
147 mutex_exit(&nfscmd_lock);
148 door_ki_rele(dh);
149 delay(hz);
150 goto retry;
151 }
152 /*
153 * If the door was _not_ revoked on us,
154 * then more than likely we took an INTR,
155 * so we need to fail the operation.
156 */
157 door_ki_rele(dh);
158 }
159 /*
160 * The only failure that can occur from getting
161 * the door info is EINVAL, so we let the code
162 * below handle it.
163 */
164 /* FALLTHROUGH */
165
166 case EBADF:
167 case EINVAL:
|
1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * Copyright 2018 Nexenta Systems, Inc.
29 */
30
31 #include <sys/param.h>
32 #include <sys/types.h>
33 #include <sys/pathname.h>
34 #include <sys/errno.h>
35 #include <sys/cmn_err.h>
36 #include <sys/debug.h>
37 #include <sys/systm.h>
38 #include <sys/unistd.h>
39 #include <sys/door.h>
40 #include <sys/socket.h>
41 #include <nfs/export.h>
42 #include <nfs/nfs_cmd.h>
43 #include <sys/kmem.h>
44 #include <sys/sunddi.h>
45
46 #define NFSCMD_DR_TRYCNT 8
47
48 #ifdef nextdp
49 #undef nextdp
50 #endif
51 #define nextdp(dp) ((struct dirent64 *)((char *)(dp) + (dp)->d_reclen))
52
53 typedef struct nfscmd_globals {
54 kmutex_t nfscmd_lock;
55 door_handle_t nfscmd_dh;
56 } nfscmd_globals_t;
57
58 static zone_key_t nfscmd_zone_key;
59
60 static struct charset_cache *nfscmd_charmap(exportinfo_t *exi,
61 struct sockaddr *sp);
62 static void *nfscmd_zone_init(zoneid_t);
63 static void nfscmd_zone_fini(zoneid_t, void *);
64
65 void
66 nfscmd_args(uint_t did)
67 {
68 nfscmd_globals_t *ncg = zone_getspecific(nfscmd_zone_key, curzone);
69
70 mutex_enter(&ncg->nfscmd_lock);
71 if (ncg->nfscmd_dh != NULL)
72 door_ki_rele(ncg->nfscmd_dh);
73 ncg->nfscmd_dh = door_ki_lookup(did);
74 mutex_exit(&ncg->nfscmd_lock);
75 }
76
77 void
78 nfscmd_init(void)
79 {
80 zone_key_create(&nfscmd_zone_key, nfscmd_zone_init,
81 NULL, nfscmd_zone_fini);
82 }
83
84 void
85 nfscmd_fini(void)
86 {
87 (void) zone_key_delete(nfscmd_zone_key);
88 }
89
90 /*ARGSUSED*/
91 static void *
92 nfscmd_zone_init(zoneid_t zoneid)
93 {
94 nfscmd_globals_t *ncg;
95
96 ncg = kmem_zalloc(sizeof (*ncg), KM_SLEEP);
97 mutex_init(&ncg->nfscmd_lock, NULL, MUTEX_DEFAULT, NULL);
98
99 return (ncg);
100 }
101
102 /*ARGSUSED*/
103 static void
104 nfscmd_zone_fini(zoneid_t zoneid, void *data)
105 {
106 nfscmd_globals_t *ncg = data;
107
108 mutex_destroy(&ncg->nfscmd_lock);
109 if (ncg->nfscmd_dh)
110 door_ki_rele(ncg->nfscmd_dh);
111 kmem_free(ncg, sizeof (*ncg));
112 }
113
114 /*
115 * nfscmd_send(arg, result)
116 *
117 * Send a command to the daemon listening on the door. The result is
118 * returned in the result pointer if the function return value is
119 * NFSCMD_ERR_SUCCESS. Otherwise it is the error value.
120 */
121 int
122 nfscmd_send(nfscmd_arg_t *arg, nfscmd_res_t *res)
123 {
124 door_handle_t dh;
125 door_arg_t da;
126 door_info_t di;
127 int ntries = 0;
128 int last = 0;
129 nfscmd_globals_t *ncg = zone_getspecific(nfscmd_zone_key, curzone);
130
131 retry:
132 mutex_enter(&ncg->nfscmd_lock);
133 dh = ncg->nfscmd_dh;
134 if (dh != NULL)
135 door_ki_hold(dh);
136 mutex_exit(&ncg->nfscmd_lock);
137
138 if (dh == NULL) {
139 /*
140 * The rendezvous point has not been established yet !
141 * This could mean that either mountd(1m) has not yet
142 * been started or that _this_ routine nuked the door
143 * handle after receiving an EINTR for a REVOKED door.
144 *
145 * Returning NFSAUTH_DROP will cause the NFS client
146 * to retransmit the request, so let's try to be more
147 * rescillient and attempt for ntries before we bail.
148 */
149 if (++ntries % NFSCMD_DR_TRYCNT) {
150 delay(hz);
151 goto retry;
152 }
153 return (NFSCMD_ERR_DROP);
154 }
155
156 da.data_ptr = (char *)arg;
163 switch (door_ki_upcall(dh, &da)) {
164 case 0:
165 /* Success */
166 break;
167 case EAGAIN:
168 /* Need to retry a couple of times */
169 door_ki_rele(dh);
170 delay(hz);
171 goto retry;
172 /* NOTREACHED */
173 case EINTR:
174 if (!door_ki_info(dh, &di)) {
175 if (di.di_attributes & DOOR_REVOKED) {
176 /*
177 * The server barfed and revoked
178 * the (existing) door on us; we
179 * want to wait to give smf(5) a
180 * chance to restart mountd(1m)
181 * and establish a new door handle.
182 */
183 mutex_enter(&ncg->nfscmd_lock);
184 if (dh == ncg->nfscmd_dh)
185 ncg->nfscmd_dh = NULL;
186 mutex_exit(&ncg->nfscmd_lock);
187 door_ki_rele(dh);
188 delay(hz);
189 goto retry;
190 }
191 /*
192 * If the door was _not_ revoked on us,
193 * then more than likely we took an INTR,
194 * so we need to fail the operation.
195 */
196 door_ki_rele(dh);
197 }
198 /*
199 * The only failure that can occur from getting
200 * the door info is EINVAL, so we let the code
201 * below handle it.
202 */
203 /* FALLTHROUGH */
204
205 case EBADF:
206 case EINVAL:
|