Print this page
6879933 Let SMBFS support extensible attributes per. PSARC 2007/315
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_client.c
+++ new/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_client.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) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 *
25 25 * Copyright (c) 1983,1984,1985,1986,1987,1988,1989 AT&T.
26 26 * All rights reserved.
27 27 */
28 28
29 29 #include <sys/param.h>
30 30 #include <sys/systm.h>
31 31 #include <sys/thread.h>
32 32 #include <sys/t_lock.h>
33 33 #include <sys/time.h>
34 34 #include <sys/vnode.h>
35 35 #include <sys/vfs.h>
36 36 #include <sys/errno.h>
37 37 #include <sys/buf.h>
38 38 #include <sys/stat.h>
39 39 #include <sys/cred.h>
40 40 #include <sys/kmem.h>
41 41 #include <sys/debug.h>
42 42 #include <sys/vmsystm.h>
43 43 #include <sys/flock.h>
44 44 #include <sys/share.h>
45 45 #include <sys/cmn_err.h>
46 46 #include <sys/tiuser.h>
47 47 #include <sys/sysmacros.h>
48 48 #include <sys/callb.h>
49 49 #include <sys/acl.h>
50 50 #include <sys/kstat.h>
51 51 #include <sys/signal.h>
52 52 #include <sys/list.h>
53 53 #include <sys/zone.h>
54 54
55 55 #include <netsmb/smb.h>
56 56 #include <netsmb/smb_conn.h>
57 57 #include <netsmb/smb_subr.h>
58 58
59 59 #include <smbfs/smbfs.h>
60 60 #include <smbfs/smbfs_node.h>
↓ open down ↓ |
60 lines elided |
↑ open up ↑ |
61 61 #include <smbfs/smbfs_subr.h>
62 62
63 63 #include <vm/hat.h>
64 64 #include <vm/as.h>
65 65 #include <vm/page.h>
66 66 #include <vm/pvn.h>
67 67 #include <vm/seg.h>
68 68 #include <vm/seg_map.h>
69 69 #include <vm/seg_vn.h>
70 70
71 -static int smbfs_getattr_cache(vnode_t *, struct smbfattr *);
72 -static int smbfattr_to_vattr(vnode_t *, struct smbfattr *,
73 - struct vattr *);
71 +static int smbfs_getattr_cache(vnode_t *, smbfattr_t *);
72 +static void smbfattr_to_vattr(vnode_t *, smbfattr_t *, vattr_t *);
73 +static void smbfattr_to_xvattr(vnode_t *, smbfattr_t *, vattr_t *);
74 74
75 75 /*
76 76 * The following code provide zone support in order to perform an action
77 77 * for each smbfs mount in a zone. This is also where we would add
78 78 * per-zone globals and kernel threads for the smbfs module (since
79 79 * they must be terminated by the shutdown callback).
80 80 */
81 81
82 82 struct smi_globals {
83 83 kmutex_t smg_lock; /* lock protecting smg_list */
84 84 list_t smg_list; /* list of SMBFS mounts in zone */
85 85 boolean_t smg_destructor_called;
86 86 };
87 87 typedef struct smi_globals smi_globals_t;
88 88
89 89 static zone_key_t smi_list_key;
90 90
91 91 /*
92 92 * Attributes caching:
93 93 *
94 94 * Attributes are cached in the smbnode in struct vattr form.
95 95 * There is a time associated with the cached attributes (r_attrtime)
96 96 * which tells whether the attributes are valid. The time is initialized
97 97 * to the difference between current time and the modify time of the vnode
98 98 * when new attributes are cached. This allows the attributes for
99 99 * files that have changed recently to be timed out sooner than for files
100 100 * that have not changed for a long time. There are minimum and maximum
101 101 * timeout values that can be set per mount point.
102 102 */
103 103
104 104 /*
105 105 * Validate caches by checking cached attributes. If they have timed out
106 106 * get the attributes from the server and compare mtimes. If mtimes are
107 107 * different purge all caches for this vnode.
108 108 */
109 109 int
110 110 smbfs_validate_caches(
111 111 struct vnode *vp,
112 112 cred_t *cr)
113 113 {
114 114 struct vattr va;
115 115
116 116 va.va_mask = AT_SIZE;
117 117 return (smbfsgetattr(vp, &va, cr));
118 118 }
119 119
120 120 /*
121 121 * Purge all of the various data caches.
122 122 */
123 123 /*ARGSUSED*/
124 124 void
125 125 smbfs_purge_caches(struct vnode *vp)
126 126 {
127 127 #if 0 /* not yet: mmap support */
128 128 /*
129 129 * NFS: Purge the DNLC for this vp,
130 130 * Clear any readdir state bits,
131 131 * the readlink response cache, ...
132 132 */
133 133 smbnode_t *np = VTOSMB(vp);
134 134
135 135 /*
136 136 * Flush the page cache.
137 137 */
138 138 if (vn_has_cached_data(vp)) {
139 139 (void) VOP_PUTPAGE(vp, (u_offset_t)0, 0, B_INVAL, cr, NULL);
140 140 }
141 141 #endif /* not yet */
142 142 }
143 143
144 144 /*
145 145 * Check the attribute cache to see if the new attributes match
146 146 * those cached. If they do, the various `data' caches are
147 147 * considered to be good. Otherwise, purge the cached data.
148 148 */
149 149 void
150 150 smbfs_cache_check(
151 151 struct vnode *vp,
152 152 struct smbfattr *fap)
153 153 {
154 154 smbnode_t *np;
155 155 int purge_data = 0;
156 156 int purge_acl = 0;
157 157
158 158 np = VTOSMB(vp);
159 159 mutex_enter(&np->r_statelock);
160 160
161 161 /*
162 162 * Compare with NFS macro: CACHE_VALID
163 163 * If the mtime or size has changed,
164 164 * purge cached data.
165 165 */
166 166 if (np->r_attr.fa_mtime.tv_sec != fap->fa_mtime.tv_sec ||
167 167 np->r_attr.fa_mtime.tv_nsec != fap->fa_mtime.tv_nsec)
168 168 purge_data = 1;
169 169 if (np->r_attr.fa_size != fap->fa_size)
170 170 purge_data = 1;
171 171
172 172 if (np->r_attr.fa_ctime.tv_sec != fap->fa_ctime.tv_sec ||
173 173 np->r_attr.fa_ctime.tv_nsec != fap->fa_ctime.tv_nsec)
174 174 purge_acl = 1;
175 175
176 176 if (purge_acl) {
177 177 /* just invalidate r_secattr (XXX: OK?) */
178 178 np->r_sectime = gethrtime();
179 179 }
180 180
181 181 mutex_exit(&np->r_statelock);
182 182
183 183 if (purge_data)
184 184 smbfs_purge_caches(vp);
185 185 }
186 186
187 187 /*
188 188 * Set attributes cache for given vnode using vnode attributes.
189 189 * From NFS: nfs_attrcache_va
190 190 */
191 191 #if 0 /* not yet (not sure if we need this) */
192 192 void
193 193 smbfs_attrcache_va(vnode_t *vp, struct vattr *vap)
194 194 {
195 195 smbfattr_t fa;
196 196 smbnode_t *np;
197 197
198 198 vattr_to_fattr(vp, vap, &fa);
199 199 smbfs_attrcache_fa(vp, &fa);
200 200 }
201 201 #endif /* not yet */
202 202
203 203 /*
204 204 * Set attributes cache for given vnode using SMB fattr
205 205 * and update the attribute cache timeout.
206 206 *
207 207 * From NFS: nfs_attrcache, nfs_attrcache_va
208 208 */
209 209 void
210 210 smbfs_attrcache_fa(vnode_t *vp, struct smbfattr *fap)
211 211 {
212 212 smbnode_t *np;
213 213 smbmntinfo_t *smi;
214 214 hrtime_t delta, now;
215 215 u_offset_t newsize;
216 216 vtype_t vtype, oldvt;
217 217 mode_t mode;
218 218
219 219 np = VTOSMB(vp);
220 220 smi = VTOSMI(vp);
221 221
222 222 /*
223 223 * We allow v_type to change, so set that here
224 224 * (and the mode, which depends on the type).
225 225 */
226 226 if (fap->fa_attr & SMB_FA_DIR) {
227 227 vtype = VDIR;
228 228 mode = smi->smi_dmode;
229 229 } else {
230 230 vtype = VREG;
231 231 mode = smi->smi_fmode;
232 232 }
233 233
234 234 mutex_enter(&np->r_statelock);
235 235 now = gethrtime();
236 236
237 237 /*
238 238 * Delta is the number of nanoseconds that we will
239 239 * cache the attributes of the file. It is based on
240 240 * the number of nanoseconds since the last time that
241 241 * we detected a change. The assumption is that files
242 242 * that changed recently are likely to change again.
243 243 * There is a minimum and a maximum for regular files
244 244 * and for directories which is enforced though.
245 245 *
246 246 * Using the time since last change was detected
247 247 * eliminates direct comparison or calculation
248 248 * using mixed client and server times. SMBFS
249 249 * does not make any assumptions regarding the
250 250 * client and server clocks being synchronized.
251 251 */
252 252 if (fap->fa_mtime.tv_sec != np->r_attr.fa_mtime.tv_sec ||
253 253 fap->fa_mtime.tv_nsec != np->r_attr.fa_mtime.tv_nsec ||
254 254 fap->fa_size != np->r_attr.fa_size)
255 255 np->r_mtime = now;
256 256
257 257 if ((smi->smi_flags & SMI_NOAC) || (vp->v_flag & VNOCACHE))
258 258 delta = 0;
259 259 else {
260 260 delta = now - np->r_mtime;
261 261 if (vtype == VDIR) {
262 262 if (delta < smi->smi_acdirmin)
263 263 delta = smi->smi_acdirmin;
264 264 else if (delta > smi->smi_acdirmax)
265 265 delta = smi->smi_acdirmax;
266 266 } else {
267 267 if (delta < smi->smi_acregmin)
268 268 delta = smi->smi_acregmin;
269 269 else if (delta > smi->smi_acregmax)
270 270 delta = smi->smi_acregmax;
271 271 }
272 272 }
273 273
274 274 np->r_attrtime = now + delta;
275 275 np->r_attr = *fap;
276 276 np->n_mode = mode;
277 277 oldvt = vp->v_type;
278 278 vp->v_type = vtype;
279 279
280 280 /*
281 281 * Shall we update r_size? (local notion of size)
282 282 *
283 283 * The real criteria for updating r_size should be:
284 284 * if the file has grown on the server, or if
285 285 * the client has not modified the file.
286 286 *
287 287 * Also deal with the fact that SMB presents
288 288 * directories as having size=0. Doing that
289 289 * here and leaving fa_size as returned OtW
290 290 * avoids fixing the size lots of places.
291 291 */
292 292 newsize = fap->fa_size;
293 293 if (vtype == VDIR && newsize < DEV_BSIZE)
294 294 newsize = DEV_BSIZE;
295 295
296 296 if (np->r_size != newsize) {
297 297 #if 0 /* not yet: mmap support */
298 298 if (!vn_has_cached_data(vp) || ...)
299 299 /* XXX: See NFS page cache code. */
300 300 #endif /* not yet */
301 301 /* OK to set the size. */
302 302 np->r_size = newsize;
303 303 }
304 304
305 305 /* NFS: np->r_flags &= ~RWRITEATTR; */
306 306 np->n_flag &= ~NATTRCHANGED;
307 307
308 308 mutex_exit(&np->r_statelock);
309 309
310 310 if (oldvt != vtype) {
311 311 SMBVDEBUG("vtype change %d to %d\n", oldvt, vtype);
312 312 }
313 313 }
314 314
315 315 /*
316 316 * Fill in attribute from the cache.
317 317 *
318 318 * If valid, copy to *fap and return zero,
319 319 * otherwise return an error.
320 320 *
321 321 * From NFS: nfs_getattr_cache()
322 322 */
323 323 int
324 324 smbfs_getattr_cache(vnode_t *vp, struct smbfattr *fap)
325 325 {
326 326 smbnode_t *np;
327 327 int error;
328 328
329 329 np = VTOSMB(vp);
330 330
331 331 mutex_enter(&np->r_statelock);
332 332 if (gethrtime() >= np->r_attrtime) {
333 333 /* cache expired */
334 334 error = ENOENT;
335 335 } else {
336 336 /* cache is valid */
337 337 *fap = np->r_attr;
338 338 error = 0;
339 339 }
340 340 mutex_exit(&np->r_statelock);
341 341
342 342 return (error);
343 343 }
344 344
345 345 /*
346 346 * Get attributes over-the-wire and update attributes cache
347 347 * if no error occurred in the over-the-wire operation.
348 348 * Return 0 if successful, otherwise error.
349 349 * From NFS: nfs_getattr_otw
350 350 */
351 351 int
352 352 smbfs_getattr_otw(vnode_t *vp, struct smbfattr *fap, cred_t *cr)
353 353 {
354 354 struct smbnode *np;
355 355 struct smb_cred scred;
356 356 int error;
357 357
358 358 np = VTOSMB(vp);
359 359
360 360 /*
361 361 * NFS uses the ACL rpc here (if smi_flags & SMI_ACL)
362 362 * With SMB, getting the ACL is a significantly more
363 363 * expensive operation, so we do that only when asked
364 364 * for the uid/gid. See smbfsgetattr().
365 365 */
366 366
367 367 /* Shared lock for (possible) n_fid use. */
368 368 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
369 369 return (EINTR);
370 370 smb_credinit(&scred, cr);
371 371
372 372 bzero(fap, sizeof (*fap));
373 373 error = smbfs_smb_getfattr(np, fap, &scred);
374 374
375 375 smb_credrele(&scred);
376 376 smbfs_rw_exit(&np->r_lkserlock);
377 377
378 378 if (error) {
379 379 /* NFS had: PURGE_STALE_FH(error, vp, cr) */
380 380 smbfs_attrcache_remove(np);
381 381 if (error == ENOENT || error == ENOTDIR) {
382 382 /*
383 383 * Getattr failed because the object was
384 384 * removed or renamed by another client.
385 385 * Remove any cached attributes under it.
386 386 */
387 387 smbfs_attrcache_prune(np);
388 388 }
389 389 return (error);
390 390 }
391 391
392 392 /*
393 393 * NFS: smbfs_cache_fattr(vap, fa, vap, t, cr);
394 394 * which did: fattr_to_vattr, nfs_attr_cache.
395 395 * We cache the fattr form, so just do the
396 396 * cache check and store the attributes.
397 397 */
398 398 smbfs_cache_check(vp, fap);
399 399 smbfs_attrcache_fa(vp, fap);
400 400
401 401 return (0);
402 402 }
403 403
404 404 /*
405 405 * Return either cached or remote attributes. If get remote attr
406 406 * use them to check and invalidate caches, then cache the new attributes.
407 407 *
408 408 * From NFS: nfsgetattr()
409 409 */
410 410 int
411 411 smbfsgetattr(vnode_t *vp, struct vattr *vap, cred_t *cr)
412 412 {
413 413 struct smbfattr fa;
414 414 smbmntinfo_t *smi;
415 415 uint_t mask;
416 416 int error;
417 417
418 418 smi = VTOSMI(vp);
419 419
420 420 ASSERT(curproc->p_zone == smi->smi_zone_ref.zref_zone);
421 421
422 422 /*
423 423 * If asked for UID or GID, update n_uid, n_gid.
424 424 */
425 425 mask = AT_ALL;
426 426 if (vap->va_mask & (AT_UID | AT_GID)) {
427 427 if (smi->smi_flags & SMI_ACL)
428 428 (void) smbfs_acl_getids(vp, cr);
429 429 /* else leave as set in make_smbnode */
430 430 } else {
431 431 mask &= ~(AT_UID | AT_GID);
432 432 }
433 433
↓ open down ↓ |
350 lines elided |
↑ open up ↑ |
434 434 /*
435 435 * If we've got cached attributes, just use them;
436 436 * otherwise go to the server to get attributes,
437 437 * which will update the cache in the process.
438 438 */
439 439 error = smbfs_getattr_cache(vp, &fa);
440 440 if (error)
441 441 error = smbfs_getattr_otw(vp, &fa, cr);
442 442 if (error)
443 443 return (error);
444 + vap->va_mask |= mask;
444 445
445 446 /*
446 447 * Re. client's view of the file size, see:
447 448 * smbfs_attrcache_fa, smbfs_getattr_otw
448 449 */
449 -
450 - error = smbfattr_to_vattr(vp, &fa, vap);
451 - vap->va_mask = mask;
452 -
453 - return (error);
450 + smbfattr_to_vattr(vp, &fa, vap);
451 + if (vap->va_mask & AT_XVATTR)
452 + smbfattr_to_xvattr(vp, &fa, vap);
453 +
454 + return (0);
454 455 }
455 456
456 457
457 458 /*
458 459 * Convert SMB over the wire attributes to vnode form.
459 460 * Returns 0 for success, error if failed (overflow, etc).
460 461 * From NFS: nattr_to_vattr()
461 462 */
462 -int
463 +void
463 464 smbfattr_to_vattr(vnode_t *vp, struct smbfattr *fa, struct vattr *vap)
464 465 {
465 466 struct smbnode *np = VTOSMB(vp);
466 467
467 - /* Set va_mask in caller */
468 -
469 468 /*
470 469 * Take type, mode, uid, gid from the smbfs node,
471 470 * which has have been updated by _getattr_otw.
472 471 */
473 472 vap->va_type = vp->v_type;
474 473 vap->va_mode = np->n_mode;
475 474
476 475 vap->va_uid = np->n_uid;
477 476 vap->va_gid = np->n_gid;
478 477
479 478 vap->va_fsid = vp->v_vfsp->vfs_dev;
480 479 vap->va_nodeid = np->n_ino;
481 480 vap->va_nlink = 1;
482 481
483 482 /*
484 483 * Difference from NFS here: We cache attributes as
485 484 * reported by the server, so r_attr.fa_size is the
486 485 * server's idea of the file size. This is called
487 486 * for getattr, so we want to return the client's
488 487 * idea of the file size. NFS deals with that in
489 488 * nfsgetattr(), the equivalent of our caller.
490 489 */
491 490 vap->va_size = np->r_size;
492 491
493 492 /*
494 493 * Times. Note, already converted from NT to
495 494 * Unix form (in the unmarshalling code).
496 495 */
497 496 vap->va_atime = fa->fa_atime;
498 497 vap->va_mtime = fa->fa_mtime;
↓ open down ↓ |
20 lines elided |
↑ open up ↑ |
499 498 vap->va_ctime = fa->fa_ctime;
500 499
501 500 /*
502 501 * rdev, blksize, seq are made up.
503 502 * va_nblocks is 512 byte blocks.
504 503 */
505 504 vap->va_rdev = vp->v_rdev;
506 505 vap->va_blksize = MAXBSIZE;
507 506 vap->va_nblocks = (fsblkcnt64_t)btod(np->r_attr.fa_allocsz);
508 507 vap->va_seq = 0;
509 -
510 - return (0);
511 508 }
512 509
510 +/*
511 + * smbfattr_to_xvattr: like smbfattr_to_vattr but for
512 + * Extensible system attributes (PSARC 2007/315)
513 + */
514 +static void
515 +smbfattr_to_xvattr(vnode_t *vp, struct smbfattr *fa, struct vattr *vap)
516 +{
517 + struct smbnode *np = VTOSMB(vp);
518 + xvattr_t *xvap = (xvattr_t *)vap; /* *vap may be xvattr_t */
519 + xoptattr_t *xoap = NULL;
513 520
521 + if ((xoap = xva_getxoptattr(xvap)) == NULL)
522 + return;
523 +
524 + if (XVA_ISSET_REQ(xvap, XAT_CREATETIME)) {
525 + xoap->xoa_createtime = fa->fa_createtime;
526 + XVA_SET_RTN(xvap, XAT_CREATETIME);
527 + }
528 +
529 + if (XVA_ISSET_REQ(xvap, XAT_ARCHIVE)) {
530 + xoap->xoa_archive =
531 + ((fa->fa_attr & SMB_FA_ARCHIVE) != 0);
532 + XVA_SET_RTN(xvap, XAT_ARCHIVE);
533 + }
534 +
535 + if (XVA_ISSET_REQ(xvap, XAT_SYSTEM)) {
536 + xoap->xoa_system =
537 + ((fa->fa_attr & SMB_FA_SYSTEM) != 0);
538 + XVA_SET_RTN(xvap, XAT_SYSTEM);
539 + }
540 +
541 + if (XVA_ISSET_REQ(xvap, XAT_READONLY)) {
542 + xoap->xoa_readonly =
543 + ((fa->fa_attr & SMB_FA_RDONLY) != 0);
544 + XVA_SET_RTN(xvap, XAT_READONLY);
545 + }
546 +
547 + if (XVA_ISSET_REQ(xvap, XAT_HIDDEN)) {
548 + xoap->xoa_hidden =
549 + ((fa->fa_attr & SMB_FA_HIDDEN) != 0);
550 + XVA_SET_RTN(xvap, XAT_HIDDEN);
551 + }
552 +}
553 +
514 554 /*
515 555 * SMB Client initialization and cleanup.
516 556 * Much of it is per-zone now.
517 557 */
518 558
519 559
520 560 /* ARGSUSED */
521 561 static void *
522 562 smbfs_zone_init(zoneid_t zoneid)
523 563 {
524 564 smi_globals_t *smg;
525 565
526 566 smg = kmem_alloc(sizeof (*smg), KM_SLEEP);
527 567 mutex_init(&smg->smg_lock, NULL, MUTEX_DEFAULT, NULL);
528 568 list_create(&smg->smg_list, sizeof (smbmntinfo_t),
529 569 offsetof(smbmntinfo_t, smi_zone_node));
530 570 smg->smg_destructor_called = B_FALSE;
531 571 return (smg);
532 572 }
533 573
534 574 /*
535 575 * Callback routine to tell all SMBFS mounts in the zone to stop creating new
536 576 * threads. Existing threads should exit.
537 577 */
538 578 /* ARGSUSED */
539 579 static void
540 580 smbfs_zone_shutdown(zoneid_t zoneid, void *data)
541 581 {
542 582 smi_globals_t *smg = data;
543 583 smbmntinfo_t *smi;
544 584
545 585 ASSERT(smg != NULL);
546 586 again:
547 587 mutex_enter(&smg->smg_lock);
548 588 for (smi = list_head(&smg->smg_list); smi != NULL;
549 589 smi = list_next(&smg->smg_list, smi)) {
550 590
551 591 /*
552 592 * If we've done the shutdown work for this FS, skip.
553 593 * Once we go off the end of the list, we're done.
554 594 */
555 595 if (smi->smi_flags & SMI_DEAD)
556 596 continue;
557 597
558 598 /*
559 599 * We will do work, so not done. Get a hold on the FS.
560 600 */
561 601 VFS_HOLD(smi->smi_vfsp);
562 602
563 603 mutex_enter(&smi->smi_lock);
564 604 smi->smi_flags |= SMI_DEAD;
565 605 mutex_exit(&smi->smi_lock);
566 606
567 607 /*
568 608 * Drop lock and release FS, which may change list, then repeat.
569 609 * We're done when every mi has been done or the list is empty.
570 610 */
571 611 mutex_exit(&smg->smg_lock);
572 612 VFS_RELE(smi->smi_vfsp);
573 613 goto again;
574 614 }
575 615 mutex_exit(&smg->smg_lock);
576 616 }
577 617
578 618 static void
579 619 smbfs_zone_free_globals(smi_globals_t *smg)
580 620 {
581 621 list_destroy(&smg->smg_list); /* makes sure the list is empty */
582 622 mutex_destroy(&smg->smg_lock);
583 623 kmem_free(smg, sizeof (*smg));
584 624
585 625 }
586 626
587 627 /* ARGSUSED */
588 628 static void
589 629 smbfs_zone_destroy(zoneid_t zoneid, void *data)
590 630 {
591 631 smi_globals_t *smg = data;
592 632
593 633 ASSERT(smg != NULL);
594 634 mutex_enter(&smg->smg_lock);
595 635 if (list_head(&smg->smg_list) != NULL) {
596 636 /* Still waiting for VFS_FREEVFS() */
597 637 smg->smg_destructor_called = B_TRUE;
598 638 mutex_exit(&smg->smg_lock);
599 639 return;
600 640 }
601 641 smbfs_zone_free_globals(smg);
602 642 }
603 643
604 644 /*
605 645 * Add an SMBFS mount to the per-zone list of SMBFS mounts.
606 646 */
607 647 void
608 648 smbfs_zonelist_add(smbmntinfo_t *smi)
609 649 {
610 650 smi_globals_t *smg;
611 651
612 652 smg = zone_getspecific(smi_list_key, smi->smi_zone_ref.zref_zone);
613 653 mutex_enter(&smg->smg_lock);
614 654 list_insert_head(&smg->smg_list, smi);
615 655 mutex_exit(&smg->smg_lock);
616 656 }
617 657
618 658 /*
619 659 * Remove an SMBFS mount from the per-zone list of SMBFS mounts.
620 660 */
621 661 void
622 662 smbfs_zonelist_remove(smbmntinfo_t *smi)
623 663 {
624 664 smi_globals_t *smg;
625 665
626 666 smg = zone_getspecific(smi_list_key, smi->smi_zone_ref.zref_zone);
627 667 mutex_enter(&smg->smg_lock);
628 668 list_remove(&smg->smg_list, smi);
629 669 /*
630 670 * We can be called asynchronously by VFS_FREEVFS() after the zone
631 671 * shutdown/destroy callbacks have executed; if so, clean up the zone's
632 672 * smi_globals.
633 673 */
634 674 if (list_head(&smg->smg_list) == NULL &&
635 675 smg->smg_destructor_called == B_TRUE) {
636 676 smbfs_zone_free_globals(smg);
637 677 return;
638 678 }
639 679 mutex_exit(&smg->smg_lock);
640 680 }
641 681
642 682 #ifdef lint
643 683 #define NEED_SMBFS_CALLBACKS 1
644 684 #endif
645 685
646 686 #ifdef NEED_SMBFS_CALLBACKS
647 687 /*
648 688 * Call-back hooks for netsmb, in case we want them.
649 689 * Apple's VFS wants them. We may not need them.
650 690 */
651 691 /*ARGSUSED*/
652 692 static void smbfs_dead(smb_share_t *ssp)
653 693 {
654 694 /*
655 695 * Walk the mount list, finding all mounts
656 696 * using this share...
657 697 */
658 698 }
659 699
660 700 /*ARGSUSED*/
661 701 static void smbfs_cb_nop(smb_share_t *ss)
662 702 {
663 703 /* no-op */
664 704 }
665 705
666 706 smb_fscb_t smbfs_cb = {
667 707 .fscb_disconn = smbfs_dead,
668 708 .fscb_connect = smbfs_cb_nop,
669 709 .fscb_down = smbfs_cb_nop,
670 710 .fscb_up = smbfs_cb_nop };
671 711
672 712 #endif /* NEED_SMBFS_CALLBACKS */
673 713
674 714 /*
675 715 * SMBFS Client initialization routine. This routine should only be called
676 716 * once. It performs the following tasks:
677 717 * - Initalize all global locks
678 718 * - Call sub-initialization routines (localize access to variables)
679 719 */
680 720 int
681 721 smbfs_clntinit(void)
682 722 {
683 723
684 724 zone_key_create(&smi_list_key, smbfs_zone_init, smbfs_zone_shutdown,
685 725 smbfs_zone_destroy);
686 726 #ifdef NEED_SMBFS_CALLBACKS
687 727 (void) smb_fscb_set(&smbfs_cb);
688 728 #endif /* NEED_SMBFS_CALLBACKS */
689 729 return (0);
690 730 }
691 731
692 732 /*
693 733 * This routine is called when the modunload is called. This will cleanup
694 734 * the previously allocated/initialized nodes.
695 735 */
696 736 void
697 737 smbfs_clntfini(void)
698 738 {
699 739 #ifdef NEED_SMBFS_CALLBACKS
700 740 (void) smb_fscb_set(NULL);
701 741 #endif /* NEED_SMBFS_CALLBACKS */
702 742 (void) zone_key_delete(smi_list_key);
703 743 }
↓ open down ↓ |
180 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX