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>
NEX-1643 dtrace provider for smbsrv
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-5844 want SMB2 ioctl FSCTL_SRV_COPYCHUNK
NEX-6124 smb_fsop_read/write should allow file != sr->fid_ofile
NEX-6125 smbtorture invalid response with smb2.ioctl
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-6041 Should pass the smbtorture lock tests
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
NEX-2370 unable to save/modify files (zip,notepad,excel) on CIFS share from Windows 7
NEX-2039 Codenomicon failure in smb_write
re #7815 SMB server delivers old modification time...

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/smbsrv/smb_write.c
          +++ new/usr/src/uts/common/fs/smbsrv/smb_write.c
↓ open down ↓ 13 lines elided ↑ open up ↑
  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  /*
  23   23   * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  24      - * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
       24 + * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
  25   25   */
  26   26  
  27   27  #include <sys/sdt.h>
  28   28  #include <smbsrv/smb_kproto.h>
  29   29  #include <smbsrv/smb_fsops.h>
  30   30  #include <smbsrv/netbios.h>
  31   31  
  32   32  
  33   33  static int smb_write_truncate(smb_request_t *, smb_rw_param_t *);
  34   34  
↓ open down ↓ 19 lines elided ↑ open up ↑
  54   54          param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP);
  55   55          sr->arg.rw = param;
  56   56          param->rw_magic = SMB_RW_MAGIC;
  57   57  
  58   58          rc = smbsr_decode_vwv(sr, "wwl", &sr->smb_fid, &count, &off);
  59   59  
  60   60          param->rw_count = (uint32_t)count;
  61   61          param->rw_offset = (uint64_t)off;
  62   62          param->rw_vdb.vdb_uio.uio_loffset = (offset_t)param->rw_offset;
  63   63  
  64      -        DTRACE_SMB_2(op__Write__start, smb_request_t *, sr,
  65      -            smb_rw_param_t *, param);
       64 +        DTRACE_SMB_START(op__Write, smb_request_t *, sr); /* arg.rw */
  66   65  
  67   66          return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
  68   67  }
  69   68  
  70   69  void
  71   70  smb_post_write(smb_request_t *sr)
  72   71  {
  73      -        DTRACE_SMB_2(op__Write__done, smb_request_t *, sr,
  74      -            smb_rw_param_t *, sr->arg.rw);
       72 +        DTRACE_SMB_DONE(op__Write, smb_request_t *, sr); /* arg.rw */
  75   73  
  76   74          kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
  77   75  }
  78   76  
  79   77  smb_sdrc_t
  80   78  smb_com_write(smb_request_t *sr)
  81   79  {
  82   80          smb_rw_param_t *param = sr->arg.rw;
  83   81          int rc;
  84   82  
↓ open down ↓ 59 lines elided ↑ open up ↑
 144  142                  rc = smbsr_decode_vwv(sr, "wwll12.", &sr->smb_fid,
 145  143                      &count, &off, &param->rw_last_write);
 146  144          } else {
 147  145                  rc = smbsr_decode_vwv(sr, "wwll", &sr->smb_fid,
 148  146                      &count, &off, &param->rw_last_write);
 149  147          }
 150  148  
 151  149          param->rw_count = (uint32_t)count;
 152  150          param->rw_offset = (uint64_t)off;
 153  151  
 154      -        DTRACE_SMB_2(op__WriteAndClose__start, smb_request_t *, sr,
 155      -            smb_rw_param_t *, param);
      152 +        DTRACE_SMB_START(op__WriteAndClose, smb_request_t *, sr); /* arg.rw */
 156  153  
 157  154          return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 158  155  }
 159  156  
 160  157  void
 161  158  smb_post_write_and_close(smb_request_t *sr)
 162  159  {
 163      -        DTRACE_SMB_2(op__WriteAndClose__done, smb_request_t *, sr,
 164      -            smb_rw_param_t *, sr->arg.rw);
      160 +        DTRACE_SMB_DONE(op__WriteAndClose, smb_request_t *, sr); /* arg.rw */
 165  161  
 166  162          kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
 167  163  }
 168  164  
 169  165  smb_sdrc_t
 170  166  smb_com_write_and_close(smb_request_t *sr)
 171  167  {
 172  168          smb_rw_param_t *param = sr->arg.rw;
 173  169          uint16_t count;
 174  170          int rc = 0;
↓ open down ↓ 67 lines elided ↑ open up ↑
 242  238  
 243  239          param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP);
 244  240          sr->arg.rw = param;
 245  241          param->rw_magic = SMB_RW_MAGIC;
 246  242  
 247  243          rc = smbsr_decode_vwv(sr, "wwlw", &sr->smb_fid, &count, &off, &remcnt);
 248  244  
 249  245          param->rw_count = (uint32_t)count;
 250  246          param->rw_offset = (uint64_t)off;
 251  247  
 252      -        DTRACE_SMB_2(op__WriteAndUnlock__start, smb_request_t *, sr,
 253      -            smb_rw_param_t *, param);
      248 +        DTRACE_SMB_START(op__WriteAndUnlock, smb_request_t *, sr); /* arg.rw */
 254  249  
 255  250          return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 256  251  }
 257  252  
 258  253  void
 259  254  smb_post_write_and_unlock(smb_request_t *sr)
 260  255  {
 261      -        DTRACE_SMB_2(op__WriteAndUnlock__done, smb_request_t *, sr,
 262      -            smb_rw_param_t *, sr->arg.rw);
      256 +        DTRACE_SMB_DONE(op__WriteAndUnlock, smb_request_t *, sr); /* arg.rw */
 263  257  
 264  258          kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
 265  259  }
 266  260  
 267  261  smb_sdrc_t
 268  262  smb_com_write_and_unlock(smb_request_t *sr)
 269  263  {
 270  264          smb_rw_param_t *param = sr->arg.rw;
      265 +        uint32_t lk_pid;
 271  266          uint32_t status;
 272  267          int rc = 0;
 273  268  
 274  269          if (STYPE_ISDSK(sr->tid_tree->t_res_type) == 0) {
 275  270                  smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess);
 276  271                  return (SDRC_ERROR);
 277  272          }
 278  273  
 279  274          smbsr_lookup_file(sr);
 280  275          if (sr->fid_ofile == NULL) {
↓ open down ↓ 18 lines elided ↑ open up ↑
 299  294          }
 300  295  
 301  296          param->rw_vdb.vdb_uio.uio_loffset = (offset_t)param->rw_offset;
 302  297  
 303  298          if ((rc = smb_common_write(sr, param)) != 0) {
 304  299                  if (sr->smb_error.status != NT_STATUS_FILE_LOCK_CONFLICT)
 305  300                          smbsr_errno(sr, rc);
 306  301                  return (SDRC_ERROR);
 307  302          }
 308  303  
 309      -        status = smb_unlock_range(sr, sr->fid_ofile->f_node, param->rw_offset,
 310      -            (uint64_t)param->rw_count);
      304 +
      305 +        /* Note: SMB1 locking uses 16-bit PIDs. */
      306 +        lk_pid = sr->smb_pid & 0xFFFF;
      307 +
      308 +        status = smb_unlock_range(sr, param->rw_offset,
      309 +            (uint64_t)param->rw_count, lk_pid);
 311  310          if (status != NT_STATUS_SUCCESS) {
 312  311                  smbsr_error(sr, NT_STATUS_RANGE_NOT_LOCKED,
 313  312                      ERRDOS, ERROR_NOT_LOCKED);
 314  313                  return (SDRC_ERROR);
 315  314          }
 316  315  
 317  316          rc = smbsr_encode_result(sr, 1, 0, "bww", 1,
 318  317              (uint16_t)param->rw_count, 0);
 319  318          return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 320  319  }
 321  320  
 322  321  /*
      322 + * The SMB_COM_WRITE_RAW protocol was a negotiated option introduced in
      323 + * SMB Core Plus to maximize performance when writing a large block
      324 + * of data to a server.  It's obsolete and no longer supported.
      325 + *
      326 + * We keep a handler for it so the dtrace provider can see if
      327 + * the client tried to use this command.
      328 + */
      329 +smb_sdrc_t
      330 +smb_pre_write_raw(smb_request_t *sr)
      331 +{
      332 +        DTRACE_SMB_START(op__WriteRaw, smb_request_t *, sr);
      333 +        return (SDRC_SUCCESS);
      334 +}
      335 +
      336 +void
      337 +smb_post_write_raw(smb_request_t *sr)
      338 +{
      339 +        DTRACE_SMB_DONE(op__WriteRaw, smb_request_t *, sr);
      340 +}
      341 +
      342 +smb_sdrc_t
      343 +smb_com_write_raw(struct smb_request *sr)
      344 +{
      345 +        smbsr_error(sr, NT_STATUS_NOT_SUPPORTED, ERRDOS,
      346 +            ERROR_NOT_SUPPORTED);
      347 +        return (SDRC_ERROR);
      348 +}
      349 +
      350 +/*
 323  351   * Write bytes to a file (SMB Core).  This request was extended in
 324  352   * LM 0.12 to support 64-bit offsets, indicated by sending a wct of
 325  353   * 14, instead of 12, and including additional offset information.
 326  354   *
 327  355   * A ByteCount of 0 does not truncate the file - use SMB_COM_WRITE
 328  356   * to truncate a file.  A zero length merely transfers zero bytes.
 329  357   *
 330  358   * If bit 0 of WriteMode is set, Fid must refer to a disk file and
 331  359   * the data must be on stable storage before responding.
 332  360   *
↓ open down ↓ 42 lines elided ↑ open up ↑
 375  403  
 376  404          /*
 377  405           * Work-around a Win7 bug, where it fails to set the
 378  406           * CAP_LARGE_WRITEX flag during session setup.  Assume
 379  407           * a large write if the data remaining is >= 64k.
 380  408           */
 381  409          if ((sr->session->capabilities & CAP_LARGE_WRITEX) != 0 ||
 382  410              (sr->smb_data.max_bytes > (sr->smb_data.chain_offset + 0xFFFF)))
 383  411                  param->rw_count |= ((uint32_t)datalen_high << 16);
 384  412  
 385      -        DTRACE_SMB_2(op__WriteX__start, smb_request_t *, sr,
 386      -            smb_rw_param_t *, param);
      413 +        DTRACE_SMB_START(op__WriteX, smb_request_t *, sr); /* arg.rw */
 387  414  
 388  415          return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 389  416  }
 390  417  
 391  418  void
 392  419  smb_post_write_andx(smb_request_t *sr)
 393  420  {
 394      -        DTRACE_SMB_2(op__WriteX__done, smb_request_t *, sr,
 395      -            smb_rw_param_t *, sr->arg.rw);
      421 +        DTRACE_SMB_DONE(op__WriteX, smb_request_t *, sr); /* arg.rw */
 396  422  
 397  423          kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
 398  424  }
 399  425  
 400  426  smb_sdrc_t
 401  427  smb_com_write_andx(smb_request_t *sr)
 402  428  {
 403  429          smb_rw_param_t *param = sr->arg.rw;
 404  430          uint16_t count_high;
 405  431          uint16_t count_low;
↓ open down ↓ 72 lines elided ↑ open up ↑
 478  504                                      ERRDOS, ERROR_LOCK_VIOLATION);
 479  505                                  return (EACCES);
 480  506                          }
 481  507                  }
 482  508  
 483  509                  if (SMB_WRMODE_IS_STABLE(param->rw_mode) ||
 484  510                      (node->flags & NODE_FLAGS_WRITE_THROUGH)) {
 485  511                          stability = FSYNC;
 486  512                  }
 487  513  
 488      -                rc = smb_fsop_write(sr, sr->user_cr, node,
      514 +                rc = smb_fsop_write(sr, sr->user_cr, node, ofile,
 489  515                      &param->rw_vdb.vdb_uio, &lcount, stability);
 490  516  
 491  517                  if (rc)
 492  518                          return (rc);
 493  519  
 494  520                  /*
 495  521                   * Used to have code here to set mtime.
 496  522                   * We have just done a write, so we know
 497  523                   * the file system will update mtime.
 498  524                   * No need to do it again here.
 499  525                   *
 500  526                   * However, keep track of the fact that
 501  527                   * we have written data via this handle.
 502  528                   */
 503  529                  ofile->f_written = B_TRUE;
 504  530  
 505      -                if (!smb_node_is_dir(node))
 506      -                        smb_oplock_break_levelII(node);
      531 +                /* This revokes read cache delegations. */
      532 +                (void) smb_oplock_break_WRITE(node, ofile);
 507  533  
 508  534                  param->rw_count = lcount;
 509  535                  break;
 510  536  
 511  537          case STYPE_IPC:
 512  538                  param->rw_count = param->rw_vdb.vdb_uio.uio_resid;
 513  539  
 514  540                  if ((rc = smb_opipe_write(sr, &param->rw_vdb.vdb_uio)) != 0)
 515  541                          param->rw_count = 0;
 516  542                  break;
↓ open down ↓ 63 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX