misc.c 24.0 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3
/*
 *   fs/cifs/misc.c
 *
S
Steve French 已提交
4
 *   Copyright (C) International Business Machines  Corp., 2002,2008
L
Linus Torvalds 已提交
5 6 7 8 9 10 11 12 13 14 15 16 17 18
 *   Author(s): Steve French (sfrench@us.ibm.com)
 *
 *   This library is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Lesser General Public License as published
 *   by the Free Software Foundation; either version 2.1 of the License, or
 *   (at your option) any later version.
 *
 *   This library is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
 *   the GNU Lesser General Public License for more details.
 *
 *   You should have received a copy of the GNU Lesser General Public License
 *   along with this library; if not, write to the Free Software
S
Steve French 已提交
19
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
L
Linus Torvalds 已提交
20 21 22 23 24
 */

#include <linux/slab.h>
#include <linux/ctype.h>
#include <linux/mempool.h>
25
#include <linux/vmalloc.h>
L
Linus Torvalds 已提交
26 27 28 29 30 31
#include "cifspdu.h"
#include "cifsglob.h"
#include "cifsproto.h"
#include "cifs_debug.h"
#include "smberr.h"
#include "nterr.h"
32
#include "cifs_unicode.h"
33
#include "smb2pdu.h"
L
Linus Torvalds 已提交
34 35 36 37

extern mempool_t *cifs_sm_req_poolp;
extern mempool_t *cifs_req_poolp;

S
Steve French 已提交
38 39 40 41
/* The xid serves as a useful identifier for each incoming vfs request,
   in a similar way to the mid which is useful to track each sent smb,
   and CurrentXid can also provide a running counter (although it
   will eventually wrap past zero) of the total vfs operations handled
L
Linus Torvalds 已提交
42 43 44
   since the cifs fs was mounted */

unsigned int
45
_get_xid(void)
L
Linus Torvalds 已提交
46 47 48 49 50
{
	unsigned int xid;

	spin_lock(&GlobalMid_Lock);
	GlobalTotalActiveXid++;
51 52

	/* keep high water mark for number of simultaneous ops in filesystem */
L
Linus Torvalds 已提交
53
	if (GlobalTotalActiveXid > GlobalMaxActiveXid)
54
		GlobalMaxActiveXid = GlobalTotalActiveXid;
S
Steve French 已提交
55
	if (GlobalTotalActiveXid > 65000)
56
		cifs_dbg(FYI, "warning: more than 65000 requests active\n");
L
Linus Torvalds 已提交
57 58 59 60 61 62
	xid = GlobalCurrentXid++;
	spin_unlock(&GlobalMid_Lock);
	return xid;
}

void
63
_free_xid(unsigned int xid)
L
Linus Torvalds 已提交
64 65
{
	spin_lock(&GlobalMid_Lock);
S
Steve French 已提交
66
	/* if (GlobalTotalActiveXid == 0)
L
Linus Torvalds 已提交
67 68 69 70 71
		BUG(); */
	GlobalTotalActiveXid--;
	spin_unlock(&GlobalMid_Lock);
}

72
struct cifs_ses *
L
Linus Torvalds 已提交
73 74
sesInfoAlloc(void)
{
75
	struct cifs_ses *ret_buf;
L
Linus Torvalds 已提交
76

77
	ret_buf = kzalloc(sizeof(struct cifs_ses), GFP_KERNEL);
L
Linus Torvalds 已提交
78 79 80
	if (ret_buf) {
		atomic_inc(&sesInfoAllocCount);
		ret_buf->status = CifsNew;
81 82
		++ret_buf->ses_count;
		INIT_LIST_HEAD(&ret_buf->smb_ses_list);
83
		INIT_LIST_HEAD(&ret_buf->tcon_list);
84
		mutex_init(&ret_buf->session_mutex);
L
Linus Torvalds 已提交
85 86 87 88 89
	}
	return ret_buf;
}

void
90
sesInfoFree(struct cifs_ses *buf_to_free)
L
Linus Torvalds 已提交
91 92
{
	if (buf_to_free == NULL) {
93
		cifs_dbg(FYI, "Null buffer passed to sesInfoFree\n");
L
Linus Torvalds 已提交
94 95 96 97
		return;
	}

	atomic_dec(&sesInfoAllocCount);
J
Jesper Juhl 已提交
98 99 100
	kfree(buf_to_free->serverOS);
	kfree(buf_to_free->serverDomain);
	kfree(buf_to_free->serverNOS);
101
	kzfree(buf_to_free->password);
102
	kfree(buf_to_free->user_name);
103
	kfree(buf_to_free->domainName);
104 105
	kzfree(buf_to_free->auth_key.response);
	kzfree(buf_to_free);
L
Linus Torvalds 已提交
106 107
}

108
struct cifs_tcon *
L
Linus Torvalds 已提交
109 110
tconInfoAlloc(void)
{
111 112
	struct cifs_tcon *ret_buf;
	ret_buf = kzalloc(sizeof(struct cifs_tcon), GFP_KERNEL);
L
Linus Torvalds 已提交
113 114 115
	if (ret_buf) {
		atomic_inc(&tconInfoAllocCount);
		ret_buf->tidStatus = CifsNew;
116
		++ret_buf->tc_count;
L
Linus Torvalds 已提交
117
		INIT_LIST_HEAD(&ret_buf->openFileList);
118
		INIT_LIST_HEAD(&ret_buf->tcon_list);
119
		spin_lock_init(&ret_buf->open_file_lock);
L
Linus Torvalds 已提交
120 121 122 123 124 125 126 127
#ifdef CONFIG_CIFS_STATS
		spin_lock_init(&ret_buf->stat_lock);
#endif
	}
	return ret_buf;
}

void
128
tconInfoFree(struct cifs_tcon *buf_to_free)
L
Linus Torvalds 已提交
129 130
{
	if (buf_to_free == NULL) {
131
		cifs_dbg(FYI, "Null buffer passed to tconInfoFree\n");
L
Linus Torvalds 已提交
132 133 134
		return;
	}
	atomic_dec(&tconInfoAllocCount);
J
Jesper Juhl 已提交
135
	kfree(buf_to_free->nativeFileSystem);
136
	kzfree(buf_to_free->password);
L
Linus Torvalds 已提交
137 138 139 140 141 142 143
	kfree(buf_to_free);
}

struct smb_hdr *
cifs_buf_get(void)
{
	struct smb_hdr *ret_buf = NULL;
144 145 146 147
	/*
	 * SMB2 header is bigger than CIFS one - no problems to clean some
	 * more bytes for CIFS.
	 */
148 149
	size_t buf_size = sizeof(struct smb2_hdr);

150 151 152 153 154 155
	/*
	 * We could use negotiated size instead of max_msgsize -
	 * but it may be more efficient to always alloc same size
	 * albeit slightly larger than necessary and maxbuffersize
	 * defaults to this and can not be bigger.
	 */
156
	ret_buf = mempool_alloc(cifs_req_poolp, GFP_NOFS);
L
Linus Torvalds 已提交
157 158 159

	/* clear the first few header bytes */
	/* for most paths, more is cleared in header_assemble */
160 161
	memset(ret_buf, 0, buf_size + 3);
	atomic_inc(&bufAllocCount);
162
#ifdef CONFIG_CIFS_STATS2
163
	atomic_inc(&totBufAllocCount);
164
#endif /* CONFIG_CIFS_STATS2 */
L
Linus Torvalds 已提交
165 166 167 168 169 170 171 172

	return ret_buf;
}

void
cifs_buf_release(void *buf_to_free)
{
	if (buf_to_free == NULL) {
173
		/* cifs_dbg(FYI, "Null buffer passed to cifs_buf_release\n");*/
L
Linus Torvalds 已提交
174 175
		return;
	}
S
Steve French 已提交
176
	mempool_free(buf_to_free, cifs_req_poolp);
L
Linus Torvalds 已提交
177 178 179 180 181 182 183 184 185 186

	atomic_dec(&bufAllocCount);
	return;
}

struct smb_hdr *
cifs_small_buf_get(void)
{
	struct smb_hdr *ret_buf = NULL;

S
Steve French 已提交
187 188 189
/* We could use negotiated size instead of max_msgsize -
   but it may be more efficient to always alloc same size
   albeit slightly larger than necessary and maxbuffersize
L
Linus Torvalds 已提交
190
   defaults to this and can not be bigger */
191
	ret_buf = mempool_alloc(cifs_sm_req_poolp, GFP_NOFS);
L
Linus Torvalds 已提交
192 193
	/* No need to clear memory here, cleared in header assemble */
	/*	memset(ret_buf, 0, sizeof(struct smb_hdr) + 27);*/
194
	atomic_inc(&smBufAllocCount);
195
#ifdef CONFIG_CIFS_STATS2
196
	atomic_inc(&totSmBufAllocCount);
197 198
#endif /* CONFIG_CIFS_STATS2 */

L
Linus Torvalds 已提交
199 200 201 202 203 204 205 206
	return ret_buf;
}

void
cifs_small_buf_release(void *buf_to_free)
{

	if (buf_to_free == NULL) {
207
		cifs_dbg(FYI, "Null buffer passed to cifs_small_buf_release\n");
L
Linus Torvalds 已提交
208 209
		return;
	}
S
Steve French 已提交
210
	mempool_free(buf_to_free, cifs_sm_req_poolp);
L
Linus Torvalds 已提交
211 212 213 214 215

	atomic_dec(&smBufAllocCount);
	return;
}

216 217 218 219 220 221 222 223 224
void
free_rsp_buf(int resp_buftype, void *rsp)
{
	if (resp_buftype == CIFS_SMALL_BUFFER)
		cifs_small_buf_release(rsp);
	else if (resp_buftype == CIFS_LARGE_BUFFER)
		cifs_buf_release(rsp);
}

225 226
/* NB: MID can not be set if treeCon not passed in, in that
   case it is responsbility of caller to set the mid */
L
Linus Torvalds 已提交
227 228
void
header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
229
		const struct cifs_tcon *treeCon, int word_count
L
Linus Torvalds 已提交
230 231 232 233
		/* length of fixed section (word count) in two byte units  */)
{
	char *temp = (char *) buffer;

S
Steve French 已提交
234
	memset(temp, 0, 256); /* bigger than MAX_CIFS_HDR_SIZE */
L
Linus Torvalds 已提交
235

236
	buffer->smb_buf_length = cpu_to_be32(
S
Steve French 已提交
237
	    (2 * word_count) + sizeof(struct smb_hdr) -
L
Linus Torvalds 已提交
238
	    4 /*  RFC 1001 length field does not count */  +
239
	    2 /* for bcc field itself */) ;
L
Linus Torvalds 已提交
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254

	buffer->Protocol[0] = 0xFF;
	buffer->Protocol[1] = 'S';
	buffer->Protocol[2] = 'M';
	buffer->Protocol[3] = 'B';
	buffer->Command = smb_command;
	buffer->Flags = 0x00;	/* case sensitive */
	buffer->Flags2 = SMBFLG2_KNOWS_LONG_NAMES;
	buffer->Pid = cpu_to_le16((__u16)current->tgid);
	buffer->PidHigh = cpu_to_le16((__u16)(current->tgid >> 16));
	if (treeCon) {
		buffer->Tid = treeCon->tid;
		if (treeCon->ses) {
			if (treeCon->ses->capabilities & CAP_UNICODE)
				buffer->Flags2 |= SMBFLG2_UNICODE;
S
Steve French 已提交
255
			if (treeCon->ses->capabilities & CAP_STATUS32)
L
Linus Torvalds 已提交
256
				buffer->Flags2 |= SMBFLG2_ERR_STATUS;
S
Steve French 已提交
257

258 259
			/* Uid is not converted */
			buffer->Uid = treeCon->ses->Suid;
260
			buffer->Mid = get_next_mid(treeCon->ses->server);
L
Linus Torvalds 已提交
261 262 263
		}
		if (treeCon->Flags & SMB_SHARE_IS_IN_DFS)
			buffer->Flags2 |= SMBFLG2_DFS;
264 265
		if (treeCon->nocase)
			buffer->Flags  |= SMBFLG_CASELESS;
S
Steve French 已提交
266
		if ((treeCon->ses) && (treeCon->ses->server))
267
			if (treeCon->ses->server->sign)
L
Linus Torvalds 已提交
268 269 270 271 272 273 274 275
				buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
	}

/*  endian conversion of flags is now done just before sending */
	buffer->WordCount = (char) word_count;
	return;
}

276
static int
277
check_smb_hdr(struct smb_hdr *smb)
L
Linus Torvalds 已提交
278
{
279 280
	/* does it have the right SMB "signature" ? */
	if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff)) {
281 282
		cifs_dbg(VFS, "Bad protocol string signature header 0x%x\n",
			 *(unsigned int *)smb->Protocol);
283 284 285 286 287 288 289 290 291 292 293
		return 1;
	}

	/* if it's a response then accept */
	if (smb->Flags & SMBFLG_RESPONSE)
		return 0;

	/* only one valid case where server sends us request */
	if (smb->Command == SMB_COM_LOCKING_ANDX)
		return 0;

294 295
	cifs_dbg(VFS, "Server sent request, not response. mid=%u\n",
		 get_mid(smb));
L
Linus Torvalds 已提交
296 297 298 299
	return 1;
}

int
300
checkSMB(char *buf, unsigned int total_read, struct TCP_Server_Info *server)
L
Linus Torvalds 已提交
301
{
302
	struct smb_hdr *smb = (struct smb_hdr *)buf;
J
Jeff Layton 已提交
303
	__u32 rfclen = be32_to_cpu(smb->smb_buf_length);
304
	__u32 clc_len;  /* calculated length */
305 306
	cifs_dbg(FYI, "checkSMB Length: 0x%x, smb_buf_length: 0x%x\n",
		 total_read, rfclen);
307

J
Jeff Layton 已提交
308 309 310
	/* is this frame too small to even get to a BCC? */
	if (total_read < 2 + sizeof(struct smb_hdr)) {
		if ((total_read >= sizeof(struct smb_hdr) - 1)
L
Linus Torvalds 已提交
311
			    && (smb->Status.CifsError != 0)) {
J
Jeff Layton 已提交
312
			/* it's an error return */
313 314 315
			smb->WordCount = 0;
			/* some error cases do not return wct and bcc */
			return 0;
J
Jeff Layton 已提交
316
		} else if ((total_read == sizeof(struct smb_hdr) + 1) &&
317
				(smb->WordCount == 0)) {
S
Steve French 已提交
318
			char *tmp = (char *)smb;
319 320 321 322 323 324 325 326 327 328 329
			/* Need to work around a bug in two servers here */
			/* First, check if the part of bcc they sent was zero */
			if (tmp[sizeof(struct smb_hdr)] == 0) {
				/* some servers return only half of bcc
				 * on simple responses (wct, bcc both zero)
				 * in particular have seen this on
				 * ulogoffX and FindClose. This leaves
				 * one byte of bcc potentially unitialized
				 */
				/* zero rest of bcc */
				tmp[sizeof(struct smb_hdr)+1] = 0;
330
				return 0;
L
Linus Torvalds 已提交
331
			}
332
			cifs_dbg(VFS, "rcvd invalid byte count (bcc)\n");
333
		} else {
334
			cifs_dbg(VFS, "Length less than smb header size\n");
L
Linus Torvalds 已提交
335
		}
J
Jeff Layton 已提交
336
		return -EIO;
L
Linus Torvalds 已提交
337 338
	}

J
Jeff Layton 已提交
339
	/* otherwise, there is enough to get to the BCC */
340
	if (check_smb_hdr(smb))
J
Jeff Layton 已提交
341
		return -EIO;
342
	clc_len = smbCalcSize(smb);
343

J
Jeff Layton 已提交
344
	if (4 + rfclen != total_read) {
345 346
		cifs_dbg(VFS, "Length read does not match RFC1001 length %d\n",
			 rfclen);
J
Jeff Layton 已提交
347
		return -EIO;
348 349
	}

J
Jeff Layton 已提交
350
	if (4 + rfclen != clc_len) {
351
		__u16 mid = get_mid(smb);
352
		/* check if bcc wrapped around for large read responses */
J
Jeff Layton 已提交
353
		if ((rfclen > 64 * 1024) && (rfclen > clc_len)) {
354
			/* check if lengths match mod 64K */
J
Jeff Layton 已提交
355
			if (((4 + rfclen) & 0xFFFF) == (clc_len & 0xFFFF))
S
Steve French 已提交
356
				return 0; /* bcc wrapped */
357
		}
358
		cifs_dbg(FYI, "Calculated size %u vs length %u mismatch for mid=%u\n",
359
			 clc_len, 4 + rfclen, mid);
360

J
Jeff Layton 已提交
361
		if (4 + rfclen < clc_len) {
362
			cifs_dbg(VFS, "RFC1001 size %u smaller than SMB for mid=%u\n",
363
				 rfclen, mid);
J
Jeff Layton 已提交
364 365
			return -EIO;
		} else if (rfclen > clc_len + 512) {
366 367 368 369 370 371 372 373 374
			/*
			 * Some servers (Windows XP in particular) send more
			 * data than the lengths in the SMB packet would
			 * indicate on certain calls (byte range locks and
			 * trans2 find first calls in particular). While the
			 * client can handle such a frame by ignoring the
			 * trailing data, we choose limit the amount of extra
			 * data to 512 bytes.
			 */
375
			cifs_dbg(VFS, "RFC1001 size %u more than 512 bytes larger than SMB for mid=%u\n",
376
				 rfclen, mid);
J
Jeff Layton 已提交
377
			return -EIO;
378
		}
L
Linus Torvalds 已提交
379
	}
380
	return 0;
L
Linus Torvalds 已提交
381
}
382 383

bool
384
is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
S
Steve French 已提交
385
{
386
	struct smb_hdr *buf = (struct smb_hdr *)buffer;
S
Steve French 已提交
387
	struct smb_com_lock_req *pSMB = (struct smb_com_lock_req *)buf;
388
	struct list_head *tmp, *tmp1, *tmp2;
389 390
	struct cifs_ses *ses;
	struct cifs_tcon *tcon;
391
	struct cifsInodeInfo *pCifsInode;
L
Linus Torvalds 已提交
392 393
	struct cifsFileInfo *netfile;

394
	cifs_dbg(FYI, "Checking for oplock break or dnotify response\n");
S
Steve French 已提交
395
	if ((pSMB->hdr.Command == SMB_COM_NT_TRANSACT) &&
L
Linus Torvalds 已提交
396
	   (pSMB->hdr.Flags & SMBFLG_RESPONSE)) {
S
Steve French 已提交
397
		struct smb_com_transaction_change_notify_rsp *pSMBr =
L
Linus Torvalds 已提交
398
			(struct smb_com_transaction_change_notify_rsp *)buf;
S
Steve French 已提交
399
		struct file_notify_information *pnotify;
L
Linus Torvalds 已提交
400
		__u32 data_offset = 0;
401
		if (get_bcc(buf) > sizeof(struct file_notify_information)) {
L
Linus Torvalds 已提交
402 403
			data_offset = le32_to_cpu(pSMBr->DataOffset);

404 405
			pnotify = (struct file_notify_information *)
				((char *)&pSMBr->hdr.Protocol + data_offset);
406
			cifs_dbg(FYI, "dnotify on %s Action: 0x%x\n",
407
				 pnotify->FileName, pnotify->Action);
S
Steve French 已提交
408
			/*   cifs_dump_mem("Rcvd notify Data: ",buf,
409
				sizeof(struct smb_hdr)+60); */
410
			return true;
L
Linus Torvalds 已提交
411
		}
S
Steve French 已提交
412
		if (pSMBr->hdr.Status.CifsError) {
413
			cifs_dbg(FYI, "notify err 0x%x\n",
414
				 pSMBr->hdr.Status.CifsError);
415
			return true;
L
Linus Torvalds 已提交
416
		}
417
		return false;
S
Steve French 已提交
418
	}
S
Steve French 已提交
419
	if (pSMB->hdr.Command != SMB_COM_LOCKING_ANDX)
420
		return false;
S
Steve French 已提交
421
	if (pSMB->hdr.Flags & SMBFLG_RESPONSE) {
L
Linus Torvalds 已提交
422 423 424 425
		/* no sense logging error on invalid handle on oplock
		   break - harmless race between close request and oplock
		   break response is expected from time to time writing out
		   large dirty files cached on the client */
S
Steve French 已提交
426 427
		if ((NT_STATUS_INVALID_HANDLE) ==
		   le32_to_cpu(pSMB->hdr.Status.CifsError)) {
428
			cifs_dbg(FYI, "invalid handle on oplock break\n");
429
			return true;
S
Steve French 已提交
430
		} else if (ERRbadfid ==
L
Linus Torvalds 已提交
431
		   le16_to_cpu(pSMB->hdr.Status.DosError.Error)) {
432
			return true;
L
Linus Torvalds 已提交
433
		} else {
434
			return false; /* on valid oplock brk we get "request" */
L
Linus Torvalds 已提交
435 436
		}
	}
S
Steve French 已提交
437
	if (pSMB->hdr.WordCount != 8)
438
		return false;
L
Linus Torvalds 已提交
439

440
	cifs_dbg(FYI, "oplock type 0x%x level 0x%x\n",
441
		 pSMB->LockType, pSMB->OplockLevel);
S
Steve French 已提交
442
	if (!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE))
443
		return false;
L
Linus Torvalds 已提交
444 445

	/* look up tcon based on tid & uid */
446
	spin_lock(&cifs_tcp_ses_lock);
447
	list_for_each(tmp, &srv->smb_ses_list) {
448
		ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
449
		list_for_each(tmp1, &ses->tcon_list) {
450
			tcon = list_entry(tmp1, struct cifs_tcon, tcon_list);
451 452 453
			if (tcon->tid != buf->Tid)
				continue;

454
			cifs_stats_inc(&tcon->stats.cifs_stats.num_oplock_brks);
455
			spin_lock(&tcon->open_file_lock);
456 457
			list_for_each(tmp2, &tcon->openFileList) {
				netfile = list_entry(tmp2, struct cifsFileInfo,
458
						     tlist);
459
				if (pSMB->Fid != netfile->fid.netfid)
460 461
					continue;

462
				cifs_dbg(FYI, "file id match, oplock break\n");
463
				pCifsInode = CIFS_I(d_inode(netfile->dentry));
464

465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480
				set_bit(CIFS_INODE_PENDING_OPLOCK_BREAK,
					&pCifsInode->flags);

				/*
				 * Set flag if the server downgrades the oplock
				 * to L2 else clear.
				 */
				if (pSMB->OplockLevel)
					set_bit(
					   CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2,
					   &pCifsInode->flags);
				else
					clear_bit(
					   CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2,
					   &pCifsInode->flags);

R
Rabin Vincent 已提交
481
				queue_work(cifsoplockd_wq,
482
					   &netfile->oplock_break);
483 484
				netfile->oplock_break_cancelled = false;

485
				spin_unlock(&tcon->open_file_lock);
486
				spin_unlock(&cifs_tcp_ses_lock);
487
				return true;
L
Linus Torvalds 已提交
488
			}
489
			spin_unlock(&tcon->open_file_lock);
490
			spin_unlock(&cifs_tcp_ses_lock);
491
			cifs_dbg(FYI, "No matching file for oplock break\n");
492
			return true;
L
Linus Torvalds 已提交
493 494
		}
	}
495
	spin_unlock(&cifs_tcp_ses_lock);
496
	cifs_dbg(FYI, "Can not process oplock break for non-existent connection\n");
497
	return true;
L
Linus Torvalds 已提交
498 499 500
}

void
501
dump_smb(void *buf, int smb_buf_length)
L
Linus Torvalds 已提交
502 503 504 505
{
	if (traceSMB == 0)
		return;

506 507
	print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_NONE, 8, 2, buf,
		       smb_buf_length, true);
L
Linus Torvalds 已提交
508
}
509

510 511 512 513
void
cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb)
{
	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
514
		cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
515 516
		cifs_dbg(VFS, "Autodisabling the use of server inode numbers on %s. This server doesn't seem to support them properly. Hardlinks will not be recognized on this mount. Consider mounting with the \"noserverino\" option to silence this message.\n",
			 cifs_sb_master_tcon(cifs_sb)->treeName);
517 518
	}
}
P
Pavel Shilovsky 已提交
519

520
void cifs_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock)
P
Pavel Shilovsky 已提交
521
{
522
	oplock &= 0xF;
P
Pavel Shilovsky 已提交
523

524
	if (oplock == OPLOCK_EXCLUSIVE) {
525
		cinode->oplock = CIFS_CACHE_WRITE_FLG | CIFS_CACHE_READ_FLG;
526 527
		cifs_dbg(FYI, "Exclusive Oplock granted on inode %p\n",
			 &cinode->vfs_inode);
528
	} else if (oplock == OPLOCK_READ) {
529
		cinode->oplock = CIFS_CACHE_READ_FLG;
530 531
		cifs_dbg(FYI, "Level II Oplock granted on inode %p\n",
			 &cinode->vfs_inode);
532 533
	} else
		cinode->oplock = 0;
P
Pavel Shilovsky 已提交
534
}
535

536 537 538 539 540 541 542 543 544 545
/*
 * We wait for oplock breaks to be processed before we attempt to perform
 * writes.
 */
int cifs_get_writer(struct cifsInodeInfo *cinode)
{
	int rc;

start:
	rc = wait_on_bit(&cinode->flags, CIFS_INODE_PENDING_OPLOCK_BREAK,
546
			 TASK_KILLABLE);
547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584
	if (rc)
		return rc;

	spin_lock(&cinode->writers_lock);
	if (!cinode->writers)
		set_bit(CIFS_INODE_PENDING_WRITERS, &cinode->flags);
	cinode->writers++;
	/* Check to see if we have started servicing an oplock break */
	if (test_bit(CIFS_INODE_PENDING_OPLOCK_BREAK, &cinode->flags)) {
		cinode->writers--;
		if (cinode->writers == 0) {
			clear_bit(CIFS_INODE_PENDING_WRITERS, &cinode->flags);
			wake_up_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS);
		}
		spin_unlock(&cinode->writers_lock);
		goto start;
	}
	spin_unlock(&cinode->writers_lock);
	return 0;
}

void cifs_put_writer(struct cifsInodeInfo *cinode)
{
	spin_lock(&cinode->writers_lock);
	cinode->writers--;
	if (cinode->writers == 0) {
		clear_bit(CIFS_INODE_PENDING_WRITERS, &cinode->flags);
		wake_up_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS);
	}
	spin_unlock(&cinode->writers_lock);
}

void cifs_done_oplock_break(struct cifsInodeInfo *cinode)
{
	clear_bit(CIFS_INODE_PENDING_OPLOCK_BREAK, &cinode->flags);
	wake_up_bit(&cinode->flags, CIFS_INODE_PENDING_OPLOCK_BREAK);
}

585 586 587 588
bool
backup_cred(struct cifs_sb_info *cifs_sb)
{
	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPUID) {
589
		if (uid_eq(cifs_sb->mnt_backupuid, current_fsuid()))
590 591 592 593 594 595 596 597 598
			return true;
	}
	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPGID) {
		if (in_group_p(cifs_sb->mnt_backupgid))
			return true;
	}

	return false;
}
599 600 601 602

void
cifs_del_pending_open(struct cifs_pending_open *open)
{
603
	spin_lock(&tlink_tcon(open->tlink)->open_file_lock);
604
	list_del(&open->olist);
605
	spin_unlock(&tlink_tcon(open->tlink)->open_file_lock);
606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622
}

void
cifs_add_pending_open_locked(struct cifs_fid *fid, struct tcon_link *tlink,
			     struct cifs_pending_open *open)
{
	memcpy(open->lease_key, fid->lease_key, SMB2_LEASE_KEY_SIZE);
	open->oplock = CIFS_OPLOCK_NO_CHANGE;
	open->tlink = tlink;
	fid->pending_open = open;
	list_add_tail(&open->olist, &tlink_tcon(tlink)->pending_opens);
}

void
cifs_add_pending_open(struct cifs_fid *fid, struct tcon_link *tlink,
		      struct cifs_pending_open *open)
{
623
	spin_lock(&tlink_tcon(tlink)->open_file_lock);
624
	cifs_add_pending_open_locked(fid, tlink, open);
625
	spin_unlock(&tlink_tcon(open->tlink)->open_file_lock);
626
}
627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731

/* parses DFS refferal V3 structure
 * caller is responsible for freeing target_nodes
 * returns:
 * - on success - 0
 * - on failure - errno
 */
int
parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size,
		    unsigned int *num_of_nodes,
		    struct dfs_info3_param **target_nodes,
		    const struct nls_table *nls_codepage, int remap,
		    const char *searchName, bool is_unicode)
{
	int i, rc = 0;
	char *data_end;
	struct dfs_referral_level_3 *ref;

	*num_of_nodes = le16_to_cpu(rsp->NumberOfReferrals);

	if (*num_of_nodes < 1) {
		cifs_dbg(VFS, "num_referrals: must be at least > 0, but we get num_referrals = %d\n",
			 *num_of_nodes);
		rc = -EINVAL;
		goto parse_DFS_referrals_exit;
	}

	ref = (struct dfs_referral_level_3 *) &(rsp->referrals);
	if (ref->VersionNumber != cpu_to_le16(3)) {
		cifs_dbg(VFS, "Referrals of V%d version are not supported, should be V3\n",
			 le16_to_cpu(ref->VersionNumber));
		rc = -EINVAL;
		goto parse_DFS_referrals_exit;
	}

	/* get the upper boundary of the resp buffer */
	data_end = (char *)rsp + rsp_size;

	cifs_dbg(FYI, "num_referrals: %d dfs flags: 0x%x ...\n",
		 *num_of_nodes, le32_to_cpu(rsp->DFSFlags));

	*target_nodes = kcalloc(*num_of_nodes, sizeof(struct dfs_info3_param),
				GFP_KERNEL);
	if (*target_nodes == NULL) {
		rc = -ENOMEM;
		goto parse_DFS_referrals_exit;
	}

	/* collect necessary data from referrals */
	for (i = 0; i < *num_of_nodes; i++) {
		char *temp;
		int max_len;
		struct dfs_info3_param *node = (*target_nodes)+i;

		node->flags = le32_to_cpu(rsp->DFSFlags);
		if (is_unicode) {
			__le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
						GFP_KERNEL);
			if (tmp == NULL) {
				rc = -ENOMEM;
				goto parse_DFS_referrals_exit;
			}
			cifsConvertToUTF16((__le16 *) tmp, searchName,
					   PATH_MAX, nls_codepage, remap);
			node->path_consumed = cifs_utf16_bytes(tmp,
					le16_to_cpu(rsp->PathConsumed),
					nls_codepage);
			kfree(tmp);
		} else
			node->path_consumed = le16_to_cpu(rsp->PathConsumed);

		node->server_type = le16_to_cpu(ref->ServerType);
		node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);

		/* copy DfsPath */
		temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
		max_len = data_end - temp;
		node->path_name = cifs_strndup_from_utf16(temp, max_len,
						is_unicode, nls_codepage);
		if (!node->path_name) {
			rc = -ENOMEM;
			goto parse_DFS_referrals_exit;
		}

		/* copy link target UNC */
		temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
		max_len = data_end - temp;
		node->node_name = cifs_strndup_from_utf16(temp, max_len,
						is_unicode, nls_codepage);
		if (!node->node_name) {
			rc = -ENOMEM;
			goto parse_DFS_referrals_exit;
		}

		ref++;
	}

parse_DFS_referrals_exit:
	if (rc) {
		free_dfs_info_array(*target_nodes, *num_of_nodes);
		*target_nodes = NULL;
		*num_of_nodes = 0;
	}
	return rc;
}
732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799

struct cifs_aio_ctx *
cifs_aio_ctx_alloc(void)
{
	struct cifs_aio_ctx *ctx;

	ctx = kzalloc(sizeof(struct cifs_aio_ctx), GFP_KERNEL);
	if (!ctx)
		return NULL;

	INIT_LIST_HEAD(&ctx->list);
	mutex_init(&ctx->aio_mutex);
	init_completion(&ctx->done);
	kref_init(&ctx->refcount);
	return ctx;
}

void
cifs_aio_ctx_release(struct kref *refcount)
{
	struct cifs_aio_ctx *ctx = container_of(refcount,
					struct cifs_aio_ctx, refcount);

	cifsFileInfo_put(ctx->cfile);
	kvfree(ctx->bv);
	kfree(ctx);
}

#define CIFS_AIO_KMALLOC_LIMIT (1024 * 1024)

int
setup_aio_ctx_iter(struct cifs_aio_ctx *ctx, struct iov_iter *iter, int rw)
{
	ssize_t rc;
	unsigned int cur_npages;
	unsigned int npages = 0;
	unsigned int i;
	size_t len;
	size_t count = iov_iter_count(iter);
	unsigned int saved_len;
	size_t start;
	unsigned int max_pages = iov_iter_npages(iter, INT_MAX);
	struct page **pages = NULL;
	struct bio_vec *bv = NULL;

	if (iter->type & ITER_KVEC) {
		memcpy(&ctx->iter, iter, sizeof(struct iov_iter));
		ctx->len = count;
		iov_iter_advance(iter, count);
		return 0;
	}

	if (max_pages * sizeof(struct bio_vec) <= CIFS_AIO_KMALLOC_LIMIT)
		bv = kmalloc_array(max_pages, sizeof(struct bio_vec),
				   GFP_KERNEL);

	if (!bv) {
		bv = vmalloc(max_pages * sizeof(struct bio_vec));
		if (!bv)
			return -ENOMEM;
	}

	if (max_pages * sizeof(struct page *) <= CIFS_AIO_KMALLOC_LIMIT)
		pages = kmalloc_array(max_pages, sizeof(struct page *),
				      GFP_KERNEL);

	if (!pages) {
		pages = vmalloc(max_pages * sizeof(struct page *));
800
		if (!pages) {
801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850
			kvfree(bv);
			return -ENOMEM;
		}
	}

	saved_len = count;

	while (count && npages < max_pages) {
		rc = iov_iter_get_pages(iter, pages, count, max_pages, &start);
		if (rc < 0) {
			cifs_dbg(VFS, "couldn't get user pages (rc=%zd)\n", rc);
			break;
		}

		if (rc > count) {
			cifs_dbg(VFS, "get pages rc=%zd more than %zu\n", rc,
				 count);
			break;
		}

		iov_iter_advance(iter, rc);
		count -= rc;
		rc += start;
		cur_npages = DIV_ROUND_UP(rc, PAGE_SIZE);

		if (npages + cur_npages > max_pages) {
			cifs_dbg(VFS, "out of vec array capacity (%u vs %u)\n",
				 npages + cur_npages, max_pages);
			break;
		}

		for (i = 0; i < cur_npages; i++) {
			len = rc > PAGE_SIZE ? PAGE_SIZE : rc;
			bv[npages + i].bv_page = pages[i];
			bv[npages + i].bv_offset = start;
			bv[npages + i].bv_len = len - start;
			rc -= len;
			start = 0;
		}

		npages += cur_npages;
	}

	kvfree(pages);
	ctx->bv = bv;
	ctx->len = saved_len - count;
	ctx->npages = npages;
	iov_iter_bvec(&ctx->iter, ITER_BVEC | rw, ctx->bv, npages, ctx->len);
	return 0;
}
851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904

/**
 * cifs_alloc_hash - allocate hash and hash context together
 *
 * The caller has to make sure @sdesc is initialized to either NULL or
 * a valid context. Both can be freed via cifs_free_hash().
 */
int
cifs_alloc_hash(const char *name,
		struct crypto_shash **shash, struct sdesc **sdesc)
{
	int rc = 0;
	size_t size;

	if (*sdesc != NULL)
		return 0;

	*shash = crypto_alloc_shash(name, 0, 0);
	if (IS_ERR(*shash)) {
		cifs_dbg(VFS, "could not allocate crypto %s\n", name);
		rc = PTR_ERR(*shash);
		*shash = NULL;
		*sdesc = NULL;
		return rc;
	}

	size = sizeof(struct shash_desc) + crypto_shash_descsize(*shash);
	*sdesc = kmalloc(size, GFP_KERNEL);
	if (*sdesc == NULL) {
		cifs_dbg(VFS, "no memory left to allocate crypto %s\n", name);
		crypto_free_shash(*shash);
		*shash = NULL;
		return -ENOMEM;
	}

	(*sdesc)->shash.tfm = *shash;
	(*sdesc)->shash.flags = 0x0;
	return 0;
}

/**
 * cifs_free_hash - free hash and hash context together
 *
 * Freeing a NULL hash or context is safe.
 */
void
cifs_free_hash(struct crypto_shash **shash, struct sdesc **sdesc)
{
	kfree(*sdesc);
	*sdesc = NULL;
	if (*shash)
		crypto_free_shash(*shash);
	*shash = NULL;
}