File Index
Files and directories
Sign in
FILE

cifssmb.c

File preview with syntax highlighting.

linux-6.19.14/fs/smb/client/cifssmb.c C
   1// SPDX-License-Identifier: LGPL-2.1
   2/*
   3 *
   4 *   Copyright (C) International Business Machines  Corp., 2002,2010
   5 *   Author(s): Steve French (sfrench@us.ibm.com)
   6 *
   7 *   Contains the routines for constructing the SMB PDUs themselves
   8 *
   9 */
  10
  11 /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c   */
  12 /* These are mostly routines that operate on a pathname, or on a tree id     */
  13 /* (mounted volume), but there are eight handle based routines which must be */
  14 /* treated slightly differently for reconnection purposes since we never     */
  15 /* want to reuse a stale file handle and only the caller knows the file info */
  16
  17#include <linux/fs.h>
  18#include <linux/filelock.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 <linux/netfs.h>
  28#include <trace/events/netfs.h>
  29#include "cifspdu.h"
  30#include "cifsfs.h"
  31#include "cifsglob.h"
  32#include "cifsacl.h"
  33#include "cifsproto.h"
  34#include "cifs_unicode.h"
  35#include "cifs_debug.h"
  36#include "fscache.h"
  37#include "smbdirect.h"
  38#ifdef CONFIG_CIFS_DFS_UPCALL
  39#include "dfs_cache.h"
  40#endif
  41
  42#ifdef CONFIG_CIFS_POSIX
  43static struct {
  44	int index;
  45	char *name;
  46} protocols[] = {
  47	{CIFS_PROT, "\2NT LM 0.12"},
  48	{POSIX_PROT, "\2POSIX 2"},
  49	{BAD_PROT, "\2"}
  50};
  51#else
  52static struct {
  53	int index;
  54	char *name;
  55} protocols[] = {
  56	{CIFS_PROT, "\2NT LM 0.12"},
  57	{BAD_PROT, "\2"}
  58};
  59#endif
  60
  61/* define the number of elements in the cifs dialect array */
  62#ifdef CONFIG_CIFS_POSIX
  63#define CIFS_NUM_PROT 2
  64#else /* not posix */
  65#define CIFS_NUM_PROT 1
  66#endif /* CIFS_POSIX */
  67
  68
  69/* reconnect the socket, tcon, and smb session if needed */
  70static int
  71cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
  72{
  73	struct TCP_Server_Info *server;
  74	struct cifs_ses *ses;
  75	int rc;
  76
  77	/*
  78	 * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
  79	 * tcp and smb session status done differently for those three - in the
  80	 * calling routine
  81	 */
  82	if (!tcon)
  83		return 0;
  84
  85	ses = tcon->ses;
  86	server = ses->server;
  87
  88	/*
  89	 * only tree disconnect, open, and write, (and ulogoff which does not
  90	 * have tcon) are allowed as we start umount
  91	 */
  92	spin_lock(&tcon->tc_lock);
  93	if (tcon->status == TID_EXITING) {
  94		if (smb_command != SMB_COM_TREE_DISCONNECT) {
  95			spin_unlock(&tcon->tc_lock);
  96			cifs_dbg(FYI, "can not send cmd %d while umounting\n",
  97				 smb_command);
  98			return -ENODEV;
  99		}
 100	}
 101	spin_unlock(&tcon->tc_lock);
 102
 103again:
 104	rc = cifs_wait_for_server_reconnect(server, tcon->retry);
 105	if (rc)
 106		return rc;
 107
 108	spin_lock(&ses->chan_lock);
 109	if (!cifs_chan_needs_reconnect(ses, server) && !tcon->need_reconnect) {
 110		spin_unlock(&ses->chan_lock);
 111		return 0;
 112	}
 113	spin_unlock(&ses->chan_lock);
 114
 115	mutex_lock(&ses->session_mutex);
 116	/*
 117	 * Handle the case where a concurrent thread failed to negotiate or
 118	 * killed a channel.
 119	 */
 120	spin_lock(&server->srv_lock);
 121	switch (server->tcpStatus) {
 122	case CifsExiting:
 123		spin_unlock(&server->srv_lock);
 124		mutex_unlock(&ses->session_mutex);
 125		return -EHOSTDOWN;
 126	case CifsNeedReconnect:
 127		spin_unlock(&server->srv_lock);
 128		mutex_unlock(&ses->session_mutex);
 129		if (!tcon->retry)
 130			return -EHOSTDOWN;
 131		goto again;
 132	default:
 133		break;
 134	}
 135	spin_unlock(&server->srv_lock);
 136
 137	/*
 138	 * need to prevent multiple threads trying to simultaneously
 139	 * reconnect the same SMB session
 140	 */
 141	spin_lock(&ses->ses_lock);
 142	spin_lock(&ses->chan_lock);
 143	if (!cifs_chan_needs_reconnect(ses, server) &&
 144	    ses->ses_status == SES_GOOD) {
 145		spin_unlock(&ses->chan_lock);
 146		spin_unlock(&ses->ses_lock);
 147
 148		/* this means that we only need to tree connect */
 149		if (tcon->need_reconnect)
 150			goto skip_sess_setup;
 151
 152		mutex_unlock(&ses->session_mutex);
 153		goto out;
 154	}
 155	spin_unlock(&ses->chan_lock);
 156	spin_unlock(&ses->ses_lock);
 157
 158	rc = cifs_negotiate_protocol(0, ses, server);
 159	if (rc) {
 160		mutex_unlock(&ses->session_mutex);
 161		if (!tcon->retry)
 162			return -EHOSTDOWN;
 163		goto again;
 164	}
 165	rc = cifs_setup_session(0, ses, server, ses->local_nls);
 166	if ((rc == -EACCES) || (rc == -EHOSTDOWN) || (rc == -EKEYREVOKED)) {
 167		/*
 168		 * Try alternate password for next reconnect if an alternate
 169		 * password is available.
 170		 */
 171		if (ses->password2)
 172			swap(ses->password2, ses->password);
 173	}
 174
 175	/* do we need to reconnect tcon? */
 176	if (rc || !tcon->need_reconnect) {
 177		mutex_unlock(&ses->session_mutex);
 178		goto out;
 179	}
 180
 181skip_sess_setup:
 182	cifs_mark_open_files_invalid(tcon);
 183	rc = cifs_tree_connect(0, tcon);
 184	mutex_unlock(&ses->session_mutex);
 185	cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc);
 186
 187	if (rc) {
 188		pr_warn_once("reconnect tcon failed rc = %d\n", rc);
 189		goto out;
 190	}
 191
 192	atomic_inc(&tconInfoReconnectCount);
 193
 194	/* tell server Unix caps we support */
 195	if (cap_unix(ses))
 196		reset_cifs_unix_caps(0, tcon, NULL, NULL);
 197
 198	/*
 199	 * Removed call to reopen open files here. It is safer (and faster) to
 200	 * reopen files one at a time as needed in read and write.
 201	 *
 202	 * FIXME: what about file locks? don't we need to reclaim them ASAP?
 203	 */
 204
 205out:
 206	/*
 207	 * Check if handle based operation so we know whether we can continue
 208	 * or not without returning to caller to reset file handle
 209	 */
 210	switch (smb_command) {
 211	case SMB_COM_READ_ANDX:
 212	case SMB_COM_WRITE_ANDX:
 213	case SMB_COM_CLOSE:
 214	case SMB_COM_FIND_CLOSE2:
 215	case SMB_COM_LOCKING_ANDX:
 216		rc = -EAGAIN;
 217	}
 218
 219	return rc;
 220}
 221
 222/* Allocate and return pointer to an SMB request buffer, and set basic
 223   SMB information in the SMB header.  If the return code is zero, this
 224   function must have filled in request_buf pointer */
 225static int
 226small_smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
 227		void **request_buf)
 228{
 229	unsigned int in_len;
 230	int rc;
 231
 232	rc = cifs_reconnect_tcon(tcon, smb_command);
 233	if (rc)
 234		return rc;
 235
 236	*request_buf = cifs_small_buf_get();
 237	if (*request_buf == NULL) {
 238		/* BB should we add a retry in here if not a writepage? */
 239		return -ENOMEM;
 240	}
 241
 242	in_len = header_assemble((struct smb_hdr *) *request_buf, smb_command,
 243				 tcon, wct);
 244
 245	if (tcon != NULL)
 246		cifs_stats_inc(&tcon->num_smbs_sent);
 247
 248	return in_len;
 249}
 250
 251int
 252small_smb_init_no_tc(const int smb_command, const int wct,
 253		     struct cifs_ses *ses, void **request_buf)
 254{
 255	int rc;
 256	struct smb_hdr *buffer;
 257
 258	rc = small_smb_init(smb_command, wct, NULL, request_buf);
 259	if (rc < 0)
 260		return rc;
 261
 262	buffer = (struct smb_hdr *)*request_buf;
 263	buffer->Mid = get_next_mid(ses->server);
 264	if (ses->capabilities & CAP_UNICODE)
 265		buffer->Flags2 |= SMBFLG2_UNICODE;
 266	if (ses->capabilities & CAP_STATUS32)
 267		buffer->Flags2 |= SMBFLG2_ERR_STATUS;
 268
 269	/* uid, tid can stay at zero as set in header assemble */
 270
 271	/* BB add support for turning on the signing when
 272	this function is used after 1st of session setup requests */
 273
 274	return rc;
 275}
 276
 277/* If the return code is zero, this function must fill in request_buf pointer */
 278static int
 279__smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
 280			void **request_buf, void **response_buf)
 281{
 282	unsigned int in_len;
 283
 284	*request_buf = cifs_buf_get();
 285	if (*request_buf == NULL) {
 286		/* BB should we add a retry in here if not a writepage? */
 287		return -ENOMEM;
 288	}
 289    /* Although the original thought was we needed the response buf for  */
 290    /* potential retries of smb operations it turns out we can determine */
 291    /* from the mid flags when the request buffer can be resent without  */
 292    /* having to use a second distinct buffer for the response */
 293	if (response_buf)
 294		*response_buf = *request_buf;
 295
 296	in_len = header_assemble((struct smb_hdr *)*request_buf, smb_command, tcon,
 297				 wct);
 298
 299	if (tcon != NULL)
 300		cifs_stats_inc(&tcon->num_smbs_sent);
 301
 302	return in_len;
 303}
 304
 305/* If the return code is zero, this function must fill in request_buf pointer */
 306static int
 307smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
 308	 void **request_buf, void **response_buf)
 309{
 310	int rc;
 311
 312	rc = cifs_reconnect_tcon(tcon, smb_command);
 313	if (rc)
 314		return rc;
 315
 316	return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
 317}
 318
 319static int
 320smb_init_no_reconnect(int smb_command, int wct, struct cifs_tcon *tcon,
 321			void **request_buf, void **response_buf)
 322{
 323	spin_lock(&tcon->ses->chan_lock);
 324	if (cifs_chan_needs_reconnect(tcon->ses, tcon->ses->server) ||
 325	    tcon->need_reconnect) {
 326		spin_unlock(&tcon->ses->chan_lock);
 327		return -EHOSTDOWN;
 328	}
 329	spin_unlock(&tcon->ses->chan_lock);
 330
 331	return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
 332}
 333
 334static int validate_t2(struct smb_t2_rsp *pSMB)
 335{
 336	unsigned int total_size;
 337
 338	/* check for plausible wct */
 339	if (pSMB->hdr.WordCount < 10)
 340		goto vt2_err;
 341
 342	/* check for parm and data offset going beyond end of smb */
 343	if (get_unaligned_le16(&pSMB->t2_rsp.ParameterOffset) > 1024 ||
 344	    get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024)
 345		goto vt2_err;
 346
 347	total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount);
 348	if (total_size >= 512)
 349		goto vt2_err;
 350
 351	/* check that bcc is at least as big as parms + data, and that it is
 352	 * less than negotiated smb buffer
 353	 */
 354	total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount);
 355	if (total_size > get_bcc(&pSMB->hdr) ||
 356	    total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)
 357		goto vt2_err;
 358
 359	return 0;
 360vt2_err:
 361	cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
 362		sizeof(struct smb_t2_rsp) + 16);
 363	return -EINVAL;
 364}
 365
 366static int
 367decode_ext_sec_blob(struct cifs_ses *ses, SMB_NEGOTIATE_RSP *pSMBr)
 368{
 369	int	rc = 0;
 370	u16	count;
 371	char	*guid = pSMBr->u.extended_response.GUID;
 372	struct TCP_Server_Info *server = ses->server;
 373
 374	count = get_bcc(&pSMBr->hdr);
 375	if (count < SMB1_CLIENT_GUID_SIZE)
 376		return smb_EIO2(smb_eio_trace_neg_sec_blob_too_small,
 377				count, SMB1_CLIENT_GUID_SIZE);
 378
 379	spin_lock(&cifs_tcp_ses_lock);
 380	if (server->srv_count > 1) {
 381		spin_unlock(&cifs_tcp_ses_lock);
 382		if (memcmp(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE) != 0) {
 383			cifs_dbg(FYI, "server UID changed\n");
 384			memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);
 385		}
 386	} else {
 387		spin_unlock(&cifs_tcp_ses_lock);
 388		memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);
 389	}
 390
 391	if (count == SMB1_CLIENT_GUID_SIZE) {
 392		server->sec_ntlmssp = true;
 393	} else {
 394		count -= SMB1_CLIENT_GUID_SIZE;
 395		rc = decode_negTokenInit(
 396			pSMBr->u.extended_response.SecurityBlob, count, server);
 397		if (rc != 1)
 398			return -EINVAL;
 399	}
 400
 401	return 0;
 402}
 403
 404static bool
 405should_set_ext_sec_flag(enum securityEnum sectype)
 406{
 407	switch (sectype) {
 408	case RawNTLMSSP:
 409	case Kerberos:
 410		return true;
 411	case Unspecified:
 412		if (global_secflags &
 413		    (CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_NTLMSSP))
 414			return true;
 415		fallthrough;
 416	default:
 417		return false;
 418	}
 419}
 420
 421int
 422CIFSSMBNegotiate(const unsigned int xid,
 423		 struct cifs_ses *ses,
 424		 struct TCP_Server_Info *server)
 425{
 426	SMB_NEGOTIATE_REQ *pSMB;
 427	SMB_NEGOTIATE_RSP *pSMBr;
 428	unsigned int in_len;
 429	int rc = 0;
 430	int bytes_returned;
 431	int i;
 432	u16 count;
 433
 434	if (!server) {
 435		WARN(1, "%s: server is NULL!\n", __func__);
 436		return smb_EIO(smb_eio_trace_null_pointers);
 437	}
 438
 439	rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
 440		      (void **) &pSMB, (void **) &pSMBr);
 441	if (rc < 0)
 442		return rc;
 443	in_len = rc;
 444
 445	pSMB->hdr.Mid = get_next_mid(server);
 446	pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
 447
 448	if (ses->unicode != 0)
 449		pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
 450
 451	if (should_set_ext_sec_flag(ses->sectype)) {
 452		cifs_dbg(FYI, "Requesting extended security\n");
 453		pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
 454	}
 455
 456	count = 0;
 457	/*
 458	 * We know that all the name entries in the protocols array
 459	 * are short (< 16 bytes anyway) and are NUL terminated.
 460	 */
 461	for (i = 0; i < CIFS_NUM_PROT; i++) {
 462		size_t len = strlen(protocols[i].name) + 1;
 463
 464		memcpy(&pSMB->DialectsArray[count], protocols[i].name, len);
 465		count += len;
 466	}
 467	in_len += count;
 468	pSMB->ByteCount = cpu_to_le16(count);
 469
 470	rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, in_len,
 471			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 472	if (rc != 0)
 473		goto neg_err_exit;
 474
 475	server->dialect = le16_to_cpu(pSMBr->DialectIndex);
 476	cifs_dbg(FYI, "Dialect: %d\n", server->dialect);
 477	/* Check wct = 1 error case */
 478	if ((pSMBr->hdr.WordCount <= 13) || (server->dialect == BAD_PROT)) {
 479		/* core returns wct = 1, but we do not ask for core - otherwise
 480		small wct just comes when dialect index is -1 indicating we
 481		could not negotiate a common dialect */
 482		rc = -EOPNOTSUPP;
 483		goto neg_err_exit;
 484	} else if (pSMBr->hdr.WordCount != 17) {
 485		/* unknown wct */
 486		rc = -EOPNOTSUPP;
 487		goto neg_err_exit;
 488	}
 489	/* else wct == 17, NTLM or better */
 490
 491	server->sec_mode = pSMBr->SecurityMode;
 492	if ((server->sec_mode & SECMODE_USER) == 0)
 493		cifs_dbg(FYI, "share mode security\n");
 494
 495	/* one byte, so no need to convert this or EncryptionKeyLen from
 496	   little endian */
 497	server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount),
 498			       cifs_max_pending);
 499	set_credits(server, server->maxReq);
 500	/* probably no need to store and check maxvcs */
 501	server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize);
 502	/* set up max_read for readahead check */
 503	server->max_read = server->maxBuf;
 504	server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
 505	cifs_dbg(NOISY, "Max buf = %d\n", ses->server->maxBuf);
 506	server->capabilities = le32_to_cpu(pSMBr->Capabilities);
 507	server->session_key_id = pSMBr->SessionKey;
 508	server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
 509	server->timeAdj *= 60;
 510
 511	if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
 512		server->negflavor = CIFS_NEGFLAVOR_UNENCAP;
 513		memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
 514		       CIFS_CRYPTO_KEY_SIZE);
 515	} else if (pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC ||
 516			server->capabilities & CAP_EXTENDED_SECURITY) {
 517		server->negflavor = CIFS_NEGFLAVOR_EXTENDED;
 518		rc = decode_ext_sec_blob(ses, pSMBr);
 519	} else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
 520		/* no crypt key only if plain text pwd */
 521		rc = smb_EIO(smb_eio_trace_neg_no_crypt_key);
 522	} else {
 523		server->negflavor = CIFS_NEGFLAVOR_UNENCAP;
 524		server->capabilities &= ~CAP_EXTENDED_SECURITY;
 525	}
 526
 527	if (!rc)
 528		rc = cifs_enable_signing(server, ses->sign);
 529neg_err_exit:
 530	cifs_buf_release(pSMB);
 531
 532	cifs_dbg(FYI, "negprot rc %d\n", rc);
 533	return rc;
 534}
 535
 536int
 537CIFSSMBTDis(const unsigned int xid, struct cifs_tcon *tcon)
 538{
 539	struct smb_hdr *smb_buffer;
 540	unsigned int in_len;
 541	int rc = 0;
 542
 543	cifs_dbg(FYI, "In tree disconnect\n");
 544
 545	/* BB: do we need to check this? These should never be NULL. */
 546	if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
 547		return smb_EIO(smb_eio_trace_null_pointers);
 548
 549	/*
 550	 * No need to return error on this operation if tid invalidated and
 551	 * closed on server already e.g. due to tcp session crashing. Also,
 552	 * the tcon is no longer on the list, so no need to take lock before
 553	 * checking this.
 554	 */
 555	spin_lock(&tcon->ses->chan_lock);
 556	if ((tcon->need_reconnect) || CIFS_ALL_CHANS_NEED_RECONNECT(tcon->ses)) {
 557		spin_unlock(&tcon->ses->chan_lock);
 558		return smb_EIO(smb_eio_trace_tdis_in_reconnect);
 559	}
 560	spin_unlock(&tcon->ses->chan_lock);
 561
 562	rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
 563			    (void **)&smb_buffer);
 564	if (rc < 0)
 565		return rc;
 566	in_len = rc;
 567
 568	rc = SendReceiveNoRsp(xid, tcon->ses, (char *)smb_buffer, in_len, 0);
 569	cifs_small_buf_release(smb_buffer);
 570	if (rc)
 571		cifs_dbg(FYI, "Tree disconnect failed %d\n", rc);
 572
 573	/* No need to return error on this operation if tid invalidated and
 574	   closed on server already e.g. due to tcp session crashing */
 575	if (rc == -EAGAIN)
 576		rc = 0;
 577
 578	return rc;
 579}
 580
 581/*
 582 * This is a no-op for now. We're not really interested in the reply, but
 583 * rather in the fact that the server sent one and that server->lstrp
 584 * gets updated.
 585 *
 586 * FIXME: maybe we should consider checking that the reply matches request?
 587 */
 588static void
 589cifs_echo_callback(struct TCP_Server_Info *server, struct mid_q_entry *mid)
 590{
 591	struct cifs_credits credits = { .value = 1, .instance = 0 };
 592
 593	release_mid(server, mid);
 594	add_credits(server, &credits, CIFS_ECHO_OP);
 595}
 596
 597int
 598CIFSSMBEcho(struct TCP_Server_Info *server)
 599{
 600	ECHO_REQ *smb;
 601	int rc = 0;
 602	struct kvec iov[1];
 603	struct smb_rqst rqst = {
 604		.rq_iov = iov,
 605		.rq_nvec = ARRAY_SIZE(iov),
 606	};
 607	unsigned int in_len;
 608
 609	cifs_dbg(FYI, "In echo request\n");
 610
 611	rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb);
 612	if (rc < 0)
 613		return rc;
 614	in_len = rc;
 615
 616	if (server->capabilities & CAP_UNICODE)
 617		smb->hdr.Flags2 |= SMBFLG2_UNICODE;
 618
 619	/* set up echo request */
 620	smb->hdr.Tid = 0xffff;
 621	smb->hdr.WordCount = 1;
 622	put_unaligned_le16(1, &smb->EchoCount);
 623	put_bcc(1, &smb->hdr);
 624	smb->Data[0] = 'a';
 625	in_len += 3;
 626
 627	iov[0].iov_len = in_len;
 628	iov[0].iov_base = smb;
 629
 630	rc = cifs_call_async(server, &rqst, NULL, cifs_echo_callback, NULL,
 631			     server, CIFS_NON_BLOCKING | CIFS_ECHO_OP, NULL);
 632	if (rc)
 633		cifs_dbg(FYI, "Echo request failed: %d\n", rc);
 634
 635	cifs_small_buf_release(smb);
 636
 637	return rc;
 638}
 639
 640int
 641CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses)
 642{
 643	LOGOFF_ANDX_REQ *pSMB;
 644	unsigned int in_len;
 645	int rc = 0;
 646
 647	cifs_dbg(FYI, "In SMBLogoff for session disconnect\n");
 648
 649	/*
 650	 * BB: do we need to check validity of ses and server? They should
 651	 * always be valid since we have an active reference. If not, that
 652	 * should probably be a BUG()
 653	 */
 654	if (!ses || !ses->server)
 655		return smb_EIO(smb_eio_trace_null_pointers);
 656
 657	mutex_lock(&ses->session_mutex);
 658	spin_lock(&ses->chan_lock);
 659	if (CIFS_ALL_CHANS_NEED_RECONNECT(ses)) {
 660		spin_unlock(&ses->chan_lock);
 661		goto session_already_dead; /* no need to send SMBlogoff if uid
 662					      already closed due to reconnect */
 663	}
 664	spin_unlock(&ses->chan_lock);
 665
 666	rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
 667	if (rc < 0) {
 668		mutex_unlock(&ses->session_mutex);
 669		return rc;
 670	}
 671	in_len = rc;
 672
 673	pSMB->hdr.Mid = get_next_mid(ses->server);
 674
 675	if (ses->server->sign)
 676		pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
 677
 678	pSMB->hdr.Uid = ses->Suid;
 679
 680	pSMB->AndXCommand = 0xFF;
 681	rc = SendReceiveNoRsp(xid, ses, (char *) pSMB, in_len, 0);
 682	cifs_small_buf_release(pSMB);
 683session_already_dead:
 684	mutex_unlock(&ses->session_mutex);
 685
 686	/* if session dead then we do not need to do ulogoff,
 687		since server closed smb session, no sense reporting
 688		error */
 689	if (rc == -EAGAIN)
 690		rc = 0;
 691	return rc;
 692}
 693
 694int
 695CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon,
 696		 const char *fileName, __u16 type,
 697		 const struct nls_table *nls_codepage, int remap)
 698{
 699	TRANSACTION2_SPI_REQ *pSMB = NULL;
 700	TRANSACTION2_SPI_RSP *pSMBr = NULL;
 701	struct unlink_psx_rq *pRqD;
 702	unsigned int in_len;
 703	int name_len;
 704	int rc = 0;
 705	int bytes_returned = 0;
 706	__u16 params, param_offset, offset, byte_count;
 707
 708	cifs_dbg(FYI, "In POSIX delete\n");
 709PsxDelete:
 710	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
 711		      (void **) &pSMBr);
 712	if (rc < 0)
 713		return rc;
 714	in_len = rc;
 715
 716	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 717		name_len =
 718		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
 719				       PATH_MAX, nls_codepage, remap);
 720		name_len++;	/* trailing null */
 721		name_len *= 2;
 722	} else {
 723		name_len = copy_path_name(pSMB->FileName, fileName);
 724	}
 725
 726	params = 6 + name_len;
 727	pSMB->MaxParameterCount = cpu_to_le16(2);
 728	pSMB->MaxDataCount = 0; /* BB double check this with jra */
 729	pSMB->MaxSetupCount = 0;
 730	pSMB->Reserved = 0;
 731	pSMB->Flags = 0;
 732	pSMB->Timeout = 0;
 733	pSMB->Reserved2 = 0;
 734	param_offset = offsetof(struct smb_com_transaction2_spi_req,
 735				InformationLevel);
 736	offset = param_offset + params;
 737
 738	/* Setup pointer to Request Data (inode type). */
 739	pRqD = (struct unlink_psx_rq *)((char *)(pSMB) + offset);
 740	pRqD->type = cpu_to_le16(type);
 741	pSMB->ParameterOffset = cpu_to_le16(param_offset);
 742	pSMB->DataOffset = cpu_to_le16(offset);
 743	pSMB->SetupCount = 1;
 744	pSMB->Reserved3 = 0;
 745	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
 746	byte_count = 3 /* pad */  + params + sizeof(struct unlink_psx_rq);
 747
 748	pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
 749	pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
 750	pSMB->ParameterCount = cpu_to_le16(params);
 751	pSMB->TotalParameterCount = pSMB->ParameterCount;
 752	pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
 753	pSMB->Reserved4 = 0;
 754	in_len += byte_count;
 755	pSMB->ByteCount = cpu_to_le16(byte_count);
 756	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
 757			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 758	if (rc)
 759		cifs_dbg(FYI, "Posix delete returned %d\n", rc);
 760	cifs_buf_release(pSMB);
 761
 762	cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
 763
 764	if (rc == -EAGAIN)
 765		goto PsxDelete;
 766
 767	return rc;
 768}
 769
 770int
 771CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
 772	       struct cifs_sb_info *cifs_sb, struct dentry *dentry)
 773{
 774	DELETE_FILE_REQ *pSMB = NULL;
 775	DELETE_FILE_RSP *pSMBr = NULL;
 776	unsigned int in_len;
 777	int rc = 0;
 778	int bytes_returned;
 779	int name_len;
 780	int remap = cifs_remap(cifs_sb);
 781
 782DelFileRetry:
 783	rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
 784		      (void **) &pSMBr);
 785	if (rc < 0)
 786		return rc;
 787	in_len = rc;
 788
 789	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 790		name_len = cifsConvertToUTF16((__le16 *) pSMB->fileName, name,
 791					      PATH_MAX, cifs_sb->local_nls,
 792					      remap);
 793		name_len++;	/* trailing null */
 794		name_len *= 2;
 795	} else {
 796		name_len = copy_path_name(pSMB->fileName, name);
 797	}
 798	pSMB->SearchAttributes =
 799	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
 800	pSMB->BufferFormat = 0x04;
 801	in_len += name_len + 1;
 802	pSMB->ByteCount = cpu_to_le16(name_len + 1);
 803	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
 804			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 805	cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
 806	if (rc)
 807		cifs_dbg(FYI, "Error in RMFile = %d\n", rc);
 808
 809	cifs_buf_release(pSMB);
 810	if (rc == -EAGAIN)
 811		goto DelFileRetry;
 812
 813	return rc;
 814}
 815
 816int
 817CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
 818	     struct cifs_sb_info *cifs_sb)
 819{
 820	DELETE_DIRECTORY_REQ *pSMB = NULL;
 821	DELETE_DIRECTORY_RSP *pSMBr = NULL;
 822	unsigned int in_len;
 823	int rc = 0;
 824	int bytes_returned;
 825	int name_len;
 826	int remap = cifs_remap(cifs_sb);
 827
 828	cifs_dbg(FYI, "In CIFSSMBRmDir\n");
 829RmDirRetry:
 830	rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
 831		      (void **) &pSMBr);
 832	if (rc < 0)
 833		return rc;
 834	in_len = rc;
 835
 836	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 837		name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
 838					      PATH_MAX, cifs_sb->local_nls,
 839					      remap);
 840		name_len++;	/* trailing null */
 841		name_len *= 2;
 842	} else {
 843		name_len = copy_path_name(pSMB->DirName, name);
 844	}
 845
 846	pSMB->BufferFormat = 0x04;
 847	in_len += name_len + 1;
 848	pSMB->ByteCount = cpu_to_le16(name_len + 1);
 849	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
 850			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 851	cifs_stats_inc(&tcon->stats.cifs_stats.num_rmdirs);
 852	if (rc)
 853		cifs_dbg(FYI, "Error in RMDir = %d\n", rc);
 854
 855	cifs_buf_release(pSMB);
 856	if (rc == -EAGAIN)
 857		goto RmDirRetry;
 858	return rc;
 859}
 860
 861int
 862CIFSSMBMkDir(const unsigned int xid, struct inode *inode, umode_t mode,
 863	     struct cifs_tcon *tcon, const char *name,
 864	     struct cifs_sb_info *cifs_sb)
 865{
 866	int rc = 0;
 867	CREATE_DIRECTORY_REQ *pSMB = NULL;
 868	CREATE_DIRECTORY_RSP *pSMBr = NULL;
 869	unsigned int in_len;
 870	int bytes_returned;
 871	int name_len;
 872	int remap = cifs_remap(cifs_sb);
 873
 874	cifs_dbg(FYI, "In CIFSSMBMkDir\n");
 875MkDirRetry:
 876	rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
 877		      (void **) &pSMBr);
 878	if (rc < 0)
 879		return rc;
 880	in_len = rc;
 881
 882	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 883		name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
 884					      PATH_MAX, cifs_sb->local_nls,
 885					      remap);
 886		name_len++;	/* trailing null */
 887		name_len *= 2;
 888	} else {
 889		name_len = copy_path_name(pSMB->DirName, name);
 890	}
 891
 892	pSMB->BufferFormat = 0x04;
 893	in_len += name_len + 1;
 894	pSMB->ByteCount = cpu_to_le16(name_len + 1);
 895	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
 896			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 897	cifs_stats_inc(&tcon->stats.cifs_stats.num_mkdirs);
 898	if (rc)
 899		cifs_dbg(FYI, "Error in Mkdir = %d\n", rc);
 900
 901	cifs_buf_release(pSMB);
 902	if (rc == -EAGAIN)
 903		goto MkDirRetry;
 904	return rc;
 905}
 906
 907int
 908CIFSPOSIXCreate(const unsigned int xid, struct cifs_tcon *tcon,
 909		__u32 posix_flags, __u64 mode, __u16 *netfid,
 910		FILE_UNIX_BASIC_INFO *pRetData, __u32 *pOplock,
 911		const char *name, const struct nls_table *nls_codepage,
 912		int remap)
 913{
 914	TRANSACTION2_SPI_REQ *pSMB = NULL;
 915	TRANSACTION2_SPI_RSP *pSMBr = NULL;
 916	unsigned int in_len;
 917	int name_len;
 918	int rc = 0;
 919	int bytes_returned = 0;
 920	__u16 params, param_offset, offset, byte_count, count;
 921	OPEN_PSX_REQ *pdata;
 922	OPEN_PSX_RSP *psx_rsp;
 923
 924	cifs_dbg(FYI, "In POSIX Create\n");
 925PsxCreat:
 926	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
 927		      (void **) &pSMBr);
 928	if (rc < 0)
 929		return rc;
 930	in_len = rc;
 931
 932	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 933		name_len =
 934		    cifsConvertToUTF16((__le16 *) pSMB->FileName, name,
 935				       PATH_MAX, nls_codepage, remap);
 936		name_len++;	/* trailing null */
 937		name_len *= 2;
 938	} else {
 939		name_len = copy_path_name(pSMB->FileName, name);
 940	}
 941
 942	params = 6 + name_len;
 943	count = sizeof(OPEN_PSX_REQ);
 944	pSMB->MaxParameterCount = cpu_to_le16(2);
 945	pSMB->MaxDataCount = cpu_to_le16(1000);	/* large enough */
 946	pSMB->MaxSetupCount = 0;
 947	pSMB->Reserved = 0;
 948	pSMB->Flags = 0;
 949	pSMB->Timeout = 0;
 950	pSMB->Reserved2 = 0;
 951	param_offset = offsetof(struct smb_com_transaction2_spi_req,
 952				InformationLevel);
 953	offset = param_offset + params;
 954	pdata = (OPEN_PSX_REQ *)((char *)(pSMB) + offset);
 955	pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
 956	pdata->Permissions = cpu_to_le64(mode);
 957	pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
 958	pdata->OpenFlags =  cpu_to_le32(*pOplock);
 959	pSMB->ParameterOffset = cpu_to_le16(param_offset);
 960	pSMB->DataOffset = cpu_to_le16(offset);
 961	pSMB->SetupCount = 1;
 962	pSMB->Reserved3 = 0;
 963	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
 964	byte_count = 3 /* pad */  + params + count;
 965
 966	pSMB->DataCount = cpu_to_le16(count);
 967	pSMB->ParameterCount = cpu_to_le16(params);
 968	pSMB->TotalDataCount = pSMB->DataCount;
 969	pSMB->TotalParameterCount = pSMB->ParameterCount;
 970	pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
 971	pSMB->Reserved4 = 0;
 972	in_len += byte_count;
 973	pSMB->ByteCount = cpu_to_le16(byte_count);
 974	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
 975			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 976	if (rc) {
 977		cifs_dbg(FYI, "Posix create returned %d\n", rc);
 978		goto psx_create_err;
 979	}
 980
 981	cifs_dbg(FYI, "copying inode info\n");
 982	rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 983
 984	if (rc || get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)) {
 985		rc = smb_EIO2(smb_eio_trace_create_rsp_too_small,
 986			      get_bcc(&pSMBr->hdr), sizeof(OPEN_PSX_RSP));
 987		goto psx_create_err;
 988	}
 989
 990	/* copy return information to pRetData */
 991	psx_rsp = (OPEN_PSX_RSP *)
 992		((char *)pSMBr + le16_to_cpu(pSMBr->t2.DataOffset));
 993
 994	*pOplock = le16_to_cpu(psx_rsp->OplockFlags);
 995	if (netfid)
 996		*netfid = psx_rsp->Fid;   /* cifs fid stays in le */
 997	/* Let caller know file was created so we can set the mode. */
 998	/* Do we care about the CreateAction in any other cases? */
 999	if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1000		*pOplock |= CIFS_CREATE_ACTION;
1001	/* check to make sure response data is there */
1002	if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1003		pRetData->Type = cpu_to_le32(-1); /* unknown */
1004		cifs_dbg(NOISY, "unknown type\n");
1005	} else {
1006		if (get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)
1007					+ sizeof(FILE_UNIX_BASIC_INFO)) {
1008			cifs_dbg(VFS, "Open response data too small\n");
1009			pRetData->Type = cpu_to_le32(-1);
1010			goto psx_create_err;
1011		}
1012		memcpy(pRetData,
1013		       (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1014		       sizeof(*pRetData));
1015	}
1016
1017psx_create_err:
1018	cifs_buf_release(pSMB);
1019
1020	if (posix_flags & SMB_O_DIRECTORY)
1021		cifs_stats_inc(&tcon->stats.cifs_stats.num_posixmkdirs);
1022	else
1023		cifs_stats_inc(&tcon->stats.cifs_stats.num_posixopens);
1024
1025	if (rc == -EAGAIN)
1026		goto PsxCreat;
1027
1028	return rc;
1029}
1030
1031static __u16 convert_disposition(int disposition)
1032{
1033	__u16 ofun = 0;
1034
1035	switch (disposition) {
1036		case FILE_SUPERSEDE:
1037			ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1038			break;
1039		case FILE_OPEN:
1040			ofun = SMBOPEN_OAPPEND;
1041			break;
1042		case FILE_CREATE:
1043			ofun = SMBOPEN_OCREATE;
1044			break;
1045		case FILE_OPEN_IF:
1046			ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1047			break;
1048		case FILE_OVERWRITE:
1049			ofun = SMBOPEN_OTRUNC;
1050			break;
1051		case FILE_OVERWRITE_IF:
1052			ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1053			break;
1054		default:
1055			cifs_dbg(FYI, "unknown disposition %d\n", disposition);
1056			ofun =  SMBOPEN_OAPPEND; /* regular open */
1057	}
1058	return ofun;
1059}
1060
1061static int
1062access_flags_to_smbopen_mode(const int access_flags)
1063{
1064	/*
1065	 * SYSTEM_SECURITY grants both read and write access to SACL, treat is as read/write.
1066	 * MAXIMUM_ALLOWED grants as many access as possible, so treat it as read/write too.
1067	 * SYNCHRONIZE as is does not grant any specific access, so do not check its mask.
1068	 * If only SYNCHRONIZE bit is specified then fallback to read access.
1069	 */
1070	bool with_write_flags = access_flags & (FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_WRITE_EA |
1071						FILE_DELETE_CHILD | FILE_WRITE_ATTRIBUTES | DELETE |
1072						WRITE_DAC | WRITE_OWNER | SYSTEM_SECURITY |
1073						MAXIMUM_ALLOWED | GENERIC_WRITE | GENERIC_ALL);
1074	bool with_read_flags = access_flags & (FILE_READ_DATA | FILE_READ_EA | FILE_EXECUTE |
1075						FILE_READ_ATTRIBUTES | READ_CONTROL |
1076						SYSTEM_SECURITY | MAXIMUM_ALLOWED | GENERIC_ALL |
1077						GENERIC_EXECUTE | GENERIC_READ);
1078	bool with_execute_flags = access_flags & (FILE_EXECUTE | MAXIMUM_ALLOWED | GENERIC_ALL |
1079						GENERIC_EXECUTE);
1080
1081	if (with_write_flags && with_read_flags)
1082		return SMBOPEN_READWRITE;
1083	else if (with_write_flags)
1084		return SMBOPEN_WRITE;
1085	else if (with_execute_flags)
1086		return SMBOPEN_EXECUTE;
1087	else
1088		return SMBOPEN_READ;
1089}
1090
1091int
1092SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon,
1093	    const char *fileName, const int openDisposition,
1094	    const int access_flags, const int create_options, __u16 *netfid,
1095	    int *pOplock, FILE_ALL_INFO *pfile_info,
1096	    const struct nls_table *nls_codepage, int remap)
1097{
1098	int rc;
1099	OPENX_REQ *pSMB = NULL;
1100	OPENX_RSP *pSMBr = NULL;
1101	unsigned int in_len;
1102	int bytes_returned;
1103	int name_len;
1104	__u16 count;
1105
1106OldOpenRetry:
1107	rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1108		      (void **) &pSMBr);
1109	if (rc < 0)
1110		return rc;
1111	in_len = rc;
1112
1113	pSMB->AndXCommand = 0xFF;       /* none */
1114
1115	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1116		count = 1;      /* account for one byte pad to word boundary */
1117		name_len =
1118		   cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
1119				      fileName, PATH_MAX, nls_codepage, remap);
1120		name_len++;     /* trailing null */
1121		name_len *= 2;
1122	} else {
1123		count = 0;      /* no pad */
1124		name_len = copy_path_name(pSMB->fileName, fileName);
1125	}
1126	if (*pOplock & REQ_OPLOCK)
1127		pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1128	else if (*pOplock & REQ_BATCHOPLOCK)
1129		pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1130
1131	pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1132	pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1133	pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1134	/* set file as system file if special file such as fifo,
1135	 * socket, char or block and server expecting SFU style and
1136	   no Unix extensions */
1137
1138	if (create_options & CREATE_OPTION_SPECIAL)
1139		pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1140	else /* BB FIXME BB */
1141		pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1142
1143	if (create_options & CREATE_OPTION_READONLY)
1144		pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1145
1146	/* BB FIXME BB */
1147/*	pSMB->CreateOptions = cpu_to_le32(create_options &
1148						 CREATE_OPTIONS_MASK); */
1149	/* BB FIXME END BB */
1150
1151	pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1152	pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1153	count += name_len;
1154	in_len += count;
1155
1156	pSMB->ByteCount = cpu_to_le16(count);
1157	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
1158			(struct smb_hdr *)pSMBr, &bytes_returned, 0);
1159	cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1160	if (rc) {
1161		cifs_dbg(FYI, "Error in Open = %d\n", rc);
1162	} else {
1163	/* BB verify if wct == 15 */
1164
1165/*		*pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1166
1167		*netfid = pSMBr->Fid;   /* cifs fid stays in le */
1168		/* Let caller know file was created so we can set the mode. */
1169		/* Do we care about the CreateAction in any other cases? */
1170	/* BB FIXME BB */
1171/*		if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1172			*pOplock |= CIFS_CREATE_ACTION; */
1173	/* BB FIXME END */
1174
1175		if (pfile_info) {
1176			pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1177			pfile_info->LastAccessTime = 0; /* BB fixme */
1178			pfile_info->LastWriteTime = 0; /* BB fixme */
1179			pfile_info->ChangeTime = 0;  /* BB fixme */
1180			pfile_info->Attributes =
1181				cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1182			/* the file_info buf is endian converted by caller */
1183			pfile_info->AllocationSize =
1184				cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1185			pfile_info->EndOfFile = pfile_info->AllocationSize;
1186			pfile_info->NumberOfLinks = cpu_to_le32(1);
1187			pfile_info->DeletePending = 0; /* successful open = not delete pending */
1188		}
1189	}
1190
1191	cifs_buf_release(pSMB);
1192	if (rc == -EAGAIN)
1193		goto OldOpenRetry;
1194	return rc;
1195}
1196
1197int
1198CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock,
1199	  FILE_ALL_INFO *buf)
1200{
1201	int rc;
1202	OPEN_REQ *req = NULL;
1203	OPEN_RSP *rsp = NULL;
1204	int bytes_returned;
1205	int name_len;
1206	__u16 count;
1207	struct cifs_sb_info *cifs_sb = oparms->cifs_sb;
1208	struct cifs_tcon *tcon = oparms->tcon;
1209	int remap = cifs_remap(cifs_sb);
1210	const struct nls_table *nls = cifs_sb->local_nls;
1211	int create_options = oparms->create_options;
1212	int desired_access = oparms->desired_access;
1213	int disposition = oparms->disposition;
1214	const char *path = oparms->path;
1215	unsigned int in_len;
1216
1217openRetry:
1218	rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **)&req,
1219		      (void **)&rsp);
1220	if (rc < 0)
1221		return rc;
1222	in_len = rc;
1223
1224	/* no commands go after this */
1225	req->AndXCommand = 0xFF;
1226
1227	if (req->hdr.Flags2 & SMBFLG2_UNICODE) {
1228		/* account for one byte pad to word boundary */
1229		count = 1;
1230		name_len = cifsConvertToUTF16((__le16 *)(req->fileName + 1),
1231					      path, PATH_MAX, nls, remap);
1232		/* trailing null */
1233		name_len++;
1234		name_len *= 2;
1235		req->NameLength = cpu_to_le16(name_len);
1236	} else {
1237		/* BB improve check for buffer overruns BB */
1238		/* no pad */
1239		count = 0;
1240		name_len = copy_path_name(req->fileName, path);
1241		req->NameLength = cpu_to_le16(name_len);
1242	}
1243
1244	if (*oplock & REQ_OPLOCK)
1245		req->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1246	else if (*oplock & REQ_BATCHOPLOCK)
1247		req->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1248
1249	req->DesiredAccess = cpu_to_le32(desired_access);
1250	req->AllocationSize = 0;
1251
1252	/*
1253	 * Set file as system file if special file such as fifo, socket, char
1254	 * or block and server expecting SFU style and no Unix extensions.
1255	 */
1256	if (create_options & CREATE_OPTION_SPECIAL)
1257		req->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1258	else
1259		req->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1260
1261	/*
1262	 * XP does not handle ATTR_POSIX_SEMANTICS but it helps speed up case
1263	 * sensitive checks for other servers such as Samba.
1264	 */
1265	if (tcon->ses->capabilities & CAP_UNIX)
1266		req->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1267
1268	if (create_options & CREATE_OPTION_READONLY)
1269		req->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1270
1271	req->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1272	req->CreateDisposition = cpu_to_le32(disposition);
1273	req->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1274
1275	/* BB Experiment with various impersonation levels and verify */
1276	req->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1277	req->SecurityFlags = SECURITY_CONTEXT_TRACKING|SECURITY_EFFECTIVE_ONLY;
1278
1279	count += name_len;
1280	in_len += count;
1281
1282	req->ByteCount = cpu_to_le16(count);
1283	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *)req, in_len,
1284			 (struct smb_hdr *)rsp, &bytes_returned, 0);
1285	cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1286	if (rc) {
1287		cifs_dbg(FYI, "Error in Open = %d\n", rc);
1288		cifs_buf_release(req);
1289		if (rc == -EAGAIN)
1290			goto openRetry;
1291		return rc;
1292	}
1293
1294	/* 1 byte no need to le_to_cpu */
1295	*oplock = rsp->OplockLevel;
1296	/* cifs fid stays in le */
1297	oparms->fid->netfid = rsp->Fid;
1298	oparms->fid->access = desired_access;
1299
1300	/* Let caller know file was created so we can set the mode. */
1301	/* Do we care about the CreateAction in any other cases? */
1302	if (cpu_to_le32(FILE_CREATE) == rsp->CreateAction)
1303		*oplock |= CIFS_CREATE_ACTION;
1304
1305	if (buf) {
1306		/* copy commonly used attributes */
1307		memcpy(&buf->common_attributes,
1308		       &rsp->common_attributes,
1309		       sizeof(buf->common_attributes));
1310		/* the file_info buf is endian converted by caller */
1311		buf->AllocationSize = rsp->AllocationSize;
1312		buf->EndOfFile = rsp->EndOfFile;
1313		buf->NumberOfLinks = cpu_to_le32(1);
1314		buf->DeletePending = 0; /* successful open = not delete pending */
1315	}
1316
1317	cifs_buf_release(req);
1318	return rc;
1319}
1320
1321static void
1322cifs_readv_callback(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1323{
1324	struct cifs_io_subrequest *rdata = mid->callback_data;
1325	struct netfs_inode *ictx = netfs_inode(rdata->rreq->inode);
1326	struct cifs_tcon *tcon = tlink_tcon(rdata->req->cfile->tlink);
1327	struct smb_rqst rqst = { .rq_iov = rdata->iov,
1328				 .rq_nvec = 1,
1329				 .rq_iter = rdata->subreq.io_iter };
1330	struct cifs_credits credits = {
1331		.value = 1,
1332		.instance = 0,
1333		.rreq_debug_id = rdata->rreq->debug_id,
1334		.rreq_debug_index = rdata->subreq.debug_index,
1335	};
1336	unsigned int rreq_debug_id = rdata->rreq->debug_id;
1337	unsigned int subreq_debug_index = rdata->subreq.debug_index;
1338
1339	cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%zu\n",
1340		 __func__, mid->mid, mid->mid_state, rdata->result,
1341		 rdata->subreq.len);
1342
1343	switch (mid->mid_state) {
1344	case MID_RESPONSE_RECEIVED:
1345		/* result already set, check signature */
1346		if (server->sign) {
1347			int rc = 0;
1348
1349			iov_iter_truncate(&rqst.rq_iter, rdata->got_bytes);
1350			rc = cifs_verify_signature(&rqst, server,
1351						  mid->sequence_number);
1352			if (rc)
1353				cifs_dbg(VFS, "SMB signature verification returned error = %d\n",
1354					 rc);
1355		}
1356		/* FIXME: should this be counted toward the initiating task? */
1357		task_io_account_read(rdata->got_bytes);
1358		cifs_stats_bytes_read(tcon, rdata->got_bytes);
1359		break;
1360	case MID_REQUEST_SUBMITTED:
1361		trace_netfs_sreq(&rdata->subreq, netfs_sreq_trace_io_req_submitted);
1362		goto do_retry;
1363	case MID_RETRY_NEEDED:
1364		trace_netfs_sreq(&rdata->subreq, netfs_sreq_trace_io_retry_needed);
1365do_retry:
1366		__set_bit(NETFS_SREQ_NEED_RETRY, &rdata->subreq.flags);
1367		rdata->result = -EAGAIN;
1368		if (server->sign && rdata->got_bytes)
1369			/* reset bytes number since we can not check a sign */
1370			rdata->got_bytes = 0;
1371		/* FIXME: should this be counted toward the initiating task? */
1372		task_io_account_read(rdata->got_bytes);
1373		cifs_stats_bytes_read(tcon, rdata->got_bytes);
1374		break;
1375	case MID_RESPONSE_MALFORMED:
1376		trace_netfs_sreq(&rdata->subreq, netfs_sreq_trace_io_malformed);
1377		rdata->result = smb_EIO(smb_eio_trace_read_rsp_malformed);
1378		break;
1379	default:
1380		trace_netfs_sreq(&rdata->subreq, netfs_sreq_trace_io_unknown);
1381		rdata->result = smb_EIO1(smb_eio_trace_read_mid_state_unknown,
1382					 mid->mid_state);
1383		break;
1384	}
1385
1386	if (rdata->result == -ENODATA) {
1387		rdata->result = 0;
1388		__set_bit(NETFS_SREQ_HIT_EOF, &rdata->subreq.flags);
1389		trace_smb3_read_err(rdata->rreq->debug_id,
1390				    rdata->subreq.debug_index,
1391				    rdata->xid,
1392				    rdata->req->cfile->fid.persistent_fid,
1393				    tcon->tid, tcon->ses->Suid,
1394				    rdata->subreq.start + rdata->subreq.transferred,
1395				    rdata->subreq.len   - rdata->subreq.transferred,
1396				    rdata->result);
1397	} else {
1398		size_t trans = rdata->subreq.transferred + rdata->got_bytes;
1399		if (trans < rdata->subreq.len &&
1400		    rdata->subreq.start + trans >= ictx->remote_i_size) {
1401			rdata->result = 0;
1402			__set_bit(NETFS_SREQ_HIT_EOF, &rdata->subreq.flags);
1403		} else if (rdata->got_bytes > 0) {
1404			__set_bit(NETFS_SREQ_MADE_PROGRESS, &rdata->subreq.flags);
1405		}
1406		if (rdata->got_bytes)
1407			__set_bit(NETFS_SREQ_MADE_PROGRESS, &rdata->subreq.flags);
1408		trace_smb3_read_done(rdata->rreq->debug_id,
1409				     rdata->subreq.debug_index,
1410				     rdata->xid,
1411				     rdata->req->cfile->fid.persistent_fid,
1412				     tcon->tid, tcon->ses->Suid,
1413				     rdata->subreq.start + rdata->subreq.transferred,
1414				     rdata->got_bytes);
1415	}
1416
1417	trace_smb3_rw_credits(rreq_debug_id, subreq_debug_index, rdata->credits.value,
1418			      server->credits, server->in_flight,
1419			      0, cifs_trace_rw_credits_read_response_clear);
1420	rdata->credits.value = 0;
1421	rdata->subreq.error = rdata->result;
1422	rdata->subreq.transferred += rdata->got_bytes;
1423	trace_netfs_sreq(&rdata->subreq, netfs_sreq_trace_io_progress);
1424	netfs_read_subreq_terminated(&rdata->subreq);
1425	release_mid(server, mid);
1426	add_credits(server, &credits, 0);
1427	trace_smb3_rw_credits(rreq_debug_id, subreq_debug_index, 0,
1428			      server->credits, server->in_flight,
1429			      credits.value, cifs_trace_rw_credits_read_response_add);
1430}
1431
1432/* cifs_async_readv - send an async write, and set up mid to handle result */
1433int
1434cifs_async_readv(struct cifs_io_subrequest *rdata)
1435{
1436	int rc;
1437	READ_REQ *smb = NULL;
1438	int wct;
1439	struct cifs_tcon *tcon = tlink_tcon(rdata->req->cfile->tlink);
1440	struct smb_rqst rqst = { .rq_iov = rdata->iov,
1441				 .rq_nvec = 1 };
1442	unsigned int in_len;
1443
1444	cifs_dbg(FYI, "%s: offset=%llu bytes=%zu\n",
1445		 __func__, rdata->subreq.start, rdata->subreq.len);
1446
1447	if (tcon->ses->capabilities & CAP_LARGE_FILES)
1448		wct = 12;
1449	else {
1450		wct = 10; /* old style read */
1451		if ((rdata->subreq.start >> 32) > 0)  {
1452			/* can not handle this big offset for old */
1453			return smb_EIO(smb_eio_trace_read_too_far);
1454		}
1455	}
1456
1457	rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **)&smb);
1458	if (rc < 0)
1459		return rc;
1460	in_len = rc;
1461
1462	smb->hdr.Pid = cpu_to_le16((__u16)rdata->req->pid);
1463	smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->req->pid >> 16));
1464
1465	smb->AndXCommand = 0xFF;	/* none */
1466	smb->Fid = rdata->req->cfile->fid.netfid;
1467	smb->OffsetLow = cpu_to_le32(rdata->subreq.start & 0xFFFFFFFF);
1468	if (wct == 12)
1469		smb->OffsetHigh = cpu_to_le32(rdata->subreq.start >> 32);
1470	smb->Remaining = 0;
1471	smb->MaxCount = cpu_to_le16(rdata->subreq.len & 0xFFFF);
1472	smb->MaxCountHigh = cpu_to_le32(rdata->subreq.len >> 16);
1473	if (wct == 12)
1474		smb->ByteCount = 0;
1475	else {
1476		/* old style read */
1477		struct smb_com_readx_req *smbr =
1478			(struct smb_com_readx_req *)smb;
1479		smbr->ByteCount = 0;
1480	}
1481
1482	/* 4 for RFC1001 length + 1 for BCC */
1483	rdata->iov[0].iov_base = smb;
1484	rdata->iov[0].iov_len = in_len;
1485
1486	trace_smb3_read_enter(rdata->rreq->debug_id,
1487			      rdata->subreq.debug_index,
1488			      rdata->xid,
1489			      rdata->req->cfile->fid.netfid,
1490			      tcon->tid, tcon->ses->Suid,
1491			      rdata->subreq.start, rdata->subreq.len);
1492
1493	rc = cifs_call_async(tcon->ses->server, &rqst, cifs_readv_receive,
1494			     cifs_readv_callback, NULL, rdata, 0, NULL);
1495
1496	if (rc == 0)
1497		cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1498	cifs_small_buf_release(smb);
1499	return rc;
1500}
1501
1502int
1503CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
1504	    unsigned int *nbytes, char **buf, int *pbuf_type)
1505{
1506	int rc = -EACCES;
1507	READ_REQ *pSMB = NULL;
1508	READ_RSP *pSMBr = NULL;
1509	char *pReadData = NULL;
1510	int wct;
1511	int resp_buf_type = 0;
1512	struct kvec iov[1];
1513	struct kvec rsp_iov;
1514	__u32 pid = io_parms->pid;
1515	__u16 netfid = io_parms->netfid;
1516	__u64 offset = io_parms->offset;
1517	struct cifs_tcon *tcon = io_parms->tcon;
1518	unsigned int in_len;
1519	unsigned int count = io_parms->length;
1520
1521	cifs_dbg(FYI, "Reading %d bytes on fid %d\n", count, netfid);
1522	if (tcon->ses->capabilities & CAP_LARGE_FILES)
1523		wct = 12;
1524	else {
1525		wct = 10; /* old style read */
1526		if ((offset >> 32) > 0)  {
1527			/* can not handle this big offset for old */
1528			return smb_EIO(smb_eio_trace_read_too_far);
1529		}
1530	}
1531
1532	*nbytes = 0;
1533	rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1534	if (rc < 0)
1535		return rc;
1536	in_len = rc;
1537
1538	pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1539	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1540
1541	/* tcon and ses pointer are checked in smb_init */
1542	if (tcon->ses->server == NULL)
1543		return -ECONNABORTED;
1544
1545	pSMB->AndXCommand = 0xFF;       /* none */
1546	pSMB->Fid = netfid;
1547	pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1548	if (wct == 12)
1549		pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1550
1551	pSMB->Remaining = 0;
1552	pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1553	pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1554	if (wct == 12)
1555		pSMB->ByteCount = 0;  /* no need to do le conversion since 0 */
1556	else {
1557		/* old style read */
1558		struct smb_com_readx_req *pSMBW =
1559			(struct smb_com_readx_req *)pSMB;
1560		pSMBW->ByteCount = 0;
1561	}
1562
1563	iov[0].iov_base = (char *)pSMB;
1564	iov[0].iov_len = in_len;
1565	rc = SendReceive2(xid, tcon->ses, iov, 1, &resp_buf_type,
1566			  CIFS_LOG_ERROR, &rsp_iov);
1567	cifs_small_buf_release(pSMB);
1568	cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1569	pSMBr = (READ_RSP *)rsp_iov.iov_base;
1570	if (rc) {
1571		cifs_dbg(VFS, "Send error in read = %d\n", rc);
1572	} else {
1573		int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1574		data_length = data_length << 16;
1575		data_length += le16_to_cpu(pSMBr->DataLength);
1576		*nbytes = data_length;
1577
1578		/*check that DataLength would not go beyond end of SMB */
1579		if ((data_length > CIFSMaxBufSize)
1580				|| (data_length > count)) {
1581			cifs_dbg(FYI, "bad length %d for count %d\n",
1582				 data_length, count);
1583			rc = smb_EIO2(smb_eio_trace_read_overlarge,
1584				      data_length, count);
1585			*nbytes = 0;
1586		} else {
1587			pReadData = (char *) (&pSMBr->hdr.Protocol) +
1588					le16_to_cpu(pSMBr->DataOffset);
1589/*			if (rc = copy_to_user(buf, pReadData, data_length)) {
1590				cifs_dbg(VFS, "Faulting on read rc = %d\n",rc);
1591				rc = -EFAULT;
1592			}*/ /* can not use copy_to_user when using page cache*/
1593			if (*buf)
1594				memcpy(*buf, pReadData, data_length);
1595		}
1596	}
1597
1598	if (*buf) {
1599		free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
1600	} else if (resp_buf_type != CIFS_NO_BUFFER) {
1601		/* return buffer to caller to free */
1602		*buf = rsp_iov.iov_base;
1603		if (resp_buf_type == CIFS_SMALL_BUFFER)
1604			*pbuf_type = CIFS_SMALL_BUFFER;
1605		else if (resp_buf_type == CIFS_LARGE_BUFFER)
1606			*pbuf_type = CIFS_LARGE_BUFFER;
1607	} /* else no valid buffer on return - leave as null */
1608
1609	/* Note: On -EAGAIN error only caller can retry on handle based calls
1610		since file handle passed in no longer valid */
1611	return rc;
1612}
1613
1614
1615int
1616CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
1617	     unsigned int *nbytes, const char *buf)
1618{
1619	int rc = -EACCES;
1620	WRITE_REQ *pSMB = NULL;
1621	WRITE_RSP *pSMBr = NULL;
1622	int bytes_returned, wct;
1623	__u32 bytes_sent;
1624	__u16 byte_count;
1625	__u32 pid = io_parms->pid;
1626	__u16 netfid = io_parms->netfid;
1627	__u64 offset = io_parms->offset;
1628	struct cifs_tcon *tcon = io_parms->tcon;
1629	unsigned int count = io_parms->length, in_len;
1630
1631	*nbytes = 0;
1632
1633	/* cifs_dbg(FYI, "write at %lld %d bytes\n", offset, count);*/
1634	if (tcon->ses == NULL)
1635		return -ECONNABORTED;
1636
1637	if (tcon->ses->capabilities & CAP_LARGE_FILES)
1638		wct = 14;
1639	else {
1640		wct = 12;
1641		if ((offset >> 32) > 0) {
1642			/* can not handle big offset for old srv */
1643			return smb_EIO(smb_eio_trace_write_too_far);
1644		}
1645	}
1646
1647	rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1648		      (void **) &pSMBr);
1649	if (rc < 0)
1650		return rc;
1651	in_len = rc;
1652
1653	pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1654	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1655
1656	/* tcon and ses pointer are checked in smb_init */
1657	if (tcon->ses->server == NULL)
1658		return -ECONNABORTED;
1659
1660	pSMB->AndXCommand = 0xFF;	/* none */
1661	pSMB->Fid = netfid;
1662	pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1663	if (wct == 14)
1664		pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1665
1666	pSMB->Reserved = 0xFFFFFFFF;
1667	pSMB->WriteMode = 0;
1668	pSMB->Remaining = 0;
1669
1670	/* Can increase buffer size if buffer is big enough in some cases ie we
1671	can send more if LARGE_WRITE_X capability returned by the server and if
1672	our buffer is big enough or if we convert to iovecs on socket writes
1673	and eliminate the copy to the CIFS buffer */
1674	if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1675		bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1676	} else {
1677		bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1678			 & ~0xFF;
1679	}
1680
1681	if (bytes_sent > count)
1682		bytes_sent = count;
1683	pSMB->DataOffset =
1684		cpu_to_le16(offsetof(struct smb_com_write_req, Data));
1685	if (buf)
1686		memcpy(pSMB->Data, buf, bytes_sent);
1687	else if (count != 0) {
1688		/* No buffer */
1689		cifs_buf_release(pSMB);
1690		return -EINVAL;
1691	} /* else setting file size with write of zero bytes */
1692	if (wct == 14)
1693		byte_count = bytes_sent + 1; /* pad */
1694	else /* wct == 12 */
1695		byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1696
1697	pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1698	pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1699	in_len += byte_count;
1700
1701	if (wct == 14)
1702		pSMB->ByteCount = cpu_to_le16(byte_count);
1703	else { /* old style write has byte count 4 bytes earlier
1704		  so 4 bytes pad  */
1705		struct smb_com_writex_req *pSMBW =
1706			(struct smb_com_writex_req *)pSMB;
1707		pSMBW->ByteCount = cpu_to_le16(byte_count);
1708	}
1709
1710	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
1711			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1712	cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
1713	if (rc) {
1714		cifs_dbg(FYI, "Send error in write = %d\n", rc);
1715	} else {
1716		*nbytes = le16_to_cpu(pSMBr->CountHigh);
1717		*nbytes = (*nbytes) << 16;
1718		*nbytes += le16_to_cpu(pSMBr->Count);
1719
1720		/*
1721		 * Mask off high 16 bits when bytes written as returned by the
1722		 * server is greater than bytes requested by the client. Some
1723		 * OS/2 servers are known to set incorrect CountHigh values.
1724		 */
1725		if (*nbytes > count)
1726			*nbytes &= 0xFFFF;
1727	}
1728
1729	cifs_buf_release(pSMB);
1730
1731	/* Note: On -EAGAIN error only caller can retry on handle based calls
1732		since file handle passed in no longer valid */
1733
1734	return rc;
1735}
1736
1737/*
1738 * Check the mid_state and signature on received buffer (if any), and queue the
1739 * workqueue completion task.
1740 */
1741static void
1742cifs_writev_callback(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1743{
1744	struct cifs_io_subrequest *wdata = mid->callback_data;
1745	struct cifs_tcon *tcon = tlink_tcon(wdata->req->cfile->tlink);
1746	WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
1747	struct cifs_credits credits = {
1748		.value = 1,
1749		.instance = 0,
1750		.rreq_debug_id = wdata->rreq->debug_id,
1751		.rreq_debug_index = wdata->subreq.debug_index,
1752	};
1753	ssize_t result;
1754	size_t written;
1755
1756	switch (mid->mid_state) {
1757	case MID_RESPONSE_RECEIVED:
1758		result = cifs_check_receive(mid, tcon->ses->server, 0);
1759		if (result != 0)
1760			break;
1761
1762		written = le16_to_cpu(smb->CountHigh);
1763		written <<= 16;
1764		written += le16_to_cpu(smb->Count);
1765		/*
1766		 * Mask off high 16 bits when bytes written as returned
1767		 * by the server is greater than bytes requested by the
1768		 * client. OS/2 servers are known to set incorrect
1769		 * CountHigh values.
1770		 */
1771		if (written > wdata->subreq.len)
1772			written &= 0xFFFF;
1773
1774		if (written < wdata->subreq.len) {
1775			result = -ENOSPC;
1776		} else {
1777			result = written;
1778			if (written > 0)
1779				__set_bit(NETFS_SREQ_MADE_PROGRESS, &wdata->subreq.flags);
1780		}
1781		break;
1782	case MID_REQUEST_SUBMITTED:
1783		trace_netfs_sreq(&wdata->subreq, netfs_sreq_trace_io_req_submitted);
1784		__set_bit(NETFS_SREQ_NEED_RETRY, &wdata->subreq.flags);
1785		result = -EAGAIN;
1786		break;
1787	case MID_RETRY_NEEDED:
1788		trace_netfs_sreq(&wdata->subreq, netfs_sreq_trace_io_retry_needed);
1789		__set_bit(NETFS_SREQ_NEED_RETRY, &wdata->subreq.flags);
1790		result = -EAGAIN;
1791		break;
1792	case MID_RESPONSE_MALFORMED:
1793		trace_netfs_sreq(&wdata->subreq, netfs_sreq_trace_io_malformed);
1794		result = smb_EIO(smb_eio_trace_write_rsp_malformed);
1795		break;
1796	default:
1797		trace_netfs_sreq(&wdata->subreq, netfs_sreq_trace_io_unknown);
1798		result = smb_EIO1(smb_eio_trace_write_mid_state_unknown,
1799				  mid->mid_state);
1800		break;
1801	}
1802
1803	trace_smb3_rw_credits(credits.rreq_debug_id, credits.rreq_debug_index,
1804			      wdata->credits.value,
1805			      server->credits, server->in_flight,
1806			      0, cifs_trace_rw_credits_write_response_clear);
1807	wdata->credits.value = 0;
1808	cifs_write_subrequest_terminated(wdata, result);
1809	release_mid(server, mid);
1810	trace_smb3_rw_credits(credits.rreq_debug_id, credits.rreq_debug_index, 0,
1811			      server->credits, server->in_flight,
1812			      credits.value, cifs_trace_rw_credits_write_response_add);
1813	add_credits(tcon->ses->server, &credits, 0);
1814}
1815
1816/* cifs_async_writev - send an async write, and set up mid to handle result */
1817void
1818cifs_async_writev(struct cifs_io_subrequest *wdata)
1819{
1820	int rc = -EACCES;
1821	WRITE_REQ *req = NULL;
1822	int wct;
1823	struct cifs_tcon *tcon = tlink_tcon(wdata->req->cfile->tlink);
1824	struct kvec iov[1];
1825	struct smb_rqst rqst = { };
1826	unsigned int in_len;
1827
1828	if (tcon->ses->capabilities & CAP_LARGE_FILES) {
1829		wct = 14;
1830	} else {
1831		wct = 12;
1832		if (wdata->subreq.start >> 32 > 0) {
1833			/* can not handle big offset for old srv */
1834			rc = smb_EIO(smb_eio_trace_write_too_far);
1835			goto out;
1836		}
1837	}
1838
1839	rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&req);
1840	if (rc < 0)
1841		goto async_writev_out;
1842	in_len = rc;
1843
1844	req->hdr.Pid = cpu_to_le16((__u16)wdata->req->pid);
1845	req->hdr.PidHigh = cpu_to_le16((__u16)(wdata->req->pid >> 16));
1846
1847	req->AndXCommand = 0xFF;	/* none */
1848	req->Fid = wdata->req->cfile->fid.netfid;
1849	req->OffsetLow = cpu_to_le32(wdata->subreq.start & 0xFFFFFFFF);
1850	if (wct == 14)
1851		req->OffsetHigh = cpu_to_le32(wdata->subreq.start >> 32);
1852	req->Reserved = 0xFFFFFFFF;
1853	req->WriteMode = 0;
1854	req->Remaining = 0;
1855
1856	req->DataOffset =
1857	    cpu_to_le16(offsetof(struct smb_com_write_req, Data));
1858
1859	iov[0].iov_base = req;
1860	iov[0].iov_len = in_len + 1; /* +1 for BCC */
1861
1862	rqst.rq_iov = iov;
1863	rqst.rq_nvec = 1;
1864	rqst.rq_iter = wdata->subreq.io_iter;
1865
1866	cifs_dbg(FYI, "async write at %llu %zu bytes\n",
1867		 wdata->subreq.start, wdata->subreq.len);
1868
1869	req->DataLengthLow = cpu_to_le16(wdata->subreq.len & 0xFFFF);
1870	req->DataLengthHigh = cpu_to_le16(wdata->subreq.len >> 16);
1871
1872	if (wct == 14) {
1873		in_len += wdata->subreq.len + 1;
1874		put_bcc(wdata->subreq.len + 1, &req->hdr);
1875	} else {
1876		/* wct == 12 */
1877		struct smb_com_writex_req *reqw =
1878				(struct smb_com_writex_req *)req;
1879		in_len += wdata->subreq.len + 5;
1880		put_bcc(wdata->subreq.len + 5, &reqw->hdr);
1881		iov[0].iov_len += 4; /* pad bigger by four bytes */
1882	}
1883
1884	rc = cifs_call_async(tcon->ses->server, &rqst, NULL,
1885			     cifs_writev_callback, NULL, wdata, 0, NULL);
1886	/* Can't touch wdata if rc == 0 */
1887	if (rc == 0)
1888		cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
1889
1890async_writev_out:
1891	cifs_small_buf_release(req);
1892out:
1893	if (rc) {
1894		add_credits_and_wake_if(wdata->server, &wdata->credits, 0);
1895		cifs_write_subrequest_terminated(wdata, rc);
1896	}
1897}
1898
1899int
1900CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
1901	      unsigned int *nbytes, struct kvec *iov, int n_vec)
1902{
1903	int rc;
1904	WRITE_REQ *pSMB = NULL;
1905	int wct;
1906	int smb_hdr_len;
1907	int resp_buf_type = 0;
1908	__u32 pid = io_parms->pid;
1909	__u16 netfid = io_parms->netfid;
1910	__u64 offset = io_parms->offset;
1911	struct cifs_tcon *tcon = io_parms->tcon;
1912	unsigned int count = io_parms->length;
1913	struct kvec rsp_iov;
1914	unsigned int in_len;
1915
1916	*nbytes = 0;
1917
1918	cifs_dbg(FYI, "write2 at %lld %d bytes\n", (long long)offset, count);
1919
1920	if (tcon->ses->capabilities & CAP_LARGE_FILES) {
1921		wct = 14;
1922	} else {
1923		wct = 12;
1924		if ((offset >> 32) > 0) {
1925			/* can not handle big offset for old srv */
1926			return smb_EIO(smb_eio_trace_write_too_far);
1927		}
1928	}
1929	rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1930	if (rc < 0)
1931		return rc;
1932	in_len = rc;
1933
1934	pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1935	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1936
1937	/* tcon and ses pointer are checked in smb_init */
1938	if (tcon->ses->server == NULL)
1939		return -ECONNABORTED;
1940
1941	pSMB->AndXCommand = 0xFF;	/* none */
1942	pSMB->Fid = netfid;
1943	pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1944	if (wct == 14)
1945		pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1946	pSMB->Reserved = 0xFFFFFFFF;
1947	pSMB->WriteMode = 0;
1948	pSMB->Remaining = 0;
1949
1950	pSMB->DataOffset =
1951	    cpu_to_le16(offsetof(struct smb_com_write_req, Data));
1952
1953	pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1954	pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1955	/* header + 1 byte pad */
1956	smb_hdr_len = in_len + 1;
1957	if (wct == 14)
1958		in_len += count + 1;
1959	else /* wct == 12 */
1960		in_len += count + 5; /* smb data starts later */
1961	if (wct == 14)
1962		pSMB->ByteCount = cpu_to_le16(count + 1);
1963	else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1964		struct smb_com_writex_req *pSMBW =
1965				(struct smb_com_writex_req *)pSMB;
1966		pSMBW->ByteCount = cpu_to_le16(count + 5);
1967	}
1968	iov[0].iov_base = pSMB;
1969	if (wct == 14)
1970		iov[0].iov_len = smb_hdr_len + 4;
1971	else /* wct == 12 pad bigger by four bytes */
1972		iov[0].iov_len = smb_hdr_len + 8;
1973
1974	rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type, 0,
1975			  &rsp_iov);
1976	cifs_small_buf_release(pSMB);
1977	cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
1978	if (rc) {
1979		cifs_dbg(FYI, "Send error Write2 = %d\n", rc);
1980	} else if (resp_buf_type == 0) {
1981		/* presumably this can not happen, but best to be safe */
1982		rc = smb_EIO1(smb_eio_trace_write_bad_buf_type, resp_buf_type);
1983	} else {
1984		WRITE_RSP *pSMBr = (WRITE_RSP *)rsp_iov.iov_base;
1985		*nbytes = le16_to_cpu(pSMBr->CountHigh);
1986		*nbytes = (*nbytes) << 16;
1987		*nbytes += le16_to_cpu(pSMBr->Count);
1988
1989		/*
1990		 * Mask off high 16 bits when bytes written as returned by the
1991		 * server is greater than bytes requested by the client. OS/2
1992		 * servers are known to set incorrect CountHigh values.
1993		 */
1994		if (*nbytes > count)
1995			*nbytes &= 0xFFFF;
1996	}
1997
1998	free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
1999
2000	/* Note: On -EAGAIN error only caller can retry on handle based calls
2001		since file handle passed in no longer valid */
2002
2003	return rc;
2004}
2005
2006int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon,
2007	       const __u16 netfid, const __u8 lock_type, const __u32 num_unlock,
2008	       const __u32 num_lock, LOCKING_ANDX_RANGE *buf)
2009{
2010	int rc = 0;
2011	LOCK_REQ *pSMB = NULL;
2012	struct kvec iov[2];
2013	struct kvec rsp_iov;
2014	unsigned int in_len;
2015	int resp_buf_type;
2016	__u16 count;
2017
2018	cifs_dbg(FYI, "cifs_lockv num lock %d num unlock %d\n",
2019		 num_lock, num_unlock);
2020
2021	rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2022	if (rc < 0)
2023		return rc;
2024	in_len = rc;
2025
2026	pSMB->Timeout = 0;
2027	pSMB->NumberOfLocks = cpu_to_le16(num_lock);
2028	pSMB->NumberOfUnlocks = cpu_to_le16(num_unlock);
2029	pSMB->LockType = lock_type;
2030	pSMB->AndXCommand = 0xFF; /* none */
2031	pSMB->Fid = netfid; /* netfid stays le */
2032
2033	count = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2034	in_len += count;
2035	pSMB->ByteCount = cpu_to_le16(count);
2036
2037	iov[0].iov_base = (char *)pSMB;
2038	iov[0].iov_len = in_len -
2039			 (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2040	iov[1].iov_base = (char *)buf;
2041	iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2042
2043	cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2044	rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type,
2045			  CIFS_NO_RSP_BUF, &rsp_iov);
2046	cifs_small_buf_release(pSMB);
2047	if (rc)
2048		cifs_dbg(FYI, "Send error in cifs_lockv = %d\n", rc);
2049
2050	return rc;
2051}
2052
2053int
2054CIFSSMBLock(const unsigned int xid, struct cifs_tcon *tcon,
2055	    const __u16 smb_file_id, const __u32 netpid, const __u64 len,
2056	    const __u64 offset, const __u32 numUnlock,
2057	    const __u32 numLock, const __u8 lockType,
2058	    const bool waitFlag, const __u8 oplock_level)
2059{
2060	int rc = 0;
2061	LOCK_REQ *pSMB = NULL;
2062/*	LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
2063	unsigned int in_len;
2064	int bytes_returned;
2065	int flags = CIFS_WINDOWS_LOCK | CIFS_INTERRUPTIBLE_WAIT;
2066	__u16 count;
2067
2068	cifs_dbg(FYI, "CIFSSMBLock timeout %d numLock %d\n",
2069		 (int)waitFlag, numLock);
2070	rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2071
2072	if (rc < 0)
2073		return rc;
2074	in_len = rc;
2075
2076	if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
2077		/* no response expected */
2078		flags = CIFS_NO_SRV_RSP | CIFS_NON_BLOCKING | CIFS_OBREAK_OP;
2079		pSMB->Timeout = 0;
2080	} else if (waitFlag) {
2081		flags = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2082		pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
2083	} else {
2084		pSMB->Timeout = 0;
2085	}
2086
2087	pSMB->NumberOfLocks = cpu_to_le16(numLock);
2088	pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
2089	pSMB->LockType = lockType;
2090	pSMB->OplockLevel = oplock_level;
2091	pSMB->AndXCommand = 0xFF;	/* none */
2092	pSMB->Fid = smb_file_id; /* netfid stays le */
2093
2094	if ((numLock != 0) || (numUnlock != 0)) {
2095		pSMB->Locks[0].Pid = cpu_to_le16(netpid);
2096		/* BB where to store pid high? */
2097		pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
2098		pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
2099		pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
2100		pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
2101		count = sizeof(LOCKING_ANDX_RANGE);
2102	} else {
2103		/* oplock break */
2104		count = 0;
2105	}
2106	in_len += count;
2107	pSMB->ByteCount = cpu_to_le16(count);
2108
2109	if (waitFlag)
2110		rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
2111				 (struct smb_hdr *) pSMB, &bytes_returned,
2112				 flags);
2113	else
2114		rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, in_len, flags);
2115	cifs_small_buf_release(pSMB);
2116	cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2117	if (rc)
2118		cifs_dbg(FYI, "Send error in Lock = %d\n", rc);
2119
2120	/* Note: On -EAGAIN error only caller can retry on handle based calls
2121	since file handle passed in no longer valid */
2122	return rc;
2123}
2124
2125int
2126CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon,
2127		const __u16 smb_file_id, const __u32 netpid,
2128		const loff_t start_offset, const __u64 len,
2129		struct file_lock *pLockData, const __u16 lock_type,
2130		const bool waitFlag)
2131{
2132	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
2133	struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2134	struct cifs_posix_lock *parm_data;
2135	unsigned int in_len;
2136	int rc = 0;
2137	int sr_flags = CIFS_INTERRUPTIBLE_WAIT;
2138	int bytes_returned = 0;
2139	int resp_buf_type = 0;
2140	__u16 params, param_offset, offset, byte_count, count;
2141	struct kvec iov[1];
2142	struct kvec rsp_iov;
2143
2144	cifs_dbg(FYI, "Posix Lock\n");
2145
2146	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
2147	if (rc < 0)
2148		return rc;
2149	in_len = rc;
2150
2151	pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
2152
2153	params = 6;
2154	pSMB->MaxSetupCount = 0;
2155	pSMB->Reserved = 0;
2156	pSMB->Flags = 0;
2157	pSMB->Reserved2 = 0;
2158	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid);
2159	offset = param_offset + params;
2160
2161	count = sizeof(struct cifs_posix_lock);
2162	pSMB->MaxParameterCount = cpu_to_le16(2);
2163	pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2164	pSMB->SetupCount = 1;
2165	pSMB->Reserved3 = 0;
2166	if (pLockData)
2167		pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2168	else
2169		pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2170	byte_count = 3 /* pad */  + params + count;
2171	pSMB->DataCount = cpu_to_le16(count);
2172	pSMB->ParameterCount = cpu_to_le16(params);
2173	pSMB->TotalDataCount = pSMB->DataCount;
2174	pSMB->TotalParameterCount = pSMB->ParameterCount;
2175	pSMB->ParameterOffset = cpu_to_le16(param_offset);
2176	parm_data = (struct cifs_posix_lock *)(((char *)pSMB) + offset);
2177
2178	parm_data->lock_type = cpu_to_le16(lock_type);
2179	if (waitFlag) {
2180		sr_flags |= CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2181		parm_data->lock_flags = cpu_to_le16(1);
2182		pSMB->Timeout = cpu_to_le32(-1);
2183	} else
2184		pSMB->Timeout = 0;
2185
2186	parm_data->pid = cpu_to_le32(netpid);
2187	parm_data->start = cpu_to_le64(start_offset);
2188	parm_data->length = cpu_to_le64(len);  /* normalize negative numbers */
2189
2190	pSMB->DataOffset = cpu_to_le16(offset);
2191	pSMB->Fid = smb_file_id;
2192	pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
2193	pSMB->Reserved4 = 0;
2194	in_len += byte_count;
2195	pSMB->ByteCount = cpu_to_le16(byte_count);
2196	if (waitFlag) {
2197		rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
2198				 (struct smb_hdr *) pSMBr, &bytes_returned,
2199				 sr_flags);
2200	} else {
2201		iov[0].iov_base = (char *)pSMB;
2202		iov[0].iov_len = in_len;
2203		rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
2204				&resp_buf_type, sr_flags, &rsp_iov);
2205		pSMBr = (struct smb_com_transaction2_sfi_rsp *)rsp_iov.iov_base;
2206	}
2207	cifs_small_buf_release(pSMB);
2208
2209	if (rc) {
2210		cifs_dbg(FYI, "Send error in Posix Lock = %d\n", rc);
2211	} else if (pLockData) {
2212		/* lock structure can be returned on get */
2213		__u16 data_offset;
2214		__u16 data_count;
2215		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2216
2217		if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) {
2218			rc = smb_EIO2(smb_eio_trace_lock_bcc_too_small,
2219				      get_bcc(&pSMBr->hdr), sizeof(*parm_data));
2220			goto plk_err_exit;
2221		}
2222		data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2223		data_count  = le16_to_cpu(pSMBr->t2.DataCount);
2224		if (data_count < sizeof(struct cifs_posix_lock)) {
2225			rc = smb_EIO2(smb_eio_trace_lock_data_too_small,
2226				      data_count, sizeof(struct cifs_posix_lock));
2227			goto plk_err_exit;
2228		}
2229		parm_data = (struct cifs_posix_lock *)
2230			((char *)&pSMBr->hdr.Protocol + data_offset);
2231		if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
2232			pLockData->c.flc_type = F_UNLCK;
2233		else {
2234			if (parm_data->lock_type ==
2235					cpu_to_le16(CIFS_RDLCK))
2236				pLockData->c.flc_type = F_RDLCK;
2237			else if (parm_data->lock_type ==
2238					cpu_to_le16(CIFS_WRLCK))
2239				pLockData->c.flc_type = F_WRLCK;
2240
2241			pLockData->fl_start = le64_to_cpu(parm_data->start);
2242			pLockData->fl_end = pLockData->fl_start +
2243				(le64_to_cpu(parm_data->length) ?
2244				 le64_to_cpu(parm_data->length) - 1 : 0);
2245			pLockData->c.flc_pid = -le32_to_cpu(parm_data->pid);
2246		}
2247	}
2248
2249plk_err_exit:
2250	free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
2251
2252	/* Note: On -EAGAIN error only caller can retry on handle based calls
2253	   since file handle passed in no longer valid */
2254
2255	return rc;
2256}
2257
2258
2259int
2260CIFSSMBClose(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2261{
2262	int rc = 0;
2263	CLOSE_REQ *pSMB = NULL;
2264	unsigned int in_len;
2265
2266	cifs_dbg(FYI, "In CIFSSMBClose\n");
2267
2268/* do not retry on dead session on close */
2269	rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
2270	if (rc == -EAGAIN)
2271		return 0;
2272	if (rc < 0)
2273		return rc;
2274	in_len = rc;
2275
2276	pSMB->FileID = (__u16) smb_file_id;
2277	pSMB->LastWriteTime = 0xFFFFFFFF;
2278	pSMB->ByteCount = 0;
2279	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, in_len, 0);
2280	cifs_small_buf_release(pSMB);
2281	cifs_stats_inc(&tcon->stats.cifs_stats.num_closes);
2282	if (rc) {
2283		if (rc != -EINTR) {
2284			/* EINTR is expected when user ctl-c to kill app */
2285			cifs_dbg(VFS, "Send error in Close = %d\n", rc);
2286		}
2287	}
2288
2289	/* Since session is dead, file will be closed on server already */
2290	if (rc == -EAGAIN)
2291		rc = 0;
2292
2293	return rc;
2294}
2295
2296int
2297CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2298{
2299	int rc = 0;
2300	FLUSH_REQ *pSMB = NULL;
2301	unsigned int in_len;
2302
2303	cifs_dbg(FYI, "In CIFSSMBFlush\n");
2304
2305	rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
2306	if (rc < 0)
2307		return rc;
2308	in_len = rc;
2309
2310	pSMB->FileID = (__u16) smb_file_id;
2311	pSMB->ByteCount = 0;
2312	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, in_len, 0);
2313	cifs_small_buf_release(pSMB);
2314	cifs_stats_inc(&tcon->stats.cifs_stats.num_flushes);
2315	if (rc)
2316		cifs_dbg(VFS, "Send error in Flush = %d\n", rc);
2317
2318	return rc;
2319}
2320
2321int CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
2322		  struct dentry *source_dentry,
2323		  const char *from_name, const char *to_name,
2324		  struct cifs_sb_info *cifs_sb)
2325{
2326	int rc = 0;
2327	RENAME_REQ *pSMB = NULL;
2328	RENAME_RSP *pSMBr = NULL;
2329	unsigned int in_len;
2330	int bytes_returned;
2331	int name_len, name_len2;
2332	__u16 count;
2333	int remap = cifs_remap(cifs_sb);
2334
2335	cifs_dbg(FYI, "In CIFSSMBRename\n");
2336renameRetry:
2337	rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
2338		      (void **) &pSMBr);
2339	if (rc < 0)
2340		return rc;
2341	in_len = rc;
2342
2343	pSMB->BufferFormat = 0x04;
2344	pSMB->SearchAttributes =
2345	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2346			ATTR_DIRECTORY);
2347
2348	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2349		name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2350					      from_name, PATH_MAX,
2351					      cifs_sb->local_nls, remap);
2352		name_len++;	/* trailing null */
2353		name_len *= 2;
2354		pSMB->OldFileName[name_len] = 0x04;	/* pad */
2355	/* protocol requires ASCII signature byte on Unicode string */
2356		pSMB->OldFileName[name_len + 1] = 0x00;
2357		name_len2 =
2358		    cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2359				       to_name, PATH_MAX, cifs_sb->local_nls,
2360				       remap);
2361		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2362		name_len2 *= 2;	/* convert to bytes */
2363	} else {
2364		name_len = copy_path_name(pSMB->OldFileName, from_name);
2365		name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name);
2366		pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
2367		name_len2++;	/* signature byte */
2368	}
2369
2370	count = 1 /* 1st signature byte */  + name_len + name_len2;
2371	in_len += count;
2372	pSMB->ByteCount = cpu_to_le16(count);
2373
2374	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
2375			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2376	cifs_stats_inc(&tcon->stats.cifs_stats.num_renames);
2377	if (rc)
2378		cifs_dbg(FYI, "Send error in rename = %d\n", rc);
2379
2380	cifs_buf_release(pSMB);
2381
2382	if (rc == -EAGAIN)
2383		goto renameRetry;
2384
2385	return rc;
2386}
2387
2388int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *pTcon,
2389		int netfid, const char *target_name,
2390		const struct nls_table *nls_codepage, int remap)
2391{
2392	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
2393	struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2394	struct set_file_rename *rename_info;
2395	unsigned int in_len;
2396	char *data_offset;
2397	char dummy_string[30];
2398	int rc = 0;
2399	int bytes_returned = 0;
2400	int len_of_str;
2401	__u16 params, param_offset, offset, count, byte_count;
2402
2403	cifs_dbg(FYI, "Rename to File by handle\n");
2404	rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2405			(void **) &pSMBr);
2406	if (rc < 0)
2407		return rc;
2408	in_len = rc;
2409
2410	params = 6;
2411	pSMB->MaxSetupCount = 0;
2412	pSMB->Reserved = 0;
2413	pSMB->Flags = 0;
2414	pSMB->Timeout = 0;
2415	pSMB->Reserved2 = 0;
2416	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid);
2417	offset = param_offset + params;
2418
2419	data_offset = (char *)(pSMB) + offset;
2420	rename_info = (struct set_file_rename *) data_offset;
2421	pSMB->MaxParameterCount = cpu_to_le16(2);
2422	pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2423	pSMB->SetupCount = 1;
2424	pSMB->Reserved3 = 0;
2425	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2426	byte_count = 3 /* pad */  + params;
2427	pSMB->ParameterCount = cpu_to_le16(params);
2428	pSMB->TotalParameterCount = pSMB->ParameterCount;
2429	pSMB->ParameterOffset = cpu_to_le16(param_offset);
2430	pSMB->DataOffset = cpu_to_le16(offset);
2431	/* construct random name ".cifs_tmp<inodenum><mid>" */
2432	rename_info->overwrite = cpu_to_le32(1);
2433	rename_info->root_fid  = 0;
2434	/* unicode only call */
2435	if (target_name == NULL) {
2436		sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2437		len_of_str =
2438			cifsConvertToUTF16((__le16 *)rename_info->target_name,
2439					dummy_string, 24, nls_codepage, remap);
2440	} else {
2441		len_of_str =
2442			cifsConvertToUTF16((__le16 *)rename_info->target_name,
2443					target_name, PATH_MAX, nls_codepage,
2444					remap);
2445	}
2446	rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2447	count = sizeof(struct set_file_rename) + (2 * len_of_str);
2448	byte_count += count;
2449	pSMB->DataCount = cpu_to_le16(count);
2450	pSMB->TotalDataCount = pSMB->DataCount;
2451	pSMB->Fid = netfid;
2452	pSMB->InformationLevel =
2453		cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2454	pSMB->Reserved4 = 0;
2455	in_len += byte_count;
2456	pSMB->ByteCount = cpu_to_le16(byte_count);
2457	rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB, in_len,
2458			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2459	cifs_stats_inc(&pTcon->stats.cifs_stats.num_t2renames);
2460	if (rc)
2461		cifs_dbg(FYI, "Send error in Rename (by file handle) = %d\n",
2462			 rc);
2463
2464	cifs_buf_release(pSMB);
2465
2466	/* Note: On -EAGAIN error only caller can retry on handle based calls
2467		since file handle passed in no longer valid */
2468
2469	return rc;
2470}
2471
2472int
2473CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon,
2474		      const char *fromName, const char *toName,
2475		      const struct nls_table *nls_codepage, int remap)
2476{
2477	TRANSACTION2_SPI_REQ *pSMB = NULL;
2478	TRANSACTION2_SPI_RSP *pSMBr = NULL;
2479	unsigned int in_len;
2480	char *data_offset;
2481	int name_len;
2482	int name_len_target;
2483	int rc = 0;
2484	int bytes_returned = 0;
2485	__u16 params, param_offset, offset, byte_count;
2486
2487	cifs_dbg(FYI, "In Symlink Unix style\n");
2488createSymLinkRetry:
2489	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2490		      (void **) &pSMBr);
2491	if (rc < 0)
2492		return rc;
2493	in_len = rc;
2494
2495	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2496		name_len =
2497		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fromName,
2498				/* find define for this maxpathcomponent */
2499					PATH_MAX, nls_codepage, remap);
2500		name_len++;	/* trailing null */
2501		name_len *= 2;
2502
2503	} else {
2504		name_len = copy_path_name(pSMB->FileName, fromName);
2505	}
2506	params = 6 + name_len;
2507	pSMB->MaxSetupCount = 0;
2508	pSMB->Reserved = 0;
2509	pSMB->Flags = 0;
2510	pSMB->Timeout = 0;
2511	pSMB->Reserved2 = 0;
2512	param_offset = offsetof(struct smb_com_transaction2_spi_req,
2513				InformationLevel);
2514	offset = param_offset + params;
2515
2516	data_offset = (char *)pSMB + offset;
2517	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2518		name_len_target =
2519		    cifsConvertToUTF16((__le16 *) data_offset, toName,
2520				/* find define for this maxpathcomponent */
2521					PATH_MAX, nls_codepage, remap);
2522		name_len_target++;	/* trailing null */
2523		name_len_target *= 2;
2524	} else {
2525		name_len_target = copy_path_name(data_offset, toName);
2526	}
2527
2528	pSMB->MaxParameterCount = cpu_to_le16(2);
2529	/* BB find exact max on data count below from sess */
2530	pSMB->MaxDataCount = cpu_to_le16(1000);
2531	pSMB->SetupCount = 1;
2532	pSMB->Reserved3 = 0;
2533	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2534	byte_count = 3 /* pad */  + params + name_len_target;
2535	pSMB->DataCount = cpu_to_le16(name_len_target);
2536	pSMB->ParameterCount = cpu_to_le16(params);
2537	pSMB->TotalDataCount = pSMB->DataCount;
2538	pSMB->TotalParameterCount = pSMB->ParameterCount;
2539	pSMB->ParameterOffset = cpu_to_le16(param_offset);
2540	pSMB->DataOffset = cpu_to_le16(offset);
2541	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2542	pSMB->Reserved4 = 0;
2543	in_len += byte_count;
2544	pSMB->ByteCount = cpu_to_le16(byte_count);
2545	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
2546			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2547	cifs_stats_inc(&tcon->stats.cifs_stats.num_symlinks);
2548	if (rc)
2549		cifs_dbg(FYI, "Send error in SetPathInfo create symlink = %d\n",
2550			 rc);
2551
2552	cifs_buf_release(pSMB);
2553
2554	if (rc == -EAGAIN)
2555		goto createSymLinkRetry;
2556
2557	return rc;
2558}
2559
2560int
2561CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2562		       const char *fromName, const char *toName,
2563		       const struct nls_table *nls_codepage, int remap)
2564{
2565	TRANSACTION2_SPI_REQ *pSMB = NULL;
2566	TRANSACTION2_SPI_RSP *pSMBr = NULL;
2567	unsigned int in_len;
2568	char *data_offset;
2569	int name_len;
2570	int name_len_target;
2571	int rc = 0;
2572	int bytes_returned = 0;
2573	__u16 params, param_offset, offset, byte_count;
2574
2575	cifs_dbg(FYI, "In Create Hard link Unix style\n");
2576createHardLinkRetry:
2577	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2578		      (void **) &pSMBr);
2579	if (rc < 0)
2580		return rc;
2581	in_len = rc;
2582
2583	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2584		name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,
2585					      PATH_MAX, nls_codepage, remap);
2586		name_len++;	/* trailing null */
2587		name_len *= 2;
2588
2589	} else {
2590		name_len = copy_path_name(pSMB->FileName, toName);
2591	}
2592	params = 6 + name_len;
2593	pSMB->MaxSetupCount = 0;
2594	pSMB->Reserved = 0;
2595	pSMB->Flags = 0;
2596	pSMB->Timeout = 0;
2597	pSMB->Reserved2 = 0;
2598	param_offset = offsetof(struct smb_com_transaction2_spi_req,
2599				InformationLevel);
2600	offset = param_offset + params;
2601
2602	data_offset = (char *)pSMB + offset;
2603	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2604		name_len_target =
2605		    cifsConvertToUTF16((__le16 *) data_offset, fromName,
2606				       PATH_MAX, nls_codepage, remap);
2607		name_len_target++;	/* trailing null */
2608		name_len_target *= 2;
2609	} else {
2610		name_len_target = copy_path_name(data_offset, fromName);
2611	}
2612
2613	pSMB->MaxParameterCount = cpu_to_le16(2);
2614	/* BB find exact max on data count below from sess*/
2615	pSMB->MaxDataCount = cpu_to_le16(1000);
2616	pSMB->SetupCount = 1;
2617	pSMB->Reserved3 = 0;
2618	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2619	byte_count = 3 /* pad */  + params + name_len_target;
2620	pSMB->ParameterCount = cpu_to_le16(params);
2621	pSMB->TotalParameterCount = pSMB->ParameterCount;
2622	pSMB->DataCount = cpu_to_le16(name_len_target);
2623	pSMB->TotalDataCount = pSMB->DataCount;
2624	pSMB->ParameterOffset = cpu_to_le16(param_offset);
2625	pSMB->DataOffset = cpu_to_le16(offset);
2626	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2627	pSMB->Reserved4 = 0;
2628	in_len += byte_count;
2629	pSMB->ByteCount = cpu_to_le16(byte_count);
2630	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
2631			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2632	cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
2633	if (rc)
2634		cifs_dbg(FYI, "Send error in SetPathInfo (hard link) = %d\n",
2635			 rc);
2636
2637	cifs_buf_release(pSMB);
2638	if (rc == -EAGAIN)
2639		goto createHardLinkRetry;
2640
2641	return rc;
2642}
2643
2644int CIFSCreateHardLink(const unsigned int xid,
2645		       struct cifs_tcon *tcon,
2646		       struct dentry *source_dentry,
2647		       const char *from_name, const char *to_name,
2648		       struct cifs_sb_info *cifs_sb)
2649{
2650	int rc = 0;
2651	NT_RENAME_REQ *pSMB = NULL;
2652	RENAME_RSP *pSMBr = NULL;
2653	unsigned int in_len;
2654	int bytes_returned;
2655	int name_len, name_len2;
2656	__u16 count;
2657	int remap = cifs_remap(cifs_sb);
2658
2659	cifs_dbg(FYI, "In CIFSCreateHardLink\n");
2660winCreateHardLinkRetry:
2661
2662	rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2663		      (void **) &pSMBr);
2664	if (rc < 0)
2665		return rc;
2666	in_len = rc;
2667
2668	pSMB->SearchAttributes =
2669	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2670			ATTR_DIRECTORY);
2671	pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2672	pSMB->ClusterCount = 0;
2673
2674	pSMB->BufferFormat = 0x04;
2675
2676	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2677		name_len =
2678		    cifsConvertToUTF16((__le16 *) pSMB->OldFileName, from_name,
2679				       PATH_MAX, cifs_sb->local_nls, remap);
2680		name_len++;	/* trailing null */
2681		name_len *= 2;
2682
2683		/* protocol specifies ASCII buffer format (0x04) for unicode */
2684		pSMB->OldFileName[name_len] = 0x04;
2685		pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2686		name_len2 =
2687		    cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2688				       to_name, PATH_MAX, cifs_sb->local_nls,
2689				       remap);
2690		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2691		name_len2 *= 2;	/* convert to bytes */
2692	} else {
2693		name_len = copy_path_name(pSMB->OldFileName, from_name);
2694		pSMB->OldFileName[name_len] = 0x04;	/* 2nd buffer format */
2695		name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name);
2696		name_len2++;	/* signature byte */
2697	}
2698
2699	count = 1 /* string type byte */  + name_len + name_len2;
2700	in_len += count;
2701	pSMB->ByteCount = cpu_to_le16(count);
2702
2703	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
2704			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2705	cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
2706	if (rc)
2707		cifs_dbg(FYI, "Send error in hard link (NT rename) = %d\n", rc);
2708
2709	cifs_buf_release(pSMB);
2710	if (rc == -EAGAIN)
2711		goto winCreateHardLinkRetry;
2712
2713	return rc;
2714}
2715
2716int
2717CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
2718			const unsigned char *searchName, char **symlinkinfo,
2719			const struct nls_table *nls_codepage, int remap)
2720{
2721/* SMB_QUERY_FILE_UNIX_LINK */
2722	TRANSACTION2_QPI_REQ *pSMB = NULL;
2723	TRANSACTION2_QPI_RSP *pSMBr = NULL;
2724	unsigned int in_len;
2725	int rc = 0;
2726	int bytes_returned;
2727	int name_len;
2728	__u16 params, byte_count;
2729	char *data_start;
2730
2731	cifs_dbg(FYI, "In QPathSymLinkInfo (Unix) for path %s\n", searchName);
2732
2733querySymLinkRetry:
2734	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2735		      (void **) &pSMBr);
2736	if (rc < 0)
2737		return rc;
2738	in_len = rc;
2739
2740	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2741		name_len =
2742			cifsConvertToUTF16((__le16 *) pSMB->FileName,
2743					   searchName, PATH_MAX, nls_codepage,
2744					   remap);
2745		name_len++;	/* trailing null */
2746		name_len *= 2;
2747	} else {
2748		name_len = copy_path_name(pSMB->FileName, searchName);
2749	}
2750
2751	params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
2752	pSMB->TotalDataCount = 0;
2753	pSMB->MaxParameterCount = cpu_to_le16(2);
2754	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
2755	pSMB->MaxSetupCount = 0;
2756	pSMB->Reserved = 0;
2757	pSMB->Flags = 0;
2758	pSMB->Timeout = 0;
2759	pSMB->Reserved2 = 0;
2760	pSMB->ParameterOffset = cpu_to_le16(offsetof(
2761		struct smb_com_transaction2_qpi_req, InformationLevel));
2762	pSMB->DataCount = 0;
2763	pSMB->DataOffset = 0;
2764	pSMB->SetupCount = 1;
2765	pSMB->Reserved3 = 0;
2766	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2767	byte_count = params + 1 /* pad */ ;
2768	pSMB->TotalParameterCount = cpu_to_le16(params);
2769	pSMB->ParameterCount = pSMB->TotalParameterCount;
2770	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2771	pSMB->Reserved4 = 0;
2772	in_len += byte_count;
2773	pSMB->ByteCount = cpu_to_le16(byte_count);
2774
2775	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
2776			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2777	if (rc) {
2778		cifs_dbg(FYI, "Send error in QuerySymLinkInfo = %d\n", rc);
2779	} else {
2780		/* decode response */
2781
2782		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2783		/* BB also check enough total bytes returned */
2784		if (rc || get_bcc(&pSMBr->hdr) < 2)
2785			rc = smb_EIO2(smb_eio_trace_qsym_bcc_too_small,
2786				      get_bcc(&pSMBr->hdr), 2);
2787		else {
2788			bool is_unicode;
2789			u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2790
2791			data_start = ((char *) &pSMBr->hdr.Protocol) +
2792					   le16_to_cpu(pSMBr->t2.DataOffset);
2793
2794			if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2795				is_unicode = true;
2796			else
2797				is_unicode = false;
2798
2799			/* BB FIXME investigate remapping reserved chars here */
2800			*symlinkinfo = cifs_strndup_from_utf16(data_start,
2801					count, is_unicode, nls_codepage);
2802			if (!*symlinkinfo)
2803				rc = -ENOMEM;
2804		}
2805	}
2806	cifs_buf_release(pSMB);
2807	if (rc == -EAGAIN)
2808		goto querySymLinkRetry;
2809	return rc;
2810}
2811
2812int cifs_query_reparse_point(const unsigned int xid,
2813			     struct cifs_tcon *tcon,
2814			     struct cifs_sb_info *cifs_sb,
2815			     const char *full_path,
2816			     u32 *tag, struct kvec *rsp,
2817			     int *rsp_buftype)
2818{
2819	struct reparse_data_buffer *buf;
2820	struct cifs_open_parms oparms;
2821	TRANSACT_IOCTL_REQ *io_req = NULL;
2822	TRANSACT_IOCTL_RSP *io_rsp = NULL;
2823	struct cifs_fid fid;
2824	unsigned int in_len;
2825	__u32 data_offset, data_count, len;
2826	__u8 *start, *end;
2827	int io_rsp_len;
2828	int oplock = 0;
2829	int rc;
2830
2831	cifs_tcon_dbg(FYI, "%s: path=%s\n", __func__, full_path);
2832
2833	if (cap_unix(tcon->ses))
2834		return -EOPNOTSUPP;
2835
2836	if (!CIFS_REPARSE_SUPPORT(tcon))
2837		return -EOPNOTSUPP;
2838
2839	oparms = (struct cifs_open_parms) {
2840		.tcon = tcon,
2841		.cifs_sb = cifs_sb,
2842		.desired_access = FILE_READ_ATTRIBUTES,
2843		.create_options = cifs_create_options(cifs_sb,
2844						      OPEN_REPARSE_POINT),
2845		.disposition = FILE_OPEN,
2846		.path = full_path,
2847		.fid = &fid,
2848	};
2849
2850	rc = CIFS_open(xid, &oparms, &oplock, NULL);
2851	if (rc)
2852		return rc;
2853
2854	rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon,
2855		      (void **)&io_req, (void **)&io_rsp);
2856	if (rc < 0)
2857		goto error;
2858	in_len = rc;
2859
2860	io_req->TotalParameterCount = 0;
2861	io_req->TotalDataCount = 0;
2862	io_req->MaxParameterCount = cpu_to_le32(0);
2863	/* BB find exact data count max from sess structure BB */
2864	io_req->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
2865	io_req->MaxSetupCount = 1;
2866	io_req->Reserved = 0;
2867	io_req->ParameterOffset = 0;
2868	io_req->DataCount = 0;
2869	io_req->DataOffset = 0;
2870	io_req->SetupCount = 4;
2871	io_req->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2872	io_req->ParameterCount = io_req->TotalParameterCount;
2873	io_req->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2874	io_req->IsFsctl = 1;
2875	io_req->IsRootFlag = 0;
2876	io_req->Fid = fid.netfid;
2877	io_req->ByteCount = 0;
2878
2879	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *)io_req, in_len,
2880			 (struct smb_hdr *)io_rsp, &io_rsp_len, 0);
2881	if (rc)
2882		goto error;
2883
2884	data_offset = le32_to_cpu(io_rsp->DataOffset);
2885	data_count = le32_to_cpu(io_rsp->DataCount);
2886	if (get_bcc(&io_rsp->hdr) < 2 || data_offset > 512 ||
2887	    !data_count || data_count > 2048) {
2888		rc = smb_EIO2(smb_eio_trace_qreparse_sizes_wrong,
2889			      get_bcc(&io_rsp->hdr), data_count);
2890		goto error;
2891	}
2892
2893	/* SetupCount must be 1, otherwise offset to ByteCount is incorrect. */
2894	if (io_rsp->SetupCount != 1) {
2895		rc = smb_EIO2(smb_eio_trace_qreparse_setup_count,
2896			      io_rsp->SetupCount, 1);
2897		goto error;
2898	}
2899
2900	/*
2901	 * ReturnedDataLen is output length of executed IOCTL.
2902	 * DataCount is output length transferred over network.
2903	 * Check that we have full FSCTL_GET_REPARSE_POINT buffer.
2904	 */
2905	if (data_count != le16_to_cpu(io_rsp->ReturnedDataLen)) {
2906		rc = smb_EIO2(smb_eio_trace_qreparse_ret_datalen,
2907			      data_count, le16_to_cpu(io_rsp->ReturnedDataLen));
2908		goto error;
2909	}
2910
2911	end = 2 + get_bcc(&io_rsp->hdr) + (__u8 *)&io_rsp->ByteCount;
2912	start = (__u8 *)&io_rsp->hdr.Protocol + data_offset;
2913	if (start >= end) {
2914		rc = smb_EIO2(smb_eio_trace_qreparse_data_area,
2915			      (unsigned long)start - (unsigned long)io_rsp,
2916			      (unsigned long)end - (unsigned long)io_rsp);
2917		goto error;
2918	}
2919
2920	data_count = le16_to_cpu(io_rsp->ByteCount);
2921	buf = (struct reparse_data_buffer *)start;
2922	len = sizeof(*buf);
2923	if (data_count < len ||
2924	    data_count < le16_to_cpu(buf->ReparseDataLength) + len) {
2925		rc = smb_EIO2(smb_eio_trace_qreparse_rep_datalen,
2926			      data_count, le16_to_cpu(buf->ReparseDataLength) + len);
2927		goto error;
2928	}
2929
2930	*tag = le32_to_cpu(buf->ReparseTag);
2931	rsp->iov_base = io_rsp;
2932	rsp->iov_len = io_rsp_len;
2933	*rsp_buftype = CIFS_LARGE_BUFFER;
2934	CIFSSMBClose(xid, tcon, fid.netfid);
2935	return 0;
2936
2937error:
2938	cifs_buf_release(io_req);
2939	CIFSSMBClose(xid, tcon, fid.netfid);
2940	return rc;
2941}
2942
2943struct inode *cifs_create_reparse_inode(struct cifs_open_info_data *data,
2944					struct super_block *sb,
2945					const unsigned int xid,
2946					struct cifs_tcon *tcon,
2947					const char *full_path,
2948					bool directory,
2949					struct kvec *reparse_iov,
2950					struct kvec *xattr_iov)
2951{
2952	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
2953	struct cifs_open_parms oparms;
2954	TRANSACT_IOCTL_REQ *io_req;
2955	struct inode *new = NULL;
2956	struct kvec in_iov[2];
2957	struct kvec out_iov;
2958	struct cifs_fid fid;
2959	unsigned int in_len;
2960	int oplock = 0;
2961	int buf_type = 0;
2962	int rc;
2963
2964	cifs_tcon_dbg(FYI, "%s: path=%s\n", __func__, full_path);
2965
2966	/*
2967	 * If server filesystem does not support reparse points then do not
2968	 * attempt to create reparse point. This will prevent creating unusable
2969	 * empty object on the server.
2970	 */
2971	if (!CIFS_REPARSE_SUPPORT(tcon))
2972		return ERR_PTR(-EOPNOTSUPP);
2973
2974#ifndef CONFIG_CIFS_XATTR
2975	if (xattr_iov)
2976		return ERR_PTR(-EOPNOTSUPP);
2977#endif
2978
2979	oparms = CIFS_OPARMS(cifs_sb, tcon, full_path,
2980			     FILE_READ_ATTRIBUTES | FILE_WRITE_DATA | FILE_WRITE_EA,
2981			     FILE_CREATE,
2982			     (directory ? CREATE_NOT_FILE : CREATE_NOT_DIR) | OPEN_REPARSE_POINT,
2983			     ACL_NO_MODE);
2984	oparms.fid = &fid;
2985
2986	rc = CIFS_open(xid, &oparms, &oplock, NULL);
2987	if (rc)
2988		return ERR_PTR(rc);
2989
2990#ifdef CONFIG_CIFS_XATTR
2991	if (xattr_iov) {
2992		struct smb2_file_full_ea_info *ea;
2993
2994		ea = &((struct smb2_create_ea_ctx *)xattr_iov->iov_base)->ea;
2995		while (1) {
2996			rc = CIFSSMBSetEA(xid,
2997					  tcon,
2998					  full_path,
2999					  &ea->ea_data[0],
3000					  &ea->ea_data[ea->ea_name_length+1],
3001					  le16_to_cpu(ea->ea_value_length),
3002					  cifs_sb->local_nls,
3003					  cifs_sb);
3004			if (rc)
3005				goto out_close;
3006			if (le32_to_cpu(ea->next_entry_offset) == 0)
3007				break;
3008			ea = (struct smb2_file_full_ea_info *)((u8 *)ea +
3009				le32_to_cpu(ea->next_entry_offset));
3010		}
3011	}
3012#endif
3013
3014	rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **)&io_req, NULL);
3015	if (rc < 0)
3016		goto out_close;
3017	in_len = rc;
3018	in_len += sizeof(io_req->Pad);
3019
3020	/* NT IOCTL response contains one-word long output setup buffer with size of output data. */
3021	io_req->MaxSetupCount = 1;
3022	/* NT IOCTL response does not contain output parameters. */
3023	io_req->MaxParameterCount = cpu_to_le32(0);
3024	/* FSCTL_SET_REPARSE_POINT response contains empty output data. */
3025	io_req->MaxDataCount = cpu_to_le32(0);
3026
3027	io_req->TotalParameterCount = cpu_to_le32(0);
3028	io_req->TotalDataCount = cpu_to_le32(reparse_iov->iov_len);
3029	io_req->ParameterCount = io_req->TotalParameterCount;
3030	io_req->ParameterOffset = cpu_to_le32(0);
3031	io_req->DataCount = io_req->TotalDataCount;
3032	io_req->DataOffset = cpu_to_le32(offsetof(typeof(*io_req), Data));
3033	io_req->SetupCount = 4;
3034	io_req->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3035	io_req->FunctionCode = cpu_to_le32(FSCTL_SET_REPARSE_POINT);
3036	io_req->Fid = fid.netfid;
3037	io_req->IsFsctl = 1;
3038	io_req->IsRootFlag = 0;
3039	io_req->ByteCount = cpu_to_le16(le32_to_cpu(io_req->DataCount) + sizeof(io_req->Pad));
3040
3041	in_iov[0].iov_base = (char *)io_req;
3042	in_iov[0].iov_len = in_len;
3043	in_iov[1] = *reparse_iov;
3044	rc = SendReceive2(xid, tcon->ses, in_iov, ARRAY_SIZE(in_iov), &buf_type,
3045			  CIFS_NO_RSP_BUF, &out_iov);
3046
3047	cifs_buf_release(io_req);
3048
3049	if (!rc)
3050		rc = cifs_get_inode_info(&new, full_path, data, sb, xid, NULL);
3051
3052out_close:
3053	CIFSSMBClose(xid, tcon, fid.netfid);
3054
3055	/*
3056	 * If CREATE was successful but FSCTL_SET_REPARSE_POINT failed then
3057	 * remove the intermediate object created by CREATE. Otherwise
3058	 * empty object stay on the server when reparse call failed.
3059	 */
3060	if (rc)
3061		CIFSSMBDelFile(xid, tcon, full_path, cifs_sb, NULL);
3062
3063	return rc ? ERR_PTR(rc) : new;
3064}
3065
3066int
3067CIFSSMB_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
3068		    __u16 fid)
3069{
3070	int rc = 0;
3071	int bytes_returned;
3072	struct smb_com_transaction_compr_ioctl_req *pSMB;
3073	struct smb_com_transaction_ioctl_rsp *pSMBr;
3074	unsigned int in_len;
3075
3076	cifs_dbg(FYI, "Set compression for %u\n", fid);
3077	rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3078		      (void **) &pSMBr);
3079	if (rc < 0)
3080		return rc;
3081	in_len = rc;
3082
3083	pSMB->compression_state = cpu_to_le16(COMPRESSION_FORMAT_DEFAULT);
3084
3085	pSMB->TotalParameterCount = 0;
3086	pSMB->TotalDataCount = cpu_to_le32(2);
3087	pSMB->MaxParameterCount = 0;
3088	pSMB->MaxDataCount = 0;
3089	pSMB->MaxSetupCount = 4;
3090	pSMB->Reserved = 0;
3091	pSMB->ParameterOffset = 0;
3092	pSMB->DataCount = cpu_to_le32(2);
3093	pSMB->DataOffset =
3094		cpu_to_le32(offsetof(struct smb_com_transaction_compr_ioctl_req,
3095				     compression_state));  /* 84 */
3096	pSMB->SetupCount = 4;
3097	pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3098	pSMB->ParameterCount = 0;
3099	pSMB->FunctionCode = cpu_to_le32(FSCTL_SET_COMPRESSION);
3100	pSMB->IsFsctl = 1; /* FSCTL */
3101	pSMB->IsRootFlag = 0;
3102	pSMB->Fid = fid; /* file handle always le */
3103	/* 3 byte pad, followed by 2 byte compress state */
3104	pSMB->ByteCount = cpu_to_le16(5);
3105	in_len += 5;
3106
3107	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
3108			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3109	if (rc)
3110		cifs_dbg(FYI, "Send error in SetCompression = %d\n", rc);
3111
3112	cifs_buf_release(pSMB);
3113
3114	/*
3115	 * Note: On -EAGAIN error only caller can retry on handle based calls
3116	 * since file handle passed in no longer valid.
3117	 */
3118	return rc;
3119}
3120
3121
3122#ifdef CONFIG_CIFS_POSIX
3123
3124#ifdef CONFIG_FS_POSIX_ACL
3125/**
3126 * cifs_init_posix_acl - convert ACL from cifs to POSIX ACL format
3127 * @ace: POSIX ACL entry to store converted ACL into
3128 * @cifs_ace: ACL in cifs format
3129 *
3130 * Convert an Access Control Entry from wire format to local POSIX xattr
3131 * format.
3132 *
3133 * Note that the @cifs_uid member is used to store both {g,u}id_t.
3134 */
3135static void cifs_init_posix_acl(struct posix_acl_entry *ace,
3136				struct cifs_posix_ace *cifs_ace)
3137{
3138	/* u8 cifs fields do not need le conversion */
3139	ace->e_perm = cifs_ace->cifs_e_perm;
3140	ace->e_tag = cifs_ace->cifs_e_tag;
3141
3142	switch (ace->e_tag) {
3143	case ACL_USER:
3144		ace->e_uid = make_kuid(&init_user_ns,
3145				       le64_to_cpu(cifs_ace->cifs_uid));
3146		break;
3147	case ACL_GROUP:
3148		ace->e_gid = make_kgid(&init_user_ns,
3149				       le64_to_cpu(cifs_ace->cifs_uid));
3150		break;
3151	}
3152	return;
3153}
3154
3155/**
3156 * cifs_to_posix_acl - copy cifs ACL format to POSIX ACL format
3157 * @acl: ACLs returned in POSIX ACL format
3158 * @src: ACLs in cifs format
3159 * @acl_type: type of POSIX ACL requested
3160 * @size_of_data_area: size of SMB we got
3161 *
3162 * This function converts ACLs from cifs format to POSIX ACL format.
3163 * If @acl is NULL then the size of the buffer required to store POSIX ACLs in
3164 * their uapi format is returned.
3165 */
3166static int cifs_to_posix_acl(struct posix_acl **acl, char *src,
3167			     const int acl_type, const int size_of_data_area)
3168{
3169	int size =  0;
3170	__u16 count;
3171	struct cifs_posix_ace *pACE;
3172	struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
3173	struct posix_acl *kacl = NULL;
3174	struct posix_acl_entry *pa, *pe;
3175
3176	if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
3177		return -EOPNOTSUPP;
3178
3179	if (acl_type == ACL_TYPE_ACCESS) {
3180		count = le16_to_cpu(cifs_acl->access_entry_count);
3181		pACE = &cifs_acl->ace_array[0];
3182		size = sizeof(struct cifs_posix_acl);
3183		size += sizeof(struct cifs_posix_ace) * count;
3184		/* check if we would go beyond end of SMB */
3185		if (size_of_data_area < size) {
3186			cifs_dbg(FYI, "bad CIFS POSIX ACL size %d vs. %d\n",
3187				 size_of_data_area, size);
3188			return -EINVAL;
3189		}
3190	} else if (acl_type == ACL_TYPE_DEFAULT) {
3191		count = le16_to_cpu(cifs_acl->access_entry_count);
3192		size = sizeof(struct cifs_posix_acl);
3193		size += sizeof(struct cifs_posix_ace) * count;
3194		/* skip past access ACEs to get to default ACEs */
3195		pACE = &cifs_acl->ace_array[count];
3196		count = le16_to_cpu(cifs_acl->default_entry_count);
3197		size += sizeof(struct cifs_posix_ace) * count;
3198		/* check if we would go beyond end of SMB */
3199		if (size_of_data_area < size)
3200			return -EINVAL;
3201	} else {
3202		/* illegal type */
3203		return -EINVAL;
3204	}
3205
3206	/* Allocate number of POSIX ACLs to store in VFS format. */
3207	kacl = posix_acl_alloc(count, GFP_NOFS);
3208	if (!kacl)
3209		return -ENOMEM;
3210
3211	FOREACH_ACL_ENTRY(pa, kacl, pe) {
3212		cifs_init_posix_acl(pa, pACE);
3213		pACE++;
3214	}
3215
3216	*acl = kacl;
3217	return 0;
3218}
3219
3220/**
3221 * cifs_init_ace - convert ACL entry from POSIX ACL to cifs format
3222 * @cifs_ace: the cifs ACL entry to store into
3223 * @local_ace: the POSIX ACL entry to convert
3224 */
3225static void cifs_init_ace(struct cifs_posix_ace *cifs_ace,
3226			  const struct posix_acl_entry *local_ace)
3227{
3228	cifs_ace->cifs_e_perm = local_ace->e_perm;
3229	cifs_ace->cifs_e_tag =  local_ace->e_tag;
3230
3231	switch (local_ace->e_tag) {
3232	case ACL_USER:
3233		cifs_ace->cifs_uid =
3234			cpu_to_le64(from_kuid(&init_user_ns, local_ace->e_uid));
3235		break;
3236	case ACL_GROUP:
3237		cifs_ace->cifs_uid =
3238			cpu_to_le64(from_kgid(&init_user_ns, local_ace->e_gid));
3239		break;
3240	default:
3241		cifs_ace->cifs_uid = cpu_to_le64(-1);
3242	}
3243}
3244
3245/**
3246 * posix_acl_to_cifs - convert ACLs from POSIX ACL to cifs format
3247 * @parm_data: ACLs in cifs format to convert to
3248 * @acl: ACLs in POSIX ACL format to convert from
3249 * @acl_type: the type of POSIX ACLs stored in @acl
3250 *
3251 * Return: the number cifs ACL entries after conversion
3252 */
3253static __u16 posix_acl_to_cifs(char *parm_data, const struct posix_acl *acl,
3254			       const int acl_type)
3255{
3256	__u16 rc = 0;
3257	struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
3258	const struct posix_acl_entry *pa, *pe;
3259	int count;
3260	int i = 0;
3261
3262	if ((acl == NULL) || (cifs_acl == NULL))
3263		return 0;
3264
3265	count = acl->a_count;
3266	cifs_dbg(FYI, "setting acl with %d entries\n", count);
3267
3268	/*
3269	 * Note that the uapi POSIX ACL version is verified by the VFS and is
3270	 * independent of the cifs ACL version. Changing the POSIX ACL version
3271	 * is a uapi change and if it's changed we will pass down the POSIX ACL
3272	 * version in struct posix_acl from the VFS. For now there's really
3273	 * only one that all filesystems know how to deal with.
3274	 */
3275	cifs_acl->version = cpu_to_le16(1);
3276	if (acl_type == ACL_TYPE_ACCESS) {
3277		cifs_acl->access_entry_count = cpu_to_le16(count);
3278		cifs_acl->default_entry_count = cpu_to_le16(0xFFFF);
3279	} else if (acl_type == ACL_TYPE_DEFAULT) {
3280		cifs_acl->default_entry_count = cpu_to_le16(count);
3281		cifs_acl->access_entry_count = cpu_to_le16(0xFFFF);
3282	} else {
3283		cifs_dbg(FYI, "unknown ACL type %d\n", acl_type);
3284		return 0;
3285	}
3286	FOREACH_ACL_ENTRY(pa, acl, pe) {
3287		cifs_init_ace(&cifs_acl->ace_array[i++], pa);
3288	}
3289	if (rc == 0) {
3290		rc = (__u16)(count * sizeof(struct cifs_posix_ace));
3291		rc += sizeof(struct cifs_posix_acl);
3292		/* BB add check to make sure ACL does not overflow SMB */
3293	}
3294	return rc;
3295}
3296
3297int cifs_do_get_acl(const unsigned int xid, struct cifs_tcon *tcon,
3298		    const unsigned char *searchName, struct posix_acl **acl,
3299		    const int acl_type, const struct nls_table *nls_codepage,
3300		    int remap)
3301{
3302/* SMB_QUERY_POSIX_ACL */
3303	TRANSACTION2_QPI_REQ *pSMB = NULL;
3304	TRANSACTION2_QPI_RSP *pSMBr = NULL;
3305	unsigned int in_len;
3306	int rc = 0;
3307	int bytes_returned;
3308	int name_len;
3309	__u16 params, byte_count;
3310
3311	cifs_dbg(FYI, "In GetPosixACL (Unix) for path %s\n", searchName);
3312
3313queryAclRetry:
3314	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3315		(void **) &pSMBr);
3316	if (rc < 0)
3317		return rc;
3318	in_len = rc;
3319
3320	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3321		name_len =
3322			cifsConvertToUTF16((__le16 *) pSMB->FileName,
3323					   searchName, PATH_MAX, nls_codepage,
3324					   remap);
3325		name_len++;     /* trailing null */
3326		name_len *= 2;
3327		pSMB->FileName[name_len] = 0;
3328		pSMB->FileName[name_len+1] = 0;
3329	} else {
3330		name_len = copy_path_name(pSMB->FileName, searchName);
3331	}
3332
3333	params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
3334	pSMB->TotalDataCount = 0;
3335	pSMB->MaxParameterCount = cpu_to_le16(2);
3336	/* BB find exact max data count below from sess structure BB */
3337	pSMB->MaxDataCount = cpu_to_le16(4000);
3338	pSMB->MaxSetupCount = 0;
3339	pSMB->Reserved = 0;
3340	pSMB->Flags = 0;
3341	pSMB->Timeout = 0;
3342	pSMB->Reserved2 = 0;
3343	pSMB->ParameterOffset = cpu_to_le16(
3344		offsetof(struct smb_com_transaction2_qpi_req,
3345			 InformationLevel));
3346	pSMB->DataCount = 0;
3347	pSMB->DataOffset = 0;
3348	pSMB->SetupCount = 1;
3349	pSMB->Reserved3 = 0;
3350	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3351	byte_count = params + 1 /* pad */ ;
3352	pSMB->TotalParameterCount = cpu_to_le16(params);
3353	pSMB->ParameterCount = pSMB->TotalParameterCount;
3354	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
3355	pSMB->Reserved4 = 0;
3356	in_len += byte_count;
3357	pSMB->ByteCount = cpu_to_le16(byte_count);
3358
3359	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
3360		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
3361	cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3362	if (rc) {
3363		cifs_dbg(FYI, "Send error in Query POSIX ACL = %d\n", rc);
3364	} else {
3365		/* decode response */
3366
3367		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3368		/* BB also check enough total bytes returned */
3369		if (rc || get_bcc(&pSMBr->hdr) < 2)
3370			rc = smb_EIO2(smb_eio_trace_getacl_bcc_too_small,
3371				      get_bcc(&pSMBr->hdr), 2);
3372		else {
3373			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3374			__u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3375			rc = cifs_to_posix_acl(acl,
3376				(char *)&pSMBr->hdr.Protocol+data_offset,
3377				acl_type, count);
3378		}
3379	}
3380	cifs_buf_release(pSMB);
3381	/*
3382	 * The else branch after SendReceive() doesn't return EAGAIN so if we
3383	 * allocated @acl in cifs_to_posix_acl() we are guaranteed to return
3384	 * here and don't leak POSIX ACLs.
3385	 */
3386	if (rc == -EAGAIN)
3387		goto queryAclRetry;
3388	return rc;
3389}
3390
3391int cifs_do_set_acl(const unsigned int xid, struct cifs_tcon *tcon,
3392		    const unsigned char *fileName, const struct posix_acl *acl,
3393		    const int acl_type, const struct nls_table *nls_codepage,
3394		    int remap)
3395{
3396	struct smb_com_transaction2_spi_req *pSMB = NULL;
3397	struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3398	unsigned int in_len;
3399	char *parm_data;
3400	int name_len;
3401	int rc = 0;
3402	int bytes_returned = 0;
3403	__u16 params, byte_count, data_count, param_offset, offset;
3404
3405	cifs_dbg(FYI, "In SetPosixACL (Unix) for path %s\n", fileName);
3406setAclRetry:
3407	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3408		      (void **) &pSMBr);
3409	if (rc < 0)
3410		return rc;
3411	in_len = rc;
3412	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3413		name_len =
3414			cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
3415					   PATH_MAX, nls_codepage, remap);
3416		name_len++;     /* trailing null */
3417		name_len *= 2;
3418	} else {
3419		name_len = copy_path_name(pSMB->FileName, fileName);
3420	}
3421	params = 6 + name_len;
3422	pSMB->MaxParameterCount = cpu_to_le16(2);
3423	/* BB find max SMB size from sess */
3424	pSMB->MaxDataCount = cpu_to_le16(1000);
3425	pSMB->MaxSetupCount = 0;
3426	pSMB->Reserved = 0;
3427	pSMB->Flags = 0;
3428	pSMB->Timeout = 0;
3429	pSMB->Reserved2 = 0;
3430	param_offset = offsetof(struct smb_com_transaction2_spi_req,
3431				InformationLevel);
3432	offset = param_offset + params;
3433	parm_data = ((char *)pSMB) + offset;
3434	pSMB->ParameterOffset = cpu_to_le16(param_offset);
3435
3436	/* convert to on the wire format for POSIX ACL */
3437	data_count = posix_acl_to_cifs(parm_data, acl, acl_type);
3438
3439	if (data_count == 0) {
3440		rc = -EOPNOTSUPP;
3441		goto setACLerrorExit;
3442	}
3443	pSMB->DataOffset = cpu_to_le16(offset);
3444	pSMB->SetupCount = 1;
3445	pSMB->Reserved3 = 0;
3446	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3447	pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
3448	byte_count = 3 /* pad */  + params + data_count;
3449	pSMB->DataCount = cpu_to_le16(data_count);
3450	pSMB->TotalDataCount = pSMB->DataCount;
3451	pSMB->ParameterCount = cpu_to_le16(params);
3452	pSMB->TotalParameterCount = pSMB->ParameterCount;
3453	pSMB->Reserved4 = 0;
3454	in_len += byte_count;
3455	pSMB->ByteCount = cpu_to_le16(byte_count);
3456	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
3457			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3458	if (rc)
3459		cifs_dbg(FYI, "Set POSIX ACL returned %d\n", rc);
3460
3461setACLerrorExit:
3462	cifs_buf_release(pSMB);
3463	if (rc == -EAGAIN)
3464		goto setAclRetry;
3465	return rc;
3466}
3467#else
3468int cifs_do_get_acl(const unsigned int xid, struct cifs_tcon *tcon,
3469		    const unsigned char *searchName, struct posix_acl **acl,
3470		    const int acl_type, const struct nls_table *nls_codepage,
3471		    int remap)
3472{
3473	return -EOPNOTSUPP;
3474}
3475
3476int cifs_do_set_acl(const unsigned int xid, struct cifs_tcon *tcon,
3477		    const unsigned char *fileName, const struct posix_acl *acl,
3478		    const int acl_type, const struct nls_table *nls_codepage,
3479		    int remap)
3480{
3481	return -EOPNOTSUPP;
3482}
3483#endif /* CONFIG_FS_POSIX_ACL */
3484
3485int
3486CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
3487	       const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3488{
3489	int rc = 0;
3490	struct smb_t2_qfi_req *pSMB = NULL;
3491	struct smb_t2_qfi_rsp *pSMBr = NULL;
3492	unsigned int in_len;
3493	int bytes_returned;
3494	__u16 params, byte_count;
3495
3496	cifs_dbg(FYI, "In GetExtAttr\n");
3497	if (tcon == NULL)
3498		return -ENODEV;
3499
3500GetExtAttrRetry:
3501	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3502		      (void **) &pSMBr);
3503	if (rc < 0)
3504		return rc;
3505	in_len = rc;
3506
3507	params = 2 /* level */ + 2 /* fid */;
3508	pSMB->t2.TotalDataCount = 0;
3509	pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3510	/* BB find exact max data count below from sess structure BB */
3511	pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3512	pSMB->t2.MaxSetupCount = 0;
3513	pSMB->t2.Reserved = 0;
3514	pSMB->t2.Flags = 0;
3515	pSMB->t2.Timeout = 0;
3516	pSMB->t2.Reserved2 = 0;
3517	pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3518					       Fid));
3519	pSMB->t2.DataCount = 0;
3520	pSMB->t2.DataOffset = 0;
3521	pSMB->t2.SetupCount = 1;
3522	pSMB->t2.Reserved3 = 0;
3523	pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3524	byte_count = params + 1 /* pad */ ;
3525	pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3526	pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3527	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3528	pSMB->Pad = 0;
3529	pSMB->Fid = netfid;
3530	in_len += byte_count;
3531	pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3532
3533	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
3534			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3535	if (rc) {
3536		cifs_dbg(FYI, "error %d in GetExtAttr\n", rc);
3537	} else {
3538		/* decode response */
3539		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3540		/* BB also check enough total bytes returned */
3541		if (rc || get_bcc(&pSMBr->hdr) < 2)
3542			/* If rc should we check for EOPNOSUPP and
3543			   disable the srvino flag? or in caller? */
3544			rc = smb_EIO2(smb_eio_trace_getextattr_bcc_too_small,
3545				      get_bcc(&pSMBr->hdr), 2);
3546		else {
3547			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3548			__u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3549			struct file_chattr_info *pfinfo;
3550
3551			if (count != 16) {
3552				cifs_dbg(FYI, "Invalid size ret in GetExtAttr\n");
3553				rc = smb_EIO2(smb_eio_trace_getextattr_inv_size,
3554					      count, 16);
3555				goto GetExtAttrOut;
3556			}
3557			pfinfo = (struct file_chattr_info *)
3558				 (data_offset + (char *) &pSMBr->hdr.Protocol);
3559			*pExtAttrBits = le64_to_cpu(pfinfo->mode);
3560			*pMask = le64_to_cpu(pfinfo->mask);
3561		}
3562	}
3563GetExtAttrOut:
3564	cifs_buf_release(pSMB);
3565	if (rc == -EAGAIN)
3566		goto GetExtAttrRetry;
3567	return rc;
3568}
3569
3570#endif /* CONFIG_POSIX */
3571
3572/*
3573 * Initialize NT TRANSACT SMB into small smb request buffer.  This assumes that
3574 * all NT TRANSACTS that we init here have total parm and data under about 400
3575 * bytes (to fit in small cifs buffer size), which is the case so far, it
3576 * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3577 * returned setup area) and MaxParameterCount (returned parms size) must be set
3578 * by caller
3579 */
3580static int
3581smb_init_nttransact(const __u16 sub_command, const int setup_count,
3582		   const int parm_len, struct cifs_tcon *tcon,
3583		   void **ret_buf)
3584{
3585	int rc;
3586	__u32 temp_offset;
3587	struct smb_com_ntransact_req *pSMB;
3588	unsigned int in_len;
3589
3590	rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
3591				(void **)&pSMB);
3592	if (rc < 0)
3593		return rc;
3594	in_len = rc;
3595	*ret_buf = (void *)pSMB;
3596	pSMB->Reserved = 0;
3597	pSMB->TotalParameterCount = cpu_to_le32(parm_len);
3598	pSMB->TotalDataCount  = 0;
3599	pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3600	pSMB->ParameterCount = pSMB->TotalParameterCount;
3601	pSMB->DataCount  = pSMB->TotalDataCount;
3602	temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3603		(setup_count * 2);
3604	pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3605	pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3606	pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
3607	pSMB->SubCommand = cpu_to_le16(sub_command);
3608	return in_len;
3609}
3610
3611static int
3612validate_ntransact(char *buf, char **ppparm, char **ppdata,
3613		   __u32 *pparmlen, __u32 *pdatalen)
3614{
3615	char *end_of_smb;
3616	__u32 data_count, data_offset, parm_count, parm_offset;
3617	struct smb_com_ntransact_rsp *pSMBr;
3618	u16 bcc;
3619
3620	*pdatalen = 0;
3621	*pparmlen = 0;
3622
3623	if (buf == NULL)
3624		return -EINVAL;
3625
3626	pSMBr = (struct smb_com_ntransact_rsp *)buf;
3627
3628	bcc = get_bcc(&pSMBr->hdr);
3629	end_of_smb = 2 /* sizeof byte count */ + bcc +
3630			(char *)&pSMBr->ByteCount;
3631
3632	data_offset = le32_to_cpu(pSMBr->DataOffset);
3633	data_count = le32_to_cpu(pSMBr->DataCount);
3634	parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3635	parm_count = le32_to_cpu(pSMBr->ParameterCount);
3636
3637	*ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3638	*ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3639
3640	/* should we also check that parm and data areas do not overlap? */
3641	if (*ppparm > end_of_smb) {
3642		cifs_dbg(FYI, "parms start after end of smb\n");
3643		return -EINVAL;
3644	} else if (parm_count + *ppparm > end_of_smb) {
3645		cifs_dbg(FYI, "parm end after end of smb\n");
3646		return -EINVAL;
3647	} else if (*ppdata > end_of_smb) {
3648		cifs_dbg(FYI, "data starts after end of smb\n");
3649		return -EINVAL;
3650	} else if (data_count + *ppdata > end_of_smb) {
3651		cifs_dbg(FYI, "data %p + count %d (%p) past smb end %p start %p\n",
3652			 *ppdata, data_count, (data_count + *ppdata),
3653			 end_of_smb, pSMBr);
3654		return -EINVAL;
3655	} else if (parm_count + data_count > bcc) {
3656		cifs_dbg(FYI, "parm count and data count larger than SMB\n");
3657		return -EINVAL;
3658	}
3659	*pdatalen = data_count;
3660	*pparmlen = parm_count;
3661	return 0;
3662}
3663
3664/* Get Security Descriptor (by handle) from remote server for a file or dir */
3665int
3666CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3667		  struct smb_ntsd **acl_inf, __u32 *pbuflen, __u32 info)
3668{
3669	int rc = 0;
3670	int buf_type = 0;
3671	QUERY_SEC_DESC_REQ *pSMB;
3672	struct kvec iov[1];
3673	struct kvec rsp_iov;
3674	unsigned int in_len;
3675
3676	cifs_dbg(FYI, "GetCifsACL\n");
3677
3678	*pbuflen = 0;
3679	*acl_inf = NULL;
3680
3681	rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3682			8 /* parm len */, tcon, (void **) &pSMB);
3683	if (rc < 0)
3684		return rc;
3685	in_len = rc;
3686
3687	pSMB->MaxParameterCount = cpu_to_le32(4);
3688	/* BB TEST with big acls that might need to be e.g. larger than 16K */
3689	pSMB->MaxSetupCount = 0;
3690	pSMB->Fid = fid; /* file handle always le */
3691	pSMB->AclFlags = cpu_to_le32(info);
3692	pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3693	in_len += 11;
3694	iov[0].iov_base = (char *)pSMB;
3695	iov[0].iov_len = in_len;
3696
3697	rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3698			  0, &rsp_iov);
3699	cifs_small_buf_release(pSMB);
3700	cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3701	if (rc) {
3702		cifs_dbg(FYI, "Send error in QuerySecDesc = %d\n", rc);
3703	} else {                /* decode response */
3704		__le32 *parm;
3705		__u32 parm_len;
3706		__u32 acl_len;
3707		struct smb_com_ntransact_rsp *pSMBr;
3708		char *pdata;
3709
3710/* validate_nttransact */
3711		rc = validate_ntransact(rsp_iov.iov_base, (char **)&parm,
3712					&pdata, &parm_len, pbuflen);
3713		if (rc)
3714			goto qsec_out;
3715		pSMBr = (struct smb_com_ntransact_rsp *)rsp_iov.iov_base;
3716
3717		cifs_dbg(FYI, "smb %p parm %p data %p\n",
3718			 pSMBr, parm, *acl_inf);
3719
3720		if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3721			rc = smb_EIO2(smb_eio_trace_getcifsacl_param_count,
3722				      le32_to_cpu(pSMBr->ParameterCount), 4);
3723			*pbuflen = 0;
3724			goto qsec_out;
3725		}
3726
3727/* BB check that data area is minimum length and as big as acl_len */
3728
3729		acl_len = le32_to_cpu(*parm);
3730		if (acl_len != *pbuflen) {
3731			cifs_dbg(VFS, "acl length %d does not match %d\n",
3732				 acl_len, *pbuflen);
3733			if (*pbuflen > acl_len)
3734				*pbuflen = acl_len;
3735		}
3736
3737		/* check if buffer is big enough for the acl
3738		   header followed by the smallest SID */
3739		if ((*pbuflen < sizeof(struct smb_ntsd) + 8) ||
3740		    (*pbuflen >= 64 * 1024)) {
3741			cifs_dbg(VFS, "bad acl length %d\n", *pbuflen);
3742			rc = -EINVAL;
3743			*pbuflen = 0;
3744		} else {
3745			*acl_inf = kmemdup(pdata, *pbuflen, GFP_KERNEL);
3746			if (*acl_inf == NULL) {
3747				*pbuflen = 0;
3748				rc = -ENOMEM;
3749			}
3750		}
3751	}
3752qsec_out:
3753	free_rsp_buf(buf_type, rsp_iov.iov_base);
3754	return rc;
3755}
3756
3757int
3758CIFSSMBSetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3759			struct smb_ntsd *pntsd, __u32 acllen, int aclflag)
3760{
3761	__u16 byte_count, param_count, data_count, param_offset, data_offset;
3762	int rc = 0;
3763	int bytes_returned = 0;
3764	SET_SEC_DESC_REQ *pSMB = NULL;
3765	unsigned int in_len;
3766	void *pSMBr;
3767
3768setCifsAclRetry:
3769	rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr);
3770	if (rc < 0)
3771		return rc;
3772	in_len = rc;
3773
3774	pSMB->MaxSetupCount = 0;
3775	pSMB->Reserved = 0;
3776
3777	param_count = 8;
3778	param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid);
3779	data_count = acllen;
3780	data_offset = param_offset + param_count;
3781	byte_count = 3 /* pad */  + param_count;
3782
3783	pSMB->DataCount = cpu_to_le32(data_count);
3784	pSMB->TotalDataCount = pSMB->DataCount;
3785	pSMB->MaxParameterCount = cpu_to_le32(4);
3786	pSMB->MaxDataCount = cpu_to_le32(16384);
3787	pSMB->ParameterCount = cpu_to_le32(param_count);
3788	pSMB->ParameterOffset = cpu_to_le32(param_offset);
3789	pSMB->TotalParameterCount = pSMB->ParameterCount;
3790	pSMB->DataOffset = cpu_to_le32(data_offset);
3791	pSMB->SetupCount = 0;
3792	pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3793	pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3794
3795	pSMB->Fid = fid; /* file handle always le */
3796	pSMB->Reserved2 = 0;
3797	pSMB->AclFlags = cpu_to_le32(aclflag);
3798
3799	if (pntsd && acllen) {
3800		memcpy((char *)pSMBr + data_offset, pntsd, acllen);
3801		in_len += byte_count + data_count;
3802	} else
3803		in_len += byte_count;
3804
3805	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
3806		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
3807
3808	cifs_dbg(FYI, "SetCIFSACL bytes_returned: %d, rc: %d\n",
3809		 bytes_returned, rc);
3810	if (rc)
3811		cifs_dbg(FYI, "Set CIFS ACL returned %d\n", rc);
3812	cifs_buf_release(pSMB);
3813
3814	if (rc == -EAGAIN)
3815		goto setCifsAclRetry;
3816
3817	return (rc);
3818}
3819
3820
3821/* Legacy Query Path Information call for lookup to old servers such
3822   as Win9x/WinME */
3823int
3824SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
3825		    const char *search_name, FILE_ALL_INFO *data,
3826		    const struct nls_table *nls_codepage, int remap)
3827{
3828	QUERY_INFORMATION_REQ *pSMB;
3829	QUERY_INFORMATION_RSP *pSMBr;
3830	unsigned int in_len;
3831	int rc = 0;
3832	int bytes_returned;
3833	int name_len;
3834
3835	cifs_dbg(FYI, "In SMBQPath path %s\n", search_name);
3836QInfRetry:
3837	rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3838		      (void **) &pSMBr);
3839	if (rc < 0)
3840		return rc;
3841	in_len = rc;
3842
3843	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3844		name_len =
3845			cifsConvertToUTF16((__le16 *) pSMB->FileName,
3846					   search_name, PATH_MAX, nls_codepage,
3847					   remap);
3848		name_len++;     /* trailing null */
3849		name_len *= 2;
3850	} else {
3851		name_len = copy_path_name(pSMB->FileName, search_name);
3852	}
3853	pSMB->BufferFormat = 0x04;
3854	name_len++; /* account for buffer type byte */
3855	in_len += name_len;
3856	pSMB->ByteCount = cpu_to_le16(name_len);
3857
3858	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
3859			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3860	if (rc) {
3861		cifs_dbg(FYI, "Send error in QueryInfo = %d\n", rc);
3862	} else if (data) {
3863		struct timespec64 ts;
3864		__u32 time = le32_to_cpu(pSMBr->last_write_time);
3865
3866		/* decode response */
3867		/* BB FIXME - add time zone adjustment BB */
3868		memset(data, 0, sizeof(FILE_ALL_INFO));
3869		ts.tv_nsec = 0;
3870		ts.tv_sec = time;
3871		/* decode time fields */
3872		data->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3873		data->LastWriteTime = data->ChangeTime;
3874		data->LastAccessTime = 0;
3875		data->AllocationSize =
3876			cpu_to_le64(le32_to_cpu(pSMBr->size));
3877		data->EndOfFile = data->AllocationSize;
3878		data->Attributes =
3879			cpu_to_le32(le16_to_cpu(pSMBr->attr));
3880	} else {
3881		/* bad buffer passed in */
3882		rc = smb_EIO(smb_eio_trace_null_pointers);
3883	}
3884
3885	cifs_buf_release(pSMB);
3886
3887	if (rc == -EAGAIN)
3888		goto QInfRetry;
3889
3890	return rc;
3891}
3892
3893int
3894CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
3895		 u16 netfid, FILE_ALL_INFO *pFindData)
3896{
3897	struct smb_t2_qfi_req *pSMB = NULL;
3898	struct smb_t2_qfi_rsp *pSMBr = NULL;
3899	unsigned int in_len;
3900	int rc = 0;
3901	int bytes_returned;
3902	__u16 params, byte_count;
3903
3904QFileInfoRetry:
3905	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3906		      (void **) &pSMBr);
3907	if (rc < 0)
3908		return rc;
3909	in_len = rc;
3910
3911	params = 2 /* level */ + 2 /* fid */;
3912	pSMB->t2.TotalDataCount = 0;
3913	pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3914	/* BB find exact max data count below from sess structure BB */
3915	pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3916	pSMB->t2.MaxSetupCount = 0;
3917	pSMB->t2.Reserved = 0;
3918	pSMB->t2.Flags = 0;
3919	pSMB->t2.Timeout = 0;
3920	pSMB->t2.Reserved2 = 0;
3921	pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3922					       Fid));
3923	pSMB->t2.DataCount = 0;
3924	pSMB->t2.DataOffset = 0;
3925	pSMB->t2.SetupCount = 1;
3926	pSMB->t2.Reserved3 = 0;
3927	pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3928	byte_count = params + 1 /* pad */ ;
3929	pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3930	pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3931	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3932	pSMB->Pad = 0;
3933	pSMB->Fid = netfid;
3934	in_len += byte_count;
3935	pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3936
3937	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
3938			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3939	if (rc) {
3940		cifs_dbg(FYI, "Send error in QFileInfo = %d\n", rc);
3941	} else {		/* decode response */
3942		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3943
3944		if (rc) /* BB add auto retry on EOPNOTSUPP? */
3945			rc = smb_EIO2(smb_eio_trace_qfileinfo_invalid,
3946				      get_bcc(&pSMBr->hdr), 40);
3947		else if (get_bcc(&pSMBr->hdr) < 40)
3948			rc = smb_EIO2(smb_eio_trace_qfileinfo_bcc_too_small,
3949				      get_bcc(&pSMBr->hdr), 40);
3950		else if (pFindData) {
3951			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3952			memcpy((char *) pFindData,
3953			       (char *) &pSMBr->hdr.Protocol +
3954			       data_offset, sizeof(FILE_ALL_INFO));
3955		} else
3956		    rc = -ENOMEM;
3957	}
3958	cifs_buf_release(pSMB);
3959	if (rc == -EAGAIN)
3960		goto QFileInfoRetry;
3961
3962	return rc;
3963}
3964
3965int
3966CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
3967		 const char *search_name, FILE_ALL_INFO *data,
3968		 int legacy /* old style infolevel */,
3969		 const struct nls_table *nls_codepage, int remap)
3970{
3971	/* level 263 SMB_QUERY_FILE_ALL_INFO */
3972	TRANSACTION2_QPI_REQ *pSMB = NULL;
3973	TRANSACTION2_QPI_RSP *pSMBr = NULL;
3974	unsigned int in_len;
3975	int rc = 0;
3976	int bytes_returned;
3977	int name_len;
3978	__u16 params, byte_count;
3979
3980	/* cifs_dbg(FYI, "In QPathInfo path %s\n", search_name); */
3981QPathInfoRetry:
3982	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3983		      (void **) &pSMBr);
3984	if (rc < 0)
3985		return rc;
3986	in_len = rc;
3987
3988	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3989		name_len =
3990		    cifsConvertToUTF16((__le16 *) pSMB->FileName, search_name,
3991				       PATH_MAX, nls_codepage, remap);
3992		name_len++;	/* trailing null */
3993		name_len *= 2;
3994	} else {
3995		name_len = copy_path_name(pSMB->FileName, search_name);
3996	}
3997
3998	params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3999	pSMB->TotalDataCount = 0;
4000	pSMB->MaxParameterCount = cpu_to_le16(2);
4001	/* BB find exact max SMB PDU from sess structure BB */
4002	pSMB->MaxDataCount = cpu_to_le16(4000);
4003	pSMB->MaxSetupCount = 0;
4004	pSMB->Reserved = 0;
4005	pSMB->Flags = 0;
4006	pSMB->Timeout = 0;
4007	pSMB->Reserved2 = 0;
4008	pSMB->ParameterOffset = cpu_to_le16(offsetof(
4009		struct smb_com_transaction2_qpi_req, InformationLevel));
4010	pSMB->DataCount = 0;
4011	pSMB->DataOffset = 0;
4012	pSMB->SetupCount = 1;
4013	pSMB->Reserved3 = 0;
4014	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4015	byte_count = params + 1 /* pad */ ;
4016	pSMB->TotalParameterCount = cpu_to_le16(params);
4017	pSMB->ParameterCount = pSMB->TotalParameterCount;
4018	if (legacy)
4019		pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
4020	else
4021		pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4022	pSMB->Reserved4 = 0;
4023	in_len += byte_count;
4024	pSMB->ByteCount = cpu_to_le16(byte_count);
4025
4026	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
4027			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4028	if (rc) {
4029		cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
4030	} else {		/* decode response */
4031		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4032
4033		if (rc) /* BB add auto retry on EOPNOTSUPP? */
4034			rc = smb_EIO2(smb_eio_trace_qpathinfo_invalid,
4035				      get_bcc(&pSMBr->hdr), 40);
4036		else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
4037			rc = smb_EIO2(smb_eio_trace_qpathinfo_bcc_too_small,
4038				      get_bcc(&pSMBr->hdr), 40);
4039		else if (legacy && get_bcc(&pSMBr->hdr) < 24)
4040			/* 24 or 26 expected but we do not read last field */
4041			rc = smb_EIO2(smb_eio_trace_qpathinfo_bcc_too_small,
4042				      get_bcc(&pSMBr->hdr), 24);
4043		else if (data) {
4044			int size;
4045			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4046
4047			/*
4048			 * On legacy responses we do not read the last field,
4049			 * EAsize, fortunately since it varies by subdialect and
4050			 * also note it differs on Set vs Get, ie two bytes or 4
4051			 * bytes depending but we don't care here.
4052			 */
4053			if (legacy)
4054				size = sizeof(FILE_INFO_STANDARD);
4055			else
4056				size = sizeof(FILE_ALL_INFO);
4057			memcpy((char *) data, (char *) &pSMBr->hdr.Protocol +
4058			       data_offset, size);
4059		} else
4060		    rc = -ENOMEM;
4061	}
4062	cifs_buf_release(pSMB);
4063	if (rc == -EAGAIN)
4064		goto QPathInfoRetry;
4065
4066	return rc;
4067}
4068
4069int
4070CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
4071		 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
4072{
4073	struct smb_t2_qfi_req *pSMB = NULL;
4074	struct smb_t2_qfi_rsp *pSMBr = NULL;
4075	unsigned int in_len;
4076	int rc = 0;
4077	int bytes_returned;
4078	__u16 params, byte_count;
4079
4080UnixQFileInfoRetry:
4081	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4082		      (void **) &pSMBr);
4083	if (rc < 0)
4084		return rc;
4085	in_len = rc;
4086
4087	params = 2 /* level */ + 2 /* fid */;
4088	pSMB->t2.TotalDataCount = 0;
4089	pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4090	/* BB find exact max data count below from sess structure BB */
4091	pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4092	pSMB->t2.MaxSetupCount = 0;
4093	pSMB->t2.Reserved = 0;
4094	pSMB->t2.Flags = 0;
4095	pSMB->t2.Timeout = 0;
4096	pSMB->t2.Reserved2 = 0;
4097	pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4098					       Fid));
4099	pSMB->t2.DataCount = 0;
4100	pSMB->t2.DataOffset = 0;
4101	pSMB->t2.SetupCount = 1;
4102	pSMB->t2.Reserved3 = 0;
4103	pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4104	byte_count = params + 1 /* pad */ ;
4105	pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4106	pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4107	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4108	pSMB->Pad = 0;
4109	pSMB->Fid = netfid;
4110	in_len += byte_count;
4111	pSMB->t2.ByteCount = cpu_to_le16(byte_count);
4112
4113	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
4114			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4115	if (rc) {
4116		cifs_dbg(FYI, "Send error in UnixQFileInfo = %d\n", rc);
4117	} else {		/* decode response */
4118		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4119
4120		if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4121			cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
4122			rc = smb_EIO2(smb_eio_trace_unixqfileinfo_bcc_too_small,
4123				      get_bcc(&pSMBr->hdr), sizeof(FILE_UNIX_BASIC_INFO));
4124		} else {
4125			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4126			memcpy((char *) pFindData,
4127			       (char *) &pSMBr->hdr.Protocol +
4128			       data_offset,
4129			       sizeof(FILE_UNIX_BASIC_INFO));
4130		}
4131	}
4132
4133	cifs_buf_release(pSMB);
4134	if (rc == -EAGAIN)
4135		goto UnixQFileInfoRetry;
4136
4137	return rc;
4138}
4139
4140int
4141CIFSSMBUnixQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
4142		     const unsigned char *searchName,
4143		     FILE_UNIX_BASIC_INFO *pFindData,
4144		     const struct nls_table *nls_codepage, int remap)
4145{
4146/* SMB_QUERY_FILE_UNIX_BASIC */
4147	TRANSACTION2_QPI_REQ *pSMB = NULL;
4148	TRANSACTION2_QPI_RSP *pSMBr = NULL;
4149	unsigned int in_len;
4150	int rc = 0;
4151	int bytes_returned = 0;
4152	int name_len;
4153	__u16 params, byte_count;
4154
4155	cifs_dbg(FYI, "In QPathInfo (Unix) the path %s\n", searchName);
4156UnixQPathInfoRetry:
4157	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4158		      (void **) &pSMBr);
4159	if (rc < 0)
4160		return rc;
4161	in_len = rc;
4162
4163	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4164		name_len =
4165		    cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4166				       PATH_MAX, nls_codepage, remap);
4167		name_len++;	/* trailing null */
4168		name_len *= 2;
4169	} else {
4170		name_len = copy_path_name(pSMB->FileName, searchName);
4171	}
4172
4173	params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4174	pSMB->TotalDataCount = 0;
4175	pSMB->MaxParameterCount = cpu_to_le16(2);
4176	/* BB find exact max SMB PDU from sess structure BB */
4177	pSMB->MaxDataCount = cpu_to_le16(4000);
4178	pSMB->MaxSetupCount = 0;
4179	pSMB->Reserved = 0;
4180	pSMB->Flags = 0;
4181	pSMB->Timeout = 0;
4182	pSMB->Reserved2 = 0;
4183	pSMB->ParameterOffset = cpu_to_le16(offsetof(
4184		struct smb_com_transaction2_qpi_req, InformationLevel));
4185	pSMB->DataCount = 0;
4186	pSMB->DataOffset = 0;
4187	pSMB->SetupCount = 1;
4188	pSMB->Reserved3 = 0;
4189	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4190	byte_count = params + 1 /* pad */ ;
4191	pSMB->TotalParameterCount = cpu_to_le16(params);
4192	pSMB->ParameterCount = pSMB->TotalParameterCount;
4193	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4194	pSMB->Reserved4 = 0;
4195	in_len += byte_count;
4196	pSMB->ByteCount = cpu_to_le16(byte_count);
4197
4198	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
4199			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4200	if (rc) {
4201		cifs_dbg(FYI, "Send error in UnixQPathInfo = %d\n", rc);
4202	} else {		/* decode response */
4203		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4204
4205		if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4206			cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
4207			rc = smb_EIO2(smb_eio_trace_unixqpathinfo_bcc_too_small,
4208				      get_bcc(&pSMBr->hdr), sizeof(FILE_UNIX_BASIC_INFO));
4209		} else {
4210			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4211			memcpy((char *) pFindData,
4212			       (char *) &pSMBr->hdr.Protocol +
4213			       data_offset,
4214			       sizeof(FILE_UNIX_BASIC_INFO));
4215		}
4216	}
4217	cifs_buf_release(pSMB);
4218	if (rc == -EAGAIN)
4219		goto UnixQPathInfoRetry;
4220
4221	return rc;
4222}
4223
4224/* xid, tcon, searchName and codepage are input parms, rest are returned */
4225int
4226CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
4227	      const char *searchName, struct cifs_sb_info *cifs_sb,
4228	      __u16 *pnetfid, __u16 search_flags,
4229	      struct cifs_search_info *psrch_inf, bool msearch)
4230{
4231/* level 257 SMB_ */
4232	TRANSACTION2_FFIRST_REQ *pSMB = NULL;
4233	TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
4234	T2_FFIRST_RSP_PARMS *parms;
4235	struct nls_table *nls_codepage;
4236	unsigned int in_len, lnoff;
4237	__u16 params, byte_count;
4238	int bytes_returned = 0;
4239	int name_len, remap;
4240	int rc = 0;
4241
4242	cifs_dbg(FYI, "In FindFirst for %s\n", searchName);
4243
4244findFirstRetry:
4245	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4246		      (void **) &pSMBr);
4247	if (rc < 0)
4248		return rc;
4249	in_len = rc;
4250
4251	nls_codepage = cifs_sb->local_nls;
4252	remap = cifs_remap(cifs_sb);
4253
4254	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4255		name_len =
4256		    cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4257				       PATH_MAX, nls_codepage, remap);
4258		/* We can not add the asterisk earlier in case
4259		it got remapped to 0xF03A as if it were part of the
4260		directory name instead of a wildcard */
4261		name_len *= 2;
4262		if (msearch) {
4263			pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb);
4264			pSMB->FileName[name_len+1] = 0;
4265			pSMB->FileName[name_len+2] = '*';
4266			pSMB->FileName[name_len+3] = 0;
4267			name_len += 4; /* now the trailing null */
4268			/* null terminate just in case */
4269			pSMB->FileName[name_len] = 0;
4270			pSMB->FileName[name_len+1] = 0;
4271			name_len += 2;
4272		} else if (!searchName[0]) {
4273			pSMB->FileName[0] = CIFS_DIR_SEP(cifs_sb);
4274			pSMB->FileName[1] = 0;
4275			pSMB->FileName[2] = 0;
4276			pSMB->FileName[3] = 0;
4277			name_len = 4;
4278		}
4279	} else {
4280		name_len = copy_path_name(pSMB->FileName, searchName);
4281		if (msearch) {
4282			if (WARN_ON_ONCE(name_len > PATH_MAX-2))
4283				name_len = PATH_MAX-2;
4284			/* overwrite nul byte */
4285			pSMB->FileName[name_len-1] = CIFS_DIR_SEP(cifs_sb);
4286			pSMB->FileName[name_len] = '*';
4287			pSMB->FileName[name_len+1] = 0;
4288			name_len += 2;
4289		} else if (!searchName[0]) {
4290			pSMB->FileName[0] = CIFS_DIR_SEP(cifs_sb);
4291			pSMB->FileName[1] = 0;
4292			name_len = 2;
4293		}
4294	}
4295
4296	params = 12 + name_len /* includes null */ ;
4297	pSMB->TotalDataCount = 0;	/* no EAs */
4298	pSMB->MaxParameterCount = cpu_to_le16(10);
4299	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4300	pSMB->MaxSetupCount = 0;
4301	pSMB->Reserved = 0;
4302	pSMB->Flags = 0;
4303	pSMB->Timeout = 0;
4304	pSMB->Reserved2 = 0;
4305	byte_count = params + 1 /* pad */ ;
4306	pSMB->TotalParameterCount = cpu_to_le16(params);
4307	pSMB->ParameterCount = pSMB->TotalParameterCount;
4308	pSMB->ParameterOffset = cpu_to_le16(
4309	      offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes));
4310	pSMB->DataCount = 0;
4311	pSMB->DataOffset = 0;
4312	pSMB->SetupCount = 1;	/* one byte, no need to make endian neutral */
4313	pSMB->Reserved3 = 0;
4314	pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
4315	pSMB->SearchAttributes =
4316	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
4317			ATTR_DIRECTORY);
4318	pSMB->SearchCount = cpu_to_le16(msearch ? CIFSMaxBufSize/sizeof(FILE_UNIX_INFO) : 1);
4319	pSMB->SearchFlags = cpu_to_le16(search_flags);
4320	pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4321
4322	/* BB what should we set StorageType to? Does it matter? BB */
4323	pSMB->SearchStorageType = 0;
4324	in_len += byte_count;
4325	pSMB->ByteCount = cpu_to_le16(byte_count);
4326
4327	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
4328			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4329	cifs_stats_inc(&tcon->stats.cifs_stats.num_ffirst);
4330
4331	if (rc) {
4332		/*
4333		 * BB: add logic to retry regular search if Unix search rejected
4334		 * unexpectedly by server.
4335		 */
4336		/* BB: add code to handle unsupported level rc */
4337		cifs_dbg(FYI, "Error in FindFirst = %d\n", rc);
4338		cifs_buf_release(pSMB);
4339		/*
4340		 * BB: eventually could optimize out free and realloc of buf for
4341		 * this case.
4342		 */
4343		if (rc == -EAGAIN)
4344			goto findFirstRetry;
4345		return rc;
4346	}
4347	/* decode response */
4348	rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4349	if (rc) {
4350		cifs_buf_release(pSMB);
4351		return rc;
4352	}
4353
4354	psrch_inf->unicode = !!(pSMBr->hdr.Flags2 & SMBFLG2_UNICODE);
4355	psrch_inf->ntwrk_buf_start = (char *)pSMBr;
4356	psrch_inf->smallBuf = false;
4357	psrch_inf->srch_entries_start = (char *)&pSMBr->hdr.Protocol +
4358		le16_to_cpu(pSMBr->t2.DataOffset);
4359
4360	parms = (T2_FFIRST_RSP_PARMS *)((char *)&pSMBr->hdr.Protocol +
4361					le16_to_cpu(pSMBr->t2.ParameterOffset));
4362	psrch_inf->endOfSearch = !!parms->EndofSearch;
4363
4364	psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
4365	psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
4366		psrch_inf->entries_in_buffer;
4367	lnoff = le16_to_cpu(parms->LastNameOffset);
4368	if (CIFSMaxBufSize < lnoff) {
4369		cifs_dbg(VFS, "ignoring corrupt resume name\n");
4370		psrch_inf->last_entry = NULL;
4371	} else {
4372		psrch_inf->last_entry = psrch_inf->srch_entries_start + lnoff;
4373		if (pnetfid)
4374			*pnetfid = parms->SearchHandle;
4375	}
4376	return 0;
4377}
4378
4379int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon,
4380		 __u16 searchHandle, __u16 search_flags,
4381		 struct cifs_search_info *psrch_inf)
4382{
4383	TRANSACTION2_FNEXT_REQ *pSMB = NULL;
4384	TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
4385	T2_FNEXT_RSP_PARMS *parms;
4386	unsigned int name_len, in_len;
4387	unsigned int lnoff;
4388	__u16 params, byte_count;
4389	char *response_data;
4390	int bytes_returned;
4391	int rc = 0;
4392
4393	cifs_dbg(FYI, "In FindNext\n");
4394
4395	if (psrch_inf->endOfSearch)
4396		return -ENOENT;
4397
4398	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4399		(void **) &pSMBr);
4400	if (rc < 0)
4401		return rc;
4402	in_len = rc;
4403
4404	params = 14; /* includes 2 bytes of null string, converted to LE below*/
4405	byte_count = 0;
4406	pSMB->TotalDataCount = 0;       /* no EAs */
4407	pSMB->MaxParameterCount = cpu_to_le16(8);
4408	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4409	pSMB->MaxSetupCount = 0;
4410	pSMB->Reserved = 0;
4411	pSMB->Flags = 0;
4412	pSMB->Timeout = 0;
4413	pSMB->Reserved2 = 0;
4414	pSMB->ParameterOffset =  cpu_to_le16(
4415	      offsetof(struct smb_com_transaction2_fnext_req, SearchHandle));
4416	pSMB->DataCount = 0;
4417	pSMB->DataOffset = 0;
4418	pSMB->SetupCount = 1;
4419	pSMB->Reserved3 = 0;
4420	pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
4421	pSMB->SearchHandle = searchHandle;      /* always kept as le */
4422	pSMB->SearchCount =
4423		cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
4424	pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4425	pSMB->ResumeKey = psrch_inf->resume_key;
4426	pSMB->SearchFlags = cpu_to_le16(search_flags);
4427
4428	name_len = psrch_inf->resume_name_len;
4429	params += name_len;
4430	if (name_len < PATH_MAX) {
4431		memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
4432		byte_count += name_len;
4433		/* 14 byte parm len above enough for 2 byte null terminator */
4434		pSMB->ResumeFileName[name_len] = 0;
4435		pSMB->ResumeFileName[name_len+1] = 0;
4436	} else {
4437		cifs_buf_release(pSMB);
4438		return -EINVAL;
4439	}
4440	byte_count = params + 1 /* pad */ ;
4441	pSMB->TotalParameterCount = cpu_to_le16(params);
4442	pSMB->ParameterCount = pSMB->TotalParameterCount;
4443	in_len += byte_count;
4444	pSMB->ByteCount = cpu_to_le16(byte_count);
4445
4446	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
4447			(struct smb_hdr *) pSMBr, &bytes_returned, 0);
4448	cifs_stats_inc(&tcon->stats.cifs_stats.num_fnext);
4449
4450	if (rc) {
4451		cifs_buf_release(pSMB);
4452		if (rc == -EBADF) {
4453			psrch_inf->endOfSearch = true;
4454			rc = 0; /* search probably was closed at end of search*/
4455		} else {
4456			cifs_dbg(FYI, "FindNext returned = %d\n", rc);
4457		}
4458		return rc;
4459	}
4460
4461	/* decode response */
4462	rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4463	if (rc) {
4464		cifs_buf_release(pSMB);
4465		return rc;
4466	}
4467	/* BB fixme add lock for file (srch_info) struct here */
4468	psrch_inf->unicode = !!(pSMBr->hdr.Flags2 & SMBFLG2_UNICODE);
4469	response_data = (char *)&pSMBr->hdr.Protocol +
4470		le16_to_cpu(pSMBr->t2.ParameterOffset);
4471	parms = (T2_FNEXT_RSP_PARMS *)response_data;
4472	response_data = (char *)&pSMBr->hdr.Protocol +
4473		le16_to_cpu(pSMBr->t2.DataOffset);
4474
4475	if (psrch_inf->smallBuf)
4476		cifs_small_buf_release(psrch_inf->ntwrk_buf_start);
4477	else
4478		cifs_buf_release(psrch_inf->ntwrk_buf_start);
4479
4480	psrch_inf->srch_entries_start = response_data;
4481	psrch_inf->ntwrk_buf_start = (char *)pSMB;
4482	psrch_inf->smallBuf = false;
4483	psrch_inf->endOfSearch = !!parms->EndofSearch;
4484	psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
4485	psrch_inf->index_of_last_entry += psrch_inf->entries_in_buffer;
4486	lnoff = le16_to_cpu(parms->LastNameOffset);
4487	if (CIFSMaxBufSize < lnoff) {
4488		cifs_dbg(VFS, "ignoring corrupt resume name\n");
4489		psrch_inf->last_entry = NULL;
4490	} else {
4491		psrch_inf->last_entry =
4492			psrch_inf->srch_entries_start + lnoff;
4493	}
4494	/* BB fixme add unlock here */
4495
4496	/*
4497	 * BB: On error, should we leave previous search buf
4498	 * (and count and last entry fields) intact or free the previous one?
4499	 *
4500	 * Note: On -EAGAIN error only caller can retry on handle based calls
4501	 * since file handle passed in no longer valid.
4502	 */
4503	return 0;
4504}
4505
4506int
4507CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon,
4508	      const __u16 searchHandle)
4509{
4510	int rc = 0;
4511	FINDCLOSE_REQ *pSMB = NULL;
4512	unsigned int in_len;
4513
4514	cifs_dbg(FYI, "In CIFSSMBFindClose\n");
4515	rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
4516
4517	/* no sense returning error if session restarted
4518		as file handle has been closed */
4519	if (rc == -EAGAIN)
4520		return 0;
4521	if (rc < 0)
4522		return rc;
4523	in_len = rc;
4524
4525	pSMB->FileID = searchHandle;
4526	pSMB->ByteCount = 0;
4527	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, in_len, 0);
4528	cifs_small_buf_release(pSMB);
4529	if (rc)
4530		cifs_dbg(VFS, "Send error in FindClose = %d\n", rc);
4531
4532	cifs_stats_inc(&tcon->stats.cifs_stats.num_fclose);
4533
4534	/* Since session is dead, search handle closed on server already */
4535	if (rc == -EAGAIN)
4536		rc = 0;
4537
4538	return rc;
4539}
4540
4541int
4542CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
4543		      const char *search_name, __u64 *inode_number,
4544		      const struct nls_table *nls_codepage, int remap)
4545{
4546	int rc = 0;
4547	TRANSACTION2_QPI_REQ *pSMB = NULL;
4548	TRANSACTION2_QPI_RSP *pSMBr = NULL;
4549	unsigned int in_len;
4550	int name_len, bytes_returned;
4551	__u16 params, byte_count;
4552
4553	cifs_dbg(FYI, "In GetSrvInodeNum for %s\n", search_name);
4554	if (tcon == NULL)
4555		return -ENODEV;
4556
4557GetInodeNumberRetry:
4558	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4559		      (void **) &pSMBr);
4560	if (rc < 0)
4561		return rc;
4562	in_len = rc;
4563
4564	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4565		name_len =
4566			cifsConvertToUTF16((__le16 *) pSMB->FileName,
4567					   search_name, PATH_MAX, nls_codepage,
4568					   remap);
4569		name_len++;     /* trailing null */
4570		name_len *= 2;
4571	} else {
4572		name_len = copy_path_name(pSMB->FileName, search_name);
4573	}
4574
4575	params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
4576	pSMB->TotalDataCount = 0;
4577	pSMB->MaxParameterCount = cpu_to_le16(2);
4578	/* BB find exact max data count below from sess structure BB */
4579	pSMB->MaxDataCount = cpu_to_le16(4000);
4580	pSMB->MaxSetupCount = 0;
4581	pSMB->Reserved = 0;
4582	pSMB->Flags = 0;
4583	pSMB->Timeout = 0;
4584	pSMB->Reserved2 = 0;
4585	pSMB->ParameterOffset = cpu_to_le16(offsetof(
4586		struct smb_com_transaction2_qpi_req, InformationLevel));
4587	pSMB->DataCount = 0;
4588	pSMB->DataOffset = 0;
4589	pSMB->SetupCount = 1;
4590	pSMB->Reserved3 = 0;
4591	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4592	byte_count = params + 1 /* pad */ ;
4593	pSMB->TotalParameterCount = cpu_to_le16(params);
4594	pSMB->ParameterCount = pSMB->TotalParameterCount;
4595	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4596	pSMB->Reserved4 = 0;
4597	in_len += byte_count;
4598	pSMB->ByteCount = cpu_to_le16(byte_count);
4599
4600	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
4601		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
4602	if (rc) {
4603		cifs_dbg(FYI, "error %d in QueryInternalInfo\n", rc);
4604	} else {
4605		/* decode response */
4606		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4607		/* BB also check enough total bytes returned */
4608		if (rc || get_bcc(&pSMBr->hdr) < 2)
4609			/* If rc should we check for EOPNOSUPP and
4610			disable the srvino flag? or in caller? */
4611			rc = smb_EIO2(smb_eio_trace_getsrvinonum_bcc_too_small,
4612				      get_bcc(&pSMBr->hdr), 2);
4613		else {
4614			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4615			__u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4616			struct file_internal_info *pfinfo;
4617			/* BB Do we need a cast or hash here ? */
4618			if (count < 8) {
4619				cifs_dbg(FYI, "Invalid size ret in QryIntrnlInf\n");
4620				rc = smb_EIO2(smb_eio_trace_getsrvinonum_size,
4621					      count, 8);
4622				goto GetInodeNumOut;
4623			}
4624			pfinfo = (struct file_internal_info *)
4625				(data_offset + (char *) &pSMBr->hdr.Protocol);
4626			*inode_number = le64_to_cpu(pfinfo->UniqueId);
4627		}
4628	}
4629GetInodeNumOut:
4630	cifs_buf_release(pSMB);
4631	if (rc == -EAGAIN)
4632		goto GetInodeNumberRetry;
4633	return rc;
4634}
4635
4636int
4637CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
4638		const char *search_name, struct dfs_info3_param **target_nodes,
4639		unsigned int *num_of_nodes,
4640		const struct nls_table *nls_codepage, int remap)
4641{
4642/* TRANS2_GET_DFS_REFERRAL */
4643	TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4644	TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4645	unsigned int in_len;
4646	int rc = 0;
4647	int bytes_returned;
4648	int name_len;
4649	__u16 params, byte_count;
4650	*num_of_nodes = 0;
4651	*target_nodes = NULL;
4652
4653	cifs_dbg(FYI, "In GetDFSRefer the path %s\n", search_name);
4654	if (ses == NULL || ses->tcon_ipc == NULL)
4655		return -ENODEV;
4656
4657getDFSRetry:
4658	/*
4659	 * Use smb_init_no_reconnect() instead of smb_init() as
4660	 * CIFSGetDFSRefer() may be called from cifs_reconnect_tcon() and thus
4661	 * causing an infinite recursion.
4662	 */
4663	rc = smb_init(SMB_COM_TRANSACTION2, 15, ses->tcon_ipc,
4664		      (void **)&pSMB, (void **)&pSMBr);
4665	if (rc < 0)
4666		return rc;
4667	in_len = rc;
4668
4669	/* server pointer checked in called function,
4670	but should never be null here anyway */
4671	pSMB->hdr.Mid = get_next_mid(ses->server);
4672	pSMB->hdr.Tid = ses->tcon_ipc->tid;
4673	pSMB->hdr.Uid = ses->Suid;
4674	if (ses->capabilities & CAP_STATUS32)
4675		pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4676	if (ses->capabilities & CAP_DFS)
4677		pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4678
4679	if (ses->capabilities & CAP_UNICODE) {
4680		pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4681		name_len =
4682		    cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
4683				       search_name, PATH_MAX, nls_codepage,
4684				       remap);
4685		name_len++;	/* trailing null */
4686		name_len *= 2;
4687	} else {	/* BB improve the check for buffer overruns BB */
4688		name_len = copy_path_name(pSMB->RequestFileName, search_name);
4689	}
4690
4691	if (ses->server->sign)
4692		pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4693
4694	pSMB->hdr.Uid = ses->Suid;
4695
4696	params = 2 /* level */  + name_len /*includes null */ ;
4697	pSMB->TotalDataCount = 0;
4698	pSMB->DataCount = 0;
4699	pSMB->DataOffset = 0;
4700	pSMB->MaxParameterCount = 0;
4701	/* BB find exact max SMB PDU from sess structure BB */
4702	pSMB->MaxDataCount = cpu_to_le16(4000);
4703	pSMB->MaxSetupCount = 0;
4704	pSMB->Reserved = 0;
4705	pSMB->Flags = 0;
4706	pSMB->Timeout = 0;
4707	pSMB->Reserved2 = 0;
4708	pSMB->ParameterOffset = cpu_to_le16(offsetof(
4709	  struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel));
4710	pSMB->SetupCount = 1;
4711	pSMB->Reserved3 = 0;
4712	pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4713	byte_count = params + 3 /* pad */ ;
4714	pSMB->ParameterCount = cpu_to_le16(params);
4715	pSMB->TotalParameterCount = pSMB->ParameterCount;
4716	pSMB->MaxReferralLevel = cpu_to_le16(3);
4717	in_len += byte_count;
4718	pSMB->ByteCount = cpu_to_le16(byte_count);
4719
4720	rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, in_len,
4721			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4722	if (rc) {
4723		cifs_dbg(FYI, "Send error in GetDFSRefer = %d\n", rc);
4724		goto GetDFSRefExit;
4725	}
4726	rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4727
4728	/* BB Also check if enough total bytes returned? */
4729	if (rc || get_bcc(&pSMBr->hdr) < 17) {
4730		rc = smb_EIO2(smb_eio_trace_getdfsrefer_bcc_too_small,
4731			      get_bcc(&pSMBr->hdr), 17);
4732		goto GetDFSRefExit;
4733	}
4734
4735	cifs_dbg(FYI, "Decoding GetDFSRefer response BCC: %d  Offset %d\n",
4736		 get_bcc(&pSMBr->hdr), le16_to_cpu(pSMBr->t2.DataOffset));
4737
4738	/* parse returned result into more usable form */
4739	rc = parse_dfs_referrals(&pSMBr->dfs_data,
4740				 le16_to_cpu(pSMBr->t2.DataCount),
4741				 num_of_nodes, target_nodes, nls_codepage,
4742				 remap, search_name,
4743				 (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) != 0);
4744
4745GetDFSRefExit:
4746	cifs_buf_release(pSMB);
4747
4748	if (rc == -EAGAIN)
4749		goto getDFSRetry;
4750
4751	return rc;
4752}
4753
4754/* Query File System Info such as free space to old servers such as Win 9x */
4755int
4756SMBOldQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4757	      struct kstatfs *FSData)
4758{
4759/* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4760	TRANSACTION2_QFSI_REQ *pSMB = NULL;
4761	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4762	FILE_SYSTEM_ALLOC_INFO *response_data;
4763	unsigned int in_len;
4764	int rc = 0;
4765	int bytes_returned = 0;
4766	__u16 params, byte_count;
4767
4768	cifs_dbg(FYI, "OldQFSInfo\n");
4769oldQFSInfoRetry:
4770	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4771		(void **) &pSMBr);
4772	if (rc < 0)
4773		return rc;
4774	in_len = rc;
4775
4776	params = 2;     /* level */
4777	pSMB->TotalDataCount = 0;
4778	pSMB->MaxParameterCount = cpu_to_le16(2);
4779	pSMB->MaxDataCount = cpu_to_le16(1000);
4780	pSMB->MaxSetupCount = 0;
4781	pSMB->Reserved = 0;
4782	pSMB->Flags = 0;
4783	pSMB->Timeout = 0;
4784	pSMB->Reserved2 = 0;
4785	byte_count = params + 1 /* pad */ ;
4786	pSMB->TotalParameterCount = cpu_to_le16(params);
4787	pSMB->ParameterCount = pSMB->TotalParameterCount;
4788	pSMB->ParameterOffset = cpu_to_le16(offsetof(
4789		struct smb_com_transaction2_qfsi_req, InformationLevel));
4790	pSMB->DataCount = 0;
4791	pSMB->DataOffset = 0;
4792	pSMB->SetupCount = 1;
4793	pSMB->Reserved3 = 0;
4794	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4795	pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4796	in_len += byte_count;
4797	pSMB->ByteCount = cpu_to_le16(byte_count);
4798
4799	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
4800		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
4801	if (rc) {
4802		cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
4803	} else {                /* decode response */
4804		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4805
4806		if (rc || get_bcc(&pSMBr->hdr) < 18)
4807			rc = smb_EIO2(smb_eio_trace_oldqfsinfo_bcc_too_small,
4808				      get_bcc(&pSMBr->hdr), 18);
4809		else {
4810			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4811			cifs_dbg(FYI, "qfsinf resp BCC: %d  Offset %d\n",
4812				 get_bcc(&pSMBr->hdr), data_offset);
4813
4814			response_data = (FILE_SYSTEM_ALLOC_INFO *)
4815				(((char *) &pSMBr->hdr.Protocol) + data_offset);
4816			FSData->f_bsize =
4817				le16_to_cpu(response_data->BytesPerSector) *
4818				le32_to_cpu(response_data->
4819					SectorsPerAllocationUnit);
4820			/*
4821			 * much prefer larger but if server doesn't report
4822			 * a valid size than 4K is a reasonable minimum
4823			 */
4824			if (FSData->f_bsize < 512)
4825				FSData->f_bsize = 4096;
4826
4827			FSData->f_blocks =
4828			       le32_to_cpu(response_data->TotalAllocationUnits);
4829			FSData->f_bfree = FSData->f_bavail =
4830				le32_to_cpu(response_data->FreeAllocationUnits);
4831			cifs_dbg(FYI, "Blocks: %lld  Free: %lld Block size %ld\n",
4832				 (unsigned long long)FSData->f_blocks,
4833				 (unsigned long long)FSData->f_bfree,
4834				 FSData->f_bsize);
4835		}
4836	}
4837	cifs_buf_release(pSMB);
4838
4839	if (rc == -EAGAIN)
4840		goto oldQFSInfoRetry;
4841
4842	return rc;
4843}
4844
4845int
4846CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4847	       struct kstatfs *FSData)
4848{
4849/* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4850	TRANSACTION2_QFSI_REQ *pSMB = NULL;
4851	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4852	FILE_SYSTEM_SIZE_INFO *response_data;
4853	unsigned int in_len;
4854	int rc = 0;
4855	int bytes_returned = 0;
4856	__u16 params, byte_count;
4857
4858	cifs_dbg(FYI, "In QFSInfo\n");
4859QFSInfoRetry:
4860	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4861		      (void **) &pSMBr);
4862	if (rc < 0)
4863		return rc;
4864	in_len = rc;
4865
4866	params = 2;	/* level */
4867	pSMB->TotalDataCount = 0;
4868	pSMB->MaxParameterCount = cpu_to_le16(2);
4869	pSMB->MaxDataCount = cpu_to_le16(1000);
4870	pSMB->MaxSetupCount = 0;
4871	pSMB->Reserved = 0;
4872	pSMB->Flags = 0;
4873	pSMB->Timeout = 0;
4874	pSMB->Reserved2 = 0;
4875	byte_count = params + 1 /* pad */ ;
4876	pSMB->TotalParameterCount = cpu_to_le16(params);
4877	pSMB->ParameterCount = pSMB->TotalParameterCount;
4878	pSMB->ParameterOffset = cpu_to_le16(offsetof(
4879		struct smb_com_transaction2_qfsi_req, InformationLevel));
4880	pSMB->DataCount = 0;
4881	pSMB->DataOffset = 0;
4882	pSMB->SetupCount = 1;
4883	pSMB->Reserved3 = 0;
4884	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4885	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4886	in_len += byte_count;
4887	pSMB->ByteCount = cpu_to_le16(byte_count);
4888
4889	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
4890			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4891	if (rc) {
4892		cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
4893	} else {		/* decode response */
4894		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4895
4896		if (rc || get_bcc(&pSMBr->hdr) < 24)
4897			rc = smb_EIO2(smb_eio_trace_qfsinfo_bcc_too_small,
4898				      get_bcc(&pSMBr->hdr), 24);
4899		else {
4900			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4901
4902			response_data =
4903			    (FILE_SYSTEM_SIZE_INFO
4904			     *) (((char *) &pSMBr->hdr.Protocol) +
4905				 data_offset);
4906			FSData->f_bsize =
4907			    le32_to_cpu(response_data->BytesPerSector) *
4908			    le32_to_cpu(response_data->
4909					SectorsPerAllocationUnit);
4910			/*
4911			 * much prefer larger but if server doesn't report
4912			 * a valid size than 4K is a reasonable minimum
4913			 */
4914			if (FSData->f_bsize < 512)
4915				FSData->f_bsize = 4096;
4916
4917			FSData->f_blocks =
4918			    le64_to_cpu(response_data->TotalAllocationUnits);
4919			FSData->f_bfree = FSData->f_bavail =
4920			    le64_to_cpu(response_data->AvailableAllocationUnits);
4921			cifs_dbg(FYI, "Blocks: %lld  Free: %lld Block size %ld\n",
4922				 (unsigned long long)FSData->f_blocks,
4923				 (unsigned long long)FSData->f_bfree,
4924				 FSData->f_bsize);
4925		}
4926	}
4927	cifs_buf_release(pSMB);
4928
4929	if (rc == -EAGAIN)
4930		goto QFSInfoRetry;
4931
4932	return rc;
4933}
4934
4935int
4936CIFSSMBQFSAttributeInfo(const unsigned int xid, struct cifs_tcon *tcon)
4937{
4938/* level 0x105  SMB_QUERY_FILE_SYSTEM_INFO */
4939	TRANSACTION2_QFSI_REQ *pSMB = NULL;
4940	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4941	FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4942	unsigned int in_len;
4943	int rc = 0;
4944	int bytes_returned = 0;
4945	__u16 params, byte_count;
4946
4947	cifs_dbg(FYI, "In QFSAttributeInfo\n");
4948QFSAttributeRetry:
4949	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4950		      (void **) &pSMBr);
4951	if (rc < 0)
4952		return rc;
4953	in_len = rc;
4954
4955	params = 2;	/* level */
4956	pSMB->TotalDataCount = 0;
4957	pSMB->MaxParameterCount = cpu_to_le16(2);
4958	/* BB find exact max SMB PDU from sess structure BB */
4959	pSMB->MaxDataCount = cpu_to_le16(1000);
4960	pSMB->MaxSetupCount = 0;
4961	pSMB->Reserved = 0;
4962	pSMB->Flags = 0;
4963	pSMB->Timeout = 0;
4964	pSMB->Reserved2 = 0;
4965	byte_count = params + 1 /* pad */ ;
4966	pSMB->TotalParameterCount = cpu_to_le16(params);
4967	pSMB->ParameterCount = pSMB->TotalParameterCount;
4968	pSMB->ParameterOffset = cpu_to_le16(offsetof(
4969		struct smb_com_transaction2_qfsi_req, InformationLevel));
4970	pSMB->DataCount = 0;
4971	pSMB->DataOffset = 0;
4972	pSMB->SetupCount = 1;
4973	pSMB->Reserved3 = 0;
4974	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4975	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4976	in_len += byte_count;
4977	pSMB->ByteCount = cpu_to_le16(byte_count);
4978
4979	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
4980			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4981	if (rc) {
4982		cifs_dbg(VFS, "Send error in QFSAttributeInfo = %d\n", rc);
4983	} else {		/* decode response */
4984		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4985
4986		if (rc || get_bcc(&pSMBr->hdr) < 13) {
4987			/* BB also check if enough bytes returned */
4988			rc = smb_EIO2(smb_eio_trace_qfsattrinfo_bcc_too_small,
4989				      get_bcc(&pSMBr->hdr), 13);
4990		} else {
4991			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4992			response_data =
4993			    (FILE_SYSTEM_ATTRIBUTE_INFO
4994			     *) (((char *) &pSMBr->hdr.Protocol) +
4995				 data_offset);
4996			memcpy(&tcon->fsAttrInfo, response_data,
4997			       sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4998		}
4999	}
5000	cifs_buf_release(pSMB);
5001
5002	if (rc == -EAGAIN)
5003		goto QFSAttributeRetry;
5004
5005	return rc;
5006}
5007
5008int
5009CIFSSMBQFSDeviceInfo(const unsigned int xid, struct cifs_tcon *tcon)
5010{
5011/* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
5012	TRANSACTION2_QFSI_REQ *pSMB = NULL;
5013	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5014	FILE_SYSTEM_DEVICE_INFO *response_data;
5015	unsigned int in_len;
5016	int rc = 0;
5017	int bytes_returned = 0;
5018	__u16 params, byte_count;
5019
5020	cifs_dbg(FYI, "In QFSDeviceInfo\n");
5021QFSDeviceRetry:
5022	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5023		      (void **) &pSMBr);
5024	if (rc < 0)
5025		return rc;
5026	in_len = rc;
5027
5028	params = 2;	/* level */
5029	pSMB->TotalDataCount = 0;
5030	pSMB->MaxParameterCount = cpu_to_le16(2);
5031	/* BB find exact max SMB PDU from sess structure BB */
5032	pSMB->MaxDataCount = cpu_to_le16(1000);
5033	pSMB->MaxSetupCount = 0;
5034	pSMB->Reserved = 0;
5035	pSMB->Flags = 0;
5036	pSMB->Timeout = 0;
5037	pSMB->Reserved2 = 0;
5038	byte_count = params + 1 /* pad */ ;
5039	pSMB->TotalParameterCount = cpu_to_le16(params);
5040	pSMB->ParameterCount = pSMB->TotalParameterCount;
5041	pSMB->ParameterOffset = cpu_to_le16(offsetof(
5042		struct smb_com_transaction2_qfsi_req, InformationLevel));
5043
5044	pSMB->DataCount = 0;
5045	pSMB->DataOffset = 0;
5046	pSMB->SetupCount = 1;
5047	pSMB->Reserved3 = 0;
5048	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5049	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
5050	in_len += byte_count;
5051	pSMB->ByteCount = cpu_to_le16(byte_count);
5052
5053	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
5054			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5055	if (rc) {
5056		cifs_dbg(FYI, "Send error in QFSDeviceInfo = %d\n", rc);
5057	} else {		/* decode response */
5058		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5059
5060		if (rc || get_bcc(&pSMBr->hdr) <
5061			  sizeof(FILE_SYSTEM_DEVICE_INFO))
5062			rc = smb_EIO2(smb_eio_trace_qfsdevinfo_bcc_too_small,
5063				      get_bcc(&pSMBr->hdr),
5064				      sizeof(FILE_SYSTEM_DEVICE_INFO));
5065		else {
5066			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5067			response_data =
5068			    (FILE_SYSTEM_DEVICE_INFO *)
5069				(((char *) &pSMBr->hdr.Protocol) +
5070				 data_offset);
5071			memcpy(&tcon->fsDevInfo, response_data,
5072			       sizeof(FILE_SYSTEM_DEVICE_INFO));
5073		}
5074	}
5075	cifs_buf_release(pSMB);
5076
5077	if (rc == -EAGAIN)
5078		goto QFSDeviceRetry;
5079
5080	return rc;
5081}
5082
5083int
5084CIFSSMBQFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon)
5085{
5086/* level 0x200  SMB_QUERY_CIFS_UNIX_INFO */
5087	TRANSACTION2_QFSI_REQ *pSMB = NULL;
5088	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5089	FILE_SYSTEM_UNIX_INFO *response_data;
5090	unsigned int in_len;
5091	int rc = 0;
5092	int bytes_returned = 0;
5093	__u16 params, byte_count;
5094
5095	cifs_dbg(FYI, "In QFSUnixInfo\n");
5096QFSUnixRetry:
5097	rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5098				   (void **) &pSMB, (void **) &pSMBr);
5099	if (rc < 0)
5100		return rc;
5101	in_len = rc;
5102
5103	params = 2;	/* level */
5104	pSMB->TotalDataCount = 0;
5105	pSMB->DataCount = 0;
5106	pSMB->DataOffset = 0;
5107	pSMB->MaxParameterCount = cpu_to_le16(2);
5108	/* BB find exact max SMB PDU from sess structure BB */
5109	pSMB->MaxDataCount = cpu_to_le16(100);
5110	pSMB->MaxSetupCount = 0;
5111	pSMB->Reserved = 0;
5112	pSMB->Flags = 0;
5113	pSMB->Timeout = 0;
5114	pSMB->Reserved2 = 0;
5115	byte_count = params + 1 /* pad */ ;
5116	pSMB->ParameterCount = cpu_to_le16(params);
5117	pSMB->TotalParameterCount = pSMB->ParameterCount;
5118	pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5119			smb_com_transaction2_qfsi_req, InformationLevel));
5120	pSMB->SetupCount = 1;
5121	pSMB->Reserved3 = 0;
5122	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5123	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
5124	in_len += byte_count;
5125	pSMB->ByteCount = cpu_to_le16(byte_count);
5126
5127	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
5128			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5129	if (rc) {
5130		cifs_dbg(VFS, "Send error in QFSUnixInfo = %d\n", rc);
5131	} else {		/* decode response */
5132		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5133
5134		if (rc || get_bcc(&pSMBr->hdr) < 13) {
5135			rc = smb_EIO2(smb_eio_trace_qfsunixinfo_bcc_too_small,
5136				      get_bcc(&pSMBr->hdr), 13);
5137		} else {
5138			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5139			response_data =
5140			    (FILE_SYSTEM_UNIX_INFO
5141			     *) (((char *) &pSMBr->hdr.Protocol) +
5142				 data_offset);
5143			memcpy(&tcon->fsUnixInfo, response_data,
5144			       sizeof(FILE_SYSTEM_UNIX_INFO));
5145		}
5146	}
5147	cifs_buf_release(pSMB);
5148
5149	if (rc == -EAGAIN)
5150		goto QFSUnixRetry;
5151
5152
5153	return rc;
5154}
5155
5156int
5157CIFSSMBSetFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon, __u64 cap)
5158{
5159/* level 0x200  SMB_SET_CIFS_UNIX_INFO */
5160	TRANSACTION2_SETFSI_REQ *pSMB = NULL;
5161	TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
5162	unsigned int in_len;
5163	int rc = 0;
5164	int bytes_returned = 0;
5165	__u16 params, param_offset, offset, byte_count;
5166
5167	cifs_dbg(FYI, "In SETFSUnixInfo\n");
5168SETFSUnixRetry:
5169	/* BB switch to small buf init to save memory */
5170	rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5171					(void **) &pSMB, (void **) &pSMBr);
5172	if (rc < 0)
5173		return rc;
5174	in_len = rc;
5175
5176	params = 4;	/* 2 bytes zero followed by info level. */
5177	pSMB->MaxSetupCount = 0;
5178	pSMB->Reserved = 0;
5179	pSMB->Flags = 0;
5180	pSMB->Timeout = 0;
5181	pSMB->Reserved2 = 0;
5182	param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum);
5183	offset = param_offset + params;
5184
5185	pSMB->MaxParameterCount = cpu_to_le16(4);
5186	/* BB find exact max SMB PDU from sess structure BB */
5187	pSMB->MaxDataCount = cpu_to_le16(100);
5188	pSMB->SetupCount = 1;
5189	pSMB->Reserved3 = 0;
5190	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
5191	byte_count = 1 /* pad */ + params + 12;
5192
5193	pSMB->DataCount = cpu_to_le16(12);
5194	pSMB->ParameterCount = cpu_to_le16(params);
5195	pSMB->TotalDataCount = pSMB->DataCount;
5196	pSMB->TotalParameterCount = pSMB->ParameterCount;
5197	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5198	pSMB->DataOffset = cpu_to_le16(offset);
5199
5200	/* Params. */
5201	pSMB->FileNum = 0;
5202	pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
5203
5204	/* Data. */
5205	pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
5206	pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
5207	pSMB->ClientUnixCap = cpu_to_le64(cap);
5208
5209	in_len += byte_count;
5210	pSMB->ByteCount = cpu_to_le16(byte_count);
5211
5212	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
5213			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5214	if (rc) {
5215		cifs_dbg(VFS, "Send error in SETFSUnixInfo = %d\n", rc);
5216	} else {		/* decode response */
5217		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5218		if (rc)
5219			rc = -EIO;	/* bad smb */
5220	}
5221	cifs_buf_release(pSMB);
5222
5223	if (rc == -EAGAIN)
5224		goto SETFSUnixRetry;
5225
5226	return rc;
5227}
5228
5229
5230
5231int
5232CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon,
5233		   struct kstatfs *FSData)
5234{
5235/* level 0x201  SMB_QUERY_CIFS_POSIX_INFO */
5236	TRANSACTION2_QFSI_REQ *pSMB = NULL;
5237	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5238	FILE_SYSTEM_POSIX_INFO *response_data;
5239	unsigned int in_len;
5240	int rc = 0;
5241	int bytes_returned = 0;
5242	__u16 params, byte_count;
5243
5244	cifs_dbg(FYI, "In QFSPosixInfo\n");
5245QFSPosixRetry:
5246	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5247		      (void **) &pSMBr);
5248	if (rc < 0)
5249		return rc;
5250	in_len = rc;
5251
5252	params = 2;	/* level */
5253	pSMB->TotalDataCount = 0;
5254	pSMB->DataCount = 0;
5255	pSMB->DataOffset = 0;
5256	pSMB->MaxParameterCount = cpu_to_le16(2);
5257	/* BB find exact max SMB PDU from sess structure BB */
5258	pSMB->MaxDataCount = cpu_to_le16(100);
5259	pSMB->MaxSetupCount = 0;
5260	pSMB->Reserved = 0;
5261	pSMB->Flags = 0;
5262	pSMB->Timeout = 0;
5263	pSMB->Reserved2 = 0;
5264	byte_count = params + 1 /* pad */ ;
5265	pSMB->ParameterCount = cpu_to_le16(params);
5266	pSMB->TotalParameterCount = pSMB->ParameterCount;
5267	pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5268			smb_com_transaction2_qfsi_req, InformationLevel));
5269	pSMB->SetupCount = 1;
5270	pSMB->Reserved3 = 0;
5271	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5272	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
5273	in_len += byte_count;
5274	pSMB->ByteCount = cpu_to_le16(byte_count);
5275
5276	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
5277			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5278	if (rc) {
5279		cifs_dbg(FYI, "Send error in QFSUnixInfo = %d\n", rc);
5280	} else {		/* decode response */
5281		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5282
5283		if (rc || get_bcc(&pSMBr->hdr) < 13) {
5284			rc = smb_EIO2(smb_eio_trace_qfsposixinfo_bcc_too_small,
5285				      get_bcc(&pSMBr->hdr), 13);
5286		} else {
5287			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5288			response_data =
5289			    (FILE_SYSTEM_POSIX_INFO
5290			     *) (((char *) &pSMBr->hdr.Protocol) +
5291				 data_offset);
5292			FSData->f_bsize =
5293					le32_to_cpu(response_data->BlockSize);
5294			/*
5295			 * much prefer larger but if server doesn't report
5296			 * a valid size than 4K is a reasonable minimum
5297			 */
5298			if (FSData->f_bsize < 512)
5299				FSData->f_bsize = 4096;
5300
5301			FSData->f_blocks =
5302					le64_to_cpu(response_data->TotalBlocks);
5303			FSData->f_bfree =
5304			    le64_to_cpu(response_data->BlocksAvail);
5305			if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
5306				FSData->f_bavail = FSData->f_bfree;
5307			} else {
5308				FSData->f_bavail =
5309				    le64_to_cpu(response_data->UserBlocksAvail);
5310			}
5311			if (response_data->TotalFileNodes != cpu_to_le64(-1))
5312				FSData->f_files =
5313				     le64_to_cpu(response_data->TotalFileNodes);
5314			if (response_data->FreeFileNodes != cpu_to_le64(-1))
5315				FSData->f_ffree =
5316				      le64_to_cpu(response_data->FreeFileNodes);
5317		}
5318	}
5319	cifs_buf_release(pSMB);
5320
5321	if (rc == -EAGAIN)
5322		goto QFSPosixRetry;
5323
5324	return rc;
5325}
5326
5327
5328/*
5329 * We can not use write of zero bytes trick to set file size due to need for
5330 * large file support. Also note that this SetPathInfo is preferred to
5331 * SetFileInfo based method in next routine which is only needed to work around
5332 * a sharing violation bugin Samba which this routine can run into.
5333 */
5334int
5335CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
5336	      const char *file_name, __u64 size, struct cifs_sb_info *cifs_sb,
5337	      bool set_allocation, struct dentry *dentry)
5338{
5339	struct smb_com_transaction2_spi_req *pSMB = NULL;
5340	struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5341	struct file_end_of_file_info *parm_data;
5342	unsigned int in_len;
5343	int name_len;
5344	int rc = 0;
5345	int bytes_returned = 0;
5346	int remap = cifs_remap(cifs_sb);
5347
5348	__u16 params, byte_count, data_count, param_offset, offset;
5349
5350	cifs_dbg(FYI, "In SetEOF\n");
5351SetEOFRetry:
5352	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5353		      (void **) &pSMBr);
5354	if (rc < 0)
5355		return rc;
5356	in_len = rc;
5357
5358	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5359		name_len =
5360		    cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
5361				       PATH_MAX, cifs_sb->local_nls, remap);
5362		name_len++;	/* trailing null */
5363		name_len *= 2;
5364	} else {
5365		name_len = copy_path_name(pSMB->FileName, file_name);
5366	}
5367	params = 6 + name_len;
5368	data_count = sizeof(struct file_end_of_file_info);
5369	pSMB->MaxParameterCount = cpu_to_le16(2);
5370	pSMB->MaxDataCount = cpu_to_le16(4100);
5371	pSMB->MaxSetupCount = 0;
5372	pSMB->Reserved = 0;
5373	pSMB->Flags = 0;
5374	pSMB->Timeout = 0;
5375	pSMB->Reserved2 = 0;
5376	param_offset = offsetof(struct smb_com_transaction2_spi_req,
5377				InformationLevel);
5378	offset = param_offset + params;
5379	if (set_allocation) {
5380		if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5381			pSMB->InformationLevel =
5382				cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5383		else
5384			pSMB->InformationLevel =
5385				cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5386	} else /* Set File Size */  {
5387	    if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5388		    pSMB->InformationLevel =
5389				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5390	    else
5391		    pSMB->InformationLevel =
5392				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5393	}
5394
5395	parm_data =
5396	    (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
5397				       offset);
5398	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5399	pSMB->DataOffset = cpu_to_le16(offset);
5400	pSMB->SetupCount = 1;
5401	pSMB->Reserved3 = 0;
5402	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5403	byte_count = 3 /* pad */  + params + data_count;
5404	pSMB->DataCount = cpu_to_le16(data_count);
5405	pSMB->TotalDataCount = pSMB->DataCount;
5406	pSMB->ParameterCount = cpu_to_le16(params);
5407	pSMB->TotalParameterCount = pSMB->ParameterCount;
5408	pSMB->Reserved4 = 0;
5409	in_len += byte_count;
5410	parm_data->FileSize = cpu_to_le64(size);
5411	pSMB->ByteCount = cpu_to_le16(byte_count);
5412	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
5413			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5414	if (rc)
5415		cifs_dbg(FYI, "SetPathInfo (file size) returned %d\n", rc);
5416
5417	cifs_buf_release(pSMB);
5418
5419	if (rc == -EAGAIN)
5420		goto SetEOFRetry;
5421
5422	return rc;
5423}
5424
5425int
5426CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon,
5427		   struct cifsFileInfo *cfile, __u64 size, bool set_allocation)
5428{
5429	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5430	struct file_end_of_file_info *parm_data;
5431	unsigned int in_len;
5432	int rc = 0;
5433	__u16 params, param_offset, offset, byte_count, count;
5434
5435	cifs_dbg(FYI, "SetFileSize (via SetFileInfo) %lld\n",
5436		 (long long)size);
5437	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5438	if (rc < 0)
5439		return rc;
5440	in_len = rc;
5441
5442	pSMB->hdr.Pid = cpu_to_le16((__u16)cfile->pid);
5443	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(cfile->pid >> 16));
5444
5445	params = 6;
5446	pSMB->MaxSetupCount = 0;
5447	pSMB->Reserved = 0;
5448	pSMB->Flags = 0;
5449	pSMB->Timeout = 0;
5450	pSMB->Reserved2 = 0;
5451	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid);
5452	offset = param_offset + params;
5453
5454	count = sizeof(struct file_end_of_file_info);
5455	pSMB->MaxParameterCount = cpu_to_le16(2);
5456	/* BB find exact max SMB PDU from sess structure BB */
5457	pSMB->MaxDataCount = cpu_to_le16(1000);
5458	pSMB->SetupCount = 1;
5459	pSMB->Reserved3 = 0;
5460	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5461	byte_count = 3 /* pad */  + params + count;
5462	pSMB->DataCount = cpu_to_le16(count);
5463	pSMB->ParameterCount = cpu_to_le16(params);
5464	pSMB->TotalDataCount = pSMB->DataCount;
5465	pSMB->TotalParameterCount = pSMB->ParameterCount;
5466	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5467	parm_data =
5468		(struct file_end_of_file_info *)(((char *)pSMB) + offset);
5469	pSMB->DataOffset = cpu_to_le16(offset);
5470	parm_data->FileSize = cpu_to_le64(size);
5471	pSMB->Fid = cfile->fid.netfid;
5472	if (set_allocation) {
5473		if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5474			pSMB->InformationLevel =
5475				cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5476		else
5477			pSMB->InformationLevel =
5478				cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5479	} else /* Set File Size */  {
5480	    if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5481		    pSMB->InformationLevel =
5482				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5483	    else
5484		    pSMB->InformationLevel =
5485				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5486	}
5487	pSMB->Reserved4 = 0;
5488	in_len += byte_count;
5489	pSMB->ByteCount = cpu_to_le16(byte_count);
5490	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, in_len, 0);
5491	cifs_small_buf_release(pSMB);
5492	if (rc) {
5493		cifs_dbg(FYI, "Send error in SetFileInfo (SetFileSize) = %d\n",
5494			 rc);
5495	}
5496
5497	/* Note: On -EAGAIN error only caller can retry on handle based calls
5498		since file handle passed in no longer valid */
5499
5500	return rc;
5501}
5502
5503int
5504SMBSetInformation(const unsigned int xid, struct cifs_tcon *tcon,
5505		  const char *fileName, __le32 attributes, __le64 write_time,
5506		  const struct nls_table *nls_codepage,
5507		  struct cifs_sb_info *cifs_sb)
5508{
5509	SETATTR_REQ *pSMB;
5510	SETATTR_RSP *pSMBr;
5511	struct timespec64 ts;
5512	unsigned int in_len;
5513	int bytes_returned;
5514	int name_len;
5515	int rc;
5516
5517	cifs_dbg(FYI, "In %s path %s\n", __func__, fileName);
5518
5519retry:
5520	rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5521		      (void **) &pSMBr);
5522	if (rc < 0)
5523		return rc;
5524	in_len = rc;
5525
5526	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5527		name_len =
5528			cifsConvertToUTF16((__le16 *) pSMB->fileName,
5529					   fileName, PATH_MAX, nls_codepage,
5530					   cifs_remap(cifs_sb));
5531		name_len++;     /* trailing null */
5532		name_len *= 2;
5533	} else {
5534		name_len = copy_path_name(pSMB->fileName, fileName);
5535	}
5536	/* Only few attributes can be set by this command, others are not accepted by Win9x. */
5537	pSMB->attr = cpu_to_le16(le32_to_cpu(attributes) &
5538			(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_ARCHIVE));
5539	/* Zero write time value (in both NT and SETATTR formats) means to not change it. */
5540	if (le64_to_cpu(write_time) != 0) {
5541		ts = cifs_NTtimeToUnix(write_time);
5542		pSMB->last_write_time = cpu_to_le32(ts.tv_sec);
5543	}
5544	pSMB->BufferFormat = 0x04;
5545	name_len++; /* account for buffer type byte */
5546	in_len += name_len;
5547	pSMB->ByteCount = cpu_to_le16(name_len);
5548
5549	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
5550			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5551	if (rc)
5552		cifs_dbg(FYI, "Send error in %s = %d\n", __func__, rc);
5553
5554	cifs_buf_release(pSMB);
5555
5556	if (rc == -EAGAIN)
5557		goto retry;
5558
5559	return rc;
5560}
5561
5562/* Some legacy servers such as NT4 require that the file times be set on
5563   an open handle, rather than by pathname - this is awkward due to
5564   potential access conflicts on the open, but it is unavoidable for these
5565   old servers since the only other choice is to go from 100 nanosecond DCE
5566   time and resort to the original setpathinfo level which takes the ancient
5567   DOS time format with 2 second granularity */
5568int
5569CIFSSMBSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5570		    const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
5571{
5572	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5573	unsigned int in_len;
5574	char *data_offset;
5575	int rc = 0;
5576	__u16 params, param_offset, offset, byte_count, count;
5577
5578	cifs_dbg(FYI, "Set Times (via SetFileInfo)\n");
5579	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5580	if (rc < 0)
5581		return rc;
5582	in_len = rc;
5583
5584	pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5585	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5586
5587	params = 6;
5588	pSMB->MaxSetupCount = 0;
5589	pSMB->Reserved = 0;
5590	pSMB->Flags = 0;
5591	pSMB->Timeout = 0;
5592	pSMB->Reserved2 = 0;
5593	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid);
5594	offset = param_offset + params;
5595
5596	data_offset = (char *)pSMB + offset;
5597
5598	count = sizeof(FILE_BASIC_INFO);
5599	pSMB->MaxParameterCount = cpu_to_le16(2);
5600	/* BB find max SMB PDU from sess */
5601	pSMB->MaxDataCount = cpu_to_le16(1000);
5602	pSMB->SetupCount = 1;
5603	pSMB->Reserved3 = 0;
5604	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5605	byte_count = 3 /* pad */  + params + count;
5606	pSMB->DataCount = cpu_to_le16(count);
5607	pSMB->ParameterCount = cpu_to_le16(params);
5608	pSMB->TotalDataCount = pSMB->DataCount;
5609	pSMB->TotalParameterCount = pSMB->ParameterCount;
5610	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5611	pSMB->DataOffset = cpu_to_le16(offset);
5612	pSMB->Fid = fid;
5613	if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5614		pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5615	else
5616		pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5617	pSMB->Reserved4 = 0;
5618	in_len += byte_count;
5619	pSMB->ByteCount = cpu_to_le16(byte_count);
5620	memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5621	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, in_len, 0);
5622	cifs_small_buf_release(pSMB);
5623	if (rc)
5624		cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
5625			 rc);
5626
5627	/* Note: On -EAGAIN error only caller can retry on handle based calls
5628		since file handle passed in no longer valid */
5629
5630	return rc;
5631}
5632
5633int
5634CIFSSMBSetFileDisposition(const unsigned int xid, struct cifs_tcon *tcon,
5635			  bool delete_file, __u16 fid, __u32 pid_of_opener)
5636{
5637	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5638	unsigned int in_len;
5639	char *data_offset;
5640	int rc = 0;
5641	__u16 params, param_offset, offset, byte_count, count;
5642
5643	cifs_dbg(FYI, "Set File Disposition (via SetFileInfo)\n");
5644	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5645	if (rc < 0)
5646		return rc;
5647	in_len = rc;
5648
5649	pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5650	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5651
5652	params = 6;
5653	pSMB->MaxSetupCount = 0;
5654	pSMB->Reserved = 0;
5655	pSMB->Flags = 0;
5656	pSMB->Timeout = 0;
5657	pSMB->Reserved2 = 0;
5658	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid);
5659	offset = param_offset + params;
5660	data_offset = (char *)(pSMB) + offset;
5661
5662	count = 1;
5663	pSMB->MaxParameterCount = cpu_to_le16(2);
5664	/* BB find max SMB PDU from sess */
5665	pSMB->MaxDataCount = cpu_to_le16(1000);
5666	pSMB->SetupCount = 1;
5667	pSMB->Reserved3 = 0;
5668	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5669	byte_count = 3 /* pad */  + params + count;
5670	pSMB->DataCount = cpu_to_le16(count);
5671	pSMB->ParameterCount = cpu_to_le16(params);
5672	pSMB->TotalDataCount = pSMB->DataCount;
5673	pSMB->TotalParameterCount = pSMB->ParameterCount;
5674	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5675	pSMB->DataOffset = cpu_to_le16(offset);
5676	pSMB->Fid = fid;
5677	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5678	pSMB->Reserved4 = 0;
5679	in_len += byte_count;
5680	pSMB->ByteCount = cpu_to_le16(byte_count);
5681	*data_offset = delete_file ? 1 : 0;
5682	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, in_len, 0);
5683	cifs_small_buf_release(pSMB);
5684	if (rc)
5685		cifs_dbg(FYI, "Send error in SetFileDisposition = %d\n", rc);
5686
5687	return rc;
5688}
5689
5690static int
5691CIFSSMBSetPathInfoFB(const unsigned int xid, struct cifs_tcon *tcon,
5692		     const char *fileName, const FILE_BASIC_INFO *data,
5693		     const struct nls_table *nls_codepage,
5694		     struct cifs_sb_info *cifs_sb)
5695{
5696	int oplock = 0;
5697	struct cifs_open_parms oparms;
5698	struct cifs_fid fid;
5699	int rc;
5700
5701	oparms = (struct cifs_open_parms) {
5702		.tcon = tcon,
5703		.cifs_sb = cifs_sb,
5704		.desired_access = GENERIC_WRITE,
5705		.create_options = cifs_create_options(cifs_sb, 0),
5706		.disposition = FILE_OPEN,
5707		.path = fileName,
5708		.fid = &fid,
5709	};
5710
5711	rc = CIFS_open(xid, &oparms, &oplock, NULL);
5712	if (rc)
5713		goto out;
5714
5715	rc = CIFSSMBSetFileInfo(xid, tcon, data, fid.netfid, current->tgid);
5716	CIFSSMBClose(xid, tcon, fid.netfid);
5717out:
5718
5719	return rc;
5720}
5721
5722int
5723CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
5724		   const char *fileName, const FILE_BASIC_INFO *data,
5725		   const struct nls_table *nls_codepage,
5726		     struct cifs_sb_info *cifs_sb)
5727{
5728	TRANSACTION2_SPI_REQ *pSMB = NULL;
5729	TRANSACTION2_SPI_RSP *pSMBr = NULL;
5730	unsigned int in_len;
5731	int name_len;
5732	int rc = 0;
5733	int bytes_returned = 0;
5734	char *data_offset;
5735	__u16 params, param_offset, offset, byte_count, count;
5736	int remap = cifs_remap(cifs_sb);
5737
5738	cifs_dbg(FYI, "In SetTimes\n");
5739
5740SetTimesRetry:
5741	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5742		      (void **) &pSMBr);
5743	if (rc < 0)
5744		return rc;
5745	in_len = rc;
5746
5747	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5748		name_len =
5749		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5750				       PATH_MAX, nls_codepage, remap);
5751		name_len++;	/* trailing null */
5752		name_len *= 2;
5753	} else {
5754		name_len = copy_path_name(pSMB->FileName, fileName);
5755	}
5756
5757	params = 6 + name_len;
5758	count = sizeof(FILE_BASIC_INFO);
5759	pSMB->MaxParameterCount = cpu_to_le16(2);
5760	/* BB find max SMB PDU from sess structure BB */
5761	pSMB->MaxDataCount = cpu_to_le16(1000);
5762	pSMB->MaxSetupCount = 0;
5763	pSMB->Reserved = 0;
5764	pSMB->Flags = 0;
5765	pSMB->Timeout = 0;
5766	pSMB->Reserved2 = 0;
5767	param_offset = offsetof(struct smb_com_transaction2_spi_req,
5768				InformationLevel);
5769	offset = param_offset + params;
5770	data_offset = (char *)pSMB + offsetof(typeof(*pSMB), hdr.Protocol) + offset;
5771	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5772	pSMB->DataOffset = cpu_to_le16(offset);
5773	pSMB->SetupCount = 1;
5774	pSMB->Reserved3 = 0;
5775	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5776	byte_count = 3 /* pad */  + params + count;
5777
5778	pSMB->DataCount = cpu_to_le16(count);
5779	pSMB->ParameterCount = cpu_to_le16(params);
5780	pSMB->TotalDataCount = pSMB->DataCount;
5781	pSMB->TotalParameterCount = pSMB->ParameterCount;
5782	if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5783		pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5784	else
5785		pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5786	pSMB->Reserved4 = 0;
5787	in_len += byte_count;
5788	memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5789	pSMB->ByteCount = cpu_to_le16(byte_count);
5790	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
5791			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5792	if (rc)
5793		cifs_dbg(FYI, "SetPathInfo (times) returned %d\n", rc);
5794
5795	cifs_buf_release(pSMB);
5796
5797	if (rc == -EAGAIN)
5798		goto SetTimesRetry;
5799
5800	if (rc == -EOPNOTSUPP)
5801		return CIFSSMBSetPathInfoFB(xid, tcon, fileName, data,
5802					    nls_codepage, cifs_sb);
5803
5804	return rc;
5805}
5806
5807static void
5808cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5809			const struct cifs_unix_set_info_args *args)
5810{
5811	u64 uid = NO_CHANGE_64, gid = NO_CHANGE_64;
5812	u64 mode = args->mode;
5813
5814	if (uid_valid(args->uid))
5815		uid = from_kuid(&init_user_ns, args->uid);
5816	if (gid_valid(args->gid))
5817		gid = from_kgid(&init_user_ns, args->gid);
5818
5819	/*
5820	 * Samba server ignores set of file size to zero due to bugs in some
5821	 * older clients, but we should be precise - we use SetFileSize to
5822	 * set file size and do not want to truncate file size to zero
5823	 * accidentally as happened on one Samba server beta by putting
5824	 * zero instead of -1 here
5825	 */
5826	data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5827	data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5828	data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5829	data_offset->LastAccessTime = cpu_to_le64(args->atime);
5830	data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5831	data_offset->Uid = cpu_to_le64(uid);
5832	data_offset->Gid = cpu_to_le64(gid);
5833	/* better to leave device as zero when it is  */
5834	data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5835	data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5836	data_offset->Permissions = cpu_to_le64(mode);
5837
5838	if (S_ISREG(mode))
5839		data_offset->Type = cpu_to_le32(UNIX_FILE);
5840	else if (S_ISDIR(mode))
5841		data_offset->Type = cpu_to_le32(UNIX_DIR);
5842	else if (S_ISLNK(mode))
5843		data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5844	else if (S_ISCHR(mode))
5845		data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5846	else if (S_ISBLK(mode))
5847		data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5848	else if (S_ISFIFO(mode))
5849		data_offset->Type = cpu_to_le32(UNIX_FIFO);
5850	else if (S_ISSOCK(mode))
5851		data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5852}
5853
5854int
5855CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5856		       const struct cifs_unix_set_info_args *args,
5857		       u16 fid, u32 pid_of_opener)
5858{
5859	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5860	unsigned int in_len;
5861	char *data_offset;
5862	int rc = 0;
5863	u16 params, param_offset, offset, byte_count, count;
5864
5865	cifs_dbg(FYI, "Set Unix Info (via SetFileInfo)\n");
5866	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5867	if (rc < 0)
5868		return rc;
5869	in_len = rc;
5870
5871	pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5872	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5873
5874	params = 6;
5875	pSMB->MaxSetupCount = 0;
5876	pSMB->Reserved = 0;
5877	pSMB->Flags = 0;
5878	pSMB->Timeout = 0;
5879	pSMB->Reserved2 = 0;
5880	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid);
5881	offset = param_offset + params;
5882
5883	data_offset = (char *)pSMB + offset;
5884
5885	count = sizeof(FILE_UNIX_BASIC_INFO);
5886
5887	pSMB->MaxParameterCount = cpu_to_le16(2);
5888	/* BB find max SMB PDU from sess */
5889	pSMB->MaxDataCount = cpu_to_le16(1000);
5890	pSMB->SetupCount = 1;
5891	pSMB->Reserved3 = 0;
5892	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5893	byte_count = 3 /* pad */  + params + count;
5894	pSMB->DataCount = cpu_to_le16(count);
5895	pSMB->ParameterCount = cpu_to_le16(params);
5896	pSMB->TotalDataCount = pSMB->DataCount;
5897	pSMB->TotalParameterCount = pSMB->ParameterCount;
5898	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5899	pSMB->DataOffset = cpu_to_le16(offset);
5900	pSMB->Fid = fid;
5901	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5902	pSMB->Reserved4 = 0;
5903	in_len += byte_count;
5904	pSMB->ByteCount = cpu_to_le16(byte_count);
5905
5906	cifs_fill_unix_set_info((FILE_UNIX_BASIC_INFO *)data_offset, args);
5907
5908	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, in_len, 0);
5909	cifs_small_buf_release(pSMB);
5910	if (rc)
5911		cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
5912			 rc);
5913
5914	/* Note: On -EAGAIN error only caller can retry on handle based calls
5915		since file handle passed in no longer valid */
5916
5917	return rc;
5918}
5919
5920int
5921CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
5922		       const char *file_name,
5923		       const struct cifs_unix_set_info_args *args,
5924		       const struct nls_table *nls_codepage, int remap)
5925{
5926	TRANSACTION2_SPI_REQ *pSMB = NULL;
5927	TRANSACTION2_SPI_RSP *pSMBr = NULL;
5928	unsigned int in_len;
5929	int name_len;
5930	int rc = 0;
5931	int bytes_returned = 0;
5932	FILE_UNIX_BASIC_INFO *data_offset;
5933	__u16 params, param_offset, offset, count, byte_count;
5934
5935	cifs_dbg(FYI, "In SetUID/GID/Mode\n");
5936setPermsRetry:
5937	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5938		      (void **) &pSMBr);
5939	if (rc < 0)
5940		return rc;
5941	in_len = rc;
5942
5943	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5944		name_len =
5945		    cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
5946				       PATH_MAX, nls_codepage, remap);
5947		name_len++;	/* trailing null */
5948		name_len *= 2;
5949	} else {
5950		name_len = copy_path_name(pSMB->FileName, file_name);
5951	}
5952
5953	params = 6 + name_len;
5954	count = sizeof(FILE_UNIX_BASIC_INFO);
5955	pSMB->MaxParameterCount = cpu_to_le16(2);
5956	/* BB find max SMB PDU from sess structure BB */
5957	pSMB->MaxDataCount = cpu_to_le16(1000);
5958	pSMB->MaxSetupCount = 0;
5959	pSMB->Reserved = 0;
5960	pSMB->Flags = 0;
5961	pSMB->Timeout = 0;
5962	pSMB->Reserved2 = 0;
5963	param_offset = offsetof(struct smb_com_transaction2_spi_req,
5964				InformationLevel);
5965	offset = param_offset + params;
5966	data_offset = (FILE_UNIX_BASIC_INFO *)((char *) pSMB + offset);
5967	memset(data_offset, 0, count);
5968	pSMB->DataOffset = cpu_to_le16(offset);
5969	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5970	pSMB->SetupCount = 1;
5971	pSMB->Reserved3 = 0;
5972	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5973	byte_count = 3 /* pad */  + params + count;
5974	pSMB->ParameterCount = cpu_to_le16(params);
5975	pSMB->DataCount = cpu_to_le16(count);
5976	pSMB->TotalParameterCount = pSMB->ParameterCount;
5977	pSMB->TotalDataCount = pSMB->DataCount;
5978	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5979	pSMB->Reserved4 = 0;
5980	in_len += byte_count;
5981
5982	cifs_fill_unix_set_info(data_offset, args);
5983
5984	pSMB->ByteCount = cpu_to_le16(byte_count);
5985	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
5986			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5987	if (rc)
5988		cifs_dbg(FYI, "SetPathInfo (perms) returned %d\n", rc);
5989
5990	cifs_buf_release(pSMB);
5991	if (rc == -EAGAIN)
5992		goto setPermsRetry;
5993	return rc;
5994}
5995
5996#ifdef CONFIG_CIFS_XATTR
5997/*
5998 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
5999 * function used by listxattr and getxattr type calls. When ea_name is set,
6000 * it looks for that attribute name and stuffs that value into the EAData
6001 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
6002 * buffer. In both cases, the return value is either the length of the
6003 * resulting data or a negative error code. If EAData is a NULL pointer then
6004 * the data isn't copied to it, but the length is returned.
6005 */
6006ssize_t
6007CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
6008		const unsigned char *searchName, const unsigned char *ea_name,
6009		char *EAData, size_t buf_size,
6010		struct cifs_sb_info *cifs_sb)
6011{
6012		/* BB assumes one setup word */
6013	TRANSACTION2_QPI_REQ *pSMB = NULL;
6014	TRANSACTION2_QPI_RSP *pSMBr = NULL;
6015	int remap = cifs_remap(cifs_sb);
6016	struct nls_table *nls_codepage = cifs_sb->local_nls;
6017	unsigned int in_len;
6018	int rc = 0;
6019	int bytes_returned;
6020	int list_len;
6021	struct fealist *ea_response_data;
6022	struct fea *temp_fea;
6023	char *temp_ptr;
6024	char *end_of_smb;
6025	__u16 params, byte_count, data_offset;
6026	unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;
6027
6028	cifs_dbg(FYI, "In Query All EAs path %s\n", searchName);
6029QAllEAsRetry:
6030	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6031		      (void **) &pSMBr);
6032	if (rc < 0)
6033		return rc;
6034	in_len = rc;
6035
6036	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6037		list_len =
6038		    cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
6039				       PATH_MAX, nls_codepage, remap);
6040		list_len++;	/* trailing null */
6041		list_len *= 2;
6042	} else {
6043		list_len = copy_path_name(pSMB->FileName, searchName);
6044	}
6045
6046	params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
6047	pSMB->TotalDataCount = 0;
6048	pSMB->MaxParameterCount = cpu_to_le16(2);
6049	/* BB find exact max SMB PDU from sess structure BB */
6050	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
6051	pSMB->MaxSetupCount = 0;
6052	pSMB->Reserved = 0;
6053	pSMB->Flags = 0;
6054	pSMB->Timeout = 0;
6055	pSMB->Reserved2 = 0;
6056	pSMB->ParameterOffset = cpu_to_le16(offsetof(
6057		struct smb_com_transaction2_qpi_req, InformationLevel));
6058	pSMB->DataCount = 0;
6059	pSMB->DataOffset = 0;
6060	pSMB->SetupCount = 1;
6061	pSMB->Reserved3 = 0;
6062	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
6063	byte_count = params + 1 /* pad */ ;
6064	pSMB->TotalParameterCount = cpu_to_le16(params);
6065	pSMB->ParameterCount = pSMB->TotalParameterCount;
6066	pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
6067	pSMB->Reserved4 = 0;
6068	in_len += byte_count;
6069	pSMB->ByteCount = cpu_to_le16(byte_count);
6070
6071	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
6072			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6073	if (rc) {
6074		cifs_dbg(FYI, "Send error in QueryAllEAs = %d\n", rc);
6075		goto QAllEAsOut;
6076	}
6077
6078
6079	/* BB also check enough total bytes returned */
6080	/* BB we need to improve the validity checking
6081	of these trans2 responses */
6082
6083	rc = validate_t2((struct smb_t2_rsp *)pSMBr);
6084	if (rc || get_bcc(&pSMBr->hdr) < 4) {
6085		rc = smb_EIO2(smb_eio_trace_qalleas_bcc_too_small,
6086			      get_bcc(&pSMBr->hdr), 4);
6087		goto QAllEAsOut;
6088	}
6089
6090	/* check that length of list is not more than bcc */
6091	/* check that each entry does not go beyond length
6092	   of list */
6093	/* check that each element of each entry does not
6094	   go beyond end of list */
6095	/* validate_trans2_offsets() */
6096	/* BB check if start of smb + data_offset > &bcc+ bcc */
6097
6098	data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
6099	ea_response_data = (struct fealist *)
6100				(((char *) &pSMBr->hdr.Protocol) + data_offset);
6101
6102	list_len = le32_to_cpu(ea_response_data->list_len);
6103	cifs_dbg(FYI, "ea length %d\n", list_len);
6104	if (list_len <= 8) {
6105		cifs_dbg(FYI, "empty EA list returned from server\n");
6106		/* didn't find the named attribute */
6107		if (ea_name)
6108			rc = -ENODATA;
6109		goto QAllEAsOut;
6110	}
6111
6112	/* make sure list_len doesn't go past end of SMB */
6113	end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
6114	if ((char *)ea_response_data + list_len > end_of_smb) {
6115		cifs_dbg(FYI, "EA list appears to go beyond SMB\n");
6116		rc = smb_EIO2(smb_eio_trace_qalleas_overlong,
6117			      (unsigned long)ea_response_data + list_len - (unsigned long)pSMBr,
6118			      (unsigned long)end_of_smb - (unsigned long)pSMBr);
6119		goto QAllEAsOut;
6120	}
6121
6122	/* account for ea list len */
6123	list_len -= 4;
6124	temp_fea = &ea_response_data->list;
6125	temp_ptr = (char *)temp_fea;
6126	while (list_len > 0) {
6127		unsigned int name_len;
6128		__u16 value_len;
6129
6130		list_len -= 4;
6131		temp_ptr += 4;
6132		/* make sure we can read name_len and value_len */
6133		if (list_len < 0) {
6134			cifs_dbg(FYI, "EA entry goes beyond length of list\n");
6135			rc = smb_EIO1(smb_eio_trace_qalleas_ea_overlong, list_len);
6136			goto QAllEAsOut;
6137		}
6138
6139		name_len = temp_fea->name_len;
6140		value_len = le16_to_cpu(temp_fea->value_len);
6141		list_len -= name_len + 1 + value_len;
6142		if (list_len < 0) {
6143			cifs_dbg(FYI, "EA entry goes beyond length of list\n");
6144			rc = smb_EIO1(smb_eio_trace_qalleas_ea_overlong, list_len);
6145			goto QAllEAsOut;
6146		}
6147
6148		if (ea_name) {
6149			if (ea_name_len == name_len &&
6150			    memcmp(ea_name, temp_ptr, name_len) == 0) {
6151				temp_ptr += name_len + 1;
6152				rc = value_len;
6153				if (buf_size == 0)
6154					goto QAllEAsOut;
6155				if ((size_t)value_len > buf_size) {
6156					rc = -ERANGE;
6157					goto QAllEAsOut;
6158				}
6159				memcpy(EAData, temp_ptr, value_len);
6160				goto QAllEAsOut;
6161			}
6162		} else {
6163			/* account for prefix user. and trailing null */
6164			rc += (5 + 1 + name_len);
6165			if (rc < (int) buf_size) {
6166				memcpy(EAData, "user.", 5);
6167				EAData += 5;
6168				memcpy(EAData, temp_ptr, name_len);
6169				EAData += name_len;
6170				/* null terminate name */
6171				*EAData = 0;
6172				++EAData;
6173			} else if (buf_size == 0) {
6174				/* skip copy - calc size only */
6175			} else {
6176				/* stop before overrun buffer */
6177				rc = -ERANGE;
6178				break;
6179			}
6180		}
6181		temp_ptr += name_len + 1 + value_len;
6182		temp_fea = (struct fea *)temp_ptr;
6183	}
6184
6185	/* didn't find the named attribute */
6186	if (ea_name)
6187		rc = -ENODATA;
6188
6189QAllEAsOut:
6190	cifs_buf_release(pSMB);
6191	if (rc == -EAGAIN)
6192		goto QAllEAsRetry;
6193
6194	return (ssize_t)rc;
6195}
6196
6197int
6198CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
6199	     const char *fileName, const char *ea_name, const void *ea_value,
6200	     const __u16 ea_value_len, const struct nls_table *nls_codepage,
6201	     struct cifs_sb_info *cifs_sb)
6202{
6203	struct smb_com_transaction2_spi_req *pSMB = NULL;
6204	struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
6205	struct fealist *parm_data;
6206	unsigned int in_len;
6207	int name_len;
6208	int rc = 0;
6209	int bytes_returned = 0;
6210	__u16 params, param_offset, byte_count, offset, count;
6211	int remap = cifs_remap(cifs_sb);
6212
6213	cifs_dbg(FYI, "In SetEA\n");
6214SetEARetry:
6215	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6216		      (void **) &pSMBr);
6217	if (rc < 0)
6218		return rc;
6219	in_len = rc;
6220
6221	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6222		name_len =
6223		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
6224				       PATH_MAX, nls_codepage, remap);
6225		name_len++;	/* trailing null */
6226		name_len *= 2;
6227	} else {
6228		name_len = copy_path_name(pSMB->FileName, fileName);
6229	}
6230
6231	params = 6 + name_len;
6232
6233	/* done calculating parms using name_len of file name,
6234	now use name_len to calculate length of ea name
6235	we are going to create in the inode xattrs */
6236	if (ea_name == NULL)
6237		name_len = 0;
6238	else
6239		name_len = strnlen(ea_name, 255);
6240
6241	count = sizeof(*parm_data) + 1 + ea_value_len + name_len;
6242	pSMB->MaxParameterCount = cpu_to_le16(2);
6243	/* BB find max SMB PDU from sess */
6244	pSMB->MaxDataCount = cpu_to_le16(1000);
6245	pSMB->MaxSetupCount = 0;
6246	pSMB->Reserved = 0;
6247	pSMB->Flags = 0;
6248	pSMB->Timeout = 0;
6249	pSMB->Reserved2 = 0;
6250	param_offset = offsetof(struct smb_com_transaction2_spi_req,
6251				InformationLevel);
6252	offset = param_offset + params;
6253	pSMB->InformationLevel =
6254		cpu_to_le16(SMB_SET_FILE_EA);
6255
6256	parm_data = (void *)pSMB + offset;
6257	pSMB->ParameterOffset = cpu_to_le16(param_offset);
6258	pSMB->DataOffset = cpu_to_le16(offset);
6259	pSMB->SetupCount = 1;
6260	pSMB->Reserved3 = 0;
6261	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
6262	byte_count = 3 /* pad */  + params + count;
6263	pSMB->DataCount = cpu_to_le16(count);
6264	parm_data->list_len = cpu_to_le32(count);
6265	parm_data->list.EA_flags = 0;
6266	/* we checked above that name len is less than 255 */
6267	parm_data->list.name_len = (__u8)name_len;
6268	/* EA names are always ASCII and NUL-terminated */
6269	strscpy(parm_data->list.name, ea_name ?: "", name_len + 1);
6270	parm_data->list.value_len = cpu_to_le16(ea_value_len);
6271	/* caller ensures that ea_value_len is less than 64K but
6272	we need to ensure that it fits within the smb */
6273
6274	/*BB add length check to see if it would fit in
6275	     negotiated SMB buffer size BB */
6276	/* if (ea_value_len > buffer_size - 512 (enough for header)) */
6277	if (ea_value_len)
6278		memcpy(parm_data->list.name + name_len + 1,
6279		       ea_value, ea_value_len);
6280
6281	pSMB->TotalDataCount = pSMB->DataCount;
6282	pSMB->ParameterCount = cpu_to_le16(params);
6283	pSMB->TotalParameterCount = pSMB->ParameterCount;
6284	pSMB->Reserved4 = 0;
6285	in_len += byte_count;
6286	pSMB->ByteCount = cpu_to_le16(byte_count);
6287	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
6288			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6289	if (rc)
6290		cifs_dbg(FYI, "SetPathInfo (EA) returned %d\n", rc);
6291
6292	cifs_buf_release(pSMB);
6293
6294	if (rc == -EAGAIN)
6295		goto SetEARetry;
6296
6297	return rc;
6298}
6299#endif
~/ Read-only file preview.