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