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-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>
SMB-119 Text file contains garbage when re-opened
SMB-120 Share enumeration fails with Windows 8
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)

*** 8,27 **** * source. A copy of the CDDL is also available via the Internet at * http://www.illumos.org/license/CDDL. */ /* ! * Copyright 2014 Nexenta Systems, Inc. All rights reserved. */ /* * Dispatch function for SMB2_WRITE */ #include <smbsrv/smb2_kproto.h> #include <smbsrv/smb_fsops.h> smb_sdrc_t smb2_write(smb_request_t *sr) { smb_ofile_t *of = NULL; smb_vdb_t *vdb = NULL; --- 8,29 ---- * source. A copy of the CDDL is also available via the Internet at * http://www.illumos.org/license/CDDL. */ /* ! * Copyright 2018 Nexenta Systems, Inc. All rights reserved. */ /* * Dispatch function for SMB2_WRITE */ #include <smbsrv/smb2_kproto.h> #include <smbsrv/smb_fsops.h> + boolean_t smb_allow_unbuffered = B_TRUE; + smb_sdrc_t smb2_write(smb_request_t *sr) { smb_ofile_t *of = NULL; smb_vdb_t *vdb = NULL;
*** 38,50 **** uint32_t XferCount; uint32_t status; int data_chain_off, skip; int stability = 0; int rc = 0; /* ! * SMB2 Write request */ rc = smb_mbc_decodef( &sr->smb_data, "wwlqqqllwwl", &StructSize, /* w */ --- 40,53 ---- uint32_t XferCount; uint32_t status; int data_chain_off, skip; int stability = 0; int rc = 0; + boolean_t unbuffered = B_FALSE; /* ! * Decode SMB2 Write request */ rc = smb_mbc_decodef( &sr->smb_data, "wwlqqqllwwl", &StructSize, /* w */
*** 61,108 **** if (rc) return (SDRC_ERROR); if (StructSize != 49) return (SDRC_ERROR); - status = smb2sr_lookup_fid(sr, &smb2fid); - if (status) { - smb2sr_put_error(sr, status); - return (SDRC_SUCCESS); - } - of = sr->fid_ofile; - - if (Length > smb2_max_rwsize) { - smb2sr_put_error(sr, NT_STATUS_INVALID_PARAMETER); - return (SDRC_SUCCESS); - } - /* * Skip any padding before the write data. */ data_chain_off = sr->smb2_cmd_hdr + DataOff; skip = data_chain_off - sr->smb_data.chain_offset; ! if (skip < 0) { ! smb2sr_put_error(sr, NT_STATUS_INVALID_PARAMETER); ! return (SDRC_SUCCESS); ! } ! if (skip > 0) { (void) smb_mbc_decodef(&sr->smb_data, "#.", skip); - } ! /* This is automatically free'd. */ vdb = smb_srm_zalloc(sr, sizeof (*vdb)); rc = smb_mbc_decodef(&sr->smb_data, "#B", Length, vdb); ! if (rc != 0 || vdb->vdb_len != Length) { ! smb2sr_put_error(sr, NT_STATUS_INVALID_PARAMETER); ! return (SDRC_SUCCESS); ! } vdb->vdb_uio.uio_loffset = (offset_t)Offset; XferCount = 0; if (Length == 0) ! goto doreply; switch (of->f_tree->t_res_type & STYPE_MASK) { case STYPE_DISKTREE: case STYPE_PRINTQ: if (!smb_node_is_dir(of->f_node)) { /* Check for conflicting locks. */ --- 64,124 ---- if (rc) return (SDRC_ERROR); if (StructSize != 49) return (SDRC_ERROR); /* * Skip any padding before the write data. */ data_chain_off = sr->smb2_cmd_hdr + DataOff; skip = data_chain_off - sr->smb_data.chain_offset; ! if (skip < 0) ! return (SDRC_ERROR); ! if (skip > 0) (void) smb_mbc_decodef(&sr->smb_data, "#.", skip); ! /* ! * Decode the write data (payload) ! * This is automatically free'd. ! */ ! if (Length > smb2_max_rwsize) ! return (SDRC_ERROR); vdb = smb_srm_zalloc(sr, sizeof (*vdb)); rc = smb_mbc_decodef(&sr->smb_data, "#B", Length, vdb); ! if (rc != 0 || vdb->vdb_len != Length) ! return (SDRC_ERROR); vdb->vdb_uio.uio_loffset = (offset_t)Offset; + /* + * Want FID lookup before the start probe. + */ + status = smb2sr_lookup_fid(sr, &smb2fid); + of = sr->fid_ofile; + + DTRACE_SMB2_START(op__Write, smb_request_t *, sr); /* arg.rw */ + + if (status) + goto errout; /* Bad FID */ + + XferCount = 0; if (Length == 0) ! goto errout; + /* + * Unbuffered refers to the MS-FSA Write argument by the same name. + * It indicates that the cache for this range should be flushed to disk, + * and data written directly to disk, bypassing the cache. + * We don't allow that degree of cache management. + * Translate this directly as FSYNC, + * which should at least flush the cache. + */ + + if (smb_allow_unbuffered && + (Flags & SMB2_WRITEFLAG_WRITE_UNBUFFERED) != 0) + unbuffered = B_TRUE; + switch (of->f_tree->t_res_type & STYPE_MASK) { case STYPE_DISKTREE: case STYPE_PRINTQ: if (!smb_node_is_dir(of->f_node)) { /* Check for conflicting locks. */
*** 111,163 **** if (rc) { rc = ERANGE; break; } } ! if ((Flags & SMB2_WRITEFLAG_WRITE_THROUGH) || ! (of->f_node->flags & NODE_FLAGS_WRITE_THROUGH)) { stability = FSYNC; } ! rc = smb_fsop_write(sr, of->f_cr, of->f_node, &vdb->vdb_uio, &XferCount, stability); if (rc) break; of->f_written = B_TRUE; ! if (!smb_node_is_dir(of->f_node)) ! smb_oplock_break_levelII(of->f_node); break; case STYPE_IPC: rc = smb_opipe_write(sr, &vdb->vdb_uio); if (rc == 0) XferCount = Length; break; default: rc = EACCES; break; } ! if (rc) { ! smb2sr_put_errno(sr, rc); return (SDRC_SUCCESS); } /* ! * SMB2 Write reply */ - doreply: DataOff = SMB2_HDR_SIZE + 16; rc = smb_mbc_encodef( &sr->reply, "wwlll", 17, /* StructSize */ /* w */ 0, /* reserved */ /* w */ XferCount, /* l */ 0, /* DataRemaining */ /* l */ 0); /* Channel Info */ /* l */ ! if (rc) return (SDRC_ERROR); mutex_enter(&of->f_mutex); of->f_seek_pos = Offset + XferCount; mutex_exit(&of->f_mutex); --- 127,189 ---- if (rc) { rc = ERANGE; break; } } ! ! if (unbuffered || (Flags & SMB2_WRITEFLAG_WRITE_THROUGH) != 0 || ! (of->f_node->flags & NODE_FLAGS_WRITE_THROUGH) != 0) { stability = FSYNC; } ! rc = smb_fsop_write(sr, of->f_cr, of->f_node, of, &vdb->vdb_uio, &XferCount, stability); if (rc) break; of->f_written = B_TRUE; ! /* This revokes read cache delegations. */ ! (void) smb_oplock_break_WRITE(of->f_node, of); break; case STYPE_IPC: + if (unbuffered || (Flags & SMB2_WRITEFLAG_WRITE_THROUGH) != 0) + rc = EINVAL; + else rc = smb_opipe_write(sr, &vdb->vdb_uio); if (rc == 0) XferCount = Length; break; default: rc = EACCES; break; } + status = smb_errno2status(rc); ! errout: ! sr->smb2_status = status; ! DTRACE_SMB2_DONE(op__Write, smb_request_t *, sr); /* arg.rw */ ! ! if (status) { ! smb2sr_put_error(sr, status); return (SDRC_SUCCESS); } /* ! * Encode SMB2 Write reply */ DataOff = SMB2_HDR_SIZE + 16; rc = smb_mbc_encodef( &sr->reply, "wwlll", 17, /* StructSize */ /* w */ 0, /* reserved */ /* w */ XferCount, /* l */ 0, /* DataRemaining */ /* l */ 0); /* Channel Info */ /* l */ ! if (rc) { ! sr->smb2_status = NT_STATUS_INTERNAL_ERROR; return (SDRC_ERROR); + } mutex_enter(&of->f_mutex); of->f_seek_pos = Offset + XferCount; mutex_exit(&of->f_mutex);