brintos

brintos / linux-shallow public Read only

0
0
Text · 48.1 KiB · 4142c7a Raw
1871 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 *   Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>4 *   Copyright (C) 2018 Samsung Electronics Co., Ltd.5 */6 7#include <linux/moduleparam.h>8 9#include "glob.h"10#include "oplock.h"11 12#include "smb_common.h"13#include "../common/smb2status.h"14#include "connection.h"15#include "mgmt/user_session.h"16#include "mgmt/share_config.h"17#include "mgmt/tree_connect.h"18 19static LIST_HEAD(lease_table_list);20static DEFINE_RWLOCK(lease_list_lock);21 22/**23 * alloc_opinfo() - allocate a new opinfo object for oplock info24 * @work:	smb work25 * @id:		fid of open file26 * @Tid:	tree id of connection27 *28 * Return:      allocated opinfo object on success, otherwise NULL29 */30static struct oplock_info *alloc_opinfo(struct ksmbd_work *work,31					u64 id, __u16 Tid)32{33	struct ksmbd_conn *conn = work->conn;34	struct ksmbd_session *sess = work->sess;35	struct oplock_info *opinfo;36 37	opinfo = kzalloc(sizeof(struct oplock_info), GFP_KERNEL);38	if (!opinfo)39		return NULL;40 41	opinfo->sess = sess;42	opinfo->conn = conn;43	opinfo->level = SMB2_OPLOCK_LEVEL_NONE;44	opinfo->op_state = OPLOCK_STATE_NONE;45	opinfo->pending_break = 0;46	opinfo->fid = id;47	opinfo->Tid = Tid;48	INIT_LIST_HEAD(&opinfo->op_entry);49	INIT_LIST_HEAD(&opinfo->interim_list);50	init_waitqueue_head(&opinfo->oplock_q);51	init_waitqueue_head(&opinfo->oplock_brk);52	atomic_set(&opinfo->refcount, 1);53	atomic_set(&opinfo->breaking_cnt, 0);54	atomic_inc(&opinfo->conn->refcnt);55 56	return opinfo;57}58 59static void lease_add_list(struct oplock_info *opinfo)60{61	struct lease_table *lb = opinfo->o_lease->l_lb;62 63	spin_lock(&lb->lb_lock);64	list_add_rcu(&opinfo->lease_entry, &lb->lease_list);65	spin_unlock(&lb->lb_lock);66}67 68static void lease_del_list(struct oplock_info *opinfo)69{70	struct lease_table *lb = opinfo->o_lease->l_lb;71 72	if (!lb)73		return;74 75	spin_lock(&lb->lb_lock);76	if (list_empty(&opinfo->lease_entry)) {77		spin_unlock(&lb->lb_lock);78		return;79	}80 81	list_del_init(&opinfo->lease_entry);82	opinfo->o_lease->l_lb = NULL;83	spin_unlock(&lb->lb_lock);84}85 86static void lb_add(struct lease_table *lb)87{88	write_lock(&lease_list_lock);89	list_add(&lb->l_entry, &lease_table_list);90	write_unlock(&lease_list_lock);91}92 93static int alloc_lease(struct oplock_info *opinfo, struct lease_ctx_info *lctx)94{95	struct lease *lease;96 97	lease = kmalloc(sizeof(struct lease), GFP_KERNEL);98	if (!lease)99		return -ENOMEM;100 101	memcpy(lease->lease_key, lctx->lease_key, SMB2_LEASE_KEY_SIZE);102	lease->state = lctx->req_state;103	lease->new_state = 0;104	lease->flags = lctx->flags;105	lease->duration = lctx->duration;106	lease->is_dir = lctx->is_dir;107	memcpy(lease->parent_lease_key, lctx->parent_lease_key, SMB2_LEASE_KEY_SIZE);108	lease->version = lctx->version;109	lease->epoch = le16_to_cpu(lctx->epoch) + 1;110	INIT_LIST_HEAD(&opinfo->lease_entry);111	opinfo->o_lease = lease;112 113	return 0;114}115 116static void free_lease(struct oplock_info *opinfo)117{118	struct lease *lease;119 120	lease = opinfo->o_lease;121	kfree(lease);122}123 124static void free_opinfo(struct oplock_info *opinfo)125{126	if (opinfo->is_lease)127		free_lease(opinfo);128	if (opinfo->conn && atomic_dec_and_test(&opinfo->conn->refcnt))129		kfree(opinfo->conn);130	kfree(opinfo);131}132 133static inline void opinfo_free_rcu(struct rcu_head *rcu_head)134{135	struct oplock_info *opinfo;136 137	opinfo = container_of(rcu_head, struct oplock_info, rcu_head);138	free_opinfo(opinfo);139}140 141struct oplock_info *opinfo_get(struct ksmbd_file *fp)142{143	struct oplock_info *opinfo;144 145	rcu_read_lock();146	opinfo = rcu_dereference(fp->f_opinfo);147	if (opinfo && !atomic_inc_not_zero(&opinfo->refcount))148		opinfo = NULL;149	rcu_read_unlock();150 151	return opinfo;152}153 154static struct oplock_info *opinfo_get_list(struct ksmbd_inode *ci)155{156	struct oplock_info *opinfo;157 158	if (list_empty(&ci->m_op_list))159		return NULL;160 161	rcu_read_lock();162	opinfo = list_first_or_null_rcu(&ci->m_op_list, struct oplock_info,163					op_entry);164	if (opinfo) {165		if (opinfo->conn == NULL ||166		    !atomic_inc_not_zero(&opinfo->refcount))167			opinfo = NULL;168		else {169			if (ksmbd_conn_releasing(opinfo->conn)) {170				atomic_dec(&opinfo->refcount);171				opinfo = NULL;172			}173		}174	}175 176	rcu_read_unlock();177 178	return opinfo;179}180 181void opinfo_put(struct oplock_info *opinfo)182{183	if (!opinfo)184		return;185 186	if (!atomic_dec_and_test(&opinfo->refcount))187		return;188 189	call_rcu(&opinfo->rcu_head, opinfo_free_rcu);190}191 192static void opinfo_add(struct oplock_info *opinfo)193{194	struct ksmbd_inode *ci = opinfo->o_fp->f_ci;195 196	down_write(&ci->m_lock);197	list_add_rcu(&opinfo->op_entry, &ci->m_op_list);198	up_write(&ci->m_lock);199}200 201static void opinfo_del(struct oplock_info *opinfo)202{203	struct ksmbd_inode *ci = opinfo->o_fp->f_ci;204 205	if (opinfo->is_lease) {206		write_lock(&lease_list_lock);207		lease_del_list(opinfo);208		write_unlock(&lease_list_lock);209	}210	down_write(&ci->m_lock);211	list_del_rcu(&opinfo->op_entry);212	up_write(&ci->m_lock);213}214 215static unsigned long opinfo_count(struct ksmbd_file *fp)216{217	if (ksmbd_stream_fd(fp))218		return atomic_read(&fp->f_ci->sop_count);219	else220		return atomic_read(&fp->f_ci->op_count);221}222 223static void opinfo_count_inc(struct ksmbd_file *fp)224{225	if (ksmbd_stream_fd(fp))226		return atomic_inc(&fp->f_ci->sop_count);227	else228		return atomic_inc(&fp->f_ci->op_count);229}230 231static void opinfo_count_dec(struct ksmbd_file *fp)232{233	if (ksmbd_stream_fd(fp))234		return atomic_dec(&fp->f_ci->sop_count);235	else236		return atomic_dec(&fp->f_ci->op_count);237}238 239/**240 * opinfo_write_to_read() - convert a write oplock to read oplock241 * @opinfo:		current oplock info242 *243 * Return:      0 on success, otherwise -EINVAL244 */245int opinfo_write_to_read(struct oplock_info *opinfo)246{247	struct lease *lease = opinfo->o_lease;248 249	if (!(opinfo->level == SMB2_OPLOCK_LEVEL_BATCH ||250	      opinfo->level == SMB2_OPLOCK_LEVEL_EXCLUSIVE)) {251		pr_err("bad oplock(0x%x)\n", opinfo->level);252		if (opinfo->is_lease)253			pr_err("lease state(0x%x)\n", lease->state);254		return -EINVAL;255	}256	opinfo->level = SMB2_OPLOCK_LEVEL_II;257 258	if (opinfo->is_lease)259		lease->state = lease->new_state;260	return 0;261}262 263/**264 * opinfo_read_handle_to_read() - convert a read/handle oplock to read oplock265 * @opinfo:		current oplock info266 *267 * Return:      0 on success, otherwise -EINVAL268 */269int opinfo_read_handle_to_read(struct oplock_info *opinfo)270{271	struct lease *lease = opinfo->o_lease;272 273	lease->state = lease->new_state;274	opinfo->level = SMB2_OPLOCK_LEVEL_II;275	return 0;276}277 278/**279 * opinfo_write_to_none() - convert a write oplock to none280 * @opinfo:	current oplock info281 *282 * Return:      0 on success, otherwise -EINVAL283 */284int opinfo_write_to_none(struct oplock_info *opinfo)285{286	struct lease *lease = opinfo->o_lease;287 288	if (!(opinfo->level == SMB2_OPLOCK_LEVEL_BATCH ||289	      opinfo->level == SMB2_OPLOCK_LEVEL_EXCLUSIVE)) {290		pr_err("bad oplock(0x%x)\n", opinfo->level);291		if (opinfo->is_lease)292			pr_err("lease state(0x%x)\n", lease->state);293		return -EINVAL;294	}295	opinfo->level = SMB2_OPLOCK_LEVEL_NONE;296	if (opinfo->is_lease)297		lease->state = lease->new_state;298	return 0;299}300 301/**302 * opinfo_read_to_none() - convert a write read to none303 * @opinfo:	current oplock info304 *305 * Return:      0 on success, otherwise -EINVAL306 */307int opinfo_read_to_none(struct oplock_info *opinfo)308{309	struct lease *lease = opinfo->o_lease;310 311	if (opinfo->level != SMB2_OPLOCK_LEVEL_II) {312		pr_err("bad oplock(0x%x)\n", opinfo->level);313		if (opinfo->is_lease)314			pr_err("lease state(0x%x)\n", lease->state);315		return -EINVAL;316	}317	opinfo->level = SMB2_OPLOCK_LEVEL_NONE;318	if (opinfo->is_lease)319		lease->state = lease->new_state;320	return 0;321}322 323/**324 * lease_read_to_write() - upgrade lease state from read to write325 * @opinfo:	current lease info326 *327 * Return:      0 on success, otherwise -EINVAL328 */329int lease_read_to_write(struct oplock_info *opinfo)330{331	struct lease *lease = opinfo->o_lease;332 333	if (!(lease->state & SMB2_LEASE_READ_CACHING_LE)) {334		ksmbd_debug(OPLOCK, "bad lease state(0x%x)\n", lease->state);335		return -EINVAL;336	}337 338	lease->new_state = SMB2_LEASE_NONE_LE;339	lease->state |= SMB2_LEASE_WRITE_CACHING_LE;340	if (lease->state & SMB2_LEASE_HANDLE_CACHING_LE)341		opinfo->level = SMB2_OPLOCK_LEVEL_BATCH;342	else343		opinfo->level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;344	return 0;345}346 347/**348 * lease_none_upgrade() - upgrade lease state from none349 * @opinfo:	current lease info350 * @new_state:	new lease state351 *352 * Return:	0 on success, otherwise -EINVAL353 */354static int lease_none_upgrade(struct oplock_info *opinfo, __le32 new_state)355{356	struct lease *lease = opinfo->o_lease;357 358	if (!(lease->state == SMB2_LEASE_NONE_LE)) {359		ksmbd_debug(OPLOCK, "bad lease state(0x%x)\n", lease->state);360		return -EINVAL;361	}362 363	lease->new_state = SMB2_LEASE_NONE_LE;364	lease->state = new_state;365	if (lease->state & SMB2_LEASE_HANDLE_CACHING_LE)366		if (lease->state & SMB2_LEASE_WRITE_CACHING_LE)367			opinfo->level = SMB2_OPLOCK_LEVEL_BATCH;368		else369			opinfo->level = SMB2_OPLOCK_LEVEL_II;370	else if (lease->state & SMB2_LEASE_WRITE_CACHING_LE)371		opinfo->level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;372	else if (lease->state & SMB2_LEASE_READ_CACHING_LE)373		opinfo->level = SMB2_OPLOCK_LEVEL_II;374 375	return 0;376}377 378/**379 * close_id_del_oplock() - release oplock object at file close time380 * @fp:		ksmbd file pointer381 */382void close_id_del_oplock(struct ksmbd_file *fp)383{384	struct oplock_info *opinfo;385 386	if (fp->reserve_lease_break)387		smb_lazy_parent_lease_break_close(fp);388 389	opinfo = opinfo_get(fp);390	if (!opinfo)391		return;392 393	opinfo_del(opinfo);394 395	rcu_assign_pointer(fp->f_opinfo, NULL);396	if (opinfo->op_state == OPLOCK_ACK_WAIT) {397		opinfo->op_state = OPLOCK_CLOSING;398		wake_up_interruptible_all(&opinfo->oplock_q);399		if (opinfo->is_lease) {400			atomic_set(&opinfo->breaking_cnt, 0);401			wake_up_interruptible_all(&opinfo->oplock_brk);402		}403	}404 405	opinfo_count_dec(fp);406	atomic_dec(&opinfo->refcount);407	opinfo_put(opinfo);408}409 410/**411 * grant_write_oplock() - grant exclusive/batch oplock or write lease412 * @opinfo_new:	new oplock info object413 * @req_oplock: request oplock414 * @lctx:	lease context information415 *416 * Return:      0417 */418static void grant_write_oplock(struct oplock_info *opinfo_new, int req_oplock,419			       struct lease_ctx_info *lctx)420{421	struct lease *lease = opinfo_new->o_lease;422 423	if (req_oplock == SMB2_OPLOCK_LEVEL_BATCH)424		opinfo_new->level = SMB2_OPLOCK_LEVEL_BATCH;425	else426		opinfo_new->level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;427 428	if (lctx) {429		lease->state = lctx->req_state;430		memcpy(lease->lease_key, lctx->lease_key, SMB2_LEASE_KEY_SIZE);431	}432}433 434/**435 * grant_read_oplock() - grant level2 oplock or read lease436 * @opinfo_new:	new oplock info object437 * @lctx:	lease context information438 *439 * Return:      0440 */441static void grant_read_oplock(struct oplock_info *opinfo_new,442			      struct lease_ctx_info *lctx)443{444	struct lease *lease = opinfo_new->o_lease;445 446	opinfo_new->level = SMB2_OPLOCK_LEVEL_II;447 448	if (lctx) {449		lease->state = SMB2_LEASE_READ_CACHING_LE;450		if (lctx->req_state & SMB2_LEASE_HANDLE_CACHING_LE)451			lease->state |= SMB2_LEASE_HANDLE_CACHING_LE;452		memcpy(lease->lease_key, lctx->lease_key, SMB2_LEASE_KEY_SIZE);453	}454}455 456/**457 * grant_none_oplock() - grant none oplock or none lease458 * @opinfo_new:	new oplock info object459 * @lctx:	lease context information460 *461 * Return:      0462 */463static void grant_none_oplock(struct oplock_info *opinfo_new,464			      struct lease_ctx_info *lctx)465{466	struct lease *lease = opinfo_new->o_lease;467 468	opinfo_new->level = SMB2_OPLOCK_LEVEL_NONE;469 470	if (lctx) {471		lease->state = 0;472		memcpy(lease->lease_key, lctx->lease_key, SMB2_LEASE_KEY_SIZE);473	}474}475 476static inline int compare_guid_key(struct oplock_info *opinfo,477				   const char *guid1, const char *key1)478{479	const char *guid2, *key2;480 481	guid2 = opinfo->conn->ClientGUID;482	key2 = opinfo->o_lease->lease_key;483	if (!memcmp(guid1, guid2, SMB2_CLIENT_GUID_SIZE) &&484	    !memcmp(key1, key2, SMB2_LEASE_KEY_SIZE))485		return 1;486 487	return 0;488}489 490/**491 * same_client_has_lease() - check whether current lease request is492 *		from lease owner of file493 * @ci:		master file pointer494 * @client_guid:	Client GUID495 * @lctx:		lease context information496 *497 * Return:      oplock(lease) object on success, otherwise NULL498 */499static struct oplock_info *same_client_has_lease(struct ksmbd_inode *ci,500						 char *client_guid,501						 struct lease_ctx_info *lctx)502{503	int ret;504	struct lease *lease;505	struct oplock_info *opinfo;506	struct oplock_info *m_opinfo = NULL;507 508	if (!lctx)509		return NULL;510 511	/*512	 * Compare lease key and client_guid to know request from same owner513	 * of same client514	 */515	down_read(&ci->m_lock);516	list_for_each_entry(opinfo, &ci->m_op_list, op_entry) {517		if (!opinfo->is_lease || !opinfo->conn)518			continue;519		lease = opinfo->o_lease;520 521		ret = compare_guid_key(opinfo, client_guid, lctx->lease_key);522		if (ret) {523			m_opinfo = opinfo;524			/* skip upgrading lease about breaking lease */525			if (atomic_read(&opinfo->breaking_cnt))526				continue;527 528			/* upgrading lease */529			if ((atomic_read(&ci->op_count) +530			     atomic_read(&ci->sop_count)) == 1) {531				if (lease->state != SMB2_LEASE_NONE_LE &&532				    lease->state == (lctx->req_state & lease->state)) {533					lease->epoch++;534					lease->state |= lctx->req_state;535					if (lctx->req_state &536						SMB2_LEASE_WRITE_CACHING_LE)537						lease_read_to_write(opinfo);538 539				}540			} else if ((atomic_read(&ci->op_count) +541				    atomic_read(&ci->sop_count)) > 1) {542				if (lctx->req_state ==543				    (SMB2_LEASE_READ_CACHING_LE |544				     SMB2_LEASE_HANDLE_CACHING_LE)) {545					lease->epoch++;546					lease->state = lctx->req_state;547				}548			}549 550			if (lctx->req_state && lease->state ==551			    SMB2_LEASE_NONE_LE) {552				lease->epoch++;553				lease_none_upgrade(opinfo, lctx->req_state);554			}555		}556	}557	up_read(&ci->m_lock);558 559	return m_opinfo;560}561 562static void wait_for_break_ack(struct oplock_info *opinfo)563{564	int rc = 0;565 566	rc = wait_event_interruptible_timeout(opinfo->oplock_q,567					      opinfo->op_state == OPLOCK_STATE_NONE ||568					      opinfo->op_state == OPLOCK_CLOSING,569					      OPLOCK_WAIT_TIME);570 571	/* is this a timeout ? */572	if (!rc) {573		if (opinfo->is_lease)574			opinfo->o_lease->state = SMB2_LEASE_NONE_LE;575		opinfo->level = SMB2_OPLOCK_LEVEL_NONE;576		opinfo->op_state = OPLOCK_STATE_NONE;577	}578}579 580static void wake_up_oplock_break(struct oplock_info *opinfo)581{582	clear_bit_unlock(0, &opinfo->pending_break);583	/* memory barrier is needed for wake_up_bit() */584	smp_mb__after_atomic();585	wake_up_bit(&opinfo->pending_break, 0);586}587 588static int oplock_break_pending(struct oplock_info *opinfo, int req_op_level)589{590	while (test_and_set_bit(0, &opinfo->pending_break)) {591		wait_on_bit(&opinfo->pending_break, 0, TASK_UNINTERRUPTIBLE);592 593		/* Not immediately break to none. */594		opinfo->open_trunc = 0;595 596		if (opinfo->op_state == OPLOCK_CLOSING)597			return -ENOENT;598		else if (opinfo->level <= req_op_level) {599			if (opinfo->is_lease == false)600				return 1;601 602			if (opinfo->o_lease->state !=603			    (SMB2_LEASE_HANDLE_CACHING_LE |604			     SMB2_LEASE_READ_CACHING_LE))605				return 1;606		}607	}608 609	if (opinfo->level <= req_op_level) {610		if (opinfo->is_lease == false) {611			wake_up_oplock_break(opinfo);612			return 1;613		}614		if (opinfo->o_lease->state !=615		    (SMB2_LEASE_HANDLE_CACHING_LE |616		     SMB2_LEASE_READ_CACHING_LE)) {617			wake_up_oplock_break(opinfo);618			return 1;619		}620	}621	return 0;622}623 624/**625 * __smb2_oplock_break_noti() - send smb2 oplock break cmd from conn626 * to client627 * @wk:     smb work object628 *629 * There are two ways this function can be called. 1- while file open we break630 * from exclusive/batch lock to levelII oplock and 2- while file write/truncate631 * we break from levelII oplock no oplock.632 * work->request_buf contains oplock_info.633 */634static void __smb2_oplock_break_noti(struct work_struct *wk)635{636	struct smb2_oplock_break *rsp = NULL;637	struct ksmbd_work *work = container_of(wk, struct ksmbd_work, work);638	struct oplock_break_info *br_info = work->request_buf;639	struct smb2_hdr *rsp_hdr;640	struct ksmbd_file *fp;641 642	fp = ksmbd_lookup_global_fd(br_info->fid);643	if (!fp)644		goto out;645 646	if (allocate_interim_rsp_buf(work)) {647		pr_err("smb2_allocate_rsp_buf failed! ");648		ksmbd_fd_put(work, fp);649		goto out;650	}651 652	rsp_hdr = smb2_get_msg(work->response_buf);653	memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);654	rsp_hdr->ProtocolId = SMB2_PROTO_NUMBER;655	rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;656	rsp_hdr->CreditRequest = cpu_to_le16(0);657	rsp_hdr->Command = SMB2_OPLOCK_BREAK;658	rsp_hdr->Flags = (SMB2_FLAGS_SERVER_TO_REDIR);659	rsp_hdr->NextCommand = 0;660	rsp_hdr->MessageId = cpu_to_le64(-1);661	rsp_hdr->Id.SyncId.ProcessId = 0;662	rsp_hdr->Id.SyncId.TreeId = 0;663	rsp_hdr->SessionId = 0;664	memset(rsp_hdr->Signature, 0, 16);665 666	rsp = smb2_get_msg(work->response_buf);667 668	rsp->StructureSize = cpu_to_le16(24);669	if (!br_info->open_trunc &&670	    (br_info->level == SMB2_OPLOCK_LEVEL_BATCH ||671	     br_info->level == SMB2_OPLOCK_LEVEL_EXCLUSIVE))672		rsp->OplockLevel = SMB2_OPLOCK_LEVEL_II;673	else674		rsp->OplockLevel = SMB2_OPLOCK_LEVEL_NONE;675	rsp->Reserved = 0;676	rsp->Reserved2 = 0;677	rsp->PersistentFid = fp->persistent_id;678	rsp->VolatileFid = fp->volatile_id;679 680	ksmbd_fd_put(work, fp);681	if (ksmbd_iov_pin_rsp(work, (void *)rsp,682			      sizeof(struct smb2_oplock_break)))683		goto out;684 685	ksmbd_debug(OPLOCK,686		    "sending oplock break v_id %llu p_id = %llu lock level = %d\n",687		    rsp->VolatileFid, rsp->PersistentFid, rsp->OplockLevel);688 689	ksmbd_conn_write(work);690 691out:692	ksmbd_free_work_struct(work);693}694 695/**696 * smb2_oplock_break_noti() - send smb2 exclusive/batch to level2 oplock697 *		break command from server to client698 * @opinfo:		oplock info object699 *700 * Return:      0 on success, otherwise error701 */702static int smb2_oplock_break_noti(struct oplock_info *opinfo)703{704	struct ksmbd_conn *conn = opinfo->conn;705	struct oplock_break_info *br_info;706	int ret = 0;707	struct ksmbd_work *work = ksmbd_alloc_work_struct();708 709	if (!work)710		return -ENOMEM;711 712	br_info = kmalloc(sizeof(struct oplock_break_info), GFP_KERNEL);713	if (!br_info) {714		ksmbd_free_work_struct(work);715		return -ENOMEM;716	}717 718	br_info->level = opinfo->level;719	br_info->fid = opinfo->fid;720	br_info->open_trunc = opinfo->open_trunc;721 722	work->request_buf = (char *)br_info;723	work->conn = conn;724	work->sess = opinfo->sess;725 726	if (opinfo->op_state == OPLOCK_ACK_WAIT) {727		INIT_WORK(&work->work, __smb2_oplock_break_noti);728		ksmbd_queue_work(work);729 730		wait_for_break_ack(opinfo);731	} else {732		__smb2_oplock_break_noti(&work->work);733		if (opinfo->level == SMB2_OPLOCK_LEVEL_II)734			opinfo->level = SMB2_OPLOCK_LEVEL_NONE;735	}736	return ret;737}738 739/**740 * __smb2_lease_break_noti() - send lease break command from server741 * to client742 * @wk:     smb work object743 */744static void __smb2_lease_break_noti(struct work_struct *wk)745{746	struct smb2_lease_break *rsp = NULL;747	struct ksmbd_work *work = container_of(wk, struct ksmbd_work, work);748	struct lease_break_info *br_info = work->request_buf;749	struct smb2_hdr *rsp_hdr;750 751	if (allocate_interim_rsp_buf(work)) {752		ksmbd_debug(OPLOCK, "smb2_allocate_rsp_buf failed! ");753		goto out;754	}755 756	rsp_hdr = smb2_get_msg(work->response_buf);757	memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);758	rsp_hdr->ProtocolId = SMB2_PROTO_NUMBER;759	rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;760	rsp_hdr->CreditRequest = cpu_to_le16(0);761	rsp_hdr->Command = SMB2_OPLOCK_BREAK;762	rsp_hdr->Flags = (SMB2_FLAGS_SERVER_TO_REDIR);763	rsp_hdr->NextCommand = 0;764	rsp_hdr->MessageId = cpu_to_le64(-1);765	rsp_hdr->Id.SyncId.ProcessId = 0;766	rsp_hdr->Id.SyncId.TreeId = 0;767	rsp_hdr->SessionId = 0;768	memset(rsp_hdr->Signature, 0, 16);769 770	rsp = smb2_get_msg(work->response_buf);771	rsp->StructureSize = cpu_to_le16(44);772	rsp->Epoch = br_info->epoch;773	rsp->Flags = 0;774 775	if (br_info->curr_state & (SMB2_LEASE_WRITE_CACHING_LE |776			SMB2_LEASE_HANDLE_CACHING_LE))777		rsp->Flags = SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED;778 779	memcpy(rsp->LeaseKey, br_info->lease_key, SMB2_LEASE_KEY_SIZE);780	rsp->CurrentLeaseState = br_info->curr_state;781	rsp->NewLeaseState = br_info->new_state;782	rsp->BreakReason = 0;783	rsp->AccessMaskHint = 0;784	rsp->ShareMaskHint = 0;785 786	if (ksmbd_iov_pin_rsp(work, (void *)rsp,787			      sizeof(struct smb2_lease_break)))788		goto out;789 790	ksmbd_conn_write(work);791 792out:793	ksmbd_free_work_struct(work);794}795 796/**797 * smb2_lease_break_noti() - break lease when a new client request798 *			write lease799 * @opinfo:		contains lease state information800 *801 * Return:	0 on success, otherwise error802 */803static int smb2_lease_break_noti(struct oplock_info *opinfo)804{805	struct ksmbd_conn *conn = opinfo->conn;806	struct list_head *tmp, *t;807	struct ksmbd_work *work;808	struct lease_break_info *br_info;809	struct lease *lease = opinfo->o_lease;810 811	work = ksmbd_alloc_work_struct();812	if (!work)813		return -ENOMEM;814 815	br_info = kmalloc(sizeof(struct lease_break_info), GFP_KERNEL);816	if (!br_info) {817		ksmbd_free_work_struct(work);818		return -ENOMEM;819	}820 821	br_info->curr_state = lease->state;822	br_info->new_state = lease->new_state;823	if (lease->version == 2)824		br_info->epoch = cpu_to_le16(++lease->epoch);825	else826		br_info->epoch = 0;827	memcpy(br_info->lease_key, lease->lease_key, SMB2_LEASE_KEY_SIZE);828 829	work->request_buf = (char *)br_info;830	work->conn = conn;831	work->sess = opinfo->sess;832 833	if (opinfo->op_state == OPLOCK_ACK_WAIT) {834		list_for_each_safe(tmp, t, &opinfo->interim_list) {835			struct ksmbd_work *in_work;836 837			in_work = list_entry(tmp, struct ksmbd_work,838					     interim_entry);839			setup_async_work(in_work, NULL, NULL);840			smb2_send_interim_resp(in_work, STATUS_PENDING);841			list_del_init(&in_work->interim_entry);842			release_async_work(in_work);843		}844		INIT_WORK(&work->work, __smb2_lease_break_noti);845		ksmbd_queue_work(work);846		wait_for_break_ack(opinfo);847	} else {848		__smb2_lease_break_noti(&work->work);849		if (opinfo->o_lease->new_state == SMB2_LEASE_NONE_LE) {850			opinfo->level = SMB2_OPLOCK_LEVEL_NONE;851			opinfo->o_lease->state = SMB2_LEASE_NONE_LE;852		}853	}854	return 0;855}856 857static void wait_lease_breaking(struct oplock_info *opinfo)858{859	if (!opinfo->is_lease)860		return;861 862	wake_up_interruptible_all(&opinfo->oplock_brk);863	if (atomic_read(&opinfo->breaking_cnt)) {864		int ret = 0;865 866		ret = wait_event_interruptible_timeout(opinfo->oplock_brk,867						       atomic_read(&opinfo->breaking_cnt) == 0,868						       HZ);869		if (!ret)870			atomic_set(&opinfo->breaking_cnt, 0);871	}872}873 874static int oplock_break(struct oplock_info *brk_opinfo, int req_op_level)875{876	int err = 0;877 878	/* Need to break exclusive/batch oplock, write lease or overwrite_if */879	ksmbd_debug(OPLOCK,880		    "request to send oplock(level : 0x%x) break notification\n",881		    brk_opinfo->level);882 883	if (brk_opinfo->is_lease) {884		struct lease *lease = brk_opinfo->o_lease;885 886		atomic_inc(&brk_opinfo->breaking_cnt);887		err = oplock_break_pending(brk_opinfo, req_op_level);888		if (err)889			return err < 0 ? err : 0;890 891		if (brk_opinfo->open_trunc) {892			/*893			 * Create overwrite break trigger the lease break to894			 * none.895			 */896			lease->new_state = SMB2_LEASE_NONE_LE;897		} else {898			if (lease->state & SMB2_LEASE_WRITE_CACHING_LE) {899				if (lease->state & SMB2_LEASE_HANDLE_CACHING_LE)900					lease->new_state =901						SMB2_LEASE_READ_CACHING_LE |902						SMB2_LEASE_HANDLE_CACHING_LE;903				else904					lease->new_state =905						SMB2_LEASE_READ_CACHING_LE;906			} else {907				if (lease->state & SMB2_LEASE_HANDLE_CACHING_LE &&908						!lease->is_dir)909					lease->new_state =910						SMB2_LEASE_READ_CACHING_LE;911				else912					lease->new_state = SMB2_LEASE_NONE_LE;913			}914		}915 916		if (lease->state & (SMB2_LEASE_WRITE_CACHING_LE |917				SMB2_LEASE_HANDLE_CACHING_LE))918			brk_opinfo->op_state = OPLOCK_ACK_WAIT;919		else920			atomic_dec(&brk_opinfo->breaking_cnt);921	} else {922		err = oplock_break_pending(brk_opinfo, req_op_level);923		if (err)924			return err < 0 ? err : 0;925 926		if (brk_opinfo->level == SMB2_OPLOCK_LEVEL_BATCH ||927		    brk_opinfo->level == SMB2_OPLOCK_LEVEL_EXCLUSIVE)928			brk_opinfo->op_state = OPLOCK_ACK_WAIT;929	}930 931	if (brk_opinfo->is_lease)932		err = smb2_lease_break_noti(brk_opinfo);933	else934		err = smb2_oplock_break_noti(brk_opinfo);935 936	ksmbd_debug(OPLOCK, "oplock granted = %d\n", brk_opinfo->level);937	if (brk_opinfo->op_state == OPLOCK_CLOSING)938		err = -ENOENT;939	wake_up_oplock_break(brk_opinfo);940 941	wait_lease_breaking(brk_opinfo);942 943	return err;944}945 946void destroy_lease_table(struct ksmbd_conn *conn)947{948	struct lease_table *lb, *lbtmp;949	struct oplock_info *opinfo;950 951	write_lock(&lease_list_lock);952	if (list_empty(&lease_table_list)) {953		write_unlock(&lease_list_lock);954		return;955	}956 957	list_for_each_entry_safe(lb, lbtmp, &lease_table_list, l_entry) {958		if (conn && memcmp(lb->client_guid, conn->ClientGUID,959				   SMB2_CLIENT_GUID_SIZE))960			continue;961again:962		rcu_read_lock();963		list_for_each_entry_rcu(opinfo, &lb->lease_list,964					lease_entry) {965			rcu_read_unlock();966			lease_del_list(opinfo);967			goto again;968		}969		rcu_read_unlock();970		list_del(&lb->l_entry);971		kfree(lb);972	}973	write_unlock(&lease_list_lock);974}975 976int find_same_lease_key(struct ksmbd_session *sess, struct ksmbd_inode *ci,977			struct lease_ctx_info *lctx)978{979	struct oplock_info *opinfo;980	int err = 0;981	struct lease_table *lb;982 983	if (!lctx)984		return err;985 986	read_lock(&lease_list_lock);987	if (list_empty(&lease_table_list)) {988		read_unlock(&lease_list_lock);989		return 0;990	}991 992	list_for_each_entry(lb, &lease_table_list, l_entry) {993		if (!memcmp(lb->client_guid, sess->ClientGUID,994			    SMB2_CLIENT_GUID_SIZE))995			goto found;996	}997	read_unlock(&lease_list_lock);998 999	return 0;1000 1001found:1002	rcu_read_lock();1003	list_for_each_entry_rcu(opinfo, &lb->lease_list, lease_entry) {1004		if (!atomic_inc_not_zero(&opinfo->refcount))1005			continue;1006		rcu_read_unlock();1007		if (opinfo->o_fp->f_ci == ci)1008			goto op_next;1009		err = compare_guid_key(opinfo, sess->ClientGUID,1010				       lctx->lease_key);1011		if (err) {1012			err = -EINVAL;1013			ksmbd_debug(OPLOCK,1014				    "found same lease key is already used in other files\n");1015			opinfo_put(opinfo);1016			goto out;1017		}1018op_next:1019		opinfo_put(opinfo);1020		rcu_read_lock();1021	}1022	rcu_read_unlock();1023 1024out:1025	read_unlock(&lease_list_lock);1026	return err;1027}1028 1029static void copy_lease(struct oplock_info *op1, struct oplock_info *op2)1030{1031	struct lease *lease1 = op1->o_lease;1032	struct lease *lease2 = op2->o_lease;1033 1034	op2->level = op1->level;1035	lease2->state = lease1->state;1036	memcpy(lease2->lease_key, lease1->lease_key,1037	       SMB2_LEASE_KEY_SIZE);1038	lease2->duration = lease1->duration;1039	lease2->flags = lease1->flags;1040	lease2->epoch = lease1->epoch;1041	lease2->version = lease1->version;1042}1043 1044static int add_lease_global_list(struct oplock_info *opinfo)1045{1046	struct lease_table *lb;1047 1048	read_lock(&lease_list_lock);1049	list_for_each_entry(lb, &lease_table_list, l_entry) {1050		if (!memcmp(lb->client_guid, opinfo->conn->ClientGUID,1051			    SMB2_CLIENT_GUID_SIZE)) {1052			opinfo->o_lease->l_lb = lb;1053			lease_add_list(opinfo);1054			read_unlock(&lease_list_lock);1055			return 0;1056		}1057	}1058	read_unlock(&lease_list_lock);1059 1060	lb = kmalloc(sizeof(struct lease_table), GFP_KERNEL);1061	if (!lb)1062		return -ENOMEM;1063 1064	memcpy(lb->client_guid, opinfo->conn->ClientGUID,1065	       SMB2_CLIENT_GUID_SIZE);1066	INIT_LIST_HEAD(&lb->lease_list);1067	spin_lock_init(&lb->lb_lock);1068	opinfo->o_lease->l_lb = lb;1069	lease_add_list(opinfo);1070	lb_add(lb);1071	return 0;1072}1073 1074static void set_oplock_level(struct oplock_info *opinfo, int level,1075			     struct lease_ctx_info *lctx)1076{1077	switch (level) {1078	case SMB2_OPLOCK_LEVEL_BATCH:1079	case SMB2_OPLOCK_LEVEL_EXCLUSIVE:1080		grant_write_oplock(opinfo, level, lctx);1081		break;1082	case SMB2_OPLOCK_LEVEL_II:1083		grant_read_oplock(opinfo, lctx);1084		break;1085	default:1086		grant_none_oplock(opinfo, lctx);1087		break;1088	}1089}1090 1091void smb_send_parent_lease_break_noti(struct ksmbd_file *fp,1092				      struct lease_ctx_info *lctx)1093{1094	struct oplock_info *opinfo;1095	struct ksmbd_inode *p_ci = NULL;1096 1097	if (lctx->version != 2)1098		return;1099 1100	p_ci = ksmbd_inode_lookup_lock(fp->filp->f_path.dentry->d_parent);1101	if (!p_ci)1102		return;1103 1104	down_read(&p_ci->m_lock);1105	list_for_each_entry(opinfo, &p_ci->m_op_list, op_entry) {1106		if (opinfo->conn == NULL || !opinfo->is_lease)1107			continue;1108 1109		if (opinfo->o_lease->state != SMB2_OPLOCK_LEVEL_NONE &&1110		    (!(lctx->flags & SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE) ||1111		     !compare_guid_key(opinfo, fp->conn->ClientGUID,1112				      lctx->parent_lease_key))) {1113			if (!atomic_inc_not_zero(&opinfo->refcount))1114				continue;1115 1116			if (ksmbd_conn_releasing(opinfo->conn))1117				continue;1118 1119			oplock_break(opinfo, SMB2_OPLOCK_LEVEL_NONE);1120			opinfo_put(opinfo);1121		}1122	}1123	up_read(&p_ci->m_lock);1124 1125	ksmbd_inode_put(p_ci);1126}1127 1128void smb_lazy_parent_lease_break_close(struct ksmbd_file *fp)1129{1130	struct oplock_info *opinfo;1131	struct ksmbd_inode *p_ci = NULL;1132 1133	rcu_read_lock();1134	opinfo = rcu_dereference(fp->f_opinfo);1135	rcu_read_unlock();1136 1137	if (!opinfo || !opinfo->is_lease || opinfo->o_lease->version != 2)1138		return;1139 1140	p_ci = ksmbd_inode_lookup_lock(fp->filp->f_path.dentry->d_parent);1141	if (!p_ci)1142		return;1143 1144	down_read(&p_ci->m_lock);1145	list_for_each_entry(opinfo, &p_ci->m_op_list, op_entry) {1146		if (opinfo->conn == NULL || !opinfo->is_lease)1147			continue;1148 1149		if (opinfo->o_lease->state != SMB2_OPLOCK_LEVEL_NONE) {1150			if (!atomic_inc_not_zero(&opinfo->refcount))1151				continue;1152 1153			if (ksmbd_conn_releasing(opinfo->conn))1154				continue;1155			oplock_break(opinfo, SMB2_OPLOCK_LEVEL_NONE);1156			opinfo_put(opinfo);1157		}1158	}1159	up_read(&p_ci->m_lock);1160 1161	ksmbd_inode_put(p_ci);1162}1163 1164/**1165 * smb_grant_oplock() - handle oplock/lease request on file open1166 * @work:		smb work1167 * @req_op_level:	oplock level1168 * @pid:		id of open file1169 * @fp:			ksmbd file pointer1170 * @tid:		Tree id of connection1171 * @lctx:		lease context information on file open1172 * @share_ret:		share mode1173 *1174 * Return:      0 on success, otherwise error1175 */1176int smb_grant_oplock(struct ksmbd_work *work, int req_op_level, u64 pid,1177		     struct ksmbd_file *fp, __u16 tid,1178		     struct lease_ctx_info *lctx, int share_ret)1179{1180	struct ksmbd_session *sess = work->sess;1181	int err = 0;1182	struct oplock_info *opinfo = NULL, *prev_opinfo = NULL;1183	struct ksmbd_inode *ci = fp->f_ci;1184	bool prev_op_has_lease;1185	__le32 prev_op_state = 0;1186 1187	/* Only v2 leases handle the directory */1188	if (S_ISDIR(file_inode(fp->filp)->i_mode)) {1189		if (!lctx || lctx->version != 2 ||1190		    (lctx->flags != SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE &&1191		     !lctx->epoch))1192			return 0;1193	}1194 1195	opinfo = alloc_opinfo(work, pid, tid);1196	if (!opinfo)1197		return -ENOMEM;1198 1199	if (lctx) {1200		err = alloc_lease(opinfo, lctx);1201		if (err)1202			goto err_out;1203		opinfo->is_lease = 1;1204	}1205 1206	/* ci does not have any oplock */1207	if (!opinfo_count(fp))1208		goto set_lev;1209 1210	/* grant none-oplock if second open is trunc */1211	if (fp->attrib_only && fp->cdoption != FILE_OVERWRITE_IF_LE &&1212	    fp->cdoption != FILE_OVERWRITE_LE &&1213	    fp->cdoption != FILE_SUPERSEDE_LE) {1214		req_op_level = SMB2_OPLOCK_LEVEL_NONE;1215		goto set_lev;1216	}1217 1218	if (lctx) {1219		struct oplock_info *m_opinfo;1220 1221		/* is lease already granted ? */1222		m_opinfo = same_client_has_lease(ci, sess->ClientGUID,1223						 lctx);1224		if (m_opinfo) {1225			copy_lease(m_opinfo, opinfo);1226			if (atomic_read(&m_opinfo->breaking_cnt))1227				opinfo->o_lease->flags =1228					SMB2_LEASE_FLAG_BREAK_IN_PROGRESS_LE;1229			goto out;1230		}1231	}1232	prev_opinfo = opinfo_get_list(ci);1233	if (!prev_opinfo ||1234	    (prev_opinfo->level == SMB2_OPLOCK_LEVEL_NONE && lctx)) {1235		opinfo_put(prev_opinfo);1236		goto set_lev;1237	}1238	prev_op_has_lease = prev_opinfo->is_lease;1239	if (prev_op_has_lease)1240		prev_op_state = prev_opinfo->o_lease->state;1241 1242	if (share_ret < 0 &&1243	    prev_opinfo->level == SMB2_OPLOCK_LEVEL_EXCLUSIVE) {1244		err = share_ret;1245		opinfo_put(prev_opinfo);1246		goto err_out;1247	}1248 1249	if (prev_opinfo->level != SMB2_OPLOCK_LEVEL_BATCH &&1250	    prev_opinfo->level != SMB2_OPLOCK_LEVEL_EXCLUSIVE) {1251		opinfo_put(prev_opinfo);1252		goto op_break_not_needed;1253	}1254 1255	list_add(&work->interim_entry, &prev_opinfo->interim_list);1256	err = oplock_break(prev_opinfo, SMB2_OPLOCK_LEVEL_II);1257	opinfo_put(prev_opinfo);1258	if (err == -ENOENT)1259		goto set_lev;1260	/* Check all oplock was freed by close */1261	else if (err < 0)1262		goto err_out;1263 1264op_break_not_needed:1265	if (share_ret < 0) {1266		err = share_ret;1267		goto err_out;1268	}1269 1270	if (req_op_level != SMB2_OPLOCK_LEVEL_NONE)1271		req_op_level = SMB2_OPLOCK_LEVEL_II;1272 1273	/* grant fixed oplock on stacked locking between lease and oplock */1274	if (prev_op_has_lease && !lctx)1275		if (prev_op_state & SMB2_LEASE_HANDLE_CACHING_LE)1276			req_op_level = SMB2_OPLOCK_LEVEL_NONE;1277 1278	if (!prev_op_has_lease && lctx) {1279		req_op_level = SMB2_OPLOCK_LEVEL_II;1280		lctx->req_state = SMB2_LEASE_READ_CACHING_LE;1281	}1282 1283set_lev:1284	set_oplock_level(opinfo, req_op_level, lctx);1285 1286out:1287	rcu_assign_pointer(fp->f_opinfo, opinfo);1288	opinfo->o_fp = fp;1289 1290	opinfo_count_inc(fp);1291	opinfo_add(opinfo);1292	if (opinfo->is_lease) {1293		err = add_lease_global_list(opinfo);1294		if (err)1295			goto err_out;1296	}1297 1298	return 0;1299err_out:1300	free_opinfo(opinfo);1301	return err;1302}1303 1304/**1305 * smb_break_all_write_oplock() - break batch/exclusive oplock to level21306 * @work:	smb work1307 * @fp:		ksmbd file pointer1308 * @is_trunc:	truncate on open1309 */1310static void smb_break_all_write_oplock(struct ksmbd_work *work,1311				       struct ksmbd_file *fp, int is_trunc)1312{1313	struct oplock_info *brk_opinfo;1314 1315	brk_opinfo = opinfo_get_list(fp->f_ci);1316	if (!brk_opinfo)1317		return;1318	if (brk_opinfo->level != SMB2_OPLOCK_LEVEL_BATCH &&1319	    brk_opinfo->level != SMB2_OPLOCK_LEVEL_EXCLUSIVE) {1320		opinfo_put(brk_opinfo);1321		return;1322	}1323 1324	brk_opinfo->open_trunc = is_trunc;1325	list_add(&work->interim_entry, &brk_opinfo->interim_list);1326	oplock_break(brk_opinfo, SMB2_OPLOCK_LEVEL_II);1327	opinfo_put(brk_opinfo);1328}1329 1330/**1331 * smb_break_all_levII_oplock() - send level2 oplock or read lease break command1332 *	from server to client1333 * @work:	smb work1334 * @fp:		ksmbd file pointer1335 * @is_trunc:	truncate on open1336 */1337void smb_break_all_levII_oplock(struct ksmbd_work *work, struct ksmbd_file *fp,1338				int is_trunc)1339{1340	struct oplock_info *op, *brk_op;1341	struct ksmbd_inode *ci;1342	struct ksmbd_conn *conn = work->conn;1343 1344	if (!test_share_config_flag(work->tcon->share_conf,1345				    KSMBD_SHARE_FLAG_OPLOCKS))1346		return;1347 1348	ci = fp->f_ci;1349	op = opinfo_get(fp);1350 1351	rcu_read_lock();1352	list_for_each_entry_rcu(brk_op, &ci->m_op_list, op_entry) {1353		if (brk_op->conn == NULL)1354			continue;1355 1356		if (!atomic_inc_not_zero(&brk_op->refcount))1357			continue;1358 1359		if (ksmbd_conn_releasing(brk_op->conn))1360			continue;1361 1362		rcu_read_unlock();1363		if (brk_op->is_lease && (brk_op->o_lease->state &1364		    (~(SMB2_LEASE_READ_CACHING_LE |1365				SMB2_LEASE_HANDLE_CACHING_LE)))) {1366			ksmbd_debug(OPLOCK, "unexpected lease state(0x%x)\n",1367				    brk_op->o_lease->state);1368			goto next;1369		} else if (brk_op->level !=1370				SMB2_OPLOCK_LEVEL_II) {1371			ksmbd_debug(OPLOCK, "unexpected oplock(0x%x)\n",1372				    brk_op->level);1373			goto next;1374		}1375 1376		/* Skip oplock being break to none */1377		if (brk_op->is_lease &&1378		    brk_op->o_lease->new_state == SMB2_LEASE_NONE_LE &&1379		    atomic_read(&brk_op->breaking_cnt))1380			goto next;1381 1382		if (op && op->is_lease && brk_op->is_lease &&1383		    !memcmp(conn->ClientGUID, brk_op->conn->ClientGUID,1384			    SMB2_CLIENT_GUID_SIZE) &&1385		    !memcmp(op->o_lease->lease_key, brk_op->o_lease->lease_key,1386			    SMB2_LEASE_KEY_SIZE))1387			goto next;1388		brk_op->open_trunc = is_trunc;1389		oplock_break(brk_op, SMB2_OPLOCK_LEVEL_NONE);1390next:1391		opinfo_put(brk_op);1392		rcu_read_lock();1393	}1394	rcu_read_unlock();1395 1396	if (op)1397		opinfo_put(op);1398}1399 1400/**1401 * smb_break_all_oplock() - break both batch/exclusive and level2 oplock1402 * @work:	smb work1403 * @fp:		ksmbd file pointer1404 */1405void smb_break_all_oplock(struct ksmbd_work *work, struct ksmbd_file *fp)1406{1407	if (!test_share_config_flag(work->tcon->share_conf,1408				    KSMBD_SHARE_FLAG_OPLOCKS))1409		return;1410 1411	smb_break_all_write_oplock(work, fp, 1);1412	smb_break_all_levII_oplock(work, fp, 1);1413}1414 1415/**1416 * smb2_map_lease_to_oplock() - map lease state to corresponding oplock type1417 * @lease_state:     lease type1418 *1419 * Return:      0 if no mapping, otherwise corresponding oplock type1420 */1421__u8 smb2_map_lease_to_oplock(__le32 lease_state)1422{1423	if (lease_state == (SMB2_LEASE_HANDLE_CACHING_LE |1424			    SMB2_LEASE_READ_CACHING_LE |1425			    SMB2_LEASE_WRITE_CACHING_LE)) {1426		return SMB2_OPLOCK_LEVEL_BATCH;1427	} else if (lease_state != SMB2_LEASE_WRITE_CACHING_LE &&1428		 lease_state & SMB2_LEASE_WRITE_CACHING_LE) {1429		if (!(lease_state & SMB2_LEASE_HANDLE_CACHING_LE))1430			return SMB2_OPLOCK_LEVEL_EXCLUSIVE;1431	} else if (lease_state & SMB2_LEASE_READ_CACHING_LE) {1432		return SMB2_OPLOCK_LEVEL_II;1433	}1434	return 0;1435}1436 1437/**1438 * create_lease_buf() - create lease context for open cmd response1439 * @rbuf:	buffer to create lease context response1440 * @lease:	buffer to stored parsed lease state information1441 */1442void create_lease_buf(u8 *rbuf, struct lease *lease)1443{1444	if (lease->version == 2) {1445		struct create_lease_v2 *buf = (struct create_lease_v2 *)rbuf;1446 1447		memset(buf, 0, sizeof(struct create_lease_v2));1448		memcpy(buf->lcontext.LeaseKey, lease->lease_key,1449		       SMB2_LEASE_KEY_SIZE);1450		buf->lcontext.LeaseFlags = lease->flags;1451		buf->lcontext.Epoch = cpu_to_le16(lease->epoch);1452		buf->lcontext.LeaseState = lease->state;1453		if (lease->flags == SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE)1454			memcpy(buf->lcontext.ParentLeaseKey, lease->parent_lease_key,1455			       SMB2_LEASE_KEY_SIZE);1456		buf->ccontext.DataOffset = cpu_to_le16(offsetof1457				(struct create_lease_v2, lcontext));1458		buf->ccontext.DataLength = cpu_to_le32(sizeof(struct lease_context_v2));1459		buf->ccontext.NameOffset = cpu_to_le16(offsetof1460				(struct create_lease_v2, Name));1461		buf->ccontext.NameLength = cpu_to_le16(4);1462		buf->Name[0] = 'R';1463		buf->Name[1] = 'q';1464		buf->Name[2] = 'L';1465		buf->Name[3] = 's';1466	} else {1467		struct create_lease *buf = (struct create_lease *)rbuf;1468 1469		memset(buf, 0, sizeof(struct create_lease));1470		memcpy(buf->lcontext.LeaseKey, lease->lease_key, SMB2_LEASE_KEY_SIZE);1471		buf->lcontext.LeaseFlags = lease->flags;1472		buf->lcontext.LeaseState = lease->state;1473		buf->ccontext.DataOffset = cpu_to_le16(offsetof1474				(struct create_lease, lcontext));1475		buf->ccontext.DataLength = cpu_to_le32(sizeof(struct lease_context));1476		buf->ccontext.NameOffset = cpu_to_le16(offsetof1477				(struct create_lease, Name));1478		buf->ccontext.NameLength = cpu_to_le16(4);1479		buf->Name[0] = 'R';1480		buf->Name[1] = 'q';1481		buf->Name[2] = 'L';1482		buf->Name[3] = 's';1483	}1484}1485 1486/**1487 * parse_lease_state() - parse lease context contained in file open request1488 * @open_req:	buffer containing smb2 file open(create) request1489 *1490 * Return: allocated lease context object on success, otherwise NULL1491 */1492struct lease_ctx_info *parse_lease_state(void *open_req)1493{1494	struct create_context *cc;1495	struct smb2_create_req *req = (struct smb2_create_req *)open_req;1496	struct lease_ctx_info *lreq;1497 1498	cc = smb2_find_context_vals(req, SMB2_CREATE_REQUEST_LEASE, 4);1499	if (IS_ERR_OR_NULL(cc))1500		return NULL;1501 1502	lreq = kzalloc(sizeof(struct lease_ctx_info), GFP_KERNEL);1503	if (!lreq)1504		return NULL;1505 1506	if (sizeof(struct lease_context_v2) == le32_to_cpu(cc->DataLength)) {1507		struct create_lease_v2 *lc = (struct create_lease_v2 *)cc;1508 1509		memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE);1510		lreq->req_state = lc->lcontext.LeaseState;1511		lreq->flags = lc->lcontext.LeaseFlags;1512		lreq->epoch = lc->lcontext.Epoch;1513		lreq->duration = lc->lcontext.LeaseDuration;1514		if (lreq->flags == SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE)1515			memcpy(lreq->parent_lease_key, lc->lcontext.ParentLeaseKey,1516			       SMB2_LEASE_KEY_SIZE);1517		lreq->version = 2;1518	} else {1519		struct create_lease *lc = (struct create_lease *)cc;1520 1521		memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE);1522		lreq->req_state = lc->lcontext.LeaseState;1523		lreq->flags = lc->lcontext.LeaseFlags;1524		lreq->duration = lc->lcontext.LeaseDuration;1525		lreq->version = 1;1526	}1527	return lreq;1528}1529 1530/**1531 * smb2_find_context_vals() - find a particular context info in open request1532 * @open_req:	buffer containing smb2 file open(create) request1533 * @tag:	context name to search for1534 * @tag_len:	the length of tag1535 *1536 * Return:	pointer to requested context, NULL if @str context not found1537 *		or error pointer if name length is invalid.1538 */1539struct create_context *smb2_find_context_vals(void *open_req, const char *tag, int tag_len)1540{1541	struct create_context *cc;1542	unsigned int next = 0;1543	char *name;1544	struct smb2_create_req *req = (struct smb2_create_req *)open_req;1545	unsigned int remain_len, name_off, name_len, value_off, value_len,1546		     cc_len;1547 1548	/*1549	 * CreateContextsOffset and CreateContextsLength are guaranteed to1550	 * be valid because of ksmbd_smb2_check_message().1551	 */1552	cc = (struct create_context *)((char *)req +1553				       le32_to_cpu(req->CreateContextsOffset));1554	remain_len = le32_to_cpu(req->CreateContextsLength);1555	do {1556		cc = (struct create_context *)((char *)cc + next);1557		if (remain_len < offsetof(struct create_context, Buffer))1558			return ERR_PTR(-EINVAL);1559 1560		next = le32_to_cpu(cc->Next);1561		name_off = le16_to_cpu(cc->NameOffset);1562		name_len = le16_to_cpu(cc->NameLength);1563		value_off = le16_to_cpu(cc->DataOffset);1564		value_len = le32_to_cpu(cc->DataLength);1565		cc_len = next ? next : remain_len;1566 1567		if ((next & 0x7) != 0 ||1568		    next > remain_len ||1569		    name_off != offsetof(struct create_context, Buffer) ||1570		    name_len < 4 ||1571		    name_off + name_len > cc_len ||1572		    (value_off & 0x7) != 0 ||1573		    (value_len && value_off < name_off + (name_len < 8 ? 8 : name_len)) ||1574		    ((u64)value_off + value_len > cc_len))1575			return ERR_PTR(-EINVAL);1576 1577		name = (char *)cc + name_off;1578		if (name_len == tag_len && !memcmp(name, tag, name_len))1579			return cc;1580 1581		remain_len -= next;1582	} while (next != 0);1583 1584	return NULL;1585}1586 1587/**1588 * create_durable_rsp_buf() - create durable handle context1589 * @cc:	buffer to create durable context response1590 */1591void create_durable_rsp_buf(char *cc)1592{1593	struct create_durable_rsp *buf;1594 1595	buf = (struct create_durable_rsp *)cc;1596	memset(buf, 0, sizeof(struct create_durable_rsp));1597	buf->ccontext.DataOffset = cpu_to_le16(offsetof1598			(struct create_durable_rsp, Data));1599	buf->ccontext.DataLength = cpu_to_le32(8);1600	buf->ccontext.NameOffset = cpu_to_le16(offsetof1601			(struct create_durable_rsp, Name));1602	buf->ccontext.NameLength = cpu_to_le16(4);1603	/* SMB2_CREATE_DURABLE_HANDLE_RESPONSE is "DHnQ" */1604	buf->Name[0] = 'D';1605	buf->Name[1] = 'H';1606	buf->Name[2] = 'n';1607	buf->Name[3] = 'Q';1608}1609 1610/**1611 * create_durable_v2_rsp_buf() - create durable handle v2 context1612 * @cc:	buffer to create durable context response1613 * @fp: ksmbd file pointer1614 */1615void create_durable_v2_rsp_buf(char *cc, struct ksmbd_file *fp)1616{1617	struct create_durable_v2_rsp *buf;1618 1619	buf = (struct create_durable_v2_rsp *)cc;1620	memset(buf, 0, sizeof(struct create_durable_rsp));1621	buf->ccontext.DataOffset = cpu_to_le16(offsetof1622			(struct create_durable_rsp, Data));1623	buf->ccontext.DataLength = cpu_to_le32(8);1624	buf->ccontext.NameOffset = cpu_to_le16(offsetof1625			(struct create_durable_rsp, Name));1626	buf->ccontext.NameLength = cpu_to_le16(4);1627	/* SMB2_CREATE_DURABLE_HANDLE_RESPONSE_V2 is "DH2Q" */1628	buf->Name[0] = 'D';1629	buf->Name[1] = 'H';1630	buf->Name[2] = '2';1631	buf->Name[3] = 'Q';1632 1633	buf->Timeout = cpu_to_le32(fp->durable_timeout);1634	if (fp->is_persistent)1635		buf->Flags = cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT);1636}1637 1638/**1639 * create_mxac_rsp_buf() - create query maximal access context1640 * @cc:			buffer to create maximal access context response1641 * @maximal_access:	maximal access1642 */1643void create_mxac_rsp_buf(char *cc, int maximal_access)1644{1645	struct create_mxac_rsp *buf;1646 1647	buf = (struct create_mxac_rsp *)cc;1648	memset(buf, 0, sizeof(struct create_mxac_rsp));1649	buf->ccontext.DataOffset = cpu_to_le16(offsetof1650			(struct create_mxac_rsp, QueryStatus));1651	buf->ccontext.DataLength = cpu_to_le32(8);1652	buf->ccontext.NameOffset = cpu_to_le16(offsetof1653			(struct create_mxac_rsp, Name));1654	buf->ccontext.NameLength = cpu_to_le16(4);1655	/* SMB2_CREATE_QUERY_MAXIMAL_ACCESS_RESPONSE is "MxAc" */1656	buf->Name[0] = 'M';1657	buf->Name[1] = 'x';1658	buf->Name[2] = 'A';1659	buf->Name[3] = 'c';1660 1661	buf->QueryStatus = STATUS_SUCCESS;1662	buf->MaximalAccess = cpu_to_le32(maximal_access);1663}1664 1665void create_disk_id_rsp_buf(char *cc, __u64 file_id, __u64 vol_id)1666{1667	struct create_disk_id_rsp *buf;1668 1669	buf = (struct create_disk_id_rsp *)cc;1670	memset(buf, 0, sizeof(struct create_disk_id_rsp));1671	buf->ccontext.DataOffset = cpu_to_le16(offsetof1672			(struct create_disk_id_rsp, DiskFileId));1673	buf->ccontext.DataLength = cpu_to_le32(32);1674	buf->ccontext.NameOffset = cpu_to_le16(offsetof1675			(struct create_mxac_rsp, Name));1676	buf->ccontext.NameLength = cpu_to_le16(4);1677	/* SMB2_CREATE_QUERY_ON_DISK_ID_RESPONSE is "QFid" */1678	buf->Name[0] = 'Q';1679	buf->Name[1] = 'F';1680	buf->Name[2] = 'i';1681	buf->Name[3] = 'd';1682 1683	buf->DiskFileId = cpu_to_le64(file_id);1684	buf->VolumeId = cpu_to_le64(vol_id);1685}1686 1687/**1688 * create_posix_rsp_buf() - create posix extension context1689 * @cc:	buffer to create posix on posix response1690 * @fp: ksmbd file pointer1691 */1692void create_posix_rsp_buf(char *cc, struct ksmbd_file *fp)1693{1694	struct create_posix_rsp *buf;1695	struct inode *inode = file_inode(fp->filp);1696	struct mnt_idmap *idmap = file_mnt_idmap(fp->filp);1697	vfsuid_t vfsuid = i_uid_into_vfsuid(idmap, inode);1698	vfsgid_t vfsgid = i_gid_into_vfsgid(idmap, inode);1699 1700	buf = (struct create_posix_rsp *)cc;1701	memset(buf, 0, sizeof(struct create_posix_rsp));1702	buf->ccontext.DataOffset = cpu_to_le16(offsetof1703			(struct create_posix_rsp, nlink));1704	/*1705	 * DataLength = nlink(4) + reparse_tag(4) + mode(4) +1706	 * domain sid(28) + unix group sid(16).1707	 */1708	buf->ccontext.DataLength = cpu_to_le32(56);1709	buf->ccontext.NameOffset = cpu_to_le16(offsetof1710			(struct create_posix_rsp, Name));1711	buf->ccontext.NameLength = cpu_to_le16(POSIX_CTXT_DATA_LEN);1712	/* SMB2_CREATE_TAG_POSIX is "0x93AD25509CB411E7B42383DE968BCD7C" */1713	buf->Name[0] = 0x93;1714	buf->Name[1] = 0xAD;1715	buf->Name[2] = 0x25;1716	buf->Name[3] = 0x50;1717	buf->Name[4] = 0x9C;1718	buf->Name[5] = 0xB4;1719	buf->Name[6] = 0x11;1720	buf->Name[7] = 0xE7;1721	buf->Name[8] = 0xB4;1722	buf->Name[9] = 0x23;1723	buf->Name[10] = 0x83;1724	buf->Name[11] = 0xDE;1725	buf->Name[12] = 0x96;1726	buf->Name[13] = 0x8B;1727	buf->Name[14] = 0xCD;1728	buf->Name[15] = 0x7C;1729 1730	buf->nlink = cpu_to_le32(inode->i_nlink);1731	buf->reparse_tag = cpu_to_le32(fp->volatile_id);1732	buf->mode = cpu_to_le32(inode->i_mode & 0777);1733	/*1734	 * SidBuffer(44) contain two sids(Domain sid(28), UNIX group sid(16)).1735	 * Domain sid(28) = revision(1) + num_subauth(1) + authority(6) +1736	 *		    sub_auth(4 * 4(num_subauth)) + RID(4).1737	 * UNIX group id(16) = revision(1) + num_subauth(1) + authority(6) +1738	 *		       sub_auth(4 * 1(num_subauth)) + RID(4).1739	 */1740	id_to_sid(from_kuid_munged(&init_user_ns, vfsuid_into_kuid(vfsuid)),1741		  SIDOWNER, (struct smb_sid *)&buf->SidBuffer[0]);1742	id_to_sid(from_kgid_munged(&init_user_ns, vfsgid_into_kgid(vfsgid)),1743		  SIDUNIX_GROUP, (struct smb_sid *)&buf->SidBuffer[28]);1744}1745 1746/*1747 * Find lease object(opinfo) for given lease key/fid from lease1748 * break/file close path.1749 */1750/**1751 * lookup_lease_in_table() - find a matching lease info object1752 * @conn:	connection instance1753 * @lease_key:	lease key to be searched for1754 *1755 * Return:      opinfo if found matching opinfo, otherwise NULL1756 */1757struct oplock_info *lookup_lease_in_table(struct ksmbd_conn *conn,1758					  char *lease_key)1759{1760	struct oplock_info *opinfo = NULL, *ret_op = NULL;1761	struct lease_table *lt;1762	int ret;1763 1764	read_lock(&lease_list_lock);1765	list_for_each_entry(lt, &lease_table_list, l_entry) {1766		if (!memcmp(lt->client_guid, conn->ClientGUID,1767			    SMB2_CLIENT_GUID_SIZE))1768			goto found;1769	}1770 1771	read_unlock(&lease_list_lock);1772	return NULL;1773 1774found:1775	rcu_read_lock();1776	list_for_each_entry_rcu(opinfo, &lt->lease_list, lease_entry) {1777		if (!atomic_inc_not_zero(&opinfo->refcount))1778			continue;1779		rcu_read_unlock();1780		if (!opinfo->op_state || opinfo->op_state == OPLOCK_CLOSING)1781			goto op_next;1782		if (!(opinfo->o_lease->state &1783		      (SMB2_LEASE_HANDLE_CACHING_LE |1784		       SMB2_LEASE_WRITE_CACHING_LE)))1785			goto op_next;1786		ret = compare_guid_key(opinfo, conn->ClientGUID,1787				       lease_key);1788		if (ret) {1789			ksmbd_debug(OPLOCK, "found opinfo\n");1790			ret_op = opinfo;1791			goto out;1792		}1793op_next:1794		opinfo_put(opinfo);1795		rcu_read_lock();1796	}1797	rcu_read_unlock();1798 1799out:1800	read_unlock(&lease_list_lock);1801	return ret_op;1802}1803 1804int smb2_check_durable_oplock(struct ksmbd_conn *conn,1805			      struct ksmbd_share_config *share,1806			      struct ksmbd_file *fp,1807			      struct lease_ctx_info *lctx,1808			      char *name)1809{1810	struct oplock_info *opinfo = opinfo_get(fp);1811	int ret = 0;1812 1813	if (!opinfo)1814		return 0;1815 1816	if (opinfo->is_lease == false) {1817		if (lctx) {1818			pr_err("create context include lease\n");1819			ret = -EBADF;1820			goto out;1821		}1822 1823		if (opinfo->level != SMB2_OPLOCK_LEVEL_BATCH) {1824			pr_err("oplock level is not equal to SMB2_OPLOCK_LEVEL_BATCH\n");1825			ret = -EBADF;1826		}1827 1828		goto out;1829	}1830 1831	if (memcmp(conn->ClientGUID, fp->client_guid,1832				SMB2_CLIENT_GUID_SIZE)) {1833		ksmbd_debug(SMB, "Client guid of fp is not equal to the one of connection\n");1834		ret = -EBADF;1835		goto out;1836	}1837 1838	if (!lctx) {1839		ksmbd_debug(SMB, "create context does not include lease\n");1840		ret = -EBADF;1841		goto out;1842	}1843 1844	if (memcmp(opinfo->o_lease->lease_key, lctx->lease_key,1845				SMB2_LEASE_KEY_SIZE)) {1846		ksmbd_debug(SMB,1847			    "lease key of fp does not match lease key in create context\n");1848		ret = -EBADF;1849		goto out;1850	}1851 1852	if (!(opinfo->o_lease->state & SMB2_LEASE_HANDLE_CACHING_LE)) {1853		ksmbd_debug(SMB, "lease state does not contain SMB2_LEASE_HANDLE_CACHING\n");1854		ret = -EBADF;1855		goto out;1856	}1857 1858	if (opinfo->o_lease->version != lctx->version) {1859		ksmbd_debug(SMB,1860			    "lease version of fp does not match the one in create context\n");1861		ret = -EBADF;1862		goto out;1863	}1864 1865	if (!ksmbd_inode_pending_delete(fp))1866		ret = ksmbd_validate_name_reconnect(share, fp, name);1867out:1868	opinfo_put(opinfo);1869	return ret;1870}1871