cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

cifssmb.c (188218B)


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