Print this page
NEX-15680 Implement SMB2 getinfo FS level FileFsSectorSizeInformation
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-15680 Implement SMB2 getinfo FS level FileFsSectorSizeInformation
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-5598 SMB needs a few more ioctls for Hyper-V
Reviewed by: Gordon Ross <gwr@nexenta.com>
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)
        
*** 18,28 ****
   *
   * CDDL HEADER END
   */
  /*
   * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
!  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
   */
  
  /*
   * Dispatch function for SMB2_QUERY_INFO
   *
--- 18,28 ----
   *
   * CDDL HEADER END
   */
  /*
   * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
!  * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
   */
  
  /*
   * Dispatch function for SMB2_QUERY_INFO
   *
*** 39,48 ****
--- 39,49 ----
  uint32_t smb2_qfs_device(smb_request_t *);
  uint32_t smb2_qfs_attr(smb_request_t *);
  uint32_t smb2_qfs_control(smb_request_t *);
  uint32_t smb2_qfs_fullsize(smb_request_t *);
  uint32_t smb2_qfs_obj_id(smb_request_t *);
+ uint32_t smb2_qfs_sectorsize(smb_request_t *);
  
  uint32_t
  smb2_qinfo_fs(smb_request_t *sr, smb_queryinfo_t *qi)
  {
          uint32_t status;
*** 69,82 ****
                  status = smb2_qfs_fullsize(sr);
                  break;
          case FileFsObjectIdInformation: /* 8 */
                  status = smb2_qfs_obj_id(sr);
                  break;
! 
!         default:
                  status = NT_STATUS_INVALID_INFO_CLASS;
                  break;
          }
  
          return (status);
  }
  
--- 70,91 ----
                  status = smb2_qfs_fullsize(sr);
                  break;
          case FileFsObjectIdInformation: /* 8 */
                  status = smb2_qfs_obj_id(sr);
                  break;
!         case FileFsVolumeFlagsInformation:      /* A */
                  status = NT_STATUS_INVALID_INFO_CLASS;
                  break;
+         case FileFsSectorSizeInformation:       /* B */
+                 status = smb2_qfs_sectorsize(sr);
+                 break;
+         default: /* there are some infoclasses we don't yet handle */
+                 status = NT_STATUS_INVALID_INFO_CLASS;
+ #ifdef  DEBUG
+                 cmn_err(CE_NOTE, "unknown InfoClass 0x%x", qi->qi_InfoClass);
+ #endif
+                 break;
          }
  
          return (status);
  }
  
*** 284,289 ****
--- 293,408 ----
  /* ARGSUSED */
  uint32_t
  smb2_qfs_obj_id(smb_request_t *sr)
  {
          return (NT_STATUS_INVALID_PARAMETER);
+ }
+ 
+ /*
+  * Not sure yet where these should go.
+  * Flags in FileFsSectorSizeInformation
+  */
+ 
+ #define SSINFO_FLAGS_ALIGNED_DEVICE     0x00000001
+ // When set, this flag indicates that the first physical sector of the device
+ // is aligned with the first logical sector. When not set, the first physical
+ // sector of the device is misaligned with the first logical sector.
+ 
+ #define SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE        0x00000002
+ // When set, this flag indicates that the partition is aligned to physical
+ // sector boundaries on the storage device.
+ 
+ #define SSINFO_FLAGS_NO_SEEK_PENALTY    0x00000004
+ // When set, the device reports that it does not incur a seek penalty (this
+ // typically indicates that the device does not have rotating media, such as
+ // flash-based disks).
+ 
+ #define SSINFO_FLAGS_TRIM_ENABLED       0x00000008
+ // When set, the device supports TRIM operations, either T13 (ATA) TRIM or
+ // T10 (SCSI/SAS) UNMAP.
+ 
+ #define SSINFO_OFFSET_UNKNOWN           0xffffffff
+ // For "Alignment" fields below
+ 
+ /* We have to lie to Windows Hyper-V about our logical record size. */
+ int smb2_max_logical_sector_size = 4096;
+ 
+ /*
+  * FileFsSectorSizeInformation
+  *
+  * Returns a FILE_FS_SECTOR_SIZE_INFORMATION
+  * See: [MS-FSCC] 2.5.8 FileFsSizeInformation
+  *
+  * LogicalBytesPerSector (4 bytes): ... number of bytes in a logical sector
+  *   for the device backing the volume. This field is the unit of logical
+  *   addressing for the device and is not the unit of atomic write.
+  * PhysicalBytesPerSectorForAtomicity (4 bytes): ... number of bytes in a
+  *   physical sector for the device backing the volume.  This is the reported
+  *   physical sector size of the device and is the unit of atomic write.
+  * PhysicalBytesPerSectorForPerformance (4 bytes): ... number of bytes in a
+  *   physical sector for the device backing the volume. This is the reported
+  *   physical sector size of the device and is the unit of performance.
+  * FileSystemEffectivePhysicalBytesPerSectorForAtomicity (4 bytes): unit, in
+  *   bytes, that the file system on the volume will use for internal operations
+  *   that require alignment and atomicity.
+  * Flags (4 bytes): See ...
+  * ByteOffsetForSectorAlignment (4 bytes): ... logical sector offset within the
+  *   first physical sector where the first logical sector is placed, in bytes.
+  *   If this value is set to SSINFO_OFFSET_UNKNOWN (0xffffffff), there was
+  *   insufficient information to compute this field.
+  * ByteOffsetForPartitionAlignment (4 bytes): ... byte offset from the first
+  *   physical sector where the first partition is placed. If this value is
+  *   set to SSINFO_OFFSET_UNKNOWN (0xffffffff), there was either insufficient
+  *   information or an error was encountered in computing this field.
+  */
+ uint32_t
+ smb2_qfs_sectorsize(smb_request_t *sr)
+ {
+         smb_fssize_t            fssize;
+         smb_tree_t *tree = sr->tid_tree;
+         uint32_t lbps, pbps;
+         uint32_t flags;
+         int rc;
+ 
+         if (!STYPE_ISDSK(tree->t_res_type))
+                 return (NT_STATUS_INVALID_PARAMETER);
+ 
+         rc = smb_fssize(sr, &fssize);
+         if (rc)
+                 return (smb_errno2status(rc));
+         pbps = fssize.fs_bytes_per_sector;
+         lbps = fssize.fs_sectors_per_unit * pbps;
+         if (lbps > smb2_max_logical_sector_size)
+                 lbps = smb2_max_logical_sector_size;
+ 
+         // LogicalBytesPerSector
+         (void) smb_mbc_encodef(&sr->raw_data, "l", lbps);
+ 
+         // PhysicalBytesPerSectorForAtomicity
+         (void) smb_mbc_encodef(&sr->raw_data, "l", pbps);
+ 
+         // PhysicalBytesPerSectorForPerformance
+         // Using logical size here.
+         (void) smb_mbc_encodef(&sr->raw_data, "l", lbps);
+ 
+         // FileSystemEffectivePhysicalBytesPerSectorForAtomicity
+         (void) smb_mbc_encodef(&sr->raw_data, "l", pbps);
+ 
+         // Flags
+         // We include "no seek penalty" because our files are
+         // always ZFS-backed, which can reorder things on disk.
+         // Leaving out SSINFO_FLAGS_TRIM_ENABLED for now.
+         flags = SSINFO_FLAGS_ALIGNED_DEVICE |
+                 SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE |
+                 SSINFO_FLAGS_NO_SEEK_PENALTY;
+         (void) smb_mbc_encodef(&sr->raw_data, "l", flags);
+ 
+         // ByteOffsetForSectorAlignment
+         // ByteOffsetForPartitionAlignment
+         // Just say "unknown" for these two.
+         (void) smb_mbc_encodef(
+             &sr->raw_data, "l",
+             SSINFO_OFFSET_UNKNOWN,
+             SSINFO_OFFSET_UNKNOWN);
+ 
+         return (0);
  }