138c8a9a5SSteve French /* SPDX-License-Identifier: GPL-2.0-or-later */ 238c8a9a5SSteve French /* 338c8a9a5SSteve French * Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org> 438c8a9a5SSteve French * Copyright (C) 2018 Samsung Electronics Co., Ltd. 538c8a9a5SSteve French */ 638c8a9a5SSteve French 738c8a9a5SSteve French #ifndef __KSMBD_OPLOCK_H 838c8a9a5SSteve French #define __KSMBD_OPLOCK_H 938c8a9a5SSteve French 1038c8a9a5SSteve French #include "smb_common.h" 1138c8a9a5SSteve French 1238c8a9a5SSteve French #define OPLOCK_WAIT_TIME (35 * HZ) 1338c8a9a5SSteve French 1438c8a9a5SSteve French /* SMB2 Oplock levels */ 1538c8a9a5SSteve French #define SMB2_OPLOCK_LEVEL_NONE 0x00 1638c8a9a5SSteve French #define SMB2_OPLOCK_LEVEL_II 0x01 1738c8a9a5SSteve French #define SMB2_OPLOCK_LEVEL_EXCLUSIVE 0x08 1838c8a9a5SSteve French #define SMB2_OPLOCK_LEVEL_BATCH 0x09 1938c8a9a5SSteve French #define SMB2_OPLOCK_LEVEL_LEASE 0xFF 2038c8a9a5SSteve French 2138c8a9a5SSteve French /* Oplock states */ 2238c8a9a5SSteve French #define OPLOCK_STATE_NONE 0x00 2338c8a9a5SSteve French #define OPLOCK_ACK_WAIT 0x01 2438c8a9a5SSteve French #define OPLOCK_CLOSING 0x02 2538c8a9a5SSteve French 2638c8a9a5SSteve French #define OPLOCK_WRITE_TO_READ 0x01 2738c8a9a5SSteve French #define OPLOCK_READ_HANDLE_TO_READ 0x02 2838c8a9a5SSteve French #define OPLOCK_WRITE_TO_NONE 0x04 2938c8a9a5SSteve French #define OPLOCK_READ_TO_NONE 0x08 3038c8a9a5SSteve French 3138c8a9a5SSteve French struct lease_ctx_info { 3238c8a9a5SSteve French __u8 lease_key[SMB2_LEASE_KEY_SIZE]; 3338c8a9a5SSteve French __le32 req_state; 3438c8a9a5SSteve French __le32 flags; 3538c8a9a5SSteve French __le64 duration; 3638c8a9a5SSteve French __u8 parent_lease_key[SMB2_LEASE_KEY_SIZE]; 37bc025d49SNamjae Jeon __le16 epoch; 3838c8a9a5SSteve French int version; 393c1e602aSNamjae Jeon bool is_dir; 4038c8a9a5SSteve French }; 4138c8a9a5SSteve French 4238c8a9a5SSteve French struct lease_table { 4338c8a9a5SSteve French char client_guid[SMB2_CLIENT_GUID_SIZE]; 4438c8a9a5SSteve French struct list_head lease_list; 4538c8a9a5SSteve French struct list_head l_entry; 4638c8a9a5SSteve French spinlock_t lb_lock; 4738c8a9a5SSteve French }; 4838c8a9a5SSteve French 4938c8a9a5SSteve French struct lease { 5038c8a9a5SSteve French __u8 lease_key[SMB2_LEASE_KEY_SIZE]; 5138c8a9a5SSteve French __le32 state; 5238c8a9a5SSteve French __le32 new_state; 5338c8a9a5SSteve French __le32 flags; 5438c8a9a5SSteve French __le64 duration; 5538c8a9a5SSteve French __u8 parent_lease_key[SMB2_LEASE_KEY_SIZE]; 5638c8a9a5SSteve French int version; 5738c8a9a5SSteve French unsigned short epoch; 583c1e602aSNamjae Jeon bool is_dir; 5938c8a9a5SSteve French struct lease_table *l_lb; 6038c8a9a5SSteve French }; 6138c8a9a5SSteve French 6238c8a9a5SSteve French struct oplock_info { 6338c8a9a5SSteve French struct ksmbd_conn *conn; 6438c8a9a5SSteve French struct ksmbd_session *sess; 6538c8a9a5SSteve French struct ksmbd_work *work; 6638c8a9a5SSteve French struct ksmbd_file *o_fp; 6738c8a9a5SSteve French int level; 6838c8a9a5SSteve French int op_state; 6938c8a9a5SSteve French unsigned long pending_break; 7038c8a9a5SSteve French u64 fid; 7138c8a9a5SSteve French atomic_t breaking_cnt; 7238c8a9a5SSteve French atomic_t refcount; 7338c8a9a5SSteve French __u16 Tid; 7438c8a9a5SSteve French bool is_lease; 7538c8a9a5SSteve French bool open_trunc; /* truncate on open */ 7638c8a9a5SSteve French struct lease *o_lease; 7738c8a9a5SSteve French struct list_head op_entry; 7838c8a9a5SSteve French struct list_head lease_entry; 7938c8a9a5SSteve French wait_queue_head_t oplock_q; /* Other server threads */ 8038c8a9a5SSteve French wait_queue_head_t oplock_brk; /* oplock breaking wait */ 8138c8a9a5SSteve French struct rcu_head rcu_head; 8238c8a9a5SSteve French }; 8338c8a9a5SSteve French 8438c8a9a5SSteve French struct lease_break_info { 8538c8a9a5SSteve French __le32 curr_state; 8638c8a9a5SSteve French __le32 new_state; 8738c8a9a5SSteve French __le16 epoch; 8838c8a9a5SSteve French char lease_key[SMB2_LEASE_KEY_SIZE]; 8938c8a9a5SSteve French }; 9038c8a9a5SSteve French 9138c8a9a5SSteve French struct oplock_break_info { 9238c8a9a5SSteve French int level; 9338c8a9a5SSteve French int open_trunc; 9438c8a9a5SSteve French int fid; 9538c8a9a5SSteve French }; 9638c8a9a5SSteve French 9738c8a9a5SSteve French int smb_grant_oplock(struct ksmbd_work *work, int req_op_level, 9838c8a9a5SSteve French u64 pid, struct ksmbd_file *fp, __u16 tid, 9938c8a9a5SSteve French struct lease_ctx_info *lctx, int share_ret); 10038c8a9a5SSteve French void smb_break_all_levII_oplock(struct ksmbd_work *work, 10138c8a9a5SSteve French struct ksmbd_file *fp, int is_trunc); 10238c8a9a5SSteve French int opinfo_write_to_read(struct oplock_info *opinfo); 10338c8a9a5SSteve French int opinfo_read_handle_to_read(struct oplock_info *opinfo); 10438c8a9a5SSteve French int opinfo_write_to_none(struct oplock_info *opinfo); 10538c8a9a5SSteve French int opinfo_read_to_none(struct oplock_info *opinfo); 10638c8a9a5SSteve French void close_id_del_oplock(struct ksmbd_file *fp); 10738c8a9a5SSteve French void smb_break_all_oplock(struct ksmbd_work *work, struct ksmbd_file *fp); 10838c8a9a5SSteve French struct oplock_info *opinfo_get(struct ksmbd_file *fp); 10938c8a9a5SSteve French void opinfo_put(struct oplock_info *opinfo); 11038c8a9a5SSteve French 11138c8a9a5SSteve French /* Lease related functions */ 11238c8a9a5SSteve French void create_lease_buf(u8 *rbuf, struct lease *lease); 113*8df4bcdbSNamjae Jeon struct lease_ctx_info *parse_lease_state(void *open_req); 11438c8a9a5SSteve French __u8 smb2_map_lease_to_oplock(__le32 lease_state); 11538c8a9a5SSteve French int lease_read_to_write(struct oplock_info *opinfo); 11638c8a9a5SSteve French 11738c8a9a5SSteve French /* Durable related functions */ 11838c8a9a5SSteve French void create_durable_rsp_buf(char *cc); 11938c8a9a5SSteve French void create_durable_v2_rsp_buf(char *cc, struct ksmbd_file *fp); 12038c8a9a5SSteve French void create_mxac_rsp_buf(char *cc, int maximal_access); 12138c8a9a5SSteve French void create_disk_id_rsp_buf(char *cc, __u64 file_id, __u64 vol_id); 12238c8a9a5SSteve French void create_posix_rsp_buf(char *cc, struct ksmbd_file *fp); 12338c8a9a5SSteve French struct create_context *smb2_find_context_vals(void *open_req, const char *tag, int tag_len); 12438c8a9a5SSteve French struct oplock_info *lookup_lease_in_table(struct ksmbd_conn *conn, 12538c8a9a5SSteve French char *lease_key); 12638c8a9a5SSteve French int find_same_lease_key(struct ksmbd_session *sess, struct ksmbd_inode *ci, 12738c8a9a5SSteve French struct lease_ctx_info *lctx); 12838c8a9a5SSteve French void destroy_lease_table(struct ksmbd_conn *conn); 1293c1e602aSNamjae Jeon void smb_send_parent_lease_break_noti(struct ksmbd_file *fp, 1303c1e602aSNamjae Jeon struct lease_ctx_info *lctx); 131ab5a0a1cSNamjae Jeon void smb_lazy_parent_lease_break_close(struct ksmbd_file *fp); 132*8df4bcdbSNamjae Jeon int smb2_check_durable_oplock(struct ksmbd_conn *conn, 133*8df4bcdbSNamjae Jeon struct ksmbd_share_config *share, 134*8df4bcdbSNamjae Jeon struct ksmbd_file *fp, 135*8df4bcdbSNamjae Jeon struct lease_ctx_info *lctx, 136*8df4bcdbSNamjae Jeon char *name); 13738c8a9a5SSteve French #endif /* __KSMBD_OPLOCK_H */ 138