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)
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/fs/smbsrv/smb2_qinfo_fs.c
+++ new/usr/src/uts/common/fs/smbsrv/smb2_qinfo_fs.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
|
↓ 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 2013 Nexenta Systems, Inc. All rights reserved.
23 + * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
24 24 */
25 25
26 26 /*
27 27 * Dispatch function for SMB2_QUERY_INFO
28 28 *
29 29 * [MS-FSCC 2.5] If a file system does not implement ...
30 30 * an Information Classs, NT_STATUS_INVALID_PARAMETER...
31 31 */
32 32
33 33 #include <smbsrv/smb2_kproto.h>
34 34 #include <smbsrv/smb_fsops.h>
35 35 #include <smbsrv/ntifs.h>
36 36
37 37 uint32_t smb2_qfs_volume(smb_request_t *);
38 38 uint32_t smb2_qfs_size(smb_request_t *);
39 39 uint32_t smb2_qfs_device(smb_request_t *);
40 40 uint32_t smb2_qfs_attr(smb_request_t *);
41 41 uint32_t smb2_qfs_control(smb_request_t *);
42 42 uint32_t smb2_qfs_fullsize(smb_request_t *);
43 43 uint32_t smb2_qfs_obj_id(smb_request_t *);
44 +uint32_t smb2_qfs_sectorsize(smb_request_t *);
44 45
45 46 uint32_t
46 47 smb2_qinfo_fs(smb_request_t *sr, smb_queryinfo_t *qi)
47 48 {
48 49 uint32_t status;
49 50
50 51 switch (qi->qi_InfoClass) {
51 52
52 53 /* pg 153 */
53 54 case FileFsVolumeInformation: /* 1 */
54 55 status = smb2_qfs_volume(sr);
55 56 break;
56 57 case FileFsSizeInformation: /* 3 */
57 58 status = smb2_qfs_size(sr);
58 59 break;
59 60 case FileFsDeviceInformation: /* 4 */
60 61 status = smb2_qfs_device(sr);
61 62 break;
62 63 case FileFsAttributeInformation: /* 5 */
63 64 status = smb2_qfs_attr(sr);
|
↓ open down ↓ |
10 lines elided |
↑ open up ↑ |
64 65 break;
65 66 case FileFsControlInformation: /* 6 */
66 67 status = smb2_qfs_control(sr);
67 68 break;
68 69 case FileFsFullSizeInformation: /* 7 */
69 70 status = smb2_qfs_fullsize(sr);
70 71 break;
71 72 case FileFsObjectIdInformation: /* 8 */
72 73 status = smb2_qfs_obj_id(sr);
73 74 break;
74 -
75 - default:
75 + case FileFsVolumeFlagsInformation: /* A */
76 76 status = NT_STATUS_INVALID_INFO_CLASS;
77 77 break;
78 + case FileFsSectorSizeInformation: /* B */
79 + status = smb2_qfs_sectorsize(sr);
80 + break;
81 + default: /* there are some infoclasses we don't yet handle */
82 + status = NT_STATUS_INVALID_INFO_CLASS;
83 +#ifdef DEBUG
84 + cmn_err(CE_NOTE, "unknown InfoClass 0x%x", qi->qi_InfoClass);
85 +#endif
86 + break;
78 87 }
79 88
80 89 return (status);
81 90 }
82 91
83 92 /*
84 93 * FileFsVolumeInformation
85 94 */
86 95 uint32_t
87 96 smb2_qfs_volume(smb_request_t *sr)
88 97 {
89 98 smb_tree_t *tree = sr->tid_tree;
90 99 smb_node_t *snode;
91 100 fsid_t fsid;
92 101 uint32_t LabelLength;
93 102
94 103 if (!STYPE_ISDSK(tree->t_res_type))
95 104 return (NT_STATUS_INVALID_PARAMETER);
96 105
97 106 snode = tree->t_snode;
98 107 fsid = SMB_NODE_FSID(snode);
99 108
100 109 LabelLength = smb_wcequiv_strlen(tree->t_volume);
101 110
102 111 /*
103 112 * NT has the "supports objects" flag set to 1.
104 113 */
105 114 (void) smb_mbc_encodef(
106 115 &sr->raw_data, "qllb.U",
107 116 0LL, /* Volume creation time (q) */
108 117 fsid.val[0], /* serial no. (l) */
109 118 LabelLength, /* (l) */
110 119 0, /* Supports objects (b) */
111 120 /* reserved (.) */
112 121 tree->t_volume); /* (U) */
113 122
114 123 return (0);
115 124 }
116 125
117 126 /*
118 127 * FileFsSizeInformation
119 128 */
120 129 uint32_t
121 130 smb2_qfs_size(smb_request_t *sr)
122 131 {
123 132 smb_fssize_t fssize;
124 133 smb_tree_t *tree = sr->tid_tree;
125 134 int rc;
126 135
127 136 if (!STYPE_ISDSK(tree->t_res_type))
128 137 return (NT_STATUS_INVALID_PARAMETER);
129 138
130 139 rc = smb_fssize(sr, &fssize);
131 140 if (rc)
132 141 return (smb_errno2status(rc));
133 142
134 143 (void) smb_mbc_encodef(
135 144 &sr->raw_data, "qqll",
136 145 fssize.fs_caller_units,
137 146 fssize.fs_caller_avail,
138 147 fssize.fs_sectors_per_unit,
139 148 fssize.fs_bytes_per_sector);
140 149
141 150 return (0);
142 151 }
143 152
144 153 /*
145 154 * FileFsFullSizeInformation
146 155 */
147 156 uint32_t
148 157 smb2_qfs_fullsize(smb_request_t *sr)
149 158 {
150 159 smb_fssize_t fssize;
151 160 smb_tree_t *tree = sr->tid_tree;
152 161 int rc;
153 162
154 163 if (!STYPE_ISDSK(tree->t_res_type))
155 164 return (NT_STATUS_INVALID_PARAMETER);
156 165
157 166 rc = smb_fssize(sr, &fssize);
158 167 if (rc)
159 168 return (smb_errno2status(rc));
160 169
161 170 (void) smb_mbc_encodef(
162 171 &sr->raw_data, "qqqll",
163 172 fssize.fs_caller_units,
164 173 fssize.fs_caller_avail,
165 174 fssize.fs_volume_avail,
166 175 fssize.fs_sectors_per_unit,
167 176 fssize.fs_bytes_per_sector);
168 177
169 178 return (0);
170 179 }
171 180
172 181 /*
173 182 * FileFsDeviceInformation
174 183 */
175 184 uint32_t
176 185 smb2_qfs_device(smb_request_t *sr)
177 186 {
178 187 smb_tree_t *tree = sr->tid_tree;
179 188 uint32_t DeviceType;
180 189 uint32_t Characteristics;
181 190
182 191 if (!STYPE_ISDSK(tree->t_res_type))
183 192 return (NT_STATUS_INVALID_PARAMETER);
184 193
185 194 DeviceType = FILE_DEVICE_DISK;
186 195 Characteristics = FILE_DEVICE_IS_MOUNTED;
187 196
188 197 (void) smb_mbc_encodef(
189 198 &sr->raw_data, "ll",
190 199 DeviceType,
191 200 Characteristics);
192 201
193 202 return (0);
194 203 }
195 204
196 205 /*
197 206 * FileFsAttributeInformation
198 207 */
199 208 uint32_t
200 209 smb2_qfs_attr(smb_request_t *sr)
201 210 {
202 211 smb_tree_t *tree = sr->tid_tree;
203 212 char *fsname;
204 213 uint32_t namelen;
205 214 uint32_t FsAttr;
206 215
207 216 /* This call is OK on all tree types. */
208 217 switch (tree->t_res_type & STYPE_MASK) {
209 218 case STYPE_IPC:
210 219 fsname = "PIPE";
211 220 break;
212 221 case STYPE_DISKTREE:
213 222 fsname = "NTFS"; /* A lie, but compatible... */
214 223 break;
215 224 case STYPE_PRINTQ:
216 225 case STYPE_DEVICE:
217 226 default: /* gcc -Wuninitialized */
218 227 return (NT_STATUS_INVALID_PARAMETER);
219 228 }
220 229 namelen = smb_wcequiv_strlen(fsname);
221 230
222 231 /*
223 232 * Todo: Store the FsAttributes in the tree object,
224 233 * then just return that directly here.
225 234 */
226 235 FsAttr = FILE_CASE_PRESERVED_NAMES;
227 236 if (tree->t_flags & SMB_TREE_UNICODE_ON_DISK)
228 237 FsAttr |= FILE_UNICODE_ON_DISK;
229 238 if (tree->t_flags & SMB_TREE_SUPPORTS_ACLS)
230 239 FsAttr |= FILE_PERSISTENT_ACLS;
231 240 if ((tree->t_flags & SMB_TREE_CASEINSENSITIVE) == 0)
232 241 FsAttr |= FILE_CASE_SENSITIVE_SEARCH;
233 242 if (tree->t_flags & SMB_TREE_STREAMS)
234 243 FsAttr |= FILE_NAMED_STREAMS;
235 244 if (tree->t_flags & SMB_TREE_QUOTA)
236 245 FsAttr |= FILE_VOLUME_QUOTAS;
237 246 if (tree->t_flags & SMB_TREE_SPARSE)
238 247 FsAttr |= FILE_SUPPORTS_SPARSE_FILES;
239 248
240 249 (void) smb_mbc_encodef(
241 250 &sr->raw_data, "lllU",
242 251 FsAttr,
243 252 MAXNAMELEN-1,
244 253 namelen,
245 254 fsname);
246 255
247 256 return (0);
248 257 }
249 258
250 259 /*
251 260 * FileFsControlInformation
252 261 */
253 262 uint32_t
254 263 smb2_qfs_control(smb_request_t *sr)
255 264 {
256 265 smb_tree_t *tree = sr->tid_tree;
257 266
258 267 if (!STYPE_ISDSK(tree->t_res_type))
259 268 return (NT_STATUS_INVALID_PARAMETER);
260 269 if (!smb_tree_has_feature(sr->tid_tree, SMB_TREE_QUOTA)) {
261 270 /*
262 271 * Strange error per. [MS-FSCC 2.5.2]
263 272 * which means quotas not supported.
264 273 */
265 274 return (NT_STATUS_VOLUME_NOT_UPGRADED);
266 275 }
267 276
268 277 (void) smb_mbc_encodef(
269 278 &sr->raw_data, "qqqqqll",
270 279 0, /* free space start filtering - MUST be 0 */
271 280 0, /* free space threshold - MUST be 0 */
272 281 0, /* free space stop filtering - MUST be 0 */
273 282 SMB_QUOTA_UNLIMITED, /* default quota threshold */
274 283 SMB_QUOTA_UNLIMITED, /* default quota limit */
275 284 FILE_VC_QUOTA_ENFORCE, /* fs control flag */
276 285 0); /* pad bytes */
277 286
278 287 return (0);
|
↓ open down ↓ |
191 lines elided |
↑ open up ↑ |
279 288 }
280 289
281 290 /*
282 291 * FileFsObjectIdInformation
283 292 */
284 293 /* ARGSUSED */
285 294 uint32_t
286 295 smb2_qfs_obj_id(smb_request_t *sr)
287 296 {
288 297 return (NT_STATUS_INVALID_PARAMETER);
298 +}
299 +
300 +/*
301 + * Not sure yet where these should go.
302 + * Flags in FileFsSectorSizeInformation
303 + */
304 +
305 +#define SSINFO_FLAGS_ALIGNED_DEVICE 0x00000001
306 +// When set, this flag indicates that the first physical sector of the device
307 +// is aligned with the first logical sector. When not set, the first physical
308 +// sector of the device is misaligned with the first logical sector.
309 +
310 +#define SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE 0x00000002
311 +// When set, this flag indicates that the partition is aligned to physical
312 +// sector boundaries on the storage device.
313 +
314 +#define SSINFO_FLAGS_NO_SEEK_PENALTY 0x00000004
315 +// When set, the device reports that it does not incur a seek penalty (this
316 +// typically indicates that the device does not have rotating media, such as
317 +// flash-based disks).
318 +
319 +#define SSINFO_FLAGS_TRIM_ENABLED 0x00000008
320 +// When set, the device supports TRIM operations, either T13 (ATA) TRIM or
321 +// T10 (SCSI/SAS) UNMAP.
322 +
323 +#define SSINFO_OFFSET_UNKNOWN 0xffffffff
324 +// For "Alignment" fields below
325 +
326 +/* We have to lie to Windows Hyper-V about our logical record size. */
327 +int smb2_max_logical_sector_size = 4096;
328 +
329 +/*
330 + * FileFsSectorSizeInformation
331 + *
332 + * Returns a FILE_FS_SECTOR_SIZE_INFORMATION
333 + * See: [MS-FSCC] 2.5.8 FileFsSizeInformation
334 + *
335 + * LogicalBytesPerSector (4 bytes): ... number of bytes in a logical sector
336 + * for the device backing the volume. This field is the unit of logical
337 + * addressing for the device and is not the unit of atomic write.
338 + * PhysicalBytesPerSectorForAtomicity (4 bytes): ... number of bytes in a
339 + * physical sector for the device backing the volume. This is the reported
340 + * physical sector size of the device and is the unit of atomic write.
341 + * PhysicalBytesPerSectorForPerformance (4 bytes): ... number of bytes in a
342 + * physical sector for the device backing the volume. This is the reported
343 + * physical sector size of the device and is the unit of performance.
344 + * FileSystemEffectivePhysicalBytesPerSectorForAtomicity (4 bytes): unit, in
345 + * bytes, that the file system on the volume will use for internal operations
346 + * that require alignment and atomicity.
347 + * Flags (4 bytes): See ...
348 + * ByteOffsetForSectorAlignment (4 bytes): ... logical sector offset within the
349 + * first physical sector where the first logical sector is placed, in bytes.
350 + * If this value is set to SSINFO_OFFSET_UNKNOWN (0xffffffff), there was
351 + * insufficient information to compute this field.
352 + * ByteOffsetForPartitionAlignment (4 bytes): ... byte offset from the first
353 + * physical sector where the first partition is placed. If this value is
354 + * set to SSINFO_OFFSET_UNKNOWN (0xffffffff), there was either insufficient
355 + * information or an error was encountered in computing this field.
356 + */
357 +uint32_t
358 +smb2_qfs_sectorsize(smb_request_t *sr)
359 +{
360 + smb_fssize_t fssize;
361 + smb_tree_t *tree = sr->tid_tree;
362 + uint32_t lbps, pbps;
363 + uint32_t flags;
364 + int rc;
365 +
366 + if (!STYPE_ISDSK(tree->t_res_type))
367 + return (NT_STATUS_INVALID_PARAMETER);
368 +
369 + rc = smb_fssize(sr, &fssize);
370 + if (rc)
371 + return (smb_errno2status(rc));
372 + pbps = fssize.fs_bytes_per_sector;
373 + lbps = fssize.fs_sectors_per_unit * pbps;
374 + if (lbps > smb2_max_logical_sector_size)
375 + lbps = smb2_max_logical_sector_size;
376 +
377 + // LogicalBytesPerSector
378 + (void) smb_mbc_encodef(&sr->raw_data, "l", lbps);
379 +
380 + // PhysicalBytesPerSectorForAtomicity
381 + (void) smb_mbc_encodef(&sr->raw_data, "l", pbps);
382 +
383 + // PhysicalBytesPerSectorForPerformance
384 + // Using logical size here.
385 + (void) smb_mbc_encodef(&sr->raw_data, "l", lbps);
386 +
387 + // FileSystemEffectivePhysicalBytesPerSectorForAtomicity
388 + (void) smb_mbc_encodef(&sr->raw_data, "l", pbps);
389 +
390 + // Flags
391 + // We include "no seek penalty" because our files are
392 + // always ZFS-backed, which can reorder things on disk.
393 + // Leaving out SSINFO_FLAGS_TRIM_ENABLED for now.
394 + flags = SSINFO_FLAGS_ALIGNED_DEVICE |
395 + SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE |
396 + SSINFO_FLAGS_NO_SEEK_PENALTY;
397 + (void) smb_mbc_encodef(&sr->raw_data, "l", flags);
398 +
399 + // ByteOffsetForSectorAlignment
400 + // ByteOffsetForPartitionAlignment
401 + // Just say "unknown" for these two.
402 + (void) smb_mbc_encodef(
403 + &sr->raw_data, "l",
404 + SSINFO_OFFSET_UNKNOWN,
405 + SSINFO_OFFSET_UNKNOWN);
406 +
407 + return (0);
289 408 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX