51 #include <sys/signal.h>
52 #include <sys/list.h>
53 #include <sys/zone.h>
54
55 #include <netsmb/smb.h>
56 #include <netsmb/smb_conn.h>
57 #include <netsmb/smb_subr.h>
58
59 #include <smbfs/smbfs.h>
60 #include <smbfs/smbfs_node.h>
61 #include <smbfs/smbfs_subr.h>
62
63 #include <vm/hat.h>
64 #include <vm/as.h>
65 #include <vm/page.h>
66 #include <vm/pvn.h>
67 #include <vm/seg.h>
68 #include <vm/seg_map.h>
69 #include <vm/seg_vn.h>
70
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(smbfattr_t *, vattr_t *);
74
75 /*
76 * The following code provide zone support in order to perform an action
77 * for each smbfs mount in a zone. This is also where we would add
78 * per-zone globals and kernel threads for the smbfs module (since
79 * they must be terminated by the shutdown callback).
80 */
81
82 struct smi_globals {
83 kmutex_t smg_lock; /* lock protecting smg_list */
84 list_t smg_list; /* list of SMBFS mounts in zone */
85 boolean_t smg_destructor_called;
86 };
87 typedef struct smi_globals smi_globals_t;
88
89 static zone_key_t smi_list_key;
90
91 /*
92 * Attributes caching:
93 *
94 * Attributes are cached in the smbnode in struct vattr form.
95 * There is a time associated with the cached attributes (r_attrtime)
96 * which tells whether the attributes are valid. The time is initialized
97 * to the difference between current time and the modify time of the vnode
98 * when new attributes are cached. This allows the attributes for
99 * files that have changed recently to be timed out sooner than for files
100 * that have not changed for a long time. There are minimum and maximum
101 * timeout values that can be set per mount point.
102 */
103
104 /*
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.
108 */
109 int
110 smbfs_validate_caches(
111 struct vnode *vp,
112 cred_t *cr)
113 {
114 struct vattr va;
115
116 va.va_mask = AT_SIZE;
117 return (smbfsgetattr(vp, &va, cr));
118 }
119
120 /*
121 * Purge all of the various data caches.
122 */
123 /*ARGSUSED*/
124 void
125 smbfs_purge_caches(struct vnode *vp)
126 {
127 #if 0 /* not yet: mmap support */
128 /*
129 * NFS: Purge the DNLC for this vp,
130 * Clear any readdir state bits,
131 * the readlink response cache, ...
132 */
133 smbnode_t *np = VTOSMB(vp);
134
135 /*
136 * Flush the page cache.
137 */
138 if (vn_has_cached_data(vp)) {
139 (void) VOP_PUTPAGE(vp, (u_offset_t)0, 0, B_INVAL, cr, NULL);
140 }
141 #endif /* not yet */
142 }
143
144 /*
145 * Check the attribute cache to see if the new attributes match
146 * those cached. If they do, the various `data' caches are
147 * considered to be good. Otherwise, purge the cached data.
148 */
149 void
150 smbfs_cache_check(
151 struct vnode *vp,
152 struct smbfattr *fap)
153 {
154 smbnode_t *np;
155 int purge_data = 0;
156 int purge_acl = 0;
157
158 np = VTOSMB(vp);
159 mutex_enter(&np->r_statelock);
160
161 /*
162 * Compare with NFS macro: CACHE_VALID
163 * If the mtime or size has changed,
164 * purge cached data.
165 */
166 if (np->r_attr.fa_mtime.tv_sec != fap->fa_mtime.tv_sec ||
167 np->r_attr.fa_mtime.tv_nsec != fap->fa_mtime.tv_nsec)
168 purge_data = 1;
169 if (np->r_attr.fa_size != fap->fa_size)
170 purge_data = 1;
171
172 if (np->r_attr.fa_ctime.tv_sec != fap->fa_ctime.tv_sec ||
173 np->r_attr.fa_ctime.tv_nsec != fap->fa_ctime.tv_nsec)
174 purge_acl = 1;
175
176 if (purge_acl) {
177 /* just invalidate r_secattr (XXX: OK?) */
178 np->r_sectime = gethrtime();
179 }
180
181 mutex_exit(&np->r_statelock);
182
183 if (purge_data)
184 smbfs_purge_caches(vp);
185 }
186
187 /*
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 * Set attributes cache for given vnode using SMB fattr
205 * and update the attribute cache timeout.
206 *
207 * From NFS: nfs_attrcache, nfs_attrcache_va
208 */
209 void
210 smbfs_attrcache_fa(vnode_t *vp, struct smbfattr *fap)
211 {
212 smbnode_t *np;
213 smbmntinfo_t *smi;
214 hrtime_t delta, now;
215 u_offset_t newsize;
216 vtype_t vtype, oldvt;
217 mode_t mode;
218
219 np = VTOSMB(vp);
220 smi = VTOSMI(vp);
221
222 /*
223 * We allow v_type to change, so set that here
224 * (and the mode, which depends on the type).
225 */
226 if (fap->fa_attr & SMB_FA_DIR) {
227 vtype = VDIR;
276 np->n_mode = mode;
277 oldvt = vp->v_type;
278 vp->v_type = vtype;
279
280 /*
281 * Shall we update r_size? (local notion of size)
282 *
283 * The real criteria for updating r_size should be:
284 * if the file has grown on the server, or if
285 * the client has not modified the file.
286 *
287 * Also deal with the fact that SMB presents
288 * directories as having size=0. Doing that
289 * here and leaving fa_size as returned OtW
290 * avoids fixing the size lots of places.
291 */
292 newsize = fap->fa_size;
293 if (vtype == VDIR && newsize < DEV_BSIZE)
294 newsize = DEV_BSIZE;
295
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 */
301 /* OK to set the size. */
302 np->r_size = newsize;
303 }
304
305 /* NFS: np->r_flags &= ~RWRITEATTR; */
306 np->n_flag &= ~NATTRCHANGED;
307
308 mutex_exit(&np->r_statelock);
309
310 if (oldvt != vtype) {
311 SMBVDEBUG("vtype change %d to %d\n", oldvt, vtype);
312 }
313 }
314
315 /*
316 * Fill in attribute from the cache.
317 *
318 * If valid, copy to *fap and return zero,
319 * otherwise return an error.
320 *
321 * From NFS: nfs_getattr_cache()
322 */
323 int
324 smbfs_getattr_cache(vnode_t *vp, struct smbfattr *fap)
325 {
326 smbnode_t *np;
327 int error;
331 mutex_enter(&np->r_statelock);
332 if (gethrtime() >= np->r_attrtime) {
333 /* cache expired */
334 error = ENOENT;
335 } else {
336 /* cache is valid */
337 *fap = np->r_attr;
338 error = 0;
339 }
340 mutex_exit(&np->r_statelock);
341
342 return (error);
343 }
344
345 /*
346 * Get attributes over-the-wire and update attributes cache
347 * if no error occurred in the over-the-wire operation.
348 * Return 0 if successful, otherwise error.
349 * From NFS: nfs_getattr_otw
350 */
351 int
352 smbfs_getattr_otw(vnode_t *vp, struct smbfattr *fap, cred_t *cr)
353 {
354 struct smbnode *np;
355 struct smb_cred scred;
356 int error;
357
358 np = VTOSMB(vp);
359
360 /*
361 * NFS uses the ACL rpc here (if smi_flags & SMI_ACL)
362 * With SMB, getting the ACL is a significantly more
363 * expensive operation, so we do that only when asked
364 * for the uid/gid. See smbfsgetattr().
365 */
366
367 /* Shared lock for (possible) n_fid use. */
368 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
369 return (EINTR);
370 smb_credinit(&scred, cr);
371
372 bzero(fap, sizeof (*fap));
373 error = smbfs_smb_getfattr(np, fap, &scred);
374
375 smb_credrele(&scred);
376 smbfs_rw_exit(&np->r_lkserlock);
377
378 if (error) {
379 /* NFS had: PURGE_STALE_FH(error, vp, cr) */
380 smbfs_attrcache_remove(np);
381 if (error == ENOENT || error == ENOTDIR) {
382 /*
383 * Getattr failed because the object was
384 * removed or renamed by another client.
385 * Remove any cached attributes under it.
386 */
387 smbfs_attrcache_prune(np);
388 }
389 return (error);
390 }
391
392 /*
393 * NFS: smbfs_cache_fattr(vap, fa, vap, t, cr);
394 * which did: fattr_to_vattr, nfs_attr_cache.
395 * We cache the fattr form, so just do the
396 * cache check and store the attributes.
397 */
398 smbfs_cache_check(vp, fap);
399 smbfs_attrcache_fa(vp, fap);
400
401 return (0);
402 }
403
404 /*
405 * Return either cached or remote attributes. If get remote attr
406 * use them to check and invalidate caches, then cache the new attributes.
407 *
408 * From NFS: nfsgetattr()
409 */
410 int
411 smbfsgetattr(vnode_t *vp, struct vattr *vap, cred_t *cr)
412 {
413 struct smbfattr fa;
414 smbmntinfo_t *smi;
415 uint_t mask;
416 int error;
417
418 smi = VTOSMI(vp);
419
420 ASSERT(curproc->p_zone == smi->smi_zone_ref.zref_zone);
421
422 /*
423 * If asked for UID or GID, update n_uid, n_gid.
424 */
425 mask = AT_ALL;
532 }
533
534 if (XVA_ISSET_REQ(xvap, XAT_SYSTEM)) {
535 xoap->xoa_system =
536 ((fa->fa_attr & SMB_FA_SYSTEM) != 0);
537 XVA_SET_RTN(xvap, XAT_SYSTEM);
538 }
539
540 if (XVA_ISSET_REQ(xvap, XAT_READONLY)) {
541 xoap->xoa_readonly =
542 ((fa->fa_attr & SMB_FA_RDONLY) != 0);
543 XVA_SET_RTN(xvap, XAT_READONLY);
544 }
545
546 if (XVA_ISSET_REQ(xvap, XAT_HIDDEN)) {
547 xoap->xoa_hidden =
548 ((fa->fa_attr & SMB_FA_HIDDEN) != 0);
549 XVA_SET_RTN(xvap, XAT_HIDDEN);
550 }
551 }
552
553 /*
554 * SMB Client initialization and cleanup.
555 * Much of it is per-zone now.
556 */
557
558
559 /* ARGSUSED */
560 static void *
561 smbfs_zone_init(zoneid_t zoneid)
562 {
563 smi_globals_t *smg;
564
565 smg = kmem_alloc(sizeof (*smg), KM_SLEEP);
566 mutex_init(&smg->smg_lock, NULL, MUTEX_DEFAULT, NULL);
567 list_create(&smg->smg_list, sizeof (smbmntinfo_t),
568 offsetof(smbmntinfo_t, smi_zone_node));
569 smg->smg_destructor_called = B_FALSE;
570 return (smg);
571 }
|
51 #include <sys/signal.h>
52 #include <sys/list.h>
53 #include <sys/zone.h>
54
55 #include <netsmb/smb.h>
56 #include <netsmb/smb_conn.h>
57 #include <netsmb/smb_subr.h>
58
59 #include <smbfs/smbfs.h>
60 #include <smbfs/smbfs_node.h>
61 #include <smbfs/smbfs_subr.h>
62
63 #include <vm/hat.h>
64 #include <vm/as.h>
65 #include <vm/page.h>
66 #include <vm/pvn.h>
67 #include <vm/seg.h>
68 #include <vm/seg_map.h>
69 #include <vm/seg_vn.h>
70
71 #define ATTRCACHE_VALID(vp) (gethrtime() < VTOSMB(vp)->r_attrtime)
72
73 static int smbfs_getattr_cache(vnode_t *, smbfattr_t *);
74 static void smbfattr_to_vattr(vnode_t *, smbfattr_t *, vattr_t *);
75 static void smbfattr_to_xvattr(smbfattr_t *, vattr_t *);
76 static int smbfs_getattr_otw(vnode_t *, struct smbfattr *, cred_t *);
77
78
79 /*
80 * The following code provide zone support in order to perform an action
81 * for each smbfs mount in a zone. This is also where we would add
82 * per-zone globals and kernel threads for the smbfs module (since
83 * they must be terminated by the shutdown callback).
84 */
85
86 struct smi_globals {
87 kmutex_t smg_lock; /* lock protecting smg_list */
88 list_t smg_list; /* list of SMBFS mounts in zone */
89 boolean_t smg_destructor_called;
90 };
91 typedef struct smi_globals smi_globals_t;
92
93 static zone_key_t smi_list_key;
94
95 /*
96 * Attributes caching:
97 *
98 * Attributes are cached in the smbnode in struct vattr form.
99 * There is a time associated with the cached attributes (r_attrtime)
100 * which tells whether the attributes are valid. The time is initialized
101 * to the difference between current time and the modify time of the vnode
102 * when new attributes are cached. This allows the attributes for
103 * files that have changed recently to be timed out sooner than for files
104 * that have not changed for a long time. There are minimum and maximum
105 * timeout values that can be set per mount point.
106 */
107
108 /*
109 * Helper for _validate_caches
110 */
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
145 smbfs_validate_caches(
146 struct vnode *vp,
147 cred_t *cr)
148 {
149 struct smbfattr fa;
150 int error;
151
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));
160 }
161
162 /*
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.
167 */
168 /* ARGSUSED */
169 void
170 smbfs_purge_caches(struct vnode *vp, cred_t *cr)
171 {
172
173 /*
174 * Here NFS has: Purge the DNLC for this vp,
175 * Clear any readdir state bits,
176 * the readlink response cache, ...
177 */
178
179 /*
180 * Flush the page cache.
181 */
182 if (vn_has_cached_data(vp)) {
183 (void) VOP_PUTPAGE(vp, (u_offset_t)0, 0, B_INVAL, cr, NULL);
184 }
185
186 /*
187 * Here NFS has: Flush the readdir response cache.
188 * No readdir cache in smbfs.
189 */
190 }
191
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 /*
201 * Check the attribute cache to see if the new attributes match
202 * those cached. If they do, the various `data' caches are
203 * considered to be good. Otherwise, purge the cached data.
204 */
205 static void
206 smbfs_cache_check(
207 struct vnode *vp,
208 struct smbfattr *fap,
209 cred_t *cr)
210 {
211 smbnode_t *np;
212 int purge_data = 0;
213 int purge_acl = 0;
214
215 np = VTOSMB(vp);
216 mutex_enter(&np->r_statelock);
217
218 /*
219 * Compare with NFS macro: CACHE_VALID
220 * If the mtime or size has changed,
221 * purge cached data.
222 */
223 if (np->r_attr.fa_mtime.tv_sec != fap->fa_mtime.tv_sec ||
224 np->r_attr.fa_mtime.tv_nsec != fap->fa_mtime.tv_nsec)
225 purge_data = 1;
226 if (np->r_attr.fa_size != fap->fa_size)
227 purge_data = 1;
228
229 if (np->r_attr.fa_ctime.tv_sec != fap->fa_ctime.tv_sec ||
230 np->r_attr.fa_ctime.tv_nsec != fap->fa_ctime.tv_nsec)
231 purge_acl = 1;
232
233 if (purge_acl) {
234 np->r_sectime = gethrtime();
235 }
236
237 mutex_exit(&np->r_statelock);
238
239 if (purge_data)
240 smbfs_purge_caches(vp, cr);
241 }
242
243 /*
244 * Set attributes cache for given vnode using SMB fattr
245 * and update the attribute cache timeout.
246 *
247 * Based on NFS: nfs_attrcache, nfs_attrcache_va
248 */
249 void
250 smbfs_attrcache_fa(vnode_t *vp, struct smbfattr *fap)
251 {
252 smbnode_t *np;
253 smbmntinfo_t *smi;
254 hrtime_t delta, now;
255 u_offset_t newsize;
256 vtype_t vtype, oldvt;
257 mode_t mode;
258
259 np = VTOSMB(vp);
260 smi = VTOSMI(vp);
261
262 /*
263 * We allow v_type to change, so set that here
264 * (and the mode, which depends on the type).
265 */
266 if (fap->fa_attr & SMB_FA_DIR) {
267 vtype = VDIR;
316 np->n_mode = mode;
317 oldvt = vp->v_type;
318 vp->v_type = vtype;
319
320 /*
321 * Shall we update r_size? (local notion of size)
322 *
323 * The real criteria for updating r_size should be:
324 * if the file has grown on the server, or if
325 * the client has not modified the file.
326 *
327 * Also deal with the fact that SMB presents
328 * directories as having size=0. Doing that
329 * here and leaving fa_size as returned OtW
330 * avoids fixing the size lots of places.
331 */
332 newsize = fap->fa_size;
333 if (vtype == VDIR && newsize < DEV_BSIZE)
334 newsize = DEV_BSIZE;
335
336 if (np->r_size != newsize &&
337 (!vn_has_cached_data(vp) ||
338 (!(np->r_flags & RDIRTY) && np->r_count == 0))) {
339 /* OK to set the size. */
340 np->r_size = newsize;
341 }
342
343 /*
344 * Here NFS has:
345 * nfs_setswaplike(vp, va);
346 * np->r_flags &= ~RWRITEATTR;
347 * (not needed here)
348 */
349
350 np->n_flag &= ~NATTRCHANGED;
351 mutex_exit(&np->r_statelock);
352
353 if (oldvt != vtype) {
354 SMBVDEBUG("vtype change %d to %d\n", oldvt, vtype);
355 }
356 }
357
358 /*
359 * Fill in attribute from the cache.
360 *
361 * If valid, copy to *fap and return zero,
362 * otherwise return an error.
363 *
364 * From NFS: nfs_getattr_cache()
365 */
366 int
367 smbfs_getattr_cache(vnode_t *vp, struct smbfattr *fap)
368 {
369 smbnode_t *np;
370 int error;
374 mutex_enter(&np->r_statelock);
375 if (gethrtime() >= np->r_attrtime) {
376 /* cache expired */
377 error = ENOENT;
378 } else {
379 /* cache is valid */
380 *fap = np->r_attr;
381 error = 0;
382 }
383 mutex_exit(&np->r_statelock);
384
385 return (error);
386 }
387
388 /*
389 * Get attributes over-the-wire and update attributes cache
390 * if no error occurred in the over-the-wire operation.
391 * Return 0 if successful, otherwise error.
392 * From NFS: nfs_getattr_otw
393 */
394 static int
395 smbfs_getattr_otw(vnode_t *vp, struct smbfattr *fap, cred_t *cr)
396 {
397 struct smbnode *np;
398 struct smb_cred scred;
399 int error;
400
401 np = VTOSMB(vp);
402
403 /*
404 * Here NFS uses the ACL RPC (if smi_flags & SMI_ACL)
405 * With SMB, getting the ACL is a significantly more
406 * expensive operation, so we do that only when asked
407 * for the uid/gid. See smbfsgetattr().
408 */
409
410 /* Shared lock for (possible) n_fid use. */
411 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
412 return (EINTR);
413 smb_credinit(&scred, cr);
414
415 bzero(fap, sizeof (*fap));
416 error = smbfs_smb_getfattr(np, fap, &scred);
417
418 smb_credrele(&scred);
419 smbfs_rw_exit(&np->r_lkserlock);
420
421 if (error) {
422 /* Here NFS has: PURGE_STALE_FH(error, vp, cr) */
423 smbfs_attrcache_remove(np);
424 if (error == ENOENT || error == ENOTDIR) {
425 /*
426 * Getattr failed because the object was
427 * removed or renamed by another client.
428 * Remove any cached attributes under it.
429 */
430 smbfs_attrcache_prune(np);
431 }
432 return (error);
433 }
434
435 /*
436 * Here NFS has: nfs_cache_fattr(vap, fa, vap, t, cr);
437 * which did: fattr_to_vattr, nfs_attr_cache.
438 * We cache the fattr form, so just do the
439 * cache check and store the attributes.
440 */
441 smbfs_cache_check(vp, fap, cr);
442 smbfs_attrcache_fa(vp, fap);
443
444 return (0);
445 }
446
447 /*
448 * Return either cached or remote attributes. If we get remote attrs,
449 * use them to check and invalidate caches, then cache the new attributes.
450 *
451 * From NFS: nfsgetattr()
452 */
453 int
454 smbfsgetattr(vnode_t *vp, struct vattr *vap, cred_t *cr)
455 {
456 struct smbfattr fa;
457 smbmntinfo_t *smi;
458 uint_t mask;
459 int error;
460
461 smi = VTOSMI(vp);
462
463 ASSERT(curproc->p_zone == smi->smi_zone_ref.zref_zone);
464
465 /*
466 * If asked for UID or GID, update n_uid, n_gid.
467 */
468 mask = AT_ALL;
575 }
576
577 if (XVA_ISSET_REQ(xvap, XAT_SYSTEM)) {
578 xoap->xoa_system =
579 ((fa->fa_attr & SMB_FA_SYSTEM) != 0);
580 XVA_SET_RTN(xvap, XAT_SYSTEM);
581 }
582
583 if (XVA_ISSET_REQ(xvap, XAT_READONLY)) {
584 xoap->xoa_readonly =
585 ((fa->fa_attr & SMB_FA_RDONLY) != 0);
586 XVA_SET_RTN(xvap, XAT_READONLY);
587 }
588
589 if (XVA_ISSET_REQ(xvap, XAT_HIDDEN)) {
590 xoap->xoa_hidden =
591 ((fa->fa_attr & SMB_FA_HIDDEN) != 0);
592 XVA_SET_RTN(xvap, XAT_HIDDEN);
593 }
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 }
664
665 /*
666 * SMB Client initialization and cleanup.
667 * Much of it is per-zone now.
668 */
669
670
671 /* ARGSUSED */
672 static void *
673 smbfs_zone_init(zoneid_t zoneid)
674 {
675 smi_globals_t *smg;
676
677 smg = kmem_alloc(sizeof (*smg), KM_SLEEP);
678 mutex_init(&smg->smg_lock, NULL, MUTEX_DEFAULT, NULL);
679 list_create(&smg->smg_list, sizeof (smbmntinfo_t),
680 offsetof(smbmntinfo_t, smi_zone_node));
681 smg->smg_destructor_called = B_FALSE;
682 return (smg);
683 }
|