Blame view

fs/cifs/smb2ops.c 59 KB
1080ef758   Steve French   CIFS: Introduce S...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  /*
   *  SMB2 version specific operations
   *
   *  Copyright (c) 2012, Jeff Layton <jlayton@redhat.com>
   *
   *  This library is free software; you can redistribute it and/or modify
   *  it under the terms of the GNU General Public License v2 as published
   *  by the Free Software Foundation.
   *
   *  This library is distributed in the hope that it will be useful,
   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
   *  the GNU Lesser General Public License for more details.
   *
   *  You should have received a copy of the GNU Lesser General Public License
   *  along with this library; if not, write to the Free Software
   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
   */
3a3bab509   Pavel Shilovsky   CIFS: Add SMB2 r/...
19
  #include <linux/pagemap.h>
6fc05c25c   Pavel Shilovsky   CIFS: Add statfs ...
20
  #include <linux/vfs.h>
f29ebb47d   Steve French   Add worker functi...
21
  #include <linux/falloc.h>
1080ef758   Steve French   CIFS: Introduce S...
22
  #include "cifsglob.h"
2dc7e1c03   Pavel Shilovsky   CIFS: Make transp...
23
24
  #include "smb2pdu.h"
  #include "smb2proto.h"
28ea5290d   Pavel Shilovsky   CIFS: Add SMB2 cr...
25
26
  #include "cifsproto.h"
  #include "cifs_debug.h"
b42bf8882   Pavel Shilovsky   CIFS: Implement f...
27
  #include "cifs_unicode.h"
2e44b2887   Pavel Shilovsky   CIFS: Process opl...
28
  #include "smb2status.h"
6fc05c25c   Pavel Shilovsky   CIFS: Add statfs ...
29
  #include "smb2glob.h"
834170c85   Steve French   Enable previous v...
30
  #include "cifs_ioctl.h"
28ea5290d   Pavel Shilovsky   CIFS: Add SMB2 cr...
31
32
33
34
35
36
37
38
39
40
41
42
  
  static int
  change_conf(struct TCP_Server_Info *server)
  {
  	server->credits += server->echo_credits + server->oplock_credits;
  	server->oplock_credits = server->echo_credits = 0;
  	switch (server->credits) {
  	case 0:
  		return -1;
  	case 1:
  		server->echoes = false;
  		server->oplocks = false;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
43
44
  		cifs_dbg(VFS, "disabling echoes and oplocks
  ");
28ea5290d   Pavel Shilovsky   CIFS: Add SMB2 cr...
45
46
47
48
49
  		break;
  	case 2:
  		server->echoes = true;
  		server->oplocks = false;
  		server->echo_credits = 1;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
50
51
  		cifs_dbg(FYI, "disabling oplocks
  ");
28ea5290d   Pavel Shilovsky   CIFS: Add SMB2 cr...
52
53
54
  		break;
  	default:
  		server->echoes = true;
e0ddde9d4   Steve French   disabling oplocks...
55
56
57
58
59
  		if (enable_oplocks) {
  			server->oplocks = true;
  			server->oplock_credits = 1;
  		} else
  			server->oplocks = false;
28ea5290d   Pavel Shilovsky   CIFS: Add SMB2 cr...
60
  		server->echo_credits = 1;
28ea5290d   Pavel Shilovsky   CIFS: Add SMB2 cr...
61
62
63
64
65
66
67
68
69
70
71
72
73
  	}
  	server->credits -= server->echo_credits + server->oplock_credits;
  	return 0;
  }
  
  static void
  smb2_add_credits(struct TCP_Server_Info *server, const unsigned int add,
  		 const int optype)
  {
  	int *val, rc = 0;
  	spin_lock(&server->req_lock);
  	val = server->ops->get_credits_field(server, optype);
  	*val += add;
141891f47   Steve French   SMB3: Add mount p...
74
75
76
77
78
  	if (*val > 65000) {
  		*val = 65000; /* Don't get near 64K credits, avoid srv bugs */
  		printk_once(KERN_WARNING "server overflowed SMB3 credits
  ");
  	}
28ea5290d   Pavel Shilovsky   CIFS: Add SMB2 cr...
79
  	server->in_flight--;
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
80
  	if (server->in_flight == 0 && (optype & CIFS_OP_MASK) != CIFS_NEG_OP)
28ea5290d   Pavel Shilovsky   CIFS: Add SMB2 cr...
81
  		rc = change_conf(server);
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
82
83
84
85
86
87
88
89
90
91
92
  	/*
  	 * Sometimes server returns 0 credits on oplock break ack - we need to
  	 * rebalance credits in this case.
  	 */
  	else if (server->in_flight > 0 && server->oplock_credits == 0 &&
  		 server->oplocks) {
  		if (server->credits > 1) {
  			server->credits--;
  			server->oplock_credits++;
  		}
  	}
28ea5290d   Pavel Shilovsky   CIFS: Add SMB2 cr...
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
  	spin_unlock(&server->req_lock);
  	wake_up(&server->request_q);
  	if (rc)
  		cifs_reconnect(server);
  }
  
  static void
  smb2_set_credits(struct TCP_Server_Info *server, const int val)
  {
  	spin_lock(&server->req_lock);
  	server->credits = val;
  	spin_unlock(&server->req_lock);
  }
  
  static int *
  smb2_get_credits_field(struct TCP_Server_Info *server, const int optype)
  {
  	switch (optype) {
  	case CIFS_ECHO_OP:
  		return &server->echo_credits;
  	case CIFS_OBREAK_OP:
  		return &server->oplock_credits;
  	default:
  		return &server->credits;
  	}
  }
  
  static unsigned int
  smb2_get_credits(struct mid_q_entry *mid)
  {
  	return le16_to_cpu(((struct smb2_hdr *)mid->resp_buf)->CreditRequest);
  }
2dc7e1c03   Pavel Shilovsky   CIFS: Make transp...
125

cb7e9eabb   Pavel Shilovsky   CIFS: Use multicr...
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
  static int
  smb2_wait_mtu_credits(struct TCP_Server_Info *server, unsigned int size,
  		      unsigned int *num, unsigned int *credits)
  {
  	int rc = 0;
  	unsigned int scredits;
  
  	spin_lock(&server->req_lock);
  	while (1) {
  		if (server->credits <= 0) {
  			spin_unlock(&server->req_lock);
  			cifs_num_waiters_inc(server);
  			rc = wait_event_killable(server->request_q,
  					has_credits(server, &server->credits));
  			cifs_num_waiters_dec(server);
  			if (rc)
  				return rc;
  			spin_lock(&server->req_lock);
  		} else {
  			if (server->tcpStatus == CifsExiting) {
  				spin_unlock(&server->req_lock);
  				return -ENOENT;
  			}
  
  			scredits = server->credits;
  			/* can deadlock with reopen */
  			if (scredits == 1) {
  				*num = SMB2_MAX_BUFFER_SIZE;
  				*credits = 0;
  				break;
  			}
  
  			/* leave one credit for a possible reopen */
  			scredits--;
  			*num = min_t(unsigned int, size,
  				     scredits * SMB2_MAX_BUFFER_SIZE);
  
  			*credits = DIV_ROUND_UP(*num, SMB2_MAX_BUFFER_SIZE);
  			server->credits -= *credits;
  			server->in_flight++;
  			break;
  		}
  	}
  	spin_unlock(&server->req_lock);
  	return rc;
  }
2dc7e1c03   Pavel Shilovsky   CIFS: Make transp...
172
173
174
175
176
177
178
179
180
181
  static __u64
  smb2_get_next_mid(struct TCP_Server_Info *server)
  {
  	__u64 mid;
  	/* for SMB2 we need the current value */
  	spin_lock(&GlobalMid_Lock);
  	mid = server->CurrentMid++;
  	spin_unlock(&GlobalMid_Lock);
  	return mid;
  }
1080ef758   Steve French   CIFS: Introduce S...
182

093b2bdad   Pavel Shilovsky   CIFS: Make demult...
183
184
185
186
187
  static struct mid_q_entry *
  smb2_find_mid(struct TCP_Server_Info *server, char *buf)
  {
  	struct mid_q_entry *mid;
  	struct smb2_hdr *hdr = (struct smb2_hdr *)buf;
9235d0987   Sachin Prabhu   Convert MessageID...
188
  	__u64 wire_mid = le64_to_cpu(hdr->MessageId);
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
189

373512ec5   Steve French   Prepare for encry...
190
191
192
193
  	if (hdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) {
  		cifs_dbg(VFS, "encrypted frame parsing not supported yet");
  		return NULL;
  	}
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
194
195
  	spin_lock(&GlobalMid_Lock);
  	list_for_each_entry(mid, &server->pending_mid_q, qhead) {
9235d0987   Sachin Prabhu   Convert MessageID...
196
  		if ((mid->mid == wire_mid) &&
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
  		    (mid->mid_state == MID_REQUEST_SUBMITTED) &&
  		    (mid->command == hdr->Command)) {
  			spin_unlock(&GlobalMid_Lock);
  			return mid;
  		}
  	}
  	spin_unlock(&GlobalMid_Lock);
  	return NULL;
  }
  
  static void
  smb2_dump_detail(void *buf)
  {
  #ifdef CONFIG_CIFS_DEBUG2
  	struct smb2_hdr *smb = (struct smb2_hdr *)buf;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
212
213
214
215
216
217
  	cifs_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Mid: %llu Pid: %d
  ",
  		 smb->Command, smb->Status, smb->Flags, smb->MessageId,
  		 smb->ProcessId);
  	cifs_dbg(VFS, "smb buf %p len %u
  ", smb, smb2_calc_size(smb));
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
218
219
  #endif
  }
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
  static bool
  smb2_need_neg(struct TCP_Server_Info *server)
  {
  	return server->max_read == 0;
  }
  
  static int
  smb2_negotiate(const unsigned int xid, struct cifs_ses *ses)
  {
  	int rc;
  	ses->server->CurrentMid = 0;
  	rc = SMB2_negotiate(xid, ses);
  	/* BB we probably don't need to retry with modern servers */
  	if (rc == -EAGAIN)
  		rc = -EHOSTDOWN;
  	return rc;
  }
3a3bab509   Pavel Shilovsky   CIFS: Add SMB2 r/...
237
238
239
240
241
242
243
244
245
  static unsigned int
  smb2_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *volume_info)
  {
  	struct TCP_Server_Info *server = tcon->ses->server;
  	unsigned int wsize;
  
  	/* start with specified wsize, or default */
  	wsize = volume_info->wsize ? volume_info->wsize : CIFS_DEFAULT_IOSIZE;
  	wsize = min_t(unsigned int, wsize, server->max_write);
cb7e9eabb   Pavel Shilovsky   CIFS: Use multicr...
246
247
248
  
  	if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU))
  		wsize = min_t(unsigned int, wsize, SMB2_MAX_BUFFER_SIZE);
3a3bab509   Pavel Shilovsky   CIFS: Add SMB2 r/...
249

3a3bab509   Pavel Shilovsky   CIFS: Add SMB2 r/...
250
251
252
253
254
255
256
257
258
259
260
261
  	return wsize;
  }
  
  static unsigned int
  smb2_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *volume_info)
  {
  	struct TCP_Server_Info *server = tcon->ses->server;
  	unsigned int rsize;
  
  	/* start with specified rsize, or default */
  	rsize = volume_info->rsize ? volume_info->rsize : CIFS_DEFAULT_IOSIZE;
  	rsize = min_t(unsigned int, rsize, server->max_read);
bed9da021   Pavel Shilovsky   CIFS: Use multicr...
262
263
264
  
  	if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU))
  		rsize = min_t(unsigned int, rsize, SMB2_MAX_BUFFER_SIZE);
3a3bab509   Pavel Shilovsky   CIFS: Add SMB2 r/...
265

3a3bab509   Pavel Shilovsky   CIFS: Add SMB2 r/...
266
267
  	return rsize;
  }
c481e9fee   Steve French   Query network ada...
268
269
270
271
272
273
274
275
276
277
278
279
  #ifdef CONFIG_CIFS_STATS2
  static int
  SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon)
  {
  	int rc;
  	unsigned int ret_data_len = 0;
  	struct network_interface_info_ioctl_rsp *out_buf;
  
  	rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
  			FSCTL_QUERY_NETWORK_INTERFACE_INFO, true /* is_fsctl */,
  			NULL /* no data input */, 0 /* no data input */,
  			(char **)&out_buf, &ret_data_len);
9ffc54129   Steve French   Check minimum res...
280
281
282
283
284
285
286
287
  	if (rc != 0)
  		cifs_dbg(VFS, "error %d on ioctl to get interface list
  ", rc);
  	else if (ret_data_len < sizeof(struct network_interface_info_ioctl_rsp)) {
  		cifs_dbg(VFS, "server returned bad net interface info buf
  ");
  		rc = -EINVAL;
  	} else {
c481e9fee   Steve French   Query network ada...
288
289
290
291
292
293
  		/* Dump info on first interface */
  		cifs_dbg(FYI, "Adapter Capability 0x%x\t",
  			le32_to_cpu(out_buf->Capability));
  		cifs_dbg(FYI, "Link Speed %lld
  ",
  			le64_to_cpu(out_buf->LinkSpeed));
9ffc54129   Steve French   Check minimum res...
294
  	}
24df1483c   Steve French   Cleanup missing f...
295
  	kfree(out_buf);
c481e9fee   Steve French   Query network ada...
296
297
298
  	return rc;
  }
  #endif /* STATS2 */
34f626406   Steve French   Query file system...
299
  static void
af6a12ea8   Steven French   Query File System...
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
  smb3_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon)
  {
  	int rc;
  	__le16 srch_path = 0; /* Null - open root of share */
  	u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
  	struct cifs_open_parms oparms;
  	struct cifs_fid fid;
  
  	oparms.tcon = tcon;
  	oparms.desired_access = FILE_READ_ATTRIBUTES;
  	oparms.disposition = FILE_OPEN;
  	oparms.create_options = 0;
  	oparms.fid = &fid;
  	oparms.reconnect = false;
  
  	rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL);
  	if (rc)
  		return;
c481e9fee   Steve French   Query network ada...
318
319
320
  #ifdef CONFIG_CIFS_STATS2
  	SMB3_request_interfaces(xid, tcon);
  #endif /* STATS2 */
af6a12ea8   Steven French   Query File System...
321
322
323
324
325
326
327
328
329
330
331
  	SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid,
  			FS_ATTRIBUTE_INFORMATION);
  	SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid,
  			FS_DEVICE_INFORMATION);
  	SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid,
  			FS_SECTOR_SIZE_INFORMATION); /* SMB3 specific */
  	SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
  	return;
  }
  
  static void
34f626406   Steve French   Query file system...
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
  smb2_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon)
  {
  	int rc;
  	__le16 srch_path = 0; /* Null - open root of share */
  	u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
  	struct cifs_open_parms oparms;
  	struct cifs_fid fid;
  
  	oparms.tcon = tcon;
  	oparms.desired_access = FILE_READ_ATTRIBUTES;
  	oparms.disposition = FILE_OPEN;
  	oparms.create_options = 0;
  	oparms.fid = &fid;
  	oparms.reconnect = false;
  
  	rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL);
  	if (rc)
  		return;
2167114c6   Steven French   Query device char...
350
351
352
353
  	SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid,
  			FS_ATTRIBUTE_INFORMATION);
  	SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid,
  			FS_DEVICE_INFORMATION);
34f626406   Steve French   Query file system...
354
355
356
  	SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
  	return;
  }
2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
357
358
359
360
361
  static int
  smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon,
  			struct cifs_sb_info *cifs_sb, const char *full_path)
  {
  	int rc;
2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
362
  	__le16 *utf16_path;
2e44b2887   Pavel Shilovsky   CIFS: Process opl...
363
  	__u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
064f6047a   Pavel Shilovsky   CIFS: Make SMB2_o...
364
365
  	struct cifs_open_parms oparms;
  	struct cifs_fid fid;
2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
366
367
368
369
  
  	utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
  	if (!utf16_path)
  		return -ENOMEM;
064f6047a   Pavel Shilovsky   CIFS: Make SMB2_o...
370
371
372
373
374
  	oparms.tcon = tcon;
  	oparms.desired_access = FILE_READ_ATTRIBUTES;
  	oparms.disposition = FILE_OPEN;
  	oparms.create_options = 0;
  	oparms.fid = &fid;
9cbc0b733   Pavel Shilovsky   CIFS: Reconnect d...
375
  	oparms.reconnect = false;
064f6047a   Pavel Shilovsky   CIFS: Make SMB2_o...
376

b42bf8882   Pavel Shilovsky   CIFS: Implement f...
377
  	rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
378
379
380
381
  	if (rc) {
  		kfree(utf16_path);
  		return rc;
  	}
064f6047a   Pavel Shilovsky   CIFS: Make SMB2_o...
382
  	rc = SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
383
384
385
  	kfree(utf16_path);
  	return rc;
  }
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
386
387
388
389
390
391
392
393
  static int
  smb2_get_srv_inum(const unsigned int xid, struct cifs_tcon *tcon,
  		  struct cifs_sb_info *cifs_sb, const char *full_path,
  		  u64 *uniqueid, FILE_ALL_INFO *data)
  {
  	*uniqueid = le64_to_cpu(data->IndexNumber);
  	return 0;
  }
b7546bc54   Pavel Shilovsky   CIFS: Add SMB2 su...
394
395
396
397
398
399
  static int
  smb2_query_file_info(const unsigned int xid, struct cifs_tcon *tcon,
  		     struct cifs_fid *fid, FILE_ALL_INFO *data)
  {
  	int rc;
  	struct smb2_file_all_info *smb2_data;
1bbe4997b   Pavel Shilovsky   CIFS: Fix wrong f...
400
  	smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2,
b7546bc54   Pavel Shilovsky   CIFS: Add SMB2 su...
401
402
403
404
405
406
407
408
409
410
411
  			    GFP_KERNEL);
  	if (smb2_data == NULL)
  		return -ENOMEM;
  
  	rc = SMB2_query_info(xid, tcon, fid->persistent_fid, fid->volatile_fid,
  			     smb2_data);
  	if (!rc)
  		move_smb2_info_to_cifs(data, smb2_data);
  	kfree(smb2_data);
  	return rc;
  }
9094fad1e   Pavel Shilovsky   CIFS: Add echo re...
412
413
414
415
416
  static bool
  smb2_can_echo(struct TCP_Server_Info *server)
  {
  	return server->echoes;
  }
d60622eb5   Pavel Shilovsky   CIFS: Allow SMB2 ...
417
418
419
420
421
422
423
424
425
426
427
428
429
  static void
  smb2_clear_stats(struct cifs_tcon *tcon)
  {
  #ifdef CONFIG_CIFS_STATS
  	int i;
  	for (i = 0; i < NUMBER_OF_SMB2_COMMANDS; i++) {
  		atomic_set(&tcon->stats.smb2_stats.smb2_com_sent[i], 0);
  		atomic_set(&tcon->stats.smb2_stats.smb2_com_failed[i], 0);
  	}
  #endif
  }
  
  static void
769ee6a40   Steve French   Add ability to di...
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
  smb2_dump_share_caps(struct seq_file *m, struct cifs_tcon *tcon)
  {
  	seq_puts(m, "
  \tShare Capabilities:");
  	if (tcon->capabilities & SMB2_SHARE_CAP_DFS)
  		seq_puts(m, " DFS,");
  	if (tcon->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY)
  		seq_puts(m, " CONTINUOUS AVAILABILITY,");
  	if (tcon->capabilities & SMB2_SHARE_CAP_SCALEOUT)
  		seq_puts(m, " SCALEOUT,");
  	if (tcon->capabilities & SMB2_SHARE_CAP_CLUSTER)
  		seq_puts(m, " CLUSTER,");
  	if (tcon->capabilities & SMB2_SHARE_CAP_ASYMMETRIC)
  		seq_puts(m, " ASYMMETRIC,");
  	if (tcon->capabilities == 0)
  		seq_puts(m, " None");
af6a12ea8   Steven French   Query File System...
446
447
448
449
450
451
452
453
  	if (tcon->ss_flags & SSINFO_FLAGS_ALIGNED_DEVICE)
  		seq_puts(m, " Aligned,");
  	if (tcon->ss_flags & SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE)
  		seq_puts(m, " Partition Aligned,");
  	if (tcon->ss_flags & SSINFO_FLAGS_NO_SEEK_PENALTY)
  		seq_puts(m, " SSD,");
  	if (tcon->ss_flags & SSINFO_FLAGS_TRIM_ENABLED)
  		seq_puts(m, " TRIM-support,");
769ee6a40   Steve French   Add ability to di...
454
  	seq_printf(m, "\tShare Flags: 0x%x", tcon->share_flags);
af6a12ea8   Steven French   Query File System...
455
456
457
  	if (tcon->perf_sector_size)
  		seq_printf(m, "\tOptimal sector size: 0x%x",
  			   tcon->perf_sector_size);
769ee6a40   Steve French   Add ability to di...
458
459
460
  }
  
  static void
d60622eb5   Pavel Shilovsky   CIFS: Allow SMB2 ...
461
462
463
464
465
466
467
468
469
470
471
472
473
  smb2_print_stats(struct seq_file *m, struct cifs_tcon *tcon)
  {
  #ifdef CONFIG_CIFS_STATS
  	atomic_t *sent = tcon->stats.smb2_stats.smb2_com_sent;
  	atomic_t *failed = tcon->stats.smb2_stats.smb2_com_failed;
  	seq_printf(m, "
  Negotiates: %d sent %d failed",
  		   atomic_read(&sent[SMB2_NEGOTIATE_HE]),
  		   atomic_read(&failed[SMB2_NEGOTIATE_HE]));
  	seq_printf(m, "
  SessionSetups: %d sent %d failed",
  		   atomic_read(&sent[SMB2_SESSION_SETUP_HE]),
  		   atomic_read(&failed[SMB2_SESSION_SETUP_HE]));
d60622eb5   Pavel Shilovsky   CIFS: Allow SMB2 ...
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
  	seq_printf(m, "
  Logoffs: %d sent %d failed",
  		   atomic_read(&sent[SMB2_LOGOFF_HE]),
  		   atomic_read(&failed[SMB2_LOGOFF_HE]));
  	seq_printf(m, "
  TreeConnects: %d sent %d failed",
  		   atomic_read(&sent[SMB2_TREE_CONNECT_HE]),
  		   atomic_read(&failed[SMB2_TREE_CONNECT_HE]));
  	seq_printf(m, "
  TreeDisconnects: %d sent %d failed",
  		   atomic_read(&sent[SMB2_TREE_DISCONNECT_HE]),
  		   atomic_read(&failed[SMB2_TREE_DISCONNECT_HE]));
  	seq_printf(m, "
  Creates: %d sent %d failed",
  		   atomic_read(&sent[SMB2_CREATE_HE]),
  		   atomic_read(&failed[SMB2_CREATE_HE]));
  	seq_printf(m, "
  Closes: %d sent %d failed",
  		   atomic_read(&sent[SMB2_CLOSE_HE]),
  		   atomic_read(&failed[SMB2_CLOSE_HE]));
  	seq_printf(m, "
  Flushes: %d sent %d failed",
  		   atomic_read(&sent[SMB2_FLUSH_HE]),
  		   atomic_read(&failed[SMB2_FLUSH_HE]));
  	seq_printf(m, "
  Reads: %d sent %d failed",
  		   atomic_read(&sent[SMB2_READ_HE]),
  		   atomic_read(&failed[SMB2_READ_HE]));
  	seq_printf(m, "
  Writes: %d sent %d failed",
  		   atomic_read(&sent[SMB2_WRITE_HE]),
  		   atomic_read(&failed[SMB2_WRITE_HE]));
  	seq_printf(m, "
  Locks: %d sent %d failed",
  		   atomic_read(&sent[SMB2_LOCK_HE]),
  		   atomic_read(&failed[SMB2_LOCK_HE]));
  	seq_printf(m, "
  IOCTLs: %d sent %d failed",
  		   atomic_read(&sent[SMB2_IOCTL_HE]),
  		   atomic_read(&failed[SMB2_IOCTL_HE]));
  	seq_printf(m, "
  Cancels: %d sent %d failed",
  		   atomic_read(&sent[SMB2_CANCEL_HE]),
  		   atomic_read(&failed[SMB2_CANCEL_HE]));
  	seq_printf(m, "
  Echos: %d sent %d failed",
  		   atomic_read(&sent[SMB2_ECHO_HE]),
  		   atomic_read(&failed[SMB2_ECHO_HE]));
  	seq_printf(m, "
  QueryDirectories: %d sent %d failed",
  		   atomic_read(&sent[SMB2_QUERY_DIRECTORY_HE]),
  		   atomic_read(&failed[SMB2_QUERY_DIRECTORY_HE]));
  	seq_printf(m, "
  ChangeNotifies: %d sent %d failed",
  		   atomic_read(&sent[SMB2_CHANGE_NOTIFY_HE]),
  		   atomic_read(&failed[SMB2_CHANGE_NOTIFY_HE]));
  	seq_printf(m, "
  QueryInfos: %d sent %d failed",
  		   atomic_read(&sent[SMB2_QUERY_INFO_HE]),
  		   atomic_read(&failed[SMB2_QUERY_INFO_HE]));
  	seq_printf(m, "
  SetInfos: %d sent %d failed",
  		   atomic_read(&sent[SMB2_SET_INFO_HE]),
  		   atomic_read(&failed[SMB2_SET_INFO_HE]));
  	seq_printf(m, "
  OplockBreaks: %d sent %d failed",
  		   atomic_read(&sent[SMB2_OPLOCK_BREAK_HE]),
  		   atomic_read(&failed[SMB2_OPLOCK_BREAK_HE]));
  #endif
  }
f0df737ee   Pavel Shilovsky   CIFS: Add open/cl...
544
545
546
  static void
  smb2_set_fid(struct cifsFileInfo *cfile, struct cifs_fid *fid, __u32 oplock)
  {
2b0143b5c   David Howells   VFS: normal files...
547
  	struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
53ef1016f   Pavel Shilovsky   CIFS: Store lease...
548
  	struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server;
f0df737ee   Pavel Shilovsky   CIFS: Add open/cl...
549
550
  	cfile->fid.persistent_fid = fid->persistent_fid;
  	cfile->fid.volatile_fid = fid->volatile_fid;
42873b0a2   Pavel Shilovsky   CIFS: Respect epo...
551
552
  	server->ops->set_oplock_level(cinode, oplock, fid->epoch,
  				      &fid->purge_cache);
18cceb6a7   Pavel Shilovsky   CIFS: Replace cli...
553
  	cinode->can_cache_brlcks = CIFS_CACHE_WRITE(cinode);
94f873717   Aurelien Aptel   fs/cifs: keep gui...
554
  	memcpy(cfile->fid.create_guid, fid->create_guid, 16);
f0df737ee   Pavel Shilovsky   CIFS: Add open/cl...
555
  }
760ad0cac   Pavel Shilovsky   CIFS: Make ops->c...
556
  static void
f0df737ee   Pavel Shilovsky   CIFS: Add open/cl...
557
558
559
  smb2_close_file(const unsigned int xid, struct cifs_tcon *tcon,
  		struct cifs_fid *fid)
  {
760ad0cac   Pavel Shilovsky   CIFS: Make ops->c...
560
  	SMB2_close(xid, tcon, fid->persistent_fid, fid->volatile_fid);
f0df737ee   Pavel Shilovsky   CIFS: Add open/cl...
561
  }
7a5cfb196   Pavel Shilovsky   CIFS: Add SMB2 su...
562
  static int
41c1358e9   Steve French   CIFS: SMB2/SMB3 C...
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
  SMB2_request_res_key(const unsigned int xid, struct cifs_tcon *tcon,
  		     u64 persistent_fid, u64 volatile_fid,
  		     struct copychunk_ioctl *pcchunk)
  {
  	int rc;
  	unsigned int ret_data_len;
  	struct resume_key_req *res_key;
  
  	rc = SMB2_ioctl(xid, tcon, persistent_fid, volatile_fid,
  			FSCTL_SRV_REQUEST_RESUME_KEY, true /* is_fsctl */,
  			NULL, 0 /* no input */,
  			(char **)&res_key, &ret_data_len);
  
  	if (rc) {
  		cifs_dbg(VFS, "refcpy ioctl error %d getting resume key
  ", rc);
  		goto req_res_key_exit;
  	}
  	if (ret_data_len < sizeof(struct resume_key_req)) {
  		cifs_dbg(VFS, "Invalid refcopy resume key length
  ");
  		rc = -EINVAL;
  		goto req_res_key_exit;
  	}
  	memcpy(pcchunk->SourceKey, res_key->ResumeKey, COPY_CHUNK_RES_KEY_SIZE);
  
  req_res_key_exit:
  	kfree(res_key);
  	return rc;
  }
  
  static int
  smb2_clone_range(const unsigned int xid,
  			struct cifsFileInfo *srcfile,
  			struct cifsFileInfo *trgtfile, u64 src_off,
  			u64 len, u64 dest_off)
  {
  	int rc;
  	unsigned int ret_data_len;
  	struct copychunk_ioctl *pcchunk;
9bf0c9cd4   Steve French   CIFS: Fix SMB2/SM...
603
604
605
606
  	struct copychunk_ioctl_rsp *retbuf = NULL;
  	struct cifs_tcon *tcon;
  	int chunks_copied = 0;
  	bool chunk_sizes_updated = false;
41c1358e9   Steve French   CIFS: SMB2/SMB3 C...
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
  
  	pcchunk = kmalloc(sizeof(struct copychunk_ioctl), GFP_KERNEL);
  
  	if (pcchunk == NULL)
  		return -ENOMEM;
  
  	cifs_dbg(FYI, "in smb2_clone_range - about to call request res key
  ");
  	/* Request a key from the server to identify the source of the copy */
  	rc = SMB2_request_res_key(xid, tlink_tcon(srcfile->tlink),
  				srcfile->fid.persistent_fid,
  				srcfile->fid.volatile_fid, pcchunk);
  
  	/* Note: request_res_key sets res_key null only if rc !=0 */
  	if (rc)
9bf0c9cd4   Steve French   CIFS: Fix SMB2/SM...
622
  		goto cchunk_out;
41c1358e9   Steve French   CIFS: SMB2/SMB3 C...
623
624
  
  	/* For now array only one chunk long, will make more flexible later */
bc09d141e   Fabian Frederick   fs/cifs: remove o...
625
  	pcchunk->ChunkCount = cpu_to_le32(1);
41c1358e9   Steve French   CIFS: SMB2/SMB3 C...
626
  	pcchunk->Reserved = 0;
41c1358e9   Steve French   CIFS: SMB2/SMB3 C...
627
  	pcchunk->Reserved2 = 0;
9bf0c9cd4   Steve French   CIFS: Fix SMB2/SM...
628
  	tcon = tlink_tcon(trgtfile->tlink);
41c1358e9   Steve French   CIFS: SMB2/SMB3 C...
629

9bf0c9cd4   Steve French   CIFS: Fix SMB2/SM...
630
631
632
633
634
  	while (len > 0) {
  		pcchunk->SourceOffset = cpu_to_le64(src_off);
  		pcchunk->TargetOffset = cpu_to_le64(dest_off);
  		pcchunk->Length =
  			cpu_to_le32(min_t(u32, len, tcon->max_bytes_chunk));
41c1358e9   Steve French   CIFS: SMB2/SMB3 C...
635

9bf0c9cd4   Steve French   CIFS: Fix SMB2/SM...
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
  		/* Request server copy to target from src identified by key */
  		rc = SMB2_ioctl(xid, tcon, trgtfile->fid.persistent_fid,
  			trgtfile->fid.volatile_fid, FSCTL_SRV_COPYCHUNK_WRITE,
  			true /* is_fsctl */, (char *)pcchunk,
  			sizeof(struct copychunk_ioctl),	(char **)&retbuf,
  			&ret_data_len);
  		if (rc == 0) {
  			if (ret_data_len !=
  					sizeof(struct copychunk_ioctl_rsp)) {
  				cifs_dbg(VFS, "invalid cchunk response size
  ");
  				rc = -EIO;
  				goto cchunk_out;
  			}
  			if (retbuf->TotalBytesWritten == 0) {
  				cifs_dbg(FYI, "no bytes copied
  ");
  				rc = -EIO;
  				goto cchunk_out;
  			}
  			/*
  			 * Check if server claimed to write more than we asked
  			 */
  			if (le32_to_cpu(retbuf->TotalBytesWritten) >
  			    le32_to_cpu(pcchunk->Length)) {
  				cifs_dbg(VFS, "invalid copy chunk response
  ");
  				rc = -EIO;
  				goto cchunk_out;
  			}
  			if (le32_to_cpu(retbuf->ChunksWritten) != 1) {
  				cifs_dbg(VFS, "invalid num chunks written
  ");
  				rc = -EIO;
  				goto cchunk_out;
  			}
  			chunks_copied++;
  
  			src_off += le32_to_cpu(retbuf->TotalBytesWritten);
  			dest_off += le32_to_cpu(retbuf->TotalBytesWritten);
  			len -= le32_to_cpu(retbuf->TotalBytesWritten);
  
  			cifs_dbg(FYI, "Chunks %d PartialChunk %d Total %d
  ",
  				le32_to_cpu(retbuf->ChunksWritten),
  				le32_to_cpu(retbuf->ChunkBytesWritten),
  				le32_to_cpu(retbuf->TotalBytesWritten));
  		} else if (rc == -EINVAL) {
  			if (ret_data_len != sizeof(struct copychunk_ioctl_rsp))
  				goto cchunk_out;
  
  			cifs_dbg(FYI, "MaxChunks %d BytesChunk %d MaxCopy %d
  ",
  				le32_to_cpu(retbuf->ChunksWritten),
  				le32_to_cpu(retbuf->ChunkBytesWritten),
  				le32_to_cpu(retbuf->TotalBytesWritten));
  
  			/*
  			 * Check if this is the first request using these sizes,
  			 * (ie check if copy succeed once with original sizes
  			 * and check if the server gave us different sizes after
  			 * we already updated max sizes on previous request).
  			 * if not then why is the server returning an error now
  			 */
  			if ((chunks_copied != 0) || chunk_sizes_updated)
  				goto cchunk_out;
  
  			/* Check that server is not asking us to grow size */
  			if (le32_to_cpu(retbuf->ChunkBytesWritten) <
  					tcon->max_bytes_chunk)
  				tcon->max_bytes_chunk =
  					le32_to_cpu(retbuf->ChunkBytesWritten);
  			else
  				goto cchunk_out; /* server gave us bogus size */
  
  			/* No need to change MaxChunks since already set to 1 */
  			chunk_sizes_updated = true;
2477bc58d   Sachin Prabhu   cifs: smb2_clone_...
713
714
  		} else
  			goto cchunk_out;
9bf0c9cd4   Steve French   CIFS: Fix SMB2/SM...
715
  	}
41c1358e9   Steve French   CIFS: SMB2/SMB3 C...
716

9bf0c9cd4   Steve French   CIFS: Fix SMB2/SM...
717
  cchunk_out:
41c1358e9   Steve French   CIFS: SMB2/SMB3 C...
718
  	kfree(pcchunk);
24df1483c   Steve French   Cleanup missing f...
719
  	kfree(retbuf);
41c1358e9   Steve French   CIFS: SMB2/SMB3 C...
720
721
722
723
  	return rc;
  }
  
  static int
7a5cfb196   Pavel Shilovsky   CIFS: Add SMB2 su...
724
725
726
727
728
  smb2_flush_file(const unsigned int xid, struct cifs_tcon *tcon,
  		struct cifs_fid *fid)
  {
  	return SMB2_flush(xid, tcon, fid->persistent_fid, fid->volatile_fid);
  }
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
729
730
731
732
733
734
735
736
737
738
739
740
741
  static unsigned int
  smb2_read_data_offset(char *buf)
  {
  	struct smb2_read_rsp *rsp = (struct smb2_read_rsp *)buf;
  	return rsp->DataOffset;
  }
  
  static unsigned int
  smb2_read_data_length(char *buf)
  {
  	struct smb2_read_rsp *rsp = (struct smb2_read_rsp *)buf;
  	return le32_to_cpu(rsp->DataLength);
  }
d8e050398   Pavel Shilovsky   CIFS: Add readpag...
742
743
  
  static int
db8b631d4   Steve French   Allow mknod and m...
744
  smb2_sync_read(const unsigned int xid, struct cifs_fid *pfid,
d8e050398   Pavel Shilovsky   CIFS: Add readpag...
745
746
747
  	       struct cifs_io_parms *parms, unsigned int *bytes_read,
  	       char **buf, int *buf_type)
  {
db8b631d4   Steve French   Allow mknod and m...
748
749
  	parms->persistent_fid = pfid->persistent_fid;
  	parms->volatile_fid = pfid->volatile_fid;
d8e050398   Pavel Shilovsky   CIFS: Add readpag...
750
751
  	return SMB2_read(xid, parms, bytes_read, buf, buf_type);
  }
009d34439   Pavel Shilovsky   CIFS: Add writepa...
752
  static int
db8b631d4   Steve French   Allow mknod and m...
753
  smb2_sync_write(const unsigned int xid, struct cifs_fid *pfid,
009d34439   Pavel Shilovsky   CIFS: Add writepa...
754
755
756
  		struct cifs_io_parms *parms, unsigned int *written,
  		struct kvec *iov, unsigned long nr_segs)
  {
db8b631d4   Steve French   Allow mknod and m...
757
758
  	parms->persistent_fid = pfid->persistent_fid;
  	parms->volatile_fid = pfid->volatile_fid;
009d34439   Pavel Shilovsky   CIFS: Add writepa...
759
760
  	return SMB2_write(xid, parms, written, iov, nr_segs);
  }
d43cc7934   Steve French   Cleanup sparse fi...
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
  /* Set or clear the SPARSE_FILE attribute based on value passed in setsparse */
  static bool smb2_set_sparse(const unsigned int xid, struct cifs_tcon *tcon,
  		struct cifsFileInfo *cfile, struct inode *inode, __u8 setsparse)
  {
  	struct cifsInodeInfo *cifsi;
  	int rc;
  
  	cifsi = CIFS_I(inode);
  
  	/* if file already sparse don't bother setting sparse again */
  	if ((cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE) && setsparse)
  		return true; /* already sparse */
  
  	if (!(cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE) && !setsparse)
  		return true; /* already not sparse */
  
  	/*
  	 * Can't check for sparse support on share the usual way via the
  	 * FS attribute info (FILE_SUPPORTS_SPARSE_FILES) on the share
  	 * since Samba server doesn't set the flag on the share, yet
  	 * supports the set sparse FSCTL and returns sparse correctly
  	 * in the file attributes. If we fail setting sparse though we
  	 * mark that server does not support sparse files for this share
  	 * to avoid repeatedly sending the unsupported fsctl to server
  	 * if the file is repeatedly extended.
  	 */
  	if (tcon->broken_sparse_sup)
  		return false;
  
  	rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
  			cfile->fid.volatile_fid, FSCTL_SET_SPARSE,
  			true /* is_fctl */, &setsparse, 1, NULL, NULL);
  	if (rc) {
  		tcon->broken_sparse_sup = true;
  		cifs_dbg(FYI, "set sparse rc = %d
  ", rc);
  		return false;
  	}
  
  	if (setsparse)
  		cifsi->cifsAttrs |= FILE_ATTRIBUTE_SPARSE_FILE;
  	else
  		cifsi->cifsAttrs &= (~FILE_ATTRIBUTE_SPARSE_FILE);
  
  	return true;
  }
c839ff244   Pavel Shilovsky   CIFS: Add SMB2 su...
807
808
809
810
811
  static int
  smb2_set_file_size(const unsigned int xid, struct cifs_tcon *tcon,
  		   struct cifsFileInfo *cfile, __u64 size, bool set_alloc)
  {
  	__le64 eof = cpu_to_le64(size);
3d1a3745d   Steve French   Add sparse file s...
812
813
814
815
816
817
  	struct inode *inode;
  
  	/*
  	 * If extending file more than one page make sparse. Many Linux fs
  	 * make files sparse by default when extending via ftruncate
  	 */
2b0143b5c   David Howells   VFS: normal files...
818
  	inode = d_inode(cfile->dentry);
3d1a3745d   Steve French   Add sparse file s...
819
820
  
  	if (!set_alloc && (size > inode->i_size + 8192)) {
3d1a3745d   Steve French   Add sparse file s...
821
  		__u8 set_sparse = 1;
d43cc7934   Steve French   Cleanup sparse fi...
822
823
824
  
  		/* whether set sparse succeeds or not, extend the file */
  		smb2_set_sparse(xid, tcon, cfile, inode, set_sparse);
3d1a3745d   Steve French   Add sparse file s...
825
  	}
c839ff244   Pavel Shilovsky   CIFS: Add SMB2 su...
826
  	return SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
f29ebb47d   Steve French   Add worker functi...
827
  			    cfile->fid.volatile_fid, cfile->pid, &eof, false);
c839ff244   Pavel Shilovsky   CIFS: Add SMB2 su...
828
  }
02b166654   Steve French   Add reflink copy ...
829
830
831
832
833
834
835
836
  static int
  smb2_duplicate_extents(const unsigned int xid,
  			struct cifsFileInfo *srcfile,
  			struct cifsFileInfo *trgtfile, u64 src_off,
  			u64 len, u64 dest_off)
  {
  	int rc;
  	unsigned int ret_data_len;
02b166654   Steve French   Add reflink copy ...
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
  	struct duplicate_extents_to_file dup_ext_buf;
  	struct cifs_tcon *tcon = tlink_tcon(trgtfile->tlink);
  
  	/* server fileays advertise duplicate extent support with this flag */
  	if ((le32_to_cpu(tcon->fsAttrInfo.Attributes) &
  	     FILE_SUPPORTS_BLOCK_REFCOUNTING) == 0)
  		return -EOPNOTSUPP;
  
  	dup_ext_buf.VolatileFileHandle = srcfile->fid.volatile_fid;
  	dup_ext_buf.PersistentFileHandle = srcfile->fid.persistent_fid;
  	dup_ext_buf.SourceFileOffset = cpu_to_le64(src_off);
  	dup_ext_buf.TargetFileOffset = cpu_to_le64(dest_off);
  	dup_ext_buf.ByteCount = cpu_to_le64(len);
  	cifs_dbg(FYI, "duplicate extents: src off %lld dst off %lld len %lld",
  		src_off, dest_off, len);
  
  	rc = smb2_set_file_size(xid, tcon, trgtfile, dest_off + len, false);
  	if (rc)
  		goto duplicate_extents_out;
  
  	rc = SMB2_ioctl(xid, tcon, trgtfile->fid.persistent_fid,
  			trgtfile->fid.volatile_fid,
  			FSCTL_DUPLICATE_EXTENTS_TO_FILE,
  			true /* is_fsctl */, (char *)&dup_ext_buf,
  			sizeof(struct duplicate_extents_to_file),
24df1483c   Steve French   Cleanup missing f...
862
  			NULL,
02b166654   Steve French   Add reflink copy ...
863
864
865
866
867
868
869
870
  			&ret_data_len);
  
  	if (ret_data_len > 0)
  		cifs_dbg(FYI, "non-zero response length in duplicate extents");
  
  duplicate_extents_out:
  	return rc;
  }
02b166654   Steve French   Add reflink copy ...
871

d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
872
  static int
64a5cfa6d   Steve French   Allow setting per...
873
874
875
876
877
878
879
880
  smb2_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
  		   struct cifsFileInfo *cfile)
  {
  	return SMB2_set_compression(xid, tcon, cfile->fid.persistent_fid,
  			    cfile->fid.volatile_fid);
  }
  
  static int
b3152e2c7   Steve French   Add ioctl to set ...
881
882
883
884
  smb3_set_integrity(const unsigned int xid, struct cifs_tcon *tcon,
  		   struct cifsFileInfo *cfile)
  {
  	struct fsctl_set_integrity_information_req integr_info;
b3152e2c7   Steve French   Add ioctl to set ...
885
886
887
888
889
890
891
892
893
894
895
  	unsigned int ret_data_len;
  
  	integr_info.ChecksumAlgorithm = cpu_to_le16(CHECKSUM_TYPE_UNCHANGED);
  	integr_info.Flags = 0;
  	integr_info.Reserved = 0;
  
  	return SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
  			cfile->fid.volatile_fid,
  			FSCTL_SET_INTEGRITY_INFORMATION,
  			true /* is_fsctl */, (char *)&integr_info,
  			sizeof(struct fsctl_set_integrity_information_req),
24df1483c   Steve French   Cleanup missing f...
896
  			NULL,
b3152e2c7   Steve French   Add ioctl to set ...
897
898
899
900
901
  			&ret_data_len);
  
  }
  
  static int
834170c85   Steve French   Enable previous v...
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
  smb3_enum_snapshots(const unsigned int xid, struct cifs_tcon *tcon,
  		   struct cifsFileInfo *cfile, void __user *ioc_buf)
  {
  	char *retbuf = NULL;
  	unsigned int ret_data_len = 0;
  	int rc;
  	struct smb_snapshot_array snapshot_in;
  
  	rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
  			cfile->fid.volatile_fid,
  			FSCTL_SRV_ENUMERATE_SNAPSHOTS,
  			true /* is_fsctl */, NULL, 0 /* no input data */,
  			(char **)&retbuf,
  			&ret_data_len);
  	cifs_dbg(FYI, "enum snaphots ioctl returned %d and ret buflen is %d
  ",
  			rc, ret_data_len);
  	if (rc)
  		return rc;
  
  	if (ret_data_len && (ioc_buf != NULL) && (retbuf != NULL)) {
  		/* Fixup buffer */
  		if (copy_from_user(&snapshot_in, ioc_buf,
  		    sizeof(struct smb_snapshot_array))) {
  			rc = -EFAULT;
  			kfree(retbuf);
  			return rc;
  		}
  		if (snapshot_in.snapshot_array_size < sizeof(struct smb_snapshot_array)) {
  			rc = -ERANGE;
  			return rc;
  		}
  
  		if (ret_data_len > snapshot_in.snapshot_array_size)
  			ret_data_len = snapshot_in.snapshot_array_size;
  
  		if (copy_to_user(ioc_buf, retbuf, ret_data_len))
  			rc = -EFAULT;
  	}
  
  	kfree(retbuf);
  	return rc;
  }
  
  static int
d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
947
948
949
950
951
952
953
  smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
  		     const char *path, struct cifs_sb_info *cifs_sb,
  		     struct cifs_fid *fid, __u16 search_flags,
  		     struct cifs_search_info *srch_inf)
  {
  	__le16 *utf16_path;
  	int rc;
2e44b2887   Pavel Shilovsky   CIFS: Process opl...
954
  	__u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
064f6047a   Pavel Shilovsky   CIFS: Make SMB2_o...
955
  	struct cifs_open_parms oparms;
d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
956
957
958
959
  
  	utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
  	if (!utf16_path)
  		return -ENOMEM;
064f6047a   Pavel Shilovsky   CIFS: Make SMB2_o...
960
961
962
963
964
  	oparms.tcon = tcon;
  	oparms.desired_access = FILE_READ_ATTRIBUTES | FILE_READ_DATA;
  	oparms.disposition = FILE_OPEN;
  	oparms.create_options = 0;
  	oparms.fid = fid;
9cbc0b733   Pavel Shilovsky   CIFS: Reconnect d...
965
  	oparms.reconnect = false;
064f6047a   Pavel Shilovsky   CIFS: Make SMB2_o...
966

b42bf8882   Pavel Shilovsky   CIFS: Implement f...
967
  	rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
968
969
  	kfree(utf16_path);
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
970
971
  		cifs_dbg(VFS, "open dir failed
  ");
d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
972
973
974
975
976
  		return rc;
  	}
  
  	srch_inf->entries_in_buffer = 0;
  	srch_inf->index_of_last_entry = 0;
d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
977

064f6047a   Pavel Shilovsky   CIFS: Make SMB2_o...
978
979
  	rc = SMB2_query_directory(xid, tcon, fid->persistent_fid,
  				  fid->volatile_fid, 0, srch_inf);
d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
980
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
981
982
  		cifs_dbg(VFS, "query directory failed
  ");
064f6047a   Pavel Shilovsky   CIFS: Make SMB2_o...
983
  		SMB2_close(xid, tcon, fid->persistent_fid, fid->volatile_fid);
d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
  	}
  	return rc;
  }
  
  static int
  smb2_query_dir_next(const unsigned int xid, struct cifs_tcon *tcon,
  		    struct cifs_fid *fid, __u16 search_flags,
  		    struct cifs_search_info *srch_inf)
  {
  	return SMB2_query_directory(xid, tcon, fid->persistent_fid,
  				    fid->volatile_fid, 0, srch_inf);
  }
  
  static int
  smb2_close_dir(const unsigned int xid, struct cifs_tcon *tcon,
  	       struct cifs_fid *fid)
  {
  	return SMB2_close(xid, tcon, fid->persistent_fid, fid->volatile_fid);
  }
2e44b2887   Pavel Shilovsky   CIFS: Process opl...
1003
1004
1005
1006
1007
1008
1009
1010
  /*
  * If we negotiate SMB2 protocol and get STATUS_PENDING - update
  * the number of credits and return true. Otherwise - return false.
  */
  static bool
  smb2_is_status_pending(char *buf, struct TCP_Server_Info *server, int length)
  {
  	struct smb2_hdr *hdr = (struct smb2_hdr *)buf;
12e8a2082   Steve French   Trivial endian fixes
1011
  	if (hdr->Status != STATUS_PENDING)
2e44b2887   Pavel Shilovsky   CIFS: Process opl...
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
  		return false;
  
  	if (!length) {
  		spin_lock(&server->req_lock);
  		server->credits += le16_to_cpu(hdr->CreditRequest);
  		spin_unlock(&server->req_lock);
  		wake_up(&server->request_q);
  	}
  
  	return true;
  }
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
1023
1024
1025
1026
  static int
  smb2_oplock_response(struct cifs_tcon *tcon, struct cifs_fid *fid,
  		     struct cifsInodeInfo *cinode)
  {
0822f5142   Pavel Shilovsky   CIFS: Add SMB2.1 ...
1027
1028
1029
  	if (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LEASING)
  		return SMB2_lease_break(0, tcon, cinode->lease_key,
  					smb2_get_lease_state(cinode));
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
1030
1031
  	return SMB2_oplock_break(0, tcon, fid->persistent_fid,
  				 fid->volatile_fid,
18cceb6a7   Pavel Shilovsky   CIFS: Replace cli...
1032
  				 CIFS_CACHE_READ(cinode) ? 1 : 0);
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
1033
  }
6fc05c25c   Pavel Shilovsky   CIFS: Add statfs ...
1034
1035
1036
1037
1038
  static int
  smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon,
  	     struct kstatfs *buf)
  {
  	int rc;
6fc05c25c   Pavel Shilovsky   CIFS: Add statfs ...
1039
1040
  	__le16 srch_path = 0; /* Null - open root of share */
  	u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
064f6047a   Pavel Shilovsky   CIFS: Make SMB2_o...
1041
1042
1043
1044
1045
1046
1047
1048
  	struct cifs_open_parms oparms;
  	struct cifs_fid fid;
  
  	oparms.tcon = tcon;
  	oparms.desired_access = FILE_READ_ATTRIBUTES;
  	oparms.disposition = FILE_OPEN;
  	oparms.create_options = 0;
  	oparms.fid = &fid;
9cbc0b733   Pavel Shilovsky   CIFS: Reconnect d...
1049
  	oparms.reconnect = false;
6fc05c25c   Pavel Shilovsky   CIFS: Add statfs ...
1050

b42bf8882   Pavel Shilovsky   CIFS: Implement f...
1051
  	rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL);
6fc05c25c   Pavel Shilovsky   CIFS: Add statfs ...
1052
1053
1054
  	if (rc)
  		return rc;
  	buf->f_type = SMB2_MAGIC_NUMBER;
064f6047a   Pavel Shilovsky   CIFS: Make SMB2_o...
1055
1056
1057
  	rc = SMB2_QFS_info(xid, tcon, fid.persistent_fid, fid.volatile_fid,
  			   buf);
  	SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
6fc05c25c   Pavel Shilovsky   CIFS: Add statfs ...
1058
1059
  	return rc;
  }
027e8eec3   Pavel Shilovsky   CIFS: Handle SMB2...
1060
1061
1062
1063
1064
1065
  static bool
  smb2_compare_fids(struct cifsFileInfo *ob1, struct cifsFileInfo *ob2)
  {
  	return ob1->fid.persistent_fid == ob2->fid.persistent_fid &&
  	       ob1->fid.volatile_fid == ob2->fid.volatile_fid;
  }
f7ba7fe68   Pavel Shilovsky   CIFS: Add brlock ...
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
  static int
  smb2_mand_lock(const unsigned int xid, struct cifsFileInfo *cfile, __u64 offset,
  	       __u64 length, __u32 type, int lock, int unlock, bool wait)
  {
  	if (unlock && !lock)
  		type = SMB2_LOCKFLAG_UNLOCK;
  	return SMB2_lock(xid, tlink_tcon(cfile->tlink),
  			 cfile->fid.persistent_fid, cfile->fid.volatile_fid,
  			 current->tgid, length, offset, type, wait);
  }
b8c32dbb0   Pavel Shilovsky   CIFS: Request SMB...
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
  static void
  smb2_get_lease_key(struct inode *inode, struct cifs_fid *fid)
  {
  	memcpy(fid->lease_key, CIFS_I(inode)->lease_key, SMB2_LEASE_KEY_SIZE);
  }
  
  static void
  smb2_set_lease_key(struct inode *inode, struct cifs_fid *fid)
  {
  	memcpy(CIFS_I(inode)->lease_key, fid->lease_key, SMB2_LEASE_KEY_SIZE);
  }
  
  static void
  smb2_new_lease_key(struct cifs_fid *fid)
  {
fa70b87cc   Steve French   SMB3: GUIDs shoul...
1091
  	generate_random_uuid(fid->lease_key);
b8c32dbb0   Pavel Shilovsky   CIFS: Request SMB...
1092
  }
7893242e2   Pavel Shilovsky   CIFS: Fix a possi...
1093
1094
  #define SMB2_SYMLINK_STRUCT_SIZE \
  	(sizeof(struct smb2_err_rsp) - 1 + sizeof(struct smb2_symlink_err_rsp))
b42bf8882   Pavel Shilovsky   CIFS: Implement f...
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
  static int
  smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
  		   const char *full_path, char **target_path,
  		   struct cifs_sb_info *cifs_sb)
  {
  	int rc;
  	__le16 *utf16_path;
  	__u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
  	struct cifs_open_parms oparms;
  	struct cifs_fid fid;
  	struct smb2_err_rsp *err_buf = NULL;
  	struct smb2_symlink_err_rsp *symlink;
7893242e2   Pavel Shilovsky   CIFS: Fix a possi...
1107
1108
1109
1110
  	unsigned int sub_len;
  	unsigned int sub_offset;
  	unsigned int print_len;
  	unsigned int print_offset;
b42bf8882   Pavel Shilovsky   CIFS: Implement f...
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
  
  	cifs_dbg(FYI, "%s: path: %s
  ", __func__, full_path);
  
  	utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
  	if (!utf16_path)
  		return -ENOMEM;
  
  	oparms.tcon = tcon;
  	oparms.desired_access = FILE_READ_ATTRIBUTES;
  	oparms.disposition = FILE_OPEN;
  	oparms.create_options = 0;
  	oparms.fid = &fid;
  	oparms.reconnect = false;
  
  	rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, &err_buf);
  
  	if (!rc || !err_buf) {
  		kfree(utf16_path);
  		return -ENOENT;
  	}
7893242e2   Pavel Shilovsky   CIFS: Fix a possi...
1132
1133
1134
1135
1136
1137
  
  	if (le32_to_cpu(err_buf->ByteCount) < sizeof(struct smb2_symlink_err_rsp) ||
  	    get_rfc1002_length(err_buf) + 4 < SMB2_SYMLINK_STRUCT_SIZE) {
  		kfree(utf16_path);
  		return -ENOENT;
  	}
b42bf8882   Pavel Shilovsky   CIFS: Implement f...
1138
1139
1140
1141
1142
  	/* open must fail on symlink - reset rc */
  	rc = 0;
  	symlink = (struct smb2_symlink_err_rsp *)err_buf->ErrorData;
  	sub_len = le16_to_cpu(symlink->SubstituteNameLength);
  	sub_offset = le16_to_cpu(symlink->SubstituteNameOffset);
7893242e2   Pavel Shilovsky   CIFS: Fix a possi...
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
  	print_len = le16_to_cpu(symlink->PrintNameLength);
  	print_offset = le16_to_cpu(symlink->PrintNameOffset);
  
  	if (get_rfc1002_length(err_buf) + 4 <
  			SMB2_SYMLINK_STRUCT_SIZE + sub_offset + sub_len) {
  		kfree(utf16_path);
  		return -ENOENT;
  	}
  
  	if (get_rfc1002_length(err_buf) + 4 <
  			SMB2_SYMLINK_STRUCT_SIZE + print_offset + print_len) {
  		kfree(utf16_path);
  		return -ENOENT;
  	}
b42bf8882   Pavel Shilovsky   CIFS: Implement f...
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
  	*target_path = cifs_strndup_from_utf16(
  				(char *)symlink->PathBuffer + sub_offset,
  				sub_len, true, cifs_sb->local_nls);
  	if (!(*target_path)) {
  		kfree(utf16_path);
  		return -ENOMEM;
  	}
  	convert_delimiter(*target_path, '/');
  	cifs_dbg(FYI, "%s: target path: %s
  ", __func__, *target_path);
  	kfree(utf16_path);
  	return rc;
  }
30175628b   Steve French   [SMB3] Enable fal...
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
  static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon,
  			    loff_t offset, loff_t len, bool keep_size)
  {
  	struct inode *inode;
  	struct cifsInodeInfo *cifsi;
  	struct cifsFileInfo *cfile = file->private_data;
  	struct file_zero_data_information fsctl_buf;
  	long rc;
  	unsigned int xid;
  
  	xid = get_xid();
2b0143b5c   David Howells   VFS: normal files...
1181
  	inode = d_inode(cfile->dentry);
30175628b   Steve French   [SMB3] Enable fal...
1182
1183
1184
1185
1186
1187
  	cifsi = CIFS_I(inode);
  
  	/* if file not oplocked can't be sure whether asking to extend size */
  	if (!CIFS_CACHE_READ(cifsi))
  		if (keep_size == false)
  			return -EOPNOTSUPP;
2bb93d244   Steve French   Trivial whitespac...
1188
  	/*
30175628b   Steve French   [SMB3] Enable fal...
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
  	 * Must check if file sparse since fallocate -z (zero range) assumes
  	 * non-sparse allocation
  	 */
  	if (!(cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE))
  		return -EOPNOTSUPP;
  
  	/*
  	 * need to make sure we are not asked to extend the file since the SMB3
  	 * fsctl does not change the file size. In the future we could change
  	 * this to zero the first part of the range then set the file size
  	 * which for a non sparse file would zero the newly extended range
  	 */
  	if (keep_size == false)
  		if (i_size_read(inode) < offset + len)
  			return -EOPNOTSUPP;
  
  	cifs_dbg(FYI, "offset %lld len %lld", offset, len);
  
  	fsctl_buf.FileOffset = cpu_to_le64(offset);
  	fsctl_buf.BeyondFinalZero = cpu_to_le64(offset + len);
  
  	rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
  			cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA,
  			true /* is_fctl */, (char *)&fsctl_buf,
  			sizeof(struct file_zero_data_information), NULL, NULL);
  	free_xid(xid);
  	return rc;
  }
31742c5a3   Steve French   enable fallocate ...
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
  static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon,
  			    loff_t offset, loff_t len)
  {
  	struct inode *inode;
  	struct cifsInodeInfo *cifsi;
  	struct cifsFileInfo *cfile = file->private_data;
  	struct file_zero_data_information fsctl_buf;
  	long rc;
  	unsigned int xid;
  	__u8 set_sparse = 1;
  
  	xid = get_xid();
2b0143b5c   David Howells   VFS: normal files...
1229
  	inode = d_inode(cfile->dentry);
31742c5a3   Steve French   enable fallocate ...
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
  	cifsi = CIFS_I(inode);
  
  	/* Need to make file sparse, if not already, before freeing range. */
  	/* Consider adding equivalent for compressed since it could also work */
  	if (!smb2_set_sparse(xid, tcon, cfile, inode, set_sparse))
  		return -EOPNOTSUPP;
  
  	cifs_dbg(FYI, "offset %lld len %lld", offset, len);
  
  	fsctl_buf.FileOffset = cpu_to_le64(offset);
  	fsctl_buf.BeyondFinalZero = cpu_to_le64(offset + len);
  
  	rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
  			cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA,
  			true /* is_fctl */, (char *)&fsctl_buf,
  			sizeof(struct file_zero_data_information), NULL, NULL);
  	free_xid(xid);
  	return rc;
  }
9ccf32162   Steve French   Add support for o...
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
  static long smb3_simple_falloc(struct file *file, struct cifs_tcon *tcon,
  			    loff_t off, loff_t len, bool keep_size)
  {
  	struct inode *inode;
  	struct cifsInodeInfo *cifsi;
  	struct cifsFileInfo *cfile = file->private_data;
  	long rc = -EOPNOTSUPP;
  	unsigned int xid;
  
  	xid = get_xid();
2b0143b5c   David Howells   VFS: normal files...
1259
  	inode = d_inode(cfile->dentry);
9ccf32162   Steve French   Add support for o...
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
  	cifsi = CIFS_I(inode);
  
  	/* if file not oplocked can't be sure whether asking to extend size */
  	if (!CIFS_CACHE_READ(cifsi))
  		if (keep_size == false)
  			return -EOPNOTSUPP;
  
  	/*
  	 * Files are non-sparse by default so falloc may be a no-op
  	 * Must check if file sparse. If not sparse, and not extending
  	 * then no need to do anything since file already allocated
  	 */
  	if ((cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE) == 0) {
  		if (keep_size == true)
  			return 0;
  		/* check if extending file */
  		else if (i_size_read(inode) >= off + len)
  			/* not extending file and already not sparse */
  			return 0;
  		/* BB: in future add else clause to extend file */
  		else
  			return -EOPNOTSUPP;
  	}
  
  	if ((keep_size == true) || (i_size_read(inode) >= off + len)) {
  		/*
  		 * Check if falloc starts within first few pages of file
  		 * and ends within a few pages of the end of file to
  		 * ensure that most of file is being forced to be
  		 * fallocated now. If so then setting whole file sparse
  		 * ie potentially making a few extra pages at the beginning
  		 * or end of the file non-sparse via set_sparse is harmless.
  		 */
  		if ((off > 8192) || (off + len + 8192 < i_size_read(inode)))
  			return -EOPNOTSUPP;
  
  		rc = smb2_set_sparse(xid, tcon, cfile, inode, false);
  	}
  	/* BB: else ... in future add code to extend file and set sparse */
  
  
  	free_xid(xid);
  	return rc;
  }
31742c5a3   Steve French   enable fallocate ...
1304
1305
1306
1307
1308
1309
  static long smb3_fallocate(struct file *file, struct cifs_tcon *tcon, int mode,
  			   loff_t off, loff_t len)
  {
  	/* KEEP_SIZE already checked for by do_fallocate */
  	if (mode & FALLOC_FL_PUNCH_HOLE)
  		return smb3_punch_hole(file, tcon, off, len);
30175628b   Steve French   [SMB3] Enable fal...
1310
1311
1312
1313
  	else if (mode & FALLOC_FL_ZERO_RANGE) {
  		if (mode & FALLOC_FL_KEEP_SIZE)
  			return smb3_zero_range(file, tcon, off, len, true);
  		return smb3_zero_range(file, tcon, off, len, false);
9ccf32162   Steve French   Add support for o...
1314
1315
1316
1317
  	} else if (mode == FALLOC_FL_KEEP_SIZE)
  		return smb3_simple_falloc(file, tcon, off, len, true);
  	else if (mode == 0)
  		return smb3_simple_falloc(file, tcon, off, len, false);
31742c5a3   Steve French   enable fallocate ...
1318
1319
1320
  
  	return -EOPNOTSUPP;
  }
53ef1016f   Pavel Shilovsky   CIFS: Store lease...
1321
  static void
c11f1df50   Sachin Prabhu   cifs: Wait for wr...
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
  smb2_downgrade_oplock(struct TCP_Server_Info *server,
  			struct cifsInodeInfo *cinode, bool set_level2)
  {
  	if (set_level2)
  		server->ops->set_oplock_level(cinode, SMB2_OPLOCK_LEVEL_II,
  						0, NULL);
  	else
  		server->ops->set_oplock_level(cinode, 0, 0, NULL);
  }
  
  static void
42873b0a2   Pavel Shilovsky   CIFS: Respect epo...
1333
1334
  smb2_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
  		      unsigned int epoch, bool *purge_cache)
53ef1016f   Pavel Shilovsky   CIFS: Store lease...
1335
1336
1337
1338
1339
  {
  	oplock &= 0xFF;
  	if (oplock == SMB2_OPLOCK_LEVEL_NOCHANGE)
  		return;
  	if (oplock == SMB2_OPLOCK_LEVEL_BATCH) {
42873b0a2   Pavel Shilovsky   CIFS: Respect epo...
1340
  		cinode->oplock = CIFS_CACHE_RHW_FLG;
53ef1016f   Pavel Shilovsky   CIFS: Store lease...
1341
1342
1343
1344
  		cifs_dbg(FYI, "Batch Oplock granted on inode %p
  ",
  			 &cinode->vfs_inode);
  	} else if (oplock == SMB2_OPLOCK_LEVEL_EXCLUSIVE) {
42873b0a2   Pavel Shilovsky   CIFS: Respect epo...
1345
  		cinode->oplock = CIFS_CACHE_RW_FLG;
53ef1016f   Pavel Shilovsky   CIFS: Store lease...
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
  		cifs_dbg(FYI, "Exclusive Oplock granted on inode %p
  ",
  			 &cinode->vfs_inode);
  	} else if (oplock == SMB2_OPLOCK_LEVEL_II) {
  		cinode->oplock = CIFS_CACHE_READ_FLG;
  		cifs_dbg(FYI, "Level II Oplock granted on inode %p
  ",
  			 &cinode->vfs_inode);
  	} else
  		cinode->oplock = 0;
  }
  
  static void
42873b0a2   Pavel Shilovsky   CIFS: Respect epo...
1359
1360
  smb21_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
  		       unsigned int epoch, bool *purge_cache)
53ef1016f   Pavel Shilovsky   CIFS: Store lease...
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
  {
  	char message[5] = {0};
  
  	oplock &= 0xFF;
  	if (oplock == SMB2_OPLOCK_LEVEL_NOCHANGE)
  		return;
  
  	cinode->oplock = 0;
  	if (oplock & SMB2_LEASE_READ_CACHING_HE) {
  		cinode->oplock |= CIFS_CACHE_READ_FLG;
  		strcat(message, "R");
  	}
  	if (oplock & SMB2_LEASE_HANDLE_CACHING_HE) {
  		cinode->oplock |= CIFS_CACHE_HANDLE_FLG;
  		strcat(message, "H");
  	}
  	if (oplock & SMB2_LEASE_WRITE_CACHING_HE) {
  		cinode->oplock |= CIFS_CACHE_WRITE_FLG;
  		strcat(message, "W");
  	}
  	if (!cinode->oplock)
  		strcat(message, "None");
  	cifs_dbg(FYI, "%s Lease granted on inode %p
  ", message,
  		 &cinode->vfs_inode);
  }
42873b0a2   Pavel Shilovsky   CIFS: Respect epo...
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
  static void
  smb3_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
  		      unsigned int epoch, bool *purge_cache)
  {
  	unsigned int old_oplock = cinode->oplock;
  
  	smb21_set_oplock_level(cinode, oplock, epoch, purge_cache);
  
  	if (purge_cache) {
  		*purge_cache = false;
  		if (old_oplock == CIFS_CACHE_READ_FLG) {
  			if (cinode->oplock == CIFS_CACHE_READ_FLG &&
  			    (epoch - cinode->epoch > 0))
  				*purge_cache = true;
  			else if (cinode->oplock == CIFS_CACHE_RH_FLG &&
  				 (epoch - cinode->epoch > 1))
  				*purge_cache = true;
  			else if (cinode->oplock == CIFS_CACHE_RHW_FLG &&
  				 (epoch - cinode->epoch > 1))
  				*purge_cache = true;
  			else if (cinode->oplock == 0 &&
  				 (epoch - cinode->epoch > 0))
  				*purge_cache = true;
  		} else if (old_oplock == CIFS_CACHE_RH_FLG) {
  			if (cinode->oplock == CIFS_CACHE_RH_FLG &&
  			    (epoch - cinode->epoch > 0))
  				*purge_cache = true;
  			else if (cinode->oplock == CIFS_CACHE_RHW_FLG &&
  				 (epoch - cinode->epoch > 1))
  				*purge_cache = true;
  		}
  		cinode->epoch = epoch;
  	}
  }
53ef1016f   Pavel Shilovsky   CIFS: Store lease...
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
  static bool
  smb2_is_read_op(__u32 oplock)
  {
  	return oplock == SMB2_OPLOCK_LEVEL_II;
  }
  
  static bool
  smb21_is_read_op(__u32 oplock)
  {
  	return (oplock & SMB2_LEASE_READ_CACHING_HE) &&
  	       !(oplock & SMB2_LEASE_WRITE_CACHING_HE);
  }
f047390a0   Pavel Shilovsky   CIFS: Add create ...
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
  static __le32
  map_oplock_to_lease(u8 oplock)
  {
  	if (oplock == SMB2_OPLOCK_LEVEL_EXCLUSIVE)
  		return SMB2_LEASE_WRITE_CACHING | SMB2_LEASE_READ_CACHING;
  	else if (oplock == SMB2_OPLOCK_LEVEL_II)
  		return SMB2_LEASE_READ_CACHING;
  	else if (oplock == SMB2_OPLOCK_LEVEL_BATCH)
  		return SMB2_LEASE_HANDLE_CACHING | SMB2_LEASE_READ_CACHING |
  		       SMB2_LEASE_WRITE_CACHING;
  	return 0;
  }
a41a28bda   Pavel Shilovsky   CIFS: Move creati...
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
  static char *
  smb2_create_lease_buf(u8 *lease_key, u8 oplock)
  {
  	struct create_lease *buf;
  
  	buf = kzalloc(sizeof(struct create_lease), GFP_KERNEL);
  	if (!buf)
  		return NULL;
  
  	buf->lcontext.LeaseKeyLow = cpu_to_le64(*((u64 *)lease_key));
  	buf->lcontext.LeaseKeyHigh = cpu_to_le64(*((u64 *)(lease_key + 8)));
f047390a0   Pavel Shilovsky   CIFS: Add create ...
1456
  	buf->lcontext.LeaseState = map_oplock_to_lease(oplock);
a41a28bda   Pavel Shilovsky   CIFS: Move creati...
1457
1458
1459
1460
1461
1462
1463
  
  	buf->ccontext.DataOffset = cpu_to_le16(offsetof
  					(struct create_lease, lcontext));
  	buf->ccontext.DataLength = cpu_to_le32(sizeof(struct lease_context));
  	buf->ccontext.NameOffset = cpu_to_le16(offsetof
  				(struct create_lease, Name));
  	buf->ccontext.NameLength = cpu_to_le16(4);
12197a7fd   Steve French   Clarify SMB2/SMB3...
1464
  	/* SMB2_CREATE_REQUEST_LEASE is "RqLs" */
a41a28bda   Pavel Shilovsky   CIFS: Move creati...
1465
1466
1467
1468
1469
1470
  	buf->Name[0] = 'R';
  	buf->Name[1] = 'q';
  	buf->Name[2] = 'L';
  	buf->Name[3] = 's';
  	return (char *)buf;
  }
f047390a0   Pavel Shilovsky   CIFS: Add create ...
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
  static char *
  smb3_create_lease_buf(u8 *lease_key, u8 oplock)
  {
  	struct create_lease_v2 *buf;
  
  	buf = kzalloc(sizeof(struct create_lease_v2), GFP_KERNEL);
  	if (!buf)
  		return NULL;
  
  	buf->lcontext.LeaseKeyLow = cpu_to_le64(*((u64 *)lease_key));
  	buf->lcontext.LeaseKeyHigh = cpu_to_le64(*((u64 *)(lease_key + 8)));
  	buf->lcontext.LeaseState = map_oplock_to_lease(oplock);
  
  	buf->ccontext.DataOffset = cpu_to_le16(offsetof
  					(struct create_lease_v2, lcontext));
  	buf->ccontext.DataLength = cpu_to_le32(sizeof(struct lease_context_v2));
  	buf->ccontext.NameOffset = cpu_to_le16(offsetof
  				(struct create_lease_v2, Name));
  	buf->ccontext.NameLength = cpu_to_le16(4);
12197a7fd   Steve French   Clarify SMB2/SMB3...
1490
  	/* SMB2_CREATE_REQUEST_LEASE is "RqLs" */
f047390a0   Pavel Shilovsky   CIFS: Add create ...
1491
1492
1493
1494
1495
1496
  	buf->Name[0] = 'R';
  	buf->Name[1] = 'q';
  	buf->Name[2] = 'L';
  	buf->Name[3] = 's';
  	return (char *)buf;
  }
b5c7cde3f   Pavel Shilovsky   CIFS: Move parsin...
1497
  static __u8
42873b0a2   Pavel Shilovsky   CIFS: Respect epo...
1498
  smb2_parse_lease_buf(void *buf, unsigned int *epoch)
b5c7cde3f   Pavel Shilovsky   CIFS: Move parsin...
1499
1500
  {
  	struct create_lease *lc = (struct create_lease *)buf;
42873b0a2   Pavel Shilovsky   CIFS: Respect epo...
1501
  	*epoch = 0; /* not used */
b5c7cde3f   Pavel Shilovsky   CIFS: Move parsin...
1502
1503
1504
1505
  	if (lc->lcontext.LeaseFlags & SMB2_LEASE_FLAG_BREAK_IN_PROGRESS)
  		return SMB2_OPLOCK_LEVEL_NOCHANGE;
  	return le32_to_cpu(lc->lcontext.LeaseState);
  }
f047390a0   Pavel Shilovsky   CIFS: Add create ...
1506
  static __u8
42873b0a2   Pavel Shilovsky   CIFS: Respect epo...
1507
  smb3_parse_lease_buf(void *buf, unsigned int *epoch)
f047390a0   Pavel Shilovsky   CIFS: Add create ...
1508
1509
  {
  	struct create_lease_v2 *lc = (struct create_lease_v2 *)buf;
42873b0a2   Pavel Shilovsky   CIFS: Respect epo...
1510
  	*epoch = le16_to_cpu(lc->lcontext.Epoch);
f047390a0   Pavel Shilovsky   CIFS: Add create ...
1511
1512
1513
1514
  	if (lc->lcontext.LeaseFlags & SMB2_LEASE_FLAG_BREAK_IN_PROGRESS)
  		return SMB2_OPLOCK_LEVEL_NOCHANGE;
  	return le32_to_cpu(lc->lcontext.LeaseState);
  }
7f6c50086   Pavel Shilovsky   CIFS: Fix cifs_wr...
1515
1516
1517
1518
1519
1520
  static unsigned int
  smb2_wp_retry_size(struct inode *inode)
  {
  	return min_t(unsigned int, CIFS_SB(inode->i_sb)->wsize,
  		     SMB2_MAX_BUFFER_SIZE);
  }
52755808d   Pavel Shilovsky   CIFS: Fix SMB2 re...
1521
1522
1523
1524
1525
  static bool
  smb2_dir_needs_close(struct cifsFileInfo *cfile)
  {
  	return !cfile->invalidHandle;
  }
53ef1016f   Pavel Shilovsky   CIFS: Store lease...
1526
  struct smb_version_operations smb20_operations = {
027e8eec3   Pavel Shilovsky   CIFS: Handle SMB2...
1527
  	.compare_fids = smb2_compare_fids,
2dc7e1c03   Pavel Shilovsky   CIFS: Make transp...
1528
  	.setup_request = smb2_setup_request,
c95b8eeda   Pavel Shilovsky   CIFS: Add SMB2 su...
1529
  	.setup_async_request = smb2_setup_async_request,
2dc7e1c03   Pavel Shilovsky   CIFS: Make transp...
1530
  	.check_receive = smb2_check_receive,
28ea5290d   Pavel Shilovsky   CIFS: Add SMB2 cr...
1531
1532
1533
1534
  	.add_credits = smb2_add_credits,
  	.set_credits = smb2_set_credits,
  	.get_credits_field = smb2_get_credits_field,
  	.get_credits = smb2_get_credits,
cb7e9eabb   Pavel Shilovsky   CIFS: Use multicr...
1535
  	.wait_mtu_credits = cifs_wait_mtu_credits,
2dc7e1c03   Pavel Shilovsky   CIFS: Make transp...
1536
  	.get_next_mid = smb2_get_next_mid,
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
1537
1538
1539
  	.read_data_offset = smb2_read_data_offset,
  	.read_data_length = smb2_read_data_length,
  	.map_error = map_smb2_to_linux_error,
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
1540
1541
1542
  	.find_mid = smb2_find_mid,
  	.check_message = smb2_check_message,
  	.dump_detail = smb2_dump_detail,
d60622eb5   Pavel Shilovsky   CIFS: Allow SMB2 ...
1543
1544
  	.clear_stats = smb2_clear_stats,
  	.print_stats = smb2_print_stats,
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
1545
  	.is_oplock_break = smb2_is_valid_oplock_break,
c11f1df50   Sachin Prabhu   cifs: Wait for wr...
1546
  	.downgrade_oplock = smb2_downgrade_oplock,
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
1547
1548
  	.need_neg = smb2_need_neg,
  	.negotiate = smb2_negotiate,
3a3bab509   Pavel Shilovsky   CIFS: Add SMB2 r/...
1549
1550
  	.negotiate_wsize = smb2_negotiate_wsize,
  	.negotiate_rsize = smb2_negotiate_rsize,
5478f9ba9   Pavel Shilovsky   CIFS: Add session...
1551
1552
  	.sess_setup = SMB2_sess_setup,
  	.logoff = SMB2_logoff,
faaf946a7   Pavel Shilovsky   CIFS: Add tree co...
1553
1554
  	.tree_connect = SMB2_tcon,
  	.tree_disconnect = SMB2_tdis,
34f626406   Steve French   Query file system...
1555
  	.qfs_tcon = smb2_qfs_tcon,
2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
1556
  	.is_path_accessible = smb2_is_path_accessible,
9094fad1e   Pavel Shilovsky   CIFS: Add echo re...
1557
1558
  	.can_echo = smb2_can_echo,
  	.echo = SMB2_echo,
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
1559
1560
  	.query_path_info = smb2_query_path_info,
  	.get_srv_inum = smb2_get_srv_inum,
b7546bc54   Pavel Shilovsky   CIFS: Add SMB2 su...
1561
  	.query_file_info = smb2_query_file_info,
c839ff244   Pavel Shilovsky   CIFS: Add SMB2 su...
1562
1563
  	.set_path_size = smb2_set_path_size,
  	.set_file_size = smb2_set_file_size,
1feeaac75   Pavel Shilovsky   CIFS: Add set_fil...
1564
  	.set_file_info = smb2_set_file_info,
64a5cfa6d   Steve French   Allow setting per...
1565
  	.set_compression = smb2_set_compression,
a0e731839   Pavel Shilovsky   CIFS: Add SMB2 su...
1566
1567
  	.mkdir = smb2_mkdir,
  	.mkdir_setinfo = smb2_mkdir_setinfo,
1a500f010   Pavel Shilovsky   CIFS: Add SMB2 su...
1568
  	.rmdir = smb2_rmdir,
cbe6f439f   Pavel Shilovsky   CIFS: Add SMB2 su...
1569
  	.unlink = smb2_unlink,
35143eb5c   Pavel Shilovsky   CIFS: Add SMB2 su...
1570
  	.rename = smb2_rename_path,
568798cc6   Pavel Shilovsky   CIFS: Add SMB2 su...
1571
  	.create_hardlink = smb2_create_hardlink,
b42bf8882   Pavel Shilovsky   CIFS: Implement f...
1572
  	.query_symlink = smb2_query_symlink,
5b23c97d7   Sachin Prabhu   Add MF-Symlinks s...
1573
1574
  	.query_mf_symlink = smb3_query_mf_symlink,
  	.create_mf_symlink = smb3_create_mf_symlink,
f0df737ee   Pavel Shilovsky   CIFS: Add open/cl...
1575
1576
1577
  	.open = smb2_open_file,
  	.set_fid = smb2_set_fid,
  	.close = smb2_close_file,
7a5cfb196   Pavel Shilovsky   CIFS: Add SMB2 su...
1578
  	.flush = smb2_flush_file,
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
1579
  	.async_readv = smb2_async_readv,
333191412   Pavel Shilovsky   CIFS: Add SMB2 su...
1580
  	.async_writev = smb2_async_writev,
d8e050398   Pavel Shilovsky   CIFS: Add readpag...
1581
  	.sync_read = smb2_sync_read,
009d34439   Pavel Shilovsky   CIFS: Add writepa...
1582
  	.sync_write = smb2_sync_write,
d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
1583
1584
1585
1586
  	.query_dir_first = smb2_query_dir_first,
  	.query_dir_next = smb2_query_dir_next,
  	.close_dir = smb2_close_dir,
  	.calc_smb_size = smb2_calc_size,
2e44b2887   Pavel Shilovsky   CIFS: Process opl...
1587
  	.is_status_pending = smb2_is_status_pending,
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
1588
  	.oplock_response = smb2_oplock_response,
6fc05c25c   Pavel Shilovsky   CIFS: Add statfs ...
1589
  	.queryfs = smb2_queryfs,
f7ba7fe68   Pavel Shilovsky   CIFS: Add brlock ...
1590
1591
  	.mand_lock = smb2_mand_lock,
  	.mand_unlock_range = smb2_unlock_range,
b140799a1   Pavel Shilovsky   CIFS: Use brlock ...
1592
  	.push_mand_locks = smb2_push_mandatory_locks,
b8c32dbb0   Pavel Shilovsky   CIFS: Request SMB...
1593
1594
1595
  	.get_lease_key = smb2_get_lease_key,
  	.set_lease_key = smb2_set_lease_key,
  	.new_lease_key = smb2_new_lease_key,
38107d45c   Steve French   Do not send SMB2 ...
1596
  	.calc_signature = smb2_calc_signature,
53ef1016f   Pavel Shilovsky   CIFS: Store lease...
1597
1598
  	.is_read_op = smb2_is_read_op,
  	.set_oplock_level = smb2_set_oplock_level,
a41a28bda   Pavel Shilovsky   CIFS: Move creati...
1599
  	.create_lease_buf = smb2_create_lease_buf,
b5c7cde3f   Pavel Shilovsky   CIFS: Move parsin...
1600
  	.parse_lease_buf = smb2_parse_lease_buf,
41c1358e9   Steve French   CIFS: SMB2/SMB3 C...
1601
  	.clone_range = smb2_clone_range,
7f6c50086   Pavel Shilovsky   CIFS: Fix cifs_wr...
1602
  	.wp_retry_size = smb2_wp_retry_size,
52755808d   Pavel Shilovsky   CIFS: Fix SMB2 re...
1603
  	.dir_needs_close = smb2_dir_needs_close,
38107d45c   Steve French   Do not send SMB2 ...
1604
  };
53ef1016f   Pavel Shilovsky   CIFS: Store lease...
1605
1606
1607
1608
1609
1610
1611
1612
1613
  struct smb_version_operations smb21_operations = {
  	.compare_fids = smb2_compare_fids,
  	.setup_request = smb2_setup_request,
  	.setup_async_request = smb2_setup_async_request,
  	.check_receive = smb2_check_receive,
  	.add_credits = smb2_add_credits,
  	.set_credits = smb2_set_credits,
  	.get_credits_field = smb2_get_credits_field,
  	.get_credits = smb2_get_credits,
cb7e9eabb   Pavel Shilovsky   CIFS: Use multicr...
1614
  	.wait_mtu_credits = smb2_wait_mtu_credits,
53ef1016f   Pavel Shilovsky   CIFS: Store lease...
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
  	.get_next_mid = smb2_get_next_mid,
  	.read_data_offset = smb2_read_data_offset,
  	.read_data_length = smb2_read_data_length,
  	.map_error = map_smb2_to_linux_error,
  	.find_mid = smb2_find_mid,
  	.check_message = smb2_check_message,
  	.dump_detail = smb2_dump_detail,
  	.clear_stats = smb2_clear_stats,
  	.print_stats = smb2_print_stats,
  	.is_oplock_break = smb2_is_valid_oplock_break,
c11f1df50   Sachin Prabhu   cifs: Wait for wr...
1625
  	.downgrade_oplock = smb2_downgrade_oplock,
53ef1016f   Pavel Shilovsky   CIFS: Store lease...
1626
1627
1628
1629
1630
1631
1632
1633
  	.need_neg = smb2_need_neg,
  	.negotiate = smb2_negotiate,
  	.negotiate_wsize = smb2_negotiate_wsize,
  	.negotiate_rsize = smb2_negotiate_rsize,
  	.sess_setup = SMB2_sess_setup,
  	.logoff = SMB2_logoff,
  	.tree_connect = SMB2_tcon,
  	.tree_disconnect = SMB2_tdis,
34f626406   Steve French   Query file system...
1634
  	.qfs_tcon = smb2_qfs_tcon,
53ef1016f   Pavel Shilovsky   CIFS: Store lease...
1635
1636
1637
1638
1639
1640
1641
1642
1643
  	.is_path_accessible = smb2_is_path_accessible,
  	.can_echo = smb2_can_echo,
  	.echo = SMB2_echo,
  	.query_path_info = smb2_query_path_info,
  	.get_srv_inum = smb2_get_srv_inum,
  	.query_file_info = smb2_query_file_info,
  	.set_path_size = smb2_set_path_size,
  	.set_file_size = smb2_set_file_size,
  	.set_file_info = smb2_set_file_info,
64a5cfa6d   Steve French   Allow setting per...
1644
  	.set_compression = smb2_set_compression,
53ef1016f   Pavel Shilovsky   CIFS: Store lease...
1645
1646
1647
1648
1649
1650
1651
  	.mkdir = smb2_mkdir,
  	.mkdir_setinfo = smb2_mkdir_setinfo,
  	.rmdir = smb2_rmdir,
  	.unlink = smb2_unlink,
  	.rename = smb2_rename_path,
  	.create_hardlink = smb2_create_hardlink,
  	.query_symlink = smb2_query_symlink,
c22870ea2   Steve French   mfsymlinks suppor...
1652
  	.query_mf_symlink = smb3_query_mf_symlink,
5ab97578c   Steve French   Add mfsymlinks su...
1653
  	.create_mf_symlink = smb3_create_mf_symlink,
53ef1016f   Pavel Shilovsky   CIFS: Store lease...
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
  	.open = smb2_open_file,
  	.set_fid = smb2_set_fid,
  	.close = smb2_close_file,
  	.flush = smb2_flush_file,
  	.async_readv = smb2_async_readv,
  	.async_writev = smb2_async_writev,
  	.sync_read = smb2_sync_read,
  	.sync_write = smb2_sync_write,
  	.query_dir_first = smb2_query_dir_first,
  	.query_dir_next = smb2_query_dir_next,
  	.close_dir = smb2_close_dir,
  	.calc_smb_size = smb2_calc_size,
  	.is_status_pending = smb2_is_status_pending,
  	.oplock_response = smb2_oplock_response,
  	.queryfs = smb2_queryfs,
  	.mand_lock = smb2_mand_lock,
  	.mand_unlock_range = smb2_unlock_range,
  	.push_mand_locks = smb2_push_mandatory_locks,
  	.get_lease_key = smb2_get_lease_key,
  	.set_lease_key = smb2_set_lease_key,
  	.new_lease_key = smb2_new_lease_key,
  	.calc_signature = smb2_calc_signature,
  	.is_read_op = smb21_is_read_op,
  	.set_oplock_level = smb21_set_oplock_level,
a41a28bda   Pavel Shilovsky   CIFS: Move creati...
1678
  	.create_lease_buf = smb2_create_lease_buf,
b5c7cde3f   Pavel Shilovsky   CIFS: Move parsin...
1679
  	.parse_lease_buf = smb2_parse_lease_buf,
41c1358e9   Steve French   CIFS: SMB2/SMB3 C...
1680
  	.clone_range = smb2_clone_range,
7f6c50086   Pavel Shilovsky   CIFS: Fix cifs_wr...
1681
  	.wp_retry_size = smb2_wp_retry_size,
52755808d   Pavel Shilovsky   CIFS: Fix SMB2 re...
1682
  	.dir_needs_close = smb2_dir_needs_close,
834170c85   Steve French   Enable previous v...
1683
  	.enum_snapshots = smb3_enum_snapshots,
53ef1016f   Pavel Shilovsky   CIFS: Store lease...
1684
  };
38107d45c   Steve French   Do not send SMB2 ...
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
  
  struct smb_version_operations smb30_operations = {
  	.compare_fids = smb2_compare_fids,
  	.setup_request = smb2_setup_request,
  	.setup_async_request = smb2_setup_async_request,
  	.check_receive = smb2_check_receive,
  	.add_credits = smb2_add_credits,
  	.set_credits = smb2_set_credits,
  	.get_credits_field = smb2_get_credits_field,
  	.get_credits = smb2_get_credits,
cb7e9eabb   Pavel Shilovsky   CIFS: Use multicr...
1695
  	.wait_mtu_credits = smb2_wait_mtu_credits,
38107d45c   Steve French   Do not send SMB2 ...
1696
1697
1698
1699
1700
1701
1702
1703
1704
  	.get_next_mid = smb2_get_next_mid,
  	.read_data_offset = smb2_read_data_offset,
  	.read_data_length = smb2_read_data_length,
  	.map_error = map_smb2_to_linux_error,
  	.find_mid = smb2_find_mid,
  	.check_message = smb2_check_message,
  	.dump_detail = smb2_dump_detail,
  	.clear_stats = smb2_clear_stats,
  	.print_stats = smb2_print_stats,
769ee6a40   Steve French   Add ability to di...
1705
  	.dump_share_caps = smb2_dump_share_caps,
38107d45c   Steve French   Do not send SMB2 ...
1706
  	.is_oplock_break = smb2_is_valid_oplock_break,
c11f1df50   Sachin Prabhu   cifs: Wait for wr...
1707
  	.downgrade_oplock = smb2_downgrade_oplock,
38107d45c   Steve French   Do not send SMB2 ...
1708
1709
1710
1711
1712
1713
1714
1715
  	.need_neg = smb2_need_neg,
  	.negotiate = smb2_negotiate,
  	.negotiate_wsize = smb2_negotiate_wsize,
  	.negotiate_rsize = smb2_negotiate_rsize,
  	.sess_setup = SMB2_sess_setup,
  	.logoff = SMB2_logoff,
  	.tree_connect = SMB2_tcon,
  	.tree_disconnect = SMB2_tdis,
af6a12ea8   Steven French   Query File System...
1716
  	.qfs_tcon = smb3_qfs_tcon,
38107d45c   Steve French   Do not send SMB2 ...
1717
1718
1719
1720
1721
1722
1723
1724
1725
  	.is_path_accessible = smb2_is_path_accessible,
  	.can_echo = smb2_can_echo,
  	.echo = SMB2_echo,
  	.query_path_info = smb2_query_path_info,
  	.get_srv_inum = smb2_get_srv_inum,
  	.query_file_info = smb2_query_file_info,
  	.set_path_size = smb2_set_path_size,
  	.set_file_size = smb2_set_file_size,
  	.set_file_info = smb2_set_file_info,
64a5cfa6d   Steve French   Allow setting per...
1726
  	.set_compression = smb2_set_compression,
38107d45c   Steve French   Do not send SMB2 ...
1727
1728
1729
1730
1731
1732
  	.mkdir = smb2_mkdir,
  	.mkdir_setinfo = smb2_mkdir_setinfo,
  	.rmdir = smb2_rmdir,
  	.unlink = smb2_unlink,
  	.rename = smb2_rename_path,
  	.create_hardlink = smb2_create_hardlink,
b42bf8882   Pavel Shilovsky   CIFS: Implement f...
1733
  	.query_symlink = smb2_query_symlink,
c22870ea2   Steve French   mfsymlinks suppor...
1734
  	.query_mf_symlink = smb3_query_mf_symlink,
5ab97578c   Steve French   Add mfsymlinks su...
1735
  	.create_mf_symlink = smb3_create_mf_symlink,
38107d45c   Steve French   Do not send SMB2 ...
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
  	.open = smb2_open_file,
  	.set_fid = smb2_set_fid,
  	.close = smb2_close_file,
  	.flush = smb2_flush_file,
  	.async_readv = smb2_async_readv,
  	.async_writev = smb2_async_writev,
  	.sync_read = smb2_sync_read,
  	.sync_write = smb2_sync_write,
  	.query_dir_first = smb2_query_dir_first,
  	.query_dir_next = smb2_query_dir_next,
  	.close_dir = smb2_close_dir,
  	.calc_smb_size = smb2_calc_size,
  	.is_status_pending = smb2_is_status_pending,
  	.oplock_response = smb2_oplock_response,
  	.queryfs = smb2_queryfs,
  	.mand_lock = smb2_mand_lock,
  	.mand_unlock_range = smb2_unlock_range,
  	.push_mand_locks = smb2_push_mandatory_locks,
  	.get_lease_key = smb2_get_lease_key,
  	.set_lease_key = smb2_set_lease_key,
  	.new_lease_key = smb2_new_lease_key,
373512ec5   Steve French   Prepare for encry...
1757
  	.generate_signingkey = generate_smb30signingkey,
38107d45c   Steve French   Do not send SMB2 ...
1758
  	.calc_signature = smb3_calc_signature,
b3152e2c7   Steve French   Add ioctl to set ...
1759
  	.set_integrity  = smb3_set_integrity,
53ef1016f   Pavel Shilovsky   CIFS: Store lease...
1760
  	.is_read_op = smb21_is_read_op,
42873b0a2   Pavel Shilovsky   CIFS: Respect epo...
1761
  	.set_oplock_level = smb3_set_oplock_level,
f047390a0   Pavel Shilovsky   CIFS: Add create ...
1762
1763
  	.create_lease_buf = smb3_create_lease_buf,
  	.parse_lease_buf = smb3_parse_lease_buf,
41c1358e9   Steve French   CIFS: SMB2/SMB3 C...
1764
  	.clone_range = smb2_clone_range,
ca9e7a1c8   Steve French   Allow duplicate e...
1765
  	.duplicate_extents = smb2_duplicate_extents,
ff1c038ad   Steve French   Check SMB3 dialec...
1766
  	.validate_negotiate = smb3_validate_negotiate,
7f6c50086   Pavel Shilovsky   CIFS: Fix cifs_wr...
1767
  	.wp_retry_size = smb2_wp_retry_size,
52755808d   Pavel Shilovsky   CIFS: Fix SMB2 re...
1768
  	.dir_needs_close = smb2_dir_needs_close,
31742c5a3   Steve French   enable fallocate ...
1769
  	.fallocate = smb3_fallocate,
834170c85   Steve French   Enable previous v...
1770
  	.enum_snapshots = smb3_enum_snapshots,
1080ef758   Steve French   CIFS: Introduce S...
1771
  };
aab1893d5   Steve French   Add SMB3.11 mount...
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
  #ifdef CONFIG_CIFS_SMB311
  struct smb_version_operations smb311_operations = {
  	.compare_fids = smb2_compare_fids,
  	.setup_request = smb2_setup_request,
  	.setup_async_request = smb2_setup_async_request,
  	.check_receive = smb2_check_receive,
  	.add_credits = smb2_add_credits,
  	.set_credits = smb2_set_credits,
  	.get_credits_field = smb2_get_credits_field,
  	.get_credits = smb2_get_credits,
  	.wait_mtu_credits = smb2_wait_mtu_credits,
  	.get_next_mid = smb2_get_next_mid,
  	.read_data_offset = smb2_read_data_offset,
  	.read_data_length = smb2_read_data_length,
  	.map_error = map_smb2_to_linux_error,
  	.find_mid = smb2_find_mid,
  	.check_message = smb2_check_message,
  	.dump_detail = smb2_dump_detail,
  	.clear_stats = smb2_clear_stats,
  	.print_stats = smb2_print_stats,
  	.dump_share_caps = smb2_dump_share_caps,
  	.is_oplock_break = smb2_is_valid_oplock_break,
  	.downgrade_oplock = smb2_downgrade_oplock,
  	.need_neg = smb2_need_neg,
  	.negotiate = smb2_negotiate,
  	.negotiate_wsize = smb2_negotiate_wsize,
  	.negotiate_rsize = smb2_negotiate_rsize,
  	.sess_setup = SMB2_sess_setup,
  	.logoff = SMB2_logoff,
  	.tree_connect = SMB2_tcon,
  	.tree_disconnect = SMB2_tdis,
  	.qfs_tcon = smb3_qfs_tcon,
  	.is_path_accessible = smb2_is_path_accessible,
  	.can_echo = smb2_can_echo,
  	.echo = SMB2_echo,
  	.query_path_info = smb2_query_path_info,
  	.get_srv_inum = smb2_get_srv_inum,
  	.query_file_info = smb2_query_file_info,
  	.set_path_size = smb2_set_path_size,
  	.set_file_size = smb2_set_file_size,
  	.set_file_info = smb2_set_file_info,
  	.set_compression = smb2_set_compression,
  	.mkdir = smb2_mkdir,
  	.mkdir_setinfo = smb2_mkdir_setinfo,
  	.rmdir = smb2_rmdir,
  	.unlink = smb2_unlink,
  	.rename = smb2_rename_path,
  	.create_hardlink = smb2_create_hardlink,
  	.query_symlink = smb2_query_symlink,
  	.query_mf_symlink = smb3_query_mf_symlink,
  	.create_mf_symlink = smb3_create_mf_symlink,
  	.open = smb2_open_file,
  	.set_fid = smb2_set_fid,
  	.close = smb2_close_file,
  	.flush = smb2_flush_file,
  	.async_readv = smb2_async_readv,
  	.async_writev = smb2_async_writev,
  	.sync_read = smb2_sync_read,
  	.sync_write = smb2_sync_write,
  	.query_dir_first = smb2_query_dir_first,
  	.query_dir_next = smb2_query_dir_next,
  	.close_dir = smb2_close_dir,
  	.calc_smb_size = smb2_calc_size,
  	.is_status_pending = smb2_is_status_pending,
  	.oplock_response = smb2_oplock_response,
  	.queryfs = smb2_queryfs,
  	.mand_lock = smb2_mand_lock,
  	.mand_unlock_range = smb2_unlock_range,
  	.push_mand_locks = smb2_push_mandatory_locks,
  	.get_lease_key = smb2_get_lease_key,
  	.set_lease_key = smb2_set_lease_key,
  	.new_lease_key = smb2_new_lease_key,
373512ec5   Steve French   Prepare for encry...
1844
  	.generate_signingkey = generate_smb311signingkey,
aab1893d5   Steve French   Add SMB3.11 mount...
1845
  	.calc_signature = smb3_calc_signature,
b3152e2c7   Steve French   Add ioctl to set ...
1846
  	.set_integrity  = smb3_set_integrity,
aab1893d5   Steve French   Add SMB3.11 mount...
1847
1848
1849
1850
1851
  	.is_read_op = smb21_is_read_op,
  	.set_oplock_level = smb3_set_oplock_level,
  	.create_lease_buf = smb3_create_lease_buf,
  	.parse_lease_buf = smb3_parse_lease_buf,
  	.clone_range = smb2_clone_range,
02b166654   Steve French   Add reflink copy ...
1852
  	.duplicate_extents = smb2_duplicate_extents,
aab1893d5   Steve French   Add SMB3.11 mount...
1853
1854
1855
1856
  /*	.validate_negotiate = smb3_validate_negotiate, */ /* not used in 3.11 */
  	.wp_retry_size = smb2_wp_retry_size,
  	.dir_needs_close = smb2_dir_needs_close,
  	.fallocate = smb3_fallocate,
834170c85   Steve French   Enable previous v...
1857
  	.enum_snapshots = smb3_enum_snapshots,
aab1893d5   Steve French   Add SMB3.11 mount...
1858
1859
  };
  #endif /* CIFS_SMB311 */
dd446b16e   Steve French   Add SMB2.02 diale...
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
  struct smb_version_values smb20_values = {
  	.version_string = SMB20_VERSION_STRING,
  	.protocol_id = SMB20_PROT_ID,
  	.req_capabilities = 0, /* MBZ */
  	.large_lock_type = 0,
  	.exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
  	.shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
  	.unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
  	.header_size = sizeof(struct smb2_hdr),
  	.max_header_size = MAX_SMB2_HDR_SIZE,
  	.read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
  	.lock_cmd = SMB2_LOCK,
  	.cap_unix = 0,
  	.cap_nt_find = SMB2_NT_FIND,
  	.cap_large_files = SMB2_LARGE_FILES,
50285882f   Jeff Layton   cifs: fix SMB2 si...
1875
1876
  	.signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
  	.signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
a41a28bda   Pavel Shilovsky   CIFS: Move creati...
1877
  	.create_lease_size = sizeof(struct create_lease),
dd446b16e   Steve French   Add SMB2.02 diale...
1878
  };
1080ef758   Steve French   CIFS: Introduce S...
1879
1880
  struct smb_version_values smb21_values = {
  	.version_string = SMB21_VERSION_STRING,
e4aa25e78   Steve French   [CIFS] Fix SMB2 n...
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
  	.protocol_id = SMB21_PROT_ID,
  	.req_capabilities = 0, /* MBZ on negotiate req until SMB3 dialect */
  	.large_lock_type = 0,
  	.exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
  	.shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
  	.unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
  	.header_size = sizeof(struct smb2_hdr),
  	.max_header_size = MAX_SMB2_HDR_SIZE,
  	.read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
  	.lock_cmd = SMB2_LOCK,
  	.cap_unix = 0,
  	.cap_nt_find = SMB2_NT_FIND,
  	.cap_large_files = SMB2_LARGE_FILES,
50285882f   Jeff Layton   cifs: fix SMB2 si...
1894
1895
  	.signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
  	.signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
a41a28bda   Pavel Shilovsky   CIFS: Move creati...
1896
  	.create_lease_size = sizeof(struct create_lease),
e4aa25e78   Steve French   [CIFS] Fix SMB2 n...
1897
1898
1899
1900
1901
  };
  
  struct smb_version_values smb30_values = {
  	.version_string = SMB30_VERSION_STRING,
  	.protocol_id = SMB30_PROT_ID,
373512ec5   Steve French   Prepare for encry...
1902
  	.req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES | SMB2_GLOBAL_CAP_ENCRYPTION,
027e8eec3   Pavel Shilovsky   CIFS: Handle SMB2...
1903
1904
1905
1906
  	.large_lock_type = 0,
  	.exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
  	.shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
  	.unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
1907
1908
  	.header_size = sizeof(struct smb2_hdr),
  	.max_header_size = MAX_SMB2_HDR_SIZE,
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
1909
  	.read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
2dc7e1c03   Pavel Shilovsky   CIFS: Make transp...
1910
  	.lock_cmd = SMB2_LOCK,
29e20f9c6   Pavel Shilovsky   CIFS: Make CAP_* ...
1911
1912
1913
  	.cap_unix = 0,
  	.cap_nt_find = SMB2_NT_FIND,
  	.cap_large_files = SMB2_LARGE_FILES,
50285882f   Jeff Layton   cifs: fix SMB2 si...
1914
1915
  	.signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
  	.signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
f047390a0   Pavel Shilovsky   CIFS: Add create ...
1916
  	.create_lease_size = sizeof(struct create_lease_v2),
1080ef758   Steve French   CIFS: Introduce S...
1917
  };
20b6d8b42   Steve French   Add SMB3.02 diale...
1918
1919
1920
1921
  
  struct smb_version_values smb302_values = {
  	.version_string = SMB302_VERSION_STRING,
  	.protocol_id = SMB302_PROT_ID,
373512ec5   Steve French   Prepare for encry...
1922
  	.req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES | SMB2_GLOBAL_CAP_ENCRYPTION,
20b6d8b42   Steve French   Add SMB3.02 diale...
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
  	.large_lock_type = 0,
  	.exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
  	.shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
  	.unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
  	.header_size = sizeof(struct smb2_hdr),
  	.max_header_size = MAX_SMB2_HDR_SIZE,
  	.read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
  	.lock_cmd = SMB2_LOCK,
  	.cap_unix = 0,
  	.cap_nt_find = SMB2_NT_FIND,
  	.cap_large_files = SMB2_LARGE_FILES,
50285882f   Jeff Layton   cifs: fix SMB2 si...
1934
1935
  	.signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
  	.signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
f047390a0   Pavel Shilovsky   CIFS: Add create ...
1936
  	.create_lease_size = sizeof(struct create_lease_v2),
20b6d8b42   Steve French   Add SMB3.02 diale...
1937
  };
5f7fbf733   Steve French   Allow parsing ver...
1938
1939
1940
1941
1942
  
  #ifdef CONFIG_CIFS_SMB311
  struct smb_version_values smb311_values = {
  	.version_string = SMB311_VERSION_STRING,
  	.protocol_id = SMB311_PROT_ID,
b618f001a   Steve French   [SMB3] Enable che...
1943
  	.req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES,
5f7fbf733   Steve French   Allow parsing ver...
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
  	.large_lock_type = 0,
  	.exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
  	.shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
  	.unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
  	.header_size = sizeof(struct smb2_hdr),
  	.max_header_size = MAX_SMB2_HDR_SIZE,
  	.read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
  	.lock_cmd = SMB2_LOCK,
  	.cap_unix = 0,
  	.cap_nt_find = SMB2_NT_FIND,
  	.cap_large_files = SMB2_LARGE_FILES,
  	.signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
  	.signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
  	.create_lease_size = sizeof(struct create_lease_v2),
  };
  #endif /* SMB311 */