Print this page
patch tsoome-feedback
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/fs/smbsrv/smb_kshare.c
+++ new/usr/src/uts/common/fs/smbsrv/smb_kshare.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
25 25 */
26 26
27 27 #include <smbsrv/smb_door.h>
28 28 #include <smbsrv/smb_kproto.h>
29 29 #include <smbsrv/smb_ktypes.h>
30 30
31 31 typedef struct smb_unshare {
32 32 list_node_t us_lnd;
33 33 char us_sharename[MAXNAMELEN];
34 34 } smb_unshare_t;
35 35
36 36 static kmem_cache_t *smb_kshare_cache_share;
37 37 static kmem_cache_t *smb_kshare_cache_unexport;
38 38 kmem_cache_t *smb_kshare_cache_vfs;
39 39
40 40 static int smb_kshare_cmp(const void *, const void *);
41 41 static void smb_kshare_hold(const void *);
42 42 static boolean_t smb_kshare_rele(const void *);
43 43 static void smb_kshare_destroy(void *);
44 44 static char *smb_kshare_oemname(const char *);
45 45 static int smb_kshare_is_special(const char *);
46 46 static boolean_t smb_kshare_is_admin(const char *);
47 47 static smb_kshare_t *smb_kshare_decode(nvlist_t *);
48 48 static uint32_t smb_kshare_decode_bool(nvlist_t *, const char *, uint32_t);
49 49 static void smb_kshare_unexport_thread(smb_thread_t *, void *);
50 50 static int smb_kshare_export(smb_server_t *, smb_kshare_t *);
51 51 static int smb_kshare_unexport(smb_server_t *, const char *);
52 52 static int smb_kshare_export_trans(smb_server_t *, char *, char *, char *);
53 53 static void smb_kshare_csc_flags(smb_kshare_t *, const char *);
54 54
55 55 static boolean_t smb_export_isready(smb_server_t *);
56 56
57 57 #ifdef _KERNEL
58 58 static int smb_kshare_chk_dsrv_status(int, smb_dr_ctx_t *);
59 59 #endif /* _KERNEL */
60 60
61 61 static const smb_avl_nops_t smb_kshare_avlops = {
62 62 smb_kshare_cmp,
63 63 smb_kshare_hold,
64 64 smb_kshare_rele,
65 65 smb_kshare_destroy
66 66 };
67 67
68 68 #ifdef _KERNEL
69 69 /*
70 70 * This function is not MultiThread safe. The caller has to make sure only one
71 71 * thread calls this function.
72 72 */
73 73 door_handle_t
74 74 smb_kshare_door_init(int door_id)
75 75 {
76 76 return (door_ki_lookup(door_id));
77 77 }
78 78
79 79 /*
80 80 * This function is not MultiThread safe. The caller has to make sure only one
81 81 * thread calls this function.
82 82 */
83 83 void
84 84 smb_kshare_door_fini(door_handle_t dhdl)
85 85 {
86 86 if (dhdl)
87 87 door_ki_rele(dhdl);
88 88 }
89 89
90 90 /*
91 91 * This is a special interface that will be utilized by ZFS to cause
92 92 * a share to be added/removed
93 93 *
94 94 * arg is either a smb_share_t or share_name from userspace.
95 95 * It will need to be copied into the kernel. It is smb_share_t
96 96 * for add operations and share_name for delete operations.
97 97 */
98 98 int
99 99 smb_kshare_upcall(door_handle_t dhdl, void *arg, boolean_t add_share)
100 100 {
101 101 door_arg_t doorarg = { 0 };
102 102 char *buf = NULL;
103 103 char *str = NULL;
104 104 int error;
105 105 int rc;
106 106 unsigned int used;
107 107 smb_dr_ctx_t *dec_ctx;
108 108 smb_dr_ctx_t *enc_ctx;
109 109 smb_share_t *lmshare = NULL;
110 110 int opcode;
111 111
112 112 opcode = (add_share) ? SMB_SHROP_ADD : SMB_SHROP_DELETE;
113 113
114 114 buf = kmem_alloc(SMB_SHARE_DSIZE, KM_SLEEP);
115 115 enc_ctx = smb_dr_encode_start(buf, SMB_SHARE_DSIZE);
116 116 smb_dr_put_uint32(enc_ctx, opcode);
117 117
118 118 switch (opcode) {
119 119 case SMB_SHROP_ADD:
120 120 lmshare = kmem_alloc(sizeof (smb_share_t), KM_SLEEP);
121 121 error = xcopyin(arg, lmshare, sizeof (smb_share_t));
122 122 if (error != 0) {
123 123 kmem_free(lmshare, sizeof (smb_share_t));
124 124 kmem_free(buf, SMB_SHARE_DSIZE);
125 125 return (error);
126 126 }
127 127 smb_dr_put_share(enc_ctx, lmshare);
128 128 break;
129 129
130 130 case SMB_SHROP_DELETE:
131 131 str = kmem_alloc(MAXPATHLEN, KM_SLEEP);
132 132 error = copyinstr(arg, str, MAXPATHLEN, NULL);
133 133 if (error != 0) {
134 134 kmem_free(str, MAXPATHLEN);
135 135 kmem_free(buf, SMB_SHARE_DSIZE);
136 136 return (error);
137 137 }
138 138 smb_dr_put_string(enc_ctx, str);
139 139 kmem_free(str, MAXPATHLEN);
140 140 break;
141 141 }
142 142
143 143 if ((error = smb_dr_encode_finish(enc_ctx, &used)) != 0) {
144 144 kmem_free(buf, SMB_SHARE_DSIZE);
145 145 if (lmshare)
146 146 kmem_free(lmshare, sizeof (smb_share_t));
147 147 return (NERR_InternalError);
148 148 }
149 149
150 150 doorarg.data_ptr = buf;
151 151 doorarg.data_size = used;
152 152 doorarg.rbuf = buf;
153 153 doorarg.rsize = SMB_SHARE_DSIZE;
154 154
155 155 error = door_ki_upcall_limited(dhdl, &doorarg, NULL, SIZE_MAX, 0);
156 156
157 157 if (error) {
158 158 kmem_free(buf, SMB_SHARE_DSIZE);
159 159 if (lmshare)
160 160 kmem_free(lmshare, sizeof (smb_share_t));
161 161 return (error);
162 162 }
163 163
164 164 dec_ctx = smb_dr_decode_start(doorarg.data_ptr, doorarg.data_size);
165 165 if (smb_kshare_chk_dsrv_status(opcode, dec_ctx) != 0) {
166 166 kmem_free(buf, SMB_SHARE_DSIZE);
167 167 if (lmshare)
168 168 kmem_free(lmshare, sizeof (smb_share_t));
169 169 return (NERR_InternalError);
170 170 }
171 171
172 172 rc = smb_dr_get_uint32(dec_ctx);
173 173 if (opcode == SMB_SHROP_ADD)
174 174 smb_dr_get_share(dec_ctx, lmshare);
175 175
176 176 if (smb_dr_decode_finish(dec_ctx))
177 177 rc = NERR_InternalError;
178 178
179 179 kmem_free(buf, SMB_SHARE_DSIZE);
180 180 if (lmshare)
181 181 kmem_free(lmshare, sizeof (smb_share_t));
182 182
183 183 return ((rc == NERR_DuplicateShare && add_share) ? 0 : rc);
184 184 }
185 185 #endif /* _KERNEL */
186 186
187 187 /*
188 188 * Executes map and unmap command for shares.
189 189 */
190 190 int
191 191 smb_kshare_exec(smb_server_t *sv, smb_shr_execinfo_t *execinfo)
192 192 {
193 193 int exec_rc = 0;
194 194
195 195 (void) smb_kdoor_upcall(sv, SMB_DR_SHR_EXEC,
196 196 execinfo, smb_shr_execinfo_xdr, &exec_rc, xdr_int);
197 197
198 198 return (exec_rc);
199 199 }
200 200
201 201 /*
202 202 * Obtains any host access restriction on the specified
203 203 * share for the given host (ipaddr) by calling smbd
204 204 */
205 205 uint32_t
206 206 smb_kshare_hostaccess(smb_kshare_t *shr, smb_session_t *session)
207 207 {
208 208 smb_shr_hostaccess_query_t req;
209 209 smb_inaddr_t *ipaddr = &session->ipaddr;
210 210 uint32_t host_access = SMB_SHRF_ACC_OPEN;
211 211 uint32_t flag = SMB_SHRF_ACC_OPEN;
212 212 uint32_t access;
213 213
214 214 if (smb_inet_iszero(ipaddr))
215 215 return (ACE_ALL_PERMS);
216 216
217 217 if ((shr->shr_access_none == NULL || *shr->shr_access_none == '\0') &&
218 218 (shr->shr_access_ro == NULL || *shr->shr_access_ro == '\0') &&
219 219 (shr->shr_access_rw == NULL || *shr->shr_access_rw == '\0'))
220 220 return (ACE_ALL_PERMS);
221 221
222 222 if (shr->shr_access_none != NULL)
223 223 flag |= SMB_SHRF_ACC_NONE;
224 224 if (shr->shr_access_ro != NULL)
225 225 flag |= SMB_SHRF_ACC_RO;
226 226 if (shr->shr_access_rw != NULL)
227 227 flag |= SMB_SHRF_ACC_RW;
228 228
229 229 req.shq_none = shr->shr_access_none;
230 230 req.shq_ro = shr->shr_access_ro;
231 231 req.shq_rw = shr->shr_access_rw;
232 232 req.shq_flag = flag;
233 233 req.shq_ipaddr = *ipaddr;
234 234
235 235 (void) smb_kdoor_upcall(session->s_server, SMB_DR_SHR_HOSTACCESS,
236 236 &req, smb_shr_hostaccess_query_xdr, &host_access, xdr_uint32_t);
237 237
238 238 switch (host_access) {
239 239 case SMB_SHRF_ACC_RO:
240 240 access = ACE_ALL_PERMS & ~ACE_ALL_WRITE_PERMS;
241 241 break;
242 242 case SMB_SHRF_ACC_OPEN:
243 243 case SMB_SHRF_ACC_RW:
244 244 access = ACE_ALL_PERMS;
245 245 break;
246 246 case SMB_SHRF_ACC_NONE:
247 247 default:
248 248 access = 0;
249 249 }
250 250
251 251 return (access);
252 252 }
253 253
254 254 /*
255 255 * This function is called when smb_server_t is
256 256 * created which means smb/service is ready for
257 257 * exporting SMB shares
258 258 */
259 259 void
260 260 smb_export_start(smb_server_t *sv)
261 261 {
262 262 mutex_enter(&sv->sv_export.e_mutex);
263 263 if (sv->sv_export.e_ready) {
264 264 mutex_exit(&sv->sv_export.e_mutex);
265 265 return;
266 266 }
267 267
268 268 sv->sv_export.e_ready = B_TRUE;
269 269 mutex_exit(&sv->sv_export.e_mutex);
270 270
271 271 smb_avl_create(&sv->sv_export.e_share_avl, sizeof (smb_kshare_t),
272 272 offsetof(smb_kshare_t, shr_link), &smb_kshare_avlops);
273 273
274 274 (void) smb_kshare_export_trans(sv, "IPC$", "IPC$", "Remote IPC");
275 275 (void) smb_kshare_export_trans(sv, "c$", SMB_CVOL, "Default Share");
276 276 (void) smb_kshare_export_trans(sv, "vss$", SMB_VSS, "VSS");
277 277 }
278 278
279 279 /*
280 280 * This function is called when smb_server_t goes
281 281 * away which means SMB shares should not be made
282 282 * available to clients
283 283 */
284 284 void
285 285 smb_export_stop(smb_server_t *sv)
286 286 {
287 287 mutex_enter(&sv->sv_export.e_mutex);
288 288 if (!sv->sv_export.e_ready) {
289 289 mutex_exit(&sv->sv_export.e_mutex);
290 290 return;
291 291 }
292 292 sv->sv_export.e_ready = B_FALSE;
293 293 mutex_exit(&sv->sv_export.e_mutex);
294 294
295 295 smb_avl_destroy(&sv->sv_export.e_share_avl);
296 296 smb_vfs_rele_all(&sv->sv_export);
297 297 }
298 298
299 299 void
300 300 smb_kshare_g_init(void)
301 301 {
302 302 smb_kshare_cache_share = kmem_cache_create("smb_share_cache",
303 303 sizeof (smb_kshare_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
304 304
305 305 smb_kshare_cache_unexport = kmem_cache_create("smb_unexport_cache",
306 306 sizeof (smb_unshare_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
307 307
308 308 smb_kshare_cache_vfs = kmem_cache_create("smb_vfs_cache",
309 309 sizeof (smb_vfs_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
310 310 }
311 311
312 312 void
313 313 smb_kshare_init(smb_server_t *sv)
314 314 {
315 315
316 316 smb_llist_constructor(&sv->sv_export.e_vfs_list, sizeof (smb_vfs_t),
317 317 offsetof(smb_vfs_t, sv_lnd));
318 318
319 319 smb_slist_constructor(&sv->sv_export.e_unexport_list,
320 320 sizeof (smb_unshare_t), offsetof(smb_unshare_t, us_lnd));
321 321 }
322 322
323 323 int
324 324 smb_kshare_start(smb_server_t *sv)
325 325 {
326 326 smb_thread_init(&sv->sv_export.e_unexport_thread, "smb_kshare_unexport",
327 327 smb_kshare_unexport_thread, sv, smbsrv_base_pri);
328 328
329 329 return (smb_thread_start(&sv->sv_export.e_unexport_thread));
330 330 }
331 331
332 332 void
333 333 smb_kshare_stop(smb_server_t *sv)
334 334 {
335 335 smb_thread_stop(&sv->sv_export.e_unexport_thread);
336 336 smb_thread_destroy(&sv->sv_export.e_unexport_thread);
337 337 }
338 338
339 339 void
340 340 smb_kshare_fini(smb_server_t *sv)
341 341 {
342 342 smb_unshare_t *ux;
343 343
344 344 while ((ux = list_head(&sv->sv_export.e_unexport_list.sl_list))
345 345 != NULL) {
346 346 smb_slist_remove(&sv->sv_export.e_unexport_list, ux);
347 347 kmem_cache_free(smb_kshare_cache_unexport, ux);
348 348 }
349 349 smb_slist_destructor(&sv->sv_export.e_unexport_list);
350 350
351 351 smb_vfs_rele_all(&sv->sv_export);
352 352
353 353 smb_llist_destructor(&sv->sv_export.e_vfs_list);
354 354 }
355 355
356 356 void
357 357 smb_kshare_g_fini(void)
358 358 {
359 359 kmem_cache_destroy(smb_kshare_cache_unexport);
360 360 kmem_cache_destroy(smb_kshare_cache_share);
361 361 kmem_cache_destroy(smb_kshare_cache_vfs);
362 362 }
363 363
364 364 /*
365 365 * A list of shares in nvlist format can be sent down
366 366 * from userspace thourgh the IOCTL interface. The nvlist
367 367 * is unpacked here and all the shares in the list will
368 368 * be exported.
369 369 */
370 370 int
371 371 smb_kshare_export_list(smb_ioc_share_t *ioc)
372 372 {
373 373 smb_server_t *sv = NULL;
374 374 nvlist_t *shrlist = NULL;
375 375 nvlist_t *share;
376 376 nvpair_t *nvp;
377 377 smb_kshare_t *shr;
378 378 char *shrname;
379 379 int rc;
380 380
381 381 if ((rc = smb_server_lookup(&sv)) != 0)
382 382 return (rc);
383 383
384 384 if (!smb_export_isready(sv)) {
385 385 rc = ENOTACTIVE;
386 386 goto out;
387 387 }
388 388
389 389 rc = nvlist_unpack(ioc->shr, ioc->shrlen, &shrlist, KM_SLEEP);
390 390 if (rc != 0)
391 391 goto out;
392 392
393 393 for (nvp = nvlist_next_nvpair(shrlist, NULL); nvp != NULL;
394 394 nvp = nvlist_next_nvpair(shrlist, nvp)) {
395 395
396 396 /*
397 397 * Since this loop can run for a while we want to exit
398 398 * as soon as the server state is anything but RUNNING
399 399 * to allow shutdown to proceed.
400 400 */
401 401 if (sv->sv_state != SMB_SERVER_STATE_RUNNING)
402 402 goto out;
403 403
404 404 if (nvpair_type(nvp) != DATA_TYPE_NVLIST)
405 405 continue;
406 406
407 407 shrname = nvpair_name(nvp);
408 408 ASSERT(shrname);
409 409
410 410 if ((rc = nvpair_value_nvlist(nvp, &share)) != 0) {
411 411 cmn_err(CE_WARN, "export[%s]: failed accessing",
412 412 shrname);
413 413 continue;
414 414 }
415 415
416 416 if ((shr = smb_kshare_decode(share)) == NULL) {
417 417 cmn_err(CE_WARN, "export[%s]: failed decoding",
418 418 shrname);
419 419 continue;
420 420 }
↓ open down ↓ |
420 lines elided |
↑ open up ↑ |
421 421
422 422 /* smb_kshare_export consumes shr so it's not leaked */
423 423 if ((rc = smb_kshare_export(sv, shr)) != 0) {
424 424 smb_kshare_destroy(shr);
425 425 continue;
426 426 }
427 427 }
428 428 rc = 0;
429 429
430 430 out:
431 - if (shrlist != NULL)
432 - nvlist_free(shrlist);
431 + nvlist_free(shrlist);
433 432 smb_server_release(sv);
434 433 return (rc);
435 434 }
436 435
437 436 /*
438 437 * This function is invoked when a share is disabled to disconnect trees
439 438 * and close files. Cleaning up may involve VOP and/or VFS calls, which
440 439 * may conflict/deadlock with stuck threads if something is amiss with the
441 440 * file system. Queueing the request for asynchronous processing allows the
442 441 * call to return immediately so that, if the unshare is being done in the
443 442 * context of a forced unmount, the forced unmount will always be able to
444 443 * proceed (unblocking stuck I/O and eventually allowing all blocked unshare
445 444 * processes to complete).
446 445 *
447 446 * The path lookup to find the root vnode of the VFS in question and the
448 447 * release of this vnode are done synchronously prior to any associated
449 448 * unmount. Doing these asynchronous to an associated unmount could run
450 449 * the risk of a spurious EBUSY for a standard unmount or an EIO during
451 450 * the path lookup due to a forced unmount finishing first.
452 451 */
453 452 int
454 453 smb_kshare_unexport_list(smb_ioc_share_t *ioc)
455 454 {
456 455 smb_server_t *sv = NULL;
457 456 smb_unshare_t *ux;
458 457 nvlist_t *shrlist = NULL;
459 458 nvpair_t *nvp;
460 459 boolean_t unexport = B_FALSE;
461 460 char *shrname;
462 461 int rc;
463 462
464 463 if ((rc = smb_server_lookup(&sv)) != 0)
465 464 return (rc);
466 465
467 466 if ((rc = nvlist_unpack(ioc->shr, ioc->shrlen, &shrlist, 0)) != 0)
468 467 goto out;
469 468
470 469 for (nvp = nvlist_next_nvpair(shrlist, NULL); nvp != NULL;
471 470 nvp = nvlist_next_nvpair(shrlist, nvp)) {
472 471 if (nvpair_type(nvp) != DATA_TYPE_NVLIST)
473 472 continue;
474 473
475 474 shrname = nvpair_name(nvp);
476 475 ASSERT(shrname);
477 476
478 477 if ((rc = smb_kshare_unexport(sv, shrname)) != 0)
479 478 continue;
480 479
481 480 ux = kmem_cache_alloc(smb_kshare_cache_unexport, KM_SLEEP);
482 481 (void) strlcpy(ux->us_sharename, shrname, MAXNAMELEN);
↓ open down ↓ |
40 lines elided |
↑ open up ↑ |
483 482
484 483 smb_slist_insert_tail(&sv->sv_export.e_unexport_list, ux);
485 484 unexport = B_TRUE;
486 485 }
487 486
488 487 if (unexport)
489 488 smb_thread_signal(&sv->sv_export.e_unexport_thread);
490 489 rc = 0;
491 490
492 491 out:
493 - if (shrlist != NULL)
494 - nvlist_free(shrlist);
492 + nvlist_free(shrlist);
495 493 smb_server_release(sv);
496 494 return (rc);
497 495 }
498 496
499 497 /*
500 498 * Get properties (currently only shortname enablement)
501 499 * of specified share.
502 500 */
503 501 int
504 502 smb_kshare_info(smb_ioc_shareinfo_t *ioc)
505 503 {
506 504 ioc->shortnames = smb_shortnames;
507 505 return (0);
508 506 }
509 507
510 508 /*
511 509 * This function builds a response for a NetShareEnum RAP request.
512 510 * List of shares is scanned twice. In the first round the total number
513 511 * of shares which their OEM name is shorter than 13 chars (esi->es_ntotal)
514 512 * and also the number of shares that fit in the given buffer are calculated.
515 513 * In the second round the shares data are encoded in the buffer.
516 514 *
517 515 * The data associated with each share has two parts, a fixed size part and
518 516 * a variable size part which is share's comment. The outline of the response
519 517 * buffer is so that fixed part for all the shares will appear first and follows
520 518 * with the comments for all those shares and that's why the data cannot be
521 519 * encoded in one round without unnecessarily complicating the code.
522 520 */
523 521 void
524 522 smb_kshare_enum(smb_server_t *sv, smb_enumshare_info_t *esi)
525 523 {
526 524 smb_avl_t *share_avl;
527 525 smb_avl_cursor_t cursor;
528 526 smb_kshare_t *shr;
529 527 int remained;
530 528 uint16_t infolen = 0;
531 529 uint16_t cmntlen = 0;
532 530 uint16_t sharelen;
533 531 uint16_t clen;
534 532 uint32_t cmnt_offs;
535 533 smb_msgbuf_t info_mb;
536 534 smb_msgbuf_t cmnt_mb;
537 535 boolean_t autohome_added = B_FALSE;
538 536
539 537 if (!smb_export_isready(sv)) {
540 538 esi->es_ntotal = esi->es_nsent = 0;
541 539 esi->es_datasize = 0;
542 540 return;
543 541 }
544 542
545 543 esi->es_ntotal = esi->es_nsent = 0;
546 544 remained = esi->es_bufsize;
547 545 share_avl = &sv->sv_export.e_share_avl;
548 546
549 547 /* Do the necessary calculations in the first round */
550 548 smb_avl_iterinit(share_avl, &cursor);
551 549
552 550 while ((shr = smb_avl_iterate(share_avl, &cursor)) != NULL) {
553 551 if (shr->shr_oemname == NULL) {
554 552 smb_avl_release(share_avl, shr);
555 553 continue;
556 554 }
557 555
558 556 if ((shr->shr_flags & SMB_SHRF_AUTOHOME) && !autohome_added) {
559 557 if (esi->es_posix_uid == shr->shr_uid) {
560 558 autohome_added = B_TRUE;
561 559 } else {
562 560 smb_avl_release(share_avl, shr);
563 561 continue;
564 562 }
565 563 }
566 564
567 565 esi->es_ntotal++;
568 566
569 567 if (remained <= 0) {
570 568 smb_avl_release(share_avl, shr);
571 569 continue;
572 570 }
573 571
574 572 clen = strlen(shr->shr_cmnt) + 1;
575 573 sharelen = SHARE_INFO_1_SIZE + clen;
576 574
577 575 if (sharelen <= remained) {
578 576 infolen += SHARE_INFO_1_SIZE;
579 577 cmntlen += clen;
580 578 }
581 579
582 580 remained -= sharelen;
583 581 smb_avl_release(share_avl, shr);
584 582 }
585 583
586 584 esi->es_datasize = infolen + cmntlen;
587 585
588 586 smb_msgbuf_init(&info_mb, (uint8_t *)esi->es_buf, infolen, 0);
589 587 smb_msgbuf_init(&cmnt_mb, (uint8_t *)esi->es_buf + infolen, cmntlen, 0);
590 588 cmnt_offs = infolen;
591 589
592 590 /* Encode the data in the second round */
593 591 smb_avl_iterinit(share_avl, &cursor);
594 592 autohome_added = B_FALSE;
595 593
596 594 while ((shr = smb_avl_iterate(share_avl, &cursor)) != NULL) {
597 595 if (shr->shr_oemname == NULL) {
598 596 smb_avl_release(share_avl, shr);
599 597 continue;
600 598 }
601 599
602 600 if ((shr->shr_flags & SMB_SHRF_AUTOHOME) && !autohome_added) {
603 601 if (esi->es_posix_uid == shr->shr_uid) {
604 602 autohome_added = B_TRUE;
605 603 } else {
606 604 smb_avl_release(share_avl, shr);
607 605 continue;
608 606 }
609 607 }
610 608
611 609 if (smb_msgbuf_encode(&info_mb, "13c.wl",
612 610 shr->shr_oemname, shr->shr_type, cmnt_offs) < 0) {
613 611 smb_avl_release(share_avl, shr);
614 612 break;
615 613 }
616 614
617 615 if (smb_msgbuf_encode(&cmnt_mb, "s", shr->shr_cmnt) < 0) {
618 616 smb_avl_release(share_avl, shr);
619 617 break;
620 618 }
621 619
622 620 cmnt_offs += strlen(shr->shr_cmnt) + 1;
623 621 esi->es_nsent++;
624 622
625 623 smb_avl_release(share_avl, shr);
626 624 }
627 625
628 626 smb_msgbuf_term(&info_mb);
629 627 smb_msgbuf_term(&cmnt_mb);
630 628 }
631 629
632 630 /*
633 631 * Looks up the given share and returns a pointer
634 632 * to its definition if it's found. A hold on the
635 633 * object is taken before the pointer is returned
636 634 * in which case the caller MUST always call
637 635 * smb_kshare_release().
638 636 */
639 637 smb_kshare_t *
640 638 smb_kshare_lookup(smb_server_t *sv, const char *shrname)
641 639 {
642 640 smb_kshare_t key;
643 641 smb_kshare_t *shr;
644 642
645 643 ASSERT(shrname);
646 644
647 645 if (!smb_export_isready(sv))
648 646 return (NULL);
649 647
650 648 key.shr_name = (char *)shrname;
651 649 shr = smb_avl_lookup(&sv->sv_export.e_share_avl, &key);
652 650 return (shr);
653 651 }
654 652
655 653 /*
656 654 * Releases the hold taken on the specified share object
657 655 */
658 656 void
659 657 smb_kshare_release(smb_server_t *sv, smb_kshare_t *shr)
660 658 {
661 659 ASSERT(shr);
662 660 ASSERT(shr->shr_magic == SMB_SHARE_MAGIC);
663 661
664 662 smb_avl_release(&sv->sv_export.e_share_avl, shr);
665 663 }
666 664
667 665 /*
668 666 * Add the given share in the specified server.
669 667 * If the share is a disk share, smb_vfs_hold() is
670 668 * invoked to ensure that there is a hold on the
671 669 * corresponding file system before the share is
672 670 * added to shares AVL.
673 671 *
674 672 * If the share is an Autohome share and it is
675 673 * already in the AVL only a reference count for
676 674 * that share is incremented.
677 675 */
678 676 static int
679 677 smb_kshare_export(smb_server_t *sv, smb_kshare_t *shr)
680 678 {
681 679 smb_avl_t *share_avl;
682 680 smb_kshare_t *auto_shr;
683 681 vnode_t *vp;
684 682 int rc = 0;
685 683
686 684 share_avl = &sv->sv_export.e_share_avl;
687 685
688 686 if (!STYPE_ISDSK(shr->shr_type)) {
689 687 if ((rc = smb_avl_add(share_avl, shr)) != 0) {
690 688 cmn_err(CE_WARN, "export[%s]: failed caching (%d)",
691 689 shr->shr_name, rc);
692 690 }
693 691
694 692 return (rc);
695 693 }
696 694
697 695 if ((auto_shr = smb_avl_lookup(share_avl, shr)) != NULL) {
698 696 if ((auto_shr->shr_flags & SMB_SHRF_AUTOHOME) == 0) {
699 697 smb_avl_release(share_avl, auto_shr);
700 698 return (EEXIST);
701 699 }
702 700
703 701 mutex_enter(&auto_shr->shr_mutex);
704 702 auto_shr->shr_autocnt++;
705 703 mutex_exit(&auto_shr->shr_mutex);
706 704 smb_avl_release(share_avl, auto_shr);
707 705 return (0);
708 706 }
709 707
710 708 if ((rc = smb_server_sharevp(sv, shr->shr_path, &vp)) != 0) {
711 709 cmn_err(CE_WARN, "export[%s(%s)]: failed obtaining vnode (%d)",
712 710 shr->shr_name, shr->shr_path, rc);
713 711 return (rc);
714 712 }
715 713
716 714 if ((rc = smb_vfs_hold(&sv->sv_export, vp->v_vfsp)) == 0) {
717 715 if ((rc = smb_avl_add(share_avl, shr)) != 0) {
718 716 cmn_err(CE_WARN, "export[%s]: failed caching (%d)",
719 717 shr->shr_name, rc);
720 718 smb_vfs_rele(&sv->sv_export, vp->v_vfsp);
721 719 }
722 720 } else {
723 721 cmn_err(CE_WARN, "export[%s(%s)]: failed holding VFS (%d)",
724 722 shr->shr_name, shr->shr_path, rc);
725 723 }
726 724
727 725 VN_RELE(vp);
728 726 return (rc);
729 727 }
730 728
731 729 /*
732 730 * Removes the share specified by 'shrname' from the AVL
733 731 * tree of the given server if it's there.
734 732 *
735 733 * If the share is an Autohome share, the autohome count
736 734 * is decremented and the share is only removed if the
737 735 * count goes to zero.
738 736 *
739 737 * If the share is a disk share, the hold on the corresponding
740 738 * file system is released before removing the share from
741 739 * the AVL tree.
742 740 */
743 741 static int
744 742 smb_kshare_unexport(smb_server_t *sv, const char *shrname)
745 743 {
746 744 smb_avl_t *share_avl;
747 745 smb_kshare_t key;
748 746 smb_kshare_t *shr;
749 747 vnode_t *vp;
750 748 int rc;
751 749 boolean_t auto_unexport;
752 750
753 751 share_avl = &sv->sv_export.e_share_avl;
754 752
755 753 key.shr_name = (char *)shrname;
756 754 if ((shr = smb_avl_lookup(share_avl, &key)) == NULL)
757 755 return (ENOENT);
758 756
759 757 if ((shr->shr_flags & SMB_SHRF_AUTOHOME) != 0) {
760 758 mutex_enter(&shr->shr_mutex);
761 759 shr->shr_autocnt--;
762 760 auto_unexport = (shr->shr_autocnt == 0);
763 761 mutex_exit(&shr->shr_mutex);
764 762 if (!auto_unexport) {
765 763 smb_avl_release(share_avl, shr);
766 764 return (0);
767 765 }
768 766 }
769 767
770 768 if (STYPE_ISDSK(shr->shr_type)) {
771 769 if ((rc = smb_server_sharevp(sv, shr->shr_path, &vp)) != 0) {
772 770 smb_avl_release(share_avl, shr);
773 771 cmn_err(CE_WARN, "unexport[%s]: failed obtaining vnode"
774 772 " (%d)", shrname, rc);
775 773 return (rc);
776 774 }
777 775
778 776 smb_vfs_rele(&sv->sv_export, vp->v_vfsp);
779 777 VN_RELE(vp);
780 778 }
781 779
782 780 smb_avl_remove(share_avl, shr);
783 781 smb_avl_release(share_avl, shr);
784 782
785 783 return (0);
786 784 }
787 785
788 786 /*
789 787 * Exports IPC$ or Admin shares
790 788 */
791 789 static int
792 790 smb_kshare_export_trans(smb_server_t *sv, char *name, char *path, char *cmnt)
793 791 {
794 792 smb_kshare_t *shr;
795 793
796 794 ASSERT(name);
797 795 ASSERT(path);
798 796
799 797 shr = kmem_cache_alloc(smb_kshare_cache_share, KM_SLEEP);
800 798 bzero(shr, sizeof (smb_kshare_t));
801 799
802 800 shr->shr_magic = SMB_SHARE_MAGIC;
803 801 shr->shr_refcnt = 1;
804 802 shr->shr_flags = SMB_SHRF_TRANS | smb_kshare_is_admin(shr->shr_name);
805 803 if (strcasecmp(name, "IPC$") == 0)
806 804 shr->shr_type = STYPE_IPC;
807 805 else
808 806 shr->shr_type = STYPE_DISKTREE;
809 807
810 808 shr->shr_type |= smb_kshare_is_special(shr->shr_name);
811 809
812 810 shr->shr_name = smb_mem_strdup(name);
813 811 if (path)
814 812 shr->shr_path = smb_mem_strdup(path);
815 813 if (cmnt)
816 814 shr->shr_cmnt = smb_mem_strdup(cmnt);
817 815 shr->shr_oemname = smb_kshare_oemname(name);
818 816
819 817 return (smb_kshare_export(sv, shr));
820 818 }
821 819
822 820 /*
823 821 * Decodes share information in an nvlist format into a smb_kshare_t
824 822 * structure.
825 823 *
826 824 * This is a temporary function and will be replaced by functions
827 825 * provided by libsharev2 code after it's available.
828 826 */
829 827 static smb_kshare_t *
830 828 smb_kshare_decode(nvlist_t *share)
831 829 {
832 830 smb_kshare_t tmp;
833 831 smb_kshare_t *shr;
834 832 nvlist_t *smb;
835 833 char *csc_name = NULL;
836 834 int rc;
837 835
838 836 ASSERT(share);
839 837
840 838 bzero(&tmp, sizeof (smb_kshare_t));
841 839
842 840 rc = nvlist_lookup_string(share, "name", &tmp.shr_name);
843 841 rc |= nvlist_lookup_string(share, "path", &tmp.shr_path);
844 842 (void) nvlist_lookup_string(share, "desc", &tmp.shr_cmnt);
845 843
846 844 ASSERT(tmp.shr_name && tmp.shr_path);
847 845
848 846 rc |= nvlist_lookup_nvlist(share, "smb", &smb);
849 847 if (rc != 0) {
850 848 cmn_err(CE_WARN, "kshare: failed looking up SMB properties"
851 849 " (%d)", rc);
852 850 return (NULL);
853 851 }
854 852
855 853 rc = nvlist_lookup_uint32(smb, "type", &tmp.shr_type);
856 854 if (rc != 0) {
857 855 cmn_err(CE_WARN, "kshare[%s]: failed getting the share type"
858 856 " (%d)", tmp.shr_name, rc);
859 857 return (NULL);
860 858 }
861 859
862 860 (void) nvlist_lookup_string(smb, SHOPT_AD_CONTAINER,
863 861 &tmp.shr_container);
864 862 (void) nvlist_lookup_string(smb, SHOPT_NONE, &tmp.shr_access_none);
865 863 (void) nvlist_lookup_string(smb, SHOPT_RO, &tmp.shr_access_ro);
866 864 (void) nvlist_lookup_string(smb, SHOPT_RW, &tmp.shr_access_rw);
867 865
868 866 tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_ABE, SMB_SHRF_ABE);
869 867 tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_CATIA,
870 868 SMB_SHRF_CATIA);
871 869 tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_GUEST,
872 870 SMB_SHRF_GUEST_OK);
873 871 tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_DFSROOT,
874 872 SMB_SHRF_DFSROOT);
875 873 tmp.shr_flags |= smb_kshare_decode_bool(smb, "Autohome",
876 874 SMB_SHRF_AUTOHOME);
877 875
878 876 if ((tmp.shr_flags & SMB_SHRF_AUTOHOME) == SMB_SHRF_AUTOHOME) {
879 877 rc = nvlist_lookup_uint32(smb, "uid", &tmp.shr_uid);
880 878 rc |= nvlist_lookup_uint32(smb, "gid", &tmp.shr_gid);
881 879 if (rc != 0) {
882 880 cmn_err(CE_WARN, "kshare: failed looking up uid/gid"
883 881 " (%d)", rc);
884 882 return (NULL);
885 883 }
886 884 }
887 885
888 886 (void) nvlist_lookup_string(smb, SHOPT_CSC, &csc_name);
889 887 smb_kshare_csc_flags(&tmp, csc_name);
890 888
891 889 shr = kmem_cache_alloc(smb_kshare_cache_share, KM_SLEEP);
892 890 bzero(shr, sizeof (smb_kshare_t));
893 891
894 892 shr->shr_magic = SMB_SHARE_MAGIC;
895 893 shr->shr_refcnt = 1;
896 894
897 895 shr->shr_name = smb_mem_strdup(tmp.shr_name);
898 896 shr->shr_path = smb_mem_strdup(tmp.shr_path);
899 897 if (tmp.shr_cmnt)
900 898 shr->shr_cmnt = smb_mem_strdup(tmp.shr_cmnt);
901 899 if (tmp.shr_container)
902 900 shr->shr_container = smb_mem_strdup(tmp.shr_container);
903 901 if (tmp.shr_access_none)
904 902 shr->shr_access_none = smb_mem_strdup(tmp.shr_access_none);
905 903 if (tmp.shr_access_ro)
906 904 shr->shr_access_ro = smb_mem_strdup(tmp.shr_access_ro);
907 905 if (tmp.shr_access_rw)
908 906 shr->shr_access_rw = smb_mem_strdup(tmp.shr_access_rw);
909 907
910 908 shr->shr_oemname = smb_kshare_oemname(shr->shr_name);
911 909 shr->shr_flags = tmp.shr_flags | smb_kshare_is_admin(shr->shr_name);
912 910 shr->shr_type = tmp.shr_type | smb_kshare_is_special(shr->shr_name);
913 911
914 912 shr->shr_uid = tmp.shr_uid;
915 913 shr->shr_gid = tmp.shr_gid;
916 914
917 915 if ((shr->shr_flags & SMB_SHRF_AUTOHOME) == SMB_SHRF_AUTOHOME)
918 916 shr->shr_autocnt = 1;
919 917
920 918 return (shr);
921 919 }
922 920
923 921 #if 0
924 922 static void
925 923 smb_kshare_log(smb_kshare_t *shr)
926 924 {
927 925 cmn_err(CE_NOTE, "Share info:");
928 926 cmn_err(CE_NOTE, "\tname: %s", (shr->shr_name) ? shr->shr_name : "");
929 927 cmn_err(CE_NOTE, "\tpath: %s", (shr->shr_path) ? shr->shr_path : "");
930 928 cmn_err(CE_NOTE, "\tcmnt: (%s)",
931 929 (shr->shr_cmnt) ? shr->shr_cmnt : "NULL");
932 930 cmn_err(CE_NOTE, "\toemname: (%s)",
933 931 (shr->shr_oemname) ? shr->shr_oemname : "NULL");
934 932 cmn_err(CE_NOTE, "\tflags: %X", shr->shr_flags);
935 933 cmn_err(CE_NOTE, "\ttype: %d", shr->shr_type);
936 934 }
937 935 #endif
938 936
939 937 /*
940 938 * Compare function used by shares AVL
941 939 */
942 940 static int
943 941 smb_kshare_cmp(const void *p1, const void *p2)
944 942 {
945 943 smb_kshare_t *shr1 = (smb_kshare_t *)p1;
946 944 smb_kshare_t *shr2 = (smb_kshare_t *)p2;
947 945 int rc;
948 946
949 947 ASSERT(shr1);
950 948 ASSERT(shr1->shr_name);
951 949
952 950 ASSERT(shr2);
953 951 ASSERT(shr2->shr_name);
954 952
955 953 rc = smb_strcasecmp(shr1->shr_name, shr2->shr_name, 0);
956 954
957 955 if (rc < 0)
958 956 return (-1);
959 957
960 958 if (rc > 0)
961 959 return (1);
962 960
963 961 return (0);
964 962 }
965 963
966 964 /*
967 965 * This function is called by smb_avl routines whenever
968 966 * there is a need to take a hold on a share structure
969 967 * inside AVL
970 968 */
971 969 static void
972 970 smb_kshare_hold(const void *p)
973 971 {
974 972 smb_kshare_t *shr = (smb_kshare_t *)p;
975 973
976 974 ASSERT(shr);
977 975 ASSERT(shr->shr_magic == SMB_SHARE_MAGIC);
978 976
979 977 mutex_enter(&shr->shr_mutex);
980 978 shr->shr_refcnt++;
981 979 mutex_exit(&shr->shr_mutex);
982 980 }
983 981
984 982 /*
985 983 * This function must be called by smb_avl routines whenever
986 984 * smb_kshare_hold is called and the hold needs to be released.
987 985 */
988 986 static boolean_t
989 987 smb_kshare_rele(const void *p)
990 988 {
991 989 smb_kshare_t *shr = (smb_kshare_t *)p;
992 990 boolean_t destroy;
993 991
994 992 ASSERT(shr);
995 993 ASSERT(shr->shr_magic == SMB_SHARE_MAGIC);
996 994
997 995 mutex_enter(&shr->shr_mutex);
998 996 ASSERT(shr->shr_refcnt > 0);
999 997 shr->shr_refcnt--;
1000 998 destroy = (shr->shr_refcnt == 0);
1001 999 mutex_exit(&shr->shr_mutex);
1002 1000
1003 1001 return (destroy);
1004 1002 }
1005 1003
1006 1004 /*
1007 1005 * Frees all the memory allocated for the given
1008 1006 * share structure. It also removes the structure
1009 1007 * from the share cache.
1010 1008 */
1011 1009 static void
1012 1010 smb_kshare_destroy(void *p)
1013 1011 {
1014 1012 smb_kshare_t *shr = (smb_kshare_t *)p;
1015 1013
1016 1014 ASSERT(shr);
1017 1015 ASSERT(shr->shr_magic == SMB_SHARE_MAGIC);
1018 1016
1019 1017 smb_mem_free(shr->shr_name);
1020 1018 smb_mem_free(shr->shr_path);
1021 1019 smb_mem_free(shr->shr_cmnt);
1022 1020 smb_mem_free(shr->shr_container);
1023 1021 smb_mem_free(shr->shr_oemname);
1024 1022 smb_mem_free(shr->shr_access_none);
1025 1023 smb_mem_free(shr->shr_access_ro);
1026 1024 smb_mem_free(shr->shr_access_rw);
1027 1025
1028 1026 kmem_cache_free(smb_kshare_cache_share, shr);
1029 1027 }
1030 1028
1031 1029
1032 1030 /*
1033 1031 * Generate an OEM name for the given share name. If the name is
1034 1032 * shorter than 13 bytes the oemname will be returned; otherwise NULL
1035 1033 * is returned.
1036 1034 */
1037 1035 static char *
1038 1036 smb_kshare_oemname(const char *shrname)
1039 1037 {
1040 1038 smb_wchar_t *unibuf;
1041 1039 char *oem_name;
1042 1040 int length;
1043 1041
1044 1042 length = strlen(shrname) + 1;
1045 1043
1046 1044 oem_name = smb_mem_alloc(length);
1047 1045 unibuf = smb_mem_alloc(length * sizeof (smb_wchar_t));
1048 1046
1049 1047 (void) smb_mbstowcs(unibuf, shrname, length);
1050 1048
1051 1049 if (ucstooem(oem_name, unibuf, length, OEM_CPG_850) == 0)
1052 1050 (void) strcpy(oem_name, shrname);
1053 1051
1054 1052 smb_mem_free(unibuf);
1055 1053
1056 1054 if (strlen(oem_name) + 1 > SMB_SHARE_OEMNAME_MAX) {
1057 1055 smb_mem_free(oem_name);
1058 1056 return (NULL);
1059 1057 }
1060 1058
1061 1059 return (oem_name);
1062 1060 }
1063 1061
1064 1062 /*
1065 1063 * Special share reserved for interprocess communication (IPC$) or
1066 1064 * remote administration of the server (ADMIN$). Can also refer to
1067 1065 * administrative shares such as C$, D$, E$, and so forth.
1068 1066 */
1069 1067 static int
1070 1068 smb_kshare_is_special(const char *sharename)
1071 1069 {
1072 1070 int len;
1073 1071
1074 1072 if (sharename == NULL)
1075 1073 return (0);
1076 1074
1077 1075 if ((len = strlen(sharename)) == 0)
1078 1076 return (0);
1079 1077
1080 1078 if (sharename[len - 1] == '$')
1081 1079 return (STYPE_SPECIAL);
1082 1080
1083 1081 return (0);
1084 1082 }
1085 1083
1086 1084 /*
1087 1085 * Check whether or not this is a default admin share: C$, D$ etc.
1088 1086 */
1089 1087 static boolean_t
1090 1088 smb_kshare_is_admin(const char *sharename)
1091 1089 {
1092 1090 if (sharename == NULL)
1093 1091 return (B_FALSE);
1094 1092
1095 1093 if (strlen(sharename) == 2 &&
1096 1094 smb_isalpha(sharename[0]) && sharename[1] == '$') {
1097 1095 return (B_TRUE);
1098 1096 }
1099 1097
1100 1098 return (B_FALSE);
1101 1099 }
1102 1100
1103 1101 /*
1104 1102 * Decodes the given boolean share option.
1105 1103 * If the option is present in the nvlist and it's value is true
1106 1104 * returns the corresponding flag value, otherwise returns 0.
1107 1105 */
1108 1106 static uint32_t
1109 1107 smb_kshare_decode_bool(nvlist_t *nvl, const char *propname, uint32_t flag)
1110 1108 {
1111 1109 char *boolp;
1112 1110
1113 1111 if (nvlist_lookup_string(nvl, propname, &boolp) == 0)
1114 1112 if (strcasecmp(boolp, "true") == 0)
1115 1113 return (flag);
1116 1114
1117 1115 return (0);
1118 1116 }
1119 1117
1120 1118 /*
1121 1119 * Map a client-side caching (CSC) option to the appropriate share
1122 1120 * flag. Only one option is allowed; an error will be logged if
1123 1121 * multiple options have been specified. We don't need to do anything
1124 1122 * about multiple values here because the SRVSVC will not recognize
1125 1123 * a value containing multiple flags and will return the default value.
1126 1124 *
1127 1125 * If the option value is not recognized, it will be ignored: invalid
1128 1126 * values will typically be caught and rejected by sharemgr.
1129 1127 */
1130 1128 static void
1131 1129 smb_kshare_csc_flags(smb_kshare_t *shr, const char *value)
1132 1130 {
1133 1131 int i;
1134 1132 static struct {
1135 1133 char *value;
1136 1134 uint32_t flag;
1137 1135 } cscopt[] = {
1138 1136 { "disabled", SMB_SHRF_CSC_DISABLED },
1139 1137 { "manual", SMB_SHRF_CSC_MANUAL },
1140 1138 { "auto", SMB_SHRF_CSC_AUTO },
1141 1139 { "vdo", SMB_SHRF_CSC_VDO }
1142 1140 };
1143 1141
1144 1142 if (value == NULL)
1145 1143 return;
1146 1144
1147 1145 for (i = 0; i < (sizeof (cscopt) / sizeof (cscopt[0])); ++i) {
1148 1146 if (strcasecmp(value, cscopt[i].value) == 0) {
1149 1147 shr->shr_flags |= cscopt[i].flag;
1150 1148 break;
1151 1149 }
1152 1150 }
1153 1151
1154 1152 switch (shr->shr_flags & SMB_SHRF_CSC_MASK) {
1155 1153 case 0:
1156 1154 case SMB_SHRF_CSC_DISABLED:
1157 1155 case SMB_SHRF_CSC_MANUAL:
1158 1156 case SMB_SHRF_CSC_AUTO:
1159 1157 case SMB_SHRF_CSC_VDO:
1160 1158 break;
1161 1159
1162 1160 default:
1163 1161 cmn_err(CE_NOTE, "csc option conflict: 0x%08x",
1164 1162 shr->shr_flags & SMB_SHRF_CSC_MASK);
1165 1163 break;
1166 1164 }
1167 1165 }
1168 1166
1169 1167 /*
1170 1168 * This function processes the unexport event list and disconnects shares
1171 1169 * asynchronously. The function executes as a zone-specific thread.
1172 1170 *
1173 1171 * The server arg passed in is safe to use without a reference count, because
1174 1172 * the server cannot be deleted until smb_thread_stop()/destroy() return,
1175 1173 * which is also when the thread exits.
1176 1174 */
1177 1175 /*ARGSUSED*/
1178 1176 static void
1179 1177 smb_kshare_unexport_thread(smb_thread_t *thread, void *arg)
1180 1178 {
1181 1179 smb_server_t *sv = arg;
1182 1180 smb_unshare_t *ux;
1183 1181
1184 1182 while (smb_thread_continue(thread)) {
1185 1183 while ((ux = list_head(&sv->sv_export.e_unexport_list.sl_list))
1186 1184 != NULL) {
1187 1185 smb_slist_remove(&sv->sv_export.e_unexport_list, ux);
1188 1186 (void) smb_server_unshare(ux->us_sharename);
1189 1187 kmem_cache_free(smb_kshare_cache_unexport, ux);
1190 1188 }
1191 1189 }
1192 1190 }
1193 1191
1194 1192 static boolean_t
1195 1193 smb_export_isready(smb_server_t *sv)
1196 1194 {
1197 1195 boolean_t ready;
1198 1196
1199 1197 mutex_enter(&sv->sv_export.e_mutex);
1200 1198 ready = sv->sv_export.e_ready;
1201 1199 mutex_exit(&sv->sv_export.e_mutex);
1202 1200
1203 1201 return (ready);
1204 1202 }
1205 1203
1206 1204 #ifdef _KERNEL
1207 1205 /*
1208 1206 * Return 0 upon success. Otherwise > 0
1209 1207 */
1210 1208 static int
1211 1209 smb_kshare_chk_dsrv_status(int opcode, smb_dr_ctx_t *dec_ctx)
1212 1210 {
1213 1211 int status = smb_dr_get_int32(dec_ctx);
1214 1212 int err;
1215 1213
1216 1214 switch (status) {
1217 1215 case SMB_SHARE_DSUCCESS:
1218 1216 return (0);
1219 1217
1220 1218 case SMB_SHARE_DERROR:
1221 1219 err = smb_dr_get_uint32(dec_ctx);
1222 1220 cmn_err(CE_WARN, "%d: Encountered door server error %d",
1223 1221 opcode, err);
1224 1222 (void) smb_dr_decode_finish(dec_ctx);
1225 1223 return (err);
1226 1224 }
1227 1225
1228 1226 ASSERT(0);
1229 1227 return (EINVAL);
1230 1228 }
1231 1229 #endif /* _KERNEL */
↓ open down ↓ |
727 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX