Print this page
NEX-17289 Minimal SMB 3.0.2 support
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Evan Layton <evan.layton@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-3662 Backport illumos 1501: taskq_create_proc ... TQ_DYNAMIC puts tasks in p0 (take 2)
Reviewed by: Garrett D'Amore <garrett@damore.org>
Reviewed by: Dan McDonald <danmcd@omniti.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Marcel Telka <marcel.telka@nexenta.com>
NEX-3576 RPC error when displaying open files via Windows MMC
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
NEX-2188 Browsing top level share produces RPC error 1728
SMB-122 smbd core dumps in smbd_dc_update / smb_log
SMB-117 Win7 fails to open security properties
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/smb2_read.c
          +++ new/usr/src/uts/common/fs/smbsrv/smb2_read.c
↓ open down ↓ 2 lines elided ↑ open up ↑
   3    3   * Common Development and Distribution License ("CDDL"), version 1.0.
   4    4   * You may only use this file in accordance with the terms of version
   5    5   * 1.0 of the CDDL.
   6    6   *
   7    7   * A full copy of the text of the CDDL should have accompanied this
   8    8   * source.  A copy of the CDDL is also available via the Internet at
   9    9   * http://www.illumos.org/license/CDDL.
  10   10   */
  11   11  
  12   12  /*
  13      - * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
       13 + * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  14   14   */
  15   15  
  16   16  /*
  17   17   * Dispatch function for SMB2_READ
  18   18   */
  19   19  
  20   20  #include <smbsrv/smb2_kproto.h>
  21   21  #include <smbsrv/smb_fsops.h>
  22   22  
       23 +extern boolean_t smb_allow_unbuffered;
       24 +
  23   25  smb_sdrc_t
  24   26  smb2_read(smb_request_t *sr)
  25   27  {
  26   28          smb_ofile_t *of = NULL;
  27   29          smb_vdb_t *vdb = NULL;
  28   30          struct mbuf *m = NULL;
  29   31          uint16_t StructSize;
  30   32          uint8_t Padding;
       33 +        uint8_t Flags;
  31   34          uint8_t DataOff;
  32   35          uint32_t Length;
  33   36          uint64_t Offset;
  34   37          smb2fid_t smb2fid;
  35   38          uint32_t MinCount;
  36   39          uint32_t Channel;
  37   40          uint32_t Remaining;
  38   41          uint16_t ChanInfoOffset;
  39   42          uint16_t ChanInfoLength;
  40   43          uint32_t XferCount;
  41   44          uint32_t status;
  42   45          int rc = 0;
       46 +        boolean_t unbuffered = B_FALSE;
       47 +        int ioflag = 0;
  43   48  
  44   49          /*
  45   50           * SMB2 Read request
  46   51           */
  47   52          rc = smb_mbc_decodef(
  48   53              &sr->smb_data,
  49      -            "wb.lqqqlllww",
       54 +            "wbblqqqlllww",
  50   55              &StructSize,                /* w */
  51      -            &Padding,                   /* b. */
       56 +            &Padding,                   /* b */
       57 +            &Flags,                     /* b */
  52   58              &Length,                    /* l */
  53   59              &Offset,                    /* q */
  54   60              &smb2fid.persistent,        /* q */
  55   61              &smb2fid.temporal,          /* q */
  56   62              &MinCount,                  /* l */
  57   63              &Channel,                   /* l */
  58   64              &Remaining,                 /* l */
  59   65              &ChanInfoOffset,            /* w */
  60   66              &ChanInfoLength);           /* w */
  61   67          if (rc)
  62   68                  return (SDRC_ERROR);
  63   69          if (StructSize != 49)
  64   70                  return (SDRC_ERROR);
  65   71  
       72 +        /*
       73 +         * Want FID lookup before the start probe.
       74 +         */
  66   75          status = smb2sr_lookup_fid(sr, &smb2fid);
  67      -        if (status) {
  68      -                smb2sr_put_error(sr, status);
  69      -                return (SDRC_SUCCESS);
  70      -        }
  71   76          of = sr->fid_ofile;
  72   77  
       78 +        DTRACE_SMB2_START(op__Read, smb_request_t *, sr); /* arg.rw */
       79 +
       80 +        if (status)
       81 +                goto errout; /* Bad FID */
       82 +
  73   83          if (Length > smb2_max_rwsize) {
  74      -                smb2sr_put_error(sr, NT_STATUS_INVALID_PARAMETER);
  75      -                return (SDRC_SUCCESS);
       84 +                status = NT_STATUS_INVALID_PARAMETER;
       85 +                goto errout;
  76   86          }
  77   87          if (MinCount > Length)
  78   88                  MinCount = Length;
  79   89  
  80   90          /* This is automatically free'd. */
  81   91          vdb = smb_srm_zalloc(sr, sizeof (*vdb));
  82   92          vdb->vdb_tag = 0;
  83   93          vdb->vdb_uio.uio_iov = &vdb->vdb_iovec[0];
  84   94          vdb->vdb_uio.uio_iovcnt = MAX_IOVEC;
  85   95          vdb->vdb_uio.uio_resid = Length;
  86   96          vdb->vdb_uio.uio_loffset = (offset_t)Offset;
  87   97          vdb->vdb_uio.uio_segflg = UIO_SYSSPACE;
  88   98          vdb->vdb_uio.uio_extflg = UIO_COPY_DEFAULT;
  89   99  
  90  100          sr->raw_data.max_bytes = Length;
  91  101          m = smb_mbuf_allocate(&vdb->vdb_uio);
  92  102  
      103 +        /*
      104 +         * Unbuffered refers to the MS-FSA Read argument by the same name.
      105 +         * It indicates that the cache for this range should be flushed to disk,
      106 +         * and data read directly from disk, bypassing the cache.
      107 +         * We don't allow that degree of cache management.
      108 +         * Translate this directly as FRSYNC,
      109 +         * which should at least flush the cache first.
      110 +         */
      111 +
      112 +        if (smb_allow_unbuffered &&
      113 +            (Flags & SMB2_READFLAG_READ_UNBUFFERED) != 0) {
      114 +                unbuffered = B_TRUE;
      115 +                ioflag = FRSYNC;
      116 +        }
      117 +
  93  118          switch (of->f_tree->t_res_type & STYPE_MASK) {
  94  119          case STYPE_DISKTREE:
  95  120                  if (!smb_node_is_dir(of->f_node)) {
  96  121                          /* Check for conflicting locks. */
  97  122                          rc = smb_lock_range_access(sr, of->f_node,
  98  123                              Offset, Length, B_FALSE);
  99  124                          if (rc) {
 100  125                                  rc = ERANGE;
 101  126                                  break;
 102  127                          }
 103  128                  }
 104      -                rc = smb_fsop_read(sr, of->f_cr, of->f_node, &vdb->vdb_uio);
      129 +                rc = smb_fsop_read(sr, of->f_cr, of->f_node, of,
      130 +                    &vdb->vdb_uio, ioflag);
 105  131                  break;
 106  132          case STYPE_IPC:
 107      -                rc = smb_opipe_read(sr, &vdb->vdb_uio);
      133 +                if (unbuffered)
      134 +                        rc = EINVAL;
      135 +                else
      136 +                        rc = smb_opipe_read(sr, &vdb->vdb_uio);
 108  137                  break;
 109  138          default:
 110  139          case STYPE_PRINTQ:
 111  140                  rc = EACCES;
 112  141                  break;
 113  142          }
      143 +        status = smb_errno2status(rc);
 114  144  
 115  145          /* How much data we moved. */
 116  146          XferCount = Length - vdb->vdb_uio.uio_resid;
 117  147  
 118  148          sr->raw_data.max_bytes = XferCount;
 119  149          smb_mbuf_trim(m, XferCount);
 120  150          MBC_ATTACH_MBUF(&sr->raw_data, m);
 121  151  
 122  152          /*
 123  153           * Checking the error return _after_ dealing with
 124  154           * the returned data so that if m was allocated,
 125  155           * it will be free'd via sr->raw_data cleanup.
 126  156           */
 127      -        if (rc) {
 128      -                smb2sr_put_errno(sr, rc);
      157 +errout:
      158 +        sr->smb2_status = status;
      159 +        DTRACE_SMB2_DONE(op__Read, smb_request_t *, sr); /* arg.rw */
      160 +        if (status) {
      161 +                smb2sr_put_error(sr, status);
 129  162                  return (SDRC_SUCCESS);
 130  163          }
 131  164  
 132  165          /*
 133  166           * SMB2 Read reply
 134  167           */
 135  168          DataOff = SMB2_HDR_SIZE + 16;
 136  169          rc = smb_mbc_encodef(
 137  170              &sr->reply,
 138  171              "wb.lllC",
 139  172              17, /* StructSize */        /* w */
 140  173              DataOff,                    /* b. */
 141  174              XferCount,                  /* l */
 142  175              0, /* DataRemaining */      /* l */
 143  176              0, /* reserved */           /* l */
 144  177              &sr->raw_data);             /* C */
 145      -        if (rc)
      178 +        if (rc) {
      179 +                sr->smb2_status = NT_STATUS_INTERNAL_ERROR;
 146  180                  return (SDRC_ERROR);
      181 +        }
 147  182  
 148  183          mutex_enter(&of->f_mutex);
 149  184          of->f_seek_pos = Offset + XferCount;
 150  185          mutex_exit(&of->f_mutex);
 151  186  
 152  187          return (SDRC_SUCCESS);
 153  188  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX