xref: /openbmc/linux/fs/smb/client/smb2inode.c (revision 9144f784f852f9a125cabe9927b986d909bfa439)
1  // SPDX-License-Identifier: LGPL-2.1
2  /*
3   *
4   *   Copyright (C) International Business Machines  Corp., 2002, 2011
5   *                 Etersoft, 2012
6   *   Author(s): Pavel Shilovsky (pshilovsky@samba.org),
7   *              Steve French (sfrench@us.ibm.com)
8   *
9   */
10  #include <linux/fs.h>
11  #include <linux/stat.h>
12  #include <linux/slab.h>
13  #include <linux/pagemap.h>
14  #include <asm/div64.h>
15  #include "cifsfs.h"
16  #include "cifspdu.h"
17  #include "cifsglob.h"
18  #include "cifsproto.h"
19  #include "cifs_debug.h"
20  #include "cifs_fs_sb.h"
21  #include "cifs_unicode.h"
22  #include "fscache.h"
23  #include "smb2glob.h"
24  #include "smb2pdu.h"
25  #include "smb2proto.h"
26  #include "cached_dir.h"
27  #include "smb2status.h"
28  
29  static inline __u32 file_create_options(struct dentry *dentry)
30  {
31  	struct cifsInodeInfo *ci;
32  
33  	if (dentry) {
34  		ci = CIFS_I(d_inode(dentry));
35  		if (ci->cifsAttrs & ATTR_REPARSE)
36  			return OPEN_REPARSE_POINT;
37  	}
38  	return 0;
39  }
40  
41  static struct reparse_data_buffer *reparse_buf_ptr(struct kvec *iov)
42  {
43  	struct reparse_data_buffer *buf;
44  	struct smb2_ioctl_rsp *io = iov->iov_base;
45  	u32 off, count, len;
46  
47  	count = le32_to_cpu(io->OutputCount);
48  	off = le32_to_cpu(io->OutputOffset);
49  	if (check_add_overflow(off, count, &len) || len > iov->iov_len)
50  		return ERR_PTR(-EIO);
51  
52  	buf = (struct reparse_data_buffer *)((u8 *)io + off);
53  	len = sizeof(*buf);
54  	if (count < len || count < le16_to_cpu(buf->ReparseDataLength) + len)
55  		return ERR_PTR(-EIO);
56  	return buf;
57  }
58  
59  /* Parse owner and group from SMB3.1.1 POSIX query info */
60  static int parse_posix_sids(struct cifs_open_info_data *data,
61  			    struct kvec *rsp_iov)
62  {
63  	struct smb2_query_info_rsp *qi = rsp_iov->iov_base;
64  	unsigned int out_len = le32_to_cpu(qi->OutputBufferLength);
65  	unsigned int qi_len = sizeof(data->posix_fi);
66  	int owner_len, group_len;
67  	u8 *sidsbuf, *sidsbuf_end;
68  
69  	if (out_len <= qi_len)
70  		return -EINVAL;
71  
72  	sidsbuf = (u8 *)qi + le16_to_cpu(qi->OutputBufferOffset) + qi_len;
73  	sidsbuf_end = sidsbuf + out_len - qi_len;
74  
75  	owner_len = posix_info_sid_size(sidsbuf, sidsbuf_end);
76  	if (owner_len == -1)
77  		return -EINVAL;
78  
79  	memcpy(&data->posix_owner, sidsbuf, owner_len);
80  	group_len = posix_info_sid_size(sidsbuf + owner_len, sidsbuf_end);
81  	if (group_len == -1)
82  		return -EINVAL;
83  
84  	memcpy(&data->posix_group, sidsbuf + owner_len, group_len);
85  	return 0;
86  }
87  
88  struct wsl_query_ea {
89  	__le32	next;
90  	__u8	name_len;
91  	__u8	name[SMB2_WSL_XATTR_NAME_LEN + 1];
92  } __packed;
93  
94  #define NEXT_OFF cpu_to_le32(sizeof(struct wsl_query_ea))
95  
96  static const struct wsl_query_ea wsl_query_eas[] = {
97  	{ .next = NEXT_OFF, .name_len = SMB2_WSL_XATTR_NAME_LEN, .name = SMB2_WSL_XATTR_UID, },
98  	{ .next = NEXT_OFF, .name_len = SMB2_WSL_XATTR_NAME_LEN, .name = SMB2_WSL_XATTR_GID, },
99  	{ .next = NEXT_OFF, .name_len = SMB2_WSL_XATTR_NAME_LEN, .name = SMB2_WSL_XATTR_MODE, },
100  	{ .next = 0,        .name_len = SMB2_WSL_XATTR_NAME_LEN, .name = SMB2_WSL_XATTR_DEV, },
101  };
102  
103  static int check_wsl_eas(struct kvec *rsp_iov)
104  {
105  	struct smb2_file_full_ea_info *ea;
106  	struct smb2_query_info_rsp *rsp = rsp_iov->iov_base;
107  	unsigned long addr;
108  	u32 outlen, next;
109  	u16 vlen;
110  	u8 nlen;
111  	u8 *end;
112  
113  	outlen = le32_to_cpu(rsp->OutputBufferLength);
114  	if (outlen < SMB2_WSL_MIN_QUERY_EA_RESP_SIZE ||
115  	    outlen > SMB2_WSL_MAX_QUERY_EA_RESP_SIZE)
116  		return -EINVAL;
117  
118  	ea = (void *)((u8 *)rsp_iov->iov_base +
119  		      le16_to_cpu(rsp->OutputBufferOffset));
120  	end = (u8 *)rsp_iov->iov_base + rsp_iov->iov_len;
121  	for (;;) {
122  		if ((u8 *)ea > end - sizeof(*ea))
123  			return -EINVAL;
124  
125  		nlen = ea->ea_name_length;
126  		vlen = le16_to_cpu(ea->ea_value_length);
127  		if (nlen != SMB2_WSL_XATTR_NAME_LEN ||
128  		    (u8 *)ea + nlen + 1 + vlen > end)
129  			return -EINVAL;
130  
131  		switch (vlen) {
132  		case 4:
133  			if (strncmp(ea->ea_data, SMB2_WSL_XATTR_UID, nlen) &&
134  			    strncmp(ea->ea_data, SMB2_WSL_XATTR_GID, nlen) &&
135  			    strncmp(ea->ea_data, SMB2_WSL_XATTR_MODE, nlen))
136  				return -EINVAL;
137  			break;
138  		case 8:
139  			if (strncmp(ea->ea_data, SMB2_WSL_XATTR_DEV, nlen))
140  				return -EINVAL;
141  			break;
142  		case 0:
143  			if (!strncmp(ea->ea_data, SMB2_WSL_XATTR_UID, nlen) ||
144  			    !strncmp(ea->ea_data, SMB2_WSL_XATTR_GID, nlen) ||
145  			    !strncmp(ea->ea_data, SMB2_WSL_XATTR_MODE, nlen) ||
146  			    !strncmp(ea->ea_data, SMB2_WSL_XATTR_DEV, nlen))
147  				break;
148  			fallthrough;
149  		default:
150  			return -EINVAL;
151  		}
152  
153  		next = le32_to_cpu(ea->next_entry_offset);
154  		if (!next)
155  			break;
156  		if (!IS_ALIGNED(next, 4) ||
157  		    check_add_overflow((unsigned long)ea, next, &addr))
158  			return -EINVAL;
159  		ea = (void *)addr;
160  	}
161  	return 0;
162  }
163  
164  /*
165   * note: If cfile is passed, the reference to it is dropped here.
166   * So make sure that you do not reuse cfile after return from this func.
167   *
168   * If passing @out_iov and @out_buftype, ensure to make them both large enough
169   * (>= 3) to hold all compounded responses.  Caller is also responsible for
170   * freeing them up with free_rsp_buf().
171   */
172  static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
173  			    struct cifs_sb_info *cifs_sb, const char *full_path,
174  			    struct cifs_open_parms *oparms, struct kvec *in_iov,
175  			    int *cmds, int num_cmds, struct cifsFileInfo *cfile,
176  			    struct kvec *out_iov, int *out_buftype, struct dentry *dentry)
177  {
178  
179  	struct reparse_data_buffer *rbuf;
180  	struct smb2_compound_vars *vars = NULL;
181  	struct kvec *rsp_iov, *iov;
182  	struct smb_rqst *rqst;
183  	int rc;
184  	__le16 *utf16_path = NULL;
185  	__u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
186  	struct cifs_fid fid;
187  	struct cifs_ses *ses = tcon->ses;
188  	struct TCP_Server_Info *server;
189  	int num_rqst = 0, i;
190  	int resp_buftype[MAX_COMPOUND];
191  	struct smb2_query_info_rsp *qi_rsp = NULL;
192  	struct cifs_open_info_data *idata;
193  	struct inode *inode = NULL;
194  	int flags = 0;
195  	__u8 delete_pending[8] = {1, 0, 0, 0, 0, 0, 0, 0};
196  	unsigned int size[2];
197  	void *data[2];
198  	unsigned int len;
199  	int retries = 0, cur_sleep = 1;
200  
201  replay_again:
202  	/* reinitialize for possible replay */
203  	flags = 0;
204  	oplock = SMB2_OPLOCK_LEVEL_NONE;
205  	num_rqst = 0;
206  	server = cifs_pick_channel(ses);
207  
208  	vars = kzalloc(sizeof(*vars), GFP_ATOMIC);
209  	if (vars == NULL)
210  		return -ENOMEM;
211  	rqst = &vars->rqst[0];
212  	rsp_iov = &vars->rsp_iov[0];
213  
214  	if (smb3_encryption_required(tcon))
215  		flags |= CIFS_TRANSFORM_REQ;
216  
217  	for (i = 0; i < ARRAY_SIZE(resp_buftype); i++)
218  		resp_buftype[i] = CIFS_NO_BUFFER;
219  
220  	/* We already have a handle so we can skip the open */
221  	if (cfile)
222  		goto after_open;
223  
224  	/* Open */
225  	utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
226  	if (!utf16_path) {
227  		rc = -ENOMEM;
228  		goto finished;
229  	}
230  
231  	/* if there is an existing lease, reuse it */
232  
233  	/*
234  	 * note: files with hardlinks cause unexpected behaviour. As per MS-SMB2,
235  	 * lease keys are associated with the filepath. We are maintaining lease keys
236  	 * with the inode on the client. If the file has hardlinks, it is possible
237  	 * that the lease for a file be reused for an operation on its hardlink or
238  	 * vice versa.
239  	 * As a workaround, send request using an existing lease key and if the server
240  	 * returns STATUS_INVALID_PARAMETER, which maps to EINVAL, send the request
241  	 * again without the lease.
242  	 */
243  	if (dentry) {
244  		inode = d_inode(dentry);
245  		if (CIFS_I(inode)->lease_granted && server->ops->get_lease_key) {
246  			oplock = SMB2_OPLOCK_LEVEL_LEASE;
247  			server->ops->get_lease_key(inode, &fid);
248  		}
249  	}
250  
251  	vars->oparms = *oparms;
252  	vars->oparms.fid = &fid;
253  
254  	rqst[num_rqst].rq_iov = &vars->open_iov[0];
255  	rqst[num_rqst].rq_nvec = SMB2_CREATE_IOV_SIZE;
256  	rc = SMB2_open_init(tcon, server,
257  			    &rqst[num_rqst], &oplock, &vars->oparms,
258  			    utf16_path);
259  	kfree(utf16_path);
260  	if (rc)
261  		goto finished;
262  
263  	smb2_set_next_command(tcon, &rqst[num_rqst]);
264   after_open:
265  	num_rqst++;
266  	rc = 0;
267  
268  	for (i = 0; i < num_cmds; i++) {
269  		/* Operation */
270  		switch (cmds[i]) {
271  		case SMB2_OP_QUERY_INFO:
272  			rqst[num_rqst].rq_iov = &vars->qi_iov;
273  			rqst[num_rqst].rq_nvec = 1;
274  
275  			if (cfile) {
276  				rc = SMB2_query_info_init(tcon, server,
277  							  &rqst[num_rqst],
278  							  cfile->fid.persistent_fid,
279  							  cfile->fid.volatile_fid,
280  							  FILE_ALL_INFORMATION,
281  							  SMB2_O_INFO_FILE, 0,
282  							  sizeof(struct smb2_file_all_info) +
283  							  PATH_MAX * 2, 0, NULL);
284  			} else {
285  				rc = SMB2_query_info_init(tcon, server,
286  							  &rqst[num_rqst],
287  							  COMPOUND_FID,
288  							  COMPOUND_FID,
289  							  FILE_ALL_INFORMATION,
290  							  SMB2_O_INFO_FILE, 0,
291  							  sizeof(struct smb2_file_all_info) +
292  							  PATH_MAX * 2, 0, NULL);
293  			}
294  			if (!rc && (!cfile || num_rqst > 1)) {
295  				smb2_set_next_command(tcon, &rqst[num_rqst]);
296  				smb2_set_related(&rqst[num_rqst]);
297  			} else if (rc) {
298  				goto finished;
299  			}
300  			num_rqst++;
301  			trace_smb3_query_info_compound_enter(xid, ses->Suid,
302  							     tcon->tid, full_path);
303  			break;
304  		case SMB2_OP_POSIX_QUERY_INFO:
305  			rqst[num_rqst].rq_iov = &vars->qi_iov;
306  			rqst[num_rqst].rq_nvec = 1;
307  
308  			if (cfile) {
309  				/* TBD: fix following to allow for longer SIDs */
310  				rc = SMB2_query_info_init(tcon, server,
311  							  &rqst[num_rqst],
312  							  cfile->fid.persistent_fid,
313  							  cfile->fid.volatile_fid,
314  							  SMB_FIND_FILE_POSIX_INFO,
315  							  SMB2_O_INFO_FILE, 0,
316  							  sizeof(struct smb311_posix_qinfo *) +
317  							  (PATH_MAX * 2) +
318  							  (sizeof(struct smb_sid) * 2), 0, NULL);
319  			} else {
320  				rc = SMB2_query_info_init(tcon, server,
321  							  &rqst[num_rqst],
322  							  COMPOUND_FID,
323  							  COMPOUND_FID,
324  							  SMB_FIND_FILE_POSIX_INFO,
325  							  SMB2_O_INFO_FILE, 0,
326  							  sizeof(struct smb311_posix_qinfo *) +
327  							  (PATH_MAX * 2) +
328  							  (sizeof(struct smb_sid) * 2), 0, NULL);
329  			}
330  			if (!rc && (!cfile || num_rqst > 1)) {
331  				smb2_set_next_command(tcon, &rqst[num_rqst]);
332  				smb2_set_related(&rqst[num_rqst]);
333  			} else if (rc) {
334  				goto finished;
335  			}
336  			num_rqst++;
337  			trace_smb3_posix_query_info_compound_enter(xid, ses->Suid,
338  								   tcon->tid, full_path);
339  			break;
340  		case SMB2_OP_DELETE:
341  			trace_smb3_delete_enter(xid, ses->Suid, tcon->tid, full_path);
342  			break;
343  		case SMB2_OP_MKDIR:
344  			/*
345  			 * Directories are created through parameters in the
346  			 * SMB2_open() call.
347  			 */
348  			trace_smb3_mkdir_enter(xid, ses->Suid, tcon->tid, full_path);
349  			break;
350  		case SMB2_OP_RMDIR:
351  			rqst[num_rqst].rq_iov = &vars->si_iov[0];
352  			rqst[num_rqst].rq_nvec = 1;
353  
354  			size[0] = 1; /* sizeof __u8 See MS-FSCC section 2.4.11 */
355  			data[0] = &delete_pending[0];
356  
357  			rc = SMB2_set_info_init(tcon, server,
358  						&rqst[num_rqst], COMPOUND_FID,
359  						COMPOUND_FID, current->tgid,
360  						FILE_DISPOSITION_INFORMATION,
361  						SMB2_O_INFO_FILE, 0, data, size);
362  			if (rc)
363  				goto finished;
364  			smb2_set_next_command(tcon, &rqst[num_rqst]);
365  			smb2_set_related(&rqst[num_rqst++]);
366  			trace_smb3_rmdir_enter(xid, ses->Suid, tcon->tid, full_path);
367  			break;
368  		case SMB2_OP_SET_EOF:
369  			rqst[num_rqst].rq_iov = &vars->si_iov[0];
370  			rqst[num_rqst].rq_nvec = 1;
371  
372  			size[0] = in_iov[i].iov_len;
373  			data[0] = in_iov[i].iov_base;
374  
375  			if (cfile) {
376  				rc = SMB2_set_info_init(tcon, server,
377  							&rqst[num_rqst],
378  							cfile->fid.persistent_fid,
379  							cfile->fid.volatile_fid,
380  							current->tgid,
381  							FILE_END_OF_FILE_INFORMATION,
382  							SMB2_O_INFO_FILE, 0,
383  							data, size);
384  			} else {
385  				rc = SMB2_set_info_init(tcon, server,
386  							&rqst[num_rqst],
387  							COMPOUND_FID,
388  							COMPOUND_FID,
389  							current->tgid,
390  							FILE_END_OF_FILE_INFORMATION,
391  							SMB2_O_INFO_FILE, 0,
392  							data, size);
393  			}
394  			if (!rc && (!cfile || num_rqst > 1)) {
395  				smb2_set_next_command(tcon, &rqst[num_rqst]);
396  				smb2_set_related(&rqst[num_rqst]);
397  			} else if (rc) {
398  				goto finished;
399  			}
400  			num_rqst++;
401  			trace_smb3_set_eof_enter(xid, ses->Suid, tcon->tid, full_path);
402  			break;
403  		case SMB2_OP_SET_INFO:
404  			rqst[num_rqst].rq_iov = &vars->si_iov[0];
405  			rqst[num_rqst].rq_nvec = 1;
406  
407  			size[0] = in_iov[i].iov_len;
408  			data[0] = in_iov[i].iov_base;
409  
410  			if (cfile) {
411  				rc = SMB2_set_info_init(tcon, server,
412  							&rqst[num_rqst],
413  							cfile->fid.persistent_fid,
414  							cfile->fid.volatile_fid, current->tgid,
415  							FILE_BASIC_INFORMATION,
416  							SMB2_O_INFO_FILE, 0, data, size);
417  			} else {
418  				rc = SMB2_set_info_init(tcon, server,
419  							&rqst[num_rqst],
420  							COMPOUND_FID,
421  							COMPOUND_FID, current->tgid,
422  							FILE_BASIC_INFORMATION,
423  							SMB2_O_INFO_FILE, 0, data, size);
424  			}
425  			if (!rc && (!cfile || num_rqst > 1)) {
426  				smb2_set_next_command(tcon, &rqst[num_rqst]);
427  				smb2_set_related(&rqst[num_rqst]);
428  			} else if (rc) {
429  				goto finished;
430  			}
431  			num_rqst++;
432  			trace_smb3_set_info_compound_enter(xid, ses->Suid,
433  							   tcon->tid, full_path);
434  			break;
435  		case SMB2_OP_RENAME:
436  			rqst[num_rqst].rq_iov = &vars->si_iov[0];
437  			rqst[num_rqst].rq_nvec = 2;
438  
439  			len = in_iov[i].iov_len;
440  
441  			vars->rename_info.ReplaceIfExists = 1;
442  			vars->rename_info.RootDirectory = 0;
443  			vars->rename_info.FileNameLength = cpu_to_le32(len);
444  
445  			size[0] = sizeof(struct smb2_file_rename_info);
446  			data[0] = &vars->rename_info;
447  
448  			size[1] = len + 2 /* null */;
449  			data[1] = in_iov[i].iov_base;
450  
451  			if (cfile) {
452  				rc = SMB2_set_info_init(tcon, server,
453  							&rqst[num_rqst],
454  							cfile->fid.persistent_fid,
455  							cfile->fid.volatile_fid,
456  							current->tgid, FILE_RENAME_INFORMATION,
457  							SMB2_O_INFO_FILE, 0, data, size);
458  			} else {
459  				rc = SMB2_set_info_init(tcon, server,
460  							&rqst[num_rqst],
461  							COMPOUND_FID, COMPOUND_FID,
462  							current->tgid, FILE_RENAME_INFORMATION,
463  							SMB2_O_INFO_FILE, 0, data, size);
464  			}
465  			if (!rc && (!cfile || num_rqst > 1)) {
466  				smb2_set_next_command(tcon, &rqst[num_rqst]);
467  				smb2_set_related(&rqst[num_rqst]);
468  			} else if (rc) {
469  				goto finished;
470  			}
471  			num_rqst++;
472  			trace_smb3_rename_enter(xid, ses->Suid, tcon->tid, full_path);
473  			break;
474  		case SMB2_OP_HARDLINK:
475  			rqst[num_rqst].rq_iov = &vars->si_iov[0];
476  			rqst[num_rqst].rq_nvec = 2;
477  
478  			len = in_iov[i].iov_len;
479  
480  			vars->link_info.ReplaceIfExists = 0;
481  			vars->link_info.RootDirectory = 0;
482  			vars->link_info.FileNameLength = cpu_to_le32(len);
483  
484  			size[0] = sizeof(struct smb2_file_link_info);
485  			data[0] = &vars->link_info;
486  
487  			size[1] = len + 2 /* null */;
488  			data[1] = in_iov[i].iov_base;
489  
490  			rc = SMB2_set_info_init(tcon, server,
491  						&rqst[num_rqst], COMPOUND_FID,
492  						COMPOUND_FID, current->tgid,
493  						FILE_LINK_INFORMATION,
494  						SMB2_O_INFO_FILE, 0, data, size);
495  			if (rc)
496  				goto finished;
497  			smb2_set_next_command(tcon, &rqst[num_rqst]);
498  			smb2_set_related(&rqst[num_rqst++]);
499  			trace_smb3_hardlink_enter(xid, ses->Suid, tcon->tid, full_path);
500  			break;
501  		case SMB2_OP_SET_REPARSE:
502  			rqst[num_rqst].rq_iov = vars->io_iov;
503  			rqst[num_rqst].rq_nvec = ARRAY_SIZE(vars->io_iov);
504  
505  			if (cfile) {
506  				rc = SMB2_ioctl_init(tcon, server, &rqst[num_rqst],
507  						     cfile->fid.persistent_fid,
508  						     cfile->fid.volatile_fid,
509  						     FSCTL_SET_REPARSE_POINT,
510  						     in_iov[i].iov_base,
511  						     in_iov[i].iov_len, 0);
512  			} else {
513  				rc = SMB2_ioctl_init(tcon, server, &rqst[num_rqst],
514  						     COMPOUND_FID, COMPOUND_FID,
515  						     FSCTL_SET_REPARSE_POINT,
516  						     in_iov[i].iov_base,
517  						     in_iov[i].iov_len, 0);
518  			}
519  			if (!rc && (!cfile || num_rqst > 1)) {
520  				smb2_set_next_command(tcon, &rqst[num_rqst]);
521  				smb2_set_related(&rqst[num_rqst]);
522  			} else if (rc) {
523  				goto finished;
524  			}
525  			num_rqst++;
526  			trace_smb3_set_reparse_compound_enter(xid, ses->Suid,
527  							      tcon->tid, full_path);
528  			break;
529  		case SMB2_OP_GET_REPARSE:
530  			rqst[num_rqst].rq_iov = vars->io_iov;
531  			rqst[num_rqst].rq_nvec = ARRAY_SIZE(vars->io_iov);
532  
533  			if (cfile) {
534  				rc = SMB2_ioctl_init(tcon, server, &rqst[num_rqst],
535  						     cfile->fid.persistent_fid,
536  						     cfile->fid.volatile_fid,
537  						     FSCTL_GET_REPARSE_POINT,
538  						     NULL, 0, CIFSMaxBufSize);
539  			} else {
540  				rc = SMB2_ioctl_init(tcon, server, &rqst[num_rqst],
541  						     COMPOUND_FID, COMPOUND_FID,
542  						     FSCTL_GET_REPARSE_POINT,
543  						     NULL, 0, CIFSMaxBufSize);
544  			}
545  			if (!rc && (!cfile || num_rqst > 1)) {
546  				smb2_set_next_command(tcon, &rqst[num_rqst]);
547  				smb2_set_related(&rqst[num_rqst]);
548  			} else if (rc) {
549  				goto finished;
550  			}
551  			num_rqst++;
552  			trace_smb3_get_reparse_compound_enter(xid, ses->Suid,
553  							      tcon->tid, full_path);
554  			break;
555  		case SMB2_OP_QUERY_WSL_EA:
556  			rqst[num_rqst].rq_iov = &vars->ea_iov;
557  			rqst[num_rqst].rq_nvec = 1;
558  
559  			if (cfile) {
560  				rc = SMB2_query_info_init(tcon, server,
561  							  &rqst[num_rqst],
562  							  cfile->fid.persistent_fid,
563  							  cfile->fid.volatile_fid,
564  							  FILE_FULL_EA_INFORMATION,
565  							  SMB2_O_INFO_FILE, 0,
566  							  SMB2_WSL_MAX_QUERY_EA_RESP_SIZE,
567  							  sizeof(wsl_query_eas),
568  							  (void *)wsl_query_eas);
569  			} else {
570  				rc = SMB2_query_info_init(tcon, server,
571  							  &rqst[num_rqst],
572  							  COMPOUND_FID,
573  							  COMPOUND_FID,
574  							  FILE_FULL_EA_INFORMATION,
575  							  SMB2_O_INFO_FILE, 0,
576  							  SMB2_WSL_MAX_QUERY_EA_RESP_SIZE,
577  							  sizeof(wsl_query_eas),
578  							  (void *)wsl_query_eas);
579  			}
580  			if (!rc && (!cfile || num_rqst > 1)) {
581  				smb2_set_next_command(tcon, &rqst[num_rqst]);
582  				smb2_set_related(&rqst[num_rqst]);
583  			} else if (rc) {
584  				goto finished;
585  			}
586  			num_rqst++;
587  			break;
588  		default:
589  			cifs_dbg(VFS, "Invalid command\n");
590  			rc = -EINVAL;
591  		}
592  	}
593  	if (rc)
594  		goto finished;
595  
596  	/* We already have a handle so we can skip the close */
597  	if (cfile)
598  		goto after_close;
599  	/* Close */
600  	flags |= CIFS_CP_CREATE_CLOSE_OP;
601  	rqst[num_rqst].rq_iov = &vars->close_iov;
602  	rqst[num_rqst].rq_nvec = 1;
603  	rc = SMB2_close_init(tcon, server,
604  			     &rqst[num_rqst], COMPOUND_FID,
605  			     COMPOUND_FID, false);
606  	smb2_set_related(&rqst[num_rqst]);
607  	if (rc)
608  		goto finished;
609   after_close:
610  	num_rqst++;
611  
612  	if (cfile) {
613  		if (retries)
614  			for (i = 1; i < num_rqst - 2; i++)
615  				smb2_set_replay(server, &rqst[i]);
616  
617  		rc = compound_send_recv(xid, ses, server,
618  					flags, num_rqst - 2,
619  					&rqst[1], &resp_buftype[1],
620  					&rsp_iov[1]);
621  	} else {
622  		if (retries)
623  			for (i = 0; i < num_rqst; i++)
624  				smb2_set_replay(server, &rqst[i]);
625  
626  		rc = compound_send_recv(xid, ses, server,
627  					flags, num_rqst,
628  					rqst, resp_buftype,
629  					rsp_iov);
630  	}
631  
632  finished:
633  	num_rqst = 0;
634  	SMB2_open_free(&rqst[num_rqst++]);
635  	if (rc == -EREMCHG) {
636  		pr_warn_once("server share %s deleted\n", tcon->tree_name);
637  		tcon->need_reconnect = true;
638  	}
639  
640  	for (i = 0; i < num_cmds; i++) {
641  		switch (cmds[i]) {
642  		case SMB2_OP_QUERY_INFO:
643  			idata = in_iov[i].iov_base;
644  			if (rc == 0 && cfile && cfile->symlink_target) {
645  				idata->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL);
646  				if (!idata->symlink_target)
647  					rc = -ENOMEM;
648  			}
649  			if (rc == 0) {
650  				qi_rsp = (struct smb2_query_info_rsp *)
651  					rsp_iov[i + 1].iov_base;
652  				rc = smb2_validate_and_copy_iov(
653  					le16_to_cpu(qi_rsp->OutputBufferOffset),
654  					le32_to_cpu(qi_rsp->OutputBufferLength),
655  					&rsp_iov[i + 1], sizeof(idata->fi), (char *)&idata->fi);
656  			}
657  			SMB2_query_info_free(&rqst[num_rqst++]);
658  			if (rc)
659  				trace_smb3_query_info_compound_err(xid,  ses->Suid,
660  								   tcon->tid, rc);
661  			else
662  				trace_smb3_query_info_compound_done(xid, ses->Suid,
663  								    tcon->tid);
664  			break;
665  		case SMB2_OP_POSIX_QUERY_INFO:
666  			idata = in_iov[i].iov_base;
667  			if (rc == 0 && cfile && cfile->symlink_target) {
668  				idata->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL);
669  				if (!idata->symlink_target)
670  					rc = -ENOMEM;
671  			}
672  			if (rc == 0) {
673  				qi_rsp = (struct smb2_query_info_rsp *)
674  					rsp_iov[i + 1].iov_base;
675  				rc = smb2_validate_and_copy_iov(
676  					le16_to_cpu(qi_rsp->OutputBufferOffset),
677  					le32_to_cpu(qi_rsp->OutputBufferLength),
678  					&rsp_iov[i + 1], sizeof(idata->posix_fi) /* add SIDs */,
679  					(char *)&idata->posix_fi);
680  			}
681  			if (rc == 0)
682  				rc = parse_posix_sids(idata, &rsp_iov[i + 1]);
683  
684  			SMB2_query_info_free(&rqst[num_rqst++]);
685  			if (rc)
686  				trace_smb3_posix_query_info_compound_err(xid,  ses->Suid,
687  									 tcon->tid, rc);
688  			else
689  				trace_smb3_posix_query_info_compound_done(xid, ses->Suid,
690  									  tcon->tid);
691  			break;
692  		case SMB2_OP_DELETE:
693  			if (rc)
694  				trace_smb3_delete_err(xid,  ses->Suid, tcon->tid, rc);
695  			else {
696  				/*
697  				 * If dentry (hence, inode) is NULL, lease break is going to
698  				 * take care of degrading leases on handles for deleted files.
699  				 */
700  				if (inode)
701  					cifs_mark_open_handles_for_deleted_file(inode, full_path);
702  				trace_smb3_delete_done(xid, ses->Suid, tcon->tid);
703  			}
704  			break;
705  		case SMB2_OP_MKDIR:
706  			if (rc)
707  				trace_smb3_mkdir_err(xid,  ses->Suid, tcon->tid, rc);
708  			else
709  				trace_smb3_mkdir_done(xid, ses->Suid, tcon->tid);
710  			break;
711  		case SMB2_OP_HARDLINK:
712  			if (rc)
713  				trace_smb3_hardlink_err(xid,  ses->Suid, tcon->tid, rc);
714  			else
715  				trace_smb3_hardlink_done(xid, ses->Suid, tcon->tid);
716  			SMB2_set_info_free(&rqst[num_rqst++]);
717  			break;
718  		case SMB2_OP_RENAME:
719  			if (rc)
720  				trace_smb3_rename_err(xid,  ses->Suid, tcon->tid, rc);
721  			else
722  				trace_smb3_rename_done(xid, ses->Suid, tcon->tid);
723  			SMB2_set_info_free(&rqst[num_rqst++]);
724  			break;
725  		case SMB2_OP_RMDIR:
726  			if (rc)
727  				trace_smb3_rmdir_err(xid,  ses->Suid, tcon->tid, rc);
728  			else
729  				trace_smb3_rmdir_done(xid, ses->Suid, tcon->tid);
730  			SMB2_set_info_free(&rqst[num_rqst++]);
731  			break;
732  		case SMB2_OP_SET_EOF:
733  			if (rc)
734  				trace_smb3_set_eof_err(xid,  ses->Suid, tcon->tid, rc);
735  			else
736  				trace_smb3_set_eof_done(xid, ses->Suid, tcon->tid);
737  			SMB2_set_info_free(&rqst[num_rqst++]);
738  			break;
739  		case SMB2_OP_SET_INFO:
740  			if (rc)
741  				trace_smb3_set_info_compound_err(xid,  ses->Suid,
742  								 tcon->tid, rc);
743  			else
744  				trace_smb3_set_info_compound_done(xid, ses->Suid,
745  								  tcon->tid);
746  			SMB2_set_info_free(&rqst[num_rqst++]);
747  			break;
748  		case SMB2_OP_SET_REPARSE:
749  			if (rc) {
750  				trace_smb3_set_reparse_compound_err(xid,  ses->Suid,
751  								    tcon->tid, rc);
752  			} else {
753  				trace_smb3_set_reparse_compound_done(xid, ses->Suid,
754  								     tcon->tid);
755  			}
756  			SMB2_ioctl_free(&rqst[num_rqst++]);
757  			break;
758  		case SMB2_OP_GET_REPARSE:
759  			if (!rc) {
760  				iov = &rsp_iov[i + 1];
761  				idata = in_iov[i].iov_base;
762  				idata->reparse.io.iov = *iov;
763  				idata->reparse.io.buftype = resp_buftype[i + 1];
764  				rbuf = reparse_buf_ptr(iov);
765  				if (IS_ERR(rbuf)) {
766  					rc = PTR_ERR(rbuf);
767  					trace_smb3_set_reparse_compound_err(xid,  ses->Suid,
768  									    tcon->tid, rc);
769  				} else {
770  					idata->reparse.tag = le32_to_cpu(rbuf->ReparseTag);
771  					trace_smb3_set_reparse_compound_done(xid, ses->Suid,
772  									     tcon->tid);
773  				}
774  				memset(iov, 0, sizeof(*iov));
775  				resp_buftype[i + 1] = CIFS_NO_BUFFER;
776  			} else {
777  				trace_smb3_set_reparse_compound_err(xid, ses->Suid,
778  								    tcon->tid, rc);
779  			}
780  			SMB2_ioctl_free(&rqst[num_rqst++]);
781  			break;
782  		case SMB2_OP_QUERY_WSL_EA:
783  			if (!rc) {
784  				idata = in_iov[i].iov_base;
785  				qi_rsp = rsp_iov[i + 1].iov_base;
786  				data[0] = (u8 *)qi_rsp + le16_to_cpu(qi_rsp->OutputBufferOffset);
787  				size[0] = le32_to_cpu(qi_rsp->OutputBufferLength);
788  				rc = check_wsl_eas(&rsp_iov[i + 1]);
789  				if (!rc) {
790  					memcpy(idata->wsl.eas, data[0], size[0]);
791  					idata->wsl.eas_len = size[0];
792  				}
793  			}
794  			if (!rc) {
795  				trace_smb3_query_wsl_ea_compound_done(xid, ses->Suid,
796  								      tcon->tid);
797  			} else {
798  				trace_smb3_query_wsl_ea_compound_err(xid, ses->Suid,
799  								     tcon->tid, rc);
800  			}
801  			SMB2_query_info_free(&rqst[num_rqst++]);
802  			break;
803  		}
804  	}
805  	SMB2_close_free(&rqst[num_rqst]);
806  
807  	num_cmds += 2;
808  	if (out_iov && out_buftype) {
809  		memcpy(out_iov, rsp_iov, num_cmds * sizeof(*out_iov));
810  		memcpy(out_buftype, resp_buftype,
811  		       num_cmds * sizeof(*out_buftype));
812  	} else {
813  		for (i = 0; i < num_cmds; i++)
814  			free_rsp_buf(resp_buftype[i], rsp_iov[i].iov_base);
815  	}
816  	num_cmds -= 2; /* correct num_cmds as there could be a retry */
817  	kfree(vars);
818  
819  	if (is_replayable_error(rc) &&
820  	    smb2_should_replay(tcon, &retries, &cur_sleep))
821  		goto replay_again;
822  
823  	if (cfile)
824  		cifsFileInfo_put(cfile);
825  
826  	return rc;
827  }
828  
829  static int parse_create_response(struct cifs_open_info_data *data,
830  				 struct cifs_sb_info *cifs_sb,
831  				 const char *full_path,
832  				 const struct kvec *iov)
833  {
834  	struct smb2_create_rsp *rsp = iov->iov_base;
835  	bool reparse_point = false;
836  	u32 tag = 0;
837  	int rc = 0;
838  
839  	switch (rsp->hdr.Status) {
840  	case STATUS_IO_REPARSE_TAG_NOT_HANDLED:
841  		reparse_point = true;
842  		break;
843  	case STATUS_STOPPED_ON_SYMLINK:
844  		rc = smb2_parse_symlink_response(cifs_sb, iov,
845  						 full_path,
846  						 &data->symlink_target);
847  		if (rc)
848  			return rc;
849  		tag = IO_REPARSE_TAG_SYMLINK;
850  		reparse_point = true;
851  		break;
852  	case STATUS_SUCCESS:
853  		reparse_point = !!(rsp->Flags & SMB2_CREATE_FLAG_REPARSEPOINT);
854  		break;
855  	}
856  	data->reparse_point = reparse_point;
857  	data->reparse.tag = tag;
858  	return rc;
859  }
860  
861  int smb2_query_path_info(const unsigned int xid,
862  			 struct cifs_tcon *tcon,
863  			 struct cifs_sb_info *cifs_sb,
864  			 const char *full_path,
865  			 struct cifs_open_info_data *data)
866  {
867  	struct cifs_open_parms oparms;
868  	__u32 create_options = 0;
869  	struct cifsFileInfo *cfile;
870  	struct cached_fid *cfid = NULL;
871  	struct smb2_hdr *hdr;
872  	struct kvec in_iov[3], out_iov[3] = {};
873  	int out_buftype[3] = {};
874  	int cmds[3];
875  	bool islink;
876  	int i, num_cmds = 0;
877  	int rc, rc2;
878  
879  	data->adjust_tz = false;
880  	data->reparse_point = false;
881  
882  	/*
883  	 * BB TODO: Add support for using cached root handle in SMB3.1.1 POSIX.
884  	 * Create SMB2_query_posix_info worker function to do non-compounded
885  	 * query when we already have an open file handle for this. For now this
886  	 * is fast enough (always using the compounded version).
887  	 */
888  	if (!tcon->posix_extensions) {
889  		if (*full_path) {
890  			rc = -ENOENT;
891  		} else {
892  			rc = open_cached_dir(xid, tcon, full_path,
893  					     cifs_sb, false, &cfid);
894  		}
895  		/* If it is a root and its handle is cached then use it */
896  		if (!rc) {
897  			if (cfid->file_all_info_is_valid) {
898  				memcpy(&data->fi, &cfid->file_all_info,
899  				       sizeof(data->fi));
900  			} else {
901  				rc = SMB2_query_info(xid, tcon,
902  						     cfid->fid.persistent_fid,
903  						     cfid->fid.volatile_fid,
904  						     &data->fi);
905  			}
906  			close_cached_dir(cfid);
907  			return rc;
908  		}
909  		cmds[num_cmds++] = SMB2_OP_QUERY_INFO;
910  	} else {
911  		cmds[num_cmds++] = SMB2_OP_POSIX_QUERY_INFO;
912  	}
913  
914  	in_iov[0].iov_base = data;
915  	in_iov[0].iov_len = sizeof(*data);
916  	in_iov[1] = in_iov[0];
917  	in_iov[2] = in_iov[0];
918  
919  	cifs_get_readable_path(tcon, full_path, &cfile);
920  	oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, FILE_READ_ATTRIBUTES,
921  			     FILE_OPEN, create_options, ACL_NO_MODE);
922  	rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
923  			      &oparms, in_iov, cmds, num_cmds,
924  			      cfile, out_iov, out_buftype, NULL);
925  	hdr = out_iov[0].iov_base;
926  	/*
927  	 * If first iov is unset, then SMB session was dropped or we've got a
928  	 * cached open file (@cfile).
929  	 */
930  	if (!hdr || out_buftype[0] == CIFS_NO_BUFFER)
931  		goto out;
932  
933  	switch (rc) {
934  	case 0:
935  		rc = parse_create_response(data, cifs_sb, full_path, &out_iov[0]);
936  		break;
937  	case -EOPNOTSUPP:
938  		/*
939  		 * BB TODO: When support for special files added to Samba
940  		 * re-verify this path.
941  		 */
942  		rc = parse_create_response(data, cifs_sb, full_path, &out_iov[0]);
943  		if (rc || !data->reparse_point)
944  			goto out;
945  
946  		if (!tcon->posix_extensions)
947  			cmds[num_cmds++] = SMB2_OP_QUERY_WSL_EA;
948  		/*
949  		 * Skip SMB2_OP_GET_REPARSE if symlink already parsed in create
950  		 * response.
951  		 */
952  		if (data->reparse.tag != IO_REPARSE_TAG_SYMLINK)
953  			cmds[num_cmds++] = SMB2_OP_GET_REPARSE;
954  
955  		oparms = CIFS_OPARMS(cifs_sb, tcon, full_path,
956  				     FILE_READ_ATTRIBUTES |
957  				     FILE_READ_EA | SYNCHRONIZE,
958  				     FILE_OPEN, create_options |
959  				     OPEN_REPARSE_POINT, ACL_NO_MODE);
960  		cifs_get_readable_path(tcon, full_path, &cfile);
961  		rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
962  				      &oparms, in_iov, cmds, num_cmds,
963  				      cfile, NULL, NULL, NULL);
964  		break;
965  	case -EREMOTE:
966  		break;
967  	default:
968  		if (hdr->Status != STATUS_OBJECT_NAME_INVALID)
969  			break;
970  		rc2 = cifs_inval_name_dfs_link_error(xid, tcon, cifs_sb,
971  						     full_path, &islink);
972  		if (rc2) {
973  			rc = rc2;
974  			goto out;
975  		}
976  		if (islink)
977  			rc = -EREMOTE;
978  	}
979  
980  out:
981  	for (i = 0; i < ARRAY_SIZE(out_buftype); i++)
982  		free_rsp_buf(out_buftype[i], out_iov[i].iov_base);
983  	return rc;
984  }
985  
986  int
987  smb2_mkdir(const unsigned int xid, struct inode *parent_inode, umode_t mode,
988  	   struct cifs_tcon *tcon, const char *name,
989  	   struct cifs_sb_info *cifs_sb)
990  {
991  	struct cifs_open_parms oparms;
992  
993  	oparms = CIFS_OPARMS(cifs_sb, tcon, name, FILE_WRITE_ATTRIBUTES,
994  			     FILE_CREATE, CREATE_NOT_FILE, mode);
995  	return smb2_compound_op(xid, tcon, cifs_sb,
996  				name, &oparms, NULL,
997  				&(int){SMB2_OP_MKDIR}, 1,
998  				NULL, NULL, NULL, NULL);
999  }
1000  
1001  void
1002  smb2_mkdir_setinfo(struct inode *inode, const char *name,
1003  		   struct cifs_sb_info *cifs_sb, struct cifs_tcon *tcon,
1004  		   const unsigned int xid)
1005  {
1006  	struct cifs_open_parms oparms;
1007  	FILE_BASIC_INFO data = {};
1008  	struct cifsInodeInfo *cifs_i;
1009  	struct cifsFileInfo *cfile;
1010  	struct kvec in_iov;
1011  	u32 dosattrs;
1012  	int tmprc;
1013  
1014  	in_iov.iov_base = &data;
1015  	in_iov.iov_len = sizeof(data);
1016  	cifs_i = CIFS_I(inode);
1017  	dosattrs = cifs_i->cifsAttrs | ATTR_READONLY;
1018  	data.Attributes = cpu_to_le32(dosattrs);
1019  	cifs_get_writable_path(tcon, name, FIND_WR_ANY, &cfile);
1020  	oparms = CIFS_OPARMS(cifs_sb, tcon, name, FILE_WRITE_ATTRIBUTES,
1021  			     FILE_CREATE, CREATE_NOT_FILE, ACL_NO_MODE);
1022  	tmprc = smb2_compound_op(xid, tcon, cifs_sb, name,
1023  				 &oparms, &in_iov,
1024  				 &(int){SMB2_OP_SET_INFO}, 1,
1025  				 cfile, NULL, NULL, NULL);
1026  	if (tmprc == 0)
1027  		cifs_i->cifsAttrs = dosattrs;
1028  }
1029  
1030  int
1031  smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
1032  	   struct cifs_sb_info *cifs_sb)
1033  {
1034  	struct cifs_open_parms oparms;
1035  
1036  	drop_cached_dir_by_name(xid, tcon, name, cifs_sb);
1037  	oparms = CIFS_OPARMS(cifs_sb, tcon, name, DELETE,
1038  			     FILE_OPEN, CREATE_NOT_FILE, ACL_NO_MODE);
1039  	return smb2_compound_op(xid, tcon, cifs_sb,
1040  				name, &oparms, NULL,
1041  				&(int){SMB2_OP_RMDIR}, 1,
1042  				NULL, NULL, NULL, NULL);
1043  }
1044  
1045  int
1046  smb2_unlink(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
1047  	    struct cifs_sb_info *cifs_sb, struct dentry *dentry)
1048  {
1049  	struct cifs_open_parms oparms;
1050  
1051  	oparms = CIFS_OPARMS(cifs_sb, tcon, name,
1052  			     DELETE, FILE_OPEN,
1053  			     CREATE_DELETE_ON_CLOSE | OPEN_REPARSE_POINT,
1054  			     ACL_NO_MODE);
1055  	int rc = smb2_compound_op(xid, tcon, cifs_sb, name, &oparms,
1056  				  NULL, &(int){SMB2_OP_DELETE}, 1,
1057  				  NULL, NULL, NULL, dentry);
1058  	if (rc == -EINVAL) {
1059  		cifs_dbg(FYI, "invalid lease key, resending request without lease");
1060  		rc = smb2_compound_op(xid, tcon, cifs_sb, name, &oparms,
1061  				      NULL, &(int){SMB2_OP_DELETE}, 1,
1062  				      NULL, NULL, NULL, NULL);
1063  	}
1064  	return rc;
1065  }
1066  
1067  static int smb2_set_path_attr(const unsigned int xid, struct cifs_tcon *tcon,
1068  			      const char *from_name, const char *to_name,
1069  			      struct cifs_sb_info *cifs_sb,
1070  			      __u32 create_options, __u32 access,
1071  			      int command, struct cifsFileInfo *cfile,
1072  				  struct dentry *dentry)
1073  {
1074  	struct cifs_open_parms oparms;
1075  	struct kvec in_iov;
1076  	__le16 *smb2_to_name = NULL;
1077  	int rc;
1078  
1079  	smb2_to_name = cifs_convert_path_to_utf16(to_name, cifs_sb);
1080  	if (smb2_to_name == NULL) {
1081  		rc = -ENOMEM;
1082  		goto smb2_rename_path;
1083  	}
1084  	in_iov.iov_base = smb2_to_name;
1085  	in_iov.iov_len = 2 * UniStrnlen((wchar_t *)smb2_to_name, PATH_MAX);
1086  	oparms = CIFS_OPARMS(cifs_sb, tcon, from_name, access, FILE_OPEN,
1087  			     create_options, ACL_NO_MODE);
1088  	rc = smb2_compound_op(xid, tcon, cifs_sb, from_name,
1089  			      &oparms, &in_iov, &command, 1,
1090  			      cfile, NULL, NULL, dentry);
1091  smb2_rename_path:
1092  	kfree(smb2_to_name);
1093  	return rc;
1094  }
1095  
1096  int smb2_rename_path(const unsigned int xid,
1097  		     struct cifs_tcon *tcon,
1098  		     struct dentry *source_dentry,
1099  		     const char *from_name, const char *to_name,
1100  		     struct cifs_sb_info *cifs_sb)
1101  {
1102  	struct cifsFileInfo *cfile;
1103  	__u32 co = file_create_options(source_dentry);
1104  
1105  	drop_cached_dir_by_name(xid, tcon, from_name, cifs_sb);
1106  	cifs_get_writable_path(tcon, from_name, FIND_WR_WITH_DELETE, &cfile);
1107  
1108  	int rc = smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb,
1109  				  co, DELETE, SMB2_OP_RENAME, cfile, source_dentry);
1110  	if (rc == -EINVAL) {
1111  		cifs_dbg(FYI, "invalid lease key, resending request without lease");
1112  		cifs_get_writable_path(tcon, from_name,
1113  				       FIND_WR_WITH_DELETE, &cfile);
1114  		rc = smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb,
1115  				  co, DELETE, SMB2_OP_RENAME, cfile, NULL);
1116  	}
1117  	return rc;
1118  }
1119  
1120  int smb2_create_hardlink(const unsigned int xid,
1121  			 struct cifs_tcon *tcon,
1122  			 struct dentry *source_dentry,
1123  			 const char *from_name, const char *to_name,
1124  			 struct cifs_sb_info *cifs_sb)
1125  {
1126  	__u32 co = file_create_options(source_dentry);
1127  
1128  	return smb2_set_path_attr(xid, tcon, from_name, to_name,
1129  				  cifs_sb, co, FILE_READ_ATTRIBUTES,
1130  				  SMB2_OP_HARDLINK, NULL, NULL);
1131  }
1132  
1133  int
1134  smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon,
1135  		   const char *full_path, __u64 size,
1136  		   struct cifs_sb_info *cifs_sb, bool set_alloc,
1137  		   struct dentry *dentry)
1138  {
1139  	struct cifs_open_parms oparms;
1140  	struct cifsFileInfo *cfile;
1141  	struct kvec in_iov;
1142  	__le64 eof = cpu_to_le64(size);
1143  	int rc;
1144  
1145  	in_iov.iov_base = &eof;
1146  	in_iov.iov_len = sizeof(eof);
1147  	cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile);
1148  
1149  	oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, FILE_WRITE_DATA,
1150  			     FILE_OPEN, 0, ACL_NO_MODE);
1151  	rc = smb2_compound_op(xid, tcon, cifs_sb,
1152  			      full_path, &oparms, &in_iov,
1153  			      &(int){SMB2_OP_SET_EOF}, 1,
1154  			      cfile, NULL, NULL, dentry);
1155  	if (rc == -EINVAL) {
1156  		cifs_dbg(FYI, "invalid lease key, resending request without lease");
1157  		cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile);
1158  		rc = smb2_compound_op(xid, tcon, cifs_sb,
1159  				      full_path, &oparms, &in_iov,
1160  				      &(int){SMB2_OP_SET_EOF}, 1,
1161  				      cfile, NULL, NULL, NULL);
1162  	}
1163  	return rc;
1164  }
1165  
1166  int
1167  smb2_set_file_info(struct inode *inode, const char *full_path,
1168  		   FILE_BASIC_INFO *buf, const unsigned int xid)
1169  {
1170  	struct cifs_open_parms oparms;
1171  	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1172  	struct tcon_link *tlink;
1173  	struct cifs_tcon *tcon;
1174  	struct cifsFileInfo *cfile;
1175  	struct kvec in_iov = { .iov_base = buf, .iov_len = sizeof(*buf), };
1176  	int rc;
1177  
1178  	if ((buf->CreationTime == 0) && (buf->LastAccessTime == 0) &&
1179  	    (buf->LastWriteTime == 0) && (buf->ChangeTime == 0) &&
1180  	    (buf->Attributes == 0))
1181  		return 0; /* would be a no op, no sense sending this */
1182  
1183  	tlink = cifs_sb_tlink(cifs_sb);
1184  	if (IS_ERR(tlink))
1185  		return PTR_ERR(tlink);
1186  	tcon = tlink_tcon(tlink);
1187  
1188  	cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile);
1189  	oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, FILE_WRITE_ATTRIBUTES,
1190  			     FILE_OPEN, 0, ACL_NO_MODE);
1191  	rc = smb2_compound_op(xid, tcon, cifs_sb,
1192  			      full_path, &oparms, &in_iov,
1193  			      &(int){SMB2_OP_SET_INFO}, 1,
1194  			      cfile, NULL, NULL, NULL);
1195  	cifs_put_tlink(tlink);
1196  	return rc;
1197  }
1198  
1199  struct inode *smb2_get_reparse_inode(struct cifs_open_info_data *data,
1200  				     struct super_block *sb,
1201  				     const unsigned int xid,
1202  				     struct cifs_tcon *tcon,
1203  				     const char *full_path,
1204  				     bool directory,
1205  				     struct kvec *reparse_iov,
1206  				     struct kvec *xattr_iov)
1207  {
1208  	struct cifs_open_parms oparms;
1209  	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
1210  	struct cifsFileInfo *cfile;
1211  	struct inode *new = NULL;
1212  	int out_buftype[4] = {};
1213  	struct kvec out_iov[4] = {};
1214  	struct kvec in_iov[2];
1215  	int cmds[2];
1216  	int rc;
1217  	int i;
1218  
1219  	oparms = CIFS_OPARMS(cifs_sb, tcon, full_path,
1220  			     SYNCHRONIZE | DELETE |
1221  			     FILE_READ_ATTRIBUTES |
1222  			     FILE_WRITE_ATTRIBUTES,
1223  			     FILE_CREATE,
1224  			     (directory ? CREATE_NOT_FILE : CREATE_NOT_DIR) | OPEN_REPARSE_POINT,
1225  			     ACL_NO_MODE);
1226  	if (xattr_iov)
1227  		oparms.ea_cctx = xattr_iov;
1228  
1229  	cmds[0] = SMB2_OP_SET_REPARSE;
1230  	in_iov[0] = *reparse_iov;
1231  	in_iov[1].iov_base = data;
1232  	in_iov[1].iov_len = sizeof(*data);
1233  
1234  	if (tcon->posix_extensions) {
1235  		cmds[1] = SMB2_OP_POSIX_QUERY_INFO;
1236  		cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile);
1237  		rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms,
1238  				      in_iov, cmds, 2, cfile, out_iov, out_buftype, NULL);
1239  		if (!rc) {
1240  			rc = smb311_posix_get_inode_info(&new, full_path,
1241  							 data, sb, xid);
1242  		}
1243  	} else {
1244  		cmds[1] = SMB2_OP_QUERY_INFO;
1245  		cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile);
1246  		rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms,
1247  				      in_iov, cmds, 2, cfile, out_iov, out_buftype, NULL);
1248  		if (!rc) {
1249  			rc = cifs_get_inode_info(&new, full_path,
1250  						 data, sb, xid, NULL);
1251  		}
1252  	}
1253  
1254  
1255  	/*
1256  	 * If CREATE was successful but SMB2_OP_SET_REPARSE failed then
1257  	 * remove the intermediate object created by CREATE. Otherwise
1258  	 * empty object stay on the server when reparse call failed.
1259  	 */
1260  	if (rc &&
1261  	    out_iov[0].iov_base != NULL && out_buftype[0] != CIFS_NO_BUFFER &&
1262  	    ((struct smb2_hdr *)out_iov[0].iov_base)->Status == STATUS_SUCCESS &&
1263  	    (out_iov[1].iov_base == NULL || out_buftype[1] == CIFS_NO_BUFFER ||
1264  	     ((struct smb2_hdr *)out_iov[1].iov_base)->Status != STATUS_SUCCESS))
1265  		smb2_unlink(xid, tcon, full_path, cifs_sb, NULL);
1266  
1267  	for (i = 0; i < ARRAY_SIZE(out_buftype); i++)
1268  		free_rsp_buf(out_buftype[i], out_iov[i].iov_base);
1269  
1270  	return rc ? ERR_PTR(rc) : new;
1271  }
1272  
1273  int smb2_query_reparse_point(const unsigned int xid,
1274  			     struct cifs_tcon *tcon,
1275  			     struct cifs_sb_info *cifs_sb,
1276  			     const char *full_path,
1277  			     u32 *tag, struct kvec *rsp,
1278  			     int *rsp_buftype)
1279  {
1280  	struct cifs_open_parms oparms;
1281  	struct cifs_open_info_data data = {};
1282  	struct cifsFileInfo *cfile;
1283  	struct kvec in_iov = { .iov_base = &data, .iov_len = sizeof(data), };
1284  	int rc;
1285  
1286  	cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);
1287  
1288  	cifs_get_readable_path(tcon, full_path, &cfile);
1289  	oparms = CIFS_OPARMS(cifs_sb, tcon, full_path,
1290  			     FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE,
1291  			     FILE_OPEN, OPEN_REPARSE_POINT, ACL_NO_MODE);
1292  	rc = smb2_compound_op(xid, tcon, cifs_sb,
1293  			      full_path, &oparms, &in_iov,
1294  			      &(int){SMB2_OP_GET_REPARSE}, 1,
1295  			      cfile, NULL, NULL, NULL);
1296  	if (rc)
1297  		goto out;
1298  
1299  	*tag = data.reparse.tag;
1300  	*rsp = data.reparse.io.iov;
1301  	*rsp_buftype = data.reparse.io.buftype;
1302  	memset(&data.reparse.io.iov, 0, sizeof(data.reparse.io.iov));
1303  	data.reparse.io.buftype = CIFS_NO_BUFFER;
1304  out:
1305  	cifs_free_open_info(&data);
1306  	return rc;
1307  }
1308