diff options
author | Gordon Ross <gordon.ross@tintri.com> | 2020-08-26 17:48:44 +0000 |
---|---|---|
committer | Gordon Ross <gwr@racktopsystems.com> | 2022-08-09 16:23:36 -0400 |
commit | e8754e84740733dd9f21c60b5a5ac47d32dacb6b (patch) | |
tree | 2d34b9716a2e3e88171d5bebab71f458621f9243 | |
parent | 345881c57eafd2f92f73791646936638889af149 (diff) | |
download | illumos-joyent-e8754e84740733dd9f21c60b5a5ac47d32dacb6b.tar.gz |
14866 SMB oplock not recalled when there is a request from NFS
Reviewed by: Prashanth Badari <prbadari@tintri.com>
Reviewed by: Suresh Jayaraman <sjayaraman@tintri.com>
Reviewed by: Jerry Jelinek <gjelinek@gmail.com>
Reviewed by: Garrett D'Amore <garrett@damore.org>
Reviewed by: Matt Barden <mbarden@tintri.com>
Approved by: Dan McDonald <danmcd@mnx.io>
-rw-r--r-- | usr/src/cmd/smbsrv/testoplock/smbsrv/smb_kproto.h | 4 | ||||
-rw-r--r-- | usr/src/cmd/smbsrv/testoplock/tol_main.c | 13 | ||||
-rw-r--r-- | usr/src/uts/common/fs/smbsrv/smb_cmn_oplock.c | 53 | ||||
-rw-r--r-- | usr/src/uts/common/fs/smbsrv/smb_node.c | 13 |
4 files changed, 75 insertions, 8 deletions
diff --git a/usr/src/cmd/smbsrv/testoplock/smbsrv/smb_kproto.h b/usr/src/cmd/smbsrv/testoplock/smbsrv/smb_kproto.h index 4ccf839f51..f743dcd179 100644 --- a/usr/src/cmd/smbsrv/testoplock/smbsrv/smb_kproto.h +++ b/usr/src/cmd/smbsrv/testoplock/smbsrv/smb_kproto.h @@ -21,7 +21,7 @@ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2018 Nexenta Systems, Inc. All rights reserved. + * Copyright 2020 Tintri by DDN, Inc. All rights reserved. */ /* @@ -103,6 +103,8 @@ uint32_t smb_oplock_wait_break(smb_node_t *, int); int smb_lock_range_access(smb_request_t *, smb_node_t *, uint64_t, uint64_t, boolean_t); +int smb_fem_oplock_install(smb_node_t *); +void smb_fem_oplock_uninstall(smb_node_t *); #ifdef __cplusplus } diff --git a/usr/src/cmd/smbsrv/testoplock/tol_main.c b/usr/src/cmd/smbsrv/testoplock/tol_main.c index 5382802b82..f78729a9d6 100644 --- a/usr/src/cmd/smbsrv/testoplock/tol_main.c +++ b/usr/src/cmd/smbsrv/testoplock/tol_main.c @@ -10,7 +10,7 @@ */ /* - * Copyright 2018 Nexenta Systems, Inc. All rights reserved. + * Copyright 2020 Tintri by DDN, Inc. All rights reserved. * Copyright 2019 Joyent, Inc. * Copyright 2022 RackTop Systems, Inc. */ @@ -645,6 +645,17 @@ smb_oplock_wait_break(smb_node_t *node, int timeout) return (0); } +int +smb_fem_oplock_install(smb_node_t *node) +{ + return (0); +} + +void +smb_fem_oplock_uninstall(smb_node_t *node) +{ +} + /* * There are a couple DTRACE_PROBE* in smb_cmn_oplock.c but we're * not linking with the user-level dtrace support, so just diff --git a/usr/src/uts/common/fs/smbsrv/smb_cmn_oplock.c b/usr/src/uts/common/fs/smbsrv/smb_cmn_oplock.c index 1b9ccce688..0afd313281 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_cmn_oplock.c +++ b/usr/src/uts/common/fs/smbsrv/smb_cmn_oplock.c @@ -977,7 +977,9 @@ smb_oplock_req_excl( * This operation MUST be made cancelable... * This operation waits until the oplock is * broken or canceled, as specified in - * section 2.1.5.17.3. + * section 2.1.5.17.3. Note: This function + * does not cause breaks that require a wait, + * so never returns ..._BREAK_IN_PROGRESS. * * When the operation specified in section * 2.1.5.17.3 is called, its following input @@ -990,11 +992,18 @@ smb_oplock_req_excl( * section 2.1.5.17.3. */ /* Keep *rop = ... from caller. */ - if ((node->n_oplock.ol_state & BREAK_ANY) != 0) { - status = NT_STATUS_OPLOCK_BREAK_IN_PROGRESS; - /* Caller does smb_oplock_wait_break() */ - } else { - status = NT_STATUS_SUCCESS; + status = NT_STATUS_SUCCESS; + + /* + * First oplock grant installs FEM hooks. + */ + if (node->n_oplock.ol_fem == B_FALSE) { + if (smb_fem_oplock_install(node) != 0) { + cmn_err(CE_NOTE, + "smb_fem_oplock_install failed"); + } else { + node->n_oplock.ol_fem = B_TRUE; + } } } @@ -1387,6 +1396,18 @@ smb_oplock_req_shared( } else { status = NT_STATUS_SUCCESS; } + + /* + * First oplock grant installs FEM hooks. + */ + if (node->n_oplock.ol_fem == B_FALSE) { + if (smb_fem_oplock_install(node) != 0) { + cmn_err(CE_NOTE, + "smb_fem_oplock_install failed"); + } else { + node->n_oplock.ol_fem = B_TRUE; + } + } } out: @@ -2075,6 +2096,18 @@ out: } /* + * If this node no longer has any oplock grants, let's + * go ahead and remove the FEM hooks now. We could leave + * that until close, but this lets access outside of SMB + * be free of FEM oplock work after a "break to none". + */ + if (node->n_oplock.ol_state == NO_OPLOCK && + node->n_oplock.ol_fem == B_TRUE) { + smb_fem_oplock_uninstall(node); + node->n_oplock.ol_fem = B_FALSE; + } + + /* * The spec. describes waiting for a break here, * but we let the caller do that (when needed) if * status == NT_STATUS_OPLOCK_BREAK_IN_PROGRESS @@ -2506,6 +2539,14 @@ smb_oplock_break_CLOSE(smb_node_t *node, smb_ofile_t *ofile) if ((node->n_oplock.ol_state & BREAK_ANY) == 0) cv_broadcast(&node->n_oplock.WaitingOpenCV); + /* + * If no longer any oplock, remove FEM hooks. + */ + if (node->n_oplock.ol_state == NO_OPLOCK && + node->n_oplock.ol_fem == B_TRUE) { + smb_fem_oplock_uninstall(node); + node->n_oplock.ol_fem = B_FALSE; + } } /* diff --git a/usr/src/uts/common/fs/smbsrv/smb_node.c b/usr/src/uts/common/fs/smbsrv/smb_node.c index a204326514..fd37c2b328 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_node.c +++ b/usr/src/uts/common/fs/smbsrv/smb_node.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2020 Tintri by DDN, Inc. All rights reserved. + * Copyright 2021 RackTop Systems, Inc. */ /* * SMB Node State Machine @@ -492,6 +493,18 @@ smb_node_release(smb_node_t *node) mutex_exit(&node->n_mutex); + /* + * Out of caution, make sure FEM hooks + * used by oplocks are also gone. + */ + mutex_enter(&node->n_oplock.ol_mutex); + ASSERT(node->n_oplock.ol_fem == B_FALSE); + if (node->n_oplock.ol_fem == B_TRUE) { + smb_fem_oplock_uninstall(node); + node->n_oplock.ol_fem = B_FALSE; + } + mutex_exit(&node->n_oplock.ol_mutex); + smb_llist_enter(node->n_hash_bucket, RW_WRITER); smb_llist_remove(node->n_hash_bucket, node); smb_llist_exit(node->n_hash_bucket); |