Print this page
NEX-5665 SMB2 oplock leases
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-5665 SMB2 oplock leases
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
SMB-131 Don't allow setting delete-on-close on non empty dirs
SMB-11 SMB2 message parse & dispatch
SMB-12 SMB2 Negotiate Protocol
SMB-13 SMB2 Session Setup
SMB-14 SMB2 Logoff
SMB-15 SMB2 Tree Connect
SMB-16 SMB2 Tree Disconnect
SMB-17 SMB2 Create
SMB-18 SMB2 Close
SMB-19 SMB2 Flush
SMB-20 SMB2 Read
SMB-21 SMB2 Write
SMB-22 SMB2 Lock/Unlock
SMB-23 SMB2 Ioctl
SMB-24 SMB2 Cancel
SMB-25 SMB2 Echo
SMB-26 SMB2 Query Dir
SMB-27 SMB2 Change Notify
SMB-28 SMB2 Query Info
SMB-29 SMB2 Set Info
SMB-30 SMB2 Oplocks
SMB-53 SMB2 Create Context options
(SMB2 code review cleanup 1, 2, 3)

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/smbsrv/smb_cmn_setfile.c
          +++ new/usr/src/uts/common/fs/smbsrv/smb_cmn_setfile.c
↓ open down ↓ 12 lines elided ↑ open up ↑
  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      - * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
       23 + * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
  24   24   */
  25   25  
  26   26  /*
  27   27   * Common functions supporting both:
  28   28   * SMB1 Trans2 Set File/Path Info,
  29   29   * SMB2 Set File Info
  30   30   */
  31   31  
  32      -#include <smbsrv/smb_kproto.h>
       32 +#include <smbsrv/smb2_kproto.h>
  33   33  #include <smbsrv/smb_fsops.h>
  34   34  
  35   35  /*
  36   36   * smb_set_basic_info
  37   37   * [MS-FSCC] 2.4.7
  38   38   *      FileBasicInformation
  39   39   *      SMB_SET_FILE_BASIC_INFO
  40   40   *      SMB_FILE_BASIC_INFORMATION
  41   41   *
  42   42   * Sets basic file/path information.
↓ open down ↓ 58 lines elided ↑ open up ↑
 101  101   *      FileEndOfFileInformation
 102  102   *      SMB_SET_FILE_END_OF_FILE_INFO
 103  103   *      SMB_FILE_END_OF_FILE_INFORMATION
 104  104   */
 105  105  uint32_t
 106  106  smb_set_eof_info(smb_request_t *sr, smb_setinfo_t *si)
 107  107  {
 108  108          smb_attr_t *attr = &si->si_attr;
 109  109          smb_node_t *node = si->si_node;
 110  110          uint64_t eof;
      111 +        uint32_t status;
 111  112          int rc;
 112  113  
 113  114          if (smb_mbc_decodef(&si->si_data, "q", &eof) != 0)
 114  115                  return (NT_STATUS_INFO_LENGTH_MISMATCH);
 115  116  
 116  117          if (smb_node_is_dir(node))
 117  118                  return (NT_STATUS_INVALID_PARAMETER);
 118  119  
 119      -        /* If opened by path, break exclusive oplock */
 120      -        if (sr->fid_ofile == NULL)
 121      -                (void) smb_oplock_break(sr, node,
 122      -                    SMB_OPLOCK_BREAK_EXCLUSIVE | SMB_OPLOCK_BREAK_TO_NONE);
      120 +        status = smb_oplock_break_SETINFO(node, sr->fid_ofile,
      121 +            FileEndOfFileInformation);
      122 +        if (status == NT_STATUS_OPLOCK_BREAK_IN_PROGRESS) {
      123 +                if (sr->session->dialect >= SMB_VERS_2_BASE)
      124 +                        (void) smb2sr_go_async(sr);
      125 +                (void) smb_oplock_wait_break(node, 0);
      126 +                status = 0;
      127 +        }
      128 +        if (status != 0)
      129 +                return (status);
 123  130  
 124  131          bzero(attr, sizeof (*attr));
 125  132          attr->sa_mask = SMB_AT_SIZE;
 126  133          attr->sa_vattr.va_size = (u_offset_t)eof;
 127  134          rc = smb_node_setattr(sr, node, sr->user_cr, sr->fid_ofile, attr);
 128  135          if (rc != 0)
 129  136                  return (smb_errno2status(rc));
 130  137  
 131      -        smb_oplock_break_levelII(node);
 132  138          return (0);
 133  139  }
 134  140  
 135  141  /*
 136  142   * smb_set_alloc_info
 137  143   *      FileAllocationInformation
 138  144   *      SMB_SET_FILE_ALLOCATION_INFO
 139  145   *      SMB_FILE_ALLOCATION_INFORMATION
 140  146   */
 141  147  uint32_t
 142  148  smb_set_alloc_info(smb_request_t *sr, smb_setinfo_t *si)
 143  149  {
 144  150          smb_attr_t *attr = &si->si_attr;
 145  151          smb_node_t *node = si->si_node;
 146  152          uint64_t allocsz;
      153 +        uint32_t status;
 147  154          int rc;
 148  155  
 149  156          if (smb_mbc_decodef(&si->si_data, "q", &allocsz) != 0)
 150  157                  return (NT_STATUS_INFO_LENGTH_MISMATCH);
 151  158  
 152  159          if (smb_node_is_dir(node))
 153  160                  return (NT_STATUS_INVALID_PARAMETER);
 154  161  
 155      -        /* If opened by path, break exclusive oplock */
 156      -        if (sr->fid_ofile == NULL)
 157      -                (void) smb_oplock_break(sr, node,
 158      -                    SMB_OPLOCK_BREAK_EXCLUSIVE | SMB_OPLOCK_BREAK_TO_NONE);
      162 +        status = smb_oplock_break_SETINFO(node, sr->fid_ofile,
      163 +            FileAllocationInformation);
      164 +        if (status == NT_STATUS_OPLOCK_BREAK_IN_PROGRESS) {
      165 +                if (sr->session->dialect >= SMB_VERS_2_BASE)
      166 +                        (void) smb2sr_go_async(sr);
      167 +                (void) smb_oplock_wait_break(node, 0);
      168 +                status = 0;
      169 +        }
      170 +        if (status != 0)
      171 +                return (status);
 159  172  
 160  173          bzero(attr, sizeof (*attr));
 161  174          attr->sa_mask = SMB_AT_ALLOCSZ;
 162  175          attr->sa_allocsz = (u_offset_t)allocsz;
 163  176          rc = smb_node_setattr(sr, node, sr->user_cr, sr->fid_ofile, attr);
 164  177          if (rc != 0)
 165  178                  return (smb_errno2status(rc));
 166  179  
 167      -        smb_oplock_break_levelII(node);
 168  180          return (0);
 169  181  }
 170  182  
 171  183  /*
 172  184   * smb_set_disposition_info
 173  185   * See:
 174  186   *      FileDispositionInformation
 175  187   *      SMB_SET_FILE_DISPOSITION_INFO
 176  188   *      SMB_FILE_DISPOSITION_INFORMATION
 177  189   *
↓ open down ↓ 26 lines elided ↑ open up ↑
 204  216   * Trans2SetFileInfo(SetDispositionInfo) at this time will unset the
 205  217   * node delete-on-close flag, which will result in the file not being
 206  218   * removed even after the last file handle is closed.
 207  219   */
 208  220  uint32_t
 209  221  smb_set_disposition_info(smb_request_t *sr, smb_setinfo_t *si)
 210  222  {
 211  223          smb_node_t *node = si->si_node;
 212  224          smb_ofile_t *of = sr->fid_ofile;
 213  225          uint8_t         mark_delete;
      226 +        uint32_t        status;
 214  227          uint32_t        flags = 0;
 215  228  
 216  229          if (smb_mbc_decodef(&si->si_data, "b", &mark_delete) != 0)
 217  230                  return (NT_STATUS_INFO_LENGTH_MISMATCH);
 218  231  
 219  232          if ((of == NULL) || !(smb_ofile_granted_access(of) & DELETE))
 220  233                  return (NT_STATUS_ACCESS_DENIED);
 221  234  
 222      -        if (mark_delete) {
 223      -                if (SMB_TREE_SUPPORTS_CATIA(sr))
 224      -                        flags |= SMB_CATIA;
 225      -                return (smb_node_set_delete_on_close(node, of->f_cr, flags));
 226      -        } else {
      235 +        if (mark_delete == 0) {
 227  236                  smb_node_reset_delete_on_close(node);
      237 +                return (NT_STATUS_SUCCESS);
 228  238          }
 229  239  
 230      -        return (NT_STATUS_SUCCESS);
      240 +        /*
      241 +         * Break any oplock handle caching.
      242 +         */
      243 +        status = smb_oplock_break_SETINFO(node, of,
      244 +            FileDispositionInformation);
      245 +        if (status == NT_STATUS_OPLOCK_BREAK_IN_PROGRESS) {
      246 +                if (sr->session->dialect >= SMB_VERS_2_BASE)
      247 +                        (void) smb2sr_go_async(sr);
      248 +                (void) smb_oplock_wait_break(node, 0);
      249 +                status = 0;
      250 +        }
      251 +        if (status != 0)
      252 +                return (status);
      253 +
      254 +        if (SMB_TREE_SUPPORTS_CATIA(sr))
      255 +                flags |= SMB_CATIA;
      256 +
      257 +        return (smb_node_set_delete_on_close(node, of->f_cr, flags));
 231  258  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX