cifssmb.c revision 76a3c92e
1// SPDX-License-Identifier: LGPL-2.1
2/*
3 *   fs/cifs/cifssmb.c
4 *
5 *   Copyright (C) International Business Machines  Corp., 2002,2010
6 *   Author(s): Steve French (sfrench@us.ibm.com)
7 *
8 *   Contains the routines for constructing the SMB PDUs themselves
9 *
10 */
11
12 /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c   */
13 /* These are mostly routines that operate on a pathname, or on a tree id     */
14 /* (mounted volume), but there are eight handle based routines which must be */
15 /* treated slightly differently for reconnection purposes since we never     */
16 /* want to reuse a stale file handle and only the caller knows the file info */
17
18#include <linux/fs.h>
19#include <linux/kernel.h>
20#include <linux/vfs.h>
21#include <linux/slab.h>
22#include <linux/posix_acl_xattr.h>
23#include <linux/pagemap.h>
24#include <linux/swap.h>
25#include <linux/task_io_accounting_ops.h>
26#include <linux/uaccess.h>
27#include "cifspdu.h"
28#include "cifsglob.h"
29#include "cifsacl.h"
30#include "cifsproto.h"
31#include "cifs_unicode.h"
32#include "cifs_debug.h"
33#include "smb2proto.h"
34#include "fscache.h"
35#include "smbdirect.h"
36#ifdef CONFIG_CIFS_DFS_UPCALL
37#include "dfs_cache.h"
38#endif
39
40#ifdef CONFIG_CIFS_POSIX
41static struct {
42	int index;
43	char *name;
44} protocols[] = {
45	{CIFS_PROT, "\2NT LM 0.12"},
46	{POSIX_PROT, "\2POSIX 2"},
47	{BAD_PROT, "\2"}
48};
49#else
50static struct {
51	int index;
52	char *name;
53} protocols[] = {
54	{CIFS_PROT, "\2NT LM 0.12"},
55	{BAD_PROT, "\2"}
56};
57#endif
58
59/* define the number of elements in the cifs dialect array */
60#ifdef CONFIG_CIFS_POSIX
61#define CIFS_NUM_PROT 2
62#else /* not posix */
63#define CIFS_NUM_PROT 1
64#endif /* CIFS_POSIX */
65
66/*
67 * Mark as invalid, all open files on tree connections since they
68 * were closed when session to server was lost.
69 */
70void
71cifs_mark_open_files_invalid(struct cifs_tcon *tcon)
72{
73	struct cifsFileInfo *open_file = NULL;
74	struct list_head *tmp;
75	struct list_head *tmp1;
76
77	/* list all files open on tree connection and mark them invalid */
78	spin_lock(&tcon->open_file_lock);
79	list_for_each_safe(tmp, tmp1, &tcon->openFileList) {
80		open_file = list_entry(tmp, struct cifsFileInfo, tlist);
81		open_file->invalidHandle = true;
82		open_file->oplock_break_cancelled = true;
83	}
84	spin_unlock(&tcon->open_file_lock);
85
86	mutex_lock(&tcon->crfid.fid_mutex);
87	tcon->crfid.is_valid = false;
88	/* cached handle is not valid, so SMB2_CLOSE won't be sent below */
89	close_cached_dir_lease_locked(&tcon->crfid);
90	memset(tcon->crfid.fid, 0, sizeof(struct cifs_fid));
91	mutex_unlock(&tcon->crfid.fid_mutex);
92
93	/*
94	 * BB Add call to invalidate_inodes(sb) for all superblocks mounted
95	 * to this tcon.
96	 */
97}
98
99/* reconnect the socket, tcon, and smb session if needed */
100static int
101cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
102{
103	int rc;
104	struct cifs_ses *ses;
105	struct TCP_Server_Info *server;
106	struct nls_table *nls_codepage;
107	int retries;
108
109	/*
110	 * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
111	 * tcp and smb session status done differently for those three - in the
112	 * calling routine
113	 */
114	if (!tcon)
115		return 0;
116
117	ses = tcon->ses;
118	server = ses->server;
119
120	/*
121	 * only tree disconnect, open, and write, (and ulogoff which does not
122	 * have tcon) are allowed as we start force umount
123	 */
124	if (tcon->tidStatus == CifsExiting) {
125		if (smb_command != SMB_COM_WRITE_ANDX &&
126		    smb_command != SMB_COM_OPEN_ANDX &&
127		    smb_command != SMB_COM_TREE_DISCONNECT) {
128			cifs_dbg(FYI, "can not send cmd %d while umounting\n",
129				 smb_command);
130			return -ENODEV;
131		}
132	}
133
134	retries = server->nr_targets;
135
136	/*
137	 * Give demultiplex thread up to 10 seconds to each target available for
138	 * reconnect -- should be greater than cifs socket timeout which is 7
139	 * seconds.
140	 */
141	while (server->tcpStatus == CifsNeedReconnect) {
142		rc = wait_event_interruptible_timeout(server->response_q,
143						      (server->tcpStatus != CifsNeedReconnect),
144						      10 * HZ);
145		if (rc < 0) {
146			cifs_dbg(FYI, "%s: aborting reconnect due to a received signal by the process\n",
147				 __func__);
148			return -ERESTARTSYS;
149		}
150
151		/* are we still trying to reconnect? */
152		if (server->tcpStatus != CifsNeedReconnect)
153			break;
154
155		if (retries && --retries)
156			continue;
157
158		/*
159		 * on "soft" mounts we wait once. Hard mounts keep
160		 * retrying until process is killed or server comes
161		 * back on-line
162		 */
163		if (!tcon->retry) {
164			cifs_dbg(FYI, "gave up waiting on reconnect in smb_init\n");
165			return -EHOSTDOWN;
166		}
167		retries = server->nr_targets;
168	}
169
170	if (!ses->need_reconnect && !tcon->need_reconnect)
171		return 0;
172
173	nls_codepage = load_nls_default();
174
175	/*
176	 * need to prevent multiple threads trying to simultaneously
177	 * reconnect the same SMB session
178	 */
179	mutex_lock(&ses->session_mutex);
180
181	/*
182	 * Recheck after acquire mutex. If another thread is negotiating
183	 * and the server never sends an answer the socket will be closed
184	 * and tcpStatus set to reconnect.
185	 */
186	if (server->tcpStatus == CifsNeedReconnect) {
187		rc = -EHOSTDOWN;
188		mutex_unlock(&ses->session_mutex);
189		goto out;
190	}
191
192	rc = cifs_negotiate_protocol(0, ses);
193	if (rc == 0 && ses->need_reconnect)
194		rc = cifs_setup_session(0, ses, nls_codepage);
195
196	/* do we need to reconnect tcon? */
197	if (rc || !tcon->need_reconnect) {
198		mutex_unlock(&ses->session_mutex);
199		goto out;
200	}
201
202	cifs_mark_open_files_invalid(tcon);
203	rc = cifs_tree_connect(0, tcon, nls_codepage);
204	mutex_unlock(&ses->session_mutex);
205	cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc);
206
207	if (rc) {
208		pr_warn_once("reconnect tcon failed rc = %d\n", rc);
209		goto out;
210	}
211
212	atomic_inc(&tconInfoReconnectCount);
213
214	/* tell server Unix caps we support */
215	if (cap_unix(ses))
216		reset_cifs_unix_caps(0, tcon, NULL, NULL);
217
218	/*
219	 * Removed call to reopen open files here. It is safer (and faster) to
220	 * reopen files one at a time as needed in read and write.
221	 *
222	 * FIXME: what about file locks? don't we need to reclaim them ASAP?
223	 */
224
225out:
226	/*
227	 * Check if handle based operation so we know whether we can continue
228	 * or not without returning to caller to reset file handle
229	 */
230	switch (smb_command) {
231	case SMB_COM_READ_ANDX:
232	case SMB_COM_WRITE_ANDX:
233	case SMB_COM_CLOSE:
234	case SMB_COM_FIND_CLOSE2:
235	case SMB_COM_LOCKING_ANDX:
236		rc = -EAGAIN;
237	}
238
239	unload_nls(nls_codepage);
240	return rc;
241}
242
243/* Allocate and return pointer to an SMB request buffer, and set basic
244   SMB information in the SMB header.  If the return code is zero, this
245   function must have filled in request_buf pointer */
246static int
247small_smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
248		void **request_buf)
249{
250	int rc;
251
252	rc = cifs_reconnect_tcon(tcon, smb_command);
253	if (rc)
254		return rc;
255
256	*request_buf = cifs_small_buf_get();
257	if (*request_buf == NULL) {
258		/* BB should we add a retry in here if not a writepage? */
259		return -ENOMEM;
260	}
261
262	header_assemble((struct smb_hdr *) *request_buf, smb_command,
263			tcon, wct);
264
265	if (tcon != NULL)
266		cifs_stats_inc(&tcon->num_smbs_sent);
267
268	return 0;
269}
270
271int
272small_smb_init_no_tc(const int smb_command, const int wct,
273		     struct cifs_ses *ses, void **request_buf)
274{
275	int rc;
276	struct smb_hdr *buffer;
277
278	rc = small_smb_init(smb_command, wct, NULL, request_buf);
279	if (rc)
280		return rc;
281
282	buffer = (struct smb_hdr *)*request_buf;
283	buffer->Mid = get_next_mid(ses->server);
284	if (ses->capabilities & CAP_UNICODE)
285		buffer->Flags2 |= SMBFLG2_UNICODE;
286	if (ses->capabilities & CAP_STATUS32)
287		buffer->Flags2 |= SMBFLG2_ERR_STATUS;
288
289	/* uid, tid can stay at zero as set in header assemble */
290
291	/* BB add support for turning on the signing when
292	this function is used after 1st of session setup requests */
293
294	return rc;
295}
296
297/* If the return code is zero, this function must fill in request_buf pointer */
298static int
299__smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
300			void **request_buf, void **response_buf)
301{
302	*request_buf = cifs_buf_get();
303	if (*request_buf == NULL) {
304		/* BB should we add a retry in here if not a writepage? */
305		return -ENOMEM;
306	}
307    /* Although the original thought was we needed the response buf for  */
308    /* potential retries of smb operations it turns out we can determine */
309    /* from the mid flags when the request buffer can be resent without  */
310    /* having to use a second distinct buffer for the response */
311	if (response_buf)
312		*response_buf = *request_buf;
313
314	header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
315			wct);
316
317	if (tcon != NULL)
318		cifs_stats_inc(&tcon->num_smbs_sent);
319
320	return 0;
321}
322
323/* If the return code is zero, this function must fill in request_buf pointer */
324static int
325smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
326	 void **request_buf, void **response_buf)
327{
328	int rc;
329
330	rc = cifs_reconnect_tcon(tcon, smb_command);
331	if (rc)
332		return rc;
333
334	return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
335}
336
337static int
338smb_init_no_reconnect(int smb_command, int wct, struct cifs_tcon *tcon,
339			void **request_buf, void **response_buf)
340{
341	if (tcon->ses->need_reconnect || tcon->need_reconnect)
342		return -EHOSTDOWN;
343
344	return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
345}
346
347static int validate_t2(struct smb_t2_rsp *pSMB)
348{
349	unsigned int total_size;
350
351	/* check for plausible wct */
352	if (pSMB->hdr.WordCount < 10)
353		goto vt2_err;
354
355	/* check for parm and data offset going beyond end of smb */
356	if (get_unaligned_le16(&pSMB->t2_rsp.ParameterOffset) > 1024 ||
357	    get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024)
358		goto vt2_err;
359
360	total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount);
361	if (total_size >= 512)
362		goto vt2_err;
363
364	/* check that bcc is at least as big as parms + data, and that it is
365	 * less than negotiated smb buffer
366	 */
367	total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount);
368	if (total_size > get_bcc(&pSMB->hdr) ||
369	    total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)
370		goto vt2_err;
371
372	return 0;
373vt2_err:
374	cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
375		sizeof(struct smb_t2_rsp) + 16);
376	return -EINVAL;
377}
378
379static int
380decode_ext_sec_blob(struct cifs_ses *ses, NEGOTIATE_RSP *pSMBr)
381{
382	int	rc = 0;
383	u16	count;
384	char	*guid = pSMBr->u.extended_response.GUID;
385	struct TCP_Server_Info *server = ses->server;
386
387	count = get_bcc(&pSMBr->hdr);
388	if (count < SMB1_CLIENT_GUID_SIZE)
389		return -EIO;
390
391	spin_lock(&cifs_tcp_ses_lock);
392	if (server->srv_count > 1) {
393		spin_unlock(&cifs_tcp_ses_lock);
394		if (memcmp(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE) != 0) {
395			cifs_dbg(FYI, "server UID changed\n");
396			memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);
397		}
398	} else {
399		spin_unlock(&cifs_tcp_ses_lock);
400		memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);
401	}
402
403	if (count == SMB1_CLIENT_GUID_SIZE) {
404		server->sec_ntlmssp = true;
405	} else {
406		count -= SMB1_CLIENT_GUID_SIZE;
407		rc = decode_negTokenInit(
408			pSMBr->u.extended_response.SecurityBlob, count, server);
409		if (rc != 1)
410			return -EINVAL;
411	}
412
413	return 0;
414}
415
416int
417cifs_enable_signing(struct TCP_Server_Info *server, bool mnt_sign_required)
418{
419	bool srv_sign_required = server->sec_mode & server->vals->signing_required;
420	bool srv_sign_enabled = server->sec_mode & server->vals->signing_enabled;
421	bool mnt_sign_enabled = global_secflags & CIFSSEC_MAY_SIGN;
422
423	/*
424	 * Is signing required by mnt options? If not then check
425	 * global_secflags to see if it is there.
426	 */
427	if (!mnt_sign_required)
428		mnt_sign_required = ((global_secflags & CIFSSEC_MUST_SIGN) ==
429						CIFSSEC_MUST_SIGN);
430
431	/*
432	 * If signing is required then it's automatically enabled too,
433	 * otherwise, check to see if the secflags allow it.
434	 */
435	mnt_sign_enabled = mnt_sign_required ? mnt_sign_required :
436				(global_secflags & CIFSSEC_MAY_SIGN);
437
438	/* If server requires signing, does client allow it? */
439	if (srv_sign_required) {
440		if (!mnt_sign_enabled) {
441			cifs_dbg(VFS, "Server requires signing, but it's disabled in SecurityFlags!\n");
442			return -ENOTSUPP;
443		}
444		server->sign = true;
445	}
446
447	/* If client requires signing, does server allow it? */
448	if (mnt_sign_required) {
449		if (!srv_sign_enabled) {
450			cifs_dbg(VFS, "Server does not support signing!\n");
451			return -ENOTSUPP;
452		}
453		server->sign = true;
454	}
455
456	if (cifs_rdma_enabled(server) && server->sign)
457		cifs_dbg(VFS, "Signing is enabled, and RDMA read/write will be disabled\n");
458
459	return 0;
460}
461
462static bool
463should_set_ext_sec_flag(enum securityEnum sectype)
464{
465	switch (sectype) {
466	case RawNTLMSSP:
467	case Kerberos:
468		return true;
469	case Unspecified:
470		if (global_secflags &
471		    (CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_NTLMSSP))
472			return true;
473		fallthrough;
474	default:
475		return false;
476	}
477}
478
479int
480CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
481{
482	NEGOTIATE_REQ *pSMB;
483	NEGOTIATE_RSP *pSMBr;
484	int rc = 0;
485	int bytes_returned;
486	int i;
487	struct TCP_Server_Info *server = ses->server;
488	u16 count;
489
490	if (!server) {
491		WARN(1, "%s: server is NULL!\n", __func__);
492		return -EIO;
493	}
494
495	rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
496		      (void **) &pSMB, (void **) &pSMBr);
497	if (rc)
498		return rc;
499
500	pSMB->hdr.Mid = get_next_mid(server);
501	pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
502
503	if (should_set_ext_sec_flag(ses->sectype)) {
504		cifs_dbg(FYI, "Requesting extended security\n");
505		pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
506	}
507
508	count = 0;
509	/*
510	 * We know that all the name entries in the protocols array
511	 * are short (< 16 bytes anyway) and are NUL terminated.
512	 */
513	for (i = 0; i < CIFS_NUM_PROT; i++) {
514		size_t len = strlen(protocols[i].name) + 1;
515
516		memcpy(pSMB->DialectsArray+count, protocols[i].name, len);
517		count += len;
518	}
519	inc_rfc1001_len(pSMB, count);
520	pSMB->ByteCount = cpu_to_le16(count);
521
522	rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
523			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
524	if (rc != 0)
525		goto neg_err_exit;
526
527	server->dialect = le16_to_cpu(pSMBr->DialectIndex);
528	cifs_dbg(FYI, "Dialect: %d\n", server->dialect);
529	/* Check wct = 1 error case */
530	if ((pSMBr->hdr.WordCount <= 13) || (server->dialect == BAD_PROT)) {
531		/* core returns wct = 1, but we do not ask for core - otherwise
532		small wct just comes when dialect index is -1 indicating we
533		could not negotiate a common dialect */
534		rc = -EOPNOTSUPP;
535		goto neg_err_exit;
536	} else if (pSMBr->hdr.WordCount != 17) {
537		/* unknown wct */
538		rc = -EOPNOTSUPP;
539		goto neg_err_exit;
540	}
541	/* else wct == 17, NTLM or better */
542
543	server->sec_mode = pSMBr->SecurityMode;
544	if ((server->sec_mode & SECMODE_USER) == 0)
545		cifs_dbg(FYI, "share mode security\n");
546
547	/* one byte, so no need to convert this or EncryptionKeyLen from
548	   little endian */
549	server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount),
550			       cifs_max_pending);
551	set_credits(server, server->maxReq);
552	/* probably no need to store and check maxvcs */
553	server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize);
554	/* set up max_read for readpages check */
555	server->max_read = server->maxBuf;
556	server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
557	cifs_dbg(NOISY, "Max buf = %d\n", ses->server->maxBuf);
558	server->capabilities = le32_to_cpu(pSMBr->Capabilities);
559	server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
560	server->timeAdj *= 60;
561
562	if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
563		server->negflavor = CIFS_NEGFLAVOR_UNENCAP;
564		memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
565		       CIFS_CRYPTO_KEY_SIZE);
566	} else if (pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC ||
567			server->capabilities & CAP_EXTENDED_SECURITY) {
568		server->negflavor = CIFS_NEGFLAVOR_EXTENDED;
569		rc = decode_ext_sec_blob(ses, pSMBr);
570	} else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
571		rc = -EIO; /* no crypt key only if plain text pwd */
572	} else {
573		server->negflavor = CIFS_NEGFLAVOR_UNENCAP;
574		server->capabilities &= ~CAP_EXTENDED_SECURITY;
575	}
576
577	if (!rc)
578		rc = cifs_enable_signing(server, ses->sign);
579neg_err_exit:
580	cifs_buf_release(pSMB);
581
582	cifs_dbg(FYI, "negprot rc %d\n", rc);
583	return rc;
584}
585
586int
587CIFSSMBTDis(const unsigned int xid, struct cifs_tcon *tcon)
588{
589	struct smb_hdr *smb_buffer;
590	int rc = 0;
591
592	cifs_dbg(FYI, "In tree disconnect\n");
593
594	/* BB: do we need to check this? These should never be NULL. */
595	if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
596		return -EIO;
597
598	/*
599	 * No need to return error on this operation if tid invalidated and
600	 * closed on server already e.g. due to tcp session crashing. Also,
601	 * the tcon is no longer on the list, so no need to take lock before
602	 * checking this.
603	 */
604	if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
605		return 0;
606
607	rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
608			    (void **)&smb_buffer);
609	if (rc)
610		return rc;
611
612	rc = SendReceiveNoRsp(xid, tcon->ses, (char *)smb_buffer, 0);
613	cifs_small_buf_release(smb_buffer);
614	if (rc)
615		cifs_dbg(FYI, "Tree disconnect failed %d\n", rc);
616
617	/* No need to return error on this operation if tid invalidated and
618	   closed on server already e.g. due to tcp session crashing */
619	if (rc == -EAGAIN)
620		rc = 0;
621
622	return rc;
623}
624
625/*
626 * This is a no-op for now. We're not really interested in the reply, but
627 * rather in the fact that the server sent one and that server->lstrp
628 * gets updated.
629 *
630 * FIXME: maybe we should consider checking that the reply matches request?
631 */
632static void
633cifs_echo_callback(struct mid_q_entry *mid)
634{
635	struct TCP_Server_Info *server = mid->callback_data;
636	struct cifs_credits credits = { .value = 1, .instance = 0 };
637
638	DeleteMidQEntry(mid);
639	add_credits(server, &credits, CIFS_ECHO_OP);
640}
641
642int
643CIFSSMBEcho(struct TCP_Server_Info *server)
644{
645	ECHO_REQ *smb;
646	int rc = 0;
647	struct kvec iov[2];
648	struct smb_rqst rqst = { .rq_iov = iov,
649				 .rq_nvec = 2 };
650
651	cifs_dbg(FYI, "In echo request\n");
652
653	rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb);
654	if (rc)
655		return rc;
656
657	if (server->capabilities & CAP_UNICODE)
658		smb->hdr.Flags2 |= SMBFLG2_UNICODE;
659
660	/* set up echo request */
661	smb->hdr.Tid = 0xffff;
662	smb->hdr.WordCount = 1;
663	put_unaligned_le16(1, &smb->EchoCount);
664	put_bcc(1, &smb->hdr);
665	smb->Data[0] = 'a';
666	inc_rfc1001_len(smb, 3);
667
668	iov[0].iov_len = 4;
669	iov[0].iov_base = smb;
670	iov[1].iov_len = get_rfc1002_length(smb);
671	iov[1].iov_base = (char *)smb + 4;
672
673	rc = cifs_call_async(server, &rqst, NULL, cifs_echo_callback, NULL,
674			     server, CIFS_NON_BLOCKING | CIFS_ECHO_OP, NULL);
675	if (rc)
676		cifs_dbg(FYI, "Echo request failed: %d\n", rc);
677
678	cifs_small_buf_release(smb);
679
680	return rc;
681}
682
683int
684CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses)
685{
686	LOGOFF_ANDX_REQ *pSMB;
687	int rc = 0;
688
689	cifs_dbg(FYI, "In SMBLogoff for session disconnect\n");
690
691	/*
692	 * BB: do we need to check validity of ses and server? They should
693	 * always be valid since we have an active reference. If not, that
694	 * should probably be a BUG()
695	 */
696	if (!ses || !ses->server)
697		return -EIO;
698
699	mutex_lock(&ses->session_mutex);
700	if (ses->need_reconnect)
701		goto session_already_dead; /* no need to send SMBlogoff if uid
702					      already closed due to reconnect */
703	rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
704	if (rc) {
705		mutex_unlock(&ses->session_mutex);
706		return rc;
707	}
708
709	pSMB->hdr.Mid = get_next_mid(ses->server);
710
711	if (ses->server->sign)
712		pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
713
714	pSMB->hdr.Uid = ses->Suid;
715
716	pSMB->AndXCommand = 0xFF;
717	rc = SendReceiveNoRsp(xid, ses, (char *) pSMB, 0);
718	cifs_small_buf_release(pSMB);
719session_already_dead:
720	mutex_unlock(&ses->session_mutex);
721
722	/* if session dead then we do not need to do ulogoff,
723		since server closed smb session, no sense reporting
724		error */
725	if (rc == -EAGAIN)
726		rc = 0;
727	return rc;
728}
729
730int
731CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon,
732		 const char *fileName, __u16 type,
733		 const struct nls_table *nls_codepage, int remap)
734{
735	TRANSACTION2_SPI_REQ *pSMB = NULL;
736	TRANSACTION2_SPI_RSP *pSMBr = NULL;
737	struct unlink_psx_rq *pRqD;
738	int name_len;
739	int rc = 0;
740	int bytes_returned = 0;
741	__u16 params, param_offset, offset, byte_count;
742
743	cifs_dbg(FYI, "In POSIX delete\n");
744PsxDelete:
745	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
746		      (void **) &pSMBr);
747	if (rc)
748		return rc;
749
750	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
751		name_len =
752		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
753				       PATH_MAX, nls_codepage, remap);
754		name_len++;	/* trailing null */
755		name_len *= 2;
756	} else {
757		name_len = copy_path_name(pSMB->FileName, fileName);
758	}
759
760	params = 6 + name_len;
761	pSMB->MaxParameterCount = cpu_to_le16(2);
762	pSMB->MaxDataCount = 0; /* BB double check this with jra */
763	pSMB->MaxSetupCount = 0;
764	pSMB->Reserved = 0;
765	pSMB->Flags = 0;
766	pSMB->Timeout = 0;
767	pSMB->Reserved2 = 0;
768	param_offset = offsetof(struct smb_com_transaction2_spi_req,
769				InformationLevel) - 4;
770	offset = param_offset + params;
771
772	/* Setup pointer to Request Data (inode type).
773	 * Note that SMB offsets are from the beginning of SMB which is 4 bytes
774	 * in, after RFC1001 field
775	 */
776	pRqD = (struct unlink_psx_rq *)((char *)(pSMB) + offset + 4);
777	pRqD->type = cpu_to_le16(type);
778	pSMB->ParameterOffset = cpu_to_le16(param_offset);
779	pSMB->DataOffset = cpu_to_le16(offset);
780	pSMB->SetupCount = 1;
781	pSMB->Reserved3 = 0;
782	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
783	byte_count = 3 /* pad */  + params + sizeof(struct unlink_psx_rq);
784
785	pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
786	pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
787	pSMB->ParameterCount = cpu_to_le16(params);
788	pSMB->TotalParameterCount = pSMB->ParameterCount;
789	pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
790	pSMB->Reserved4 = 0;
791	inc_rfc1001_len(pSMB, byte_count);
792	pSMB->ByteCount = cpu_to_le16(byte_count);
793	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
794			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
795	if (rc)
796		cifs_dbg(FYI, "Posix delete returned %d\n", rc);
797	cifs_buf_release(pSMB);
798
799	cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
800
801	if (rc == -EAGAIN)
802		goto PsxDelete;
803
804	return rc;
805}
806
807int
808CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
809	       struct cifs_sb_info *cifs_sb)
810{
811	DELETE_FILE_REQ *pSMB = NULL;
812	DELETE_FILE_RSP *pSMBr = NULL;
813	int rc = 0;
814	int bytes_returned;
815	int name_len;
816	int remap = cifs_remap(cifs_sb);
817
818DelFileRetry:
819	rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
820		      (void **) &pSMBr);
821	if (rc)
822		return rc;
823
824	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
825		name_len = cifsConvertToUTF16((__le16 *) pSMB->fileName, name,
826					      PATH_MAX, cifs_sb->local_nls,
827					      remap);
828		name_len++;	/* trailing null */
829		name_len *= 2;
830	} else {
831		name_len = copy_path_name(pSMB->fileName, name);
832	}
833	pSMB->SearchAttributes =
834	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
835	pSMB->BufferFormat = 0x04;
836	inc_rfc1001_len(pSMB, name_len + 1);
837	pSMB->ByteCount = cpu_to_le16(name_len + 1);
838	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
839			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
840	cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
841	if (rc)
842		cifs_dbg(FYI, "Error in RMFile = %d\n", rc);
843
844	cifs_buf_release(pSMB);
845	if (rc == -EAGAIN)
846		goto DelFileRetry;
847
848	return rc;
849}
850
851int
852CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
853	     struct cifs_sb_info *cifs_sb)
854{
855	DELETE_DIRECTORY_REQ *pSMB = NULL;
856	DELETE_DIRECTORY_RSP *pSMBr = NULL;
857	int rc = 0;
858	int bytes_returned;
859	int name_len;
860	int remap = cifs_remap(cifs_sb);
861
862	cifs_dbg(FYI, "In CIFSSMBRmDir\n");
863RmDirRetry:
864	rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
865		      (void **) &pSMBr);
866	if (rc)
867		return rc;
868
869	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
870		name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
871					      PATH_MAX, cifs_sb->local_nls,
872					      remap);
873		name_len++;	/* trailing null */
874		name_len *= 2;
875	} else {
876		name_len = copy_path_name(pSMB->DirName, name);
877	}
878
879	pSMB->BufferFormat = 0x04;
880	inc_rfc1001_len(pSMB, name_len + 1);
881	pSMB->ByteCount = cpu_to_le16(name_len + 1);
882	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
883			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
884	cifs_stats_inc(&tcon->stats.cifs_stats.num_rmdirs);
885	if (rc)
886		cifs_dbg(FYI, "Error in RMDir = %d\n", rc);
887
888	cifs_buf_release(pSMB);
889	if (rc == -EAGAIN)
890		goto RmDirRetry;
891	return rc;
892}
893
894int
895CIFSSMBMkDir(const unsigned int xid, struct inode *inode, umode_t mode,
896	     struct cifs_tcon *tcon, const char *name,
897	     struct cifs_sb_info *cifs_sb)
898{
899	int rc = 0;
900	CREATE_DIRECTORY_REQ *pSMB = NULL;
901	CREATE_DIRECTORY_RSP *pSMBr = NULL;
902	int bytes_returned;
903	int name_len;
904	int remap = cifs_remap(cifs_sb);
905
906	cifs_dbg(FYI, "In CIFSSMBMkDir\n");
907MkDirRetry:
908	rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
909		      (void **) &pSMBr);
910	if (rc)
911		return rc;
912
913	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
914		name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
915					      PATH_MAX, cifs_sb->local_nls,
916					      remap);
917		name_len++;	/* trailing null */
918		name_len *= 2;
919	} else {
920		name_len = copy_path_name(pSMB->DirName, name);
921	}
922
923	pSMB->BufferFormat = 0x04;
924	inc_rfc1001_len(pSMB, name_len + 1);
925	pSMB->ByteCount = cpu_to_le16(name_len + 1);
926	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
927			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
928	cifs_stats_inc(&tcon->stats.cifs_stats.num_mkdirs);
929	if (rc)
930		cifs_dbg(FYI, "Error in Mkdir = %d\n", rc);
931
932	cifs_buf_release(pSMB);
933	if (rc == -EAGAIN)
934		goto MkDirRetry;
935	return rc;
936}
937
938int
939CIFSPOSIXCreate(const unsigned int xid, struct cifs_tcon *tcon,
940		__u32 posix_flags, __u64 mode, __u16 *netfid,
941		FILE_UNIX_BASIC_INFO *pRetData, __u32 *pOplock,
942		const char *name, const struct nls_table *nls_codepage,
943		int remap)
944{
945	TRANSACTION2_SPI_REQ *pSMB = NULL;
946	TRANSACTION2_SPI_RSP *pSMBr = NULL;
947	int name_len;
948	int rc = 0;
949	int bytes_returned = 0;
950	__u16 params, param_offset, offset, byte_count, count;
951	OPEN_PSX_REQ *pdata;
952	OPEN_PSX_RSP *psx_rsp;
953
954	cifs_dbg(FYI, "In POSIX Create\n");
955PsxCreat:
956	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
957		      (void **) &pSMBr);
958	if (rc)
959		return rc;
960
961	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
962		name_len =
963		    cifsConvertToUTF16((__le16 *) pSMB->FileName, name,
964				       PATH_MAX, nls_codepage, remap);
965		name_len++;	/* trailing null */
966		name_len *= 2;
967	} else {
968		name_len = copy_path_name(pSMB->FileName, name);
969	}
970
971	params = 6 + name_len;
972	count = sizeof(OPEN_PSX_REQ);
973	pSMB->MaxParameterCount = cpu_to_le16(2);
974	pSMB->MaxDataCount = cpu_to_le16(1000);	/* large enough */
975	pSMB->MaxSetupCount = 0;
976	pSMB->Reserved = 0;
977	pSMB->Flags = 0;
978	pSMB->Timeout = 0;
979	pSMB->Reserved2 = 0;
980	param_offset = offsetof(struct smb_com_transaction2_spi_req,
981				InformationLevel) - 4;
982	offset = param_offset + params;
983	/* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
984	pdata = (OPEN_PSX_REQ *)((char *)(pSMB) + offset + 4);
985	pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
986	pdata->Permissions = cpu_to_le64(mode);
987	pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
988	pdata->OpenFlags =  cpu_to_le32(*pOplock);
989	pSMB->ParameterOffset = cpu_to_le16(param_offset);
990	pSMB->DataOffset = cpu_to_le16(offset);
991	pSMB->SetupCount = 1;
992	pSMB->Reserved3 = 0;
993	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
994	byte_count = 3 /* pad */  + params + count;
995
996	pSMB->DataCount = cpu_to_le16(count);
997	pSMB->ParameterCount = cpu_to_le16(params);
998	pSMB->TotalDataCount = pSMB->DataCount;
999	pSMB->TotalParameterCount = pSMB->ParameterCount;
1000	pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1001	pSMB->Reserved4 = 0;
1002	inc_rfc1001_len(pSMB, byte_count);
1003	pSMB->ByteCount = cpu_to_le16(byte_count);
1004	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1005			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1006	if (rc) {
1007		cifs_dbg(FYI, "Posix create returned %d\n", rc);
1008		goto psx_create_err;
1009	}
1010
1011	cifs_dbg(FYI, "copying inode info\n");
1012	rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1013
1014	if (rc || get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)) {
1015		rc = -EIO;	/* bad smb */
1016		goto psx_create_err;
1017	}
1018
1019	/* copy return information to pRetData */
1020	psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1021			+ le16_to_cpu(pSMBr->t2.DataOffset));
1022
1023	*pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1024	if (netfid)
1025		*netfid = psx_rsp->Fid;   /* cifs fid stays in le */
1026	/* Let caller know file was created so we can set the mode. */
1027	/* Do we care about the CreateAction in any other cases? */
1028	if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1029		*pOplock |= CIFS_CREATE_ACTION;
1030	/* check to make sure response data is there */
1031	if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1032		pRetData->Type = cpu_to_le32(-1); /* unknown */
1033		cifs_dbg(NOISY, "unknown type\n");
1034	} else {
1035		if (get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)
1036					+ sizeof(FILE_UNIX_BASIC_INFO)) {
1037			cifs_dbg(VFS, "Open response data too small\n");
1038			pRetData->Type = cpu_to_le32(-1);
1039			goto psx_create_err;
1040		}
1041		memcpy((char *) pRetData,
1042			(char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1043			sizeof(FILE_UNIX_BASIC_INFO));
1044	}
1045
1046psx_create_err:
1047	cifs_buf_release(pSMB);
1048
1049	if (posix_flags & SMB_O_DIRECTORY)
1050		cifs_stats_inc(&tcon->stats.cifs_stats.num_posixmkdirs);
1051	else
1052		cifs_stats_inc(&tcon->stats.cifs_stats.num_posixopens);
1053
1054	if (rc == -EAGAIN)
1055		goto PsxCreat;
1056
1057	return rc;
1058}
1059
1060static __u16 convert_disposition(int disposition)
1061{
1062	__u16 ofun = 0;
1063
1064	switch (disposition) {
1065		case FILE_SUPERSEDE:
1066			ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1067			break;
1068		case FILE_OPEN:
1069			ofun = SMBOPEN_OAPPEND;
1070			break;
1071		case FILE_CREATE:
1072			ofun = SMBOPEN_OCREATE;
1073			break;
1074		case FILE_OPEN_IF:
1075			ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1076			break;
1077		case FILE_OVERWRITE:
1078			ofun = SMBOPEN_OTRUNC;
1079			break;
1080		case FILE_OVERWRITE_IF:
1081			ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1082			break;
1083		default:
1084			cifs_dbg(FYI, "unknown disposition %d\n", disposition);
1085			ofun =  SMBOPEN_OAPPEND; /* regular open */
1086	}
1087	return ofun;
1088}
1089
1090static int
1091access_flags_to_smbopen_mode(const int access_flags)
1092{
1093	int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1094
1095	if (masked_flags == GENERIC_READ)
1096		return SMBOPEN_READ;
1097	else if (masked_flags == GENERIC_WRITE)
1098		return SMBOPEN_WRITE;
1099
1100	/* just go for read/write */
1101	return SMBOPEN_READWRITE;
1102}
1103
1104int
1105SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon,
1106	    const char *fileName, const int openDisposition,
1107	    const int access_flags, const int create_options, __u16 *netfid,
1108	    int *pOplock, FILE_ALL_INFO *pfile_info,
1109	    const struct nls_table *nls_codepage, int remap)
1110{
1111	int rc;
1112	OPENX_REQ *pSMB = NULL;
1113	OPENX_RSP *pSMBr = NULL;
1114	int bytes_returned;
1115	int name_len;
1116	__u16 count;
1117
1118OldOpenRetry:
1119	rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1120		      (void **) &pSMBr);
1121	if (rc)
1122		return rc;
1123
1124	pSMB->AndXCommand = 0xFF;       /* none */
1125
1126	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1127		count = 1;      /* account for one byte pad to word boundary */
1128		name_len =
1129		   cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
1130				      fileName, PATH_MAX, nls_codepage, remap);
1131		name_len++;     /* trailing null */
1132		name_len *= 2;
1133	} else {
1134		count = 0;      /* no pad */
1135		name_len = copy_path_name(pSMB->fileName, fileName);
1136	}
1137	if (*pOplock & REQ_OPLOCK)
1138		pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1139	else if (*pOplock & REQ_BATCHOPLOCK)
1140		pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1141
1142	pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1143	pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1144	pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1145	/* set file as system file if special file such
1146	   as fifo and server expecting SFU style and
1147	   no Unix extensions */
1148
1149	if (create_options & CREATE_OPTION_SPECIAL)
1150		pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1151	else /* BB FIXME BB */
1152		pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1153
1154	if (create_options & CREATE_OPTION_READONLY)
1155		pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1156
1157	/* BB FIXME BB */
1158/*	pSMB->CreateOptions = cpu_to_le32(create_options &
1159						 CREATE_OPTIONS_MASK); */
1160	/* BB FIXME END BB */
1161
1162	pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1163	pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1164	count += name_len;
1165	inc_rfc1001_len(pSMB, count);
1166
1167	pSMB->ByteCount = cpu_to_le16(count);
1168	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1169			(struct smb_hdr *)pSMBr, &bytes_returned, 0);
1170	cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1171	if (rc) {
1172		cifs_dbg(FYI, "Error in Open = %d\n", rc);
1173	} else {
1174	/* BB verify if wct == 15 */
1175
1176/*		*pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1177
1178		*netfid = pSMBr->Fid;   /* cifs fid stays in le */
1179		/* Let caller know file was created so we can set the mode. */
1180		/* Do we care about the CreateAction in any other cases? */
1181	/* BB FIXME BB */
1182/*		if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1183			*pOplock |= CIFS_CREATE_ACTION; */
1184	/* BB FIXME END */
1185
1186		if (pfile_info) {
1187			pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1188			pfile_info->LastAccessTime = 0; /* BB fixme */
1189			pfile_info->LastWriteTime = 0; /* BB fixme */
1190			pfile_info->ChangeTime = 0;  /* BB fixme */
1191			pfile_info->Attributes =
1192				cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1193			/* the file_info buf is endian converted by caller */
1194			pfile_info->AllocationSize =
1195				cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1196			pfile_info->EndOfFile = pfile_info->AllocationSize;
1197			pfile_info->NumberOfLinks = cpu_to_le32(1);
1198			pfile_info->DeletePending = 0;
1199		}
1200	}
1201
1202	cifs_buf_release(pSMB);
1203	if (rc == -EAGAIN)
1204		goto OldOpenRetry;
1205	return rc;
1206}
1207
1208int
1209CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock,
1210	  FILE_ALL_INFO *buf)
1211{
1212	int rc;
1213	OPEN_REQ *req = NULL;
1214	OPEN_RSP *rsp = NULL;
1215	int bytes_returned;
1216	int name_len;
1217	__u16 count;
1218	struct cifs_sb_info *cifs_sb = oparms->cifs_sb;
1219	struct cifs_tcon *tcon = oparms->tcon;
1220	int remap = cifs_remap(cifs_sb);
1221	const struct nls_table *nls = cifs_sb->local_nls;
1222	int create_options = oparms->create_options;
1223	int desired_access = oparms->desired_access;
1224	int disposition = oparms->disposition;
1225	const char *path = oparms->path;
1226
1227openRetry:
1228	rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **)&req,
1229		      (void **)&rsp);
1230	if (rc)
1231		return rc;
1232
1233	/* no commands go after this */
1234	req->AndXCommand = 0xFF;
1235
1236	if (req->hdr.Flags2 & SMBFLG2_UNICODE) {
1237		/* account for one byte pad to word boundary */
1238		count = 1;
1239		name_len = cifsConvertToUTF16((__le16 *)(req->fileName + 1),
1240					      path, PATH_MAX, nls, remap);
1241		/* trailing null */
1242		name_len++;
1243		name_len *= 2;
1244		req->NameLength = cpu_to_le16(name_len);
1245	} else {
1246		/* BB improve check for buffer overruns BB */
1247		/* no pad */
1248		count = 0;
1249		name_len = copy_path_name(req->fileName, path);
1250		req->NameLength = cpu_to_le16(name_len);
1251	}
1252
1253	if (*oplock & REQ_OPLOCK)
1254		req->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1255	else if (*oplock & REQ_BATCHOPLOCK)
1256		req->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1257
1258	req->DesiredAccess = cpu_to_le32(desired_access);
1259	req->AllocationSize = 0;
1260
1261	/*
1262	 * Set file as system file if special file such as fifo and server
1263	 * expecting SFU style and no Unix extensions.
1264	 */
1265	if (create_options & CREATE_OPTION_SPECIAL)
1266		req->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1267	else
1268		req->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1269
1270	/*
1271	 * XP does not handle ATTR_POSIX_SEMANTICS but it helps speed up case
1272	 * sensitive checks for other servers such as Samba.
1273	 */
1274	if (tcon->ses->capabilities & CAP_UNIX)
1275		req->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1276
1277	if (create_options & CREATE_OPTION_READONLY)
1278		req->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1279
1280	req->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1281	req->CreateDisposition = cpu_to_le32(disposition);
1282	req->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1283
1284	/* BB Expirement with various impersonation levels and verify */
1285	req->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1286	req->SecurityFlags = SECURITY_CONTEXT_TRACKING|SECURITY_EFFECTIVE_ONLY;
1287
1288	count += name_len;
1289	inc_rfc1001_len(req, count);
1290
1291	req->ByteCount = cpu_to_le16(count);
1292	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *)req,
1293			 (struct smb_hdr *)rsp, &bytes_returned, 0);
1294	cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1295	if (rc) {
1296		cifs_dbg(FYI, "Error in Open = %d\n", rc);
1297		cifs_buf_release(req);
1298		if (rc == -EAGAIN)
1299			goto openRetry;
1300		return rc;
1301	}
1302
1303	/* 1 byte no need to le_to_cpu */
1304	*oplock = rsp->OplockLevel;
1305	/* cifs fid stays in le */
1306	oparms->fid->netfid = rsp->Fid;
1307	oparms->fid->access = desired_access;
1308
1309	/* Let caller know file was created so we can set the mode. */
1310	/* Do we care about the CreateAction in any other cases? */
1311	if (cpu_to_le32(FILE_CREATE) == rsp->CreateAction)
1312		*oplock |= CIFS_CREATE_ACTION;
1313
1314	if (buf) {
1315		/* copy from CreationTime to Attributes */
1316		memcpy((char *)buf, (char *)&rsp->CreationTime, 36);
1317		/* the file_info buf is endian converted by caller */
1318		buf->AllocationSize = rsp->AllocationSize;
1319		buf->EndOfFile = rsp->EndOfFile;
1320		buf->NumberOfLinks = cpu_to_le32(1);
1321		buf->DeletePending = 0;
1322	}
1323
1324	cifs_buf_release(req);
1325	return rc;
1326}
1327
1328/*
1329 * Discard any remaining data in the current SMB. To do this, we borrow the
1330 * current bigbuf.
1331 */
1332int
1333cifs_discard_remaining_data(struct TCP_Server_Info *server)
1334{
1335	unsigned int rfclen = server->pdu_size;
1336	int remaining = rfclen + server->vals->header_preamble_size -
1337		server->total_read;
1338
1339	while (remaining > 0) {
1340		int length;
1341
1342		length = cifs_discard_from_socket(server,
1343				min_t(size_t, remaining,
1344				      CIFSMaxBufSize + MAX_HEADER_SIZE(server)));
1345		if (length < 0)
1346			return length;
1347		server->total_read += length;
1348		remaining -= length;
1349	}
1350
1351	return 0;
1352}
1353
1354static int
1355__cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid,
1356		     bool malformed)
1357{
1358	int length;
1359
1360	length = cifs_discard_remaining_data(server);
1361	dequeue_mid(mid, malformed);
1362	mid->resp_buf = server->smallbuf;
1363	server->smallbuf = NULL;
1364	return length;
1365}
1366
1367static int
1368cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1369{
1370	struct cifs_readdata *rdata = mid->callback_data;
1371
1372	return  __cifs_readv_discard(server, mid, rdata->result);
1373}
1374
1375int
1376cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1377{
1378	int length, len;
1379	unsigned int data_offset, data_len;
1380	struct cifs_readdata *rdata = mid->callback_data;
1381	char *buf = server->smallbuf;
1382	unsigned int buflen = server->pdu_size +
1383		server->vals->header_preamble_size;
1384	bool use_rdma_mr = false;
1385
1386	cifs_dbg(FYI, "%s: mid=%llu offset=%llu bytes=%u\n",
1387		 __func__, mid->mid, rdata->offset, rdata->bytes);
1388
1389	/*
1390	 * read the rest of READ_RSP header (sans Data array), or whatever we
1391	 * can if there's not enough data. At this point, we've read down to
1392	 * the Mid.
1393	 */
1394	len = min_t(unsigned int, buflen, server->vals->read_rsp_size) -
1395							HEADER_SIZE(server) + 1;
1396
1397	length = cifs_read_from_socket(server,
1398				       buf + HEADER_SIZE(server) - 1, len);
1399	if (length < 0)
1400		return length;
1401	server->total_read += length;
1402
1403	if (server->ops->is_session_expired &&
1404	    server->ops->is_session_expired(buf)) {
1405		cifs_reconnect(server);
1406		return -1;
1407	}
1408
1409	if (server->ops->is_status_pending &&
1410	    server->ops->is_status_pending(buf, server)) {
1411		cifs_discard_remaining_data(server);
1412		return -1;
1413	}
1414
1415	/* set up first two iov for signature check and to get credits */
1416	rdata->iov[0].iov_base = buf;
1417	rdata->iov[0].iov_len = server->vals->header_preamble_size;
1418	rdata->iov[1].iov_base = buf + server->vals->header_preamble_size;
1419	rdata->iov[1].iov_len =
1420		server->total_read - server->vals->header_preamble_size;
1421	cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n",
1422		 rdata->iov[0].iov_base, rdata->iov[0].iov_len);
1423	cifs_dbg(FYI, "1: iov_base=%p iov_len=%zu\n",
1424		 rdata->iov[1].iov_base, rdata->iov[1].iov_len);
1425
1426	/* Was the SMB read successful? */
1427	rdata->result = server->ops->map_error(buf, false);
1428	if (rdata->result != 0) {
1429		cifs_dbg(FYI, "%s: server returned error %d\n",
1430			 __func__, rdata->result);
1431		/* normal error on read response */
1432		return __cifs_readv_discard(server, mid, false);
1433	}
1434
1435	/* Is there enough to get to the rest of the READ_RSP header? */
1436	if (server->total_read < server->vals->read_rsp_size) {
1437		cifs_dbg(FYI, "%s: server returned short header. got=%u expected=%zu\n",
1438			 __func__, server->total_read,
1439			 server->vals->read_rsp_size);
1440		rdata->result = -EIO;
1441		return cifs_readv_discard(server, mid);
1442	}
1443
1444	data_offset = server->ops->read_data_offset(buf) +
1445		server->vals->header_preamble_size;
1446	if (data_offset < server->total_read) {
1447		/*
1448		 * win2k8 sometimes sends an offset of 0 when the read
1449		 * is beyond the EOF. Treat it as if the data starts just after
1450		 * the header.
1451		 */
1452		cifs_dbg(FYI, "%s: data offset (%u) inside read response header\n",
1453			 __func__, data_offset);
1454		data_offset = server->total_read;
1455	} else if (data_offset > MAX_CIFS_SMALL_BUFFER_SIZE) {
1456		/* data_offset is beyond the end of smallbuf */
1457		cifs_dbg(FYI, "%s: data offset (%u) beyond end of smallbuf\n",
1458			 __func__, data_offset);
1459		rdata->result = -EIO;
1460		return cifs_readv_discard(server, mid);
1461	}
1462
1463	cifs_dbg(FYI, "%s: total_read=%u data_offset=%u\n",
1464		 __func__, server->total_read, data_offset);
1465
1466	len = data_offset - server->total_read;
1467	if (len > 0) {
1468		/* read any junk before data into the rest of smallbuf */
1469		length = cifs_read_from_socket(server,
1470					       buf + server->total_read, len);
1471		if (length < 0)
1472			return length;
1473		server->total_read += length;
1474	}
1475
1476	/* how much data is in the response? */
1477#ifdef CONFIG_CIFS_SMB_DIRECT
1478	use_rdma_mr = rdata->mr;
1479#endif
1480	data_len = server->ops->read_data_length(buf, use_rdma_mr);
1481	if (!use_rdma_mr && (data_offset + data_len > buflen)) {
1482		/* data_len is corrupt -- discard frame */
1483		rdata->result = -EIO;
1484		return cifs_readv_discard(server, mid);
1485	}
1486
1487	length = rdata->read_into_pages(server, rdata, data_len);
1488	if (length < 0)
1489		return length;
1490
1491	server->total_read += length;
1492
1493	cifs_dbg(FYI, "total_read=%u buflen=%u remaining=%u\n",
1494		 server->total_read, buflen, data_len);
1495
1496	/* discard anything left over */
1497	if (server->total_read < buflen)
1498		return cifs_readv_discard(server, mid);
1499
1500	dequeue_mid(mid, false);
1501	mid->resp_buf = server->smallbuf;
1502	server->smallbuf = NULL;
1503	return length;
1504}
1505
1506static void
1507cifs_readv_callback(struct mid_q_entry *mid)
1508{
1509	struct cifs_readdata *rdata = mid->callback_data;
1510	struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1511	struct TCP_Server_Info *server = tcon->ses->server;
1512	struct smb_rqst rqst = { .rq_iov = rdata->iov,
1513				 .rq_nvec = 2,
1514				 .rq_pages = rdata->pages,
1515				 .rq_offset = rdata->page_offset,
1516				 .rq_npages = rdata->nr_pages,
1517				 .rq_pagesz = rdata->pagesz,
1518				 .rq_tailsz = rdata->tailsz };
1519	struct cifs_credits credits = { .value = 1, .instance = 0 };
1520
1521	cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%u\n",
1522		 __func__, mid->mid, mid->mid_state, rdata->result,
1523		 rdata->bytes);
1524
1525	switch (mid->mid_state) {
1526	case MID_RESPONSE_RECEIVED:
1527		/* result already set, check signature */
1528		if (server->sign) {
1529			int rc = 0;
1530
1531			rc = cifs_verify_signature(&rqst, server,
1532						  mid->sequence_number);
1533			if (rc)
1534				cifs_dbg(VFS, "SMB signature verification returned error = %d\n",
1535					 rc);
1536		}
1537		/* FIXME: should this be counted toward the initiating task? */
1538		task_io_account_read(rdata->got_bytes);
1539		cifs_stats_bytes_read(tcon, rdata->got_bytes);
1540		break;
1541	case MID_REQUEST_SUBMITTED:
1542	case MID_RETRY_NEEDED:
1543		rdata->result = -EAGAIN;
1544		if (server->sign && rdata->got_bytes)
1545			/* reset bytes number since we can not check a sign */
1546			rdata->got_bytes = 0;
1547		/* FIXME: should this be counted toward the initiating task? */
1548		task_io_account_read(rdata->got_bytes);
1549		cifs_stats_bytes_read(tcon, rdata->got_bytes);
1550		break;
1551	default:
1552		rdata->result = -EIO;
1553	}
1554
1555	queue_work(cifsiod_wq, &rdata->work);
1556	DeleteMidQEntry(mid);
1557	add_credits(server, &credits, 0);
1558}
1559
1560/* cifs_async_readv - send an async write, and set up mid to handle result */
1561int
1562cifs_async_readv(struct cifs_readdata *rdata)
1563{
1564	int rc;
1565	READ_REQ *smb = NULL;
1566	int wct;
1567	struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1568	struct smb_rqst rqst = { .rq_iov = rdata->iov,
1569				 .rq_nvec = 2 };
1570
1571	cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n",
1572		 __func__, rdata->offset, rdata->bytes);
1573
1574	if (tcon->ses->capabilities & CAP_LARGE_FILES)
1575		wct = 12;
1576	else {
1577		wct = 10; /* old style read */
1578		if ((rdata->offset >> 32) > 0)  {
1579			/* can not handle this big offset for old */
1580			return -EIO;
1581		}
1582	}
1583
1584	rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **)&smb);
1585	if (rc)
1586		return rc;
1587
1588	smb->hdr.Pid = cpu_to_le16((__u16)rdata->pid);
1589	smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16));
1590
1591	smb->AndXCommand = 0xFF;	/* none */
1592	smb->Fid = rdata->cfile->fid.netfid;
1593	smb->OffsetLow = cpu_to_le32(rdata->offset & 0xFFFFFFFF);
1594	if (wct == 12)
1595		smb->OffsetHigh = cpu_to_le32(rdata->offset >> 32);
1596	smb->Remaining = 0;
1597	smb->MaxCount = cpu_to_le16(rdata->bytes & 0xFFFF);
1598	smb->MaxCountHigh = cpu_to_le32(rdata->bytes >> 16);
1599	if (wct == 12)
1600		smb->ByteCount = 0;
1601	else {
1602		/* old style read */
1603		struct smb_com_readx_req *smbr =
1604			(struct smb_com_readx_req *)smb;
1605		smbr->ByteCount = 0;
1606	}
1607
1608	/* 4 for RFC1001 length + 1 for BCC */
1609	rdata->iov[0].iov_base = smb;
1610	rdata->iov[0].iov_len = 4;
1611	rdata->iov[1].iov_base = (char *)smb + 4;
1612	rdata->iov[1].iov_len = get_rfc1002_length(smb);
1613
1614	kref_get(&rdata->refcount);
1615	rc = cifs_call_async(tcon->ses->server, &rqst, cifs_readv_receive,
1616			     cifs_readv_callback, NULL, rdata, 0, NULL);
1617
1618	if (rc == 0)
1619		cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1620	else
1621		kref_put(&rdata->refcount, cifs_readdata_release);
1622
1623	cifs_small_buf_release(smb);
1624	return rc;
1625}
1626
1627int
1628CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
1629	    unsigned int *nbytes, char **buf, int *pbuf_type)
1630{
1631	int rc = -EACCES;
1632	READ_REQ *pSMB = NULL;
1633	READ_RSP *pSMBr = NULL;
1634	char *pReadData = NULL;
1635	int wct;
1636	int resp_buf_type = 0;
1637	struct kvec iov[1];
1638	struct kvec rsp_iov;
1639	__u32 pid = io_parms->pid;
1640	__u16 netfid = io_parms->netfid;
1641	__u64 offset = io_parms->offset;
1642	struct cifs_tcon *tcon = io_parms->tcon;
1643	unsigned int count = io_parms->length;
1644
1645	cifs_dbg(FYI, "Reading %d bytes on fid %d\n", count, netfid);
1646	if (tcon->ses->capabilities & CAP_LARGE_FILES)
1647		wct = 12;
1648	else {
1649		wct = 10; /* old style read */
1650		if ((offset >> 32) > 0)  {
1651			/* can not handle this big offset for old */
1652			return -EIO;
1653		}
1654	}
1655
1656	*nbytes = 0;
1657	rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1658	if (rc)
1659		return rc;
1660
1661	pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1662	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1663
1664	/* tcon and ses pointer are checked in smb_init */
1665	if (tcon->ses->server == NULL)
1666		return -ECONNABORTED;
1667
1668	pSMB->AndXCommand = 0xFF;       /* none */
1669	pSMB->Fid = netfid;
1670	pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1671	if (wct == 12)
1672		pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1673
1674	pSMB->Remaining = 0;
1675	pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1676	pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1677	if (wct == 12)
1678		pSMB->ByteCount = 0;  /* no need to do le conversion since 0 */
1679	else {
1680		/* old style read */
1681		struct smb_com_readx_req *pSMBW =
1682			(struct smb_com_readx_req *)pSMB;
1683		pSMBW->ByteCount = 0;
1684	}
1685
1686	iov[0].iov_base = (char *)pSMB;
1687	iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
1688	rc = SendReceive2(xid, tcon->ses, iov, 1, &resp_buf_type,
1689			  CIFS_LOG_ERROR, &rsp_iov);
1690	cifs_small_buf_release(pSMB);
1691	cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1692	pSMBr = (READ_RSP *)rsp_iov.iov_base;
1693	if (rc) {
1694		cifs_dbg(VFS, "Send error in read = %d\n", rc);
1695	} else {
1696		int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1697		data_length = data_length << 16;
1698		data_length += le16_to_cpu(pSMBr->DataLength);
1699		*nbytes = data_length;
1700
1701		/*check that DataLength would not go beyond end of SMB */
1702		if ((data_length > CIFSMaxBufSize)
1703				|| (data_length > count)) {
1704			cifs_dbg(FYI, "bad length %d for count %d\n",
1705				 data_length, count);
1706			rc = -EIO;
1707			*nbytes = 0;
1708		} else {
1709			pReadData = (char *) (&pSMBr->hdr.Protocol) +
1710					le16_to_cpu(pSMBr->DataOffset);
1711/*			if (rc = copy_to_user(buf, pReadData, data_length)) {
1712				cifs_dbg(VFS, "Faulting on read rc = %d\n",rc);
1713				rc = -EFAULT;
1714			}*/ /* can not use copy_to_user when using page cache*/
1715			if (*buf)
1716				memcpy(*buf, pReadData, data_length);
1717		}
1718	}
1719
1720	if (*buf) {
1721		free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
1722	} else if (resp_buf_type != CIFS_NO_BUFFER) {
1723		/* return buffer to caller to free */
1724		*buf = rsp_iov.iov_base;
1725		if (resp_buf_type == CIFS_SMALL_BUFFER)
1726			*pbuf_type = CIFS_SMALL_BUFFER;
1727		else if (resp_buf_type == CIFS_LARGE_BUFFER)
1728			*pbuf_type = CIFS_LARGE_BUFFER;
1729	} /* else no valid buffer on return - leave as null */
1730
1731	/* Note: On -EAGAIN error only caller can retry on handle based calls
1732		since file handle passed in no longer valid */
1733	return rc;
1734}
1735
1736
1737int
1738CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
1739	     unsigned int *nbytes, const char *buf)
1740{
1741	int rc = -EACCES;
1742	WRITE_REQ *pSMB = NULL;
1743	WRITE_RSP *pSMBr = NULL;
1744	int bytes_returned, wct;
1745	__u32 bytes_sent;
1746	__u16 byte_count;
1747	__u32 pid = io_parms->pid;
1748	__u16 netfid = io_parms->netfid;
1749	__u64 offset = io_parms->offset;
1750	struct cifs_tcon *tcon = io_parms->tcon;
1751	unsigned int count = io_parms->length;
1752
1753	*nbytes = 0;
1754
1755	/* cifs_dbg(FYI, "write at %lld %d bytes\n", offset, count);*/
1756	if (tcon->ses == NULL)
1757		return -ECONNABORTED;
1758
1759	if (tcon->ses->capabilities & CAP_LARGE_FILES)
1760		wct = 14;
1761	else {
1762		wct = 12;
1763		if ((offset >> 32) > 0) {
1764			/* can not handle big offset for old srv */
1765			return -EIO;
1766		}
1767	}
1768
1769	rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1770		      (void **) &pSMBr);
1771	if (rc)
1772		return rc;
1773
1774	pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1775	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1776
1777	/* tcon and ses pointer are checked in smb_init */
1778	if (tcon->ses->server == NULL)
1779		return -ECONNABORTED;
1780
1781	pSMB->AndXCommand = 0xFF;	/* none */
1782	pSMB->Fid = netfid;
1783	pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1784	if (wct == 14)
1785		pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1786
1787	pSMB->Reserved = 0xFFFFFFFF;
1788	pSMB->WriteMode = 0;
1789	pSMB->Remaining = 0;
1790
1791	/* Can increase buffer size if buffer is big enough in some cases ie we
1792	can send more if LARGE_WRITE_X capability returned by the server and if
1793	our buffer is big enough or if we convert to iovecs on socket writes
1794	and eliminate the copy to the CIFS buffer */
1795	if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1796		bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1797	} else {
1798		bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1799			 & ~0xFF;
1800	}
1801
1802	if (bytes_sent > count)
1803		bytes_sent = count;
1804	pSMB->DataOffset =
1805		cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1806	if (buf)
1807		memcpy(pSMB->Data, buf, bytes_sent);
1808	else if (count != 0) {
1809		/* No buffer */
1810		cifs_buf_release(pSMB);
1811		return -EINVAL;
1812	} /* else setting file size with write of zero bytes */
1813	if (wct == 14)
1814		byte_count = bytes_sent + 1; /* pad */
1815	else /* wct == 12 */
1816		byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1817
1818	pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1819	pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1820	inc_rfc1001_len(pSMB, byte_count);
1821
1822	if (wct == 14)
1823		pSMB->ByteCount = cpu_to_le16(byte_count);
1824	else { /* old style write has byte count 4 bytes earlier
1825		  so 4 bytes pad  */
1826		struct smb_com_writex_req *pSMBW =
1827			(struct smb_com_writex_req *)pSMB;
1828		pSMBW->ByteCount = cpu_to_le16(byte_count);
1829	}
1830
1831	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1832			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1833	cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
1834	if (rc) {
1835		cifs_dbg(FYI, "Send error in write = %d\n", rc);
1836	} else {
1837		*nbytes = le16_to_cpu(pSMBr->CountHigh);
1838		*nbytes = (*nbytes) << 16;
1839		*nbytes += le16_to_cpu(pSMBr->Count);
1840
1841		/*
1842		 * Mask off high 16 bits when bytes written as returned by the
1843		 * server is greater than bytes requested by the client. Some
1844		 * OS/2 servers are known to set incorrect CountHigh values.
1845		 */
1846		if (*nbytes > count)
1847			*nbytes &= 0xFFFF;
1848	}
1849
1850	cifs_buf_release(pSMB);
1851
1852	/* Note: On -EAGAIN error only caller can retry on handle based calls
1853		since file handle passed in no longer valid */
1854
1855	return rc;
1856}
1857
1858void
1859cifs_writedata_release(struct kref *refcount)
1860{
1861	struct cifs_writedata *wdata = container_of(refcount,
1862					struct cifs_writedata, refcount);
1863#ifdef CONFIG_CIFS_SMB_DIRECT
1864	if (wdata->mr) {
1865		smbd_deregister_mr(wdata->mr);
1866		wdata->mr = NULL;
1867	}
1868#endif
1869
1870	if (wdata->cfile)
1871		cifsFileInfo_put(wdata->cfile);
1872
1873	kvfree(wdata->pages);
1874	kfree(wdata);
1875}
1876
1877/*
1878 * Write failed with a retryable error. Resend the write request. It's also
1879 * possible that the page was redirtied so re-clean the page.
1880 */
1881static void
1882cifs_writev_requeue(struct cifs_writedata *wdata)
1883{
1884	int i, rc = 0;
1885	struct inode *inode = d_inode(wdata->cfile->dentry);
1886	struct TCP_Server_Info *server;
1887	unsigned int rest_len;
1888
1889	server = tlink_tcon(wdata->cfile->tlink)->ses->server;
1890	i = 0;
1891	rest_len = wdata->bytes;
1892	do {
1893		struct cifs_writedata *wdata2;
1894		unsigned int j, nr_pages, wsize, tailsz, cur_len;
1895
1896		wsize = server->ops->wp_retry_size(inode);
1897		if (wsize < rest_len) {
1898			nr_pages = wsize / PAGE_SIZE;
1899			if (!nr_pages) {
1900				rc = -ENOTSUPP;
1901				break;
1902			}
1903			cur_len = nr_pages * PAGE_SIZE;
1904			tailsz = PAGE_SIZE;
1905		} else {
1906			nr_pages = DIV_ROUND_UP(rest_len, PAGE_SIZE);
1907			cur_len = rest_len;
1908			tailsz = rest_len - (nr_pages - 1) * PAGE_SIZE;
1909		}
1910
1911		wdata2 = cifs_writedata_alloc(nr_pages, cifs_writev_complete);
1912		if (!wdata2) {
1913			rc = -ENOMEM;
1914			break;
1915		}
1916
1917		for (j = 0; j < nr_pages; j++) {
1918			wdata2->pages[j] = wdata->pages[i + j];
1919			lock_page(wdata2->pages[j]);
1920			clear_page_dirty_for_io(wdata2->pages[j]);
1921		}
1922
1923		wdata2->sync_mode = wdata->sync_mode;
1924		wdata2->nr_pages = nr_pages;
1925		wdata2->offset = page_offset(wdata2->pages[0]);
1926		wdata2->pagesz = PAGE_SIZE;
1927		wdata2->tailsz = tailsz;
1928		wdata2->bytes = cur_len;
1929
1930		rc = cifs_get_writable_file(CIFS_I(inode), FIND_WR_ANY,
1931					    &wdata2->cfile);
1932		if (!wdata2->cfile) {
1933			cifs_dbg(VFS, "No writable handle to retry writepages rc=%d\n",
1934				 rc);
1935			if (!is_retryable_error(rc))
1936				rc = -EBADF;
1937		} else {
1938			wdata2->pid = wdata2->cfile->pid;
1939			rc = server->ops->async_writev(wdata2,
1940						       cifs_writedata_release);
1941		}
1942
1943		for (j = 0; j < nr_pages; j++) {
1944			unlock_page(wdata2->pages[j]);
1945			if (rc != 0 && !is_retryable_error(rc)) {
1946				SetPageError(wdata2->pages[j]);
1947				end_page_writeback(wdata2->pages[j]);
1948				put_page(wdata2->pages[j]);
1949			}
1950		}
1951
1952		kref_put(&wdata2->refcount, cifs_writedata_release);
1953		if (rc) {
1954			if (is_retryable_error(rc))
1955				continue;
1956			i += nr_pages;
1957			break;
1958		}
1959
1960		rest_len -= cur_len;
1961		i += nr_pages;
1962	} while (i < wdata->nr_pages);
1963
1964	/* cleanup remaining pages from the original wdata */
1965	for (; i < wdata->nr_pages; i++) {
1966		SetPageError(wdata->pages[i]);
1967		end_page_writeback(wdata->pages[i]);
1968		put_page(wdata->pages[i]);
1969	}
1970
1971	if (rc != 0 && !is_retryable_error(rc))
1972		mapping_set_error(inode->i_mapping, rc);
1973	kref_put(&wdata->refcount, cifs_writedata_release);
1974}
1975
1976void
1977cifs_writev_complete(struct work_struct *work)
1978{
1979	struct cifs_writedata *wdata = container_of(work,
1980						struct cifs_writedata, work);
1981	struct inode *inode = d_inode(wdata->cfile->dentry);
1982	int i = 0;
1983
1984	if (wdata->result == 0) {
1985		spin_lock(&inode->i_lock);
1986		cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes);
1987		spin_unlock(&inode->i_lock);
1988		cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink),
1989					 wdata->bytes);
1990	} else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN)
1991		return cifs_writev_requeue(wdata);
1992
1993	for (i = 0; i < wdata->nr_pages; i++) {
1994		struct page *page = wdata->pages[i];
1995		if (wdata->result == -EAGAIN)
1996			__set_page_dirty_nobuffers(page);
1997		else if (wdata->result < 0)
1998			SetPageError(page);
1999		end_page_writeback(page);
2000		cifs_readpage_to_fscache(inode, page);
2001		put_page(page);
2002	}
2003	if (wdata->result != -EAGAIN)
2004		mapping_set_error(inode->i_mapping, wdata->result);
2005	kref_put(&wdata->refcount, cifs_writedata_release);
2006}
2007
2008struct cifs_writedata *
2009cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete)
2010{
2011	struct page **pages =
2012		kcalloc(nr_pages, sizeof(struct page *), GFP_NOFS);
2013	if (pages)
2014		return cifs_writedata_direct_alloc(pages, complete);
2015
2016	return NULL;
2017}
2018
2019struct cifs_writedata *
2020cifs_writedata_direct_alloc(struct page **pages, work_func_t complete)
2021{
2022	struct cifs_writedata *wdata;
2023
2024	wdata = kzalloc(sizeof(*wdata), GFP_NOFS);
2025	if (wdata != NULL) {
2026		wdata->pages = pages;
2027		kref_init(&wdata->refcount);
2028		INIT_LIST_HEAD(&wdata->list);
2029		init_completion(&wdata->done);
2030		INIT_WORK(&wdata->work, complete);
2031	}
2032	return wdata;
2033}
2034
2035/*
2036 * Check the mid_state and signature on received buffer (if any), and queue the
2037 * workqueue completion task.
2038 */
2039static void
2040cifs_writev_callback(struct mid_q_entry *mid)
2041{
2042	struct cifs_writedata *wdata = mid->callback_data;
2043	struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2044	unsigned int written;
2045	WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
2046	struct cifs_credits credits = { .value = 1, .instance = 0 };
2047
2048	switch (mid->mid_state) {
2049	case MID_RESPONSE_RECEIVED:
2050		wdata->result = cifs_check_receive(mid, tcon->ses->server, 0);
2051		if (wdata->result != 0)
2052			break;
2053
2054		written = le16_to_cpu(smb->CountHigh);
2055		written <<= 16;
2056		written += le16_to_cpu(smb->Count);
2057		/*
2058		 * Mask off high 16 bits when bytes written as returned
2059		 * by the server is greater than bytes requested by the
2060		 * client. OS/2 servers are known to set incorrect
2061		 * CountHigh values.
2062		 */
2063		if (written > wdata->bytes)
2064			written &= 0xFFFF;
2065
2066		if (written < wdata->bytes)
2067			wdata->result = -ENOSPC;
2068		else
2069			wdata->bytes = written;
2070		break;
2071	case MID_REQUEST_SUBMITTED:
2072	case MID_RETRY_NEEDED:
2073		wdata->result = -EAGAIN;
2074		break;
2075	default:
2076		wdata->result = -EIO;
2077		break;
2078	}
2079
2080	queue_work(cifsiod_wq, &wdata->work);
2081	DeleteMidQEntry(mid);
2082	add_credits(tcon->ses->server, &credits, 0);
2083}
2084
2085/* cifs_async_writev - send an async write, and set up mid to handle result */
2086int
2087cifs_async_writev(struct cifs_writedata *wdata,
2088		  void (*release)(struct kref *kref))
2089{
2090	int rc = -EACCES;
2091	WRITE_REQ *smb = NULL;
2092	int wct;
2093	struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2094	struct kvec iov[2];
2095	struct smb_rqst rqst = { };
2096
2097	if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2098		wct = 14;
2099	} else {
2100		wct = 12;
2101		if (wdata->offset >> 32 > 0) {
2102			/* can not handle big offset for old srv */
2103			return -EIO;
2104		}
2105	}
2106
2107	rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&smb);
2108	if (rc)
2109		goto async_writev_out;
2110
2111	smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
2112	smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
2113
2114	smb->AndXCommand = 0xFF;	/* none */
2115	smb->Fid = wdata->cfile->fid.netfid;
2116	smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF);
2117	if (wct == 14)
2118		smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32);
2119	smb->Reserved = 0xFFFFFFFF;
2120	smb->WriteMode = 0;
2121	smb->Remaining = 0;
2122
2123	smb->DataOffset =
2124	    cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2125
2126	/* 4 for RFC1001 length + 1 for BCC */
2127	iov[0].iov_len = 4;
2128	iov[0].iov_base = smb;
2129	iov[1].iov_len = get_rfc1002_length(smb) + 1;
2130	iov[1].iov_base = (char *)smb + 4;
2131
2132	rqst.rq_iov = iov;
2133	rqst.rq_nvec = 2;
2134	rqst.rq_pages = wdata->pages;
2135	rqst.rq_offset = wdata->page_offset;
2136	rqst.rq_npages = wdata->nr_pages;
2137	rqst.rq_pagesz = wdata->pagesz;
2138	rqst.rq_tailsz = wdata->tailsz;
2139
2140	cifs_dbg(FYI, "async write at %llu %u bytes\n",
2141		 wdata->offset, wdata->bytes);
2142
2143	smb->DataLengthLow = cpu_to_le16(wdata->bytes & 0xFFFF);
2144	smb->DataLengthHigh = cpu_to_le16(wdata->bytes >> 16);
2145
2146	if (wct == 14) {
2147		inc_rfc1001_len(&smb->hdr, wdata->bytes + 1);
2148		put_bcc(wdata->bytes + 1, &smb->hdr);
2149	} else {
2150		/* wct == 12 */
2151		struct smb_com_writex_req *smbw =
2152				(struct smb_com_writex_req *)smb;
2153		inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
2154		put_bcc(wdata->bytes + 5, &smbw->hdr);
2155		iov[1].iov_len += 4; /* pad bigger by four bytes */
2156	}
2157
2158	kref_get(&wdata->refcount);
2159	rc = cifs_call_async(tcon->ses->server, &rqst, NULL,
2160			     cifs_writev_callback, NULL, wdata, 0, NULL);
2161
2162	if (rc == 0)
2163		cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2164	else
2165		kref_put(&wdata->refcount, release);
2166
2167async_writev_out:
2168	cifs_small_buf_release(smb);
2169	return rc;
2170}
2171
2172int
2173CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
2174	      unsigned int *nbytes, struct kvec *iov, int n_vec)
2175{
2176	int rc;
2177	WRITE_REQ *pSMB = NULL;
2178	int wct;
2179	int smb_hdr_len;
2180	int resp_buf_type = 0;
2181	__u32 pid = io_parms->pid;
2182	__u16 netfid = io_parms->netfid;
2183	__u64 offset = io_parms->offset;
2184	struct cifs_tcon *tcon = io_parms->tcon;
2185	unsigned int count = io_parms->length;
2186	struct kvec rsp_iov;
2187
2188	*nbytes = 0;
2189
2190	cifs_dbg(FYI, "write2 at %lld %d bytes\n", (long long)offset, count);
2191
2192	if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2193		wct = 14;
2194	} else {
2195		wct = 12;
2196		if ((offset >> 32) > 0) {
2197			/* can not handle big offset for old srv */
2198			return -EIO;
2199		}
2200	}
2201	rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
2202	if (rc)
2203		return rc;
2204
2205	pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
2206	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
2207
2208	/* tcon and ses pointer are checked in smb_init */
2209	if (tcon->ses->server == NULL)
2210		return -ECONNABORTED;
2211
2212	pSMB->AndXCommand = 0xFF;	/* none */
2213	pSMB->Fid = netfid;
2214	pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
2215	if (wct == 14)
2216		pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
2217	pSMB->Reserved = 0xFFFFFFFF;
2218	pSMB->WriteMode = 0;
2219	pSMB->Remaining = 0;
2220
2221	pSMB->DataOffset =
2222	    cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2223
2224	pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
2225	pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
2226	/* header + 1 byte pad */
2227	smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1;
2228	if (wct == 14)
2229		inc_rfc1001_len(pSMB, count + 1);
2230	else /* wct == 12 */
2231		inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */
2232	if (wct == 14)
2233		pSMB->ByteCount = cpu_to_le16(count + 1);
2234	else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
2235		struct smb_com_writex_req *pSMBW =
2236				(struct smb_com_writex_req *)pSMB;
2237		pSMBW->ByteCount = cpu_to_le16(count + 5);
2238	}
2239	iov[0].iov_base = pSMB;
2240	if (wct == 14)
2241		iov[0].iov_len = smb_hdr_len + 4;
2242	else /* wct == 12 pad bigger by four bytes */
2243		iov[0].iov_len = smb_hdr_len + 8;
2244
2245	rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type, 0,
2246			  &rsp_iov);
2247	cifs_small_buf_release(pSMB);
2248	cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2249	if (rc) {
2250		cifs_dbg(FYI, "Send error Write2 = %d\n", rc);
2251	} else if (resp_buf_type == 0) {
2252		/* presumably this can not happen, but best to be safe */
2253		rc = -EIO;
2254	} else {
2255		WRITE_RSP *pSMBr = (WRITE_RSP *)rsp_iov.iov_base;
2256		*nbytes = le16_to_cpu(pSMBr->CountHigh);
2257		*nbytes = (*nbytes) << 16;
2258		*nbytes += le16_to_cpu(pSMBr->Count);
2259
2260		/*
2261		 * Mask off high 16 bits when bytes written as returned by the
2262		 * server is greater than bytes requested by the client. OS/2
2263		 * servers are known to set incorrect CountHigh values.
2264		 */
2265		if (*nbytes > count)
2266			*nbytes &= 0xFFFF;
2267	}
2268
2269	free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
2270
2271	/* Note: On -EAGAIN error only caller can retry on handle based calls
2272		since file handle passed in no longer valid */
2273
2274	return rc;
2275}
2276
2277int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon,
2278	       const __u16 netfid, const __u8 lock_type, const __u32 num_unlock,
2279	       const __u32 num_lock, LOCKING_ANDX_RANGE *buf)
2280{
2281	int rc = 0;
2282	LOCK_REQ *pSMB = NULL;
2283	struct kvec iov[2];
2284	struct kvec rsp_iov;
2285	int resp_buf_type;
2286	__u16 count;
2287
2288	cifs_dbg(FYI, "cifs_lockv num lock %d num unlock %d\n",
2289		 num_lock, num_unlock);
2290
2291	rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2292	if (rc)
2293		return rc;
2294
2295	pSMB->Timeout = 0;
2296	pSMB->NumberOfLocks = cpu_to_le16(num_lock);
2297	pSMB->NumberOfUnlocks = cpu_to_le16(num_unlock);
2298	pSMB->LockType = lock_type;
2299	pSMB->AndXCommand = 0xFF; /* none */
2300	pSMB->Fid = netfid; /* netfid stays le */
2301
2302	count = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2303	inc_rfc1001_len(pSMB, count);
2304	pSMB->ByteCount = cpu_to_le16(count);
2305
2306	iov[0].iov_base = (char *)pSMB;
2307	iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4 -
2308			 (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2309	iov[1].iov_base = (char *)buf;
2310	iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2311
2312	cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2313	rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type,
2314			  CIFS_NO_RSP_BUF, &rsp_iov);
2315	cifs_small_buf_release(pSMB);
2316	if (rc)
2317		cifs_dbg(FYI, "Send error in cifs_lockv = %d\n", rc);
2318
2319	return rc;
2320}
2321
2322int
2323CIFSSMBLock(const unsigned int xid, struct cifs_tcon *tcon,
2324	    const __u16 smb_file_id, const __u32 netpid, const __u64 len,
2325	    const __u64 offset, const __u32 numUnlock,
2326	    const __u32 numLock, const __u8 lockType,
2327	    const bool waitFlag, const __u8 oplock_level)
2328{
2329	int rc = 0;
2330	LOCK_REQ *pSMB = NULL;
2331/*	LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
2332	int bytes_returned;
2333	int flags = 0;
2334	__u16 count;
2335
2336	cifs_dbg(FYI, "CIFSSMBLock timeout %d numLock %d\n",
2337		 (int)waitFlag, numLock);
2338	rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2339
2340	if (rc)
2341		return rc;
2342
2343	if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
2344		/* no response expected */
2345		flags = CIFS_NO_SRV_RSP | CIFS_NON_BLOCKING | CIFS_OBREAK_OP;
2346		pSMB->Timeout = 0;
2347	} else if (waitFlag) {
2348		flags = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2349		pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
2350	} else {
2351		pSMB->Timeout = 0;
2352	}
2353
2354	pSMB->NumberOfLocks = cpu_to_le16(numLock);
2355	pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
2356	pSMB->LockType = lockType;
2357	pSMB->OplockLevel = oplock_level;
2358	pSMB->AndXCommand = 0xFF;	/* none */
2359	pSMB->Fid = smb_file_id; /* netfid stays le */
2360
2361	if ((numLock != 0) || (numUnlock != 0)) {
2362		pSMB->Locks[0].Pid = cpu_to_le16(netpid);
2363		/* BB where to store pid high? */
2364		pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
2365		pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
2366		pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
2367		pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
2368		count = sizeof(LOCKING_ANDX_RANGE);
2369	} else {
2370		/* oplock break */
2371		count = 0;
2372	}
2373	inc_rfc1001_len(pSMB, count);
2374	pSMB->ByteCount = cpu_to_le16(count);
2375
2376	if (waitFlag)
2377		rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2378			(struct smb_hdr *) pSMB, &bytes_returned);
2379	else
2380		rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, flags);
2381	cifs_small_buf_release(pSMB);
2382	cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2383	if (rc)
2384		cifs_dbg(FYI, "Send error in Lock = %d\n", rc);
2385
2386	/* Note: On -EAGAIN error only caller can retry on handle based calls
2387	since file handle passed in no longer valid */
2388	return rc;
2389}
2390
2391int
2392CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon,
2393		const __u16 smb_file_id, const __u32 netpid,
2394		const loff_t start_offset, const __u64 len,
2395		struct file_lock *pLockData, const __u16 lock_type,
2396		const bool waitFlag)
2397{
2398	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
2399	struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2400	struct cifs_posix_lock *parm_data;
2401	int rc = 0;
2402	int timeout = 0;
2403	int bytes_returned = 0;
2404	int resp_buf_type = 0;
2405	__u16 params, param_offset, offset, byte_count, count;
2406	struct kvec iov[1];
2407	struct kvec rsp_iov;
2408
2409	cifs_dbg(FYI, "Posix Lock\n");
2410
2411	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
2412
2413	if (rc)
2414		return rc;
2415
2416	pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
2417
2418	params = 6;
2419	pSMB->MaxSetupCount = 0;
2420	pSMB->Reserved = 0;
2421	pSMB->Flags = 0;
2422	pSMB->Reserved2 = 0;
2423	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2424	offset = param_offset + params;
2425
2426	count = sizeof(struct cifs_posix_lock);
2427	pSMB->MaxParameterCount = cpu_to_le16(2);
2428	pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2429	pSMB->SetupCount = 1;
2430	pSMB->Reserved3 = 0;
2431	if (pLockData)
2432		pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2433	else
2434		pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2435	byte_count = 3 /* pad */  + params + count;
2436	pSMB->DataCount = cpu_to_le16(count);
2437	pSMB->ParameterCount = cpu_to_le16(params);
2438	pSMB->TotalDataCount = pSMB->DataCount;
2439	pSMB->TotalParameterCount = pSMB->ParameterCount;
2440	pSMB->ParameterOffset = cpu_to_le16(param_offset);
2441	/* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
2442	parm_data = (struct cifs_posix_lock *)
2443			(((char *)pSMB) + offset + 4);
2444
2445	parm_data->lock_type = cpu_to_le16(lock_type);
2446	if (waitFlag) {
2447		timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2448		parm_data->lock_flags = cpu_to_le16(1);
2449		pSMB->Timeout = cpu_to_le32(-1);
2450	} else
2451		pSMB->Timeout = 0;
2452
2453	parm_data->pid = cpu_to_le32(netpid);
2454	parm_data->start = cpu_to_le64(start_offset);
2455	parm_data->length = cpu_to_le64(len);  /* normalize negative numbers */
2456
2457	pSMB->DataOffset = cpu_to_le16(offset);
2458	pSMB->Fid = smb_file_id;
2459	pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
2460	pSMB->Reserved4 = 0;
2461	inc_rfc1001_len(pSMB, byte_count);
2462	pSMB->ByteCount = cpu_to_le16(byte_count);
2463	if (waitFlag) {
2464		rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2465			(struct smb_hdr *) pSMBr, &bytes_returned);
2466	} else {
2467		iov[0].iov_base = (char *)pSMB;
2468		iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
2469		rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
2470				&resp_buf_type, timeout, &rsp_iov);
2471		pSMBr = (struct smb_com_transaction2_sfi_rsp *)rsp_iov.iov_base;
2472	}
2473	cifs_small_buf_release(pSMB);
2474
2475	if (rc) {
2476		cifs_dbg(FYI, "Send error in Posix Lock = %d\n", rc);
2477	} else if (pLockData) {
2478		/* lock structure can be returned on get */
2479		__u16 data_offset;
2480		__u16 data_count;
2481		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2482
2483		if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) {
2484			rc = -EIO;      /* bad smb */
2485			goto plk_err_exit;
2486		}
2487		data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2488		data_count  = le16_to_cpu(pSMBr->t2.DataCount);
2489		if (data_count < sizeof(struct cifs_posix_lock)) {
2490			rc = -EIO;
2491			goto plk_err_exit;
2492		}
2493		parm_data = (struct cifs_posix_lock *)
2494			((char *)&pSMBr->hdr.Protocol + data_offset);
2495		if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
2496			pLockData->fl_type = F_UNLCK;
2497		else {
2498			if (parm_data->lock_type ==
2499					cpu_to_le16(CIFS_RDLCK))
2500				pLockData->fl_type = F_RDLCK;
2501			else if (parm_data->lock_type ==
2502					cpu_to_le16(CIFS_WRLCK))
2503				pLockData->fl_type = F_WRLCK;
2504
2505			pLockData->fl_start = le64_to_cpu(parm_data->start);
2506			pLockData->fl_end = pLockData->fl_start +
2507					le64_to_cpu(parm_data->length) - 1;
2508			pLockData->fl_pid = -le32_to_cpu(parm_data->pid);
2509		}
2510	}
2511
2512plk_err_exit:
2513	free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
2514
2515	/* Note: On -EAGAIN error only caller can retry on handle based calls
2516	   since file handle passed in no longer valid */
2517
2518	return rc;
2519}
2520
2521
2522int
2523CIFSSMBClose(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2524{
2525	int rc = 0;
2526	CLOSE_REQ *pSMB = NULL;
2527	cifs_dbg(FYI, "In CIFSSMBClose\n");
2528
2529/* do not retry on dead session on close */
2530	rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
2531	if (rc == -EAGAIN)
2532		return 0;
2533	if (rc)
2534		return rc;
2535
2536	pSMB->FileID = (__u16) smb_file_id;
2537	pSMB->LastWriteTime = 0xFFFFFFFF;
2538	pSMB->ByteCount = 0;
2539	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2540	cifs_small_buf_release(pSMB);
2541	cifs_stats_inc(&tcon->stats.cifs_stats.num_closes);
2542	if (rc) {
2543		if (rc != -EINTR) {
2544			/* EINTR is expected when user ctl-c to kill app */
2545			cifs_dbg(VFS, "Send error in Close = %d\n", rc);
2546		}
2547	}
2548
2549	/* Since session is dead, file will be closed on server already */
2550	if (rc == -EAGAIN)
2551		rc = 0;
2552
2553	return rc;
2554}
2555
2556int
2557CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2558{
2559	int rc = 0;
2560	FLUSH_REQ *pSMB = NULL;
2561	cifs_dbg(FYI, "In CIFSSMBFlush\n");
2562
2563	rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
2564	if (rc)
2565		return rc;
2566
2567	pSMB->FileID = (__u16) smb_file_id;
2568	pSMB->ByteCount = 0;
2569	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2570	cifs_small_buf_release(pSMB);
2571	cifs_stats_inc(&tcon->stats.cifs_stats.num_flushes);
2572	if (rc)
2573		cifs_dbg(VFS, "Send error in Flush = %d\n", rc);
2574
2575	return rc;
2576}
2577
2578int
2579CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
2580	      const char *from_name, const char *to_name,
2581	      struct cifs_sb_info *cifs_sb)
2582{
2583	int rc = 0;
2584	RENAME_REQ *pSMB = NULL;
2585	RENAME_RSP *pSMBr = NULL;
2586	int bytes_returned;
2587	int name_len, name_len2;
2588	__u16 count;
2589	int remap = cifs_remap(cifs_sb);
2590
2591	cifs_dbg(FYI, "In CIFSSMBRename\n");
2592renameRetry:
2593	rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
2594		      (void **) &pSMBr);
2595	if (rc)
2596		return rc;
2597
2598	pSMB->BufferFormat = 0x04;
2599	pSMB->SearchAttributes =
2600	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2601			ATTR_DIRECTORY);
2602
2603	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2604		name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2605					      from_name, PATH_MAX,
2606					      cifs_sb->local_nls, remap);
2607		name_len++;	/* trailing null */
2608		name_len *= 2;
2609		pSMB->OldFileName[name_len] = 0x04;	/* pad */
2610	/* protocol requires ASCII signature byte on Unicode string */
2611		pSMB->OldFileName[name_len + 1] = 0x00;
2612		name_len2 =
2613		    cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2614				       to_name, PATH_MAX, cifs_sb->local_nls,
2615				       remap);
2616		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2617		name_len2 *= 2;	/* convert to bytes */
2618	} else {
2619		name_len = copy_path_name(pSMB->OldFileName, from_name);
2620		name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name);
2621		pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
2622		name_len2++;	/* signature byte */
2623	}
2624
2625	count = 1 /* 1st signature byte */  + name_len + name_len2;
2626	inc_rfc1001_len(pSMB, count);
2627	pSMB->ByteCount = cpu_to_le16(count);
2628
2629	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2630			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2631	cifs_stats_inc(&tcon->stats.cifs_stats.num_renames);
2632	if (rc)
2633		cifs_dbg(FYI, "Send error in rename = %d\n", rc);
2634
2635	cifs_buf_release(pSMB);
2636
2637	if (rc == -EAGAIN)
2638		goto renameRetry;
2639
2640	return rc;
2641}
2642
2643int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *pTcon,
2644		int netfid, const char *target_name,
2645		const struct nls_table *nls_codepage, int remap)
2646{
2647	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
2648	struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2649	struct set_file_rename *rename_info;
2650	char *data_offset;
2651	char dummy_string[30];
2652	int rc = 0;
2653	int bytes_returned = 0;
2654	int len_of_str;
2655	__u16 params, param_offset, offset, count, byte_count;
2656
2657	cifs_dbg(FYI, "Rename to File by handle\n");
2658	rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2659			(void **) &pSMBr);
2660	if (rc)
2661		return rc;
2662
2663	params = 6;
2664	pSMB->MaxSetupCount = 0;
2665	pSMB->Reserved = 0;
2666	pSMB->Flags = 0;
2667	pSMB->Timeout = 0;
2668	pSMB->Reserved2 = 0;
2669	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2670	offset = param_offset + params;
2671
2672	/* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
2673	data_offset = (char *)(pSMB) + offset + 4;
2674	rename_info = (struct set_file_rename *) data_offset;
2675	pSMB->MaxParameterCount = cpu_to_le16(2);
2676	pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2677	pSMB->SetupCount = 1;
2678	pSMB->Reserved3 = 0;
2679	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2680	byte_count = 3 /* pad */  + params;
2681	pSMB->ParameterCount = cpu_to_le16(params);
2682	pSMB->TotalParameterCount = pSMB->ParameterCount;
2683	pSMB->ParameterOffset = cpu_to_le16(param_offset);
2684	pSMB->DataOffset = cpu_to_le16(offset);
2685	/* construct random name ".cifs_tmp<inodenum><mid>" */
2686	rename_info->overwrite = cpu_to_le32(1);
2687	rename_info->root_fid  = 0;
2688	/* unicode only call */
2689	if (target_name == NULL) {
2690		sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2691		len_of_str =
2692			cifsConvertToUTF16((__le16 *)rename_info->target_name,
2693					dummy_string, 24, nls_codepage, remap);
2694	} else {
2695		len_of_str =
2696			cifsConvertToUTF16((__le16 *)rename_info->target_name,
2697					target_name, PATH_MAX, nls_codepage,
2698					remap);
2699	}
2700	rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2701	count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2702	byte_count += count;
2703	pSMB->DataCount = cpu_to_le16(count);
2704	pSMB->TotalDataCount = pSMB->DataCount;
2705	pSMB->Fid = netfid;
2706	pSMB->InformationLevel =
2707		cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2708	pSMB->Reserved4 = 0;
2709	inc_rfc1001_len(pSMB, byte_count);
2710	pSMB->ByteCount = cpu_to_le16(byte_count);
2711	rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2712			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2713	cifs_stats_inc(&pTcon->stats.cifs_stats.num_t2renames);
2714	if (rc)
2715		cifs_dbg(FYI, "Send error in Rename (by file handle) = %d\n",
2716			 rc);
2717
2718	cifs_buf_release(pSMB);
2719
2720	/* Note: On -EAGAIN error only caller can retry on handle based calls
2721		since file handle passed in no longer valid */
2722
2723	return rc;
2724}
2725
2726int
2727CIFSSMBCopy(const unsigned int xid, struct cifs_tcon *tcon,
2728	    const char *fromName, const __u16 target_tid, const char *toName,
2729	    const int flags, const struct nls_table *nls_codepage, int remap)
2730{
2731	int rc = 0;
2732	COPY_REQ *pSMB = NULL;
2733	COPY_RSP *pSMBr = NULL;
2734	int bytes_returned;
2735	int name_len, name_len2;
2736	__u16 count;
2737
2738	cifs_dbg(FYI, "In CIFSSMBCopy\n");
2739copyRetry:
2740	rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2741			(void **) &pSMBr);
2742	if (rc)
2743		return rc;
2744
2745	pSMB->BufferFormat = 0x04;
2746	pSMB->Tid2 = target_tid;
2747
2748	pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2749
2750	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2751		name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2752					      fromName, PATH_MAX, nls_codepage,
2753					      remap);
2754		name_len++;     /* trailing null */
2755		name_len *= 2;
2756		pSMB->OldFileName[name_len] = 0x04;     /* pad */
2757		/* protocol requires ASCII signature byte on Unicode string */
2758		pSMB->OldFileName[name_len + 1] = 0x00;
2759		name_len2 =
2760		    cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2761				       toName, PATH_MAX, nls_codepage, remap);
2762		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2763		name_len2 *= 2; /* convert to bytes */
2764	} else {
2765		name_len = copy_path_name(pSMB->OldFileName, fromName);
2766		pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
2767		name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, toName);
2768		name_len2++;    /* signature byte */
2769	}
2770
2771	count = 1 /* 1st signature byte */  + name_len + name_len2;
2772	inc_rfc1001_len(pSMB, count);
2773	pSMB->ByteCount = cpu_to_le16(count);
2774
2775	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2776		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
2777	if (rc) {
2778		cifs_dbg(FYI, "Send error in copy = %d with %d files copied\n",
2779			 rc, le16_to_cpu(pSMBr->CopyCount));
2780	}
2781	cifs_buf_release(pSMB);
2782
2783	if (rc == -EAGAIN)
2784		goto copyRetry;
2785
2786	return rc;
2787}
2788
2789int
2790CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon,
2791		      const char *fromName, const char *toName,
2792		      const struct nls_table *nls_codepage, int remap)
2793{
2794	TRANSACTION2_SPI_REQ *pSMB = NULL;
2795	TRANSACTION2_SPI_RSP *pSMBr = NULL;
2796	char *data_offset;
2797	int name_len;
2798	int name_len_target;
2799	int rc = 0;
2800	int bytes_returned = 0;
2801	__u16 params, param_offset, offset, byte_count;
2802
2803	cifs_dbg(FYI, "In Symlink Unix style\n");
2804createSymLinkRetry:
2805	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2806		      (void **) &pSMBr);
2807	if (rc)
2808		return rc;
2809
2810	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2811		name_len =
2812		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fromName,
2813				/* find define for this maxpathcomponent */
2814					PATH_MAX, nls_codepage, remap);
2815		name_len++;	/* trailing null */
2816		name_len *= 2;
2817
2818	} else {
2819		name_len = copy_path_name(pSMB->FileName, fromName);
2820	}
2821	params = 6 + name_len;
2822	pSMB->MaxSetupCount = 0;
2823	pSMB->Reserved = 0;
2824	pSMB->Flags = 0;
2825	pSMB->Timeout = 0;
2826	pSMB->Reserved2 = 0;
2827	param_offset = offsetof(struct smb_com_transaction2_spi_req,
2828				InformationLevel) - 4;
2829	offset = param_offset + params;
2830
2831	/* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
2832	data_offset = (char *)pSMB + offset + 4;
2833	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2834		name_len_target =
2835		    cifsConvertToUTF16((__le16 *) data_offset, toName,
2836				/* find define for this maxpathcomponent */
2837					PATH_MAX, nls_codepage, remap);
2838		name_len_target++;	/* trailing null */
2839		name_len_target *= 2;
2840	} else {
2841		name_len_target = copy_path_name(data_offset, toName);
2842	}
2843
2844	pSMB->MaxParameterCount = cpu_to_le16(2);
2845	/* BB find exact max on data count below from sess */
2846	pSMB->MaxDataCount = cpu_to_le16(1000);
2847	pSMB->SetupCount = 1;
2848	pSMB->Reserved3 = 0;
2849	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2850	byte_count = 3 /* pad */  + params + name_len_target;
2851	pSMB->DataCount = cpu_to_le16(name_len_target);
2852	pSMB->ParameterCount = cpu_to_le16(params);
2853	pSMB->TotalDataCount = pSMB->DataCount;
2854	pSMB->TotalParameterCount = pSMB->ParameterCount;
2855	pSMB->ParameterOffset = cpu_to_le16(param_offset);
2856	pSMB->DataOffset = cpu_to_le16(offset);
2857	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2858	pSMB->Reserved4 = 0;
2859	inc_rfc1001_len(pSMB, byte_count);
2860	pSMB->ByteCount = cpu_to_le16(byte_count);
2861	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2862			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2863	cifs_stats_inc(&tcon->stats.cifs_stats.num_symlinks);
2864	if (rc)
2865		cifs_dbg(FYI, "Send error in SetPathInfo create symlink = %d\n",
2866			 rc);
2867
2868	cifs_buf_release(pSMB);
2869
2870	if (rc == -EAGAIN)
2871		goto createSymLinkRetry;
2872
2873	return rc;
2874}
2875
2876int
2877CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2878		       const char *fromName, const char *toName,
2879		       const struct nls_table *nls_codepage, int remap)
2880{
2881	TRANSACTION2_SPI_REQ *pSMB = NULL;
2882	TRANSACTION2_SPI_RSP *pSMBr = NULL;
2883	char *data_offset;
2884	int name_len;
2885	int name_len_target;
2886	int rc = 0;
2887	int bytes_returned = 0;
2888	__u16 params, param_offset, offset, byte_count;
2889
2890	cifs_dbg(FYI, "In Create Hard link Unix style\n");
2891createHardLinkRetry:
2892	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2893		      (void **) &pSMBr);
2894	if (rc)
2895		return rc;
2896
2897	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2898		name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,
2899					      PATH_MAX, nls_codepage, remap);
2900		name_len++;	/* trailing null */
2901		name_len *= 2;
2902
2903	} else {
2904		name_len = copy_path_name(pSMB->FileName, toName);
2905	}
2906	params = 6 + name_len;
2907	pSMB->MaxSetupCount = 0;
2908	pSMB->Reserved = 0;
2909	pSMB->Flags = 0;
2910	pSMB->Timeout = 0;
2911	pSMB->Reserved2 = 0;
2912	param_offset = offsetof(struct smb_com_transaction2_spi_req,
2913				InformationLevel) - 4;
2914	offset = param_offset + params;
2915
2916	/* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
2917	data_offset = (char *)pSMB + offset + 4;
2918	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2919		name_len_target =
2920		    cifsConvertToUTF16((__le16 *) data_offset, fromName,
2921				       PATH_MAX, nls_codepage, remap);
2922		name_len_target++;	/* trailing null */
2923		name_len_target *= 2;
2924	} else {
2925		name_len_target = copy_path_name(data_offset, fromName);
2926	}
2927
2928	pSMB->MaxParameterCount = cpu_to_le16(2);
2929	/* BB find exact max on data count below from sess*/
2930	pSMB->MaxDataCount = cpu_to_le16(1000);
2931	pSMB->SetupCount = 1;
2932	pSMB->Reserved3 = 0;
2933	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2934	byte_count = 3 /* pad */  + params + name_len_target;
2935	pSMB->ParameterCount = cpu_to_le16(params);
2936	pSMB->TotalParameterCount = pSMB->ParameterCount;
2937	pSMB->DataCount = cpu_to_le16(name_len_target);
2938	pSMB->TotalDataCount = pSMB->DataCount;
2939	pSMB->ParameterOffset = cpu_to_le16(param_offset);
2940	pSMB->DataOffset = cpu_to_le16(offset);
2941	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2942	pSMB->Reserved4 = 0;
2943	inc_rfc1001_len(pSMB, byte_count);
2944	pSMB->ByteCount = cpu_to_le16(byte_count);
2945	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2946			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2947	cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
2948	if (rc)
2949		cifs_dbg(FYI, "Send error in SetPathInfo (hard link) = %d\n",
2950			 rc);
2951
2952	cifs_buf_release(pSMB);
2953	if (rc == -EAGAIN)
2954		goto createHardLinkRetry;
2955
2956	return rc;
2957}
2958
2959int
2960CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2961		   const char *from_name, const char *to_name,
2962		   struct cifs_sb_info *cifs_sb)
2963{
2964	int rc = 0;
2965	NT_RENAME_REQ *pSMB = NULL;
2966	RENAME_RSP *pSMBr = NULL;
2967	int bytes_returned;
2968	int name_len, name_len2;
2969	__u16 count;
2970	int remap = cifs_remap(cifs_sb);
2971
2972	cifs_dbg(FYI, "In CIFSCreateHardLink\n");
2973winCreateHardLinkRetry:
2974
2975	rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2976		      (void **) &pSMBr);
2977	if (rc)
2978		return rc;
2979
2980	pSMB->SearchAttributes =
2981	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2982			ATTR_DIRECTORY);
2983	pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2984	pSMB->ClusterCount = 0;
2985
2986	pSMB->BufferFormat = 0x04;
2987
2988	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2989		name_len =
2990		    cifsConvertToUTF16((__le16 *) pSMB->OldFileName, from_name,
2991				       PATH_MAX, cifs_sb->local_nls, remap);
2992		name_len++;	/* trailing null */
2993		name_len *= 2;
2994
2995		/* protocol specifies ASCII buffer format (0x04) for unicode */
2996		pSMB->OldFileName[name_len] = 0x04;
2997		pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2998		name_len2 =
2999		    cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
3000				       to_name, PATH_MAX, cifs_sb->local_nls,
3001				       remap);
3002		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
3003		name_len2 *= 2;	/* convert to bytes */
3004	} else {
3005		name_len = copy_path_name(pSMB->OldFileName, from_name);
3006		pSMB->OldFileName[name_len] = 0x04;	/* 2nd buffer format */
3007		name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name);
3008		name_len2++;	/* signature byte */
3009	}
3010
3011	count = 1 /* string type byte */  + name_len + name_len2;
3012	inc_rfc1001_len(pSMB, count);
3013	pSMB->ByteCount = cpu_to_le16(count);
3014
3015	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3016			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3017	cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
3018	if (rc)
3019		cifs_dbg(FYI, "Send error in hard link (NT rename) = %d\n", rc);
3020
3021	cifs_buf_release(pSMB);
3022	if (rc == -EAGAIN)
3023		goto winCreateHardLinkRetry;
3024
3025	return rc;
3026}
3027
3028int
3029CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
3030			const unsigned char *searchName, char **symlinkinfo,
3031			const struct nls_table *nls_codepage, int remap)
3032{
3033/* SMB_QUERY_FILE_UNIX_LINK */
3034	TRANSACTION2_QPI_REQ *pSMB = NULL;
3035	TRANSACTION2_QPI_RSP *pSMBr = NULL;
3036	int rc = 0;
3037	int bytes_returned;
3038	int name_len;
3039	__u16 params, byte_count;
3040	char *data_start;
3041
3042	cifs_dbg(FYI, "In QPathSymLinkInfo (Unix) for path %s\n", searchName);
3043
3044querySymLinkRetry:
3045	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3046		      (void **) &pSMBr);
3047	if (rc)
3048		return rc;
3049
3050	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3051		name_len =
3052			cifsConvertToUTF16((__le16 *) pSMB->FileName,
3053					   searchName, PATH_MAX, nls_codepage,
3054					   remap);
3055		name_len++;	/* trailing null */
3056		name_len *= 2;
3057	} else {
3058		name_len = copy_path_name(pSMB->FileName, searchName);
3059	}
3060
3061	params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
3062	pSMB->TotalDataCount = 0;
3063	pSMB->MaxParameterCount = cpu_to_le16(2);
3064	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3065	pSMB->MaxSetupCount = 0;
3066	pSMB->Reserved = 0;
3067	pSMB->Flags = 0;
3068	pSMB->Timeout = 0;
3069	pSMB->Reserved2 = 0;
3070	pSMB->ParameterOffset = cpu_to_le16(offsetof(
3071	struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3072	pSMB->DataCount = 0;
3073	pSMB->DataOffset = 0;
3074	pSMB->SetupCount = 1;
3075	pSMB->Reserved3 = 0;
3076	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3077	byte_count = params + 1 /* pad */ ;
3078	pSMB->TotalParameterCount = cpu_to_le16(params);
3079	pSMB->ParameterCount = pSMB->TotalParameterCount;
3080	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
3081	pSMB->Reserved4 = 0;
3082	inc_rfc1001_len(pSMB, byte_count);
3083	pSMB->ByteCount = cpu_to_le16(byte_count);
3084
3085	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3086			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3087	if (rc) {
3088		cifs_dbg(FYI, "Send error in QuerySymLinkInfo = %d\n", rc);
3089	} else {
3090		/* decode response */
3091
3092		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3093		/* BB also check enough total bytes returned */
3094		if (rc || get_bcc(&pSMBr->hdr) < 2)
3095			rc = -EIO;
3096		else {
3097			bool is_unicode;
3098			u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3099
3100			data_start = ((char *) &pSMBr->hdr.Protocol) +
3101					   le16_to_cpu(pSMBr->t2.DataOffset);
3102
3103			if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3104				is_unicode = true;
3105			else
3106				is_unicode = false;
3107
3108			/* BB FIXME investigate remapping reserved chars here */
3109			*symlinkinfo = cifs_strndup_from_utf16(data_start,
3110					count, is_unicode, nls_codepage);
3111			if (!*symlinkinfo)
3112				rc = -ENOMEM;
3113		}
3114	}
3115	cifs_buf_release(pSMB);
3116	if (rc == -EAGAIN)
3117		goto querySymLinkRetry;
3118	return rc;
3119}
3120
3121/*
3122 *	Recent Windows versions now create symlinks more frequently
3123 *	and they use the "reparse point" mechanism below.  We can of course
3124 *	do symlinks nicely to Samba and other servers which support the
3125 *	CIFS Unix Extensions and we can also do SFU symlinks and "client only"
3126 *	"MF" symlinks optionally, but for recent Windows we really need to
3127 *	reenable the code below and fix the cifs_symlink callers to handle this.
3128 *	In the interim this code has been moved to its own config option so
3129 *	it is not compiled in by default until callers fixed up and more tested.
3130 */
3131int
3132CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
3133		    __u16 fid, char **symlinkinfo,
3134		    const struct nls_table *nls_codepage)
3135{
3136	int rc = 0;
3137	int bytes_returned;
3138	struct smb_com_transaction_ioctl_req *pSMB;
3139	struct smb_com_transaction_ioctl_rsp *pSMBr;
3140	bool is_unicode;
3141	unsigned int sub_len;
3142	char *sub_start;
3143	struct reparse_symlink_data *reparse_buf;
3144	struct reparse_posix_data *posix_buf;
3145	__u32 data_offset, data_count;
3146	char *end_of_smb;
3147
3148	cifs_dbg(FYI, "In Windows reparse style QueryLink for fid %u\n", fid);
3149	rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3150		      (void **) &pSMBr);
3151	if (rc)
3152		return rc;
3153
3154	pSMB->TotalParameterCount = 0 ;
3155	pSMB->TotalDataCount = 0;
3156	pSMB->MaxParameterCount = cpu_to_le32(2);
3157	/* BB find exact data count max from sess structure BB */
3158	pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3159	pSMB->MaxSetupCount = 4;
3160	pSMB->Reserved = 0;
3161	pSMB->ParameterOffset = 0;
3162	pSMB->DataCount = 0;
3163	pSMB->DataOffset = 0;
3164	pSMB->SetupCount = 4;
3165	pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3166	pSMB->ParameterCount = pSMB->TotalParameterCount;
3167	pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
3168	pSMB->IsFsctl = 1; /* FSCTL */
3169	pSMB->IsRootFlag = 0;
3170	pSMB->Fid = fid; /* file handle always le */
3171	pSMB->ByteCount = 0;
3172
3173	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3174			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3175	if (rc) {
3176		cifs_dbg(FYI, "Send error in QueryReparseLinkInfo = %d\n", rc);
3177		goto qreparse_out;
3178	}
3179
3180	data_offset = le32_to_cpu(pSMBr->DataOffset);
3181	data_count = le32_to_cpu(pSMBr->DataCount);
3182	if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
3183		/* BB also check enough total bytes returned */
3184		rc = -EIO;	/* bad smb */
3185		goto qreparse_out;
3186	}
3187	if (!data_count || (data_count > 2048)) {
3188		rc = -EIO;
3189		cifs_dbg(FYI, "Invalid return data count on get reparse info ioctl\n");
3190		goto qreparse_out;
3191	}
3192	end_of_smb = 2 + get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
3193	reparse_buf = (struct reparse_symlink_data *)
3194				((char *)&pSMBr->hdr.Protocol + data_offset);
3195	if ((char *)reparse_buf >= end_of_smb) {
3196		rc = -EIO;
3197		goto qreparse_out;
3198	}
3199	if (reparse_buf->ReparseTag == cpu_to_le32(IO_REPARSE_TAG_NFS)) {
3200		cifs_dbg(FYI, "NFS style reparse tag\n");
3201		posix_buf =  (struct reparse_posix_data *)reparse_buf;
3202
3203		if (posix_buf->InodeType != cpu_to_le64(NFS_SPECFILE_LNK)) {
3204			cifs_dbg(FYI, "unsupported file type 0x%llx\n",
3205				 le64_to_cpu(posix_buf->InodeType));
3206			rc = -EOPNOTSUPP;
3207			goto qreparse_out;
3208		}
3209		is_unicode = true;
3210		sub_len = le16_to_cpu(reparse_buf->ReparseDataLength);
3211		if (posix_buf->PathBuffer + sub_len > end_of_smb) {
3212			cifs_dbg(FYI, "reparse buf beyond SMB\n");
3213			rc = -EIO;
3214			goto qreparse_out;
3215		}
3216		*symlinkinfo = cifs_strndup_from_utf16(posix_buf->PathBuffer,
3217				sub_len, is_unicode, nls_codepage);
3218		goto qreparse_out;
3219	} else if (reparse_buf->ReparseTag !=
3220			cpu_to_le32(IO_REPARSE_TAG_SYMLINK)) {
3221		rc = -EOPNOTSUPP;
3222		goto qreparse_out;
3223	}
3224
3225	/* Reparse tag is NTFS symlink */
3226	sub_start = le16_to_cpu(reparse_buf->SubstituteNameOffset) +
3227				reparse_buf->PathBuffer;
3228	sub_len = le16_to_cpu(reparse_buf->SubstituteNameLength);
3229	if (sub_start + sub_len > end_of_smb) {
3230		cifs_dbg(FYI, "reparse buf beyond SMB\n");
3231		rc = -EIO;
3232		goto qreparse_out;
3233	}
3234	if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3235		is_unicode = true;
3236	else
3237		is_unicode = false;
3238
3239	/* BB FIXME investigate remapping reserved chars here */
3240	*symlinkinfo = cifs_strndup_from_utf16(sub_start, sub_len, is_unicode,
3241					       nls_codepage);
3242	if (!*symlinkinfo)
3243		rc = -ENOMEM;
3244qreparse_out:
3245	cifs_buf_release(pSMB);
3246
3247	/*
3248	 * Note: On -EAGAIN error only caller can retry on handle based calls
3249	 * since file handle passed in no longer valid.
3250	 */
3251	return rc;
3252}
3253
3254int
3255CIFSSMB_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
3256		    __u16 fid)
3257{
3258	int rc = 0;
3259	int bytes_returned;
3260	struct smb_com_transaction_compr_ioctl_req *pSMB;
3261	struct smb_com_transaction_ioctl_rsp *pSMBr;
3262
3263	cifs_dbg(FYI, "Set compression for %u\n", fid);
3264	rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3265		      (void **) &pSMBr);
3266	if (rc)
3267		return rc;
3268
3269	pSMB->compression_state = cpu_to_le16(COMPRESSION_FORMAT_DEFAULT);
3270
3271	pSMB->TotalParameterCount = 0;
3272	pSMB->TotalDataCount = cpu_to_le32(2);
3273	pSMB->MaxParameterCount = 0;
3274	pSMB->MaxDataCount = 0;
3275	pSMB->MaxSetupCount = 4;
3276	pSMB->Reserved = 0;
3277	pSMB->ParameterOffset = 0;
3278	pSMB->DataCount = cpu_to_le32(2);
3279	pSMB->DataOffset =
3280		cpu_to_le32(offsetof(struct smb_com_transaction_compr_ioctl_req,
3281				compression_state) - 4);  /* 84 */
3282	pSMB->SetupCount = 4;
3283	pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3284	pSMB->ParameterCount = 0;
3285	pSMB->FunctionCode = cpu_to_le32(FSCTL_SET_COMPRESSION);
3286	pSMB->IsFsctl = 1; /* FSCTL */
3287	pSMB->IsRootFlag = 0;
3288	pSMB->Fid = fid; /* file handle always le */
3289	/* 3 byte pad, followed by 2 byte compress state */
3290	pSMB->ByteCount = cpu_to_le16(5);
3291	inc_rfc1001_len(pSMB, 5);
3292
3293	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3294			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3295	if (rc)
3296		cifs_dbg(FYI, "Send error in SetCompression = %d\n", rc);
3297
3298	cifs_buf_release(pSMB);
3299
3300	/*
3301	 * Note: On -EAGAIN error only caller can retry on handle based calls
3302	 * since file handle passed in no longer valid.
3303	 */
3304	return rc;
3305}
3306
3307
3308#ifdef CONFIG_CIFS_POSIX
3309
3310/*Convert an Access Control Entry from wire format to local POSIX xattr format*/
3311static void cifs_convert_ace(struct posix_acl_xattr_entry *ace,
3312			     struct cifs_posix_ace *cifs_ace)
3313{
3314	/* u8 cifs fields do not need le conversion */
3315	ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
3316	ace->e_tag  = cpu_to_le16(cifs_ace->cifs_e_tag);
3317	ace->e_id   = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
3318/*
3319	cifs_dbg(FYI, "perm %d tag %d id %d\n",
3320		 ace->e_perm, ace->e_tag, ace->e_id);
3321*/
3322
3323	return;
3324}
3325
3326/* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
3327static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
3328			       const int acl_type, const int size_of_data_area)
3329{
3330	int size =  0;
3331	int i;
3332	__u16 count;
3333	struct cifs_posix_ace *pACE;
3334	struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
3335	struct posix_acl_xattr_header *local_acl = (void *)trgt;
3336
3337	if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
3338		return -EOPNOTSUPP;
3339
3340	if (acl_type == ACL_TYPE_ACCESS) {
3341		count = le16_to_cpu(cifs_acl->access_entry_count);
3342		pACE = &cifs_acl->ace_array[0];
3343		size = sizeof(struct cifs_posix_acl);
3344		size += sizeof(struct cifs_posix_ace) * count;
3345		/* check if we would go beyond end of SMB */
3346		if (size_of_data_area < size) {
3347			cifs_dbg(FYI, "bad CIFS POSIX ACL size %d vs. %d\n",
3348				 size_of_data_area, size);
3349			return -EINVAL;
3350		}
3351	} else if (acl_type == ACL_TYPE_DEFAULT) {
3352		count = le16_to_cpu(cifs_acl->access_entry_count);
3353		size = sizeof(struct cifs_posix_acl);
3354		size += sizeof(struct cifs_posix_ace) * count;
3355/* skip past access ACEs to get to default ACEs */
3356		pACE = &cifs_acl->ace_array[count];
3357		count = le16_to_cpu(cifs_acl->default_entry_count);
3358		size += sizeof(struct cifs_posix_ace) * count;
3359		/* check if we would go beyond end of SMB */
3360		if (size_of_data_area < size)
3361			return -EINVAL;
3362	} else {
3363		/* illegal type */
3364		return -EINVAL;
3365	}
3366
3367	size = posix_acl_xattr_size(count);
3368	if ((buflen == 0) || (local_acl == NULL)) {
3369		/* used to query ACL EA size */
3370	} else if (size > buflen) {
3371		return -ERANGE;
3372	} else /* buffer big enough */ {
3373		struct posix_acl_xattr_entry *ace = (void *)(local_acl + 1);
3374
3375		local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
3376		for (i = 0; i < count ; i++) {
3377			cifs_convert_ace(&ace[i], pACE);
3378			pACE++;
3379		}
3380	}
3381	return size;
3382}
3383
3384static void convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
3385				     const struct posix_acl_xattr_entry *local_ace)
3386{
3387	cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
3388	cifs_ace->cifs_e_tag =  le16_to_cpu(local_ace->e_tag);
3389	/* BB is there a better way to handle the large uid? */
3390	if (local_ace->e_id == cpu_to_le32(-1)) {
3391	/* Probably no need to le convert -1 on any arch but can not hurt */
3392		cifs_ace->cifs_uid = cpu_to_le64(-1);
3393	} else
3394		cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
3395/*
3396	cifs_dbg(FYI, "perm %d tag %d id %d\n",
3397		 ace->e_perm, ace->e_tag, ace->e_id);
3398*/
3399}
3400
3401/* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
3402static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
3403			       const int buflen, const int acl_type)
3404{
3405	__u16 rc = 0;
3406	struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
3407	struct posix_acl_xattr_header *local_acl = (void *)pACL;
3408	struct posix_acl_xattr_entry *ace = (void *)(local_acl + 1);
3409	int count;
3410	int i;
3411
3412	if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
3413		return 0;
3414
3415	count = posix_acl_xattr_count((size_t)buflen);
3416	cifs_dbg(FYI, "setting acl with %d entries from buf of length %d and version of %d\n",
3417		 count, buflen, le32_to_cpu(local_acl->a_version));
3418	if (le32_to_cpu(local_acl->a_version) != 2) {
3419		cifs_dbg(FYI, "unknown POSIX ACL version %d\n",
3420			 le32_to_cpu(local_acl->a_version));
3421		return 0;
3422	}
3423	cifs_acl->version = cpu_to_le16(1);
3424	if (acl_type == ACL_TYPE_ACCESS) {
3425		cifs_acl->access_entry_count = cpu_to_le16(count);
3426		cifs_acl->default_entry_count = cpu_to_le16(0xFFFF);
3427	} else if (acl_type == ACL_TYPE_DEFAULT) {
3428		cifs_acl->default_entry_count = cpu_to_le16(count);
3429		cifs_acl->access_entry_count = cpu_to_le16(0xFFFF);
3430	} else {
3431		cifs_dbg(FYI, "unknown ACL type %d\n", acl_type);
3432		return 0;
3433	}
3434	for (i = 0; i < count; i++)
3435		convert_ace_to_cifs_ace(&cifs_acl->ace_array[i], &ace[i]);
3436	if (rc == 0) {
3437		rc = (__u16)(count * sizeof(struct cifs_posix_ace));
3438		rc += sizeof(struct cifs_posix_acl);
3439		/* BB add check to make sure ACL does not overflow SMB */
3440	}
3441	return rc;
3442}
3443
3444int
3445CIFSSMBGetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3446		   const unsigned char *searchName,
3447		   char *acl_inf, const int buflen, const int acl_type,
3448		   const struct nls_table *nls_codepage, int remap)
3449{
3450/* SMB_QUERY_POSIX_ACL */
3451	TRANSACTION2_QPI_REQ *pSMB = NULL;
3452	TRANSACTION2_QPI_RSP *pSMBr = NULL;
3453	int rc = 0;
3454	int bytes_returned;
3455	int name_len;
3456	__u16 params, byte_count;
3457
3458	cifs_dbg(FYI, "In GetPosixACL (Unix) for path %s\n", searchName);
3459
3460queryAclRetry:
3461	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3462		(void **) &pSMBr);
3463	if (rc)
3464		return rc;
3465
3466	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3467		name_len =
3468			cifsConvertToUTF16((__le16 *) pSMB->FileName,
3469					   searchName, PATH_MAX, nls_codepage,
3470					   remap);
3471		name_len++;     /* trailing null */
3472		name_len *= 2;
3473		pSMB->FileName[name_len] = 0;
3474		pSMB->FileName[name_len+1] = 0;
3475	} else {
3476		name_len = copy_path_name(pSMB->FileName, searchName);
3477	}
3478
3479	params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
3480	pSMB->TotalDataCount = 0;
3481	pSMB->MaxParameterCount = cpu_to_le16(2);
3482	/* BB find exact max data count below from sess structure BB */
3483	pSMB->MaxDataCount = cpu_to_le16(4000);
3484	pSMB->MaxSetupCount = 0;
3485	pSMB->Reserved = 0;
3486	pSMB->Flags = 0;
3487	pSMB->Timeout = 0;
3488	pSMB->Reserved2 = 0;
3489	pSMB->ParameterOffset = cpu_to_le16(
3490		offsetof(struct smb_com_transaction2_qpi_req,
3491			 InformationLevel) - 4);
3492	pSMB->DataCount = 0;
3493	pSMB->DataOffset = 0;
3494	pSMB->SetupCount = 1;
3495	pSMB->Reserved3 = 0;
3496	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3497	byte_count = params + 1 /* pad */ ;
3498	pSMB->TotalParameterCount = cpu_to_le16(params);
3499	pSMB->ParameterCount = pSMB->TotalParameterCount;
3500	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
3501	pSMB->Reserved4 = 0;
3502	inc_rfc1001_len(pSMB, byte_count);
3503	pSMB->ByteCount = cpu_to_le16(byte_count);
3504
3505	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3506		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
3507	cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3508	if (rc) {
3509		cifs_dbg(FYI, "Send error in Query POSIX ACL = %d\n", rc);
3510	} else {
3511		/* decode response */
3512
3513		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3514		/* BB also check enough total bytes returned */
3515		if (rc || get_bcc(&pSMBr->hdr) < 2)
3516			rc = -EIO;      /* bad smb */
3517		else {
3518			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3519			__u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3520			rc = cifs_copy_posix_acl(acl_inf,
3521				(char *)&pSMBr->hdr.Protocol+data_offset,
3522				buflen, acl_type, count);
3523		}
3524	}
3525	cifs_buf_release(pSMB);
3526	if (rc == -EAGAIN)
3527		goto queryAclRetry;
3528	return rc;
3529}
3530
3531int
3532CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3533		   const unsigned char *fileName,
3534		   const char *local_acl, const int buflen,
3535		   const int acl_type,
3536		   const struct nls_table *nls_codepage, int remap)
3537{
3538	struct smb_com_transaction2_spi_req *pSMB = NULL;
3539	struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3540	char *parm_data;
3541	int name_len;
3542	int rc = 0;
3543	int bytes_returned = 0;
3544	__u16 params, byte_count, data_count, param_offset, offset;
3545
3546	cifs_dbg(FYI, "In SetPosixACL (Unix) for path %s\n", fileName);
3547setAclRetry:
3548	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3549		      (void **) &pSMBr);
3550	if (rc)
3551		return rc;
3552	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3553		name_len =
3554			cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
3555					   PATH_MAX, nls_codepage, remap);
3556		name_len++;     /* trailing null */
3557		name_len *= 2;
3558	} else {
3559		name_len = copy_path_name(pSMB->FileName, fileName);
3560	}
3561	params = 6 + name_len;
3562	pSMB->MaxParameterCount = cpu_to_le16(2);
3563	/* BB find max SMB size from sess */
3564	pSMB->MaxDataCount = cpu_to_le16(1000);
3565	pSMB->MaxSetupCount = 0;
3566	pSMB->Reserved = 0;
3567	pSMB->Flags = 0;
3568	pSMB->Timeout = 0;
3569	pSMB->Reserved2 = 0;
3570	param_offset = offsetof(struct smb_com_transaction2_spi_req,
3571				InformationLevel) - 4;
3572	offset = param_offset + params;
3573	parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
3574	pSMB->ParameterOffset = cpu_to_le16(param_offset);
3575
3576	/* convert to on the wire format for POSIX ACL */
3577	data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
3578
3579	if (data_count == 0) {
3580		rc = -EOPNOTSUPP;
3581		goto setACLerrorExit;
3582	}
3583	pSMB->DataOffset = cpu_to_le16(offset);
3584	pSMB->SetupCount = 1;
3585	pSMB->Reserved3 = 0;
3586	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3587	pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
3588	byte_count = 3 /* pad */  + params + data_count;
3589	pSMB->DataCount = cpu_to_le16(data_count);
3590	pSMB->TotalDataCount = pSMB->DataCount;
3591	pSMB->ParameterCount = cpu_to_le16(params);
3592	pSMB->TotalParameterCount = pSMB->ParameterCount;
3593	pSMB->Reserved4 = 0;
3594	inc_rfc1001_len(pSMB, byte_count);
3595	pSMB->ByteCount = cpu_to_le16(byte_count);
3596	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3597			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3598	if (rc)
3599		cifs_dbg(FYI, "Set POSIX ACL returned %d\n", rc);
3600
3601setACLerrorExit:
3602	cifs_buf_release(pSMB);
3603	if (rc == -EAGAIN)
3604		goto setAclRetry;
3605	return rc;
3606}
3607
3608/* BB fix tabs in this function FIXME BB */
3609int
3610CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
3611	       const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3612{
3613	int rc = 0;
3614	struct smb_t2_qfi_req *pSMB = NULL;
3615	struct smb_t2_qfi_rsp *pSMBr = NULL;
3616	int bytes_returned;
3617	__u16 params, byte_count;
3618
3619	cifs_dbg(FYI, "In GetExtAttr\n");
3620	if (tcon == NULL)
3621		return -ENODEV;
3622
3623GetExtAttrRetry:
3624	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3625			(void **) &pSMBr);
3626	if (rc)
3627		return rc;
3628
3629	params = 2 /* level */ + 2 /* fid */;
3630	pSMB->t2.TotalDataCount = 0;
3631	pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3632	/* BB find exact max data count below from sess structure BB */
3633	pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3634	pSMB->t2.MaxSetupCount = 0;
3635	pSMB->t2.Reserved = 0;
3636	pSMB->t2.Flags = 0;
3637	pSMB->t2.Timeout = 0;
3638	pSMB->t2.Reserved2 = 0;
3639	pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3640					       Fid) - 4);
3641	pSMB->t2.DataCount = 0;
3642	pSMB->t2.DataOffset = 0;
3643	pSMB->t2.SetupCount = 1;
3644	pSMB->t2.Reserved3 = 0;
3645	pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3646	byte_count = params + 1 /* pad */ ;
3647	pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3648	pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3649	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3650	pSMB->Pad = 0;
3651	pSMB->Fid = netfid;
3652	inc_rfc1001_len(pSMB, byte_count);
3653	pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3654
3655	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3656			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3657	if (rc) {
3658		cifs_dbg(FYI, "error %d in GetExtAttr\n", rc);
3659	} else {
3660		/* decode response */
3661		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3662		/* BB also check enough total bytes returned */
3663		if (rc || get_bcc(&pSMBr->hdr) < 2)
3664			/* If rc should we check for EOPNOSUPP and
3665			   disable the srvino flag? or in caller? */
3666			rc = -EIO;      /* bad smb */
3667		else {
3668			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3669			__u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3670			struct file_chattr_info *pfinfo;
3671			/* BB Do we need a cast or hash here ? */
3672			if (count != 16) {
3673				cifs_dbg(FYI, "Invalid size ret in GetExtAttr\n");
3674				rc = -EIO;
3675				goto GetExtAttrOut;
3676			}
3677			pfinfo = (struct file_chattr_info *)
3678				 (data_offset + (char *) &pSMBr->hdr.Protocol);
3679			*pExtAttrBits = le64_to_cpu(pfinfo->mode);
3680			*pMask = le64_to_cpu(pfinfo->mask);
3681		}
3682	}
3683GetExtAttrOut:
3684	cifs_buf_release(pSMB);
3685	if (rc == -EAGAIN)
3686		goto GetExtAttrRetry;
3687	return rc;
3688}
3689
3690#endif /* CONFIG_POSIX */
3691
3692/*
3693 * Initialize NT TRANSACT SMB into small smb request buffer.  This assumes that
3694 * all NT TRANSACTS that we init here have total parm and data under about 400
3695 * bytes (to fit in small cifs buffer size), which is the case so far, it
3696 * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3697 * returned setup area) and MaxParameterCount (returned parms size) must be set
3698 * by caller
3699 */
3700static int
3701smb_init_nttransact(const __u16 sub_command, const int setup_count,
3702		   const int parm_len, struct cifs_tcon *tcon,
3703		   void **ret_buf)
3704{
3705	int rc;
3706	__u32 temp_offset;
3707	struct smb_com_ntransact_req *pSMB;
3708
3709	rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
3710				(void **)&pSMB);
3711	if (rc)
3712		return rc;
3713	*ret_buf = (void *)pSMB;
3714	pSMB->Reserved = 0;
3715	pSMB->TotalParameterCount = cpu_to_le32(parm_len);
3716	pSMB->TotalDataCount  = 0;
3717	pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3718	pSMB->ParameterCount = pSMB->TotalParameterCount;
3719	pSMB->DataCount  = pSMB->TotalDataCount;
3720	temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3721			(setup_count * 2) - 4 /* for rfc1001 length itself */;
3722	pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3723	pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3724	pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
3725	pSMB->SubCommand = cpu_to_le16(sub_command);
3726	return 0;
3727}
3728
3729static int
3730validate_ntransact(char *buf, char **ppparm, char **ppdata,
3731		   __u32 *pparmlen, __u32 *pdatalen)
3732{
3733	char *end_of_smb;
3734	__u32 data_count, data_offset, parm_count, parm_offset;
3735	struct smb_com_ntransact_rsp *pSMBr;
3736	u16 bcc;
3737
3738	*pdatalen = 0;
3739	*pparmlen = 0;
3740
3741	if (buf == NULL)
3742		return -EINVAL;
3743
3744	pSMBr = (struct smb_com_ntransact_rsp *)buf;
3745
3746	bcc = get_bcc(&pSMBr->hdr);
3747	end_of_smb = 2 /* sizeof byte count */ + bcc +
3748			(char *)&pSMBr->ByteCount;
3749
3750	data_offset = le32_to_cpu(pSMBr->DataOffset);
3751	data_count = le32_to_cpu(pSMBr->DataCount);
3752	parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3753	parm_count = le32_to_cpu(pSMBr->ParameterCount);
3754
3755	*ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3756	*ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3757
3758	/* should we also check that parm and data areas do not overlap? */
3759	if (*ppparm > end_of_smb) {
3760		cifs_dbg(FYI, "parms start after end of smb\n");
3761		return -EINVAL;
3762	} else if (parm_count + *ppparm > end_of_smb) {
3763		cifs_dbg(FYI, "parm end after end of smb\n");
3764		return -EINVAL;
3765	} else if (*ppdata > end_of_smb) {
3766		cifs_dbg(FYI, "data starts after end of smb\n");
3767		return -EINVAL;
3768	} else if (data_count + *ppdata > end_of_smb) {
3769		cifs_dbg(FYI, "data %p + count %d (%p) past smb end %p start %p\n",
3770			 *ppdata, data_count, (data_count + *ppdata),
3771			 end_of_smb, pSMBr);
3772		return -EINVAL;
3773	} else if (parm_count + data_count > bcc) {
3774		cifs_dbg(FYI, "parm count and data count larger than SMB\n");
3775		return -EINVAL;
3776	}
3777	*pdatalen = data_count;
3778	*pparmlen = parm_count;
3779	return 0;
3780}
3781
3782/* Get Security Descriptor (by handle) from remote server for a file or dir */
3783int
3784CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3785		  struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3786{
3787	int rc = 0;
3788	int buf_type = 0;
3789	QUERY_SEC_DESC_REQ *pSMB;
3790	struct kvec iov[1];
3791	struct kvec rsp_iov;
3792
3793	cifs_dbg(FYI, "GetCifsACL\n");
3794
3795	*pbuflen = 0;
3796	*acl_inf = NULL;
3797
3798	rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3799			8 /* parm len */, tcon, (void **) &pSMB);
3800	if (rc)
3801		return rc;
3802
3803	pSMB->MaxParameterCount = cpu_to_le32(4);
3804	/* BB TEST with big acls that might need to be e.g. larger than 16K */
3805	pSMB->MaxSetupCount = 0;
3806	pSMB->Fid = fid; /* file handle always le */
3807	pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3808				     CIFS_ACL_DACL);
3809	pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3810	inc_rfc1001_len(pSMB, 11);
3811	iov[0].iov_base = (char *)pSMB;
3812	iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
3813
3814	rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3815			  0, &rsp_iov);
3816	cifs_small_buf_release(pSMB);
3817	cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3818	if (rc) {
3819		cifs_dbg(FYI, "Send error in QuerySecDesc = %d\n", rc);
3820	} else {                /* decode response */
3821		__le32 *parm;
3822		__u32 parm_len;
3823		__u32 acl_len;
3824		struct smb_com_ntransact_rsp *pSMBr;
3825		char *pdata;
3826
3827/* validate_nttransact */
3828		rc = validate_ntransact(rsp_iov.iov_base, (char **)&parm,
3829					&pdata, &parm_len, pbuflen);
3830		if (rc)
3831			goto qsec_out;
3832		pSMBr = (struct smb_com_ntransact_rsp *)rsp_iov.iov_base;
3833
3834		cifs_dbg(FYI, "smb %p parm %p data %p\n",
3835			 pSMBr, parm, *acl_inf);
3836
3837		if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3838			rc = -EIO;      /* bad smb */
3839			*pbuflen = 0;
3840			goto qsec_out;
3841		}
3842
3843/* BB check that data area is minimum length and as big as acl_len */
3844
3845		acl_len = le32_to_cpu(*parm);
3846		if (acl_len != *pbuflen) {
3847			cifs_dbg(VFS, "acl length %d does not match %d\n",
3848				 acl_len, *pbuflen);
3849			if (*pbuflen > acl_len)
3850				*pbuflen = acl_len;
3851		}
3852
3853		/* check if buffer is big enough for the acl
3854		   header followed by the smallest SID */
3855		if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3856		    (*pbuflen >= 64 * 1024)) {
3857			cifs_dbg(VFS, "bad acl length %d\n", *pbuflen);
3858			rc = -EINVAL;
3859			*pbuflen = 0;
3860		} else {
3861			*acl_inf = kmemdup(pdata, *pbuflen, GFP_KERNEL);
3862			if (*acl_inf == NULL) {
3863				*pbuflen = 0;
3864				rc = -ENOMEM;
3865			}
3866		}
3867	}
3868qsec_out:
3869	free_rsp_buf(buf_type, rsp_iov.iov_base);
3870	return rc;
3871}
3872
3873int
3874CIFSSMBSetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3875			struct cifs_ntsd *pntsd, __u32 acllen, int aclflag)
3876{
3877	__u16 byte_count, param_count, data_count, param_offset, data_offset;
3878	int rc = 0;
3879	int bytes_returned = 0;
3880	SET_SEC_DESC_REQ *pSMB = NULL;
3881	void *pSMBr;
3882
3883setCifsAclRetry:
3884	rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr);
3885	if (rc)
3886		return rc;
3887
3888	pSMB->MaxSetupCount = 0;
3889	pSMB->Reserved = 0;
3890
3891	param_count = 8;
3892	param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3893	data_count = acllen;
3894	data_offset = param_offset + param_count;
3895	byte_count = 3 /* pad */  + param_count;
3896
3897	pSMB->DataCount = cpu_to_le32(data_count);
3898	pSMB->TotalDataCount = pSMB->DataCount;
3899	pSMB->MaxParameterCount = cpu_to_le32(4);
3900	pSMB->MaxDataCount = cpu_to_le32(16384);
3901	pSMB->ParameterCount = cpu_to_le32(param_count);
3902	pSMB->ParameterOffset = cpu_to_le32(param_offset);
3903	pSMB->TotalParameterCount = pSMB->ParameterCount;
3904	pSMB->DataOffset = cpu_to_le32(data_offset);
3905	pSMB->SetupCount = 0;
3906	pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3907	pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3908
3909	pSMB->Fid = fid; /* file handle always le */
3910	pSMB->Reserved2 = 0;
3911	pSMB->AclFlags = cpu_to_le32(aclflag);
3912
3913	if (pntsd && acllen) {
3914		memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) +
3915				data_offset, pntsd, acllen);
3916		inc_rfc1001_len(pSMB, byte_count + data_count);
3917	} else
3918		inc_rfc1001_len(pSMB, byte_count);
3919
3920	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3921		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
3922
3923	cifs_dbg(FYI, "SetCIFSACL bytes_returned: %d, rc: %d\n",
3924		 bytes_returned, rc);
3925	if (rc)
3926		cifs_dbg(FYI, "Set CIFS ACL returned %d\n", rc);
3927	cifs_buf_release(pSMB);
3928
3929	if (rc == -EAGAIN)
3930		goto setCifsAclRetry;
3931
3932	return (rc);
3933}
3934
3935
3936/* Legacy Query Path Information call for lookup to old servers such
3937   as Win9x/WinME */
3938int
3939SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
3940		    const char *search_name, FILE_ALL_INFO *data,
3941		    const struct nls_table *nls_codepage, int remap)
3942{
3943	QUERY_INFORMATION_REQ *pSMB;
3944	QUERY_INFORMATION_RSP *pSMBr;
3945	int rc = 0;
3946	int bytes_returned;
3947	int name_len;
3948
3949	cifs_dbg(FYI, "In SMBQPath path %s\n", search_name);
3950QInfRetry:
3951	rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3952		      (void **) &pSMBr);
3953	if (rc)
3954		return rc;
3955
3956	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3957		name_len =
3958			cifsConvertToUTF16((__le16 *) pSMB->FileName,
3959					   search_name, PATH_MAX, nls_codepage,
3960					   remap);
3961		name_len++;     /* trailing null */
3962		name_len *= 2;
3963	} else {
3964		name_len = copy_path_name(pSMB->FileName, search_name);
3965	}
3966	pSMB->BufferFormat = 0x04;
3967	name_len++; /* account for buffer type byte */
3968	inc_rfc1001_len(pSMB, (__u16)name_len);
3969	pSMB->ByteCount = cpu_to_le16(name_len);
3970
3971	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3972			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3973	if (rc) {
3974		cifs_dbg(FYI, "Send error in QueryInfo = %d\n", rc);
3975	} else if (data) {
3976		struct timespec64 ts;
3977		__u32 time = le32_to_cpu(pSMBr->last_write_time);
3978
3979		/* decode response */
3980		/* BB FIXME - add time zone adjustment BB */
3981		memset(data, 0, sizeof(FILE_ALL_INFO));
3982		ts.tv_nsec = 0;
3983		ts.tv_sec = time;
3984		/* decode time fields */
3985		data->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3986		data->LastWriteTime = data->ChangeTime;
3987		data->LastAccessTime = 0;
3988		data->AllocationSize =
3989			cpu_to_le64(le32_to_cpu(pSMBr->size));
3990		data->EndOfFile = data->AllocationSize;
3991		data->Attributes =
3992			cpu_to_le32(le16_to_cpu(pSMBr->attr));
3993	} else
3994		rc = -EIO; /* bad buffer passed in */
3995
3996	cifs_buf_release(pSMB);
3997
3998	if (rc == -EAGAIN)
3999		goto QInfRetry;
4000
4001	return rc;
4002}
4003
4004int
4005CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
4006		 u16 netfid, FILE_ALL_INFO *pFindData)
4007{
4008	struct smb_t2_qfi_req *pSMB = NULL;
4009	struct smb_t2_qfi_rsp *pSMBr = NULL;
4010	int rc = 0;
4011	int bytes_returned;
4012	__u16 params, byte_count;
4013
4014QFileInfoRetry:
4015	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4016		      (void **) &pSMBr);
4017	if (rc)
4018		return rc;
4019
4020	params = 2 /* level */ + 2 /* fid */;
4021	pSMB->t2.TotalDataCount = 0;
4022	pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4023	/* BB find exact max data count below from sess structure BB */
4024	pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4025	pSMB->t2.MaxSetupCount = 0;
4026	pSMB->t2.Reserved = 0;
4027	pSMB->t2.Flags = 0;
4028	pSMB->t2.Timeout = 0;
4029	pSMB->t2.Reserved2 = 0;
4030	pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4031					       Fid) - 4);
4032	pSMB->t2.DataCount = 0;
4033	pSMB->t2.DataOffset = 0;
4034	pSMB->t2.SetupCount = 1;
4035	pSMB->t2.Reserved3 = 0;
4036	pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4037	byte_count = params + 1 /* pad */ ;
4038	pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4039	pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4040	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4041	pSMB->Pad = 0;
4042	pSMB->Fid = netfid;
4043	inc_rfc1001_len(pSMB, byte_count);
4044	pSMB->t2.ByteCount = cpu_to_le16(byte_count);
4045
4046	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4047			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4048	if (rc) {
4049		cifs_dbg(FYI, "Send error in QFileInfo = %d\n", rc);
4050	} else {		/* decode response */
4051		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4052
4053		if (rc) /* BB add auto retry on EOPNOTSUPP? */
4054			rc = -EIO;
4055		else if (get_bcc(&pSMBr->hdr) < 40)
4056			rc = -EIO;	/* bad smb */
4057		else if (pFindData) {
4058			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4059			memcpy((char *) pFindData,
4060			       (char *) &pSMBr->hdr.Protocol +
4061			       data_offset, sizeof(FILE_ALL_INFO));
4062		} else
4063		    rc = -ENOMEM;
4064	}
4065	cifs_buf_release(pSMB);
4066	if (rc == -EAGAIN)
4067		goto QFileInfoRetry;
4068
4069	return rc;
4070}
4071
4072int
4073CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
4074		 const char *search_name, FILE_ALL_INFO *data,
4075		 int legacy /* old style infolevel */,
4076		 const struct nls_table *nls_codepage, int remap)
4077{
4078	/* level 263 SMB_QUERY_FILE_ALL_INFO */
4079	TRANSACTION2_QPI_REQ *pSMB = NULL;
4080	TRANSACTION2_QPI_RSP *pSMBr = NULL;
4081	int rc = 0;
4082	int bytes_returned;
4083	int name_len;
4084	__u16 params, byte_count;
4085
4086	/* cifs_dbg(FYI, "In QPathInfo path %s\n", search_name); */
4087QPathInfoRetry:
4088	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4089		      (void **) &pSMBr);
4090	if (rc)
4091		return rc;
4092
4093	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4094		name_len =
4095		    cifsConvertToUTF16((__le16 *) pSMB->FileName, search_name,
4096				       PATH_MAX, nls_codepage, remap);
4097		name_len++;	/* trailing null */
4098		name_len *= 2;
4099	} else {
4100		name_len = copy_path_name(pSMB->FileName, search_name);
4101	}
4102
4103	params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4104	pSMB->TotalDataCount = 0;
4105	pSMB->MaxParameterCount = cpu_to_le16(2);
4106	/* BB find exact max SMB PDU from sess structure BB */
4107	pSMB->MaxDataCount = cpu_to_le16(4000);
4108	pSMB->MaxSetupCount = 0;
4109	pSMB->Reserved = 0;
4110	pSMB->Flags = 0;
4111	pSMB->Timeout = 0;
4112	pSMB->Reserved2 = 0;
4113	pSMB->ParameterOffset = cpu_to_le16(offsetof(
4114	struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4115	pSMB->DataCount = 0;
4116	pSMB->DataOffset = 0;
4117	pSMB->SetupCount = 1;
4118	pSMB->Reserved3 = 0;
4119	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4120	byte_count = params + 1 /* pad */ ;
4121	pSMB->TotalParameterCount = cpu_to_le16(params);
4122	pSMB->ParameterCount = pSMB->TotalParameterCount;
4123	if (legacy)
4124		pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
4125	else
4126		pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4127	pSMB->Reserved4 = 0;
4128	inc_rfc1001_len(pSMB, byte_count);
4129	pSMB->ByteCount = cpu_to_le16(byte_count);
4130
4131	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4132			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4133	if (rc) {
4134		cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
4135	} else {		/* decode response */
4136		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4137
4138		if (rc) /* BB add auto retry on EOPNOTSUPP? */
4139			rc = -EIO;
4140		else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
4141			rc = -EIO;	/* bad smb */
4142		else if (legacy && get_bcc(&pSMBr->hdr) < 24)
4143			rc = -EIO;  /* 24 or 26 expected but we do not read
4144					last field */
4145		else if (data) {
4146			int size;
4147			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4148
4149			/*
4150			 * On legacy responses we do not read the last field,
4151			 * EAsize, fortunately since it varies by subdialect and
4152			 * also note it differs on Set vs Get, ie two bytes or 4
4153			 * bytes depending but we don't care here.
4154			 */
4155			if (legacy)
4156				size = sizeof(FILE_INFO_STANDARD);
4157			else
4158				size = sizeof(FILE_ALL_INFO);
4159			memcpy((char *) data, (char *) &pSMBr->hdr.Protocol +
4160			       data_offset, size);
4161		} else
4162		    rc = -ENOMEM;
4163	}
4164	cifs_buf_release(pSMB);
4165	if (rc == -EAGAIN)
4166		goto QPathInfoRetry;
4167
4168	return rc;
4169}
4170
4171int
4172CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
4173		 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
4174{
4175	struct smb_t2_qfi_req *pSMB = NULL;
4176	struct smb_t2_qfi_rsp *pSMBr = NULL;
4177	int rc = 0;
4178	int bytes_returned;
4179	__u16 params, byte_count;
4180
4181UnixQFileInfoRetry:
4182	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4183		      (void **) &pSMBr);
4184	if (rc)
4185		return rc;
4186
4187	params = 2 /* level */ + 2 /* fid */;
4188	pSMB->t2.TotalDataCount = 0;
4189	pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4190	/* BB find exact max data count below from sess structure BB */
4191	pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4192	pSMB->t2.MaxSetupCount = 0;
4193	pSMB->t2.Reserved = 0;
4194	pSMB->t2.Flags = 0;
4195	pSMB->t2.Timeout = 0;
4196	pSMB->t2.Reserved2 = 0;
4197	pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4198					       Fid) - 4);
4199	pSMB->t2.DataCount = 0;
4200	pSMB->t2.DataOffset = 0;
4201	pSMB->t2.SetupCount = 1;
4202	pSMB->t2.Reserved3 = 0;
4203	pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4204	byte_count = params + 1 /* pad */ ;
4205	pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4206	pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4207	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4208	pSMB->Pad = 0;
4209	pSMB->Fid = netfid;
4210	inc_rfc1001_len(pSMB, byte_count);
4211	pSMB->t2.ByteCount = cpu_to_le16(byte_count);
4212
4213	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4214			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4215	if (rc) {
4216		cifs_dbg(FYI, "Send error in UnixQFileInfo = %d\n", rc);
4217	} else {		/* decode response */
4218		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4219
4220		if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4221			cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
4222			rc = -EIO;	/* bad smb */
4223		} else {
4224			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4225			memcpy((char *) pFindData,
4226			       (char *) &pSMBr->hdr.Protocol +
4227			       data_offset,
4228			       sizeof(FILE_UNIX_BASIC_INFO));
4229		}
4230	}
4231
4232	cifs_buf_release(pSMB);
4233	if (rc == -EAGAIN)
4234		goto UnixQFileInfoRetry;
4235
4236	return rc;
4237}
4238
4239int
4240CIFSSMBUnixQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
4241		     const unsigned char *searchName,
4242		     FILE_UNIX_BASIC_INFO *pFindData,
4243		     const struct nls_table *nls_codepage, int remap)
4244{
4245/* SMB_QUERY_FILE_UNIX_BASIC */
4246	TRANSACTION2_QPI_REQ *pSMB = NULL;
4247	TRANSACTION2_QPI_RSP *pSMBr = NULL;
4248	int rc = 0;
4249	int bytes_returned = 0;
4250	int name_len;
4251	__u16 params, byte_count;
4252
4253	cifs_dbg(FYI, "In QPathInfo (Unix) the path %s\n", searchName);
4254UnixQPathInfoRetry:
4255	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4256		      (void **) &pSMBr);
4257	if (rc)
4258		return rc;
4259
4260	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4261		name_len =
4262		    cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4263				       PATH_MAX, nls_codepage, remap);
4264		name_len++;	/* trailing null */
4265		name_len *= 2;
4266	} else {
4267		name_len = copy_path_name(pSMB->FileName, searchName);
4268	}
4269
4270	params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4271	pSMB->TotalDataCount = 0;
4272	pSMB->MaxParameterCount = cpu_to_le16(2);
4273	/* BB find exact max SMB PDU from sess structure BB */
4274	pSMB->MaxDataCount = cpu_to_le16(4000);
4275	pSMB->MaxSetupCount = 0;
4276	pSMB->Reserved = 0;
4277	pSMB->Flags = 0;
4278	pSMB->Timeout = 0;
4279	pSMB->Reserved2 = 0;
4280	pSMB->ParameterOffset = cpu_to_le16(offsetof(
4281	struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4282	pSMB->DataCount = 0;
4283	pSMB->DataOffset = 0;
4284	pSMB->SetupCount = 1;
4285	pSMB->Reserved3 = 0;
4286	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4287	byte_count = params + 1 /* pad */ ;
4288	pSMB->TotalParameterCount = cpu_to_le16(params);
4289	pSMB->ParameterCount = pSMB->TotalParameterCount;
4290	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4291	pSMB->Reserved4 = 0;
4292	inc_rfc1001_len(pSMB, byte_count);
4293	pSMB->ByteCount = cpu_to_le16(byte_count);
4294
4295	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4296			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4297	if (rc) {
4298		cifs_dbg(FYI, "Send error in UnixQPathInfo = %d\n", rc);
4299	} else {		/* decode response */
4300		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4301
4302		if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4303			cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
4304			rc = -EIO;	/* bad smb */
4305		} else {
4306			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4307			memcpy((char *) pFindData,
4308			       (char *) &pSMBr->hdr.Protocol +
4309			       data_offset,
4310			       sizeof(FILE_UNIX_BASIC_INFO));
4311		}
4312	}
4313	cifs_buf_release(pSMB);
4314	if (rc == -EAGAIN)
4315		goto UnixQPathInfoRetry;
4316
4317	return rc;
4318}
4319
4320/* xid, tcon, searchName and codepage are input parms, rest are returned */
4321int
4322CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
4323	      const char *searchName, struct cifs_sb_info *cifs_sb,
4324	      __u16 *pnetfid, __u16 search_flags,
4325	      struct cifs_search_info *psrch_inf, bool msearch)
4326{
4327/* level 257 SMB_ */
4328	TRANSACTION2_FFIRST_REQ *pSMB = NULL;
4329	TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
4330	T2_FFIRST_RSP_PARMS *parms;
4331	int rc = 0;
4332	int bytes_returned = 0;
4333	int name_len, remap;
4334	__u16 params, byte_count;
4335	struct nls_table *nls_codepage;
4336
4337	cifs_dbg(FYI, "In FindFirst for %s\n", searchName);
4338
4339findFirstRetry:
4340	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4341		      (void **) &pSMBr);
4342	if (rc)
4343		return rc;
4344
4345	nls_codepage = cifs_sb->local_nls;
4346	remap = cifs_remap(cifs_sb);
4347
4348	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4349		name_len =
4350		    cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4351				       PATH_MAX, nls_codepage, remap);
4352		/* We can not add the asterik earlier in case
4353		it got remapped to 0xF03A as if it were part of the
4354		directory name instead of a wildcard */
4355		name_len *= 2;
4356		if (msearch) {
4357			pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb);
4358			pSMB->FileName[name_len+1] = 0;
4359			pSMB->FileName[name_len+2] = '*';
4360			pSMB->FileName[name_len+3] = 0;
4361			name_len += 4; /* now the trailing null */
4362			/* null terminate just in case */
4363			pSMB->FileName[name_len] = 0;
4364			pSMB->FileName[name_len+1] = 0;
4365			name_len += 2;
4366		}
4367	} else {
4368		name_len = copy_path_name(pSMB->FileName, searchName);
4369		if (msearch) {
4370			if (WARN_ON_ONCE(name_len > PATH_MAX-2))
4371				name_len = PATH_MAX-2;
4372			/* overwrite nul byte */
4373			pSMB->FileName[name_len-1] = CIFS_DIR_SEP(cifs_sb);
4374			pSMB->FileName[name_len] = '*';
4375			pSMB->FileName[name_len+1] = 0;
4376			name_len += 2;
4377		}
4378	}
4379
4380	params = 12 + name_len /* includes null */ ;
4381	pSMB->TotalDataCount = 0;	/* no EAs */
4382	pSMB->MaxParameterCount = cpu_to_le16(10);
4383	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4384	pSMB->MaxSetupCount = 0;
4385	pSMB->Reserved = 0;
4386	pSMB->Flags = 0;
4387	pSMB->Timeout = 0;
4388	pSMB->Reserved2 = 0;
4389	byte_count = params + 1 /* pad */ ;
4390	pSMB->TotalParameterCount = cpu_to_le16(params);
4391	pSMB->ParameterCount = pSMB->TotalParameterCount;
4392	pSMB->ParameterOffset = cpu_to_le16(
4393	      offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
4394		- 4);
4395	pSMB->DataCount = 0;
4396	pSMB->DataOffset = 0;
4397	pSMB->SetupCount = 1;	/* one byte, no need to make endian neutral */
4398	pSMB->Reserved3 = 0;
4399	pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
4400	pSMB->SearchAttributes =
4401	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
4402			ATTR_DIRECTORY);
4403	pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
4404	pSMB->SearchFlags = cpu_to_le16(search_flags);
4405	pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4406
4407	/* BB what should we set StorageType to? Does it matter? BB */
4408	pSMB->SearchStorageType = 0;
4409	inc_rfc1001_len(pSMB, byte_count);
4410	pSMB->ByteCount = cpu_to_le16(byte_count);
4411
4412	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4413			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4414	cifs_stats_inc(&tcon->stats.cifs_stats.num_ffirst);
4415
4416	if (rc) {/* BB add logic to retry regular search if Unix search
4417			rejected unexpectedly by server */
4418		/* BB Add code to handle unsupported level rc */
4419		cifs_dbg(FYI, "Error in FindFirst = %d\n", rc);
4420
4421		cifs_buf_release(pSMB);
4422
4423		/* BB eventually could optimize out free and realloc of buf */
4424		/*    for this case */
4425		if (rc == -EAGAIN)
4426			goto findFirstRetry;
4427	} else { /* decode response */
4428		/* BB remember to free buffer if error BB */
4429		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4430		if (rc == 0) {
4431			unsigned int lnoff;
4432
4433			if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4434				psrch_inf->unicode = true;
4435			else
4436				psrch_inf->unicode = false;
4437
4438			psrch_inf->ntwrk_buf_start = (char *)pSMBr;
4439			psrch_inf->smallBuf = false;
4440			psrch_inf->srch_entries_start =
4441				(char *) &pSMBr->hdr.Protocol +
4442					le16_to_cpu(pSMBr->t2.DataOffset);
4443			parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
4444			       le16_to_cpu(pSMBr->t2.ParameterOffset));
4445
4446			if (parms->EndofSearch)
4447				psrch_inf->endOfSearch = true;
4448			else
4449				psrch_inf->endOfSearch = false;
4450
4451			psrch_inf->entries_in_buffer =
4452					le16_to_cpu(parms->SearchCount);
4453			psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
4454				psrch_inf->entries_in_buffer;
4455			lnoff = le16_to_cpu(parms->LastNameOffset);
4456			if (CIFSMaxBufSize < lnoff) {
4457				cifs_dbg(VFS, "ignoring corrupt resume name\n");
4458				psrch_inf->last_entry = NULL;
4459				return rc;
4460			}
4461
4462			psrch_inf->last_entry = psrch_inf->srch_entries_start +
4463							lnoff;
4464
4465			if (pnetfid)
4466				*pnetfid = parms->SearchHandle;
4467		} else {
4468			cifs_buf_release(pSMB);
4469		}
4470	}
4471
4472	return rc;
4473}
4474
4475int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon,
4476		 __u16 searchHandle, __u16 search_flags,
4477		 struct cifs_search_info *psrch_inf)
4478{
4479	TRANSACTION2_FNEXT_REQ *pSMB = NULL;
4480	TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
4481	T2_FNEXT_RSP_PARMS *parms;
4482	char *response_data;
4483	int rc = 0;
4484	int bytes_returned;
4485	unsigned int name_len;
4486	__u16 params, byte_count;
4487
4488	cifs_dbg(FYI, "In FindNext\n");
4489
4490	if (psrch_inf->endOfSearch)
4491		return -ENOENT;
4492
4493	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4494		(void **) &pSMBr);
4495	if (rc)
4496		return rc;
4497
4498	params = 14; /* includes 2 bytes of null string, converted to LE below*/
4499	byte_count = 0;
4500	pSMB->TotalDataCount = 0;       /* no EAs */
4501	pSMB->MaxParameterCount = cpu_to_le16(8);
4502	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4503	pSMB->MaxSetupCount = 0;
4504	pSMB->Reserved = 0;
4505	pSMB->Flags = 0;
4506	pSMB->Timeout = 0;
4507	pSMB->Reserved2 = 0;
4508	pSMB->ParameterOffset =  cpu_to_le16(
4509	      offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
4510	pSMB->DataCount = 0;
4511	pSMB->DataOffset = 0;
4512	pSMB->SetupCount = 1;
4513	pSMB->Reserved3 = 0;
4514	pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
4515	pSMB->SearchHandle = searchHandle;      /* always kept as le */
4516	pSMB->SearchCount =
4517		cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
4518	pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4519	pSMB->ResumeKey = psrch_inf->resume_key;
4520	pSMB->SearchFlags = cpu_to_le16(search_flags);
4521
4522	name_len = psrch_inf->resume_name_len;
4523	params += name_len;
4524	if (name_len < PATH_MAX) {
4525		memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
4526		byte_count += name_len;
4527		/* 14 byte parm len above enough for 2 byte null terminator */
4528		pSMB->ResumeFileName[name_len] = 0;
4529		pSMB->ResumeFileName[name_len+1] = 0;
4530	} else {
4531		rc = -EINVAL;
4532		goto FNext2_err_exit;
4533	}
4534	byte_count = params + 1 /* pad */ ;
4535	pSMB->TotalParameterCount = cpu_to_le16(params);
4536	pSMB->ParameterCount = pSMB->TotalParameterCount;
4537	inc_rfc1001_len(pSMB, byte_count);
4538	pSMB->ByteCount = cpu_to_le16(byte_count);
4539
4540	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4541			(struct smb_hdr *) pSMBr, &bytes_returned, 0);
4542	cifs_stats_inc(&tcon->stats.cifs_stats.num_fnext);
4543	if (rc) {
4544		if (rc == -EBADF) {
4545			psrch_inf->endOfSearch = true;
4546			cifs_buf_release(pSMB);
4547			rc = 0; /* search probably was closed at end of search*/
4548		} else
4549			cifs_dbg(FYI, "FindNext returned = %d\n", rc);
4550	} else {                /* decode response */
4551		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4552
4553		if (rc == 0) {
4554			unsigned int lnoff;
4555
4556			/* BB fixme add lock for file (srch_info) struct here */
4557			if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4558				psrch_inf->unicode = true;
4559			else
4560				psrch_inf->unicode = false;
4561			response_data = (char *) &pSMBr->hdr.Protocol +
4562			       le16_to_cpu(pSMBr->t2.ParameterOffset);
4563			parms = (T2_FNEXT_RSP_PARMS *)response_data;
4564			response_data = (char *)&pSMBr->hdr.Protocol +
4565				le16_to_cpu(pSMBr->t2.DataOffset);
4566			if (psrch_inf->smallBuf)
4567				cifs_small_buf_release(
4568					psrch_inf->ntwrk_buf_start);
4569			else
4570				cifs_buf_release(psrch_inf->ntwrk_buf_start);
4571			psrch_inf->srch_entries_start = response_data;
4572			psrch_inf->ntwrk_buf_start = (char *)pSMB;
4573			psrch_inf->smallBuf = false;
4574			if (parms->EndofSearch)
4575				psrch_inf->endOfSearch = true;
4576			else
4577				psrch_inf->endOfSearch = false;
4578			psrch_inf->entries_in_buffer =
4579						le16_to_cpu(parms->SearchCount);
4580			psrch_inf->index_of_last_entry +=
4581				psrch_inf->entries_in_buffer;
4582			lnoff = le16_to_cpu(parms->LastNameOffset);
4583			if (CIFSMaxBufSize < lnoff) {
4584				cifs_dbg(VFS, "ignoring corrupt resume name\n");
4585				psrch_inf->last_entry = NULL;
4586				return rc;
4587			} else
4588				psrch_inf->last_entry =
4589					psrch_inf->srch_entries_start + lnoff;
4590
4591/*  cifs_dbg(FYI, "fnxt2 entries in buf %d index_of_last %d\n",
4592    psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
4593
4594			/* BB fixme add unlock here */
4595		}
4596
4597	}
4598
4599	/* BB On error, should we leave previous search buf (and count and
4600	last entry fields) intact or free the previous one? */
4601
4602	/* Note: On -EAGAIN error only caller can retry on handle based calls
4603	since file handle passed in no longer valid */
4604FNext2_err_exit:
4605	if (rc != 0)
4606		cifs_buf_release(pSMB);
4607	return rc;
4608}
4609
4610int
4611CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon,
4612	      const __u16 searchHandle)
4613{
4614	int rc = 0;
4615	FINDCLOSE_REQ *pSMB = NULL;
4616
4617	cifs_dbg(FYI, "In CIFSSMBFindClose\n");
4618	rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
4619
4620	/* no sense returning error if session restarted
4621		as file handle has been closed */
4622	if (rc == -EAGAIN)
4623		return 0;
4624	if (rc)
4625		return rc;
4626
4627	pSMB->FileID = searchHandle;
4628	pSMB->ByteCount = 0;
4629	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
4630	cifs_small_buf_release(pSMB);
4631	if (rc)
4632		cifs_dbg(VFS, "Send error in FindClose = %d\n", rc);
4633
4634	cifs_stats_inc(&tcon->stats.cifs_stats.num_fclose);
4635
4636	/* Since session is dead, search handle closed on server already */
4637	if (rc == -EAGAIN)
4638		rc = 0;
4639
4640	return rc;
4641}
4642
4643int
4644CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
4645		      const char *search_name, __u64 *inode_number,
4646		      const struct nls_table *nls_codepage, int remap)
4647{
4648	int rc = 0;
4649	TRANSACTION2_QPI_REQ *pSMB = NULL;
4650	TRANSACTION2_QPI_RSP *pSMBr = NULL;
4651	int name_len, bytes_returned;
4652	__u16 params, byte_count;
4653
4654	cifs_dbg(FYI, "In GetSrvInodeNum for %s\n", search_name);
4655	if (tcon == NULL)
4656		return -ENODEV;
4657
4658GetInodeNumberRetry:
4659	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4660		      (void **) &pSMBr);
4661	if (rc)
4662		return rc;
4663
4664	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4665		name_len =
4666			cifsConvertToUTF16((__le16 *) pSMB->FileName,
4667					   search_name, PATH_MAX, nls_codepage,
4668					   remap);
4669		name_len++;     /* trailing null */
4670		name_len *= 2;
4671	} else {
4672		name_len = copy_path_name(pSMB->FileName, search_name);
4673	}
4674
4675	params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
4676	pSMB->TotalDataCount = 0;
4677	pSMB->MaxParameterCount = cpu_to_le16(2);
4678	/* BB find exact max data count below from sess structure BB */
4679	pSMB->MaxDataCount = cpu_to_le16(4000);
4680	pSMB->MaxSetupCount = 0;
4681	pSMB->Reserved = 0;
4682	pSMB->Flags = 0;
4683	pSMB->Timeout = 0;
4684	pSMB->Reserved2 = 0;
4685	pSMB->ParameterOffset = cpu_to_le16(offsetof(
4686		struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4687	pSMB->DataCount = 0;
4688	pSMB->DataOffset = 0;
4689	pSMB->SetupCount = 1;
4690	pSMB->Reserved3 = 0;
4691	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4692	byte_count = params + 1 /* pad */ ;
4693	pSMB->TotalParameterCount = cpu_to_le16(params);
4694	pSMB->ParameterCount = pSMB->TotalParameterCount;
4695	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4696	pSMB->Reserved4 = 0;
4697	inc_rfc1001_len(pSMB, byte_count);
4698	pSMB->ByteCount = cpu_to_le16(byte_count);
4699
4700	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4701		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
4702	if (rc) {
4703		cifs_dbg(FYI, "error %d in QueryInternalInfo\n", rc);
4704	} else {
4705		/* decode response */
4706		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4707		/* BB also check enough total bytes returned */
4708		if (rc || get_bcc(&pSMBr->hdr) < 2)
4709			/* If rc should we check for EOPNOSUPP and
4710			disable the srvino flag? or in caller? */
4711			rc = -EIO;      /* bad smb */
4712		else {
4713			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4714			__u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4715			struct file_internal_info *pfinfo;
4716			/* BB Do we need a cast or hash here ? */
4717			if (count < 8) {
4718				cifs_dbg(FYI, "Invalid size ret in QryIntrnlInf\n");
4719				rc = -EIO;
4720				goto GetInodeNumOut;
4721			}
4722			pfinfo = (struct file_internal_info *)
4723				(data_offset + (char *) &pSMBr->hdr.Protocol);
4724			*inode_number = le64_to_cpu(pfinfo->UniqueId);
4725		}
4726	}
4727GetInodeNumOut:
4728	cifs_buf_release(pSMB);
4729	if (rc == -EAGAIN)
4730		goto GetInodeNumberRetry;
4731	return rc;
4732}
4733
4734int
4735CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
4736		const char *search_name, struct dfs_info3_param **target_nodes,
4737		unsigned int *num_of_nodes,
4738		const struct nls_table *nls_codepage, int remap)
4739{
4740/* TRANS2_GET_DFS_REFERRAL */
4741	TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4742	TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4743	int rc = 0;
4744	int bytes_returned;
4745	int name_len;
4746	__u16 params, byte_count;
4747	*num_of_nodes = 0;
4748	*target_nodes = NULL;
4749
4750	cifs_dbg(FYI, "In GetDFSRefer the path %s\n", search_name);
4751	if (ses == NULL || ses->tcon_ipc == NULL)
4752		return -ENODEV;
4753
4754getDFSRetry:
4755	rc = smb_init(SMB_COM_TRANSACTION2, 15, ses->tcon_ipc, (void **) &pSMB,
4756		      (void **) &pSMBr);
4757	if (rc)
4758		return rc;
4759
4760	/* server pointer checked in called function,
4761	but should never be null here anyway */
4762	pSMB->hdr.Mid = get_next_mid(ses->server);
4763	pSMB->hdr.Tid = ses->tcon_ipc->tid;
4764	pSMB->hdr.Uid = ses->Suid;
4765	if (ses->capabilities & CAP_STATUS32)
4766		pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4767	if (ses->capabilities & CAP_DFS)
4768		pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4769
4770	if (ses->capabilities & CAP_UNICODE) {
4771		pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4772		name_len =
4773		    cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
4774				       search_name, PATH_MAX, nls_codepage,
4775				       remap);
4776		name_len++;	/* trailing null */
4777		name_len *= 2;
4778	} else {	/* BB improve the check for buffer overruns BB */
4779		name_len = copy_path_name(pSMB->RequestFileName, search_name);
4780	}
4781
4782	if (ses->server->sign)
4783		pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4784
4785	pSMB->hdr.Uid = ses->Suid;
4786
4787	params = 2 /* level */  + name_len /*includes null */ ;
4788	pSMB->TotalDataCount = 0;
4789	pSMB->DataCount = 0;
4790	pSMB->DataOffset = 0;
4791	pSMB->MaxParameterCount = 0;
4792	/* BB find exact max SMB PDU from sess structure BB */
4793	pSMB->MaxDataCount = cpu_to_le16(4000);
4794	pSMB->MaxSetupCount = 0;
4795	pSMB->Reserved = 0;
4796	pSMB->Flags = 0;
4797	pSMB->Timeout = 0;
4798	pSMB->Reserved2 = 0;
4799	pSMB->ParameterOffset = cpu_to_le16(offsetof(
4800	  struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4801	pSMB->SetupCount = 1;
4802	pSMB->Reserved3 = 0;
4803	pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4804	byte_count = params + 3 /* pad */ ;
4805	pSMB->ParameterCount = cpu_to_le16(params);
4806	pSMB->TotalParameterCount = pSMB->ParameterCount;
4807	pSMB->MaxReferralLevel = cpu_to_le16(3);
4808	inc_rfc1001_len(pSMB, byte_count);
4809	pSMB->ByteCount = cpu_to_le16(byte_count);
4810
4811	rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4812			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4813	if (rc) {
4814		cifs_dbg(FYI, "Send error in GetDFSRefer = %d\n", rc);
4815		goto GetDFSRefExit;
4816	}
4817	rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4818
4819	/* BB Also check if enough total bytes returned? */
4820	if (rc || get_bcc(&pSMBr->hdr) < 17) {
4821		rc = -EIO;      /* bad smb */
4822		goto GetDFSRefExit;
4823	}
4824
4825	cifs_dbg(FYI, "Decoding GetDFSRefer response BCC: %d  Offset %d\n",
4826		 get_bcc(&pSMBr->hdr), le16_to_cpu(pSMBr->t2.DataOffset));
4827
4828	/* parse returned result into more usable form */
4829	rc = parse_dfs_referrals(&pSMBr->dfs_data,
4830				 le16_to_cpu(pSMBr->t2.DataCount),
4831				 num_of_nodes, target_nodes, nls_codepage,
4832				 remap, search_name,
4833				 (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) != 0);
4834
4835GetDFSRefExit:
4836	cifs_buf_release(pSMB);
4837
4838	if (rc == -EAGAIN)
4839		goto getDFSRetry;
4840
4841	return rc;
4842}
4843
4844/* Query File System Info such as free space to old servers such as Win 9x */
4845int
4846SMBOldQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4847	      struct kstatfs *FSData)
4848{
4849/* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4850	TRANSACTION2_QFSI_REQ *pSMB = NULL;
4851	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4852	FILE_SYSTEM_ALLOC_INFO *response_data;
4853	int rc = 0;
4854	int bytes_returned = 0;
4855	__u16 params, byte_count;
4856
4857	cifs_dbg(FYI, "OldQFSInfo\n");
4858oldQFSInfoRetry:
4859	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4860		(void **) &pSMBr);
4861	if (rc)
4862		return rc;
4863
4864	params = 2;     /* level */
4865	pSMB->TotalDataCount = 0;
4866	pSMB->MaxParameterCount = cpu_to_le16(2);
4867	pSMB->MaxDataCount = cpu_to_le16(1000);
4868	pSMB->MaxSetupCount = 0;
4869	pSMB->Reserved = 0;
4870	pSMB->Flags = 0;
4871	pSMB->Timeout = 0;
4872	pSMB->Reserved2 = 0;
4873	byte_count = params + 1 /* pad */ ;
4874	pSMB->TotalParameterCount = cpu_to_le16(params);
4875	pSMB->ParameterCount = pSMB->TotalParameterCount;
4876	pSMB->ParameterOffset = cpu_to_le16(offsetof(
4877	struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4878	pSMB->DataCount = 0;
4879	pSMB->DataOffset = 0;
4880	pSMB->SetupCount = 1;
4881	pSMB->Reserved3 = 0;
4882	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4883	pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4884	inc_rfc1001_len(pSMB, byte_count);
4885	pSMB->ByteCount = cpu_to_le16(byte_count);
4886
4887	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4888		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
4889	if (rc) {
4890		cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
4891	} else {                /* decode response */
4892		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4893
4894		if (rc || get_bcc(&pSMBr->hdr) < 18)
4895			rc = -EIO;      /* bad smb */
4896		else {
4897			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4898			cifs_dbg(FYI, "qfsinf resp BCC: %d  Offset %d\n",
4899				 get_bcc(&pSMBr->hdr), data_offset);
4900
4901			response_data = (FILE_SYSTEM_ALLOC_INFO *)
4902				(((char *) &pSMBr->hdr.Protocol) + data_offset);
4903			FSData->f_bsize =
4904				le16_to_cpu(response_data->BytesPerSector) *
4905				le32_to_cpu(response_data->
4906					SectorsPerAllocationUnit);
4907			/*
4908			 * much prefer larger but if server doesn't report
4909			 * a valid size than 4K is a reasonable minimum
4910			 */
4911			if (FSData->f_bsize < 512)
4912				FSData->f_bsize = 4096;
4913
4914			FSData->f_blocks =
4915			       le32_to_cpu(response_data->TotalAllocationUnits);
4916			FSData->f_bfree = FSData->f_bavail =
4917				le32_to_cpu(response_data->FreeAllocationUnits);
4918			cifs_dbg(FYI, "Blocks: %lld  Free: %lld Block size %ld\n",
4919				 (unsigned long long)FSData->f_blocks,
4920				 (unsigned long long)FSData->f_bfree,
4921				 FSData->f_bsize);
4922		}
4923	}
4924	cifs_buf_release(pSMB);
4925
4926	if (rc == -EAGAIN)
4927		goto oldQFSInfoRetry;
4928
4929	return rc;
4930}
4931
4932int
4933CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4934	       struct kstatfs *FSData)
4935{
4936/* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4937	TRANSACTION2_QFSI_REQ *pSMB = NULL;
4938	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4939	FILE_SYSTEM_INFO *response_data;
4940	int rc = 0;
4941	int bytes_returned = 0;
4942	__u16 params, byte_count;
4943
4944	cifs_dbg(FYI, "In QFSInfo\n");
4945QFSInfoRetry:
4946	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4947		      (void **) &pSMBr);
4948	if (rc)
4949		return rc;
4950
4951	params = 2;	/* level */
4952	pSMB->TotalDataCount = 0;
4953	pSMB->MaxParameterCount = cpu_to_le16(2);
4954	pSMB->MaxDataCount = cpu_to_le16(1000);
4955	pSMB->MaxSetupCount = 0;
4956	pSMB->Reserved = 0;
4957	pSMB->Flags = 0;
4958	pSMB->Timeout = 0;
4959	pSMB->Reserved2 = 0;
4960	byte_count = params + 1 /* pad */ ;
4961	pSMB->TotalParameterCount = cpu_to_le16(params);
4962	pSMB->ParameterCount = pSMB->TotalParameterCount;
4963	pSMB->ParameterOffset = cpu_to_le16(offsetof(
4964		struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4965	pSMB->DataCount = 0;
4966	pSMB->DataOffset = 0;
4967	pSMB->SetupCount = 1;
4968	pSMB->Reserved3 = 0;
4969	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4970	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4971	inc_rfc1001_len(pSMB, byte_count);
4972	pSMB->ByteCount = cpu_to_le16(byte_count);
4973
4974	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4975			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4976	if (rc) {
4977		cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
4978	} else {		/* decode response */
4979		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4980
4981		if (rc || get_bcc(&pSMBr->hdr) < 24)
4982			rc = -EIO;	/* bad smb */
4983		else {
4984			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4985
4986			response_data =
4987			    (FILE_SYSTEM_INFO
4988			     *) (((char *) &pSMBr->hdr.Protocol) +
4989				 data_offset);
4990			FSData->f_bsize =
4991			    le32_to_cpu(response_data->BytesPerSector) *
4992			    le32_to_cpu(response_data->
4993					SectorsPerAllocationUnit);
4994			/*
4995			 * much prefer larger but if server doesn't report
4996			 * a valid size than 4K is a reasonable minimum
4997			 */
4998			if (FSData->f_bsize < 512)
4999				FSData->f_bsize = 4096;
5000
5001			FSData->f_blocks =
5002			    le64_to_cpu(response_data->TotalAllocationUnits);
5003			FSData->f_bfree = FSData->f_bavail =
5004			    le64_to_cpu(response_data->FreeAllocationUnits);
5005			cifs_dbg(FYI, "Blocks: %lld  Free: %lld Block size %ld\n",
5006				 (unsigned long long)FSData->f_blocks,
5007				 (unsigned long long)FSData->f_bfree,
5008				 FSData->f_bsize);
5009		}
5010	}
5011	cifs_buf_release(pSMB);
5012
5013	if (rc == -EAGAIN)
5014		goto QFSInfoRetry;
5015
5016	return rc;
5017}
5018
5019int
5020CIFSSMBQFSAttributeInfo(const unsigned int xid, struct cifs_tcon *tcon)
5021{
5022/* level 0x105  SMB_QUERY_FILE_SYSTEM_INFO */
5023	TRANSACTION2_QFSI_REQ *pSMB = NULL;
5024	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5025	FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
5026	int rc = 0;
5027	int bytes_returned = 0;
5028	__u16 params, byte_count;
5029
5030	cifs_dbg(FYI, "In QFSAttributeInfo\n");
5031QFSAttributeRetry:
5032	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5033		      (void **) &pSMBr);
5034	if (rc)
5035		return rc;
5036
5037	params = 2;	/* level */
5038	pSMB->TotalDataCount = 0;
5039	pSMB->MaxParameterCount = cpu_to_le16(2);
5040	/* BB find exact max SMB PDU from sess structure BB */
5041	pSMB->MaxDataCount = cpu_to_le16(1000);
5042	pSMB->MaxSetupCount = 0;
5043	pSMB->Reserved = 0;
5044	pSMB->Flags = 0;
5045	pSMB->Timeout = 0;
5046	pSMB->Reserved2 = 0;
5047	byte_count = params + 1 /* pad */ ;
5048	pSMB->TotalParameterCount = cpu_to_le16(params);
5049	pSMB->ParameterCount = pSMB->TotalParameterCount;
5050	pSMB->ParameterOffset = cpu_to_le16(offsetof(
5051		struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5052	pSMB->DataCount = 0;
5053	pSMB->DataOffset = 0;
5054	pSMB->SetupCount = 1;
5055	pSMB->Reserved3 = 0;
5056	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5057	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
5058	inc_rfc1001_len(pSMB, byte_count);
5059	pSMB->ByteCount = cpu_to_le16(byte_count);
5060
5061	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5062			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5063	if (rc) {
5064		cifs_dbg(VFS, "Send error in QFSAttributeInfo = %d\n", rc);
5065	} else {		/* decode response */
5066		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5067
5068		if (rc || get_bcc(&pSMBr->hdr) < 13) {
5069			/* BB also check if enough bytes returned */
5070			rc = -EIO;	/* bad smb */
5071		} else {
5072			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5073			response_data =
5074			    (FILE_SYSTEM_ATTRIBUTE_INFO
5075			     *) (((char *) &pSMBr->hdr.Protocol) +
5076				 data_offset);
5077			memcpy(&tcon->fsAttrInfo, response_data,
5078			       sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
5079		}
5080	}
5081	cifs_buf_release(pSMB);
5082
5083	if (rc == -EAGAIN)
5084		goto QFSAttributeRetry;
5085
5086	return rc;
5087}
5088
5089int
5090CIFSSMBQFSDeviceInfo(const unsigned int xid, struct cifs_tcon *tcon)
5091{
5092/* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
5093	TRANSACTION2_QFSI_REQ *pSMB = NULL;
5094	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5095	FILE_SYSTEM_DEVICE_INFO *response_data;
5096	int rc = 0;
5097	int bytes_returned = 0;
5098	__u16 params, byte_count;
5099
5100	cifs_dbg(FYI, "In QFSDeviceInfo\n");
5101QFSDeviceRetry:
5102	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5103		      (void **) &pSMBr);
5104	if (rc)
5105		return rc;
5106
5107	params = 2;	/* level */
5108	pSMB->TotalDataCount = 0;
5109	pSMB->MaxParameterCount = cpu_to_le16(2);
5110	/* BB find exact max SMB PDU from sess structure BB */
5111	pSMB->MaxDataCount = cpu_to_le16(1000);
5112	pSMB->MaxSetupCount = 0;
5113	pSMB->Reserved = 0;
5114	pSMB->Flags = 0;
5115	pSMB->Timeout = 0;
5116	pSMB->Reserved2 = 0;
5117	byte_count = params + 1 /* pad */ ;
5118	pSMB->TotalParameterCount = cpu_to_le16(params);
5119	pSMB->ParameterCount = pSMB->TotalParameterCount;
5120	pSMB->ParameterOffset = cpu_to_le16(offsetof(
5121		struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5122
5123	pSMB->DataCount = 0;
5124	pSMB->DataOffset = 0;
5125	pSMB->SetupCount = 1;
5126	pSMB->Reserved3 = 0;
5127	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5128	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
5129	inc_rfc1001_len(pSMB, byte_count);
5130	pSMB->ByteCount = cpu_to_le16(byte_count);
5131
5132	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5133			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5134	if (rc) {
5135		cifs_dbg(FYI, "Send error in QFSDeviceInfo = %d\n", rc);
5136	} else {		/* decode response */
5137		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5138
5139		if (rc || get_bcc(&pSMBr->hdr) <
5140			  sizeof(FILE_SYSTEM_DEVICE_INFO))
5141			rc = -EIO;	/* bad smb */
5142		else {
5143			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5144			response_data =
5145			    (FILE_SYSTEM_DEVICE_INFO *)
5146				(((char *) &pSMBr->hdr.Protocol) +
5147				 data_offset);
5148			memcpy(&tcon->fsDevInfo, response_data,
5149			       sizeof(FILE_SYSTEM_DEVICE_INFO));
5150		}
5151	}
5152	cifs_buf_release(pSMB);
5153
5154	if (rc == -EAGAIN)
5155		goto QFSDeviceRetry;
5156
5157	return rc;
5158}
5159
5160int
5161CIFSSMBQFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon)
5162{
5163/* level 0x200  SMB_QUERY_CIFS_UNIX_INFO */
5164	TRANSACTION2_QFSI_REQ *pSMB = NULL;
5165	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5166	FILE_SYSTEM_UNIX_INFO *response_data;
5167	int rc = 0;
5168	int bytes_returned = 0;
5169	__u16 params, byte_count;
5170
5171	cifs_dbg(FYI, "In QFSUnixInfo\n");
5172QFSUnixRetry:
5173	rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5174				   (void **) &pSMB, (void **) &pSMBr);
5175	if (rc)
5176		return rc;
5177
5178	params = 2;	/* level */
5179	pSMB->TotalDataCount = 0;
5180	pSMB->DataCount = 0;
5181	pSMB->DataOffset = 0;
5182	pSMB->MaxParameterCount = cpu_to_le16(2);
5183	/* BB find exact max SMB PDU from sess structure BB */
5184	pSMB->MaxDataCount = cpu_to_le16(100);
5185	pSMB->MaxSetupCount = 0;
5186	pSMB->Reserved = 0;
5187	pSMB->Flags = 0;
5188	pSMB->Timeout = 0;
5189	pSMB->Reserved2 = 0;
5190	byte_count = params + 1 /* pad */ ;
5191	pSMB->ParameterCount = cpu_to_le16(params);
5192	pSMB->TotalParameterCount = pSMB->ParameterCount;
5193	pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5194			smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5195	pSMB->SetupCount = 1;
5196	pSMB->Reserved3 = 0;
5197	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5198	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
5199	inc_rfc1001_len(pSMB, byte_count);
5200	pSMB->ByteCount = cpu_to_le16(byte_count);
5201
5202	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5203			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5204	if (rc) {
5205		cifs_dbg(VFS, "Send error in QFSUnixInfo = %d\n", rc);
5206	} else {		/* decode response */
5207		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5208
5209		if (rc || get_bcc(&pSMBr->hdr) < 13) {
5210			rc = -EIO;	/* bad smb */
5211		} else {
5212			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5213			response_data =
5214			    (FILE_SYSTEM_UNIX_INFO
5215			     *) (((char *) &pSMBr->hdr.Protocol) +
5216				 data_offset);
5217			memcpy(&tcon->fsUnixInfo, response_data,
5218			       sizeof(FILE_SYSTEM_UNIX_INFO));
5219		}
5220	}
5221	cifs_buf_release(pSMB);
5222
5223	if (rc == -EAGAIN)
5224		goto QFSUnixRetry;
5225
5226
5227	return rc;
5228}
5229
5230int
5231CIFSSMBSetFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon, __u64 cap)
5232{
5233/* level 0x200  SMB_SET_CIFS_UNIX_INFO */
5234	TRANSACTION2_SETFSI_REQ *pSMB = NULL;
5235	TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
5236	int rc = 0;
5237	int bytes_returned = 0;
5238	__u16 params, param_offset, offset, byte_count;
5239
5240	cifs_dbg(FYI, "In SETFSUnixInfo\n");
5241SETFSUnixRetry:
5242	/* BB switch to small buf init to save memory */
5243	rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5244					(void **) &pSMB, (void **) &pSMBr);
5245	if (rc)
5246		return rc;
5247
5248	params = 4;	/* 2 bytes zero followed by info level. */
5249	pSMB->MaxSetupCount = 0;
5250	pSMB->Reserved = 0;
5251	pSMB->Flags = 0;
5252	pSMB->Timeout = 0;
5253	pSMB->Reserved2 = 0;
5254