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