Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/fs/smbsrv/smb_fem.c
+++ new/usr/src/uts/common/fs/smbsrv/smb_fem.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 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23 23 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
24 24 * Copyright 2015 Joyent, Inc.
25 25 */
26 26
27 27 #include <smbsrv/smb_kproto.h>
28 28 #include <smbsrv/smb_fsops.h>
29 29 #include <sys/sdt.h>
30 30 #include <sys/fcntl.h>
31 31 #include <sys/vfs.h>
32 32 #include <sys/vfs_opreg.h>
33 33 #include <sys/vnode.h>
34 34 #include <sys/fem.h>
35 35
36 36 extern caller_context_t smb_ct;
37 37
38 38 static boolean_t smb_fem_initialized = B_FALSE;
39 39 static fem_t *smb_fcn_ops = NULL;
40 40 static fem_t *smb_oplock_ops = NULL;
41 41
42 42 /*
43 43 * Declarations for FCN (file change notification) FEM monitors
44 44 */
45 45
46 46 static int smb_fem_fcn_create(femarg_t *, char *, vattr_t *, vcexcl_t, int,
47 47 vnode_t **, cred_t *, int, caller_context_t *, vsecattr_t *);
48 48 static int smb_fem_fcn_remove(femarg_t *, char *, cred_t *,
49 49 caller_context_t *, int);
50 50 static int smb_fem_fcn_rename(femarg_t *, char *, vnode_t *, char *,
51 51 cred_t *, caller_context_t *, int);
↓ open down ↓ |
51 lines elided |
↑ open up ↑ |
52 52 static int smb_fem_fcn_mkdir(femarg_t *, char *, vattr_t *, vnode_t **,
53 53 cred_t *, caller_context_t *, int, vsecattr_t *);
54 54 static int smb_fem_fcn_rmdir(femarg_t *, char *, vnode_t *, cred_t *,
55 55 caller_context_t *, int);
56 56 static int smb_fem_fcn_link(femarg_t *, vnode_t *, char *, cred_t *,
57 57 caller_context_t *, int);
58 58 static int smb_fem_fcn_symlink(femarg_t *, char *, vattr_t *,
59 59 char *, cred_t *, caller_context_t *, int);
60 60
61 61 static const fs_operation_def_t smb_fcn_tmpl[] = {
62 - VOPNAME_CREATE, { .femop_create = smb_fem_fcn_create },
63 - VOPNAME_REMOVE, {.femop_remove = smb_fem_fcn_remove},
64 - VOPNAME_RENAME, {.femop_rename = smb_fem_fcn_rename},
65 - VOPNAME_MKDIR, {.femop_mkdir = smb_fem_fcn_mkdir},
66 - VOPNAME_RMDIR, {.femop_rmdir = smb_fem_fcn_rmdir},
67 - VOPNAME_LINK, {.femop_link = smb_fem_fcn_link},
68 - VOPNAME_SYMLINK, {.femop_symlink = smb_fem_fcn_symlink},
69 - NULL, NULL
62 + { VOPNAME_CREATE, { .femop_create = smb_fem_fcn_create } },
63 + { VOPNAME_REMOVE, {.femop_remove = smb_fem_fcn_remove} },
64 + { VOPNAME_RENAME, {.femop_rename = smb_fem_fcn_rename} },
65 + { VOPNAME_MKDIR, {.femop_mkdir = smb_fem_fcn_mkdir} },
66 + { VOPNAME_RMDIR, {.femop_rmdir = smb_fem_fcn_rmdir} },
67 + { VOPNAME_LINK, {.femop_link = smb_fem_fcn_link} },
68 + { VOPNAME_SYMLINK, {.femop_symlink = smb_fem_fcn_symlink} },
69 + { NULL, {NULL} }
70 70 };
71 71
72 72 /*
73 73 * Declarations for oplock FEM monitors
74 74 */
75 75
76 76 static int smb_fem_oplock_open(femarg_t *, int, cred_t *,
77 77 struct caller_context *);
78 78 static int smb_fem_oplock_read(femarg_t *, uio_t *, int, cred_t *,
79 79 struct caller_context *);
80 80 static int smb_fem_oplock_write(femarg_t *, uio_t *, int, cred_t *,
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
81 81 struct caller_context *);
82 82 static int smb_fem_oplock_setattr(femarg_t *, vattr_t *, int, cred_t *,
83 83 caller_context_t *);
84 84 static int smb_fem_oplock_rwlock(femarg_t *, int, caller_context_t *);
85 85 static int smb_fem_oplock_space(femarg_t *, int, flock64_t *, int,
86 86 offset_t, cred_t *, caller_context_t *);
87 87 static int smb_fem_oplock_vnevent(femarg_t *, vnevent_t, vnode_t *, char *,
88 88 caller_context_t *);
89 89
90 90 static const fs_operation_def_t smb_oplock_tmpl[] = {
91 - VOPNAME_OPEN, { .femop_open = smb_fem_oplock_open },
92 - VOPNAME_READ, { .femop_read = smb_fem_oplock_read },
93 - VOPNAME_WRITE, { .femop_write = smb_fem_oplock_write },
94 - VOPNAME_SETATTR, { .femop_setattr = smb_fem_oplock_setattr },
95 - VOPNAME_RWLOCK, { .femop_rwlock = smb_fem_oplock_rwlock },
96 - VOPNAME_SPACE, { .femop_space = smb_fem_oplock_space },
97 - VOPNAME_VNEVENT, { .femop_vnevent = smb_fem_oplock_vnevent },
98 - NULL, NULL
91 + { VOPNAME_OPEN, { .femop_open = smb_fem_oplock_open } },
92 + { VOPNAME_READ, { .femop_read = smb_fem_oplock_read } },
93 + { VOPNAME_WRITE, { .femop_write = smb_fem_oplock_write } },
94 + { VOPNAME_SETATTR, { .femop_setattr = smb_fem_oplock_setattr } },
95 + { VOPNAME_RWLOCK, { .femop_rwlock = smb_fem_oplock_rwlock } },
96 + { VOPNAME_SPACE, { .femop_space = smb_fem_oplock_space } },
97 + { VOPNAME_VNEVENT, { .femop_vnevent = smb_fem_oplock_vnevent } },
98 + { NULL, {NULL} }
99 99 };
100 100
101 101 static int smb_fem_oplock_break(femarg_t *, caller_context_t *, uint32_t);
102 102
103 103 /*
104 104 * smb_fem_init
105 105 *
106 106 * This function is not multi-thread safe. The caller must make sure only one
107 107 * thread makes the call.
108 108 */
109 109 int
110 110 smb_fem_init(void)
111 111 {
112 112 int rc = 0;
113 113
114 114 if (smb_fem_initialized)
115 115 return (0);
116 116
117 117 rc = fem_create("smb_fcn_ops", smb_fcn_tmpl, &smb_fcn_ops);
118 118 if (rc)
119 119 return (rc);
120 120
121 121 rc = fem_create("smb_oplock_ops", smb_oplock_tmpl,
122 122 &smb_oplock_ops);
123 123
124 124 if (rc) {
125 125 fem_free(smb_fcn_ops);
126 126 smb_fcn_ops = NULL;
127 127 return (rc);
128 128 }
129 129
130 130 smb_fem_initialized = B_TRUE;
131 131
132 132 return (0);
133 133 }
134 134
135 135 /*
136 136 * smb_fem_fini
137 137 *
138 138 * This function is not multi-thread safe. The caller must make sure only one
139 139 * thread makes the call.
140 140 */
141 141 void
142 142 smb_fem_fini(void)
143 143 {
144 144 if (!smb_fem_initialized)
145 145 return;
146 146
147 147 if (smb_fcn_ops != NULL) {
148 148 fem_free(smb_fcn_ops);
149 149 smb_fcn_ops = NULL;
150 150 }
151 151 if (smb_oplock_ops != NULL) {
152 152 fem_free(smb_oplock_ops);
153 153 smb_oplock_ops = NULL;
154 154 }
155 155 smb_fem_initialized = B_FALSE;
156 156 }
157 157
158 158 int
159 159 smb_fem_fcn_install(smb_node_t *node)
160 160 {
161 161 int rc;
162 162
163 163 if (smb_fcn_ops == NULL)
164 164 return (ENOSYS);
165 165 rc = fem_install(node->vp, smb_fcn_ops, (void *)node, OPARGUNIQ,
166 166 (fem_func_t)smb_node_ref, (fem_func_t)smb_node_release);
167 167 return (rc);
168 168 }
169 169
170 170 void
171 171 smb_fem_fcn_uninstall(smb_node_t *node)
172 172 {
173 173 if (smb_fcn_ops == NULL)
174 174 return;
175 175 VERIFY0(fem_uninstall(node->vp, smb_fcn_ops, (void *)node));
176 176 }
177 177
178 178 int
179 179 smb_fem_oplock_install(smb_node_t *node)
180 180 {
181 181 int rc;
182 182
183 183 if (smb_oplock_ops == NULL)
184 184 return (ENOSYS);
185 185 rc = fem_install(node->vp, smb_oplock_ops, (void *)node, OPARGUNIQ,
186 186 (fem_func_t)smb_node_ref, (fem_func_t)smb_node_release);
187 187 return (rc);
188 188 }
189 189
190 190 void
191 191 smb_fem_oplock_uninstall(smb_node_t *node)
192 192 {
193 193 if (smb_oplock_ops == NULL)
194 194 return;
195 195 VERIFY0(fem_uninstall(node->vp, smb_oplock_ops, (void *)node));
196 196 }
197 197
198 198 /*
199 199 * FEM FCN monitors
200 200 *
201 201 * The FCN monitors intercept the respective VOP_* call regardless
202 202 * of whether the call originates from CIFS, NFS, or a local process.
203 203 */
204 204
205 205 /*
206 206 * smb_fem_fcn_create()
207 207 *
208 208 * This monitor will catch only changes to VREG files and not to extended
209 209 * attribute files. This is fine because, for CIFS files, stream creates
210 210 * should not trigger any file change notification on the VDIR directory
211 211 * being monitored. Creates of any other kind of extended attribute in
212 212 * the directory will also not trigger any file change notification on the
213 213 * VDIR directory being monitored.
214 214 */
215 215
216 216 static int
217 217 smb_fem_fcn_create(
218 218 femarg_t *arg,
219 219 char *name,
220 220 vattr_t *vap,
221 221 vcexcl_t excl,
222 222 int mode,
223 223 vnode_t **vpp,
224 224 cred_t *cr,
225 225 int flag,
226 226 caller_context_t *ct,
227 227 vsecattr_t *vsecp)
228 228 {
229 229 smb_node_t *dnode;
230 230 int error;
231 231
232 232 dnode = (smb_node_t *)arg->fa_fnode->fn_available;
233 233
234 234 ASSERT(dnode);
235 235
236 236 error = vnext_create(arg, name, vap, excl, mode, vpp, cr, flag,
237 237 ct, vsecp);
238 238
239 239 if (error == 0 && ct != &smb_ct)
240 240 smb_node_notify_change(dnode, FILE_ACTION_ADDED, name);
241 241
242 242 return (error);
243 243 }
244 244
245 245 /*
246 246 * smb_fem_fcn_remove()
247 247 *
248 248 * This monitor will catch only changes to VREG files and to not extended
249 249 * attribute files. This is fine because, for CIFS files, stream deletes
250 250 * should not trigger any file change notification on the VDIR directory
251 251 * being monitored. Deletes of any other kind of extended attribute in
252 252 * the directory will also not trigger any file change notification on the
253 253 * VDIR directory being monitored.
254 254 */
255 255
256 256 static int
257 257 smb_fem_fcn_remove(
258 258 femarg_t *arg,
259 259 char *name,
260 260 cred_t *cr,
261 261 caller_context_t *ct,
262 262 int flags)
263 263 {
264 264 smb_node_t *dnode;
265 265 int error;
266 266
267 267 dnode = (smb_node_t *)arg->fa_fnode->fn_available;
268 268
269 269 ASSERT(dnode);
270 270
271 271 error = vnext_remove(arg, name, cr, ct, flags);
272 272
273 273 if (error == 0 && ct != &smb_ct)
274 274 smb_node_notify_change(dnode, FILE_ACTION_REMOVED, name);
275 275
276 276 return (error);
277 277 }
278 278
279 279 static int
280 280 smb_fem_fcn_rename(
281 281 femarg_t *arg,
282 282 char *snm,
283 283 vnode_t *tdvp,
284 284 char *tnm,
285 285 cred_t *cr,
286 286 caller_context_t *ct,
287 287 int flags)
288 288 {
289 289 smb_node_t *dnode;
290 290 int error;
291 291
292 292 dnode = (smb_node_t *)arg->fa_fnode->fn_available;
293 293
294 294 ASSERT(dnode);
295 295
296 296 error = vnext_rename(arg, snm, tdvp, tnm, cr, ct, flags);
297 297
298 298 if (error == 0 && ct != &smb_ct) {
299 299 /*
300 300 * Note that renames in the same directory are normally
301 301 * delivered in {old,new} pairs, and clients expect them
302 302 * in that order, if both events are delivered.
303 303 */
304 304 smb_node_notify_change(dnode,
305 305 FILE_ACTION_RENAMED_OLD_NAME, snm);
306 306 smb_node_notify_change(dnode,
307 307 FILE_ACTION_RENAMED_NEW_NAME, tnm);
308 308 }
309 309
310 310 return (error);
311 311 }
312 312
313 313 static int
314 314 smb_fem_fcn_mkdir(
315 315 femarg_t *arg,
316 316 char *name,
317 317 vattr_t *vap,
318 318 vnode_t **vpp,
319 319 cred_t *cr,
320 320 caller_context_t *ct,
321 321 int flags,
322 322 vsecattr_t *vsecp)
323 323 {
324 324 smb_node_t *dnode;
325 325 int error;
326 326
327 327 dnode = (smb_node_t *)arg->fa_fnode->fn_available;
328 328
329 329 ASSERT(dnode);
330 330
331 331 error = vnext_mkdir(arg, name, vap, vpp, cr, ct, flags, vsecp);
332 332
333 333 if (error == 0 && ct != &smb_ct)
334 334 smb_node_notify_change(dnode, FILE_ACTION_ADDED, name);
335 335
336 336 return (error);
337 337 }
338 338
339 339 static int
340 340 smb_fem_fcn_rmdir(
341 341 femarg_t *arg,
342 342 char *name,
343 343 vnode_t *cdir,
344 344 cred_t *cr,
345 345 caller_context_t *ct,
346 346 int flags)
347 347 {
348 348 smb_node_t *dnode;
349 349 int error;
350 350
351 351 dnode = (smb_node_t *)arg->fa_fnode->fn_available;
352 352
353 353 ASSERT(dnode);
354 354
355 355 error = vnext_rmdir(arg, name, cdir, cr, ct, flags);
356 356
357 357 if (error == 0 && ct != &smb_ct)
358 358 smb_node_notify_change(dnode, FILE_ACTION_REMOVED, name);
359 359
360 360 return (error);
361 361 }
362 362
363 363 static int
364 364 smb_fem_fcn_link(
365 365 femarg_t *arg,
366 366 vnode_t *svp,
367 367 char *tnm,
368 368 cred_t *cr,
369 369 caller_context_t *ct,
370 370 int flags)
371 371 {
372 372 smb_node_t *dnode;
373 373 int error;
374 374
375 375 dnode = (smb_node_t *)arg->fa_fnode->fn_available;
376 376
377 377 ASSERT(dnode);
378 378
379 379 error = vnext_link(arg, svp, tnm, cr, ct, flags);
380 380
381 381 if (error == 0 && ct != &smb_ct)
382 382 smb_node_notify_change(dnode, FILE_ACTION_ADDED, tnm);
383 383
384 384 return (error);
385 385 }
386 386
387 387 static int
388 388 smb_fem_fcn_symlink(
389 389 femarg_t *arg,
390 390 char *linkname,
391 391 vattr_t *vap,
392 392 char *target,
393 393 cred_t *cr,
394 394 caller_context_t *ct,
395 395 int flags)
396 396 {
397 397 smb_node_t *dnode;
398 398 int error;
399 399
400 400 dnode = (smb_node_t *)arg->fa_fnode->fn_available;
401 401
402 402 ASSERT(dnode);
403 403
404 404 error = vnext_symlink(arg, linkname, vap, target, cr, ct, flags);
405 405
406 406 if (error == 0 && ct != &smb_ct)
407 407 smb_node_notify_change(dnode, FILE_ACTION_ADDED, linkname);
408 408
409 409 return (error);
410 410 }
411 411
412 412 /*
413 413 * FEM oplock monitors
414 414 *
415 415 * The monitors below are not intended to intercept CIFS calls.
416 416 * CIFS higher-level routines will break oplocks as needed prior
417 417 * to getting to the VFS layer.
418 418 */
419 419 static int
420 420 smb_fem_oplock_open(
421 421 femarg_t *arg,
422 422 int mode,
423 423 cred_t *cr,
424 424 caller_context_t *ct)
425 425 {
426 426 uint32_t flags;
427 427 int rc = 0;
428 428
429 429 if (ct != &smb_ct) {
430 430 if (mode & (FWRITE|FTRUNC))
431 431 flags = SMB_OPLOCK_BREAK_TO_NONE;
432 432 else
433 433 flags = SMB_OPLOCK_BREAK_TO_LEVEL_II;
434 434 rc = smb_fem_oplock_break(arg, ct, flags);
435 435 }
436 436 if (rc == 0)
437 437 rc = vnext_open(arg, mode, cr, ct);
438 438
439 439 return (rc);
440 440 }
441 441
442 442 /*
443 443 * Should normally be hit only via NFSv2/v3. All other accesses
444 444 * (CIFS/NFS/local) should call VOP_OPEN first.
445 445 */
446 446
447 447 static int
448 448 smb_fem_oplock_read(
449 449 femarg_t *arg,
450 450 uio_t *uiop,
451 451 int ioflag,
452 452 cred_t *cr,
453 453 caller_context_t *ct)
454 454 {
455 455 int rc = 0;
456 456
457 457 if (ct != &smb_ct) {
458 458 rc = smb_fem_oplock_break(arg, ct,
459 459 SMB_OPLOCK_BREAK_TO_LEVEL_II);
460 460 }
461 461 if (rc == 0)
462 462 rc = vnext_read(arg, uiop, ioflag, cr, ct);
463 463
464 464 return (rc);
465 465 }
466 466
467 467 /*
468 468 * Should normally be hit only via NFSv2/v3. All other accesses
469 469 * (CIFS/NFS/local) should call VOP_OPEN first.
470 470 */
471 471
472 472 static int
473 473 smb_fem_oplock_write(
474 474 femarg_t *arg,
475 475 uio_t *uiop,
476 476 int ioflag,
477 477 cred_t *cr,
478 478 caller_context_t *ct)
479 479 {
480 480 int rc = 0;
481 481
482 482 if (ct != &smb_ct)
483 483 rc = smb_fem_oplock_break(arg, ct, SMB_OPLOCK_BREAK_TO_NONE);
484 484 if (rc == 0)
485 485 rc = vnext_write(arg, uiop, ioflag, cr, ct);
486 486
487 487 return (rc);
488 488 }
489 489
490 490 static int
491 491 smb_fem_oplock_setattr(
492 492 femarg_t *arg,
493 493 vattr_t *vap,
494 494 int flags,
495 495 cred_t *cr,
496 496 caller_context_t *ct)
497 497 {
498 498 int rc = 0;
499 499
500 500 if (ct != &smb_ct && (vap->va_mask & AT_SIZE) != 0)
501 501 rc = smb_fem_oplock_break(arg, ct, SMB_OPLOCK_BREAK_TO_NONE);
502 502 if (rc == 0)
503 503 rc = vnext_setattr(arg, vap, flags, cr, ct);
504 504 return (rc);
505 505 }
506 506
507 507 static int
508 508 smb_fem_oplock_rwlock(
509 509 femarg_t *arg,
510 510 int write_lock,
511 511 caller_context_t *ct)
512 512 {
513 513 uint32_t flags;
514 514 int rc = 0;
515 515
516 516 if (ct != &smb_ct) {
517 517 if (write_lock)
518 518 flags = SMB_OPLOCK_BREAK_TO_NONE;
519 519 else
520 520 flags = SMB_OPLOCK_BREAK_TO_LEVEL_II;
521 521 rc = smb_fem_oplock_break(arg, ct, flags);
522 522 }
523 523 if (rc == 0)
524 524 rc = vnext_rwlock(arg, write_lock, ct);
525 525
526 526 return (rc);
527 527 }
528 528
529 529 static int
530 530 smb_fem_oplock_space(
531 531 femarg_t *arg,
532 532 int cmd,
533 533 flock64_t *bfp,
534 534 int flag,
535 535 offset_t offset,
536 536 cred_t *cr,
537 537 caller_context_t *ct)
538 538 {
539 539 int rc = 0;
540 540
541 541 if (ct != &smb_ct)
542 542 rc = smb_fem_oplock_break(arg, ct, SMB_OPLOCK_BREAK_TO_NONE);
543 543 if (rc == 0)
544 544 rc = vnext_space(arg, cmd, bfp, flag, offset, cr, ct);
545 545 return (rc);
546 546 }
547 547
548 548 /*
549 549 * smb_fem_oplock_vnevent()
550 550 *
551 551 * To intercept NFS and local renames and removes in order to break any
552 552 * existing oplock prior to the operation.
553 553 *
554 554 * Note: Currently, this monitor is traversed only when an FS is mounted
555 555 * non-nbmand. (When the FS is mounted nbmand, share reservation checking
556 556 * will detect a share violation and return an error prior to the VOP layer
557 557 * being reached.) Thus, for nbmand NFS and local renames and removes,
558 558 * an existing oplock is never broken prior to share checking (contrary to
559 559 * how it is with intra-CIFS remove and rename requests).
560 560 */
561 561
562 562 static int
563 563 smb_fem_oplock_vnevent(
564 564 femarg_t *arg,
565 565 vnevent_t vnevent,
566 566 vnode_t *dvp,
567 567 char *name,
568 568 caller_context_t *ct)
569 569 {
570 570 uint32_t flags;
571 571 int rc = 0;
572 572
573 573 if (ct != &smb_ct) {
574 574 switch (vnevent) {
575 575 case VE_REMOVE:
576 576 case VE_PRE_RENAME_DEST:
577 577 case VE_RENAME_DEST:
578 578 flags = SMB_OPLOCK_BREAK_TO_NONE |
579 579 SMB_OPLOCK_BREAK_BATCH;
580 580 rc = smb_fem_oplock_break(arg, ct, flags);
581 581 break;
582 582 case VE_PRE_RENAME_SRC:
583 583 case VE_RENAME_SRC:
584 584 flags = SMB_OPLOCK_BREAK_TO_LEVEL_II |
585 585 SMB_OPLOCK_BREAK_BATCH;
586 586 rc = smb_fem_oplock_break(arg, ct, flags);
587 587 break;
588 588 default:
589 589 rc = 0;
590 590 break;
591 591 }
592 592 }
593 593 if (rc == 0)
594 594 rc = vnext_vnevent(arg, vnevent, dvp, name, ct);
595 595
596 596 return (rc);
597 597 }
598 598
599 599 static int
600 600 smb_fem_oplock_break(femarg_t *arg, caller_context_t *ct, uint32_t flags)
601 601 {
602 602 smb_node_t *node;
603 603 int rc;
604 604
605 605 node = (smb_node_t *)((arg)->fa_fnode->fn_available);
606 606 SMB_NODE_VALID(node);
607 607
608 608 ASSERT(ct != &smb_ct);
609 609
610 610 if (ct && (ct->cc_flags & CC_DONTBLOCK)) {
611 611 flags |= SMB_OPLOCK_BREAK_NOWAIT;
612 612 rc = smb_oplock_break(NULL, node, flags);
613 613 if (rc == EAGAIN)
614 614 ct->cc_flags |= CC_WOULDBLOCK;
615 615 } else {
616 616 rc = smb_oplock_break(NULL, node, flags);
617 617 }
618 618
619 619 return (rc);
620 620 }
↓ open down ↓ |
512 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX