linux/fs/smb/server/oplock.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 *   Copyright (C) 2016 Namjae Jeon <[email protected]>
 *   Copyright (C) 2018 Samsung Electronics Co., Ltd.
 */

#include <linux/moduleparam.h>

#include "glob.h"
#include "oplock.h"

#include "smb_common.h"
#include "smbstatus.h"
#include "connection.h"
#include "mgmt/user_session.h"
#include "mgmt/share_config.h"
#include "mgmt/tree_connect.h"

static LIST_HEAD(lease_table_list);
static DEFINE_RWLOCK(lease_list_lock);

/**
 * alloc_opinfo() - allocate a new opinfo object for oplock info
 * @work:	smb work
 * @id:		fid of open file
 * @Tid:	tree id of connection
 *
 * Return:      allocated opinfo object on success, otherwise NULL
 */
static struct oplock_info *alloc_opinfo(struct ksmbd_work *work,
					u64 id, __u16 Tid)
{}

static void lease_add_list(struct oplock_info *opinfo)
{}

static void lease_del_list(struct oplock_info *opinfo)
{}

static void lb_add(struct lease_table *lb)
{}

static int alloc_lease(struct oplock_info *opinfo, struct lease_ctx_info *lctx)
{}

static void free_lease(struct oplock_info *opinfo)
{}

static void free_opinfo(struct oplock_info *opinfo)
{}

static inline void opinfo_free_rcu(struct rcu_head *rcu_head)
{}

struct oplock_info *opinfo_get(struct ksmbd_file *fp)
{}

static struct oplock_info *opinfo_get_list(struct ksmbd_inode *ci)
{}

static void opinfo_conn_put(struct oplock_info *opinfo)
{}

void opinfo_put(struct oplock_info *opinfo)
{}

static void opinfo_add(struct oplock_info *opinfo)
{}

static void opinfo_del(struct oplock_info *opinfo)
{}

static unsigned long opinfo_count(struct ksmbd_file *fp)
{}

static void opinfo_count_inc(struct ksmbd_file *fp)
{}

static void opinfo_count_dec(struct ksmbd_file *fp)
{}

/**
 * opinfo_write_to_read() - convert a write oplock to read oplock
 * @opinfo:		current oplock info
 *
 * Return:      0 on success, otherwise -EINVAL
 */
int opinfo_write_to_read(struct oplock_info *opinfo)
{}

/**
 * opinfo_read_handle_to_read() - convert a read/handle oplock to read oplock
 * @opinfo:		current oplock info
 *
 * Return:      0 on success, otherwise -EINVAL
 */
int opinfo_read_handle_to_read(struct oplock_info *opinfo)
{}

/**
 * opinfo_write_to_none() - convert a write oplock to none
 * @opinfo:	current oplock info
 *
 * Return:      0 on success, otherwise -EINVAL
 */
int opinfo_write_to_none(struct oplock_info *opinfo)
{}

/**
 * opinfo_read_to_none() - convert a write read to none
 * @opinfo:	current oplock info
 *
 * Return:      0 on success, otherwise -EINVAL
 */
int opinfo_read_to_none(struct oplock_info *opinfo)
{}

/**
 * lease_read_to_write() - upgrade lease state from read to write
 * @opinfo:	current lease info
 *
 * Return:      0 on success, otherwise -EINVAL
 */
int lease_read_to_write(struct oplock_info *opinfo)
{}

/**
 * lease_none_upgrade() - upgrade lease state from none
 * @opinfo:	current lease info
 * @new_state:	new lease state
 *
 * Return:	0 on success, otherwise -EINVAL
 */
static int lease_none_upgrade(struct oplock_info *opinfo, __le32 new_state)
{}

/**
 * close_id_del_oplock() - release oplock object at file close time
 * @fp:		ksmbd file pointer
 */
void close_id_del_oplock(struct ksmbd_file *fp)
{}

/**
 * grant_write_oplock() - grant exclusive/batch oplock or write lease
 * @opinfo_new:	new oplock info object
 * @req_oplock: request oplock
 * @lctx:	lease context information
 *
 * Return:      0
 */
static void grant_write_oplock(struct oplock_info *opinfo_new, int req_oplock,
			       struct lease_ctx_info *lctx)
{}

/**
 * grant_read_oplock() - grant level2 oplock or read lease
 * @opinfo_new:	new oplock info object
 * @lctx:	lease context information
 *
 * Return:      0
 */
static void grant_read_oplock(struct oplock_info *opinfo_new,
			      struct lease_ctx_info *lctx)
{}

/**
 * grant_none_oplock() - grant none oplock or none lease
 * @opinfo_new:	new oplock info object
 * @lctx:	lease context information
 *
 * Return:      0
 */
static void grant_none_oplock(struct oplock_info *opinfo_new,
			      struct lease_ctx_info *lctx)
{}

static inline int compare_guid_key(struct oplock_info *opinfo,
				   const char *guid1, const char *key1)
{}

/**
 * same_client_has_lease() - check whether current lease request is
 *		from lease owner of file
 * @ci:		master file pointer
 * @client_guid:	Client GUID
 * @lctx:		lease context information
 *
 * Return:      oplock(lease) object on success, otherwise NULL
 */
static struct oplock_info *same_client_has_lease(struct ksmbd_inode *ci,
						 char *client_guid,
						 struct lease_ctx_info *lctx)
{}

static void wait_for_break_ack(struct oplock_info *opinfo)
{}

static void wake_up_oplock_break(struct oplock_info *opinfo)
{}

static int oplock_break_pending(struct oplock_info *opinfo, int req_op_level)
{}

/**
 * __smb2_oplock_break_noti() - send smb2 oplock break cmd from conn
 * to client
 * @wk:     smb work object
 *
 * There are two ways this function can be called. 1- while file open we break
 * from exclusive/batch lock to levelII oplock and 2- while file write/truncate
 * we break from levelII oplock no oplock.
 * work->request_buf contains oplock_info.
 */
static void __smb2_oplock_break_noti(struct work_struct *wk)
{}

/**
 * smb2_oplock_break_noti() - send smb2 exclusive/batch to level2 oplock
 *		break command from server to client
 * @opinfo:		oplock info object
 *
 * Return:      0 on success, otherwise error
 */
static int smb2_oplock_break_noti(struct oplock_info *opinfo)
{}

/**
 * __smb2_lease_break_noti() - send lease break command from server
 * to client
 * @wk:     smb work object
 */
static void __smb2_lease_break_noti(struct work_struct *wk)
{}

/**
 * smb2_lease_break_noti() - break lease when a new client request
 *			write lease
 * @opinfo:		conains lease state information
 *
 * Return:	0 on success, otherwise error
 */
static int smb2_lease_break_noti(struct oplock_info *opinfo)
{}

static void wait_lease_breaking(struct oplock_info *opinfo)
{}

static int oplock_break(struct oplock_info *brk_opinfo, int req_op_level)
{}

void destroy_lease_table(struct ksmbd_conn *conn)
{}

int find_same_lease_key(struct ksmbd_session *sess, struct ksmbd_inode *ci,
			struct lease_ctx_info *lctx)
{}

static void copy_lease(struct oplock_info *op1, struct oplock_info *op2)
{}

static int add_lease_global_list(struct oplock_info *opinfo)
{}

static void set_oplock_level(struct oplock_info *opinfo, int level,
			     struct lease_ctx_info *lctx)
{}

void smb_send_parent_lease_break_noti(struct ksmbd_file *fp,
				      struct lease_ctx_info *lctx)
{}

void smb_lazy_parent_lease_break_close(struct ksmbd_file *fp)
{}

/**
 * smb_grant_oplock() - handle oplock/lease request on file open
 * @work:		smb work
 * @req_op_level:	oplock level
 * @pid:		id of open file
 * @fp:			ksmbd file pointer
 * @tid:		Tree id of connection
 * @lctx:		lease context information on file open
 * @share_ret:		share mode
 *
 * Return:      0 on success, otherwise error
 */
int smb_grant_oplock(struct ksmbd_work *work, int req_op_level, u64 pid,
		     struct ksmbd_file *fp, __u16 tid,
		     struct lease_ctx_info *lctx, int share_ret)
{}

/**
 * smb_break_all_write_oplock() - break batch/exclusive oplock to level2
 * @work:	smb work
 * @fp:		ksmbd file pointer
 * @is_trunc:	truncate on open
 */
static void smb_break_all_write_oplock(struct ksmbd_work *work,
				       struct ksmbd_file *fp, int is_trunc)
{}

/**
 * smb_break_all_levII_oplock() - send level2 oplock or read lease break command
 *	from server to client
 * @work:	smb work
 * @fp:		ksmbd file pointer
 * @is_trunc:	truncate on open
 */
void smb_break_all_levII_oplock(struct ksmbd_work *work, struct ksmbd_file *fp,
				int is_trunc)
{}

/**
 * smb_break_all_oplock() - break both batch/exclusive and level2 oplock
 * @work:	smb work
 * @fp:		ksmbd file pointer
 */
void smb_break_all_oplock(struct ksmbd_work *work, struct ksmbd_file *fp)
{}

/**
 * smb2_map_lease_to_oplock() - map lease state to corresponding oplock type
 * @lease_state:     lease type
 *
 * Return:      0 if no mapping, otherwise corresponding oplock type
 */
__u8 smb2_map_lease_to_oplock(__le32 lease_state)
{}

/**
 * create_lease_buf() - create lease context for open cmd response
 * @rbuf:	buffer to create lease context response
 * @lease:	buffer to stored parsed lease state information
 */
void create_lease_buf(u8 *rbuf, struct lease *lease)
{}

/**
 * parse_lease_state() - parse lease context containted in file open request
 * @open_req:	buffer containing smb2 file open(create) request
 *
 * Return:  oplock state, -ENOENT if create lease context not found
 */
struct lease_ctx_info *parse_lease_state(void *open_req)
{}

/**
 * smb2_find_context_vals() - find a particular context info in open request
 * @open_req:	buffer containing smb2 file open(create) request
 * @tag:	context name to search for
 * @tag_len:	the length of tag
 *
 * Return:	pointer to requested context, NULL if @str context not found
 *		or error pointer if name length is invalid.
 */
struct create_context *smb2_find_context_vals(void *open_req, const char *tag, int tag_len)
{}

/**
 * create_durable_rsp_buf() - create durable handle context
 * @cc:	buffer to create durable context response
 */
void create_durable_rsp_buf(char *cc)
{}

/**
 * create_durable_v2_rsp_buf() - create durable handle v2 context
 * @cc:	buffer to create durable context response
 * @fp: ksmbd file pointer
 */
void create_durable_v2_rsp_buf(char *cc, struct ksmbd_file *fp)
{}

/**
 * create_mxac_rsp_buf() - create query maximal access context
 * @cc:			buffer to create maximal access context response
 * @maximal_access:	maximal access
 */
void create_mxac_rsp_buf(char *cc, int maximal_access)
{}

void create_disk_id_rsp_buf(char *cc, __u64 file_id, __u64 vol_id)
{}

/**
 * create_posix_rsp_buf() - create posix extension context
 * @cc:	buffer to create posix on posix response
 * @fp: ksmbd file pointer
 */
void create_posix_rsp_buf(char *cc, struct ksmbd_file *fp)
{}

/*
 * Find lease object(opinfo) for given lease key/fid from lease
 * break/file close path.
 */
/**
 * lookup_lease_in_table() - find a matching lease info object
 * @conn:	connection instance
 * @lease_key:	lease key to be searched for
 *
 * Return:      opinfo if found matching opinfo, otherwise NULL
 */
struct oplock_info *lookup_lease_in_table(struct ksmbd_conn *conn,
					  char *lease_key)
{}

int smb2_check_durable_oplock(struct ksmbd_conn *conn,
			      struct ksmbd_share_config *share,
			      struct ksmbd_file *fp,
			      struct lease_ctx_info *lctx,
			      char *name)
{}